相关参考
- EDK II Module Writer’s Guide : 官方模块编写指导
- EDK II Module Information (INF) File Specification : 官方INF文件说明
- UEFI原理与编程_戴正华 第3章
参考文章下载地址:
链接: https://pan.baidu.com/s/1LjrydEzCACG3ohpx7mMKKg 提取码: 4i3j
模块和包
EDK下的模块(Module)和包(Package)
包
在EDKII目录下,有很多 xxxxPkg文件,每一个这种文件,称为一个Package。
包 由 一组模块及平台描述文件(dsc)和 包声明文件(dec)组成的集合。
模块(重点)
可执行文件,即 efi文件,像Linux驱动一样 可动态加载到 UEFI内核中。
包括 : 源码文件 .c ** 和 元数据文件 .inf 组成 ,挂到dsc中编译生成 .efi文件**
inf工程描述文件说明
参考:
- EDK II Module Information (INF) File Specification : 官方INF文件说明
- UEFI原理与编程_戴正华 第3.1.2
小技巧:使用时 find下,然后从别人那边拷贝一个改改用就好
这里提供一个通用的inf文件,根据自己需要修改
[Defines]
INF_VERSION = 0x00010006 # INF支持标准版本, find下看别人是多少,直接写。 格式可以参考
BASE_NAME = UefiMain # 目标文件名,编译后在build下搜索 "BASE_NAME.efi" 就是目标文件
FILE_GUID = f12a2e88-9f0b-4ae0-bb7c-c6557175f10c # GUID, 使用 uuidgen 命令生成一个就好
MODULE_TYPE = UEFI_APPLICATION # !!!根据UEFI模块类型,填写不同字段
VERSION_STRING = 0.1
ENTRY_POINT = UefiMain_test # 入口函数名, 比如 main
[Sources]
main.c # 源文件列表
[Packages]
MdePkg/MdePkg.dec # 本模块引用到所有包的包声明文件
[LibraryClasses] # 本模块要链接的库模块
UefiApplicationEntryPoint # 库名称
当然,还有 Protocols, BuildOptions 模块,这里就不列举了
UEFI下应用开发
源码
(base) baiy@inno-MS-7B89:test01$ cat main.c
#include <Uefi.h>
EFI_STATUS EFIAPI testUefiMain (IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
{
SystemTable->ConOut->OutputString(SystemTable->ConOut, L"HelloWorld\n");
return EFI_SUCCESS;
}
配置inf文件
inf文件相当于Linux下的Makefile
(base) baiy@inno-MS-7B89:test01$ cat main.inf
[Defines]
INF_VERSION = 0x00010006
BASE_NAME = UefiMain
FILE_GUID = f12a2e88-9f0b-4ae0-bb7c-c6557175f10c
MODULE_TYPE = UEFI_APPLICATION
VERSION_STRING = 0.1
ENTRY_POINT = testUefiMain
[Sources]
main.c
[Packages]
MdePkg/MdePkg.dec
OptionRomPkg/OptionRomPkg.dec
[LibraryClasses]
UefiApplicationEntryPoint
拷贝和执行
mount 将自己的app.disk 挂到目录上,然后将目标文件拷贝进去,运行时直接运行即可(驱动 需要 load xxx.efi, 应用直接运行就好)
root@inno-MS-7B89:edk2# find ./ -name "UefiMain.efi"
./Build/OvmfX64/DEBUG_GCC5/X64/UefiMain.efi
./Build/OvmfX64/DEBUG_GCC5/X64/test/stdapp_test/test01/main/DEBUG/UefiMain.efi
./Build/OvmfX64/DEBUG_GCC5/X64/test/stdapp_test/test01/main/OUTPUT/UefiMain.efi
UEFI应用程序的加载
UEFI应用程序的编译
UEFI应用的加载
gBS关于Image的接口
EFI_BOOT_SERVICES *gBS = NULL; // BootServices中关于Image的描述:
///
/// EFI Boot Services Table.
///
typedef struct {
//
// Image Services
//
EFI_IMAGE_LOAD LoadImage;
EFI_IMAGE_START StartImage;
EFI_EXIT Exit;
EFI_IMAGE_UNLOAD UnloadImage;
EFI_EXIT_BOOT_SERVICES ExitBootServices;
}
实现如下
// DXE Core Module Variables
//
EFI_BOOT_SERVICES mBootServices = {
(EFI_IMAGE_LOAD) CoreLoadImage, // LoadImage
(EFI_IMAGE_START) CoreStartImage, // StartImage
(EFI_EXIT) CoreExit, // Exit
(EFI_IMAGE_UNLOAD) CoreUnloadImage, // UnloadImage
(EFI_EXIT_BOOT_SERVICES) CoreExitBootServices, // ExitBootServices
};
Shell加载应用过程
我们应用程序运行 在Shell中
解析过程如下:
InternalShellExecuteDevicePath
gBS->LoadImage // 将文件加载到内存,生成Image对象
gBS->OpenProtocol // 获取命令行参数
gBS->StartImage // 启动Image,调用CoreStartImage
CoreStartImage
// 设置退出时的位置
Image->JumpBuffer = AllocatePool 设置Long jump,用于退出程序
SetJumpFlag = SetJump (Image->JumpContext);
// 跳转到程序中运行
Image->Status = Image->EntryPoint (ImageHandle, Image->Info.SystemTable);
_ModuleEntryPoint() // 入口 MdePkg\Library\UefiApplicationEntryPoint\ApplicationEntryPoint.c
_ModuleEntryPoint
ProcessLibraryConstructorList // 所有库的构造函数
ProcessModuleEntryPointList // 调用Image main的入口函数
ProcessLibraryDestructorList // 所有库的析构函数
这三个函数,在build的时候,根据inf文件生成 Autogen.c和Autogen.h文件,这三个函数就是Autogen文件的一部分。
dsc,dec,fdt文件描述
dsc文件(Platform Description File)
dec文件(Package Declaration File) 包声明文件。
fdt文件 用于生成Image文件。