最近小看了一下SEC部分的code,现在来做个总结。所谓SEC就是CPU刚刚完成硬件初始化的是时候执行的和CPU体系架构息息相关的代码。主要是为后续CPU以及Chipset初始化代码所需的必备的环境做准备。大概总结了下有以下几个方面:
1.RestVector的初始化,以及异常向量的初始化
2.CPU工作模式的切换
3.Enable Memory mape PCI-E Config Space,RCBA,MCHBAR,GPIOBASE,PMBASE,HPEC,等
4.MicroCode的加载(可选)
5.侦测系统中的CPU的数量
6.初始化NEM(至此我们基本从渺无人烟的荒漠跳到了小绿洲了)
7.跳转到PEICore至此SEC阶段结束(继续在这片贫瘠的小绿洲上辛勤耕耘,亟待解救)
8.PEICore初始化内存(这次算是从绿洲迁移到土地肥沃富庶的中原地带了)
9.从PEI跳到DXECore(在核心的中原腹地大展拳脚,攻城略地)
10.从DXE历经BDS引导操作系统,交由OS来掌控大权。(功成身退,为避兔死狗烹,正式进行权利交接,BIOS退出历史舞台,到后台享清福去)
ResetVector:

      这里我们用一个intel的的BIOS ROM作为分析对象,ROM是从系统当中用RW读取的,当然你不需要读取所有的ROM文件,实际上SEC部分很小,
大概只有几百字节到几K的大小,用RW来读完全没有问题,当然你RU之类的工具也行,如果使用其他的一些工具能读回来整个ROM更好,或者如果你是一个BIOSREN的话完全可以打开你的source code来看,读取回来之后保存为BIOS.bin文件,然后就可以使用UE或者Notpadd来打开查看,这个bin档案是我们的CPU最终执行的二进制目标文件,我们可以在DOS下使用debug工具来进行反汇编,可以在没有源代码的情况下分析我们的CPU的第一条指令是如何执行的。具体的实现方法大概如下:
    1.使用RW来读取memory的0xfffffff0位置就像下面截图1一样,不过在做这个之前,下确认下你的主板的BIOS是否是UEFI的,本人的NB是intel的HM86,看了下是AMI Aptio的core这里仅仅以intel的板子为例,AMD的可自行研究,但是方法一样。上面的90 90就是CPU上电之后执行的第一条指令,可以查intel的文档,这两个字节其实是表示两条指令,NOP NOP意思是CPU什么也不做,等待两个指令周期。然后下一条指令是
E9
 C3F8 这里的意思是一条跳转指令,意思是JMP 0xF8C3,这是一条段内相对跳转指令,CPU只改变IP地址,不改变段地址。跳转的目标地址是:0xfffffff5+0xF8C3 =?这地址是多少,会算吗?这里有好几个陷阱需要我们注意:

1.JMP指令是基于当前的下一条地址往另外一个地址做段内跳转,所有是0xfffffff5
2.X86是小端模式,所以目标的偏移地址是0xF8C3,而不是0xC3F8
3.0xF8C3是一个负数,所以跳转地址是在0xfffffff5基础上往回跳,否则IP已经指向了0xfffffff5,再跳就跳出了4G的了(不知道的跳出去了,会发生什么异常)。
4.所以最终的结果是:0xfffffff5+0xF8C3 =0xfffff8B8
                                                                                    图1

下面2就是CPU完成了ResetVector跳转之后执行的第一条有意义的指令,我们通过查询inel的手册:FINIT指令(0xdb,0xe3)用来清除浮点数据寄存器栈和异常,初始化
FPU。为程序提供一个“干净”的初始状态。否则,遗留在浮点寄存器栈中的数据可能会产生堆栈溢出,至此的第一条指令的讲解到此为止。细节有再说。
                                                                                    图2
5.刚刚说完了第一条指令,下面来说重点SECCore。
    那么说了半天SECCore到底在哪里呢,其实刚刚我们看到的第一条指令就是SECCore的入口,经过刚刚的一番折腾其实我们已经进入到了SECCore,那么现在我们来看看真正的SECCore。这回还是使用RW。从下面的这张图可以看到在0xffffff60的位置有如下的一系列数字,这个看似无序的数字其实是有着特殊的意义的,相信高手一眼就能可能出端倪来。仔细看看能看到什么?没错这个从offset 00~FF其实是一个很特殊的数字,我们把他称之为top file GUID当然它还有一个更为官方的名字叫做Volume Top File (VTF),从这里开始到我们刚刚的ResetVector结束这一段所有的内容就是我们的SECCore,看起来很诡异是吧,其实不然,这个都是有文档规定的,细节可以参考intel的大叔们写的那一堆的文档。

