4. 工作空间与包:Workspace 概念、Package (.dec) 定义与结构、DSC 文件与 FDF 文件基础

EDK II 的构建系统围绕 工作空间 (Workspace) 和 包 (Package) 两个核心概念组织。理解它们之间的关系以及 .dec、.dsc、.fdf 三种描述文件的作用,是进行模块开发与集成的基础。

4.1 Workspace 概念与结构

Workspace 是 EDK II 构建系统的顶层目录,它定义了所有源文件、库、平台描述文件和生成固件映像的边界。一个 Workspace 通常包含多个 Package,以及一个或多个平台描述文件。

关键点: Workspace 本身不是一个物理文件,而是一个目录结构约定。构建工具通过环境变量 WORKSPACE 或 PACKAGES_PATH 定位该目录。

4.1.1 典型 Workspace 目录布局

Workspace/
├── edk2/                    # 核心 EDK II 代码库 (一个 Package 集合)
│   ├── MdePkg/
│   ├── MdeModulePkg/
│   ├── UefiCpuPkg/
│   └── ...
├── MyPlatform/              # 自定义平台 Package
│   ├── MyPlatformPkg/
│   │   ├── MyPlatformPkg.dec
│   │   ├── MyPlatformPkg.dsc
│   │   ├── MyPlatformPkg.fdf
│   │   ├── Include/
│   │   ├── Library/
│   │   └── ...
│   └── ...
├── MyDrivers/               # 自定义驱动 Package
│   ├── MyDriverPkg/
│   │   ├── MyDriverPkg.dec
│   │   ├── MyDriverPkg.dsc
│   │   └── ...
│   └── ...
└── Build/                   # 构建输出目录 (由工具自动生成)
    └── ...

4.2 Package (.dec) 定义与结构

Package 是 EDK II 中代码组织和分发的基本单元。一个 Package 是一个逻辑上相关的模块、库、头文件和协议的集合。每个 Package 必须包含一个 .dec (Declaration) 文件,作为该 Package 的“身份证”和“目录”。

4.2.1 .dec 文件的作用

  • 声明 GUID:定义该 Package 中所有模块、协议、PPI、GUID 的全局唯一标识符。
  • 声明 PCD:定义该 Package 提供的平台配置数据库 (PCD) 条目及其默认值。
  • 声明 Include 路径:指定该 Package 对外公开的头文件目录。
  • 声明 Library Classes:列出该 Package 提供的库类 (Library Class) 名称。

4.2.2 .dec 文件结构示例

## @file
# MyDriverPkg.dec
# 声明 MyDriverPkg 的 GUID、PCD 和 Include 路径
#

[Defines]
  DEC_SPECIFICATION              = 0x0001001A
  PACKAGE_NAME                   = MyDriverPkg
  PACKAGE_GUID                   = 12345678-9ABC-DEF0-1234-56789ABCDEF0
  PACKAGE_VERSION                = 1.0

[Includes]
  Include                        # 公开头文件目录

[LibraryClasses]
  MyCustomLib|Include/Library/MyCustomLib.h

[Guids]
  gMyDriverGuid                  = { 0x11111111, 0x2222, 0x3333, { 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB } }

[PcdsFixedAtBuild]
  gMyDriverPcdTokenSpaceGuid.PcdMyDriverDebugLevel|0x00000003|UINT32|0x30000001

4.2.3 .dec 文件主要章节

章节名称 用途 示例内容
[Defines] 定义 Package 元数据 PACKAGE_NAME, PACKAGE_GUID, DEC_SPECIFICATION
[Includes] 声明公开头文件搜索路径 Include, Include/Protocol
[LibraryClasses] 声明库类及其头文件映射 MyLib|Include/Library/MyLib.h
[Guids] 声明该 Package 拥有的所有 GUID gMyProtocolGuid = { ... }
[PcdsFixedAtBuild] 声明编译时固定的 PCD gMyPkg.PcdMyValue|0x5|UINT32|0x40000001
[PcdsDynamic] 声明运行时可动态修改的 PCD gMyPkg.PcdMyDynamicValue|0x0|UINT8|0x50000001
最佳实践: 每个 Package 应只包含一个 .dec 文件。所有对外接口(GUID、PCD、Library Class)都应在此文件中声明,以实现接口与实现的分离。

4.3 DSC 文件基础

DSC (Platform Description) 文件是平台级别的描述文件,它定义了构建一个特定固件映像所需的所有模块、库实例、PCD 值和构建选项。DSC 文件是构建过程的“主控清单”。

4.3.1 DSC 文件核心章节

  • [Defines]:定义平台名称、GUID、固件版本、目标架构等。
  • [LibraryClasses]:将抽象的 Library Class 映射到具体的 Library Instance (INF 文件)。
  • [PcdsFixedAtBuild] / [PcdsDynamic]:覆盖或设置该平台下所有模块使用的 PCD 值。
  • [Components]:列出需要构建并包含进固件映像的所有模块 (INF 文件)。

4.3.2 DSC 文件片段示例

[Defines]
  PLATFORM_NAME                  = MyPlatform
  PLATFORM_GUID                  = 22222222-3333-4444-5555-666677778888
  PLATFORM_VERSION               = 0.1
  DSC_SPECIFICATION              = 0x0001001C
  SUPPORTED_ARCHITECTURES        = IA32|X64
  BUILD_TARGETS                  = DEBUG|RELEASE
  SKUID_IDENTIFIER               = DEFAULT
  FLASH_DEFINITION               = MyPlatformPkg/MyPlatformPkg.fdf

