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)
}
}