EDK2之Hello Uefi

admin 2024年1月31日20:38:40评论57 views字数 5329阅读17分45秒阅读模式

EDK2之Hello Uefi

继EDK2的环境搭建与模拟执行。现在开始学习如何在EDK2中使用UEFI提供的接口编写一个属于自己的包,并完成一些力所能及的实验性功能。

1、在制作一些大型事务之前,很多软件都会需要先新建工程。在EDK2中也是如此,在之前的文章中有介绍过EDK2使用包来区分不同的工程代码。并使用一些文件来描述这个工程的内容,被称之为包描述文件,或者说时项目描述文件。

因此在开始写代码前需要先新建一个包。来到edk2源码根目录,有很多的Pkg。

EDK2之Hello Uefi

2、新建HelloUefiPkg文件夹用于作为此文章中的实验性包。

edk2自身的包下还存在很多目录用于划分包下面的各个功能点项目的代码,但我们的包没有那么多功能点,所以可以不需要再套更多的文件夹。直接新建HelloUefi.c。

3、写如下代码:

#include <Uefi.h>#include <Library/UefiLib.h>EFI_STATUS UefiMain(IN EFI_HANDLE image, IN EFI_SYSTEM_TABLE* systemTable){    Print("Hello UEFI.n");    return EFI_SUCCESS;}

其中Uefi.h和Library/UefiLib.h相当于Uefi中的标准库,是必须要导入的库,其中包含了很多基础设施。包含基本的数据类型,基本的函数。

UefiMain是Uefi的入口点,是常用的名称但不是固定的名称,入口函数的名称需要在接下来的编译配置文件中指定。但它的函数参数与返回值是固定的。

关于UefiMain:

    1)返回值EFI_STATUS作为当前Uefi应用程序是否正常执行的标识。当程序正常结束时返回EFI_SUCCESS,否则返回错误原因。

    2)参数image:类型是EFI_HANDLE,此句柄描述着Uefi程序本身在内存中的对象。在使用Uefi提供的部分API时需要传递给API来记录调用者。

    3)参数systemTable:类型是EFI_SYSTEM_TABLE指针,此结构体描述着当前系统各种状态与系统提供的一些接口、对象供给Uefi应用程序使用。是经常使用的表项之一。

4、Print和c语言的printf一样支持格式化字符串输出。之后返回EFI_SUCCESS标识程序成功运行。至此最简单的Uefi应用程序就算完成了。

5、为了方便之后的编码更加方便,可以使用VSCode来对edk2的项目进行管理。

使用VSCode打开edk2的根目录:

EDK2之Hello Uefi

如果没装C/C++扩展,可以参考网上教程安装VSCode的C扩展插件。

6、随后找到刚才新建的HelloUefi.c,可能会出现找不到头文件的情况。这是因为没有在VSCode中配置Uefi导入库。

EDK2之Hello Uefi

在.vscode目录下新建VSCode  C/C++配置文件c_cpp_properties.json并写入如下配置项:

{    "configurations": [        {            "name": "Win32",            "includePath": [                "${workspaceFolder}/**",                "${workspaceFolder}/MdePkg/Include"            ],            "defines": [                "_DEBUG",                "UNICODE",                "_UNICODE"            ],            "compilerPath": "XXX\WinGW\bin\gcc.exe",            "cStandard": "c11",            "cppStandard": "gnu++14",            "intelliSenseMode": "windows-gcc-x86"        }    ],    "version": 4}

7、之后VSCode就能正常识别导入库了。ctrl+点击 跟进Print试试:

EDK2之Hello Uefi

8、随后要创建两个文件,一个和Makefile的功能差不多的inf文件,用于描述如何编译这些.c文件。另一个是dsc文件用于描述当前包信息。

      1)dsc文件用于描述整个解决方案的配置信息, 包括支持的平台信息,编译的目标类型和项目名称, 格式如下:

 [Defines]      属性定义标签    INF_VERSION    INF版本号 (0x00010006,可以通过查看edk2自身的inf文件查看)    BASE_NAME      编译结果的文件名称,不包含后缀    FILE_GUID      随机GUID用于唯一标识子模块,可在线生成或使用VSCode的GUID生成器插件    MODULE_TYPE    可选BASE、SEC、PEI_CORE、PEIM、DXE_CORE、DXE_DRIVER、DXE_RUNTIME_DRIVER、DXE_SAL_DRIVER、DXE_SMM_DRIVE、UEFI_DRIVER、UEFI_APPLICATION、USER_DEFINED、HOST_APPLICATION、SMM_CORE、MM_STANDALONE、MM_CORE_STANDALONE,使用UEFI_APPLICATION表示开发UEFI应用程序。    VERSION_STRING  自定义的模块版本,第一个版本1.0    ENTRY_POINT    模块入口点函数名,此处为UefiMain[Sources]      源文件及资源文件列表[Sources.$(ARCH)]  可以指定仅在$(ARCH)架构下才编译的文件[Sources.common]   表示可以在所有架构下编译的文件[Packages]      列出本模块引用的所有包的dec文件,MdePkg/MdePkg.dec必须包含并且放在第一位。[LibraryClasses]  列出本模块引用的链接库名,如UefiLib。在dsc中写的包名称[Protocols]    引用到的Protocols[BuildOptions]  附加的编译选项[Depex]      用来定义驱动的执行顺序,当设置为TRUE时表示当前模块不需要依赖任何模块,轮询到直接执行。否则需要写依赖项,如MdeModulePkg/Logo/LogoDxe.inf中。

       2)dsc文件用于描述整个解决方案的配置信息,包括支持的平台信息,编译的目标类型和项目名称,格式如下:

