UEFI学习笔记(3)——编译自己的包和HelloWorld程序

在 EDK2(UEFI 开发环境) 中,编译自己的包(Package)和 HelloWorld 程序主要是为了 学习 UEFI 开发流程 和 避免污染 EDK2 主代码库。

EDK2 是一个复杂的 UEFI 开发框架,直接修改核心代码(如 MdeModulePkg 或 OvmfPkg)可能会引入错误,影响整个编译环境。
通过创建自己的包(如 MyPkg)和 HelloWorld 程序,可以:

  • 理解 UEFI 模块的编译过程.inf.dec.dsc.fdf 文件的作用)。
  • 掌握 UEFI 应用程序、驱动程序的开发方式EFI_APPLICATIONUEFI_DRIVER)。
  • 熟悉 UEFI Shell 下的调试方法(如 loadunloaddmpstore 等命令)。

EDK2 的核心包(如 MdePkgMdeModulePkgOvmfPkg)是 UEFI 固件的基础,随意修改可能导致:

  • 编译失败(依赖关系复杂,容易破坏其他模块)。
  • 难以升级 EDK2(如果修改了官方代码,更新 EDK2 时可能冲突)。
  • 难以维护(调试问题时难以区分是官方代码的问题还是自己的改动导致的)。

因此需要编译自己的Package包。

文章参考:UEFI学习(二)-- 搭建属于自己的Package和Library_orin uefi学习-CSDN博客

1. 创建自定义包的目录结构

MyPkg/
├── MyApplications
│   └── MyHelloWorld
│       ├── MyHelloWorld.c
│       └── MyHelloWorld.inf
├── MyDrivers
│   └── MyDriver
├── MyPkg.dec
└── MyPkg.dsc

1.1 文件描述

文件 描述
Applications放置不同的应用程序
Drivers放置不同的驱动测序

MyPkg.dec

定义包的依赖和接口(类似头文件集合)
MyPkg.dsc指定编译哪些模块和库依赖。

2. 编写自己的HelloWorld程序

为了方便Build,可以使用vscode 的task功能,对应的task.json代码为这个,为了方便联想,还可以添加c_cpp_properties.json,这个自动生成就好。

{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "Build EDK2",
      "type": "shell",
      "command": "bash",
      "args": [
        "-c",
        "source ../myexport.sh && build -a X64 -p MyPkg/MyPkg.dsc"
      ],
      "group": {
        "kind": "build",
        "isDefault": true
      },
      "presentation": {
        "echo": true,
        "reveal": "always",
        "focus": false,
        "panel": "dedicated"
      },
      "problemMatcher": []
    }
  ]
}

 2.1 MyHelloWorld.c

#include <Uefi.h>
#include <Library/UefiLib.h>

EFI_STATUS
EFIAPI UefiMain(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE *SystemTable)
{
    Print(L"Hello,This is my first UEFI Application\n");
    return EFI_SUCCESS;
}

在UEFI中,函数的返回值都是返回状态,对应的返回值都是通过指针形参进行返回,使用INOUT,尽量不要使用中文的标点符号,不然在 qemu 终端里面显示不出来。

2.2 MyHelloWorld.inf

对应的GUID可以在线生成。

[Defines]
    INF_VERSION = 0x00010006                            # INF 文件格式版本 (EDK2 v1.6)
    BASE_NAME = MyHelloWorld                            # 输出文件名 (生成 MyHelloWorld.efi)
    FILE_GUID = 92C5A2F5-7CFC-1C83-EADA-0F9A5BBB8AE7    # 模块唯一标识符 (必须全局唯一)
    MODULE_TYPE = UEFI_APPLICATION                      # 模块类型 (UEFI应用程序)
    VERSION_STRING = 1.0                                # 模块版本号
    ENTRY_POINT = UefiMain                              # 程序入口函数名

[Sources]
    MyHelloWorld.c                 # 源代码文件列表

[Packages]
    MdePkg/MdePkg.dec              # 依赖的包声明文件

[LibraryClasses]
    UefiApplicationEntryPoint      # 应用入口点库
    UefiLib                        # UEFI基础功能库

2.3 MyPkg.dec 

[Defines]
    DEC_SPECIFICATION   = 0x00010005
    PACKAGE_NAME        = MyPkg
    PACKAGE_GUID        = 263EC29A-EAB4-4504-FFFD-970978EA3246
    PACKAGE_VERSION     =0.01

2.4 MyPkg.dsc

在LibraryClasses添加库的时候,会出现 error 4000: Instance of library class [PrintLib] is not found for module,这样的错误,可以直接在vscode下按住ctrl+p然后搜索PrintLib.inf这样的文件,然后可以进行快速查找,如果是其他的库文件也是类似的查找办法,这样感觉edk2有点坑。

[Defines]
    PLATFORM_NAME           = MyPkg
    PLATFORM_GUID           = 0D4E362C-6CBC-F881-7625-84B95963D6C8
    PLATFORM_VERSION        = 0.1
    DSC_SPECIFICATION       = 0X00010005
    OUTPUT_DIRECTORY        = Build/MyPkg
    SUPPORTED_ARCHITECTURES = X64
    BUILD_TARGETS           = DEBUG|RELEASE
    SKUID_IDENTIFIER        = DEFAULT

    #
    #  Debug output control
    #
    DEFINE DEBUG_ENABLE_OUTPUT      = FALSE       # Set to TRUE to enable debug output
    DEFINE DEBUG_PRINT_ERROR_LEVEL  = 0x80000040  # Flags to control amount of debug output
    DEFINE DEBUG_PROPERTY_MASK      = 0

[LibraryClasses]
    UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf
    UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
    PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
    PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
    MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
    DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
    BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
    BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
    UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
    DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
    UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
    RegisterFilterLib|MdePkg/Library/RegisterFilterLibNull/RegisterFilterLibNull.inf
    StackCheckLib|MdePkg/Library/StackCheckLib/StackCheckLib.inf
    StackCheckFailureHookLib|MdePkg/Library/StackCheckFailureHookLibNull/StackCheckFailureHookLibNull.inf

[Components]
    MyPkg/MyApplications/MyHelloWorld/MyHelloWorld.inf

3. 编译自己的包

因为已经添加了task.json文件,可以直接按住ctrl+shift+B进行自动化任务编译,如果想要编译其他的包,可以更改task.json里面的"source ../myexport.sh && build -a X64 -p MyPkg/MyPkg.dsc"这一行代码,然后把-p MyPkg/MyPkg.dsc改为对应的路径就好。

编译成功就会出现Done关键字,然后就可以放到QEMU虚拟机里面进行运行。类似于上一章,可以把Build/MyPkg/DEBUG_GCC5/X64/MyHelloWorld.efi拷贝到ESP目录下,运行.bat文件,结果如图所示:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值