我们首先先看一些UEFI 的框架图:

无论是从功能划分还是各个文件划分,我们都可以看到这种模块话思想。模块话是现在软件的主流,这样能让不同的人独立开发自己的模块,通过统一的接口添加整合到一个firmware file里。

我们uefi firmware 模块,是通过几个core 联系到一起的,这几个core 包括(SEC core, PEI core, Dxe core, SMM core)。如果单单从软件角度讲想学习UEFI 架构,那么这几个core 是很值得学习的,因为他们说架构核心。当然这是指软件方面的,因为还有各种外围设备,总线协议,等等要去学习或者了解。

在uefi 世界里,efi 文件我们是不会陌生的,这些文件就是围绕各种core 身边然后组成一个完整uefi firmware 。所以也有必要了解一下efi。efi 文件就是一个小的module ,是一种可执行文件类型。比如Microsoft PE/COFF , Linux EFL 等等。这些可执行文件类型都有相似之处,应为都是同一种文件类型发展演化出来的。
efi 文件里面包的文件类型可能是PE32, TE(精简版PE), PE32+中的一种。efi 文件作为可以被动态载入然后被执行,那么其中的文件类型可以选择linux 下.so 和 windows .dll。 相比so 文件,dll 文件重定向更简单,效率可能会高点,但是dll 会比.so 文件占用更多的空间。intel 选择了dll 文件类型,可能有他们的考量吧。

介绍EFI 这种能被动态load 然后还能被执行的image 来讲,我们首先先来热身一下,通过一个例子,我们可能会比列出各种spec ,贴代码强多了。通过例子来思考可能会有带入感,再去看spec,就会很有感觉。

  1. 我们首先先实现一个c 程序a.c 和一个经过编译过的可执行文件b.bin。在a.c 里去动态加载到内存里,然后把控制权交给b.bin

这个问题首先我们是要练习如果在一个程序里去加载另外的程序并执行它,所以我们不考虑增加线程或者进程去实现它。

下面是我的实现思路(linux )

  1. 这个linux 下比较好实现,其实windows 下思路一样,只不过函数名字不一样而已。linux 有一个mmap函数它会把其他文件映射到当前进程的虚拟空间里。并且映射的地址空间可以设置成可读,可写,可执行。所以知道这个mmap function 其他就迎刃而解了。下面是伪代码:
//a.c
handle = open(b.bin)
// address 是映射文件到内存返回的虚拟地址
address = mmap(handle,可读,可写,可执行)
//把控制权交给b.bin
jmp/call  address
--------------------------------
b.c
// b.bin 就是一个打印hello world 的可执行文件
char str[] = "hello world\n"
write (4, 1, str, strlen(str));
  1. 思路就是这样,看起来a.c 不难,b.c 更是简单,但是把这两个合在一块能在屏幕上打印一个hello world 还是有点细节要注意的。(赶紧去写一个吧,看看能不能打印出来)。

  2. 如果自己写的执行有点问题可以接着往下看看,我直接就贴代码了。

.section .data
output:.asciz "Hello World\n"
length:.int .-output.section .text
.global _start
_start:movl $4, %eaxmovl $1, %ebxmovl $output, %ecxmovl length, %edxint $0x80movl $1, %eaxmovl $0, %ebxint $0x80
; 这个就是那个只打印hello world 的源文件 hello.s,
; 这里是用的汇编调用int 0x80 的function 4 也就是 write。

编译hello.s :
as hello.s -o hello.o
ld hello.o -T test.ld -o hello.elf
objcoby -j .text -O binary hello.elf hello.bin
第一条,把hello.s 编译成目标文件hello.o
第二条,把hello.o 链接成一个可执行的文件hello.elf 其中test.ld 是我写的一个链接脚本主要是把链接的的Section 从0 地址开始,并且把数据段和代码段合并成一个Segment。
第三条, 主要是避免还得多了解elf 文件格式而浪费时间,我这边只输出一个没有文件格式的可执行文件.bin (当然在linux 下也可以用nasm 去编译,会省去第二条和第三条)

hello.s 还是很简单的,但是有一个细节地方

movl $output, %ecx

这句话意思是把output 的地址给到ecx寄存器,那么问题来了,当我们编译的时候这个地址编译器会用0x00000000先代替,链接的时候链接器会根据代码实际地址进行修正。链接器是如何知道哪个地方要修正?修正成多少?
第一个问题,链接器会根据目标文件里的可重定向表,去修正要重定向的值。
第二个问题,修正成多少(这里有很多规则,不详细讲解,具体请参考elf 文件相关文档),简单理解是由链接器决定的,配置的话可以下参数,也可以写一个链接器脚本(相当于我们.fdf 文件)

先来看一下hello.s 汇编之后的目标文件

我们可以看到代码段a 行,f 行,那两段给寄存器填的值都是0,也就是说这两个值是要重定向的。我们也看一下重定向表长啥样:

这张图,我们可以看到编译器要告诉它人,.text 需要重定向,两个地方,分别是.text 段偏移0x0b 位置,和 0x12 的位置,填什么值,后面VALUE 字段有讲。

于是乎,链接器知道哪里需要修改了,好了它去执行链接(这篇文章例子是用的静态链接,linux 动态链接因为和主题无关,略去),看看静态链接之后可执行文件长什么样。

