Многие относятся к BIOS (имеется в виду именно программа) как к чему-то незыбленно-потаённому, известному только узкому кругу разработчиков и совершенно не подлежащему самостоятельной правке. Однако реально не всё так страшно, я бы даже сказал – всё достаточно просто, надо только чётко понимать и осознавать, что ты делаешь. И тогда вы сможете получить моральное удовольствие от собственной картинки в BIOS да повеселиться, увидев при загрузке «Pentium 12 - 33.33GHz». или, если серьёзно, добавить дополнительные возможности вашей плате – будь то поддержка «больших винтов» или каких-то новых, незнакомых вашей старенькой маме, других устройств (если, конечно, вы – программист).
Попробуем разобраться. Чтоб не опростоволоситься, нужно чётко знать две вещи: как устроен биос, что делать и чем.
Для начала – «чем» – инструментарий:
В начале кратко, но достаточно точно рассмотрим основные части биоса. Он состоит из двух главных частей:
1. BootBlock.
В его функцию входят самые первые шаги по инициализации регистров чипсета и распаковка главной части в память для последующего исполнения. При несовпадении подсчитанной контрольной суммы биоса он же (bootblock) запускает программу аварийного восстановления биоса (с дисковода).
2. Основная часть.
Главный исполняемый код. Состоит из нескольких «модулей» и хранится в запакованном виде как архив LHA с немного изменёнными заголовками (не принципиально для нас). Как правило, используются следующие названия для составных частей (модулей) этого «архива» (детально можно посмотреть с помощью утилиты cbrom):
- original.tmp – главная часть, всегда размером 128k, она нас и интересует. Именно в ней происходит вся инициализация компьютера, в ней же подпрограмма BIOS Setup
- awardext.rom – «расширение» главной части, в т.ч. в нём подпрограмма вывода конфигурации компьютера - табличка, появляющаяся сразу же перед «Starting Windows (DOS, linux и т.д.) …»
- awardepa.bin – «картинка» Energy Star
Другие встречающиеся части:
- cpucode.bin – таблица микрокодов для Intel-процессоров (PPro, P2/P3/P4, Celeron)
- acpitbl.bin – подпрограмма поддержки ACPI
Так же, бывает, попадаются всякие VGA.rom (при интегрированном видео), logo.bin и др., что есть либо не принципиально, либо банально-понятно. Названия могут меняться производителем, но по смыслу-размеру-названию всегда можно догадаться.
Как теперь стало понятно, «просто» редактировать биос нельзя, т.к. это архив. Поэтому, если мы хотим что-то изменить – сначала надо распаковать нужную часть, исправить, что нужно и запаковать обратно. «Главная» часть, как уже говорилось, это original.tmp. Его и будем править.
Рецепт 1 (описан в интернете).
Берём modbin, открываем в нём нужный файл биоса (прошивки, которую будем править). modbin создаёт два временных файла – bios.rom и original.tmp. bios.rom – это просто копия открытого файла, а вот original.tmp – это и есть уже распакованный наш «главный» модуль (см. выше). Т.е. распаковка – просто.
Если мы выберем в modbin верхний пункт «Update File», то «временный» файл original.tmp запаковывается назад в файл биоса. Напрашивается простое решение: если это сделать (открыть файл биоса в modbin) из-под винды, а потом просто переключиться по Alt-Tab в любой другой файлменеджер (VC, Explorer, Far и т.п.) – то у нас появится возможность внести любые изменения в original.tmp. Сделав, что нужно, переключаемся назад в modbin и тискаем “update”. modbin берёт исправленный нами original.tmp и сам запаковывает его в биос. Всё – радуемся. (Особенно, ежели после перешивки исправленная версия заработает:)
Однако описанный способ имеет важный недостаток – он не позволяет исправлять второй сегмент, т.е. можно менять лишь первые 64k – 00000-0FFFFh. Просто во вторых 64k лежат изменяемые модбином всякие регистры, потому он вторые 64k заменяет «своими», и все изменения по адресам 10000-1FFFFh игнорируются. Этого недостатка лишён второй способ. Кроме этого, в отличие от первого, здесь всё делается под «голым» ДОСом, а также можно распаковать и изменить любой «модуль».
Рецепт 2 (©apple_rom;)
Придётся чуть более подробно поговорить о структуре биос. Как было сказано выше, биос представляет собой архив. Но правильнее и точнее – это последовательность заархивированных с помощью LHA файлов с bootblock-ом в конце. Он (bootblock), конечно же, не заархивирован, т.к. именно он и распаковывает все эти «модули» в оперативную память. В применении к конкретными адресам структура примерно такова:
Таблица 1. Структура и адреса для 1Mbit-ного (128kB) биоса.
00000 – xxxxx+1 | Файл запакованного original.tmp плюс один байт («дополнительного» CRC) |
xxxxx+1 – yyyyy | Cразу же дальше (т.е. без разрыва) идёт файл следующего запакованного модуля, например, awardext.rom (на конце уже никаких «дополнительных» байтов) |
yyyyy – zzzzz | Дальше (также без разрыва) – следующий. И так все имеющиеся в конкретном биосе модули |
zzzzz - ~17FFEh* | Свободное место, обычно заполняется «00» или «FF» |
~1C000* – 1FFFFh | Бутблок |
* - адреса могут отличаться, т.к. бывают прошивки с разными по величине бутблоками.
Теперь о том, что представляет собой заголовок LHA-архива. Мы не будем вникать в подробности, а лишь отметим те моменты, которые нам помогут точно определить его начало (ведь все «модули» идут друг за другом «без пробелов»). Зная адрес начала каждого модуля, мы будем знать, соответственно и его конец. Начало любого файла, заархивированного с помощью LHA, выглядит примерно так: "%·-lh5...". Главный и постоянный отличительный признак здесь – “lh5”, эти три символа присутствует всегда. Три символа левей “lh5” – и есть начало. Т.е. просто введя несколько раз подряд поиск “lh5” мы запросто вычислим вышеуказанные xxxxx+1 (отнимая тройку от адреса найденного “lh5”), yyyyy, zzzzz… Разберём на конкретном примере - прошивка для платы Zida 5SVA v.1.4:
Начало:
00000000: 25 E6 2D 6C-68 35 2D B3-4D 01 00 00-00 02 00 00 %ц-lh5-│M☺ ☻
00000010: 00 00 50 20-01 0C 6F 72-69 67 69 6E-61 6C 2E 74 P ☺♀original.t
00000020: 6D 70 07 08-20 00 00 2D-08 8E 1E FD-AC 49 4B DA mp•◘ -◘О▲¤мIK┌
Тут и так понятно, начало файла заархивированного original.tmp – 00000. Ищем следующее “lh5”:
Следующее найденное “lh5”:
00014DD0: 39 0B F8 01-C1 E8 07 61-FA 50 00 B9-25 73 2D 6C 9♂°☺┴ш•a·P ╣%s-l
00014DE0: 68 35 2D 79-02 00 00 42-06 00 00 00-00 02 40 20 h5-y☻ B♠ ☻@
00014DF0: 01 0C 41 57-41 52 44 45-50 41 2E 42-49 4E 29 49 ☺♀AWARDEPA.BIN)I
Как видно, дальше идёт файл заархивированной картинки EnergyStar – AWARDEPA.BIN. Он начинается с адреса 14DDCh. Соответственно, файл заархивированного original.tmp – 0-14DDAh. На байт 14DDBh (CRC) не обращаем внимания, его позже пересчитает и установит сам modbin.
Следующее найденное “lh5”:
00015070: 0F 68 CF 55-8F 4F 88 8C-9B 96 B5 80-00 25 B3 2D ☼h╧UПOИМЫЦ╡А %│-
00015080: 6C 68 35 2D-E1 1D 00 00-98 2B 00 00-00 00 00 41 lh5-с↔ Ш+ A
00015090: 20 01 0C 61-77 61 72 64-65 78 74 2E-72 6F 6D 51 ☺♀awardext.romQ
Нашли по адресу 1507Dh начало awardext.rom. Получается, AWARDEPA.BIN – 0-14DDCh. Кстати, как уже заметно, последний байт LHA-архива всегда “00”.
Последнее найденное “lh5”:
0001E860: 8E D8 8E C0-66 BE 00 00-0E 00 67 66-81 7E 02 2D О╪О└f╛ ♫ gfБ~☻-
0001E870: 6C 68 35 74-07 66 81 CE-00 00 F0 FF-66 BF 00 00 lh5t•fБ╬ Ё f┐
0001E880: 01 00 66 B9-00 80 00 00-67 F3 66 A5-0F 20 C0 24 ☺ f╣ А gєfе☼ └$
Последнее найденное “lh5” отбрасываем, так как видно даже по адресам, что это область бутблока. Чтоб найти конец awardext.rom, просто пролистываем прошивку после предпоследнего “lh5” до начала пустого места (заполнено “00” или “FF”).
00016E70: 11 85 2A F7-D0 82 2D 90-76 0A E6 27-39 FB FC 17 ◄Е*ў╨В-Рv◙ц`9√№↨
00016E80: 5B EC 16 B0-C0 00 FF FF-FF FF FF FF-FF FF FF FF [ь▬░└
00016E90: FF FF FF FF-FF FF FF FF-FF FF FF FF-FF FF FF FF
Т.е. с 16E86h начинается пустое место, значит awardext.rom – 1507D-16E85h.
Если записать найденные куски кода в файлы, дать им расширение “*.lha”, то с помощью LHA (или любого другого «современного» архиватора) сможем их разархивировать и получить нужные нам файлы для просмотра/правки.
Теперь, подробно зная «скелет» прошивки нам не составит труда её разобрать и собрать. После наших (ваших;) исправлений, отредактированный файл original.tmp запаковываем с помощью LHA (название архиву можно дать любое). В конец полученному “*.lha”-файлу дописываем предварительно сохранённый кусок кода 14DDB-16E85h, т.е. все остальные «модули» (в т.ч. байт CRC), кроме original.tmp. Это можно сделать с помощью любого hex-редактора или, например, выбрав “Append” вместо “Overwrite” в WindowsCommander-е. Таким образом получим новый «слепок» заархивированных «модулей». Его и записываем в начало файла прошивки (поверх имеющегося). Конечно, после наших действий изменится контрольная сумма, поэтому для того, чтоб пересчитать/перезаписать CRC полученной прошивки, просто открываем её в модбине и, ничего не изменяя, нажимаем “Update File”. Если модбин при открытии не «возмутится», значит, всё было проделано правильно.
Мы рассмотрели алгоритм замены для 1Mbit-ных (128kB) биосов. Для 2Mbit- ных всё ещё проще, т.к. original.tmp лежит отдельно от других модулей:
Таблица 2. Структура и адреса для 2Mbit-ного (256kB) биоса.
00000 – xxxxx | Файл одного из запакованных «модулей», например, awardext.rom |
xxxxx – yyyyy | Cразу же дальше (т.е. без разрыва) идёт файл следующего запакованного модуля, например, cpucode.bin. Дальше (также без разрыва) – следующий. И так все имеющиеся в конкретном биосе “модули” (кроме original.tmp) |
yyyyy – 1FFFFh | Свободное место, обычно заполняется «00» или «FF» |
20000 – zzzzz+1 | Файл запакованного original.tmp плюс один байт («дополнительного» CRC) |
zzzzz+1 - ~37FFEh* | Свободное место, обычно заполняется «00» или «FF» |
~3C000* – 3FFFFh | Бутблок |
* - адреса могут отличаться, т.к. бывают прошивки с разными по величине бутблоками.
И значит, не надо дополнительно мучаться с оставшимися «модулями» - заархивированный LHA модуль original.tmpзаписываем по адресу 20000h в нашу прошивку (поверх, конечно) и для пересчёта CRC «пересохраняем» (“Update File”) в модбине.
Правка BootBlock-а.
BootBlock, располагающийся в самом конце биоса, как уже говорилось, не запакован (ведь кто-то должен всё распаковывать:). Поэтому с правкой тут особых проблем нет – берём любой hex-редактор и правим. CRC считается вплоть до 17FFFh для 1M-bit и 37FFFh для 2M-bit, так что если вы исправили что-то по более старшим адресам, обновлять CRC не нужно.
Примечание для программистов: не забывайте – в бутблоке не используется стэк (он на первой стадии инициализации запрещён), поэтому для исполнения своих подпрограмм пользоваться указателем sp «вручную». Как? – проще взглянуть на любой кусок кода оттуда от любой прошивки и станет понятно.