组装-如何在UEFI中设置图形模式(不使用VGA,不使用BIOS,不使用任何东西) [英] Assembly - How to set graphics mode in UEFI (No VGA, No BIOS, Nothing deprecated)

查看:259
本文介绍了组装-如何在UEFI中设置图形模式(不使用VGA,不使用BIOS,不使用任何东西)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用的工具: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.

组件8086中的图形模式

这对我不起作用,因为问题不是关于长模式的问题,而是关于实模式下的VGA图形的问题。

This didn't work for me because the question does not ask about Long Mode, but rather about VGA graphics in Real Mode.

如何在不使用BIOS的情况下将数据写入图形卡?

这对我不起作用,因为答案本质上是它太复杂了,请使用已弃用的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.

直接在Intel 8086上通过图形卡绘图

这对我不起作用,因为答案与设置图形模式无关。

This didn't work for me because the answer has nothing to do with setting the graphics mode.

一些x86汇编语言问题

这对我不起作用因为答案没有说明如何在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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