UEFI 原理与编程 之 三种方式实现 HelloWorld
创始人
2024-05-30 14:09:54
0

在工作区新建目录 infs/UefiMain

添加文件: UefiMain.c, 内容如下:

#include
EFI_STATUS
UefiMain (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
SystemTable -> ConOut-> OutputString(SystemTable->ConOut, L"HelloWorld\n");
return EFI_SUCCESS;
}
再添加一个文件: UefiMain.inf, 内容如下:

[Defines]
INF_VERSION = 0x00010006
BASE_NAME = UefiMain
FILE_GUID = 4ea97c46-7491-4dfd-b442-747010f3ce5f
MODULE_TYPE = UEFI_APPLICATION
VERSION_STRING = 0.1
ENTRY_POINT = UefiMain
[Sources]
UefiMain.c

[Packages]
MdePkg/MdePkg.dec

[LibraryClasses]
UefiApplicationEntryPoint
UefiLib
[FixedPcd]
gEfiMdePkgTokenSpaceGuid.PcdFSBClock|600000000
gEfiMdePkgTokenSpaceGuid.PcdMaximumUnicodeStringLength
[FeaturePcd]
gEfiMdePkgTokenSpaceGuid.PcdComponentNameDisable|FALSE
gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnosticsDisable
[PatchPcd]
gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultLangCodes
[BuildOptions]
MSFT:DEBUG_*_IA32_CC_FLAGS = /Od
之后修改 Nt32Pkg\Nt32Pkg.dsc, 在 356 行添加一行

infs/UefiMain/UefiMain.inf
之后编译, 运行模拟器

edksetup.bat --nt32
build -p Nt32Pkg\Nt32Pkg.dsc -a IA32
build run
进入模拟器后,

cd fs0:
UefiMain.efi
看到结果:

使用 C 标准库
修改文件: UefiMain.c, 内容如下:

#include
#include
int main (int argc, char **argv )
{
printf(“HelloWorld\n”);
return 0;
}
修改文件: UefiMain.inf, 内容如下:

@file main.inf

[Defines]
INF_VERSION = 0x00010006
BASE_NAME = UefiMain
FILE_GUID = 4ea97c46-7491-4dfd-b442-747010f3ce5f
MODULE_TYPE = UEFI_APPLICATION
VERSION_STRING = 0.1
ENTRY_POINT = ShellCEntryLib
[Sources]
main.c
[Packages]
MdePkg/MdePkg.dec
ShellPkg/ShellPkg.dec
StdLib/StdLib.dec
[LibraryClasses]
LibC
LibStdio
ShellCEntryLib

之后修改 Nt32Pkg\Nt32Pkg.dsc, 在 最后再添加一行

!include StdLib/StdLib.inc
之后编译, 运行模拟器

edksetup.bat --nt32
build -p Nt32Pkg\Nt32Pkg.dsc -a IA32
build run
进入模拟器后,

cd fs0:
UefiMain.efi
可以看到同样的结果:

Shell App
修改文件: UefiMain.c, 内容如下:

#include
#include

INTN
EFIAPI
ShellAppMain (
IN UINTN Argc,
IN CHAR16 **Argv
)
{
gST -> ConOut-> OutputString(gST -> ConOut, L"HelloWorld\n");
return 0;
}

修改文件: UefiMain.inf, 内容如下:

[Defines]
INF_VERSION = 0x00010006
BASE_NAME = UefiMain
FILE_GUID = 4ea97c46-7491-4dfd-b442-747010f3ce5f
MODULE_TYPE = UEFI_APPLICATION
VERSION_STRING = 0.1
ENTRY_POINT = ShellCEntryLib

VALID_ARCHITECTURES = IA32 X64 IPF

[Sources]
Main.c

[Packages]
MdePkg/MdePkg.dec
ShellPkg/ShellPkg.dec

[LibraryClasses]
ShellCEntryLib
UefiLib

[BuildOptions]
之后修改 Nt32Pkg\Nt32Pkg.dsc, 在 最后再添加一行

!include StdLib/StdLib.inc
之后编译, 运行模拟器

edksetup.bat --nt32
build -p Nt32Pkg\Nt32Pkg.dsc -a IA32
build run
进入模拟器后,

cd fs0:
UefiMain.efi
也可以看到同样的结果:

标准工程模块
每个工程模块都由两部分组成:工程文件和源文件。
工程文件就是 .inf 文件,用于指导EDK2编译工具自动编译模块。
源文件包括C/C++文件、.asm汇编文件也可以包括.uni(字符串资源文件)和.vfr(资源窗体文件)等。

源文件
入口函数名可以在工程文件中自定义,但是一般用UefiMain。入口参数有ImageHandle和SystemTable, ImageHandle就是编译生成.efl文件加载到内存中的的Image对象的句柄。
SystemTable是程序和UEFI内核交互的桥梁,可以通过它获得各种UEFI提供的服务。它本身是一个UEFI内核的全局结构体。

工程文件
其中包含如下几个“块”

[Defines]
INF_VERSION=0x00010005
BASE_NAME= 生成的.efi文件名
FILE_GUID=生成链接
MODULE_TYPE=UEFI_APPLICATION #写驱动和库的时候会有变动,大多情况下都是填这个
VERSION_STRING=1.0 #版本号,想改就改
ENTRY_POINT=UefiMain # 源文件的入口函数名

