相关参考

参考文章下载地址:
链接: https://pan.baidu.com/s/1LjrydEzCACG3ohpx7mMKKg 提取码: 4i3j

模块和包

EDK下的模块(Module)和包(Package)

在EDKII目录下,有很多 xxxxPkg文件,每一个这种文件,称为一个Package。
包 由 一组模块及平台描述文件(dsc)和 包声明文件(dec)组成的集合。

模块(重点)

可执行文件,即 efi文件,像Linux驱动一样 可动态加载到 UEFI内核中。
包括 : 源码文件 .c ** 和 元数据文件 .inf 组成 ,挂到dsc中编译生成 .efi文件**

image.png
image.png

inf工程描述文件说明

参考:

小技巧:使用时 find下,然后从别人那边拷贝一个改改用就好

image.png
这里提供一个通用的inf文件,根据自己需要修改

  1. [Defines]
  2. INF_VERSION = 0x00010006 # INF支持标准版本, find下看别人是多少,直接写。 格式可以参考
  3. BASE_NAME = UefiMain # 目标文件名,编译后在build下搜索 "BASE_NAME.efi" 就是目标文件
  4. FILE_GUID = f12a2e88-9f0b-4ae0-bb7c-c6557175f10c # GUID, 使用 uuidgen 命令生成一个就好
  5. MODULE_TYPE = UEFI_APPLICATION # !!!根据UEFI模块类型,填写不同字段
  6. VERSION_STRING = 0.1
  7. ENTRY_POINT = UefiMain_test # 入口函数名, 比如 main
  8. [Sources]
  9. main.c # 源文件列表
  10. [Packages]
  11. MdePkg/MdePkg.dec # 本模块引用到所有包的包声明文件
  12. [LibraryClasses] # 本模块要链接的库模块
  13. UefiApplicationEntryPoint # 库名称

当然,还有 Protocols, BuildOptions 模块,这里就不列举了

UEFI下应用开发

源码

  1. (base) baiy@inno-MS-7B89:test01$ cat main.c
  2. #include <Uefi.h>
  3. EFI_STATUS EFIAPI testUefiMain (IN EFI_HANDLE ImageHandle IN EFI_SYSTEM_TABLE *SystemTable)
  4. {
  5. SystemTable->ConOut->OutputString(SystemTable->ConOut, L"HelloWorld\n");
  6. return EFI_SUCCESS;
  7. }

配置inf文件

inf文件相当于Linux下的Makefile

  1. (base) baiy@inno-MS-7B89:test01$ cat main.inf
  2. [Defines]
  3. INF_VERSION = 0x00010006
  4. BASE_NAME = UefiMain
  5. FILE_GUID = f12a2e88-9f0b-4ae0-bb7c-c6557175f10c
  6. MODULE_TYPE = UEFI_APPLICATION
  7. VERSION_STRING = 0.1
  8. ENTRY_POINT = testUefiMain
  9. [Sources]
  10. main.c
  11. [Packages]
  12. MdePkg/MdePkg.dec
  13. OptionRomPkg/OptionRomPkg.dec
  14. [LibraryClasses]
  15. UefiApplicationEntryPoint

拷贝和执行

mount 将自己的app.disk 挂到目录上,然后将目标文件拷贝进去,运行时直接运行即可(驱动 需要 load xxx.efi, 应用直接运行就好)

  1. root@inno-MS-7B89:edk2# find ./ -name "UefiMain.efi"
  2. ./Build/OvmfX64/DEBUG_GCC5/X64/UefiMain.efi
  3. ./Build/OvmfX64/DEBUG_GCC5/X64/test/stdapp_test/test01/main/DEBUG/UefiMain.efi
  4. ./Build/OvmfX64/DEBUG_GCC5/X64/test/stdapp_test/test01/main/OUTPUT/UefiMain.efi

image.png

UEFI应用程序的加载

UEFI应用程序的编译

UEFI应用的加载

gBS关于Image的接口

  1. EFI_BOOT_SERVICES *gBS = NULL; // BootServices中关于Image的描述:
  2. ///
  3. /// EFI Boot Services Table.
  4. ///
  5. typedef struct {
  6. //
  7. // Image Services
  8. //
  9. EFI_IMAGE_LOAD LoadImage;
  10. EFI_IMAGE_START StartImage;
  11. EFI_EXIT Exit;
  12. EFI_IMAGE_UNLOAD UnloadImage;
  13. EFI_EXIT_BOOT_SERVICES ExitBootServices;
  14. }
  15. 实现如下
  16. // DXE Core Module Variables
  17. //
  18. EFI_BOOT_SERVICES mBootServices = {
  19. (EFI_IMAGE_LOAD) CoreLoadImage, // LoadImage
  20. (EFI_IMAGE_START) CoreStartImage, // StartImage
  21. (EFI_EXIT) CoreExit, // Exit
  22. (EFI_IMAGE_UNLOAD) CoreUnloadImage, // UnloadImage
  23. (EFI_EXIT_BOOT_SERVICES) CoreExitBootServices, // ExitBootServices
  24. };

Shell加载应用过程

我们应用程序运行 在Shell中
image.png
解析过程如下:

  1. InternalShellExecuteDevicePath
  2. gBS->LoadImage // 将文件加载到内存,生成Image对象
  3. gBS->OpenProtocol // 获取命令行参数
  4. gBS->StartImage // 启动Image,调用CoreStartImage
  5. CoreStartImage
  6. // 设置退出时的位置
  7. Image->JumpBuffer = AllocatePool 设置Long jump,用于退出程序
  8. SetJumpFlag = SetJump (Image->JumpContext);
  9. // 跳转到程序中运行
  10. Image->Status = Image->EntryPoint (ImageHandle, Image->Info.SystemTable);
  11. _ModuleEntryPoint() // 入口 MdePkg\Library\UefiApplicationEntryPoint\ApplicationEntryPoint.c

image.png

  1. _ModuleEntryPoint
  2. ProcessLibraryConstructorList // 所有库的构造函数
  3. ProcessModuleEntryPointList // 调用Image main的入口函数
  4. ProcessLibraryDestructorList // 所有库的析构函数

这三个函数,在build的时候,根据inf文件生成 Autogen.c和Autogen.h文件,这三个函数就是Autogen文件的一部分。

dsc,dec,fdt文件描述

image.png
dsc文件(Platform Description File)
dec文件(Package Declaration File) 包声明文件。
fdt文件 用于生成Image文件。