C 如何在EFI图形模式下使用文本?

C 如何在EFI图形模式下使用文本?,c,macos,uefi,C,Macos,Uefi,我是超级新创建efi应用程序。我的目标是在efi中创建一个小应用程序,在背景上显示一些文本。但是我一直在尝试在显示器上显示文本(最好有一个自定义字体,但在这个阶段没有必要)。我希望应用程序(也)在苹果系统上运行(从usb启动) 如何找到有关EFI函数的良好文档?似乎很难找到好的例子等等 如何使用EFI在背景上显示文本 这就是我目前得到的。我使用图形协议将背景更改为颜色。如何在其上显示文本。输出字符串似乎不起作用 #包括“efibind.h” #包括“efidef.h” #包括“efidevp.h

我是超级新创建efi应用程序。我的目标是在efi中创建一个小应用程序,在背景上显示一些文本。但是我一直在尝试在显示器上显示文本(最好有一个自定义字体,但在这个阶段没有必要)。我希望应用程序(也)在苹果系统上运行(从usb启动)

  • 如何找到有关EFI函数的良好文档?似乎很难找到好的例子等等

  • 如何使用EFI在背景上显示文本

  • 这就是我目前得到的。我使用图形协议将背景更改为颜色。如何在其上显示文本。输出字符串似乎不起作用

    #包括“efibind.h”
    #包括“efidef.h”
    #包括“efidevp.h”
    #包括“eficon.h”
    #包括“efiapi.h”
    #包括“efierr.h”
    #包括“efiprot.h”
    静态EFI_GUID GraphicsOutProtocolGUID=EFI_GRAPHICS_OUTPUT_ProtocolGUID;
    /**
    *efi_main-efi应用程序的入口点
    *@image:标识映像的固件分配句柄
    *@SystemTable:EFI系统表
    */
    EFI_状态EFI_主(EFI_句柄图像,EFI_系统表*系统表){
    EFI_BOOT_SERVICES*bs=systemTable->BootServices;
    EFI_状态;
    EFI_图形_输出_协议*图形协议;
    简单文本输出接口*conOut=systemTable->conOut;
    EFI_图形_输出_模式_信息*info;
    瑞士斯威特斯齐奥芬福;
    status=bs->LocateProtocol(&graphicsoutprotocolguid,NULL,
    (void**)和graphicsProtocol);
    如果(EFI|U错误(状态)| graphicsProtocol==NULL){
    conOut->OutputString(conOut,L“初始化gfx失败!\r\n”);
    返回状态;
    }
    输入输出->清除屏幕(输入输出);
    //切换到当前模式,以便启动gfx。
    状态=graphicsProtocol->SetMode(graphicsProtocol,graphicsProtocol->Mode->Mode);
    如果(EFI_错误(状态)){
    conOut->OutputString(conOut,L“无法设置默认模式!\r\n”);
    返回状态;
    }
    EFI_图形_输出_BLT_像素p;
    p、 红色=200;
    p、 绿色=77;
    p、 蓝色=13;
    graphicsProtocol->QueryMode(graphicsProtocol,graphicsProtocol->Mode->Mode,&SizeOfInfo,&info);
    sWidth=信息->水平分辨率;
    sHeight=信息->垂直分辨率;
    状态=graphicsProtocol->Blt(graphicsProtocol,&p,EFIBLTVIDEFILL,0,0,0,sWidth,sHeight,0);
    而(1){
    conOut->OutputString(conOut,L“我要显示的某些文本\r\n”);
    bs->摊位(500000);
    }
    返回EFI_成功;
    }
    
    如果您专门针对MacEFI,则需要额外的协议调用来强制控制台进入文本模式。

    UEFI支持图形输出。它还支持文本输出(这可能意味着输出到串行控制台,或文本呈现到图形控制台,或两者兼而有之)。但是,目前还没有一种明确的方式来控制它们之间的相互作用


    提供带有文本元素的图形环境(BIOS配置菜单,GRUB)的应用程序通常使用自己的框架,使用图形输出协议在图形控制台上绘制文本。

    这是使用字体模块的文本渲染器的一个简短示例(可独立使用,替换#包括lv_font.h文件中的“../../lv_conf.h”和#定义使用_lv_font_DEJAVU 20 8)以及图形输出协议中的Blt方法

    #include <Uefi.h>
    #include <Library\UefiLib.h>
    #include <Protocol\GraphicsOutput.h>
    #include "lv_font.h"
    
    #define LETTER_SPACE 2
    #define WAIT_SECONDS 10
    #define FONT &lv_font_dejavu_20
    
    static EFI_BOOT_SERVICES *gBS;
    static EFI_RUNTIME_SERVICES *gRT;
    static EFI_GRAPHICS_OUTPUT_PROTOCOL *gGOP = (EFI_GRAPHICS_OUTPUT_PROTOCOL *)NULL;
    static EFI_GRAPHICS_OUTPUT_BLT_PIXEL gWhite = { 255,255,255,0 };
    
    static void _util_render_glyph(UINT32 x, UINT32 y, CHAR8 letter)
    {
        UINT32        height;
        UINT32        width;
        UINT32        pm_x;
        UINT32        pm_y;
        UINT32        index;
        const UINT8*  bitmap;
        EFI_GRAPHICS_OUTPUT_BLT_PIXEL *pixelmap;
    
        if (gGOP == NULL) {
            return;
        }
    
        height = lv_font_get_height(FONT);
        width = lv_font_get_width(FONT, letter);
    
        // glyph is not defined in this font
        if (width == 0) {
            return;
        }
    
        bitmap = lv_font_get_bitmap(FONT, letter);
    
        // using 8 bpp for simplicity
        if (EFI_ERROR(gBS->AllocatePool(EfiLoaderData, height * width * sizeof(*pixelmap), (VOID**)&pixelmap))) {
            return;
        }
    
        gBS->SetMem((VOID*)pixelmap, height * width * sizeof(*pixelmap), 0);
    
        // get the current content of the framebuffer to allow 'transparent' blt operations
        gGOP->Blt(gGOP, pixelmap, EfiBltVideoToBltBuffer, x, y, 0, 0, width, height, 0);
    
        for (pm_y = 0; pm_y < height; pm_y++) {
            for (pm_x = 0; pm_x < width; pm_x++) {
                index = width * pm_y + pm_x;
    
                if (bitmap[index] > 200) {
                    pixelmap[index].Red = 0;
                    pixelmap[index].Blue = 0;
                    pixelmap[index].Green = 0;
                    pixelmap[index].Reserved = 0;
                }
                else if (bitmap[index] > 100) {
                    pixelmap[index].Red = 105;
                    pixelmap[index].Blue = 105;
                    pixelmap[index].Green = 105;
                    pixelmap[index].Reserved = 0;
                }
            }
        }
    
        gGOP->Blt(gGOP, pixelmap, EfiBltBufferToVideo, 0, 0, x, y, width, height, 0);
        gBS->FreePool(pixelmap);
    }
    
    static void _util_render_text(UINT32 x, UINT32 y, const CHAR8 *string)
    {
        UINT32 index;
        UINTN length;
        UINT32 scr_w;
        UINT32 scr_h;
    
        UINT32 str_x;
    
        UINT32 gly_w;
        UINT32 gly_h;
    
        if (string == NULL) {
            return;
        }
    
        if (gGOP == NULL) {
            return;
        }
    
        scr_w = gGOP->Mode->Info->HorizontalResolution;
        scr_h = gGOP->Mode->Info->VerticalResolution;
    
        length = AsciiStrnLenS(string, 32);
    
        gly_h = lv_font_get_height(FONT);
    
        // check if the string can be printed 
        if ((y + gly_h) > scr_h) {
            return;
        }
    
        if (x > scr_w) {
            return;
        }
    
        // print the string glyph by glyph
        str_x = x;
        for (index = 0; index < length; index++) {
            // check if the glyph can be printed
            gly_w = lv_font_get_width(FONT, string[index]);
            if ((str_x + gly_w) > scr_w) {
                break;
            }
    
            // print the glyph
            _util_render_glyph(str_x, y, string[index]);
    
            // calculate the position of the next glyph
            str_x += gly_w + LETTER_SPACE;
        }
    }
    
    static void _util_fill_screen(EFI_GRAPHICS_OUTPUT_BLT_PIXEL *color)
    {
        if (gGOP == NULL) {
            return;
        }
    
        gGOP->Blt(gGOP, color, EfiBltVideoFill, 0, 0, 0, 0, gGOP->Mode->Info->HorizontalResolution, gGOP->Mode->Info->VerticalResolution, 0);
    }
    
    
    static void _util_wait(UINT32 seconds)
    {
        EFI_TIME    time;
        UINT8       current_second = 255;
        UINT32      elapsed_seconds = 0;
    
        //wait for some seconds
        while (elapsed_seconds <= WAIT_SECONDS) {
            if (!EFI_ERROR(gRT->GetTime(&time, (EFI_TIME_CAPABILITIES*)NULL))) {
                if (current_second != time.Second) {
                    elapsed_seconds++;
                    current_second = time.Second;
                }
            }
            else {
                break;
            }
            CpuPause();
        }
    }
    
    EFI_STATUS
    EFIAPI
    UefiMain(
        IN EFI_HANDLE        ImageHandle,
        IN EFI_SYSTEM_TABLE  *SystemTable)
    {
        EFI_STATUS  eRc;
    
        gBS = SystemTable->BootServices;
        gRT = SystemTable->RuntimeServices;
    
        eRc = gBS->LocateProtocol(
            &gEfiGraphicsOutputProtocolGuid,
            NULL,
            (VOID**)&gGOP);
    
        if (EFI_ERROR(eRc) || gGOP == NULL) {
            return EFI_SUCCESS;
        }
    
        _util_fill_screen(&gWhite);
        _util_render_text(0, 0, "HELLO WORLD!");
    
        _util_wait(WAIT_SECONDS);
    
        return EFI_SUCCESS;
    }
    
    #包括
    #包括
    #包括
    #包括“lv_font.h”
    #定义字母_空格2
    #定义等待10秒
    #定义字体&lv\u FONT\u dejavu\u 20
    静态EFI_引导_服务*gBS;
    静态EFI_运行时_服务*gRT;
    静态EFI_图形_输出_协议*gGOP=(EFI_图形_输出_协议*)NULL;
    静态EFI_图形_输出_BLT_像素gWhite={255255,0};
    静态无效_util_render_图示符(UINT32 x,UINT32 y,字符8)
    {
    UINT32高度;
    UINT32宽度;
    UINT32下午十点;
    UINT32下午(y);
    UINT32指数;
    const UINT8*位图;
    EFI_图形_输出_BLT_像素*像素地图;
    if(gGOP==NULL){
    返回;
    }
    高度=lv\U font\U get\U高度(font);
    宽度=lv\u字体\u获取\u宽度(字体,字母);
    //此字体中未定义字形
    如果(宽度==0){
    返回;
    }
    位图=lv\U font\U get\U位图(字体、字母);
    //为了简单起见,使用8bpp
    如果(EFI_错误(gBS->AllocatePool(EfiLoaderData,高度*宽度*大小(*pixelmap),(VOID**)和pixelmap))){
    返回;
    }
    gBS->SetMem((VOID*)像素地图,高度*宽度*大小(*像素地图),0;
    //获取帧缓冲区的当前内容以允许“透明”blt操作
    gGOP->Blt(gGOP,像素地图,EfiBltVideoToBltBuffer,x,y,0,0,宽度,高度,0);
    对于(pm_y=0;pm_y200){
    pixelmap[索引]。红色=0;
    pixelmap[索引]。蓝色=0;
    pixelmap[索引]。绿色=0;
    pixelmap[索引]。保留=0;
    }
    else if(位图[索引]>100){
    像素图[索引]。红色=105;
    像素图[索引]。蓝色=105;
    像素图[索引]。绿色=105;
    pixelmap[索引]。保留=0;
    }
    }
    }
    gGOP->Blt(gGOP,像素地图,EfiBltBufferToVideo,0,0,x,y,宽度,高度,0);
    gBS->FreePool(像素地图);
    }
    静态void\u util\u render\u文本(UINT32 x,UINT32 y,const CHAR8*字符串)
    {
    UINT32指数;
    单位长度;
    UINT32 scr_w;
    UINT32 scr_h;
    UINT32 str_x;
    UINT32-gly_-w;
    UINT32-gly_-h;
    if(字符串==NULL){
    返回;
    }
    if(gGOP==NULL){
    返回;
    }
    scr_w=gGOP->模式->信息->水平分辨率;
    scr\U h=gGOP->模式->信息->垂直分辨率;
    长度=ASCISTRNLENS(字符串,32);
    gly_h=lv_字体获得高度(F