菜单

kaoqi
kaoqi
发布于 2026-09-04 / 22 阅读
0
0

依托EDK2的自定义efi文件编译命令流程

efi文件的编译过程将会分为编译、链接、格式转换三个部分。

编译

此时进行编译,需要指定gcc命令,指定gcc编译过程中的参数,指定编译文件(将GOP文件替换为你希望的文件)。

编译命令如下:

aarch64-linux-gnu-gcc -c -Os -g -fshort-wchar -fno-builtin -Wall -fno-common -ffunction-sections -fdata-sections -mlittle-endian -fno-short-enums -funsigned-char -fno-asynchronous-unwind-tables -fno-unwind-tables -fno-pic -fno-pie -fno-stack-protector -ffreestanding -ffixed-x18 -mcmodel=small -fPIC -o GOP.obj GOP.c

链接命令如下:

aarch64-linux-gnu-gcc -o GOP.dll  -nostdlib  -Wl,--gc-sections -Wl,-e,EFI_Main,-Map,/GOP.map -z common-page-size=0x1000  -Os  -g  -fshort-wchar  -fno-builtin  -Wall  -Wno-array-bounds  -fno-common  -ffunction-sections  -fdata-sections  -mlittle-endian  -fno-short-enums  -fverbose-asm  -funsigned-char  -Wno-address  -fno-asynchronous-unwind-tables  -fno-unwind-tables  -fno-pic  -fno-pie  -Wl,-plugin-opt=-fno-stack-protector  -ffreestanding  -ffixed-x18  -mcmodel=small  -Wno-unused-but-set-variable  -Wno-unused-const-variable  -fPIC  -Wl,--script=/edk2/BaseTools/Scripts/GccBase.lds  -Wl,--defsym=PECOFF_HEADER_SIZE=0x228  -Wno-error  GOP.obj

格式转换命令如下:

GenFw -e UEFI_APPLICATION -o /GOP.efi /GOP.dll

编译后的执行效果

如下:

GOP源代码:(说明汇编S文件并不一定是必须的)

typedef unsigned long long UINT64;
typedef long long INT64;
typedef unsigned int UINT32;
typedef unsigned short UINT16;
typedef unsigned short CHAR16;
typedef unsigned char UINT8;
typedef UINT64 UINTN;
typedef INT64 INTN;
typedef void VOID;

typedef UINT32 EFI_STATUS;
typedef VOID* EFI_HANDLE;

#define NULL ((void *)0)

typedef struct {
    UINT32  Data1;
    UINT16  Data2;
    UINT16  Data3;
    UINT8   Data4[8];
} EFI_GUID;

typedef struct {
    UINT64      Signature;
    UINT32      Revision;
    UINT32      HeaderSize;
    UINT32      CRC32;
    UINT32      Reserved;
} EFI_TABLE_HEADER;

typedef struct {
    UINT8                        Blue;
    UINT8                        Green;
    UINT8                        Red;
    UINT8                        Reserved;
} EFI_GRAPHICS_OUTPUT_BLT_PIXEL;

typedef enum {
    EfiBltVideoFill,
    EfiBltVideoToBltBuffer,
    EfiBltBufferToVideo,
    EfiBltVideoToVideo,
    EfiGraphicsOutputBltOperationMax
} EFI_GRAPHICS_OUTPUT_BLT_OPERATION;

typedef enum {
    PixelRedGreenBlueReserved8BitPerColor,
    PixelBlueGreenRedReserved8BitPerColor,
    PixelBitMask,
    PixelBltOnly,
    PixelFormatMax
} EFI_GRAPHICS_PIXEL_FORMAT;

typedef struct {
    UINT32              RedMask;
    UINT32              GreenMask;
    UINT32              BlueMask;
    UINT32              ReservedMask;
} EFI_PIXEL_BITMASK;

typedef struct {
    UINT32 Version;
    UINT32 HorizontalResolution;
    UINT32 VerticalResolution;
    EFI_GRAPHICS_PIXEL_FORMAT PixelFormat;
    EFI_PIXEL_BITMASK PixelInformation;
    UINT32 PixelsPerScanLine;
} EFI_GRAPHICS_OUTPUT_MODE_INFORMATION;

typedef EFI_STATUS 
(*EFI_GRAPHICS_OUTPUT_PROTOCOL_QUERY_MODE) (
    UINT32 *This,
    UINT32 ModeNumber,
    UINTN *SizeOfInfo,
    EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
);

typedef EFI_STATUS
(*EFI_GRAPHICS_OUTPUT_PROTOCOL_SET_MODE) (
    UINT32 *This,
    UINT32 ModeNumber
);

typedef EFI_STATUS 
(*EFI_GRAPHICS_OUTPUT_PROTOCOL_BLT) (
    UINT32 *This,
    EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer,
    EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
    UINTN SourceX,
    UINTN SourceY,
    UINTN DestinationX,
    UINTN DestinationY,
    UINTN Width,
    UINTN Height,
    UINTN Delta
);

typedef struct {
    UINT32 MaxMode;
    UINT32 Mode;
    EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
    UINTN SizeOfInfo;
    UINT64 FrameBufferBase;
    UINTN FrameBufferSize;
} EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE;

typedef struct EFI_GRAPHICS_OUTPUT_PROTOCOL {
    EFI_GRAPHICS_OUTPUT_PROTOCOL_QUERY_MODE QueryMode;
    EFI_GRAPHICS_OUTPUT_PROTOCOL_SET_MODE SetMode;
    EFI_GRAPHICS_OUTPUT_PROTOCOL_BLT Blt;
    EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *Mode;
} EFI_GRAPHICS_OUTPUT_PROTOCOL;