6.接着往下看图3,Offset 10~17,这里是SECCore的FFS file header,意思是说,SECCore文件的校验和是(0xAA5e),文件是0x03(SECCore),属性是0x00(1 Byte对齐),文件大小是0xaa0字节,当前文件状态是0xF8(可查看相关文档具体信息);再往下就是offset 18~ 1b,这里表示FFS file section大小是0x0a44字节,Section类型是0x10(PE32类型),这里我们找到了第一个的FFS file section;如图4接着刚刚的步骤递归的往下找,我们可以找到第二个section在0xffffffbc的位置,其大小为0x44字节,类型为0x19(RAW类型),其实深究的话你会发现这个部分并不是我们的汇编语言编译产生的,而是在我们的代码编译完成之后使用特殊的工具来修改我们的SECcore代码,把这部分的二进制的文档强行插入进来的。然后修改部分的地址定位和文件大小的偏移。细看下底下的第二幅图4和最上面的图1是否有些相似,是的,其实这两个就是同一幅图,只不过是从不同的方式去找打他们并且读出来而已。
                                                                                    图3

                                                                                    图4

7.现在我接着看图3,来看下PE32 section里面有什么东西。
    我们先紧接着(6)来看,仔细看图3的Offset 1c~1d看能看到什么,“MZ”没错,这个就是传说中的幻数,说起这个幻数,我还查了一下资料,这是是MS的一位大叔Mark Zbikowski的名字的缩写,牛人就是牛人,让所有的KB的程序猿都记住他的大名了,更可恨的是这辈子咱们离不开它,你不用他还不行。看到了幻数我们就距离真相不远了,看下下面的数据结构,偏移量为0x3d的位置是0xB8(
e_lfanew),然后我们再看offset 0xB8的位置,看到了什么 "PE",没错看到了熟悉的字符,这个就表示这里是这个PE32 格式section的文件头,剩下的就是一些关于PE32/PE32+格式的一些头,大家可以自行研究,再附上一张图5展示PE的格式。方便进行之后的分析。
typedef struct {
  UINT16  e_magic;    // Magic number
  UINT16  e_cblp;     // Bytes on last page of file
  UINT16  e_cp;       // Pages in file
  UINT16  e_crlc;     // Relocations
  UINT16  e_cparhdr;  // Size of header in paragraphs
  UINT16  e_minalloc; // Minimum extra paragraphs needed
  UINT16  e_maxalloc; // Maximum extra paragraphs needed
  UINT16  e_ss;       // Initial (relative) SS value
  UINT16  e_sp;       // Initial SP value
  UINT16  e_csum;     // Checksum
  UINT16  e_ip;       // Initial IP value
  UINT16  e_cs;       // Initial (relative) CS value
  UINT16  e_lfarlc;   // File address of relocation table
  UINT16  e_ovno;     // Overlay number
  UINT16  e_res[4];   // Reserved words
  UINT16  e_oemid;    // OEM identifier (for e_oeminfo)
  UINT16  e_oeminfo;  // OEM information; e_oemid specific
  UINT16  e_res2[10]; // Reserved words
  UINT32  e_lfanew;   // File address of new exe header//偏移量为0x3d
} EFI_IMAGE_DOS_HEADER;

                                                                                    图5

今天就先到这里,觅食去,今天的第二顿,饿、饿、饿,之后在接着图5往下分析,尽请期待。

转载请注明出处
Cstyle.z.zhou@gmail.com  //  http://blog.csdn.net/CStyle_0x007

