UEFI原理与编程第二章学习- .dsc .dec .fdf文件与包

.dsc .dec .fdf文件及包

   上一篇介绍了 .inf文件, .inf文件相当于Visual Studio中的工程文件。而 .dsc(Platform Description File)则相当于Visual Studio中的 solution 文件。每个包都要包含一个.dec(Package Declaration File)文件、一个 .dsc文件。如果这个包还用于固件Iamge或Option Rom Image的生成,则还需要添加 .fdf(Flash Description File)文件, .fdf文件还用于启动Image。

   build命令用于编译包,编译时需要一个 .dsc文件以及一个或多个 .inf文件。

   GenFW命令用于制作固件或Option Rom Image,它需要一个 .dec文件和一个 .fdf文件。

   EDK2文件及EDK2工具链命令之间的关系如下:

UEFI原理与编程第二章学习- .dsc .dec .fdf文件与包_第1张图片

   接下来了解一下常用的两种文件: .dsc与 .dec文件。

  • 1、 .dsc文件

    .inf用于编译一个模块,而 .dsc文件用于编译一个Package,它包含了[Defines]、[LibraryClasses]、[Components]几个必须部分以及[PCD]、[BuildOptions]等几个可选部分。

    1. [Defines]块

      [Defines]用于设置build相关的全局宏变量,这些变量可以被 .dsc文件的其他模块引用。[Defines]块必须时 .dsc文件的第一个部分,格式如下:

      [Defines]
      	宏变量名 = 值
      	EDFINE 宏变量名 = 值
      	EDK_GLOBAL 宏变量名 = 值
      	
      

      [Defines]块中通过DEFINE和EDK_GLOBAL定义的宏可以在 .dsc文件和 .fdf文件中通过$(宏变量名)使用。

      .dsc文件中[Defines]块必须定义的宏变量。

      宏变量名 值类型 说明
      DSC_SPECIFICATION 数值 DSC Spec 1.22对应的值为0x00010006.目前的常用值为0x00010005.DSC必须保证向后兼容
      PLATFORM_GUID GUID 平台GUID,每个.dsc文件必须有一个唯一的GUID
      PLATFORM_VERSION 数值 .dsc文件变化时,增加此数值
      PLATFORM_NAME 标识符 标识符字符串中只能包含英文字符数字、横线、下划线
      SKUID_IDENTIFIER 标识符 该宏可以通过命令行在build时传入。可以为Default或[SkuIds]中的一个
      SUPPORTED_ARCHITECTUPES 列表 通过“|”分隔的列表,表示该 .dsc所支持平台的体系结构。例如支持IA32和X64:IA32|X64
      BUILD_TARGETS 列表 通过“|”分隔的列表,表示该 .dsc所支持的编译目标,例如BUILD或BUILD|RELEASE。

      .dsc文件 [Defines]块的可选宏变量

      宏变量名 值类型 说明
      OUTPUT_DIRECTORY 路径 目标文件路径。可以时绝对路径,也可以是相对路径。默认为 ( W O R K S P A C E ) / B u i l d / (WORKSPACE)/Build/ (WORKSPACE)/Build/(PLATFORM_NAME)
      FLASH_DEFINTTION 文件名FILE_NAME FDF文件。可以是文件名,也可以是带带路径的文件名。如果仅是文件名,则该文件必须在.dsc所在的目录
      BUILD_NUMBER 最多四个字符 用于Mkefile文件
      FIX_LOAD_TOP_MEMORY_ADD RESS 地址 驱动、应用程序在内存中的起始地址
      TIME_STAMP_FILE 文件名 时间戳文件。可以是文件名,也可以是带路径的文件名。该文件中包含了一个时间戳,所有编译过程中生成的文件都使用该时间戳
      DEFINE MACRO=PATH|Value ? 宏定义,定义的宏可以在 .dsc文件中调用。例如,DEFINE DEBUG_ENABLE_OUTPUT=FALSE,在后续的 .dsc文件中可以直接:!if$(DEBUG_ENABLE_OUTPUT) \n !endif
      EDK_GLOBAL MACRO=PATH|Value 仅在EDK模块适用,EDK2模块会自动忽略
      RfC_lANGUAGES RFC 4646语言代码列表 RFC4646语言代码字符串中,各个语言代码之间使用分号“;”分隔。用于在AutoGen阶段处理Unicode字符串。字符串必须用“包裹”?
      VPD_TOOL_GUID GUID 在AutoGen阶段调用此GUID对应的VPD程序。VPD程序定义在Conf\tool_def.txt文件中,默认为BPDG
      PCD_INFO_GENERATION_GENERATION BOOL值 TRUE表示在PCD数据库中存在PCD信息

      Nt32Pkg中 .dsc文件的[defines]部分:

      [Defines]
      	PLATFORM_NAME				=NT32
      	PLATFORM_GUID				=EB12332-123S-21XZ-1DD1-AS231ER523C2
      	PLATFORM_VERSION			=0.4
      	DSC_SPECIFICATION			=0x00010005
      	OUTPUT_SPECIFICATION		=Build/NT32
      	SUPPORTED_ARCHITECTURES		=IA32
      	BUILD_TARGETS				=DEBUG|RELEASE
      	SKUID_IDENTIFIER			=DEFAULT
      	FLASH_DEFINITION			=Nt32Pkg/Nt32Pkg.fdf
      	
      
    2. [LibraryClasses]块

      在[LibraryClasses]块中定义了库的名字以及库的 .inf文件的路径。这些库可以被[Components]块引用。

      1)语法:

         [LibraryClasses]块 语法如下:

      #方法一
      [LibraryClasses.$(Arch).$(MODULE_TYPE)]
      	LibraryName | Path/LibraryName.inf
      	
      

         或

      #方法二
      [LibraryClasses.$(Arch).$(MODULE_TYPE), LibraryClasses.$(Arch1).$(MODULE_TYPE1)]
      	LibraryName | Path/LibraryName.inf
      	
      

         ( A r c h ) 和 (Arch)和 (Arch)(MODULE_TYPE)是可选项。用“ , ”表示并列关系,块内的库对LibraryClasses. ( A r c h ) . (Arch). (Arch).(MODULE_TYPE)和LibraryClasses. ( A r c h 1 ) . (Arch1). (Arch1).(MODULE_TYPE1)都有效。

         $(Arch)表示体系结构,可以是下列值之一:IA32、X64、IPF、EBC、ARM、common。其中,common表示对所有体系结构都有效。

         KaTeX parse error: Undefined control sequence: \? at position 35: …*类别**,块内列出的库只能(\̲?̲用于)提供(MODULE_TYPE)类别的模块链接。$(MODULE_TYPE)可以是以下值:SEC、PEI_CORE、PEIM、DXE_CORE、DXE_SAL_DRIVER、DEX_RUNTIME_DRIVER、BASE、UEFI_DRIVER等。

         通常, .dsc文件中都有[LibraryClasses]区块,表示块内定义的库对所有体系结构和所有类型的模块都有效。

      2)示例:

         在Nt32Pkg.dsc中有:

      [LibraryClasses.common.PEIM, LibraryClasses.common.PEI_CORE]
      	HobLib | MdePkg/Library/PeiHobLib/PeiHobLib.inf
      	
      

         在ShellPkg.dsc中有:

      [LibraryClasses.ARM]
      	NULL | ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf
      	
      

         引用库是在 .inf 文件的[LibraryClasses]块中完成的。例如,上上篇博客中第一个示例程序的 .inf文件中引用了UefiApplicationEntryPoint和UefiLib,如下代码所示:

      [LibraryClasses]
      	UefiApplicationEntryPoint
      	UefiLib
      	
      
    3. [Components]块

      在[Components]块内定义的模块都会被build工具编译、并生成.efi文件,其格式如下:

      #格式一
      [Components.$(Arch)]
      	Path\Exectuables.inf
      	
      

      或者

      #格式二
      [Components.$(Arch)]
      	Path\Exectuables.inf{
      	
      	 #嵌套块
      		LibraryName | Path/LibraryName.inf
      
      	 #嵌套块
      		#子块中还可以包含
      	
      	}
      	
      

         如果Path是相对路径,则相对路径起始于 ( W O R K S P A C E ) , (WORKSPACE), (WORKSPACE)(WORKSPACE)通常是EDK2的根目录。在Path中可以使用通过 DEFINE命令 定义的宏。例如:

      [Components]
      	DEFINE MYSOURCE_PATH = D:/Source
      	$(MYSOURCE_PATH)/Hello.inf #相当于 D:/Source/Hello.inf
      	
      

         格式二中大括号内的内容仅对本模块有效,例如下面的代码中[Components]声明的DevicePathDxe.inf会调用在MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf中定义的DevicePathLib库,而其它的模块则使用在全局[LibraryClasses]块中声明的UefiDevicePathLibDevicePathProtocol.inf对应的DevicePathLib库。

      [LibraryClasses]
      DevicePathLib | MdePkg/Library/UefiDevicePathLibDevicePathProtocol/UefiDevicePathLibPathProtocol.inf
      
      [Components]
      	...
      	MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf{
      		
      			DevicePathLib | MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
      	}
      	
      

         下面编写一个MdeMoudlePkg.dsc中的一个实例,这个块内的模块对IA32、X64和IPF体系结构有效:

      [Components.IA32, Components.X64, Components.IPF]
      	MdeModulePkg/Universal/Network/UefiPxeBcDxe/UefiPxeBcDxe.inf
      	MdeModulePkg/Universal/DebugSupportDxe/DebugSupportDxe.inf
      	MdeModulePkg/Universal/EbcDxe/EbcDxe.inf
      	
      
    4. [BuildOptions]块

         [BuildOptions]格式在 .inf文件中以及进行过介绍, .dsc文件的[BuildOptions]与 .inf文件的[BuildOptions]格式大致相同,区别在于 .dsc文件的[BuildOptions]对 .dsc文件内的所有模块有效。 .dsc文件的[BuildOptions]模块格式如下:

      [BuildOptions.$(Arch).$(CodeBase)]
      	[编译器]:[$(Target)]_[Tool]_[$(Arch)]_[CC|DLINK]_FLAGS = 
      	
      

         ( A r c h ) 与 (Arch)与 (Arch)(CodeBase)都是可选项。 ( C o d e B a s e ) 的 值 是 E D K 和 E D K 2 中 的 一 个 。 (CodeBase)的值是EDK和EDK2中的一个。 (CodeBase)EDKEDK2(Arch)是体系结构,如IA32、X64等。

         $(Target)选项的值是DEBUG、RELEASE、*中的某个;Tool是编译工具的名字,如VS2012、GCC44等;CC表示编译选项;DLIKN表示连接选项。

      AppPkg.dsc中的[BuildOptions]块中的代码如下:

      [BuildOptions]
      !ifndef $(EMULATE)
      	INTEL:*_*_*_CC_FLAGS		= /Qfreestanding /D UEFI_C_SOURCE
      	 MSFT:*_*_*_CC_FLAGS		= /X /Zc:wchar_t /D UEFI_C_SOURCE
      	 ...
      
      !else
      	INTEL:*_*_IA32_CC_FLAGS		= /Od /D UEFI_C_SOURCE
      	 MSFT:*_*_IA32_CC_FLAGS		= /Od /D UEFI_C_SOURCE
      	 ...
      	 
      !endif
      
      

         在 .dsc文件中可使用" ! “命令。” !include “用于加载其他文件。” !if、!ifdef、!ifndef、!else、!end"等则是条件处理语句。

         最后简单介绍下[PCD]块。[PCD]块用于定义平台配置数据。其目的是在不改动 .inf文件和源文件的情况下完成对平台的配置。例如在UEFI模拟器Nt32Pkg的 .dsc文件Nt32Pkg.dsc 中可以通过PCD的PcdWinNtFileSystem配置模拟器文件系统路径,如下所示:

      gEfiNt32PkgTokenSpaceGuid.PcdWinNtFileSystem | L".!..\..\..\..\EdkShellBinPkg\Bin\Ia32\Apps" | VOID* | 106
      

         配置文件被" | "分成四个部分:第一部分中gEfiNt32PkgTokenSpaceGuid是命名空间,PcdWinNtFileSystem是变量名;第二部分是值;第三部分是变量类型。第四部分是变量数据的最大长度。

         在源文件中可以通过LIbPcdGetPtr(_PCD_TOKEN_PcdWinNtFileSystem)获得gEfiNt32PkgTokenSpaceGuid.PcdWinNtFileSystem定义的值。

  • 2、 .dec文件

       .dec文件定义了公开的数据和接口以供其他模块使用。包含有必须模块[Defines]以及可选区块[Includes]、[LibraryClasse、[Guids]、[Protocols]、[Ppis]和[PCD]等部分。

    1. [Defines]块

         [Defines]块用于提供package的名称、GUID、版本号等信息,格式如下:

      [Defines]
      	Name = Vlaue
      	
      

         其中,Name的取值范围是[DEC_SPECIFICATION、PACKAGE_NAME、PACKAGE_GUID、PACKAGE_VERSION]。

         例如,MdePkg.dsc中的[Defines]部分如下所示:

      [Defines]
      	Dec_SPECIFICATION = 0x00010001
      	PACKAGE_NAME = MdePkg
      	PACKAGE_GUID = 1W2323F-F31S-1242-SDC1-F23C123F1211
      	PACKAGE_VERSION = 1.03
      	
      
    2. [Includes]块

         [includes]块列出了本Package提供的头文件所在的目录,格式如下:

      [Includes.$(Arch)]
      	Path
      	
      

         Path只能是相对路径,该相对路径起始于本Package的.dsc所在的目录。

         MdePkg.dec文件中的[Includes]部分如下:

      [Include]
      	Include
      	
      [Include.IA32]				#编译 32 位程序时的头文件路径
      	Include/Ia32
      	
      [Include.X64]				#编译x86——64位程序时的头文件路径
      	Include/X64
      
    3. [LibraryClasses]块

         package可以通过 .dec文件对外提供库,每个库都必须有一个头文件,放在Include\Library目录下。[LibraryClasses]块用于明确库和头文件的对应关系。其格式如下:

      [LibraryClasses.$(Arch)]
      	LibraryName | Path/LibraryHeader.h
      	
      

         MdePkg.dec中[LibraryClasses]块中代码的一部分如下:

      [LibraryClasses]
      	UefiUsbLib | Include/Library/UefiUsbLib.h
      	
      [LibraryClasses.IA32, LibraryClasses.X64]
      	SmmLib | Include/Library/SmmLib.h
      	
      
    4. [Guids]块

         在Package\Include\Guid目录中有很多文件,每个文件内定义了一个或几个GUID,例如在MdePkg\Include\Gpt.h文件中定义了Gpt分区相关的GUID,如下所示:

      extern EFI_GUID gEfiPartTypeUnusedGuid;
      extern EFI_GUID gEfiPartTypeSystemPartGuid;
      extern EFI_GUID gEfiPartTypeLegacyMbrGuid
      
      

         可以看出这些定义只是声明了变量,并未对其进行赋值。真正的常量定义?在AutoGen.c中,其值定义在 .dec文件的[Guids]块中。格式为:

      [Guid.$(Arch)]
      	GUIDName = GUID
      	
      

         上文中提到的Gpt相关的GUID,定义在在MdePkg.dec中,这些GUID定义如下:

      [Guids]
      ...
      ## include/Guid/Gpt.h
      	gEfiPartTypeLegacyMbrGuid = { 0x024DEE41, 0x33E7, 0x11D3, { 0x9d, 0x69, 0x00, 0x08, 0xc7, 0x81, 0xF3, 0x9F}}
      	gEfiPartTypeSystemPartGuid = { 0xC12A7328, 0xF81F, 0x11D2, { 0xBA, 0x4B, 0x00, 0xA0, 0xC9, 0x3E, 0xC9, 0x3B}}
      	gEfiPartTypeUnusedGuid = { 0x00000000, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}
      	
      
    5. [Protocols]块

         与Guids相似,在Package\Include\Protocols 目录下有很多头文件,每个头文件定义了一个或多个Protocol,这些Protocol的GUID值就定义在 .dec文件的[Protocols]块,格式如下:

      [Protocols.$(Arch)]
      	ProtocolName = GUID
      	
      

         如,在MdePkg\Include\Protocol目录下BlockIo.h定义的BlockIo Protocol

      extern EFI_GUID gEfiBlockIoProtocolGuid;
      
      

         gEfiBlockIoProtocolGuid的值定义在MdePkg.dec的[Protocls]块中。

      [Protocols]
      	gEfiBlockProtocolGuid = { 0x964EB21, 0x6459, 0x11D2, { 0x8E, 0x39, 0x00, 0x00, 0xC9, 0x69, 0xE2, 0x2C}}
      	
      
    6. [Ppis]块、[PCD]块、[UserExtensions]块

         [Ppis]块用于定义源文件中用到的PPI(PPI是PEI阶段,PEI模块间通信的接口),语法类似于[Protocols]。

         [PCD]块是 .dsc文件中对[PCD]块的补充,

         [UserExtensions]块

你可能感兴趣的:(#UEFI,底层开发)