组装-如何在UEFI中设置图形模式(不使用VGA,不使用BIOS,不使用任何东西) [英] Assembly - How to set graphics mode in UEFI (No VGA, No BIOS, Nothing deprecated)
问题描述
我正在使用的工具:nasm,qemu-system-x86_64。
Tools I'm using: nasm, qemu-system-x86_64.
我使用的操作系统:Windows 10。
Operating System I'm on: Windows 10.
因此,我在 https://wiki.osdev处检查了实模式操作系统警告 .org / Real_Mode_OS_Warning
该文章似乎暗示,无需使用BIOS中断即可完成所有操作。我知道如何加载长模式,因此我已经做到了,但是现在我被困住了,因为到目前为止,我只知道BIOS中断。我想做一些类似的操作,将图形模式设置为全内存访问模式(如果您看到 int 10h / AX = 4F02h / BX = 81FFh
,可能听起来很熟悉) ),但是由于我不想使用已过时的东西(BIOS),因此在网上搜索如何设置图形模式并仅在长模式下访问单个像素时遇到了麻烦。
What the article seems to imply is that everything can be done without using BIOS interrupts whatsoever. I know how to load Long Mode, and so I've done this, but now I am stuck because BIOS interrupts were all I knew until now. I want to do something like set the graphics mode to full-memory-access-mode (might sound familiar if you've seen int 10h / AX = 4F02h / BX = 81FFh
), but since I don't want to use something that's deprecated (BIOS), I have been having trouble searching the web for how to set the graphics mode and then access individual pixels in Long Mode only.
希望可以在StackOverflow上回答这个问题。我坚信太复杂了不会作为答案,特别是因为OSDev告诉我不要使用不推荐使用的东西。告诉某人这太困难了,他们会假设他们知道什么以及他们能够学习什么,甚至都不知道自己是谁。我只是需要一个起点来了解如何做到这一点。
Hopefully it turns out to be possible to answer this question on StackOverflow. I have much faith that "it's too complicated" won't show up as an answer, especially since I was just told by OSDev NOT to use deprecated things. Telling someone it's too difficult assumes what they know and what they're able to learn without even knowing who they are. I just need a starting point to find out how to do this.
为了澄清一下,对我不起作用的事情:
To give clarification, things that didn't work for me:
这对我不起作用,因为答案给出了我不想要的VGA链接。
This didn't work for me because the answer gives a link to VGA, which I don't want.
这对我不起作用,因为问题不是关于长模式的问题,而是关于实模式下的VGA图形的问题。
This didn't work for me because the question does not ask about Long Mode, but rather about VGA graphics in Real Mode.
这对我不起作用,因为答案本质上是它太复杂了,请使用已弃用的stuf f,这与我正在尝试做的相反,并且与我刚刚在OSDev上告诉的相反。
This didn't work for me because the answer was essentially "it's too complicated, use the deprecated stuff", which is the opposite of what i'm trying to do and quite contradictory to what I was just told on OSDev.
这对我不起作用,因为答案与设置图形模式无关。
This didn't work for me because the answer has nothing to do with setting the graphics mode.
这对我不起作用因为答案没有说明如何在UEFI中设置图形模式。他们只谈论过时的东西。
This didn't work for me because the answers do not say how to set the graphics mode in UEFI. They only talk about deprecated things.
推荐答案
下面是使用UEFI获取并打印第一个可用图形模式的示例代码。图形设备并可以选择设置模式。
Here is sample code that uses UEFI to get and print the available graphics modes on the first graphics device and optionally sets the mode.
我使用了以下引用: http://wiki.phoenix.com/wiki/index.php/EFI_GRAPHICS_OUTPUT_PROTOCOL 。
实施注意事项:
- 它调用LocateProtocol以获取图形输出协议。我尝试使用LocateHandle获得支持图形输出协议的所有句柄。它返回了两个句柄,但是OpenProtocol失败了。我还没有机会用LocateHandle调试版本。此版本使用LocateProtocol起作用。
- 它打印可用模式的数量,当前模式以及每种模式的特征。
- 参数to该功能是要设置的模式。如果为-1,则不更改模式。否则,它必须在0到N-1之间,其中N是支持的图形模式数。此函数未检查该参数,但SetMode函数对其进行了检查。
- 它使用Sys V x86-64函数调用约定,但使用UEFI约定的UEFI函数调用除外
- 它使用一个名为efi_printf的函数,该函数与printf一样,并使用EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL写入ConOut。
- 它依赖于启动代码存储
- 它是为gas而不是nasm编写的。
- It calls LocateProtocol to obtain a Graphics Output Protocol. I tried using LocateHandle to obtain all the handles that support Graphics Output Protocol. It returned two handles, but OpenProtocol failed. I haven't had a chance to debug the version with LocateHandle. This version using LocateProtocol works.
- It prints the number of available modes, the current mode, and the characteristics of each mode.
- The parameter to the function is the mode to set. If it is -1, the mode is not changed. Otherwise it must be between 0 and N - 1, where N is the number of graphics modes supported. The parameter is not checked by this function, but the SetMode function checks it.
- It uses Sys V x86-64 function calling conventions, except for calls to UEFI functions, which use the UEFI convention.
- It uses a function called efi_printf, which works just like printf and writes to ConOut using EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.
- It relies on the startup code storing a pointer to the EFI Boot Services Table in a global variable named efi_boot_services.
- It is written for gas rather than nasm.
这里是示例输出:
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,所以我还没有解释一切工作原理,所以请告诉我是否需要更多解释。
I assume you are familiar with UEFI, so I haven't explained how everything works, so let me know if you need more explanation.
.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
这篇关于组装-如何在UEFI中设置图形模式(不使用VGA,不使用BIOS,不使用任何东西)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!