Cstyle的UEFI导读之SEC第一篇 Reset Vector的更多相关文章

  1. Cstyle的UEFI导读:第18.0篇 NVRAM的工作原理(上)

        虽有句话说的好,实用的东西记在脑子里.没有的记在笔记本上. 可是如今的信息量越来越大,并且随着时间的推移记忆力会越来越不可靠,所以仅仅好把近期工作之余看的一些东西记录下来,避免被迅速忘记.这里 ...

  2. Cstyle的UEFI导读:第20.0篇 IGD OpRegion interface && IGD OpRegion PROTOCOL

        ACPI IGD OpRegion interface是用SCI来实现IGD driver,OS,BIOS之间沟通的桥梁,IGD OpRegion PROTOCOL是UEFI BIOS构建桥梁 ...

  3. 从0开始搭建SQL Server AlwaysOn 第一篇(配置域控)

    从0开始搭建SQL Server AlwaysOn 第一篇(配置域控) 第一篇http://www.cnblogs.com/lyhabc/p/4678330.html第二篇http://www.cnb ...

  4. Python爬虫小白入门(四)PhatomJS+Selenium第一篇

    一.前言 在上一篇博文中,我们的爬虫面临着一个问题,在爬取Unsplash网站的时候,由于网站是下拉刷新,并没有分页.所以不能够通过页码获取页面的url来分别发送网络请求.我也尝试了其他方式,比如下拉 ...

  5. Three.js 第一篇:绘制一个静态的3D球体

    第一篇就画一个球体吧 首先我们知道Three.js其实是一个3D的JS引擎,其中的强大之处就在于这个JS框架并不是依托于JQUERY来写的.那么,我们在写这一篇绘制3D球体的文章的时候,应该注意哪些地 ...

  6. 深入学习jQuery选择器系列第一篇——基础选择器和层级选择器

    × 目录 [1]id选择器 [2]元素选择器 [3]类选择器[4]通配选择器[5]群组选择器[6]后代选择器[7]兄弟选择器 前面的话 选择器是jQuery的根基,在jQuery中,对事件处理.遍历D ...

  7. 【第一篇】ASP.NET MVC快速入门之数据库操作(MVC5+EF6)

    目录 [第一篇]ASP.NET MVC快速入门之数据库操作(MVC5+EF6) [第二篇]ASP.NET MVC快速入门之数据注解(MVC5+EF6) [第三篇]ASP.NET MVC快速入门之安全策 ...

  8. Android基础学习第一篇—Project目录结构

    写在前面的话: 1. 最近在自学Android,也是边看书边写一些Demo,由于知识点越来越多,脑子越来越记不清楚,所以打算写成读书笔记,供以后查看,也算是把自己学到所理解的东西写出来,献丑,如有不对 ...

  9. 深入理解ajax系列第一篇——XHR对象

    × 目录 [1]创建对象 [2]发送请求 [3]接收响应[4]异步处理[5]实例演示 前面的话 ajax是asynchronous javascript and XML的简写,中文翻译是异步的java ...

随机推荐

  1. 欢迎使用 Markdown 编辑器写博客

    本Markdown编辑器使用StackEdit修改而来,用它写博客,将会带来全新的体验哦: Markdown和扩展Markdown简洁的语法 代码块高亮 图片链接和图片上传 LaTex数学公式 UML ...

  2. 用layer添加UIView的动画

    项目有时会遇到用UIView 添加动画的情况,这里我觉得在layer上添加动画比较好,因为可以详细地设定动画属性,方便理解 下面是一个旋转动画: -(void)roundBtnAction:(id)s ...

  3. Vijos1865 NOI2014 魔法森林 LCT维护生成树

    基本思路: 首先按照weightA升序排序,然后依次在图中加边,并维护起点到终点路径上weightB的最大值 如果加边过程中生成了环,则删除环中weightB最大的边 由于是无向图,点之间没有拓扑序, ...

  4. POJ3285 River Hopscotch(最大化最小值之二分查找)

    POJ3285 River Hopscotch 此题是大白P142页(即POJ2456)的一个变形题,典型的最大化最小值问题. C(x)表示要求的最小距离为X时,此时需要删除的石子.二分枚举X,直到找 ...

  5. laravel5通过auth.attempt事件加入登陆验证码

    <?php namespace WangDong\Http\Controllers\Auth; use Illuminate\Http\Exception\HttpResponseExcepti ...

  6. iOS 获取项目名称及版本号

    可用于版本让用户手动检测是否有版本更新可用. NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];  CFSho ...

  7. ubuntu 实现界面切换

    1.按ALT+CTRL+F1切换到字符界面(Linux实体机) 如果是VMware虚拟机安装的Linux系统,则切换到字符界面的时候需要以下操作 按下ALT+CTRL+SPACE(空格),ALT+CT ...

  8. 提供进销存、ERP系统快速开发框架源码 (C#+SQL)

    C/S系统开发框架-企业版 V4.0 (Enterprise Edition) 简介: http://www.csframework.com/cs-framework-4.0.htm 视频下载: 百度 ...

  9. python学习的一些感悟

    首先声明,这里用到的库是在coursera上学习时,老师建立的一个库 #timer import simplegui import random # global state message = &q ...

  10. 如何把iOS代码编译为Android应用

    新闻 <iPhone 6/6 Plus中国销量曝光:单月销量650万>:据iSuppli Corp.中国研究总监王阳爆料,iPhone 6和iPhone 6 Plus在国内受欢迎的情况大大 ...