[Sources]
源文件名,一般源文件会和inf文件放一起,路径啥的没仔细考虑过

[Packages]
用到的库的.dec声明文件,要有路径

[LibraryClasses]
要链接的库模块,库要在该工程模块所在的包的dsc文件中有对应路径
示例如下

.inf .dsc
[LibraryClasses] [LibraryClasses]
UefiApplicationEntryPoint UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf
UefiLib UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
tips
注意inf文件中的函数名和源文件一致,编译之前要把inf文件路径添加到dsc文件的Components中。
UEFI使用UTF-8编码,使用Print函数的时候要加 L 。
Shell应用程序工程模块
源文件
以INTN EFIAPI ShellAppMain (IN UINTN Argc, IN CHAR16 **Argv)为入口函数

工程文件
改动点如下

[Defines]
ENTRY_POINT=ShellCEntryLib

[Packages]
MdePkg/MdePkg.dec
ShellPkg/ShellPkg.dec #必须包含

[LibraryClasses]
ShellCEntryLib #必须列出

tips
Shell工程模板入口是ShellCEntryLib,该函数的源码实现入口参数和标准工程模板相同,函数内部使用EfiShellInterface获取命令行参数传入开发者编写的函数。
main函数应用程序模块
源文件
使用C标准库中的函数。

工程文件
基本和Shell配置相同。

[Packages]
StdLib/StdLib.dec

[LibraryClasses]
ShellCEntryLib #提供ShellCEntryLib函数
LibC #提供ShellAppMain函数
LibStdio #提供printf函数

tips
真正的模块入口函数也是ShellCEntryLib,调用过程为ShellCEntryLib->ShellAppMain->main

相关内容

热门资讯

读什么什么有感的英文 读什么什么有感的英文英语读后感标题 “读XXX有感”用英语说是 “Reading after XX...
秦岚个人资料身高体重 秦岚个人资料身高体重身高:165公分 体重:46公斤秦岚 生日:七月十七日 星座:巨蟹座 出生地:沈...
双鱼和天秤会纠缠一辈子,既相配... 双鱼和天秤会纠缠一辈子,既相配又相克,为什么?双鱼座的人和天秤座的人都是比较细心的,而且特别敏感,有...
独自一人在外怎样和别人相处? 独自一人在外怎样和别人相处?我觉得独自一个人在外面一定要好好的照顾自己,应该找一份工作,找一个住的地...
朱自清散文集有哪些写的好,值得... 朱自清散文集有哪些写的好,值得背诵的?《背影》、《 春》、《 荷塘月色》、《 匆匆》都是不错的佳...
大家最讨厌的电视剧的哪一个主角... 大家最讨厌的电视剧的哪一个主角?我觉得最讨厌的电视剧主角是容嬷嬷。都挺好,里面的苏大强就是越看越别扭...
69DT伤害怎么才能上1300... 69DT伤害怎么才能上1300 !我加点是4L1M!现在60了!伤害才800!我没大号,想买梦幻币买...
孩子上课不认真听讲 孩子上课不认真听讲我的孩子七周半,已经上二年级了,但是上课不认真听讲总是搞小动作,说了很多次也不听,...
《红脸儿》的主要内容 《红脸儿》的主要内容  红脸儿主要内容:   小说以散淡而富有诗意的语言回顾了“我”与3个小伙伴之间...
异地恋的成功例子 异地恋的成功例子 情侣异地恋8年终成正果 两人存下186张火车票见证爱情一对河南的情侣在大学恋爱时便...
小狗吃了死耗子怎么办 小狗吃了死耗子怎么办你好,没事的,放心吧,你的小狗是宠物狗还是土狗,若是宠物狗的话可能会给它造成身体...
请问有没有死亡万花筒广播剧资源... 请问有没有死亡万花筒广播剧资源?死亡万花筒,我有呀!死亡万花筒广播剧,地·址:9525.video(...
徐缺有哪些女人 徐缺有哪些女人徐缺是小说《最强反套路系统》中的角色,他有许多女性关系,其中包括:1. 林小红:徐缺的...
假如我是四大名著中的人物作文9... 假如我是四大名著中的人物作文900假如你是的林黛玉的话那你就会好好读书,不至于连900个字都写不出了...
西游记81难? 西游记81难?西游记的81难是师徒四人取经回来在河中落水经书被淹了的事
魔兽世界风暴王子问题! 魔兽世界风暴王子问题!现在3.05这版本 王子第4阶段的屏障 是不是可以被MS驱散? 屏障驱散后是...
如何评价张杰的少年中国说 如何评价张杰的少年中国说我觉得非常棒,张杰的家庭条件不好。从小就非常努力。刻苦学习音乐,经过拼搏奋斗...
智取生辰纲中杨志是怎样的人?他... 智取生辰纲中杨志是怎样的人?他失败的原因是什么?简短些志有智慧,但是他忽略了一个重要的因素:团队的合...
有一本书,名字忘记了.好象是美... 有一本书,名字忘记了.好象是美国人写的.梭罗《瓦尔登湖》 如果你用的是新教材,应该是这篇吧是 海明威...
四岁孩子看什么书 四岁孩子看什么书可以看一些带有简单数字的书、色彩鲜艳的图画、动物图画等,培养他的数字感和色彩感,尽量...