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

相关内容

热门资讯

李光洁32天走7500公里吃8... 李光洁32天走7500公里吃8城,《拿一座城市下酒》这部纪录片怎么样?我觉得这部纪录片非常好,观看的...
每我世如你果只没界喜就欢的生一... 每我世如你果只没界喜就欢的生一爱有你过在想会。把这22个字组成一句话。我想过,如果在每一生只喜欢你,...
调查校园里的植物和动物说说有哪... 调查校园里的植物和动物说说有哪些动植物?可以分成几类?兰花,梅花可人丌··植物:乔木(杨树、柳树、银...
血脂高的原因? 血脂高的原因?血脂高的原因高血脂的诱因包括原发性和继发性两种:原发性高血脂症的病因:1、遗传因素。2...
为什么孩子总是重复看同一集动画... 为什么孩子总是重复看同一集动画片?是在传递这3个信号 小孩子爱看动画片是非常普遍的,动画片带给他们动...
终极三国里 49集刘备为什么这... 终极三国里 49集刘备为什么这么做?有没有官方回答?下集自己看吧 现在不会有官方回答的哟第一:可能真...
西式糕点制作大全的内容简介 西式糕点制作大全的内容简介《西式糕点制作大全》主要介绍了制作甜点的基本知识,例如各种制作工具,制作点...
逻辑思维又是什么?就是推理吗,... 逻辑思维又是什么?就是推理吗,怎么培养!?逻辑思维是一种严格分析思维。不一定是推理。推理是逻辑思维的...
囊萤夜读有一句俗语就是出自这个... 囊萤夜读有一句俗语就是出自这个故事你知道是什么吗?囊萤映雪 ( náng yíng yìng xuě...
什么是不伦恋情? 什么是不伦恋情?什么是不伦恋情.,?男跟女年龄相差很大?还是?男的比女的小?还是老夫少妻?是近亲谈恋...
有书名带晨星的嘛? 有书名带晨星的嘛?有书名带晨星的嘛?晨星传这本书。漫画书晨星物语
如果有些事情说不出口怎么办? 如果有些事情说不出口怎么办?烦恼皆是因为自己过分的执着 即使你在这样子下去 更不就不会有好的结果 为...
有哪些类似于《非自然死亡》题材... 有哪些类似于《非自然死亡》题材的日剧推荐?非自然死亡的题材电影确实不多,电视剧的话也不好找啊。不喜欢...
素书全集的内容简介 素书全集的内容简介 本书采用了《素书》的权威原著,参照《四库全书》并加上了宋代宰相张商英的注和清代王...
【世纪花园】小区对口的学校有重... 【世纪花园】小区对口的学校有重点小学和初中吗?世纪花园东区里有未来强者幼儿园,小区南边有个华兴小区,...
东南大学现有的专业中有哪些是属... 东南大学现有的专业中有哪些是属于老东南的1928年学校改名为国立中央大学,设理、工、医、农、文、法、...
一个男人一有钱就请朋友吃饭,没... 一个男人一有钱就请朋友吃饭,没钱就又说,买东西还赊账,商店里的老板都找上门来了?像陵念前这种男人的话...
坟上栽什么草好? 坟上栽什么草好?坟地种什么草好耐旱坟上栽野蕨草、扎根不深、浅根植物、可以固土、南方雨水多、不会造成坟...
关于国富潜力基金 关于国富潜力基金我9月24日上午买的国富基金,申购价格是9月24日开盘的价格吗?还是9月28日开盘的...
我是一个高中生。想学武术。在学... 我是一个高中生。想学武术。在学校没什么时间。是练散打还是跆拳道好。我是一个高中生。想学武术。在学校没...