[Defines]        属性定义标签    PLATFORM_NAME      解决方案名称    PLATFORM_GUID      随机GUID用于唯一标识解决方案,可在线生成或使用VSCode的GUID生成器插件    PLATFORM_VERSION    包版本,第一版本1.0    DSC_SPECIFICATION    dsc文件版本号(当前为0x00010005,可以通过查看edk2自身的dsc查看)    OUTPUT_DIRECTORY      编译结果目录(可选填)    SUPPORTED_ARCHITECTURES  包所支持的cpu架构,用|分割,大小写敏感。包括IA32|X64|EBC|ARM|AARCH64|RISCV64|LOONGARCH64等    BUILD_TARGETS      编译的目标版本,包括DEBUG|RELEASE|NOOPT    SKUID_IDENTIFIER    DEFAULT(可选,暂时不需要填)    FLASH_DEFINITION    当前模块的fdf文件[LibraryClasses]    格式:库名称 | 库的inf文件路径,    以下这两个必加    UefiLib|MdePkg/Library/UefiLib/UefiLib.inf    UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf[Components] 包内需要编译的inf路径[BuildOptions] 附加的编译选项

9、编写HelloUefiPkg.dsc文件:

[Defines]            PLATFORM_NAME      = HelloUefiPkg    PLATFORM_GUID      = 645dc7cb-fb24-4635-a062-a1ce306ea8e3    PLATFORM_VERSION    = 1.0    DSC_SPECIFICATION    = 0x00010005      SUPPORTED_ARCHITECTURES = X64      BUILD_TARGETS      = DEBUG|RELEASE|NOOPT[LibraryClasses]    UefiLib|MdePkg/Library/UefiLib/UefiLib.inf    UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf    DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf    PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf    BaseLib|MdePkg/Library/BaseLib/BaseLib.inf    PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf    BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf    RegisterFilterLib|MdePkg/Library/RegisterFilterLibNull/RegisterFilterLibNull.inf    MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf    UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf    DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf    UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf[Components]

10、HelloUefiPkg/HelloUefi.inf其中

编写HelloUefi.inf文件:

[Defines]    INF_VERSION    = 0x00010006    BASE_NAME      = HelloUefi    FILE_GUID      = ddc14bd1-9cd6-4206-a6e4-2284f299537b    MODULE_TYPE    = UEFI_APPLICATION    VERSION_STRING  = 1.0    ENTRY_POINT    = UefiMain  [Sources]              HelloUefi.c  [Packages]        MdePkg/MdePkg.dec  [LibraryClasses]        UefiLib        DebugLib        PrintLib        BaseLib        PcdLib        BaseMemoryLib        RegisterFilterLib        UefiApplicationEntryPoint        MemoryAllocationLib        UefiBootServicesTableLib        DevicePathLib        UefiRuntimeServicesTableLib

11、关于LibraryClasses如何选取没什么好的办法。当缺少导入库时会报错提示,如在inf与dsc中删除掉UefiRuntimeServicesTableLib,编译时的报错。

EDK2之Hello Uefi

此时在edk2中搜索报错中缺少的库就能找到其他dsc的导入代码,可以拿来用。

EDK2之Hello Uefi

12、随后修改ACTIVE_PLATFORM为HelloUefiPkg.dsc的路径,直接编译:

EDK2之Hello Uefi

编译成功:

EDK2之Hello Uefi

13、生成的文件在edk2BuildHelloUefiPkgDEBUG_VS2019X64HelloUefi.efi。

拷贝到上节课搭建的环境的文件夹下:

EDK2之Hello Uefi

14、进入fs0:EFI并执行HelloUefi.efi,可以看到输出了Hello UEFI。

EDK2之Hello Uefi

下篇文章介绍如何通过UEFI协议接口操作设备,实现修改分辨率与在屏幕中绘制图像,制作简易的开机动画。

EDK2之Hello Uefi

原文始发于微信公众号(锋刃科技):EDK2之Hello Uefi

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年1月31日20:38:40
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   EDK2之Hello Uefihttps://cn-sec.com/archives/2449831.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息