UEFI——保姆级教程的HelloWold Application

HelloWorld Application

  • 前言
  • 为什么是HelloWorld
  • Application又是什么
  • 代码部分
    • test_application.c文件
    • test_application.inf
    • 编译运行
  • 总结

前言

毕业之后工作开始接触UEFI,现在为止也不过短短的四个月,UEFI开发涉猎面广,知识体系庞杂,参考文献却相对少的可先,所以在此将自己学习过程中一些问题、成果、问题、经验进行一个记录,一来方便自己的复习,二来能给一些入坑的伙伴一点方向。
我自己磕磕绊绊,发现书、经验贴上的知识都是高屋建瓴,很少从基础一点一点说起,让我摸不到头脑,因此我从最简单的地方一点一点把初学者可能遇到的问题写下来,帮助大家少走弯路。

为什么是HelloWorld

我本人是从C++语言转到这个方向,不能说毫不相关,只能说关系不大。UEFI中主要使用的还是C语言,但这不是主要的问题,我觉得从我的角度出发,对于一个UEFI的初学者,理解UEFI整个过程中的概念、流程才是最难的。
通过网上的资料我们能够很容易的知道UEFI是OS前的一个过程,相当于传统BIOS的替代品或者说是优化版本。但是又有几个人能够详细的说明白传统BIOS在OS前是怎么工作的?可能对于大神很容易,但是对我,这个问题很难。所以我更加不能理解UEFI的详细内容。Lucky,经过这几个月,我想明白了,我可以慢慢的去理解具体的结构,转而把实践放在第一位,遇到问题之后再去解决研究可能效果更好。
在学习C、C++语言的时候,我们写的第一个程序一般就是HelloWorld,简单的一句HelloWorld,向我们展示了程序的魅力,更重要的是,直观的展现了Code与Cout的关系。听别人说代码很抽象,但是如果自己能够在代码上进行修改,比如把HelloWorld改成干啥呢 老铁,然后在屏幕上观察两次输出的不同就非常的直观。按照这个思路,我选择了HelloWorld作为自己学习UEFI的第一个小目标:在屏幕上输出自己的HelloWorld

Application又是什么

如果现在你一定要让我解释清楚什么是UEFI中的Application模块,那我只能说一声打扰了。对于Driver、Application这种划分,目前我自己也是迷迷糊糊,因此,也不敢在此胡言乱语。但是为了能够让初学的人理解,我还是想用我自己的方式介绍一下,此处纯属个人理解,不保证正确性,如有错误请见谅。
首先,前面已经说了UEFI的过程细节我并不全部了解,但为了不影响后续的学习和说明,我将整个UEFI过程进行了一句话概括:UEFI就是为OS创造完备运行环境的准备阶段。也就是说,UEFI运行完成之后没就算没有进入传统的OS比如Windows、Linux,也能够通过某种方式进行类似操作系统的各种操作——最简单的操作就是输入输出。
UEFI的大牛们已经贴心的为我们准备好了UEFI Shell(把他想象成基于UEFI的OS),我们就可以在UEFI Shell下面安装自己的Application,并且让自己的Application执行相应的功能。这样是不是容易理解了?UEFI Application 就是 基于UEFI Shell的能够执行任务的Application(相当于OS下的软件)。Application加载的过程就可以看成是软件运行的过程,Application运行的结果就是软件执行的结果。Ok?

注意:本节的解释只是为了容易理解,和实际UEFI的运行无关!!!

代码部分

说了这么多,可能你也是蒙圈的,是的,刚开始学的我也是,那既然不明白,不如直接上Code。前面已经说过了UEFI 是C语言主打,那么我们就从.C文件开始。

test_application.c文件

代码直接上

#include <Uefi.h>EFI_STATUS
EFIAPI
Test_Application_Entry (IN EFI_HANDLE        ImageHandle,IN EFI_SYSTEM_TABLE  *SystemTable
){SystemTable->ConOut->OutputString(SystemTable->ConOut,L"HelloWorld\n");return EFI_SUCCESS;
}

上面就是想要输出HelloWorld的最简单的C代码。代码很简单核心只有一行,但是对于啥也不懂的新人(比如我),刚刚开始学的时候可能就要发问了 EFI_SYSTEM_TABLE 表示什么啊?EFI_HANDLE表示什么啊?SystemTable是什么样子的啊?我现在告诉你,作为一个新人,你不需要知道的非常详细,你需要知道的就是如下几点:

  1. 这是一个入口函数,这种函数的开头和结尾是固定的格式,UEFI Application的入口函数都必须这么写。
    格式模板:
