Приветствую,тут под моё внимание попала одна виндовая прога под названием memtest.efi это прога для теста RAM,так вот возникают такие вопросы к каким сервисам или апи даннная прога обращается ?,что нужно что бы разработать такую же прогу ? задачу она будет решать совсем другую, не тест RAM.Я гуглил на тему разработки таких приложений мне так найти и не удалось ничего.
*.efi это формат загрузочных файлов и модулей UEFI. Статей на эту тему мало. Вот к примеру https://habr.com/ru/post/274463/ АПИ описан в спецификации https://www.uefi.org/sites/default/files/resources/UEFI Spec 2_6.pdf Первые версии попроще будут. https://www.intel.com/content/dam/www/public/us/en/zip/efi-110.zip Лучше смотреть исходный код биосов и загрузчиков. https://github.com/fpmurphy/UEFI-Utilities https://github.com/linuxboot/linuxboot https://github.com/pbatard/uefi-ntfs/blob/master/boot.c
краткое вступление http://x86asm.net/articles/uefi-programming-first-steps/index.html Как писать - можно сразу на fasm'е . Если на C - нужен developement kit. Как сейчас не знаю - года 4 назад были самые используемые публичные это edk2 и Gnu efi. Первый заточен под студию, второй - под ГНУтое. Что в программе можно сделать - в функции main передаются параметры. Один из двух - это указатель на структуру EFI_SYSTEM_TABLE - что-то вроде рантайма + всяких структур. Через неё дергаются другие функции, работают с другими модулями и т.д. Про это надо читать соотв. доки по efi. Вообще, бОльшая часть кодинга под efi - чтение документации. Как это проверять. Если просто запустить приложение - из efi биоса загрузить EFI Shell (у вмвари есть вроде даже встроенная), из которой запустить приложение. А поотлаживать - на эмуляторе. Есть виндовый псевдоэмулятор ( но как-то имхо, не очень). Есть вариант встроить в efi биос vmware - выдрать из exe'шника её 'родной' биос виртуалки, добавить свое поделие чем-то вроде uefitool (тут надо понимать что и куда, а это читать оф. доки по efi) и дебажить по wmware gdb stub + Ida - реально почти как на реальном биосе ведет себя. Или qemu с ovmf bios . В реальный efi биос, скорее всего, просто встроить не получится - часто какая-то защита, нужно отключать.
njeen, memtest.efi я уже пробовал запускать в efi shell,он не запускается,и вообще структура memtest.efi и того PE файла что генерит edk2 очень сильно отличается,к примеру тот PE файл что генерит edk2 у него поле ImageBase = 0,винда с нулевым ImageBase файл не запустит,и у меня возникает такое предположение что memtest.efi ни какого абсолютно отношения к UEFI не имеет,то есть это чисто виндовая прога.Я даже на реальной машине с UEFI пробовал запустить memtest.efi
Если все еще интересно. Данные приложения boot application, вроде memtest, действительно не запускаются обычным образом. Подсистема установлена у них в 0x10. Но это efi приложения, только ожидающие в entry point другие параметры, которые скомпоновал виндовый boot manager. То есть, на точке входа такое приложение первым параметром ожидает указатель на структуру BOOT_APPLICATION_PARAMETER_BLOCK . Из нее можно получить стандартные efi'шные как-то так: Код (Text): BL_FIRMWARE_DESCRIPTOR* fwdesc = (BL_FIRMWARE_DESCRIPTOR*)(((UINTN)BootAppParameters) + BootAppParameters->FirmwareParametersOffset); EFI_HANDLE ImageHandle = fwdesc->ImageHandle; EFI_SYSTEM_TABLE* SystemTable = fwdesc->SystemTable; Только в них как-то странно обстоят дела с выводом на экран - его при попытке вывести, например, строку не видно вообще. И запустить это приложение надо не просто так - либо подписать чем-то, либо отключить подпись для этого пункта загрузки. Например, так bcdedit.exe /set {MY_GUID} loadoptions DDISABLE_INTEGRITY_CHECKS где MY_GUID - гуид корректно добавленной записи типа boot application в windows boot manager. У меня пока вышло только заставить запуститься без ругательств со стороны windows boot manager'а. Например, вот товарищ сделал такое boot application приложение, только под ARM'овый виндофон https://github.com/imbushuo/boot-shim.git . Там сделано вне edk2, и подписывает к тому же. И дискуссия про это http://reboot.pro/index.php?showtopic=17655&page=3 . Где еще можно об этом узнать - товарищ Ионеску заикался про какие-то свои курсы, как писать такие приложения, но в доступе нигде не нахожу. Также он вносит вклад в reactos - может, там какие-то следы есть.
njeen, я об этом с самого начала и толковал,к тому же у этого memtest предположительно имеются хардварные привелегии,глянул туда дизасмом обнаружил команды для отключения кэша процессора
Не совсем понял про какую версию Memtest.efi речь, но сам запускал такое приложение под Uefi на Atom буке. (входит, вроде, в сборку Strelec) Всё красиво выглядит в графике UEFI, но из проявившихся "шероховатостей" - медленное перемещение мыша (клавишами быстрее)
речь идёт об этом C:\Windows\Boot\EFI\memtest.efi --- Сообщение объединено, 27 апр 2021 --- файл по пути C:\Windows\Boot\EFI\memtest.efi, в дизассемблере IDA Version 7.0.191002 Freeware --- Сообщение объединено, 27 апр 2021 --- Windows 7 x64
Значица предоставляем себе возможность для запуска Windows boot приложений,за средство диагностики памяти отвечает загрузочная запись {memdiag},путём её модификации предоставим себе такую возможность,модифицировать будем следующим образом: 1.Определяем раздел где находится приложение Код (Text): bcdedit /set {memdiag} device PARTITION=C: 2.Указываем путь к приложению с подсистемой 0x10 Код (Text): bcdedit /set {memdiag} path \Windows\Boot\EFI\memtest.efi 3.Вносим однократную запись в менеджер загрузок {bootmgr},эта запись будет использована всего 1 раз Код (Text): bcdedit /bootsequence {bootmgr} {memdiag} --- Сообщение объединено, 30 апр 2021 --- после того как внесли однократную запись перезагружаемся и должно запуститься это приложение,в заголовке должна быть правильная контрольная сумма
Не выводились сообщения в моем тестовом boot application приложении вот почему. Потому, что boot application запускаются в protected mode, а работа с efi функционалом возможна только в real mode. И , например, чтобы вывести строку в консоль, они переключаются в real mode, дергают efi функции , затем возвращаются обратно. Моя догадка была правильной - тов. Ионеску сделал приложение в составе реактоси - аналог bootmgr. Можно даже изучать. https://doxygen.reactos.org/dir_e979f1c4d9aec725da11c29584d02043.html
но есть системы где efi нет,тогда в этом случаи какое будет у них поведение ? --- Сообщение объединено, 2 май 2021 --- Мне всё таки удалось запустить boot application,но для этого его пришлось подписать тестовым сертификатом,и проделать вот это Код (Text): bcdedit /set {bootmgr} TESTSIGNING 1 ну а далее это приложение я расположил в C:\Windows\Boot\EFI\ разумеется я его назвал memtest.efi
в файле memtest.efi заметил секцию .reloc,если делаем такое же приложение то скорее всего её надо сгенерировать
И так я написал такое приложение на ассмеблере,оно ничего не делает,без секции .reloc оно запустилось вот код на MASM64: memtest.asm Код (ASM): public startup .data argb db 0 .code startup: hlt jmp startup end компилим: Код (Text): ml64 memtest.asm линкуем: Код (Text): link memtest.obj /SUBSYSTEM:BOOT_APPLICATION /ENTRY:startup --- Сообщение объединено, 20 май 2021 --- запускал это приложение на Windows 7 x64 Корпоративная
А чому б ему не запуститься? Это всего лишь pe dll с измененной точкой входа и без импорта. И с поменянным признаком подсистемы.
Вдруг кому-то пригодится. Как написать рабочее windows boot application приложение, чтобы оно корректно работало под x86_64 как обычное efi приложение. 1. Описание Windows efi boot appliation - это тоже efi приложение, то со своими "особенностями". Отличия от обычного efi app: - в опциональном PE заголовке поле subsystem должно быть установлено в 0x10 - точка входа отличается - вместо привычной UefiMain, у которой 2 входных параметра EFI_HANDLE и EFI_SYSTEM_TABLE *, у этого типа прилложений точка входа имеет один параметр, который передает ей windows boot manager. И это указатель на недокументированную структуру BOOT_APPLICATION_PARAMETER_BLOCK. Из него можно, в том числе, добыть привычные нам EFI_HANDLE и EFI_SYSTEM_TABLE *. - Есть такое понятие у данных приложений, как "режим выполнения", или "контекст". Контекст бывает application context и firmware context. Firmware context - это контекст, в котором работают "обычные" efi приложения. Контекст application - это контекст, в котором изначально работают windows boot applications. Контекст определяется состоянием регистра cr3 и тем, разрешены ли прерывания. Можно переходить из одного режима в другой, переключая контекст. Это возможно, т.к при старте windows boot application мы имеем состояние регистра cr3 для контекста application context - и можем его где-то сохранить, а firmware context cr3 можно добыть посредством указателя на BOOT_APPLICATION_PARAMETER_BLOCK, полученном в entry point. Также в firmware context'е прерывания должны быть разрешены. В случае application context - запрещены. Если изменить контекст на firmware context, и добыть параметры EFI_HANDLE и EFI_SYSTEM_TABLE *, то можно вызывать "обычную" efi application entry point. Чтобы корректно "вернуться" после завершения программы, надо вернуть контекст в изначальное состояние. Зачем может понадобиться делать такие приложения - можно, например, сделать прокси загрузчик efi загрузчиков других ОС, которые не могут быть добавлены в windows boot menu непосредственно. Этот прокси загрузчик будет подгружать образ соотв. настоящего загрузчика и запускать его на выполнение. Либо можно прямо из опций загрузки windows запускать efi shell. Или вообще любое другое приложение. Либо подгружать загрузчик windows, делать небольшие, но очень необходимые патчи, и также запускать на выполнение. 2. Пример реализации Данный пример просто переходит в контекст firmware, запускает "обычную" efi application entry функцию, выводит hello world на экран, корректно возвращается из нее, переключает контекст обратно. Текст выводится очень быстро, поэтому, чтобы увидеть, можно, например, сделать перед возвратом управления бесконечный цикл. Также нужно помнить, что у собираемого efi subsystem должна быть проставлена в 0x10, иначе виндовый загрузчик не найдет приложение того типа, которое ищет. Текст программы усечен, реализация обычной efi части основана на http://x86asm.net/articles/uefi-programming-first-steps/index.html Код (ASM): format pe64 dll efi entry BaMain section '.text' code executable readable ; EFI_STATUS ; EFIAPI ; BaMain(BOOT_APPLICATION_PARAMETER_BLOCK * BootAppParameters) BaMain: ;jmp short BaMain ; debug loop ; get 'normal' efi entry parameters from boot parameters mov [BootAppParameters], rcx ; save address to boot parameters mov r8d, dword [rcx+0x30] ; get UINT32 FirmwareParametersOffset from BOOT_APPLICATION_PARAMETER_BLOCK lea r8, [rcx+r8] ; get BL_FIRMWARE_DESCRIPTOR address mov [firmwareDescriptorAddress], r8 mov rax, qword [r8+0x8] ; get BL_FIRMWARE_DESCRIPTOR::ImageHandle by offset 0x8 mov [ImageHandle], rax mov rax, qword [r8+0x10] ; get BL_FIRMWARE_DESCRIPTOR::SystemTable address by offset 0x10 mov [SystemTable], rax ; we're in 'application context' and it stored now in cr3. mov rax, cr3 mov [appContext], rax mov rax, qword [r8+0x1c] ; saved firmware context is stored by ; offset 0x1c in BL_FIRMWARE_DESCRIPTOR . ; Seems to be undocumented. mov [firmwareContext], rax call SwitchToFirmwareContext mov rcx, [ImageHandle] mov rdx, [SystemTable] sub rsp, 4*8 ; reserve space for 4 arguments for ms stdcall x64 function callings call UefiMain add rsp, 4*8 push rax ; save result from UefiMain call SwitchToApplicationContext pop rax ;@@: ; debug loop to show written text ;jmp short @b retn SwitchToFirmwareContext: mov rax, [firmwareContext] mov cr3, rax sti retn SwitchToApplicationContext: cli mov rax, [appContext] mov cr3, rax retn ; EFI_STATUS ; EFIAPI ; UefiMain ( ; IN EFI_HANDLE ImageHandle, ; IN EFI_SYSTEM_TABLE *SystemTable ; ) UefiMain: sub rsp, 4*8 ; reserve space for 4 arguments mov [ImageHandle], rcx ; ImageHandle mov [SystemTable], rdx ; pointer to SystemTable lea rdx, [_hello] mov rcx, [SystemTable] mov rcx, [rcx + 0x40] ; [rcx + EFI_SYSTEM_TABLE.ConOut] call qword [rcx + 8] ; [rcx + SIMPLE_TEXT_OUTPUT_INTERFACE.OutputString] add rsp, 4*8 mov rax, 0 ; EFI_SUCCESS retn section '.data' data readable writeable BootAppParameters dq ? firmwareDescriptorAddress dq ? appContext dq ? firmwareContext dq ? ImageHandle dq ? SystemTable dq ? _hello du 'Hello World',0xd,0xa,'(From windows boot app written in FASM)',0xd,0xa,0x0 section '.reloc' fixups data discardable 3. Добавление пункта с приложением в список загрузки windows boot manager (пример) - Нужно смонтировать boot volume на какую-нибудь букву. Пусть это будет K: - скопировать наш efi (boothello.efi) в папку \EFI\Boot\ - с помощью bcdedit.exe добавить соотв. запись в список загрузки: bcdedit /create /application bootapp /d "HelloBoot" Это создаст новую запись в бд boot manager'а, в результате выведется guid созданной записи. Дальше - <GUID>. bcdedit /set <GUID> path "\EFI\Boot\boothello.efi" Задаем путь к программе. bcdedit /set <GUID> device partition=k: Задаем раздел, к которому у нас сейчас примонтирован efi том bcdedit /displayorder <GUID> /addlast Добавим видимую строку в список загрузки bcdedit.exe /set <GUID> loadoptions DDISABLE_INTEGRITY_CHECKS Выключаем проверку crc приложения для данного guid bcdedit.exe /set {MY_GUID} nointegritychecks on Отключаем проверку того, подписано ли приложение. Если у вас crc корректный и вы сумели корректно подписать, то последние два пункта можно не делать ^^ . Ну и далее все - можно перезагружать и любоваться строчками текста, если все сделали правильно.