GRUB2 分析 (三)
接上一篇
从地址0x8200开始的是lzma_decompress.img。这是由startup_raw.S编译生成的。这个文件稍微复杂点。首先一开始就是个跳转指令:
ljmp $0, $ABS(LOCAL (codestart)) /* 机器码:ea 1c 82 */
跳转到0x821c,这里是真正的开始代码。0x8203到0x821b之间存放的是一些特殊数据,如压缩数据前后的长度、冗余数据的长度等,由GRUB安装时填写,后面会用到。
接下来设置实模式堆栈后,切换到保护模式:DATA32 call real_to_prot
然后打开Gate A20,即第21根地址线的控制线: call grub_gate_a20 这是在80286时代IBM想出来的通过开闭Gate A20来兼容8086/8088实模式的方法。在保护模式下,为了正常寻址必须把Gate A20打开。
然后开始利用里德-所罗门(Reed Solomon)算法对GRUB受保护数据进行检查和修复:
call EXT_C (grub_reed_solomon_recover)
RS恢复代码是用C写的,文件是lib/reed_solomon.c。编译时会先编译成rs_decoder.S然后被startup_raw.S包含。(最新的GRUB版本应该生成的文件名是rs_decoder.h,只是改了个名字。)
RS保护的范围以reed_solomon_part标记开始(Gate A20代码后,多重启动代码前),到lzma_decompress.img结尾,再到后面接着的压缩过的kernel.img映像结尾。在此后面是冗余数据区。冗余数据是被算法利用对受保护数据进行修复的。
这样算来GRUB数据的前5个扇区(0-4)以及部分第6个扇区是不受保护的,其他都受到了保护。
为什么要做这件事情?如之前提到的,硬盘2-62号扇区是不安全的,有可能被其他软件写入数据破坏。利用冗余数据,GRUB有能力从这种破坏中正常引导,如果破坏的数据量在可接受范围内的话。我记得GRUB社区有一场讨论,关于如何处理与其他软件冲突的问题。就像一场罗马元老院辩论一样,有人忿忿不平,觉得这种在保留扇区写隐藏数据的行为是邪恶的,GRUB应该以牙还牙,数据恢复过来后,就应该写回硬盘,虽然这会造成其他软件不能工作。也有人认为,普通用户并不会理解这里面的是非曲折,而把一切问题怪罪到GRUB头上,GRUB应仅仅支持防御性的操作。
RS恢复操作执行完后跳转到标记post_reed_solomon对余下的压缩过的kernel.img进行解压缩:
jmp post_reed_solomon /* 偏移量:0x07a6,不同版本会有差异 */
解压后的数据存放在地址0x100000开始的内存区域。
解压算法采用LZMA算法。具体实现在lzma_decode.S中,是手工优化精简的版本。
最后执行跳转指令:
jmp *%esi /* GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR = 0x100000 */
跳转到地址0x100000执行下一条指令。也就是刚才解压缩出来的第一条指令。
至此startup_raw.S执行完毕。
GRUB2 分析 (三)的更多相关文章
- tomcat源码分析(三)一次http请求的旅行-从Socket说起
p { margin-bottom: 0.25cm; line-height: 120% } tomcat源码分析(三)一次http请求的旅行 在http请求旅行之前,我们先来准备下我们所需要的工具. ...
- 一些有用的javascript实例分析(三)
原文:一些有用的javascript实例分析(三) 10 输入两个数字,比较大小 window.onload = function () { var aInput = document.getElem ...
- Java线程池ThreadPoolExecutor使用和分析(三) - 终止线程池原理
相关文章目录: Java线程池ThreadPoolExecutor使用和分析(一) Java线程池ThreadPoolExecutor使用和分析(二) - execute()原理 Java线程池Thr ...
- 使用react全家桶制作博客后台管理系统 网站PWA升级 移动端常见问题处理 循序渐进学.Net Core Web Api开发系列【4】:前端访问WebApi [Abp 源码分析]四、模块配置 [Abp 源码分析]三、依赖注入
使用react全家桶制作博客后台管理系统 前面的话 笔者在做一个完整的博客上线项目,包括前台.后台.后端接口和服务器配置.本文将详细介绍使用react全家桶制作的博客后台管理系统 概述 该项目是基 ...
- Nouveau源代码分析(三):NVIDIA设备初始化之nouveau_drm_probe
Nouveau源代码分析(三) 向DRM注冊了Nouveau驱动之后,内核中的PCI模块就会扫描全部没有相应驱动的设备,然后和nouveau_drm_pci_table对比. 对于匹配的设备,PCI模 ...
- Linux I2C驱动分析(三)----i2c_dev驱动和应用层分析 【转】
本文转载自:http://blog.chinaunix.net/uid-21558711-id-3959287.html 分类: LINUX 原文地址:Linux I2C驱动分析(三)----i2c_ ...
- [ipsec][strongswan] strongswan源码分析-- (三) xfrm与strongswan内核接口分析
目录 strongwan sa分析(三) xfrm与strongswan内核接口分析 1. strongswan的实现 2. 交互机制 4. xfrm的消息通信的实现 strongwan sa分析(三 ...
- 13 数组 Java内存分析 三种初始化
Java内存分析 三种初始化 静态初始化 //静态初始化 创建+赋值 int[] a = {1,2,3}; Man[] mans = {new Man(1,1),new Man(2,2)}; 动态初始 ...
- ABP源码分析三:ABP Module
Abp是一种基于模块化设计的思想构建的.开发人员可以将自定义的功能以模块(module)的形式集成到ABP中.具体的功能都可以设计成一个单独的Module.Abp底层框架提供便捷的方法集成每个Modu ...
随机推荐
- gulp报错160
gulp报错: 这种提示,说明端口被占用,并且要改端口号,首先,我需要把Apache服务器关掉, 然后在gulpfile.js里: 把8080的端口号加进去.就解决了
- kafka "HelloWorld"实践
前面我们分别介绍了kafka的相关基本原理,kafka的集群服务器搭建以及kafka相关的配置,本文综合前面的理论知识,运用kafka Java API实现一个简单的客户端Demo. 开发环境 操作系 ...
- Spring---Bean的继承与依赖
Spring 允许继承 bean 的配置(通过Bean的parent属性来指定,例如parent=”teacher“), 被继承的 bean 称为父 bean. 继承这个父 Bean 的 Bean ...
- 通过TZ来设置嵌入式ARM+Linux的时区
1.在/etc/profile或者/root/.profile(/home/username/.profile) 在其中加入: TZ=UTC-08:00 export TZ hwclock -s
- Should You Build Your Own Backtester?
By Michael Halls-Moore on August 2nd, 2016 This post relates to a talk I gave in April at QuantCon 2 ...
- Guess Your Way Out! II---cf 558D (区间覆盖,c++STL map 的使用)
题目链接:http://codeforces.com/contest/558/problem/D 题意就是有一个二叉树高度为 h ,人站在根节点上,现在要走出去,出口在叶子节点上,有 q 条信息,每条 ...
- 【我的Android进阶之旅】Android 7.0报异常:java.lang.SecurityException: COLUMN_LOCAL_FILENAME is deprecated;
之前开发的一个和第三方合作的apk,在之前公司的 Android 5.1 系统的手表上运行正常,今天在公司新开发的 Android 7.1系统的手表上运行的时候,使用 DownloadManager ...
- javascript 之 valueOf
var m = { i:10, toString:function () { console.log('toString'); return this.i; }, valueOf:function ( ...
- srs(srs-librtmp推送h264原始数据)
1.下载最新srs源码 https://github.com/ossrs/srs/releases 2.编译(进入~/srs-2.0-r4/trunk目录) ./configure --with-li ...
- 如何保护自己的GitHub代码不被别人覆盖
我们在自己的github上创建了免费的公开代码,为了防止别人通过git push upstream master 覆盖了自己原有的代码,需要作一下设置:Settings->Branchs,然后在 ...