EFI_STATUS
EFIAPI
FunctionName(IN EFI_HANDLE        ImageHandle,IN EFI_SYSTEM_TABLE  *SystemTable
){//Code Bodyreturn EFI_SUCCESS;
}
  1. UEFI Application的C代码都必须包含 <Uefi.h>文件。这个文件定义了最最基础的结构,是整个UEFI程序搭建的基础。
  2. SystemTable->ConOut->OutputString(SystemTable->ConOut,L"HelloWorld\n");是Application中输出的固定语句,将想要输出的内容进行替换即可。(替换哪里不需要说吧)

掌握了以上三点,本片文章C代码部分的精髓你就已经掌握了。

test_application.inf

在UEFI的开发中,会看到众多的文件格式,包括但是不限于:.c .h .sdl .inf .dec .dsc .fdf .sd,涉及到的我们在一个一个的忽悠你 解释。本篇文章中除了.c文件外需要自己编写的文件就是.inf文件。
.inf(Module Information File)文件是模块挖个坑,后面写文章总结这些个用语)的工程文件,其作用相当于Makefile文件或者VisualStudio的.proj文件1。一句话概括就是:.inf文件是告诉编译器模块可能使用的其他模块以及本模块的基本情况。
上代码:

[Defines]INF_VERSION                = 0x00010015BASE_NAME                  = Test_ApplicationFILE_GUID                  = 16BEFBED-60DC-4EA2-8E81-A3430A6C2117MODULE_TYPE                = UEFI_APPLICATIONVERSION_STRING             = 1.0ENTRY_POINT                = Test_Application_Entry[Sources]test_application.c[Packages]MdePkg/MdePkg.dec[LibraryClasses]UefiApplicationEntryPoint

从上面的,Code可以看出,.inf[Name]为分界分成不同的块,[Name]表示块的名称,块名独占一行才能生效。上述四个块是每一个.inf必须的块,还有一些非必须的块,用到再说。先解释上面四个块的情况:

  1. Defines块
    下面是Application的Defines块模板。
[Defines]INF_VERSION                = 0x00010015      BASE_NAME                  = XXXXXFILE_GUID                  = XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX  (8-4-4-4-12格式)MODULE_TYPE                = UEFI_APPLICATIONVERSION_STRING             = 1.0ENTRY_POINT                = XXXXX

INF_VERSION 版本号 ,不赘述
BASE_NAME 表示本模块的名字,最后输出的.efi文件也是这个名字
FILE_GUID GUID是一个唯一的标记,通过这一串唯一的标记可以找到对应的模块,想象成人的身份证就比较容易理解了。
MODULE_TYPE Application的时候必须这么写。其他情况遇到再说
VERSION_STRING 不重要 1.0就行
ENTRY_POINT 本模块的入口函数的名称,就是.c文件中函数体的名称

  1. Sources 块
    这部分相对简单,只需要写出本模块使用到的相关文件就行。

  2. Package 块
    使用相对路径写出使用到的包的对应.dec文件。
    我们用到了 <Uefi.h>文件,这个文件在MdePkg下,所以引用对应的 .dec文件。

  3. LibraryClasses块
    描述本模块使用的库。所有的Application都要连接UefiApplicationEntryPoint库 ,写上就完事。

以上涉及的很多名词三言两语解释不清楚,本篇文章需要的知识已经说明或者强加给了读者,详细规范的整理可能需要等我学习后写了。

编译运行

(如果你还没有完成基本的环境安装、配置等,可以参考安装教程先将环境进行配置。)
需要的基本代码已经编译完成,接下来就是如何在UEFI Shell上让这个Application运行起来。
在此之前还需要进行一步操作,将test_application.inf文件添加到MdeModulePkg的.dscComponent部分。
添加到Component处
注意了,我添加在MdeModulePkg的.dsc是因为我将这个文件夹放在了MdeModulePkg下面,如果你不是,请在对应文件夹的.dsc文件夹下添加。

为了说明文件夹的关系,这里放个插图:
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

接下来就可以进行编译了。
我用的是Windows系统,具体的过程如下:

  1. 在命令行窗口打开Code所在文件夹,执行edksetup.bat --nt32
    在这里插入图片描述
    执行完毕结果如图(Warning忽略即可):
    在这里插入图片描述

  2. build编译
    在这里插入图片描述

  3. 启动模拟器 执行命令加载Application
    我的模拟器位置:D:\MyWorkSpace\Build\NT32IA32\DEBUG_VS2013x86\IA32\SecMain.exe
    请大家按照自己文件的位置找模拟器
    启动后就会出现如下三个界面:
    在这里插入图片描述
    加载中(两个一样的):
    在这里插入图片描述
    加载完成(两个一样的):
    在这里插入图片描述

  4. 执行命令 运行Application
    这个地方实际上是Shell加载了生成了.efi文件(文件名与BASE_NAME 一致),最后输出对应的结果。最终结果如图。
    在这里插入图片描述

