UEFI——UEFI Package & Module

EDKII官方Spec 合集网站
EDK II Documentation · tianocore/tianocore.github.io Wiki · GitHub

前言

之前在向代码中添加自己创建的代码时,一直都是在自己创建的 LilyPackage 中创建好相应的 .h .c .inf文件,然后在 EmulatorPkg.dsc 文件中将 .inf 文件进行包含,一直没有出现问题。但是在创建新的 protocol 的时候,出现了一点问题,就是关于 include 的 TestProtocol.h
在UEFI中,创建新的 protocol 是需要在 .dec 文件中声明对应的GUID 的,我当时的做法是将GUID 在 EmulatorPkg.dsc [Protocols] 下进行声明,并且将自己定义的 .h文件放在了 EmulatorPkg\Include\Protocol 路径下。但是有人提出,在他的代码中需要将定义的 .h文件放在 MdePkg\Include\Protocol 路径下才可以得到编译结果。之前我从来没有关心过文件的路径问题,对于不同类型的文件作用也没有进行深入的研究,借着这个疑问,也终于有机会对这些问题深入的研究一下。

Module & Package 概念

刚刚学习UEFI的人,不能避免的会遇到这两个概念,EDKII的代码组织形式就是以这两个概念为基础的,但是这两个概念在代码结构中的表现却很少有人提起。
我们打开EDKII代码的根目录,就可以看到许多个.pkg结尾的文件夹,每一个都是一个package
在这里插入图片描述

继续向下 我们就可以看到更多的子文件夹 有的子文件夹就是一个模块 ,但这也并不是绝对的。我们这样可以说是语焉不详,这种模棱两可的表述肯定搞不清楚这两个UEFI中最常见的概念的定义。为了明晰这两个概念,首先先看一下Build Spec (下载链接已经放在开头了 所有的EDKII需要的SPEC基本都能从这个连接中找到 )中对这两个定义的解释:

Module :A module is either an executable image or a library instance. For a list of module types supported by this package, see module type
Module: 是一个可执行image或者一个 lib instance 。某一个package中支持的module类型可以查看module type类型

Package:A package is a container. It can hold a collection of files for any given set of modules.
Packages may be described as one of the following types of modules:

  1. source modules, containing all source files and descriptions of a module
  2. binary modules, containing EFI Sections or a Framework File System and a description file specific to linking and binary editing of features and attributes specified in a Platform Configuration Database (PCD).
  3. mixed modules, with both binary and source modules
    Multiple modules can be combined into a package, and multiple packages can be combined into a single package.

Package:Package是一个容器,他容纳了一系列给定Module的文件的集合。
Package可以被描述成为以下几种类型的Modules的之一:

  1. source modules:包含了一个模块的所有源代码文件和描述文件
  2. 二进制 modules:包含了 EFI section 或者 一个ffs,以及一个des 文件,专门用来链接和二进制编辑PCD中指定的功能和属性
  3. 混合modules :包含以上两种
    多个modules可以被包含在一个package中,多个package也可以结合成一个package

我觉得Spec里面的解释可以说是非常抽象了 幸亏 我手边有两本参考书 可以看一下书中所言:

  1. 包(package)是一组模块及平台描述文件(dsc)、包声明(dec)文件组成的集合。
    模块(可执行文件,即.efi文件)像插件一样可以动态地加载到UEFI内核中。1
  2. 模块是UEFI上最小的可单独编译的代码单元,或是预编译的二进制文件,比如.efi执行文件。
    包由模块、平台描述文件和包声明文件组成。它可以不包含模块,也可以包含多个模块。2

😓 好吧还是挺抽象的 就不能结合代码说一下吗? 
我自己的理解是(不一定准确):

模块 :UEFI中的最小的可单独编译的代码范围,一般情况下一个 .inf 文件就对应一个模块。模块的编译能够对应的产生 .efi 可执行文件或者.lab文件以实现某种功能。
包:module+.dec文件+.dsc文件(dsc文件并不是绝对的 看dec文件可能更加准确 后面详细说例外情况,但是 EDKII中是两个文件都存在的)。包是模块的组合。一般情况下,包都是用来实现一个相对完整的功能的。

用一个比较通俗的例子来说。我觉得模块就像C++代码中,能够实现某一个功能的部分文件,比如:有一些代码能够实现加法的功能。你可以单独的将这些代码进行编译实现加法的功能,也可以将这个代码与其他的代码配合实现更加完整的结构比如计算器。在UEFI中,这个完整的结构就是 package

