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

相关内容

热门资讯

ennie meenie 是什... ennie meenie 是什么意思?请说详细点,网上说的太杂,不地道我只知道Eenie, meen...
饶雪漫的酸甜书面封底有一段话,... 饶雪漫的酸甜书面封底有一段话,请问是什么??饶雪漫的酸甜书面封底有一段话,请问是什么??我非常非常的...
有人叫全能直播是真的吗 有人叫全能直播是真的吗有人叫全能直播是真的,张大仙就是全能直播,王者当红主播,春季赛中,xyg的雹橡...
林毅夫委员:会开船的人,逆风也... 转自:北京日报客户端只要把国内的事做好,不管外部环境如何,我们总能乘风破浪前进。我相信,沿着我们的道...
在哪能知道少年JUMP是否要休... 在哪能知道少年JUMP是否要休刊(中文的网啊不懂日文的),就像刚刚过去的2周都是在休刊人家要过年的。...
喜欢上了隔壁班级的女生,我怎样... 喜欢上了隔壁班级的女生,我怎样才能让她注意到我呢?如果喜欢她罩拦的话,那么自己就应该主动一点,可以借...
动漫是叫什么阴阳师来着,男主是... 动漫是叫什么阴阳师来着,男主是个少年和一只猫妖除妖来着?少年阴阳师,那个是腾蛇红莲夏目友人帐。动漫:...
点击浏览过的文章标题变为蓝色,... 点击浏览过的文章标题变为蓝色,表明已浏览过.关闭浏览器再进入之后颜色变回原来状态.这个怎么实现目测自...
分析〈项羽本纪〉中项羽的形象特... 分析〈项羽本纪〉中项羽的形象特征急求答案,拜托各位了~~~~刚愎自用,优柔寡断,不能用人。
伤寒论。郝万山。刘渡舟。胡希恕... 伤寒论。郝万山。刘渡舟。胡希恕的有什么区别吗。那个讲的更好?胡希恕先生讲的最好,看过胡希恕先生讲的《...
老雪花多少度? 老雪花多少度?全天运转,1.1度电,实际用起来大概0.4度左右。全天运转,1.1度电,实际用起来大概...
这段时间感触最深的就是:初读不... 这段时间感触最深的就是:初读不知书中意,再读已是书中人,长大真的这么苦吗?少年不知愁滋味 成长哺育叶...
名人传的好词 名人传的好词好词:庸俗 裨益 晨光 凄凉 渺茫 隐忍 无可救药 衰退 云翳 崇山峻岭 落寞 巅峰 底...
陕西神木市一学校餐厅吃出异物?... 来源:神木市实验中学 神木市实验中学微信公号3月8日发布“关于网传我校餐厅不实消息的情况通报”,全文...
两会声音|吴相君代表:补齐农村... 转自:河北新闻网吴相君代表。 河北日报记者 赵海江摄河北日报讯(记者崔丛丛)政府工作报告提出,扩大普...
合肥最新公开招聘! 转自:合肥发布为深入贯彻党的二十大和二十届三中全会精神,积极促进高质量充分就业,着力为企业招人才、为...
外商投资中国区域样本观察:在上... 政府工作报告提出,加强外资企业服务保障,加快标志性项目落地,持续打造“投资中国”品牌。近期,乐高、丰...
开放透明,干货很多!人大代表团... 转自:上观新闻连日来,十四届全国人大三次会议代表团密集举行开放团组活动。截至发稿时,已有33个人大代...
林毅夫委员人民日报撰文:会开船... 北京大学新结构经济学研究院院长  林毅夫委员只要把国内的事做好,不管外部环境如何,我们总能乘风破浪前...
49岁的她,夺冠!本人发文回应 3月8日,即将年满50周岁的乌兹别克斯坦传奇运动员丘索维金娜在体操世界杯巴库站,凭借总分13.516...