http://vasilisc.com/hcl/detect.php
Сделал первую версию статистики, в дальнейшем исправим, подрихтуем, приукрасим.
http://vasilisc.com/hcl/stats.php
Многие видели сайты, посвящённые оборудованию в Linux. Сама мысль, что информация собрана в ручную или скриптами, но так или иначе людьми, которые не поленились и отправили отчёт о своём оборудовании с указанием "работает/не работает" - всё это наводило на меня уныние.
Ведь если вдуматься, то работающее оборудование в Linux обслуживает или само ядро или модуль ядра. А мы люди опять описываем на многочисленных сайтах, то что определил наш релиз Linux, точнее его новое ядро и окружение. То есть у ядра есть своя "база данных устройств", а мы её через наш человеческий фактор выносим на сайты.
Начал интересоваться как именно Linux обслуживает мои железяки и загружает тот или иной модуль для обслуживания конкретного устройства. Здесь и далее мы будем обсуждать только "PCI устройства", иными словами "всё что расположено на материнке".
В Линуксе есть команда lspci, которая выводит информацию об вашем оборудовании и какой "модуль" обслуживает конкретный компонент.
Типа так,
03:00.0 Ethernet controller [0200]: Realtek Semiconductor Co., Ltd. RTL8101E/RTL8102E PCI Express Fast Ethernet controller [10ec:8136] (rev 01) Kernel driver in use: r8169 Kernel modules: r8169 04:01.0 Ethernet controller [0200]: VIA Technologies, Inc. VT6105/VT6106S [Rhine-III] [1106:3106] (rev 86) Kernel driver in use: via-rhine Kernel modules: via-rhine
И меня терзала мысль, а как именно Линукс определяет, кто будет обслуживать устройство. В выше указанном примере сетевую карту "RTL8101E/RTL8102E PCI Express Fast Ethernet controller" будет обслуживать модуль r8169, а другую сетевую карту "VT6105/VT6106S [Rhine-III]" - модуль via-rhine.
Но они обе сетевые карты, хоть и разного производителя!
И как Linux их различает?
И как "знает" что для одной сетевой карты нужен один модуль, а для другой карты - другой модуль?
До этого момента я знал об идентификаторах оборудования, но не был силён в этой теме. Прочитав литературу, выяснилось что есть некие числа, которые определяют во-первых, класс устройства (далее Class Code - CC). То есть видеокарта это одно, а сетевая карта это другое и у них разные "числа класса устройств".
Самое главное, что есть база описывающая, какой Class Code что значит, но об этом чуть позже.
Во-вторых, есть число, которое однозначно определяет производителя железяки и называется Vendor ID. У каждого производителя своё уникальное число.
В-третьих, есть число, которое однозначно определяет саму железяку и называется Device ID. У каждой железяки своё уникальное число, НО в пределах производителя!
Есть еще числа, но мы на этом остановимся, кому интересно, то подробности в википедии в статье PCI configuration space.
И так есть 3 числа, но пока не понятно как эти числа связаны с модулями, то есть какой модуль кого будет обслуживать. Сначала я выяснил, что большинство утилит, типа lspci, пользуется базой, в которой числа расшифровываются в понятные человеку описания.
База расположена в Ubuntu Linux по адресу /usr/share/misc/pci.ids и обновляется командой update-pciids. Благодаря этой базе, можно узнать что значат те или иные числа.
Следующая моя мысль была "покопаться в исходниках lspci", ведь как-то утилита выводит обслуживающий железяку модуль! Ковыряя исходники lspci выяснилось, что lspci использует виртуальную файловую систему sysfs в Linux. Изменив чуток исходники lspci и заставив выводить путь, откуда lspci берёт имя обслуживающего модуля, я увидел картину
03:00.0 0200: 10ec:8136 (rev 01) Subsystem: 1462:529c Path to : /sys/bus/pci/devices/0000:03:00.0/driver Kernel driver in use: r8169 04:01.0 0200: 1106:3106 (rev 86) Subsystem: 1186:1403 Path to : /sys/bus/pci/devices/0000:04:01.0/driver Kernel driver in use: via-rhine
То есть lspci банально читает псевдофайл driver из сконструированного пути в /sys/bus/pci/ и всё!
Линукс грузится, происходит инициализация устройств, sysfs заполняется псевдофайлами, которые описывают конкретный компьютер, а утилита lspci просто читает эти файлы ... мдаааа.
Тут я понял, что тупик! От чего ушёл, к тому и пришёл. Время потрачено зря и толку ноль.
Но где-то всё таки есть "база", какой модуль и какие "числа" обслуживает. И я нашёл её - это файл modules.pcimap.
Файл имеет следующую структуру и наполнен данными:
# pci module vendor device subvendor subdevice class class_mask driver_data nvidiafb 0x000010de 0xffffffff 0xffffffff 0xffffffff 0x00030000 0x00ff0000 0x0 shpchp 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0x00060400 0xffffffff 0x0 via-rhine 0x00001106 0x00003106 0xffffffff 0xffffffff 0x00000000 0x00000000 0x0 r8169 0x000010ec 0x00008136 0xffffffff 0xffffffff 0x00000000 0x00000000 0x0 ........
Из файла modules.pcimap многое стало ясно! Определённый "класс устройства Class Code" + "производитель Vendor" + "устройство Device" определённо указывают на модуль, который будет обслуживать.
Решено было воплотить идею на сайте в виде скрипта, которому скармливают файл отчёт об оборудовании, а он выдаёт какое устройство, каким модулем будет обслуживаться. И тут меня посетила с дружественным визитом гениальная идея - файл-отчёт нужно создавать в MS Windows!
Если человек так или иначе загрузил Linux, то он сам увидит как его оборудование поддерживается. Нужно заманивать windows пользователей! Увидев, что его оборудование отлично поддерживается в Linux, многие задумаются - "а не попробовать ли мне установить Linux?"
Вся идея, вроде, была неплоха: "делаем в винде отчёт, а получаем какой результат будет в линуксе". В MS Windows есть утилита devcon.exe, которая поможет создать нужный файл-отчёт.
Но накидав черновик на сайте, "был опечален". Все было не так радужно, как представлялось вначале. На одних и тех же компьютерах были сделаны отчёты в MS Windows с помощью devcon.exe и в Ubuntu Linux с помощью lspci. На этих отчётах сразу "нарисовалась" проблема, что не все устройства "определялись" в макете сайта, который использовал первую версию базы данных, основанной на modules.pcimap. Сейчас кажется смешным, но я не сразу понял, что есть модули, которые занимаются группой устройств и охватывают, естественно, множество VendorID и DeviceID.
Взгляните:
# pci module vendor device subvendor subdevice class class_mask driver_data nvidiafb 0x000010de 0xffffffff 0xffffffff 0xffffffff 0x00030000 0x00ff0000 0x0 shpchp 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0x00060400 0xffffffff 0x0
Модуль nvidiafb занимается только видеокартами, так как класс устройства 0x00030000 - это видеокарты. Но производитель должен быть nVidia, так как 0x000010de зарезервирован за этой фирмой. А вот 0xffffffff в поле device и говорит, что устройство-видеокарта может быть любой!
Модуль shpchp (Standard Hot Plug PCI Controller Driver) занимается всеми "PCI bridge" (0x00060400). Производитель и само устройство может быть любым, так как выставлено 0xffffffff.
Улучшив скрипт, улучшилось распознавание и настроение! Зелёным цветом выводились устройства, для которых найден обслуживающий их linux модуль. Красным цветом окрашивалось не найденое и было огромное желание сделать так, чтобы красного было как можно меньше.
Многое, но не всё, находится в файле modules.pcimap, который хранит связи между устройствами и модулями. У меня мелькнула ободряющая мысль - "а в исходниках ядра linux есть то, чего нет в modules.pcimap?". Оказалось есть!
Нужно разыскивать конструкции вида
PCI_DEVICE(0x8086,0x25F0) PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8185)в файлах исходниках ядра линукс. Если в каком-то файле в дереве исходниках линукса встречается конструкция PCI_DEVICE(), значит программный код этого исходника будет обслуживать данное устройство.
Очень лениво было писать программу, которая бы обходила дерево файлов и читая, разыскивала конструкции вида PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8185). Так же находила чему равно значение переменных, если вместо шестнадцатеричных чисел указана переменная, и заменяла имя переменной на её значение. Дал себе слово, что напишу позже такую программу на Питоне, а пока сваял баш-скриптик, который с помощью grep/sed и "такой-то матери" составил мне базу вида
/путь/к/файлу/модуля vendorid deviceid
И так у нас теперь "две базы". Ищем в базе "modules.pcimap", если не найден, то ищем в базе "исходники ядра линукс". К этому моменту хорошо улучшилось определение устройств.
Стало понятно, что нужно больше файлов-отчётов devcon и я решил обратиться к единомышленникам с forum.ubuntu.ru, которые очень сильно помогли, отправив мне множество различных отчётов. Какой-то период времени заняло тестирование, так как присланные отчёты показали множество моментов, которые я пропустил своими личными отчётами.
К этому времени нужно было решить что делать с устройствами к которым не нужны драйвера в полном смысле этого слова. Вывод lspci у таких устройств не показывал наличие задействованных модулей, но lspci легче! Lspci, редиска, просто читает псевдофайлы, а моему скрипту на сайте нужно что-то решить, когда в процессе разбора файла от devcon он найдёт упоминание об устройстве. Я решил добавить код, который отрабатывает когда поиск по двум базам заканчивается неудачно. Код простой, анализируется класс устройства и для таких устройств как память (0500), флеш-память (0501), контроллер памяти (0580), ISA которая теперь часть LPC Bus (0601) выводится информация, что "драйвер" не нужен.
К этому времени всё работало более-менее хорошо, нужно было делать красивую одёжку для скрипта php, так как чёрные буквы на белом фоне в 21 веке - не камильфо. Так как вебмастер из меня никакой, решил обратиться к другу, который в этом деле профи. Евгений Пашков потратил своё время и силы и создал интерфейс, который имитирует внешний вид Ubuntu, так как сайт по мимо основной задачи выполняет функцию "пропаганды дистрибутива Ubuntu среди пользователей MS Windows".
Пока Евгений ваял интерфейс, я озадачился безопасностью. Прочёл статьи о безопасном программировании в PHP и применил их на практике, всё таки есть процедура закачки файл-отчёта на сайт. Хакеры не дремлют и это нужно помнить.
Вот в принципе и всё.
В планах:
1) избавится от багов, которые вылезут при активном использовании сайта
2) написать всё таки программу для разбора исходников ядра линукс и пополнении базы
3) попробовать замахнутся на разбор и определение внешних устройств, таких как принтеры, сканеры и т.д и т.п.
АААА вот собственно и скрипт http://vasilisc.com/hcl/detect.php
Продолжение Сказка про USB устройства
Немає коментарів:
Дописати коментар