看到了a,f 行,分别给寄存器的值修正成0x24,和0x31, 因为我们编译的时候把base address 设成0 了。仔细一想,我们如果把hello.bin 在a.c 里load 到虚拟地址0开始的位置,那么这段代码就不用修正(这叫固定加载,之后看efi 加载的时候会看到,固定下载相关的代码)。但是这样只能load 在固定位置显示不太合理。所以我们还得手动修改a,f 行的修正值,举例,如果我们的hello.bin被load在0x10000处,那么output地址0x10024,
length 地址就是0x10031,我们的任务就是让代码段偏移0x0b,0x12地方的里值 + 0x10000。(这个例子就和uefi 代码里load efi image 的时候很像了,如果这个例子弄明白,关于efi 文件加载,执行,估计只要贴两个图,就明白怎么回事了,根本不用看代码翻spec,信不?)

主要分析过程结束。看看代码的执行结果

hello.bin 被load 在虚拟地址0x50000000 位置,我们看看0x0B 和 0x12 位置被修改成了0x50000000 + 0x24和0x50000000 + 0x31, 最后打印出hello world。

代码链接:
app

UEFI 文件类型.efi相关推荐

  1. 不限文件类型的ftp服务器,ftp服务器文件类型

    ftp服务器文件类型 内容精选 换一换 在SAP系统中,如果选择共享文件系统由SFS Turbo而非NFS Server提供时,例如SAP HANA中的Backup卷或者Shared卷,您需要创建SF ...

  2. 服务器同步什么文件类型,不同服务器同步文件类型

    不同服务器同步文件类型 内容精选 换一换 通过注册镜像操作,将外部镜像ISO文件注册为云平台的私有镜像,即ISO镜像.注册镜像前,需先将ISO文件上传到OBS桶中.如果制作的是鲲鹏服务器镜像,&quo ...

  3. 第五课:系统目录及ls·文件类型及alias命令介绍

    1.上过一次我们学习了单用户和救援模式及服务器秘钥登录等操作,而我们最终的目的还是要操作和使用linux系统,所以我们今天先初步学习linux的基本命令如下: 一·目录介绍        ls命令介绍 ...

  4. mysql文件头标记_通过文件头准确识别PHP上传的文件类型 ( 一 )

    /** * 通过文件名,获得文件类型* * @version 0.1 * $filename="d:/1.png";echo cFileTypeCheck::getFileType ...

  5. 云计算Python自动化运维开发实战 三、python文件类型

    为什么80%的码农都做不了架构师?>>>    云计算Python自动化运维开发实战 三.python文件类型 导语: python常用的有3种文件类型 1. 源代码     py ...

  6. 2.1/2.2 系统目录结构, 2.3 ls命令, 2.4 文件类型, 2.5 alias命令

    2019独角兽企业重金招聘Python工程师标准>>> 一.系统目录结构 ls / 查看根下面的文件 [root@linux-128 ~]# ls / bin dev home li ...

  7. 2.1/2.2 系统目录结构 2.3 ls命令 2.4 文件类型 2.5 alias命令

    2.1 系统目录结构 1.系统目录 ssh的配置文件存放位置 [root@wangborambo ~]# ls /etc/ssh/sshd_config /etc/ssh/sshd_config 根下 ...

  8. Windows注册文件类型信息的学习心得

    前一阵做系统注册文件类型图标的提取工具,本来以为使用SHGetFileInfo()函数只能获取指定文件名的图标,没想到还能获取指定扩展名关联的图标,因此绕了一个大弯路去研究注册表.虽然花费了很多时间, ...

  9. 根据文件头数据判断文件类型

    现有一文件,其扩展名未知或标记错误.假设它是一个正常的.非空的文件,且将扩展名更正后可以正常使用,那么,如何判断它是哪种类型的文件? 在后缀未知,或者后缀被修改的文件,依然通过文件头来判断该文件究竟是 ...

  10. 系统目录结构文件类型及ls.alias命令

    一.系统目录结构 root,为root用户的家目录 bin(sbin),存放常用命令,如ls tree man vi mkdir sbin下命令普通用户无权限使用 boot存放系统启动相关文件(不要误 ...

最新文章

  1. RTP timestamp与帧率及时钟频率的关系
  2. pandas mysql主键_使用Autoincrement将Pandas Dataframe插入MySQL表自动生成主键
  3. 微软正式发布Azure Storage上的静态网站
  4. Optimal Strategy 组合数,dp,博弈论(济南)
  5. Git之深入解析48个经典操作场景的分析和处理,专治不会合并代码
  6. 单独获取ShopEx商品类型中的扩展参数,如配货时间
  7. SAP云平台上的ABAP编程环境能做哪些事情
  8. PM2.5空气质量指数(AQI)是如何计算的
  9. 为什么[]比list()更快?
  10. MATLAB中的柱面与球面
  11. 怎么看微信公众号开发文档-微信开发教程14
  12. 【目标检测】《DINO: DETR with Improved DeNoising Anchor Boxes for End-to-End Object Detection》论文阅读笔记
  13. 虚拟云服务器能调用本地摄像头,云服务器本地摄像头
  14. ArcGIS导入xyz序列并绘制地形图(含等高线、面体积、点距离的计算)
  15. 区块链概念及简单介绍
  16. Android自定义控件开发入门与实战(7)SVG动画,android底层架构
  17. Linux——设置汉字拼音输入法
  18. matlab 图像输入/显示等
  19. JMeter 基本身份验证
  20. 区块链在游戏产业掀起狂潮

热门文章

  1. 应届生从头脑风暴到游戏策划案的个人思路(二)
  2. gedit文本编辑器
  3. Android加速球、360加速球
  4. 【Python】基于Python的百度迁徙(2020年10月21日更)
  5. 对C语言指针的学习与理解
  6. Android Json解析工具类
  7. OpenCV算法精解1--OpenCV中C++基本操作1
  8. 在Vue项目中引入 ECharts 3D 路径图 Flights GL(需安装echarts、echarts-gl、jQuery依赖,已踩坑)
  9. DataSet用法详细 转
  10. 计算机网络——数据包抓取与分析