Глава 9 Обращение к BIOS из операционной системы Введение В данной главе мы рассмотрим, как получить доступ к содержимому чипа BIOS, включая содержимое чипов ROM BIOS расширения, непосредственно из операционной системы. В первом разделе излагаются основные принципы, а далее рассматриваются конкретные вопросы, связанные с операционной системой, и соответствующие интерфейсы. Наконец, демонстрируется принципиальная возможность воплощения этой идеи для Linux{ XE "Linux" } и Windows{ XE "Windows" }. 9.1. Общий способ доступа Реализация прямого доступа к содержимому чипа BIOS из операционной системы может показаться задачей не из легких, но в действительности это проще, чем кажется на первый взгляд. Прямой доступ к содержимому чипа BIOS и манипулирование этим содержимым из операционной системы можно реализовать только в случае с чипами типа EEPROM{ XE "EEPROM" } (electrically erasable programmable ROM{ XE "electrically erasable programmable ROM" } — электрически стираемое программируемое ПЗУ) или флэш-ROM{ XE "флэш-ROM" }. К счастью, начиная с конца 1990-х, во всех материнских платах применяются именно эти виды чипов ROM BIOS. В разных операционных системах имеются разные уровни программного обеспечения. Однако, благодаря единой модели программирования для архитектуры х86, логические действия для доступа к содержимому BIOS с любого уровня почти одинаковы. В большинстве операционных систем архитектуры х86 аппаратными средствами реализуется два уровня привилегий для предоставления прикладным программам прямого доступа к системным ресурсам. Эти уровни привилегий известны как кольцо 0{ XE "кольцо 0" } (ring 0{ XE 360 Часть IV. Внесение изменений в код BIOS "ring 0" }), или режим ядра{ XE "режим ядра" } (kernel mode{ XE "kernel mode" }) и кольцо 3{ XE "кольцо 3" } (ring 3{ XE "ring 3" }), или пользовательский режим{ XE "пользовательский режим" } (user mode{ XE "user mode" }). Любое программное обеспечение, исполняющееся в режиме ядра, может обращаться напрямую к аппаратным средствам, включая чип ROM BIOS, и манипулировать ими. Таким образом, общая процедура для получения доступа к чипу ROM BIOS материнской платы из операционной системы состоит из следующих шагов: 1. В операционной системе входим в режим ядра. В большинстве случаев, чтобы выполнить этот шаг, необходимо разработать драйвер устройства для конкретной операционной системы. Специальный драйвер необходим по следующим двум причинам. Во-первых, операционная система предоставляет доступ к режиму ядра только драйверам устройств. Во-вторых, в большинстве случаев, операционные системы не предоставляют четко определенного интерфейса для манипуляции чипом BIOS (если такой интерфейс предоставляется вообще). С первого взгляда, может показаться, что для предоставления пользовательскому приложению доступа к чипу ROM BIOS посредством драйвера устройства для Linux и Windows необходимо применять разные подходы. Но это совсем не так, по причине уже упомянутой единой системной архитектуры программного обеспечения. Основным назначением драйвера устройства является предоставление приложениям пользовательского режима прямого доступа к адресному пространству чипа ROM BIOS. Как показано в разд. 9.2, для Linux нет даже необходимости создавать драйвер устройства для реализации этой идеи, так как ядро этой операционной системы предоставляет доступ к адресному пространству чипа ROM BIOS посредством виртуального файла в каталоге /dev/mem. Общий способ для "экспортирования" адресного пространства чипа ROM BIOS в пользовательское приложение заключается в следующем: • Отображаем физический диапазон адресов чипа ROM BIOS (т. е. ад- ресное пространство, примыкающее к пределу памяти в 4 Гбайт) на виртуальное адресное пространство процесса 1, которому нужно предоставить доступ к содержимому чипа ROM BIOS. • Создаем указатель на начало отображенного содержимого чипа ROM BIOS в виртуальном адресном пространстве процесса. • С помощью указателя, созданного на предыдущем шаге, манипулируем содержимым чипа ROM BIOS непосредственно из пользовательского приложения. Это означает, что содержимое чипа можно считывать при 1 В данном контексте процесс — это один из экземпляров приложения пользовательского режима, исполняющихся в настоящее время. Глава 9. Обращение к BIOS из операционной системы 361 помощи оператора разыменования 2. Однако, так как чип BIOS является памятью ROM, для выполнения операций записи, как и для стирания чипа, необходимо выполнить определенные подготовительные действия. 2. Осуществляется аппаратно-зависимая часть операций, необходимых для получения доступа к содержимому чипа ROM BIOS и манипулирования этим содержимым. Для выполнения этого шага необходимо точно знать, каким способом производится доступ к чипу BIOS на уровне аппаратных средств. Эту информацию можно найти в технической документации на чипсет и на чип ROM BIOS. Как правило, чтобы получить аппаратный доступ к чипу BIOS, необходимо выполнить следующие действия: • Регистры чипсета конфигурируются таким образом, чтобы разрешить доступ к адресному пространству чипа ROM BIOS с правом чтения и записи. В архитектуре х86 адресное пространство чипа ROM BIOS отображается в область общесистемного адресного пространства, примыкающую к верхней границе первых 4 Гбайт. Регистры чипсета, управляющие доступом к чипу ROM BIOS, обычно находятся в южном мосте. • Далее необходимо прочитать байты идентификаторов производителя и чипа, расположенные по стандартным адресам. Эта информация необходима, чтобы решить, каким методом пользоваться для обращения к содержимому чипа ROM BIOS. Обратите внимание, что чипы ROM BIOS разных производителей имеют индивидуальные наборы команд для доступа к их содержимому. Некоторые команды приведены к общему стандарту ассоциацией JEDEC 3 (http://jedec.org/). • Двоичный код записывается в чип и считывается из него согласно спецификации производителя чипа. Только что описанный способ представляет технику доступа к содержимому чипа ROM BIOS и манипулирования этим содержимым из операционной системы. В последующих разделах рассматривается практическая реализация принципов доступа к чипу BIOS из конкретных операционных систем. 2 Операция разыменования (indirection operator) — унарная операция, операндом которой является указатель, а значением — указываемый объект. 3 Joint Electronic Device Engineering Council — Объединенный инженерный совет по электронным устройствам. 362 Часть IV. Внесение изменений в код BIOS 9.2. Доступ к содержимому BIOS материнской платы из Linux В разд. 9.1 мы ознакомились с общими принципами получения прямого доступа к чипу ROM BIOS из операционной системы. Для подтверждения этой концепции рассмотрим, как выполнить поставленную задачу в Linux{ XE "Linux" }. Эксперимент я проводил на устаревшей материнской плате Iwill VD133{ XE "Iwill VD133" }, выпущенной в 2000 году. Я выбрал данную плату по двум причинам. Во-первых, я хотел показать, что поставленная задача осуществима даже с устаревшими материнскими платами. Во-вторых, так как эта материнская плата морально устарела, бесплатную документацию 4 на ее чипсет можно без труда найти в Интернете. Техническая документация на чипсет, а также на соответствующий чип ROM BIOS необходима для реализации доступа к содержимому BIOS и манипулирования им. Технические характеристики системы, на которой я проводил эксперимент, следующие: Материнская плата Iwill VD133 с северным мостом VIA 693A и южным мостом VIA 596B. Первоначальная BIOS датируется 28 июля 2000 года. Чип BIOS — флэш-ROM Winbond{ XE "Winbond" } W49F002U. Операционная система — Linux Slackware 9.1{ XE "Linux Slackware 9.1" }, версия ядра 2.4.24. Обратите внимание, что при инсталляции необходимо установить и исходный код ядра. Исходный код требуется для перекомпиляции программного обеспечения, предназначенного для прямого доступа к содержимому чипа ROM BIOS. В дальнейшем я буду называть эту систему целевой. Чтобы выполнить нашу задачу, нам также потребуется следующая документация: Техническая документация на чипсет, в особенности — на его южный мост. В материнских платах архитектуры х86 южный мост управляет доступом к чипу BIOS. В данном случае, нам нужна техническая документация на южный мост VIA 596B. Ее можно скачать бесплатно по адресу http://www.megaupload.com/?d=FF297JQD. Так как каждый чип ROM BIOS имеет свой собственный набор команд (см. разд. 9.1), нам будет необходима техническая документация на наш чип ROM BIOS. В данном случае, это техническая документация 4 Компании Intel и AMD обычно предоставляют спецификации технических характеристик для скачивания сразу же после выпуска чипсета на рынок. Компании VIA, Nvidia, SiS и многие другие производители чипсетов этого не делают. Глава 9. Обращение к BIOS из операционной системы 363 на чип ROM Winbond W49F002U. Ее можно скачать по адресу http://www.winbond.com/e-winbondhtm/partner/_Memory_F_PF.htm. Кроме того, потребуется и утилита, с помощью которой можно будет осуществлять прямой доступ к чипу ROM BIOS. Я предпочитаю создавать такие утилиты сам, так как это позволяет мне реализовать все возможности управления системой, требующиеся для решения конкретной задачи, не дожидаясь, пока кто-то создаст необходимый мне инструмент. К счастью, для решения рассматриваемой задачи уже имеется готовая утилита для прошивки 5 BIOS из Linux от разработчиков проекта Freebios (http://sourceforge.net/ cvs/?group_id=3206). Называется она flash_n_burn{ XE "flash_n_burn:для Linux" }. Исходный код утилиты можно скачать по адресу http://freebios.cvs.sourceforge.net/freebios/freebios/ util/flash_and_burn/. Плохо то, что эта утилита не является стандартным компонентом дистрибутива Freebios{ XE "Freebios" }. С помощью этого инструмента можно сделать дамп двоичного файла BIOS из чипа ROM BIOS и прошить его обратно в чип из Linux. Я рекомендую вам добавить эту утилиту, которую можно приспособить для выполнения ваших конкретных задач, в ваш набор инструментов. 9.2.1. Знакомство с утилитой flash_n_burn Начнем наше знакомство с утилитой flash_n_burn{ XE "утилита с рассмотрения процедур компиляции ее исходного кода. Скопируйте исходный код в каталог ~/Project/freebios_flash_n_burn. Компиляция производится с помощью утилиты make, результаты работы которой показаны в листинге 9.1. Вывод информации о результатах процесса компиляции можно подавить, запустив компиляцию с помощью команды make clean вместо просто make из каталога, в котором находится исходный код. flash_n_burn" } Листинг 9.1. Компилирование утилиты flash_n_burn pinczakko@opunaga:~/Project/freebios_flash_n_burn> make gcc -O2 -g -Wall -Werror -c -o flash_rom.o flash_rom.c gcc -O2 -g -Wall -Werror -c -o jedec.o jedec.c 5 Под "прошивкой" BIOS имеется в виду запись содержимого двоичного файла в чип ROM BIOS. Английский глагол для этой операции будет "flash", сама операция называется "flashing", а утилита для прошики — "flasher". Для более ранних чипов ROM (не флэш) применялось слово "burn" и его производные "bruning" и "burner". Термин "burn" и его производные также применяются в отношении чипов флэш-ROM. 364 Часть IV. Внесение изменений в код BIOS gcc -O2 -g -Wall -Werror -c -o sst28sf040.o sst28sf040.c gcc -O2 -g -Wall -Werror -c -o am29f040b.o am29f040b.c gcc -O2 -g -Wall -Werror -c -o sst39sf020.o sst39sf020.c gcc -O2 -g -Wall -Werror -c -o m29f400bt.o m29f400bt.c gcc -O2 -g -Wall -Werror -c -o w49f002u.o w49f002u.c gcc -O2 -g -Wall -Werror -c -o 82802ab.o 82802ab.c gcc -O2 -g -Wall -Werror -c -o msys_doc.o msys_doc.c gcc -O2 -g -Wall -Werror -o flash_rom flash_rom.c jedec.o sst28sf040.o am29f040b.o mx29f002.c sst39sf020.o m29f400bt.o w49f002u.o 82802ab.o msys_doc.o -lpci gcc -O2 -g -Wall -Werror -o flash_on flash_on.c pinczakko@opunaga:~/Project/freebios_flash_n_burn> Результатом работы команды make будут два исполняемых файла — flash_on и flash_rom (листинг 9.2). Для ясности, я оставил только эти два файла в листинге содержимого каталога (листинг 9.2). Листинг 9.2. Исполняемые файлы утилиты flash_n_burn pinczakko@opunaga:~/Project/freebios_flash_n_burn> ls -l ... -rwxr-xr-x 1 pinczakko users 25041 Aug 5 11:49 flash_on* -rwxr-xr-x 1 pinczakko users 133028 Aug 5 11:49 flash_rom* ... Вообще говоря, в файле flash_on нет необходимости, так как его функциональность включена в файл flash_rom. Назначение файла flash_on — активировать доступ к чипу ROM BIOS через южный мост чипсета SiS. Эта функциональность была впоследствии интегрирована в файл flash_rom, и, таким образом, файл flash_on стал ненужным. Поэтому я рассматриваю только применение утилиты flash_rom. Утилита запускается на исполнение обычным способом — для этого достаточно ввести в терминале ее название и указать необходимые параметры, как показано в листинге 9.3. Если введены неправильные параметры, утилита flash_rom сообщает об этом и предоставляет информацию по ее использованию, включая правильное указание необходимых параметров (см. листинг 9.3). Листинг 9.3. Использование утилиты flash_rom pinczakko@opunaga:~/Project/A-List_Publishing/freebios_flash_n_burn> ./flash_rom --help Глава 9. Обращение к BIOS из операционной системы 365 ./flash_rom: invalid option -- ; ./flash_rom: invalid option -- - Недействительная опция usage: ./flash_rom [-rwv] [-c chipname][file] ; использование: ./flash_rom [-rwv] [-c имя_чипа][файл] -r: read flash and save into file ; -r: считать содержимое чипа флэш и сохранить в файл -w: write file into flash (default when file is specified) ; -w: записать файл в чип флэш (по умолчанию, когда указан файл) -v: verify flash against file ; -v: сверить содержимое чипа флэш с содержимым файла -c: probe only for specified flash chip ; -c: исследовать только указанный чип флэш If no file is specified, then all that happens is that flash info is dumped ; Если не указано файла, тогда выводится ; только информация о чипе флэш Чтобы воспользоваться возможностями flash_rom в полном объеме, утилиту следует запускать, зарегистрировавшись от имени пользователя root, так как в противном случае, вы даже не сможете прочитать содержимое чипа ROM BIOS. Причина этого состоит в том, что для запуска этой программы необходим определенный уровень привилегий ввода-вывода. Снимем дамп двоичного файла BIOS целевой системы. Не забудьте, что для успешного выполнения этой операции необходимо войти в систему под учетной записью администратора (root). Результаты процесса снятия дампа показаны в листинге 9.4. Обратите внимание, что для краткости в листинге 9.4 показана урезанная часть дампа, содержащая только информацию, необходимую для понимания происходящего. Листинг 9.4. Считывание двоичного файла BIOS из чипа ROM BIOS в файл в Linux root@opunaga:/home/pinczakko/Project/freebios_flash_n_burn# ./flash_rom -r dump.bin Calibrating timer since microsleep sucks ... takes a second // Калибрируем таймер, так как функция microsleep никуда не годится. // Это займет всего лишь секунду. Setting up microsecond timing loop // Устанавливаем цикл замера микросекунды. 128M loops per second // 128 миллионов циклов в секунду. 366 Часть IV. Внесение изменений в код BIOS OK, calibrated, now do the deed // Таймер откалиброван. Выполняем задание. Enabling flash write on VT82C596B ... OK // Разрешаем запись в VT82C596B. Разрешение успешно. Trying Am29F040B, 512 KB // Пробуем чип Am29F040B, 512 Кбайт probe_29f040b: id1 0x25, id2 0xf2 Trying At29C040A, 512 KB // Пробуем чип Am29F040C, 512 Кбайт probe_jedec: id1 0xda, id2 0xb Trying Mx29f002, 256 KB // Пробуем чип Mx29f002, 256 Кбайт probe_29f002: id1 218, id2 11 ... Trying W49F002U, 256 KB // Пробуем чип W49F002U, 256 Кбайт probe_49f002: id1 0xda, id2 0xb flash chip manufacturer id = 0xda // Идентификатор производителя чипа = 0xda W49F002U found at physical address: 0xfffc0000 // Нашли чип W49F002U по физическому адресу - 0xfffc0000 Part is W49F002U // Номер детали - W49F002U Reading flash ... Done // Считывание чипа флэш-ROM завершено В первую очередь необходимо разобраться, что именно происходит во время считывания содержимого чипа ROM BIOS в файл. Процесс начинается с конфигурирования регистров южного моста VIA 956B таким образом, чтобы разрешить доступ к чипу ROM BIOS. Затем утилита выполняет проверку на наличие чипа ROM BIOS из числа поддерживаемых ею. В данном случае, обнаружен чип Winbond{ XE "Winbond" } W49F002U, и его содержимое считано и сохранено в файл dump.bin. Инструкции для выполнения именно этих действий были указаны параметром — r при запуске утилиты flash_rom (см. листинг 9.3). Файл, считанный из чипа ROM BIOS, сохраняется в двоичном формате, и для его просмотра нужна специальная утилита Linux, называющаяся hexdump. Эта утилита, соответствующая стандарту POSIX{ XE "POSIX" } (Portable Operating System Interface — интерфейс переносимых операционных систем), включена в боль-шинство дистрибутивов Linux. Формат команды для просмотра содержимого двоичного файла BIOS с помощью этой утилиты в тер- Глава 9. Обращение к BIOS из операционной системы минале в листинге 9.5. 367 Linux показан Листинг 9.5. Просмотр сохраненного двоичного файла BIOS в Linux root@opunaga:/home/pinczakko/Project/ freebios_flash_n_burn# hexdump -f fmt dump.bin | less Вывод команды hexdump форматируется при помощи специального файла форматирования, fmt, который указывается как опция при вызове команды. Это — обычный текстовый файл, содержимое которого показано в листинге 9.6. Листинг 9.6. Содержимое файла форматирования fmt "%06.6_ax " " 12/1 "%02X " " "%_p " "\n" Если у вас возникают затруднения с пониманием листинга 9.6, обратитесь к объяснению листинга 7.11 в разд. 7.3.4. Содержимое обоих файлов одинаково. Результат выполнения команды hexdump, заданной в листинге 9.5, показан в листинге 9.7. Листинг 9.7. Содержимое файла dump.bin Адрес Шестнадцатеричные значения Значения ASCII 000000 25 F2 2D 6C 68 35 2D 85 3A 00 00 C0 % . - l h 5 - . : . . . 00000c 57 00 00 00 00 00 41 20 01 0C 61 77 W . . . . . A 000018 61 72 64 65 78 74 2E 72 6F 6D DB 74 a r d e x t . r o m . t 000024 20 00 00 2C F8 8E FB DF DD 23 49 DB . . , . . . . . # I . 00 00 00 00 00 00 00 00 00 00 00 00 . . . . . . . . . . . . 03ffe4 00 00 00 00 32 41 36 4C 47 49 33 43 . . . . 2 A 6 L G I 3 C 03fff0 EA 5B E0 00 F0 2A 4D 52 42 2A 02 00 . [ . . . * M R B * . . 03fffc 00 00 FF FF . . . . . . a w ...... 03ff90 * Шестнадцатеричный дамп файла dump.bin, показанный в листинге 9.7, показывает лишь часть информации настоящего дампа, выводимого в терминале Linux, а именно — первый сжатый модуль двоичного файла BIOS в конце области кода блока начальной загрузки.