总结

本片文章主要就是手把手的教你写一个基于UEFI的HelloWorld,以此打消新手对UEFI的恐惧,让菜鸟们知道UEFI 和其他的各种代码一样是从HelloWorld起步的,让小白不至于两眼一抹黑。第一次写博客难免有疏漏不足,欢迎指正,也希望有更多志同道合的伙伴一起交流。
文末了 ,我要着重感谢几个CSDN上的大佬 @Hi,Hubery @jiangwei0512,感谢他们在我学习道路上的帮助。最后 感谢@我是管小亮 一路以来的支持和陪伴


  1. 参考来源:UEFI原理与编程(戴正华著) ↩︎

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/354194.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

云南省工信厅洪正华一行莅临红谷滩区·高通中国·影创联合创新中心考察调研

9月9日上午&#xff0c;国内首个XR(扩展现实)产业联合创新中心自开业后&#xff0c;迎来首批参观领导。云南省工信厅党组书记、厅长洪正华&#xff0c;云南省工信厅党组成员、副厅长袁国书&#xff0c;云南省工信厅综合处处长薛贵辉&#xff0c;云南省工信厅发展规划处处长王兵…

UEFI Protocol

一、概述 二、Protocol的定义 1、Protocol是服务器端和客户端之间的一种约定&#xff0c;在软件编程上称为接口&#xff0c;服务器端和客户端通过这个约定信息的互通。 2、服务器端和客户端在UEFI中都是可执行的二进制文件。 3、为了实现这些二进制文件之间的互通&#xff0c;…

UEFI原理与编程(二):UEFI工程模块文件-标准应用程序工程模块

UEFI 工程模块文件-标准应用程序工程模块 前言 在EDK2环境下编程之前&#xff0c;先介绍EDK2的两个概念模块(Module)和包(Package).   “包”是一组模块及平台描述文件(.dsc文件)、包声明文件(.dec文件)则、组成的集合&#xff0c;多在以*pkg命名的文件夹中&#xff0c;一般…

如何理解UEFI的事件机制(三)——时钟中断

一&#xff0c;时钟中断概述 UEFI 中的EVENT是使用时钟中断来驱动的。 在时钟中断处理函数中&#xff0c;它会检查系统中的定时器事件并处理到期的定时器事件&#xff0c;并在合适的时机调度事件的Notify函数&#xff0c;是事件的实现基础。时钟中断在DXE的主函数DxeMain中初始…

UEFI原理与编程(七):包及.dsc、.dec、.fdf文件

包及.dsc、.dec、.fdf文件 前言 前面的文章中比较详细介绍了UEFI工程文件即.inf。UEFI的包中一般都会包含一个.dsc文件和一个dec文件。在包生成固件Image、Option Rom Image&#xff0c;这个包还要包含.fdf文件。.fdf用于生成固件Image、Option Rom Image或可以启动Image。 b…

UEFI学习——在qemu上读取设备PCI信息

1.编写读取设备PCI信息的Application 代码参考罗斌大佬&#xff0c;博客地址&#xff1a;UEFI开发探索13 – 访问PCI/PCI-E设备1 感谢罗斌大佬的贡献&#xff0c;让我在学习UEFI的道路上站在了巨人的肩膀上。 代码&#xff1a; #include <Uefi.h> #include <L…

UEFI开发与调试---ImageHandle和ControllerHandle

##1.ImageHandle 每个uefi module都是一个image&#xff0c;而每个image对应都有一个ImageHandle&#xff0c;其实ImageHandle的类型就是EFI_HANDLE typedef VOID *EFI_HANDLE;因此实际上每个ImageHandle是一个void*指针&#xff0c;那么也就是说任何结…

UEFI的诞生与优势

UEFI的诞生 随着CPU及其他硬件设备的技术革新&#xff0c;CPU和操作系统已支持到64位&#xff0c;而BIOS却还停留在16位&#xff1b;主板上更加丰富多样的扩展设备&#xff0c;也让BIOS愈加无能为力&#xff0c;使得硬件无法完成初始化。现实表明&#xff0c;BIOS已经无法满足…

UEFI shell - 标准应用程序的编译和加载过程

一、标准应用工程编译 首先了解下,应用程序是怎么被编译成.efi文件: UefiMain.c首先被编译成目标文件UefiMain.obj连接器将目标文件UefiMain.obj和其他库连接成UefiMain.dllGenFw工具将UefiMain.dll转换成UefiMain.efi 说明:连接器在生成UefiMain.dll时使用了/dll/entry:_Mo…

