UEFI学习笔记(4)——编译自己的库

本文记录如何在 EDK II 项目中编写并编译自己的库模块(Library Module),并在其他模块中调用这个库函数。通过实战掌握 UEFI 模块化开发的重要组成部分——库的创建与复用。

一、前言

UEFI 开发中,代码高度模块化,库模块(Library Module)是其核心机制之一。很多驱动、应用程序都依赖于多个通用库进行构建。因此,学会创建和使用自己的库是 UEFI 学习的重要一步。

二、基础知识回顾

  • EDK II 工程核心文件类型

    • .INF:模块定义文件

    • .DEC:包描述文件,声明头文件、LibraryClass 等

    • .DSC:平台配置文件,指定模块构建方式

    • .FDF:固件镜像配置文件(用于最终构建固件镜像)

  • Library Module 与普通 Module 区别

    • 普通模块可以独立运行或链接到 文件中(如 App、Driver)

    • Library Module 不可独立运行,必须被其他模块引用

  • LibraryClass 的作用

    • 每个库使用唯一的 LibraryClass 名称,供外部模块引用

    • 相当于一个命名接口,类似 C++ 虚基类的“接口名”

三、工程目录结构设计

我们假设创建一个名为 MyPkg 的包,内部包含一个名为 01MyLibrarytest的库模块:

MyPkg/
├── MyLibrary/
│   └── 01MyLibrarytest/
│       ├── 01MyLibrarytest.c       // 库函数实现
│       ├── 01MyLibrarytest.h       // 库函数头文件
│       └── 01MyLibrarytest.inf     // 库模块描述文件
├── MyApplications/
│   └── MyHelloWorld/
│       ├── MyHelloWorld.c          // 应用调用库
│       └── MyHelloWorld.inf        // 应用模块描述文件
├── MyPkg.dec                       // 包描述文件
└── MyPkg.dsc                       // 平台描述文件

四、编写自己的库模块

1. 编写 .inf 文件(01MyLibrarytest.inf)

[Defines]
  INF_VERSION                    = 0x00010006
  BASE_NAME                      = 01MyLibrarytest
  FILE_GUID                      = D8114FB9-2FDF-E1D6-D107-6FD899B8F433
  MODULE_TYPE                    = BASE
  VERSION_STRING                 = 1.0
  LIBRARY_CLASS                  = 01MyLibrarytest

[Sources]
  01MyLibrarytest.c

[Packages]
  MdePkg/MdePkg.dec

[LibraryClasses]
  UefiLib
  BaseLib

关键字段说明:

  • MODULE_TYPE = BASE 表示这是一个基础模块(通常为库)

  • LIBRARY_CLASS = 01MyLibrarytest 表示该库的接口名,外部模块使用这个名称引用它

2. 编写头文件(01MyLibrarytest.h)

#ifndef __MY_LIBRARY_TEST_H__
#define __MY_LIBRARY_TEST_H__

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

VOID EFIAPI MyLibraryTestFunction();

#endif

3. 编写实现文件(01MyLibrarytest.c)

#include "01MyLibrarytest.h"

VOID EFIAPI MyLibraryTestFunction()
{
    Print(L"Hello from MyLibraryTestFunction!\n");
}

四、配置 MyPkg.dec

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

[Includes]
  MyLibrary/01MyLibrarytest

[LibraryClasses]
  01MyLibrarytest|MyLibrary/01MyLibrarytest/01MyLibrarytest.h

说明:

  • [Includes] 让头文件能被外部模块找到(传给编译器的 -I 路径)

  • [LibraryClasses] 声明库类及其接口头文件路径

五、配置平台文件 MyPkg.dsc

[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
    01MyLibrarytest|MyPkg/MyLibrary/01MyLibrarytest/01MyLibrarytest.inf
 
[Components]
    MyPkg/MyLibrary/01MyLibrarytest/01MyLibrarytest.inf
    MyPkg/MyApplications/MyHelloWorld/MyHelloWorld.inf

六、编写调用库的应用模块

✅ 1. MyHelloWorld.c

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

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

✅ 2. MyHelloWorld.inf

[Defines]
  INF_VERSION  = 0x00010006
  BASE_NAME    = MyHelloWorld
  FILE_GUID    = 22222222-2222-2222-2222-222222222222
  MODULE_TYPE  = UEFI_APPLICATION
  ENTRY_POINT  = UefiMain

[Sources]
  MyHelloWorld.c

[Packages]
  MdePkg/MdePkg.dec
  MyPkg/MyPkg.dec   # 需要添加这一行

[LibraryClasses]
  UefiLib
  01MyLibrarytest

七、构建并测试

✅ 构建命令:

build -p MyPkg/MyPkg.dsc -m MyPkg/MyApplications/MyHelloWorld/MyHelloWorld.inf

构建成功后,生成的 MyHelloWorld.efi 可在 UEFI Shell 或 QEMU 中运行:

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值