我觉得可能这样说还不是很明白,看代码是最好的解释,但是在深入的代码分析之前,我们需要仔细的看一下用以区分module package的三种不同类型的文件

Module

.inf

.inf文件是模块的工程文件。其主要作用就是指导编译工具对模块进行编译,(这也可以和前面说的一个.inf对应一个模块相对应 编译生成的.efi文件就是能够直接运行的二进制文件。.inf文件提供了本模块的基本信息,让编译工具能够按照一定的规则进行编译,.inf 也有固定的格式,是由多个部分组成,下面以之前提过的 TestProtocolInstall.inf为例进行介绍

[Defines]

[Defines]
  INF_VERSION                = 0x00010015
  BASE_NAME                  = TestProtocolInstall
  FILE_GUID                  = 16BEFBED-60DC-4EA2-8E81-A343DF6C2117
  MODULE_TYPE                = UEFI_DRIVER        
  VERSION_STRING             = 1.0
  ENTRY_POINT                = TestProtocolInstallEntry

以上定义了若干的变量,这些变量是后续在编译的过程中需要用到的。其中前四个是必须定义的变量

变量名变量说明
INF_VERSIONINF版本号 我一般写的都是 10015
BASE_NAME编译结果文件的名称
FILE_GUID生成文件的GUID值
MODULE_TYPE模块类型的定义

以上四个变量大都是固定的值 没有可以深入讨论的价值 ,FILE_GUID我们后续讨论固件的构成的时候再深入研究,现在知道是一个标志就可以了。剩下的只有 MODULE_TYPE 这个位置比较重要,这个变量决定了Module 的类型。
前面我们说过,编译过后模块会生成 .efi 或者 .lib文件,生成什么类型的文件的关键就是在这个位置。
MODULE_TYPE 类型包括了BASE , SEC , PEI_CORE , PEIM ,DXE_CORE , SMM_CORE , DXE_DRIVER , DXE_RUNTIME_DRIVER , DXE_SMM_DRIVER , DXE_SAL_DRIVER , UEFI_DRIVER , or UEFI_APPLICATION
而我目前最常用的类型就 DXE_DRIVER UEFI_DRIVER UEFI_APPLICATION三种。这三种类型最终都是生成 .efi文件。
仍然以TestProtocol 举例,在路径 EmulatorX64\DEBUG_VS2019\X64\LilyPkg\TestProtocol\TestProtocolInstall\OUTPUT 下,我们就能够找到最终的生成结果:
在这里插入图片描述
前面我们说过,Module还可以生成 .lab类型的文件,在此也举一例:
观察 MdePkg\Library\BaseCacheMaintenanceLib\BaseCacheMaintenanceLib.inf 其部分内容如下:

[Defines]
  INF_VERSION                    = 0x00010005
  BASE_NAME                      = BaseCacheMaintenanceLib
  MODULE_UNI_FILE                = BaseCacheMaintenanceLib.uni
  FILE_GUID                      = 123dd843-57c9-4158-8418-ce68b3944ce7
  MODULE_TYPE                    = BASE
  VERSION_STRING                 = 1.1
  LIBRARY_CLASS                  = CacheMaintenanceLib

可以看到其MODULE_TYPE 并未上述我们说的常见的三个类型之一 我们在 Build\EmulatorX64\DEBUG_VS2019\X64\MdePkg\Library\BaseCacheMaintenanceLib\BaseCacheMaintenanceLib\OUTPUT 路径下,就可以发现最终生成的 .lab类型的文件,如下图所示:
在这里插入图片描述

[Source]

此处列出了当前模块需要用到的全部文件,文件位于inf文件所处的路径或者子路径下,此处需要使用相对路径来表示。
我们只用了一个文件 所以当前这个位置只包含了一个文件名

[Sources]
  TestProtocolInstall.c

[Packages]

此处列出当前模块用到的其他包dec文件 。(前面说过dec文件是package的标志文件,可以理解为对包进行了形容 以便其他包对此包中的内容进行调用)
此时使用的是文件的相对路径,并且被包含文件是有顺序要求的

此处一定要包含的一个dec文件就是 MdePkg/MdePkg.dec ,并且必须放在第一位

[Packages]
	MdePkg/MdePkg.dec
#	MdeModulePkg/MdeModulePkg.dec
	EmulatorPkg/EmulatorPkg.dec

上面一个部分 MdePkg/MdePkg.dec 是一定要包含的 并且在第一位
我们将 .h 文件放在了 EmulatorPkg 文件夹路径下 并且protocol GUID 的声明放在了 EmulatorPkg/EmulatorPkg.dec ,所以也要包含EmulatorPkg/EmulatorPkg.dec。这样就能保证当前模块能够顺利的编译通过

[LibraryClasses]

当前模块需要用到的库文件。我们在此处添加的库文件一定是在 当前package的dsc文件下[LibraryClasses]下包含的 ,否则就需要包含library对应的.inf文件同时进行编译

[LibraryClasses]
	UefiDriverEntryPoint
	UefiBootServicesTableLib
	MemoryAllocationLib
	DebugLib

我们此处添加的 LibraryClasses 都可以在 EmulatorPkg/EmulatorPkg.dsc 的 [LibraryClasses] 中找到


从这里我们就能发现 虽然当前我是将自己定义的模块都保存在了另外新建的文件夹中,但是我没有在当前的文件夹下创建自己的dec dsc 文件,所以当前我新创建的文件夹并不能算作一个package 只能是一个module的集合。实际上这个module在结构上还是属于 EmulatorPkg的。(因为我将自己定义的 .h 文件 存放在了 EmulatorPkg 的include 下 并且在EmulatorPkg.dec 中添加了ProtocolGUID 的定义) 后续的分析中 谨记当前的文件夹属于 EmulatorPkg.dec EmulatorPkg.des 定义的 EmulatorPkg package


[Protocols]

这是一个选择性的部分,如果当前的模块没有使用任何的protocol 则不需要此部分,比如最开始的 HelloWorld 中就没有使用此模块。这个位置中添加的protocol声明,也必须在对应的 .dec文件下已经存在对此protocol的声明了。

[Protocols] 
   gEfiHelloWorldProtocolGuid

上述protocol ,就能够在 EmulatorPkg.dec 中找到 (再次验证了当前的文件本质上还是属于EmulatorPkg)

[Depex]

这是选择性添加的部分,一般是用来定义驱动的执行顺序(此处不详细说 研究好驱动再说这个问题)

[Depex]
	TRUE

上述模块设置为 TRUE表示当前模块不需要依赖任何模块 轮询到直接执行即可

上述几个部分就是当前我能够使用的一个 .inf 文件常见的主要部分 ,前面说过模块是最小的编译单元,也就是能够独立的编译某一个模块不影响其他的部分。为了验证这个独立的模块能够生成单独的可执行文件 ,利用如下命令进行验证

build -m LilyPkg\TestProtocol\TestProtocolInstall.inf

上述命令就是单独编译之前定义好的 TestProtocolInstall 模块


注:我已经在EmulatorPkg.dsc中添加过 TestProtocol\TestProtocolInstall.inf 如果没有添加或者在别的dsc中添加的这个模块 需要将 dsc 文件位置也在cmd指定
例如我如果在 OvmfPkg.dsc中指定 那我的命令行就应该是:

build -p OvmfPkg\OvmfPkgX64.dsc -m LilyPkg\TestProtocol\TestProtocolInstall.inf
在这里插入图片描述


编译生成的结果我们可以在 Build\EmulatorX64\DEBUG_VS2019\X64 路径下查询 可见此时在路径下生成了单独的可执行文件
在这里插入图片描述

此处我还想说 ,UEFI 叫做 统一可扩展固件接口 ,当前我觉得 这种module的形式就是可扩展的核心。任何人编译出符合当前标准的 Module 都可以被UEFI 系统识别并且执行,这样就给了开发商们足够的自由度能够以自己的方式实现驱动并且成功交给UEFI 进行执行,同时这种功能的分散又很好的缓解了之前BIOS难以维护的问题,UEFI只需要维护好当前的这种结构和接口,其他的就交给OEM厂商尽情发挥。
前面我觉得我已经将Module 说的很清楚了 ,而且也用例子进行证明当前我自己定义的模块的情况。下面就该介绍package的情况

Package

前面已经说过,在EDKII中,一个package的标志性文件有两个,分别是.dec .dsc,刚刚开始学习的时候总是分不清这两个文件,也搞不清楚这两个文件的区别和作用,现在终于可以说自己略知一二了

dec

.dec文件对应的英文为 package Declaration File, 翻译过来就是 包声明文件。
这个文件会对当前package 进行一个描述 ,包括当前package的名称 外部package可以使用的library GUID protocol 等 。
个人觉得.dec主要就是承担了 一个对外沟通的作用:只有在dec中声明的东西才有可能被其他的package调用。 比较官方的说法就是: .dec文件定义了包的公共数据和接口,供其他模块使用。1

此处以EmulatorPkg.dec 为例说明 dec的组成部分

[Defines]
[Defines]
  DEC_SPECIFICATION              = 0x00010005
  PACKAGE_NAME                   = EmulatorPkg
  PACKAGE_GUID                   = 36E48BD7-7D92-5A47-A2CD-513F072E3300
  PACKAGE_VERSION                = 0.1

以上四个变量是dec文件都要有的,分别对package的属性属性进行了定义。其中PACKAGE_GUID后续讨论固件结构的时候可详细讨论。

[Includes]

此处列出了当前包中头文件所在的目录。使用相对路径

[Includes]
  Include

前面在进行自定义protocol的时候,就是将自己定义的 .h文件放在了EmulatorPkg\Include\Protocol 的路径下,自然就被包含在此范围内

[LibraryClasses]

前面说过 ,外部package可以使用当前package的library。那些可以被外部使用的lab 与 所对应的头文件对应关系就是在这被声明的。在EDKII中,所有的lab头文件都被包含在 Include \Library 之下

[LibraryClasses]
  ThunkPpiList|Include/Library/ThunkPpiList.h
  ThunkProtocolList|Include/Library/ThunkProtocolList.h
  EmuThunkLib|Include/Library/EmuThunkLib.h
  KeyMap|Include/Library/KeyMapLib.h
  PpiListLib|Include/Library/PpiListLib.h
  SmbiosLib|Include/Library/SmbiosLib.h
  EmuMagicPageLib|Include/Library/EmuMagicPageLib.h

Library的定义是有相应的语法格式的

LibraryName | Path/Header.h

[Protocols]

在 Include \Protocol 路径下 定义了很多的protocol, 这些protocol 对应的GUID值就是在这个位置进行声明的 之前我自己添加的protocol 就是在这个位置将GUID值进行定义的

[Protocols]
  gEmuThunkProtocolGuid          = { 0x5CF32E0B, 0x8EDF, 0x2E44, { 0x9C, 0xDA, 0x93, 0x20, 0x5E, 0x99, 0xEC, 0x1C } }
  gEmuIoThunkProtocolGuid        = { 0x453368F6, 0x7C85, 0x434A, { 0xA9, 0x8A, 0x72, 0xD1, 0xB7, 0xFF, 0xA9, 0x26 } }
  gEmuGraphicsWindowProtocolGuid = { 0x30FD316A, 0x6728, 0x2E41, { 0xA6, 0x90, 0x0D, 0x13, 0x33, 0xD8, 0xCA, 0xC1 } }
  gEmuThreadThunkProtocolGuid    = { 0x3B1E4B7C, 0x09D8, 0x944F, { 0xA4, 0x08, 0x13, 0x09, 0xEB, 0x8B, 0x44, 0x27 } }
  gEmuBlockIoProtocolGuid        = { 0x6888A4AE, 0xAFCE, 0xE84B, { 0x91, 0x02, 0xF7, 0xB9, 0xDA, 0xE6, 0xA0, 0x30 } }
  gEmuSnpProtocolGuid            = { 0xFD5FBE54, 0x8C35, 0xB345, { 0x8A, 0x0F, 0x7A, 0xC8, 0xA5, 0xFD, 0x05, 0x21 } }
###
###  Lily Start
###
	  
##  Include/Protocol/TestProtocol.h
		gEfiHelloWorldProtocolGuid =   {0x039d1af8, 0x1c8d, 0x408f, { 0x59, 0x25, 0x30, 0x4f, 0x5b, 0x96, 0x5d, 0x6e }}
###
###  Lily  End
###

需要注意的是,这个位置声明的protocol 还可以是在其他package进行定义的protocol 这样就能够在当前package进行使用了 (important!!!)

[Ppis]

这个位置和上一节类似 都是对相应的GUID进行声明 只不过这是对PPI对应的GUID 进行声明
(这个部分可能需要等启动流程详细说 在此简单带过)

[Guids]

这个位置定义的是GUID常量 这些GUID常量表示了不同的固件层级与位置 在固件生成的时候起到了关键作用 以后有机会详细说 (固件结构 又一个坑 …)

[Guids]
  gEmulatorPkgTokenSpaceGuid  = { 0x4F792E68, 0xE8C8, 0x794E, { 0xB1, 0xD8, 0x37, 0x03, 0xF3, 0xF2, 0xD5, 0xA5 } }
  gEmuSystemConfigGuid       = { 0xF8626165, 0x6CEB, 0x924A, { 0xBA, 0xFC, 0xF1, 0x3A, 0xB9, 0xD6, 0x57, 0x28 } }
  gEmuVirtualDisksGuid       = { 0xf2ba331a, 0x8985, 0x11db, { 0xa4, 0x06, 0x00, 0x40, 0xd0, 0x2b, 0x18, 0x35 } }
  gEmuPhysicalDisksGuid      = { 0xf2bdcc96, 0x8985, 0x11db, { 0x87, 0x19, 0x00, 0x40, 0xd0, 0x2b, 0x18, 0x35 } }
  gEmuRedfishServiceGuid     = { 0x3fb208ac, 0x2185, 0x498c, { 0xbf, 0x46, 0xdc, 0x23, 0xda, 0x58, 0x7b, 0x55 } }
[PCD]

目前我对PCD模块一无所有 故不敢妄言 暂时略过 后续学习了再补上 还是那句话 新人总不可能什么都知道

一个.dec 文件的大致结构就介绍完成了 下面介绍 .dsc文件

dsc

.dsc 的英文全称为 Platform Description File,翻译过来就是平台描述文件。这个平台我个人觉得可以理解为前面说的 能够实现一个完整功能的结构。
最开始的就说过 package 的主要标志就是两个类型的文件 :.dec .dsc 。前面介绍的.dsc文件是包对外沟通的接口,UEFI文件类型但是一套代码 仅仅提供接口是完全不够的,还需要有人指导编译,在module中,这个角色由.inf来扮演,在package中 这个角色就由.dsc来扮演了。
总结一句话 : .dsc 是指导整个包进行编译的文件
下面 以 EmulatorPkg.dsc 对文件的结构进行介绍

[Defines]

defines下声明的变量是可以被 .dsc文件中的其他位置引用的。

[Defines]
  PLATFORM_NAME                  = EmulatorPkg
  PLATFORM_GUID                  = 05FD064D-1073-E844-936C-A0E16317107D
  PLATFORM_VERSION               = 0.3
  DSC_SPECIFICATION              = 0x00010005
  OUTPUT_DIRECTORY               = Build/Emulator$(ARCH)

  SUPPORTED_ARCHITECTURES        = X64|IA32
  BUILD_TARGETS                  = DEBUG|RELEASE|NOOPT
  SKUID_IDENTIFIER               = DEFAULT
  FLASH_DEFINITION               = EmulatorPkg/EmulatorPkg.fdf

这个位置只有一个地方需要注意 FLASH_DEFINITION 这个位置指明了想要生成固件,其布局是按照何种方式进行分布的。EmulatorPkg.fdf就是描述固件结构的文件。如果不需要生成固件 这个变量可以没有 。
不同的platform下 .fdf也是不同的 ,如果感兴趣可以去分别编译一下 OvmfPkgX64.dsc 和 EmulatorPkg.dsc观察一下不同(详细的我还没有研究明白 可能需要等后面)

[LibraryClasses]

此处定义了供模块使用的库的名称以及对应文件的路径,这些库可以被下面[Components]的模块使用

  PeiCoreEntryPoint|MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.inf
  PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
  DxeCoreEntryPoint|MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf
  UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
  UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf

此处的语法与前述 .dec 的 [LibraryClasses] 语法相同就不再说了

[Components]

此处声明的都是本package下需要编译的模块。前面我就是将自己定义的 .inf 在此进行了声明,然后编译就可以得到想要的二进制文件。

[Components]
 	LilyPkg/TestProtocol/TestProtocolUse.inf
	LilyPkg/TestProtocol/TestProtocolInstall.in

想要某一个模块能够编译 ,必须在其包的dsc文件的这个位置进行声明才能让对应模块生成编译结果

.dsc 文件常见的部分都已经说完,最后我们说一下根据 .dsc进行的编译。
我们最常使用的编译形式是如下两行命令:

edksetup.bat rebuild
build

此时我们实际上编译的包,是我们在 Conf\target.txt下定义的
在这里插入图片描述

如果我们在此将 ACTIVE_PLATFORM所定义的路径进行更换,变成OvmfPkg/OvmfPkgx64.dsc ,然后再次执行上述命令就会发现在build的 路径下生成了 与 OvmfPkg对应的文件。
此时如果在 OvmfPkg.dec 的 [Protocols]中添加

gEfiHelloWorldProtocolGuid = {0x039d1af8, 0x1c8d, 0x408f, { 0x59, 0x25, 0x30, 0x4f, 0x5b, 0x96, 0x5d, 0x6e }}

在 EmulatorPkg.dsc 中 [Components] 下声明

LilyPkg/TestProtocol/TestProtocolUse.inf
LilyPkg/TestProtocol/TestProtocolInstall.inf

(不需要更改前述的 TestProtocol.h的位置 仍放在 EmulatorPkg\Include\Protocol 即可 前面我们说过这个问题 我们能够直接通过 TestProtocol )
这时候再次进行编译就能在 生成文件的路径下找到自己添加的 TestProtocolInstall.efi 文件了。
这也证明了前述的说明,.dec 的 [Protocols]下 是可以声明其他文件下的protocol的,这样就能 使用其他package中声明的protocol 了

针对前言问题

在一开始说过有人可能需要将 .h文件放到不同的路径下进行编译才能通过,我觉得最有可能的情况就是在 自己写的 .inf 文件中, [Packages] 下并没有包含EmulatorPkg.dec 而是只包括了 MdePkg.dec ,这样就导致将 .h文件放在 EmulatorPkg 路径下的 include 不能生效了。我也做了相应的实验 结果也是和我的猜想一致。

创建 package

前面反复强调过 当前自己创建的并非一个 package 而是一个单纯的 module 集合,有了之前的学习 现在想要自己创建一个package 非常简单
如前所述 ,EDKII中的package 一定是要有 .dec.dsc文件的 于是我就在当前的文件夹下创建了这两个文件夹
dec文件内容如下

##
#
# Copyright :  Lily
# Date:2022/12/1   
# Lily.dec
##

[Defines]
  DEC_SPECIFICATION              = 0x00010005
  PACKAGE_NAME                   = LilyPkg
  PACKAGE_GUID                   = E6E40BD7-7D92-5A47-A2F1-513F07003300
  PACKAGE_VERSION                = 0.1

[Includes]
  Include

[LibraryClasses]

[Protocols]
##  Include/Protocol/TestProtocol.h
		gEfiHelloWorldProtocolGuid =   {0x039d1af8, 0x1c8d, 0x408f, { 0x59, 0x25, 0x30, 0x4f, 0x5b, 0x96, 0x5d, 0x6e }}

当前只将必要的内容进行了填充,其中 protocol 部分就是我们自己定义的 。上述内容中Include模块下包含了一个路径 ,所以在当前文件夹下,我还创建了一个名为 Include的文件夹。

前面说过,创建的protocol的头文件就是需要放在 package的 Include路径下的
所以我将之前定义好的 TestProtocol.h移到了创建的 Include文件夹中。此时 .dec所需内容已经全部准备完成。
下面来看 .dsc文件 前面介绍 .dsc文件的时候,我们着重就介绍了三个部分 我们自己的文件也就只需要这三个部分

##
#
# Copyright :  Lily
# Date:2022/12/1   
# Lily.dsc
##

[Defines]
  PLATFORM_NAME                  = LilyPkg
  PLATFORM_GUID                  = 05FD984D-1073-E83D-936C-A0E16317107D
  PLATFORM_VERSION               = 0.3
  DSC_SPECIFICATION              = 0x00010005
  OUTPUT_DIRECTORY               = Build/Lily$(ARCH)
  SUPPORTED_ARCHITECTURES        = X64|IA32
  BUILD_TARGETS                  = DEBUG|RELEASE|NOOPT
  SKUID_IDENTIFIER               = DEFAULT

!include MdePkg/MdeLibs.dsc.inc

[LibraryClasses]
  #
  # Entry point
  #
  PeiCoreEntryPoint|MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.inf
  PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
  DxeCoreEntryPoint|MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf
  UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
  UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf
  #
  # Basic
  #
  BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
  SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
  PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
  CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf
  PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
  PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
  BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
  FrameBufferBltLib|MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf

  #
  # UEFI & PI
  #
  UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
  UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
  UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf
  UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
  UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf
  HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf
  DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
  UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf

  PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf
  DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
  DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf
  SmbiosLib|EmulatorPkg/Library/SmbiosLib/SmbiosLib.inf

  #
  # Generic Modules
  #
  UefiScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf
  OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
  BootLogoLib|MdeModulePkg/Library/BootLogoLib/BootLogoLib.inf
  FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf
  UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf
  BmpSupportLib|MdeModulePkg/Library/BaseBmpSupportLib/BaseBmpSupportLib.inf
  SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
  CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf
  SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf
  TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf
  SerialPortLib|MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.inf
  CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
  #
  # Platform
  #
  PlatformBootManagerLib|EmulatorPkg/Library/PlatformBmLib/PlatformBmLib.inf
  KeyMapLib|EmulatorPkg/Library/KeyMapLibNull/KeyMapLibNull.inf
  !if $(REDFISH_ENABLE) == TRUE
    RedfishPlatformHostInterfaceLib|EmulatorPkg/Library/RedfishPlatformHostInterfaceLib/RedfishPlatformHostInterfaceLib.inf
    RedfishPlatformCredentialLib|EmulatorPkg/Library/RedfishPlatformCredentialLib/RedfishPlatformCredentialLib.inf
  !endif
  #
  # Misc
  #
  DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
  PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
  DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf
  PeiServicesTablePointerLib|EmulatorPkg/Library/PeiServicesTablePointerLibMagicPage/PeiServicesTablePointerLibMagicPage.inf
  DebugLib|MdeModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.inf
  LockBoxLib|MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf
  CpuExceptionHandlerLib|MdeModulePkg/Library/CpuExceptionHandlerLibNull/CpuExceptionHandlerLibNull.inf
  TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf
  VarCheckLib|MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf
  VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf
  VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf
  VariableFlashInfoLib|MdeModulePkg/Library/BaseVariableFlashInfoLib/BaseVariableFlashInfoLib.inf
  SortLib|MdeModulePkg/Library/BaseSortLib/BaseSortLib.inf
  ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf
  FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf

!if $(SECURE_BOOT_ENABLE) == TRUE
  RngLib|MdePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.inf
  IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf
  OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf
  PlatformSecureLib|SecurityPkg/Library/PlatformSecureLibNull/PlatformSecureLibNull.inf
  AuthVariableLib|SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf
  SecureBootVariableLib|SecurityPkg/Library/SecureBootVariableLib/SecureBootVariableLib.inf
  SecureBootVariableProvisionLib|SecurityPkg/Library/SecureBootVariableProvisionLib/SecureBootVariableProvisionLib.inf
!else
  AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf
!endif

[LibraryClasses.common.SEC]
  PeiServicesLib|EmulatorPkg/Library/SecPeiServicesLib/SecPeiServicesLib.inf
  PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
  PeCoffGetEntryPointLib|EmulatorPkg/Library/PeiEmuPeCoffGetEntryPointLib/PeiEmuPeCoffGetEntryPointLib.inf
  PeCoffExtraActionLib|EmulatorPkg/Library/PeiEmuPeCoffExtraActionLib/PeiEmuPeCoffExtraActionLib.inf
  SerialPortLib|EmulatorPkg/Library/PeiEmuSerialPortLib/PeiEmuSerialPortLib.inf
  PpiListLib|EmulatorPkg/Library/SecPpiListLib/SecPpiListLib.inf
  DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
  TimerLib|EmulatorPkg/Library/PeiTimerLib/PeiTimerLib.inf

[LibraryClasses.common.USER_DEFINED, LibraryClasses.common.BASE]
  DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
  PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
  MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
  PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
  PpiListLib|EmulatorPkg/Library/SecPpiListLib/SecPpiListLib.inf
  ThunkPpiList|EmulatorPkg/Library/ThunkPpiList/ThunkPpiList.inf
  ThunkProtocolList|EmulatorPkg/Library/ThunkProtocolList/ThunkProtocolList.inf
  PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
  PpiListLib|EmulatorPkg/Library/SecPpiListLib/SecPpiListLib.inf
  PeiServicesLib|EmulatorPkg/Library/SecPeiServicesLib/SecPeiServicesLib.inf


[LibraryClasses.common.PEIM, LibraryClasses.common.PEI_CORE]
  HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
  MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
  ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf
  PeCoffGetEntryPointLib|EmulatorPkg/Library/PeiEmuPeCoffGetEntryPointLib/PeiEmuPeCoffGetEntryPointLib.inf
  PeCoffExtraActionLib|EmulatorPkg/Library/PeiEmuPeCoffExtraActionLib/PeiEmuPeCoffExtraActionLib.inf
  ExtractGuidedSectionLib|MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf
  SerialPortLib|EmulatorPkg/Library/PeiEmuSerialPortLib/PeiEmuSerialPortLib.inf
  ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf
  TimerLib|EmulatorPkg/Library/PeiTimerLib/PeiTimerLib.inf

[LibraryClasses.common.PEI_CORE]
  PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf

[LibraryClasses.common.PEIM]
  PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf

[LibraryClasses.common.DXE_CORE]
  HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf
  MemoryAllocationLib|MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.inf
  ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
  PeCoffExtraActionLib|EmulatorPkg/Library/DxeEmuPeCoffExtraActionLib/DxeEmuPeCoffExtraActionLib.inf
  ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf
  PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
  TimerLib|EmulatorPkg/Library/DxeCoreTimerLib/DxeCoreTimerLib.inf
  EmuThunkLib|EmulatorPkg/Library/DxeEmuLib/DxeEmuLib.inf

[LibraryClasses.common.DXE_DRIVER, LibraryClasses.common.UEFI_DRIVER, LibraryClasses.common.UEFI_APPLICATION]
!if $(SECURE_BOOT_ENABLE) == TRUE
  BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
!endif

[LibraryClasses.common.DXE_RUNTIME_DRIVER]
!if $(SECURE_BOOT_ENABLE) == TRUE
  BaseCryptLib|CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf
!endif

[LibraryClasses.common.DXE_RUNTIME_DRIVER, LibraryClasses.common.UEFI_DRIVER, LibraryClasses.common.DXE_DRIVER, LibraryClasses.common.UEFI_APPLICATION]
  HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
  PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
  MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
  ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
  EmuThunkLib|EmulatorPkg/Library/DxeEmuLib/DxeEmuLib.inf
  PeCoffExtraActionLib|EmulatorPkg/Library/DxeEmuPeCoffExtraActionLib/DxeEmuPeCoffExtraActionLib.inf
  ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
  TimerLib|EmulatorPkg/Library/DxeTimerLib/DxeTimerLib.inf


[Components]
 LilyPkg/TestProtocol/TestProtocolUse.inf
 LilyPkg/TestProtocol/TestProtocolInstall.inf

当前的 [Components]部分就是将自己定义的 .inf文件 填写在此。 [Defines] 仅修改自己需要的位置即可。 [LibraryClasses] 我懒得自己去鉴别当前需要的库文件都有什么 所以将 EmulatorPkg.dsc 中的这个部分通通复制过来的,有兴趣的自己挑一下哪部分有用
当前一个package所需的文件夹已经全部完成 ,在根目录下执行下面的命令 即可以得到编译的结果

edksetup.bat rebuild
build -p LilyPkg\Lily.dsc (此处的文件夹是我的文件夹的名字 可替换成任意自己定义的文件夹)

build路径下就可以得到编译的结果
在这里插入图片描述
在这里插入图片描述

成功!!!
由此可见 我现在已经成功获得了一个package

其他package

当前我自己实验使用的都是EDKII的代码,这套代码下,package都是由 模块 .dec .dsc组成的。但是这并不是绝对的,可能有的代码中,package中并没有包含 .dsc 文件 ,其文件的编译是由某公司自己开发的编译器进行编译的。使用编译器打开的文件其本质与 .dsc文件相同 是由众多的 另种 文件组成的。 但是其本质和EDKII是相同的 只不过是将编译器图形化并且使用了另一个格式的逻辑声明文件而已。
此部分旨在说明 当前包的概念仅在EDKII的代码中成立 在其他代码中 可采用同种思想思考即可


  1. UEFI原理与编程 by 戴正华 ↩︎ ↩︎

  2. UEFI编程实践 by罗冰 ↩︎

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值