UEFI开发,记录第一场胜利——调用一个自己编写的protocol

本文参考BIOS/UEFI基础——Protocol介绍 大四第一个签三方的工作&#xff0c;BIOS的开发&#xff0c;第一次接触这个领域&#xff0c;在实习之前很好奇&#xff0c;也很有兴趣&#xff0c;但是学习BIOS在一开始注定要碰多次碰壁&#xff0c;实习第三周第二天&#xff0c;终于写…

linux系统nohob安装,Linux启动详解1

一、固件运行 本部分主要参考 戴正华 著《UEFI原理与编程》 CPU在加电后会进入16位实模式状态运行&#xff0c;同时CPU的逻辑电路设计为加电瞬间将CS的值设置为 0xF000、IP的值置为0xFFF0&#xff0c;这样CS&#xff1a;IP就指向0xFFFF0这个地址位置。然后开始执行固件 固件的执…

《UEFI原理与编程》读书笔记

《UEFI原理与编程》读书笔记 读书笔记仅摘取对个人有用的部分&#xff0c;详细内容请阅读原著 目前更新至第七章&#xff0c;因个人仅需要引导程序&#xff0c;故其余部分未介绍&#xff0c;详细内容请阅读原著 书及其资料均已放置在本人资源中&#xff0c;如需下载请移步资源模…

UEFI简介

前言 大多数人接触UEFI都是在PC的应用场景上&#xff0c;有在PC上安装过多操作系统的经历的同学&#xff0c;通常会进入UEFI界面设置操作系统引导顺序、CPU虚拟化等设置。UEFI诞生之初也确实是作为BIOS的替代者&#xff0c;主要应用在PC电脑上。随着手机/平板等移动设备的发展&…

10月书讯(上) | 小长假我读这些新书

华章科技提前祝大家国庆快乐 7天小长假&#xff0c;正是读书好时节 又到上新季&#xff0c;读书与休假更配哦 10月书讯&#xff08;上&#xff09;请查收 快来看看哪本书最属你心意 参与文末赠书活动&#xff0c;好书就要抢先读 — 新书速览 — 1、《计算机系统解密&#xff1a…

UEFI启动流程浅析

BIOS启动流程 SEC&#xff08;Security Phase&#xff0c;安全阶段&#xff09;阶段 SEC阶段是平台初始话的第一个阶段&#xff0c;计算机系统加电后首先进入这个阶段。 CPU上电之后&#xff0c;首先会进行硬件初始化&#xff08;hard reset&#xff09; 其次会进行可选的自检…

UEFI规范实现EDKII项目学习笔记绪论[0]

UEFI规范实现EDKII项目学习笔记绪论[0] 2015-07-10 北京海淀区 张俊浩 这段时间在学习UEFI( Unified Extensible Firmware Interface,统一的可扩展固件接口)&#xff0c;熟悉EDKII&#xff08;EFI Developer KitII&#xff0c;EFI开发工具包&#xff09;项目&#xff0c;…

3.UEFI-edk2 增加中文显示

UEFI-edk2源码中默认只有英文和法文的字库&#xff0c;在UI界面上或者shell终端打印中文字符串&#xff0c;则无法显示。例如&#xff0c;上一篇博客中的TestoneApp.cpp中&#xff0c;增加一行带中文字符串的打印&#xff1a; Print(L"Hello, world!\r\n");Print(L&…

UEFI原理与编程(一)

第一章 UEFI概述(Unified Extensible Firmware Interface 统一的可扩展固件接口) 常见缩写及描述&#xff1a; 缩略词全名描述UEFIUnified Extensible Firmware Interface统一的可扩展固件接口BSBoot Services启动服务RTRuntime Service运行时服务BIOSBasic Input Output Sys…

UEFI学习——事件函数WaitForEvent和CreateEvent/CreateEventEx

本文参考戴正华《UEFI原理与编程》 1.等待事件的服务WaitForEvent 启动服务中的WaitForEvent服务的函数原型&#xff1a; /**等待Event数组内任一事件被触发retval EFI_SUCCESS 下表为*index的事件被触发retval EFI_UNSUPPORTED 当前的TPL不是TPL_AP…

开宗明义—UEFI介绍 (二)

UEFI介绍 声明 上一篇介绍了UEFI的发展历史&#xff0c;以及对UEFI在ARM嵌入式领域的生态状况做了简单的调研。本篇旨在对UEFI规范和PI规范的内容以及二者之间的关系做一个简单的梳理。 本篇参考内容主要来源于以下3方面&#xff1a; (1) 微信公众号“ Wolf UEFI社区 ”系列文章…