Вот пример кода, который использует UEFI для получения и печати доступных графических режимов на первом графическом устройстве и при необходимости устанавливает режим.
Я использовал эту ссылку: http://wiki.phoenix.com/wiki/index.php/EFI_GRAPHICS_OUTPUT_PROTOCOL.
Примечанияна реализацию:
- Вызывает LocateProtocol для получения протокола вывода графики.Я пытался использовать LocateHandle, чтобы получить все дескрипторы, которые поддерживают протокол вывода графики.Он вернул два дескриптора, но OpenProtocol не удалось.У меня не было возможности отладить версию с LocateHandle.Эта версия с использованием LocateProtocol работает.
- Она печатает количество доступных режимов, текущий режим и характеристики каждого режима.
- Параметром для функции является режим, который необходимо установить.Если это -1, режим не изменяется.В противном случае оно должно быть между 0 и N - 1, где N - количество поддерживаемых графических режимов.Параметр не проверяется этой функцией, но функция SetMode проверяет его.
- Используются соглашения о вызовах функций Sys V x86-64, за исключением вызовов функций UEFI, которые используют соглашение UEFI.
- Он использует функцию с именем efi_printf, которая работает так же, как printf, и выполняет запись в ConOut с использованием EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.
- Она опирается на код запуска, хранящий указатель на таблицу служб загрузки EFI в глобальной переменной с именем efi_boot_services.
- Это написано для газа, а не для насм.
Вот пример вывода:
max mode: 5
mode 1: size 36, ver 0, hor res 800, ver res 600, pixel format 1
frame buffer: b1000000, frame buffer size: 1d4c00
mode 0: size 36, ver 0, hor res 640, ver res 480, pixel format 1
mode 1: size 36, ver 0, hor res 800, ver res 600, pixel format 1
mode 2: size 36, ver 0, hor res 1024, ver res 768, pixel format 1
mode 3: size 36, ver 0, hor res 1280, ver res 1024, pixel format 1
mode 4: size 36, ver 0, hor res 1600, ver res 1200, pixel format 1
Я предполагаю, что вы знакомы с UEFI, поэтому я необъяснил, как все работает, поэтому дайте мне знать, если вам нужно больше объяснений.
.intel_syntax noprefix
.section .text
.align 16
.globl gfxmode
gfxmode:
push rbx
push rbp
push r14
push r15
sub rsp, 0x38
mov ebp, edi // desired mode
lea rcx, EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID[rip]
xor edx, edx // arg 2: unused
lea r8, 0x20[rsp] // arg 3: address of protocol
mov rax, efi_boot_services[rip]
call 0x140[rax] // locate protocol
test rax, rax
js 2f
mov r15, 0x20[rsp] // graphics output protocol
mov r14, 0x18[r15] // mode
lea rdi, trace1[rip]
mov esi, [r14] // max mode
call efi_printf
mov rdi, 8[r14] // current mode info
mov esi, 4[r14] // current mode number
mov edx, 16[r14] // current mode info size
call print_mode
lea rdi, trace3[rip]
mov rsi, 24[r14] // frame buffer addr
mov rdx, 32[r14] // frame buffer size
call efi_printf
xor ebx, ebx
1:
mov rcx, r15 // arg 1: graphics output protocol
mov edx, ebx // arg 2: mode number
lea r8, 0x30[rsp] // arg 3: &info size
lea r9, 0x28[rsp] // arg 4: &info
call 0x00[rcx] // query mode
test rax, rax
js 2f
mov rdi, 0x28[rsp] // mode info
mov esi, ebx // mode number
mov edx, 0x30[rsp] // mode info size
call print_mode
mov rax, efi_boot_services[rip]
mov rcx, 0x28[rsp] // mode info
call 0x48[rax] // free pool
inc ebx
cmp ebx, [r14] // max mode
jb 1b
xor eax, eax
test ebp, ebp // new mode
js 2f
mov rcx, r15 // arg 1: graphics output protocol
mov edx, ebp // arg 2: mode number
call 0x08[rcx] // set mode
2:
add rsp, 0x38
pop r15
pop r14
pop rbp
pop rbx
ret
.align 16
print_mode:
// rdi: mode info
// esi: mode number
// edx: mode size
mov ecx, [rdi] // mode version
mov r8d, 4[rdi] // hor res
mov r9d, 8[rdi] // ver res
mov eax, 12[rdi] // pixel format
push rax
lea rdi, trace2[rip]
call efi_printf
add rsp, 8
ret
trace1: .asciz "max mode: %d\n"
trace2: .asciz "mode %d: size %d, ver %d, hor res %d, ver res %d, pixel format %d\n"
trace3: .asciz "frame buffer: %p, frame buffer size: %llx\n"
.align 16
EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID:
.byte 0xde,0xa9,0x42,0x90,0xdc,0x23,0x38,0x4a
.byte 0x96,0xfb,0x7a,0xde,0xd0,0x80,0x51,0x6a