[LibraryClasses]
  # 将 UefiDriverEntryPoint 库类映射到 MdePkg 中的实例
  UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
  UefiLib|MdePkg/Library/UefiLib/UefiLib.inf

[PcdsFixedAtBuild]
  gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2F
  gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x80000000

[Components]
  # 列出要构建的模块
  MyDriverPkg/MyDriver/MyDriver.inf
  MdeModulePkg/Universal/HelloWorld/HelloWorld.inf

4.4 FDF 文件基础

FDF (Flash Description File) 文件定义了固件映像在 Flash 设备上的物理布局。它描述了哪些模块、固件卷 (FV)、固件文件系统 (FFS) 以及原始二进制数据应该被放置在 Flash 的哪个地址和区域。

4.4.1 FDF 文件核心概念

  • FD (Flash Device):代表整个 Flash 芯片。
  • FV (Firmware Volume):Flash 设备内的逻辑存储区域,包含一个或多个 FFS 文件。
  • FFS (Firmware File System):FV 内部的组织结构,用于存储模块、数据文件等。
  • INF 文件引用:在 FDF 中通过 INF 语句引用 DSC 中已声明的模块,将其打包进指定的 FV。

4.4.2 FDF 文件片段示例

[FD.MyPlatform]
  BaseAddress   = 0xFFF00000
  Size          = 0x00100000
  ErasePolarity = 1
  BlockSize     = 0x1000
  NumBlocks     = 0x100

  # 定义第一个固件卷
  0x00000000|0x00080000
  FV = PEI_FV

  # 定义第二个固件卷
  0x00080000|0x00080000
  FV = DXE_FV

[FV.PEI_FV]
  FvAlignment        = 16
  ERASE_POLARITY     = 1
  MEMORY_MAPPED      = TRUE
  STICKY_WRITE       = TRUE
  LOCK_CAP           = TRUE
  LOCK_STATUS        = TRUE
  READ_DISABLED_CAP  = FALSE
  READ_ENABLED       = TRUE
  READ_LOCK_CAP      = TRUE
  READ_LOCK_STATUS   = FALSE
  WRITE_DISABLED_CAP = FALSE
  WRITE_ENABLED      = TRUE
  WRITE_LOCK_CAP     = TRUE
  WRITE_LOCK_STATUS  = FALSE

  INF  MdeModulePkg/Core/Pei/PeiMain.inf
  INF  MdeModulePkg/Universal/PCD/Pei/Pcd.inf

[FV.DXE_FV]
  FvAlignment        = 16
  ERASE_POLARITY     = 1
  MEMORY_MAPPED      = TRUE
  STICKY_WRITE       = TRUE
  LOCK_CAP           = TRUE
  LOCK_STATUS        = TRUE
  READ_DISABLED_CAP  = FALSE
  READ_ENABLED       = TRUE
  READ_LOCK_CAP      = TRUE
  READ_LOCK_STATUS   = FALSE
  WRITE_DISABLED_CAP = FALSE
  WRITE_ENABLED      = TRUE
  WRITE_LOCK_CAP     = TRUE
  WRITE_LOCK_STATUS  = FALSE

  INF  MdeModulePkg/Core/Dxe/DxeMain.inf
  INF  MyDriverPkg/MyDriver/MyDriver.inf

4.5 三文件关系与构建流程

下图展示了 .dec、.dsc、.fdf 三者在 EDK II 构建系统中的协作关系。

EDK II 三文件协作关系图 EDK II 构建三文件协作关系 .dec (声明文件) .dsc (平台描述) .fdf (Flash布局) 提供GUID/PCD 引用模块列表 Build 工具 (build.py) 解析模块依赖 提供布局规则 固件映像 (.fd/.bin) 链接、打包、生成 说明:.dec 定义接口与数据;.dsc 选择模块与配置;.fdf 决定物理布局。三者共同决定最终固件。 Build 工具解析 .dsc 和 .fdf,结合 .dec 中的声明,完成编译、链接与打包。

4.6 三文件职责对比

文件类型 核心职责 作用域 关键内容
.dec 声明 Package 的公共接口 Package 级别 GUID、PCD 定义、Library Class 声明、Include 路径
.dsc 描述平台构建配置 平台级别 模块列表、库实例映射、PCD 赋值、构建选项
.fdf 描述 Flash 设备布局 平台级别 FD 区域划分、FV 定义、FFS 文件放置、INF 引用
常见错误: 初学者常将模块的 .inf 文件与 .dec 文件混淆。.inf 描述单个模块的构建信息,而 .dec 描述整个 Package 的公共接口。一个 Package 可以有多个 .inf,但通常只有一个 .dec。

4.7 本章小结

  • Workspace 是顶层目录,包含所有 Package 和平台文件。
  • Package 是代码组织单元,其 .dec 文件声明了所有对外接口。
  • DSC 文件 是平台构建的“主控清单”,决定构建哪些模块以及如何配置。
  • FDF 文件 是 Flash 的“施工图纸”,决定固件映像的物理布局。
  • 三者通过 GUID、PCD 和 INF 引用紧密协作,最终由 Build 工具生成固件映像。