typedef
EFI_STATUS
(*EFI_SET_WATCHDOG_TIMER) (
    UINTN                          Timeout,
    UINT64                         WatchdogCode,
    UINTN                          DataSize,
    CHAR16                         *WatchdogData
);

typedef
EFI_STATUS
(*EFI_LOCATE_PROTOCOL) (
    EFI_GUID                            *Protocol,
    VOID                                *Registration,
    VOID                                **Interface
);

typedef struct {
    EFI_TABLE_HEADER                 Hdr;
    UINT64                           _bufA[29]; 
    EFI_SET_WATCHDOG_TIMER           SetWatchdogTimer;
    UINT64                           _bufB[7];
    EFI_LOCATE_PROTOCOL              LocateProtocol;
    UINT64                           _bufC[5];
} EFI_BOOT_SERVICES;

typedef struct {
    EFI_TABLE_HEADER                 Hdr;
    CHAR16                           *FirmwareVendor;
    UINT32                           FirmwareRevision;
    EFI_HANDLE                       ConsoleInHandle;
    UINT32                           *ConIn;
    EFI_HANDLE                       ConsoleOutHandle;
    UINT32                           *ConOut;
    EFI_HANDLE                       StandardErrorHandle;
    UINT32                           *StdErr;
    UINT32                           *RuntimeServices;
    EFI_BOOT_SERVICES                *BootServices;
    UINTN                            NumberOfTableEntries;
    UINT32                           *ConfigurationTable;
} EFI_SYSTEM_TABLE;

EFI_STATUS EFI_Main (EFI_HANDLE ImageHandle,EFI_SYSTEM_TABLE *SystemTable)
{
    //在main函数中可以直接定义一个gop的guid数据结构
    EFI_GUID gop_guid = {
	    0x9042a9de, 
	    0x23dc, 
	    0x4a38, 
	    {0x96, 0xfb, 0x7a, 0xde, 0xd0, 0x80, 0x51, 0x6a}
    };

    //调用系统表、启动表,找GOP句柄
    EFI_GRAPHICS_OUTPUT_PROTOCOL *GOP = NULL;
    EFI_STATUS Status;

    SystemTable->BootServices->SetWatchdogTimer(0, 0, 0, NULL);
    Status = SystemTable->BootServices->LocateProtocol(
        &gop_guid,
        NULL,
        (void**)&GOP
    );

    if (Status != 0 || GOP == NULL) {
        return Status; //GOP协议不可用直接返回
    }

    //获取GOP句柄后画画
    unsigned int width  = GOP->Mode->Info->HorizontalResolution;
    unsigned int height = GOP->Mode->Info->VerticalResolution;
    unsigned long long fb_base = GOP->Mode->FrameBufferBase;
    unsigned int *fb_ptr = (unsigned int*)(unsigned long)fb_base;

    unsigned int red_pixel;
    if (GOP->Mode->Info->PixelFormat == 1) {
        red_pixel = 0x00FF0000; // RGBA格式红色
    } else {
        red_pixel = 0x000000FF; // BGRA格式红色
    }

    //填充整个区域为红色
    unsigned int total_pixels = width * height;
    for (unsigned int i = 0; i < total_pixels; i++) {
        fb_ptr[i] = red_pixel;
    }
    return 0;
}

最后补充一个lds脚本的代码

/** @file

  Unified linker script for GCC based builds

  Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>
  Copyright (c) 2015, Linaro Ltd. All rights reserved.<BR>
  (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>

  SPDX-License-Identifier: BSD-2-Clause-Patent

**/

SECTIONS {

  /*
   * The PE/COFF binary consists of DOS and PE/COFF headers, and a sequence of
   * section headers adding up to PECOFF_HEADER_SIZE bytes (which differs
   * between 32-bit and 64-bit builds). The actual start of the .text section
   * will be rounded up based on its actual alignment.
   */
  . = PECOFF_HEADER_SIZE;

  .text : ALIGN(CONSTANT(COMMONPAGESIZE)) {
    *(.text .text.* .stub .gnu.linkonce.t.*)
    *(.rodata .rodata.* .gnu.linkonce.r.*)
    *(.got .got.*)

    /*
     * The contents of AutoGen.c files are mostly constant from the POV of the
     * program, but most of it ends up in .data or .bss by default since few of
     * the variable definitions that get emitted are declared as CONST.
     * Unfortunately, we cannot pull it into the .text section entirely, since
     * patchable PCDs are also emitted here, but we can at least move all of the
     * emitted GUIDs here.
     */
    *:AutoGen.obj(.data.g*Guid)
  }

  /*
   * The alignment of the .data section should be less than or equal to the
   * alignment of the .text section. This ensures that the relative offset
   * between these sections is the same in the ELF and the PE/COFF versions of
   * this binary.
   */
  .data ALIGN(ALIGNOF(.text)) : ALIGN(CONSTANT(COMMONPAGESIZE)) {
    *(.data .data.* .gnu.linkonce.d.*)
    *(.bss .bss.*)
  }

  .eh_frame ALIGN(CONSTANT(COMMONPAGESIZE)) : {
    KEEP (*(.eh_frame))
  }

  .rela (INFO) : {
    *(.rela .rela.*)
  }

  .hii : ALIGN(CONSTANT(COMMONPAGESIZE)) {
    KEEP (*(.hii))
  }

  /*
   * Retain the GNU build id but in a non-allocatable section so GenFw
   * does not copy it into the PE/COFF image.
   */
  .build-id (INFO) : { *(.note.gnu.build-id) }

  /DISCARD/ : {
    *(.note.GNU-stack)
    *(.gnu_debuglink)
    *(.interp)
    *(.dynsym)
    *(.dynstr)
    *(.dynamic)
    *(.hash .gnu.hash)
    *(.comment)
  }
}


评论