OpenBSD引导的第二部PBR,也是活动分区的一个扇区的代码,由第一步的MBR加载到0x7C00处,manpage里详细的讲解了过程和大致实现 biosboot(8) (http://man.openbsd.org/OpenBSD-6.0/man8/i386/biosboot.8),代码在sys/arch/i386/stand/biosboot/目录下,主要就是其中的biosboot.S;和mbr.S一样,在代码的开头清晰的介绍了该代码要做的事情:

/*
* Memory layout:
*
* 0x00000 -> 0x07BFF our stack (to 31k)
* 0x07A00 -> 0x07BFF typical MBR loc (at 30k5)
* 0x07C00 -> 0x07DFF our code (at 31k)
* 0x07E00 -> ... /boot inode block (at 31k5)
* 0x07E00 -> ... (indirect block if nec)
* 0x40000 -> ... /boot (at 256k)
*
* The BIOS loads the MBR at physical address 0x07C00. It then relocates
* itself to (typically) 0x07A00.
*
* The MBR then loads us at physical address 0x07C00.
*
* We use a long jmp to normalise our address to seg:offset 07C0:0000.
* (In real mode on x86, segment registers contain a base address in
* paragraphs (16 bytes). 0000:00010 is the same as 0001:0000.)
*
* We set the stack to start at 0000:7BFC (grows down on i386)
*
* We then read the inode for /boot into memory just above us at
* 07E0:0000, and run through the direct block table (and the first
* indirect block table, if necessary).
*
* We load /boot at seg:offset 4000:0000.
*
* Previous versions limited the size of /boot to 64k (loaded in a single
* segment). This version does not have this limitation.
*/

  注释内容包含了mbr.S开头的内容,还是讲解了大致引导过程:BIOS 读MBR到0x7C00处,然后MBR将自身重定位到0x7A00,MBR加载PBR也就是biosboot.S到0x7C00,然后jmp到0x7C00处的biosboot.S执行。

  biosboot.S的特殊之处在于不像mbr.S里那样直接从磁盘扇区的第1扇区这种“物理”定位信息加载后续代码,也就是说biosboot需要能直接操作文件系统了,因为它后续加载的是/boot,要直接从根分区加载boot!对比其他的bootloader,比如GRUB,GRUB能直接读各种各样的文件系统,其代码复杂度可想而知,OpenBSD的biosboot实际上并不能读文件系统,因为它只有512字节啊,这点空间不可能能放下文件系统驱动!biosboot采取的方法是在最终的二进制内容里直接保存/boot所在的磁盘扇区位置信息,当然不可能直接写死在biosboot.S代码里,采取的办法是打二进制patch,也就是直接修改编译后的二进制文件里的,通过用户态程序/usr/sbin/installboot将/boot的物理位置信息写到编译后的biosboot中,然后将修改后的biosboot写到分区第一个扇区;这里涉及到ELF文件相关知识,在biosboot.S中有几个导出的符号,installboot将/boot物理位置信息写到这几个符号所指的位置处,代码的注释里清晰的讲解了这几个导出符号:

/*
* The data passed by installboot is:
*
* inodeblk uint32 the filesystem block that holds /boot's inode
* inodedbl uint32 the memory offset to the beginning of the
* direct block list (di_db[]). (This is the
* offset within the block + $INODEOFF, which is
* where we load the block to.)
* fs_bsize_p uint16 the filesystem block size _in paragraphs_
* (i.e. fs_bsize / 16)
* fs_bsize_s uint16 the number of disk sectors in a filesystem
* block (i.e. fs_bsize / d_secsize). Directly written
* into the LBA command block, at lba_count.
* XXX LIMITED TO 127 BY PHOENIX EDD SPEC.
* fsbtodb uint8 shift count to convert filesystem blocks to
* disk blocks (sectors). Note that this is NOT
* log2 fs_bsize, since fragmentation allows
* the trailing part of a file to use part of a
* filesystem block. In other words, filesystem
* block numbers can point into the middle of
* filesystem blocks.
* p_offset uint32 the starting disk block (sector) of the
* filesystem
* nblocks uint16 the number of filesystem blocks to read.
* While this can be calculated as
* howmany(di_size, fs_bsize) it takes us too
* many code bytes to do it.
*
* All of these are patched directly into the code where they are used
* (once only, each), to save space.
*
* One more symbol is exported, in anticipation of a "-c" flag in
* installboot to force CHS reads:
*
* force_chs uint8 set to the value 1 to force biosboot to use CHS
* reads (this will of course cause the boot sequence
* to fail if /boot is above 8 GB).
*/

  这几个值使biosboot能直接定位到磁盘上的boot。biosboot中和mbr一样也有CHS、LBA相关的代码,按住shift键强制使用CHS模式。加载boot到0x40000,也就是256KB处,然后jmp到其中继续执行/boot。

  OK,终于看完这些实模式的鬼东西了……后面空了再继续写boot后面的东西吧。

OpenBSD内核之引导PBR的更多相关文章

  1. OpenBSD内核之引导MBR

    MBR的介绍网上很多,没错,就那个最后以0x55AA结尾的512字节的引导块,OpenBSD提供了引导MBR实现:OpenBSD在x86上的引导过程为MBR --> PBR --> boo ...

  2. linux 驱动学习笔记03--Linux 内核的引导

    如图所示为 X86 PC 上从上电/复位到运行 Linux 用户空间初始进程的流程.在进入与 Linux相关代码之间,会经历如下阶段. ( 1 ) 当系统上电或复位时, CPU 会将 PC 指针赋值为 ...

  3. Linux内核的引导

    1,当系统上电或复位时,CPU会将PC指针赋值为一个特定的地址0xFFFF0并执行该地址处的指令.在PC机中,该地址位于BIOS中,它保存在主板上的ROM或Flash中 2,BIOS运行时按照CMOS ...

  4. mini2440 uboot使用nfs方式引导内核,文件系统

    mini2440 uboot使用nfs方式引导内核,文件系统 成于坚持,败于止步 看了一段时间的u-boot了,到今天才真正完全实现u-boot引导内核和文件系统,顺利开机,在此记录完整过程 1.首先 ...

  5. Linux 内核引导选项简介

    Linux 内核引导选项简介 作者:金步国 连接地址:http://www.jinbuguo.com/kernel/boot_parameters.html 参考参数:https://www.cnbl ...

  6. UBoot常用命令及内核下载与引导

    一.常用命令 1. 获取帮助 ① help 或 ? 2. 环境变量与相关命令 (1)环境变量 ① bootdely ② baudrate ③ netmask ④ ethaddr ⑤ bootfile ...

  7. Linux CentOS 修改内核引导顺序

    CentOS 7.0 系统更改内核启动顺序 可以 uname -a查下当前的 由于 CentOS 7 使用 grub2 作为引导程序,所以和 CentOS 6 有所不同,并不是修改 /etc/grub ...

  8. 非常好!!!Linux源代码阅读——内核引导【转】

    Linux源代码阅读——内核引导 转自:http://home.ustc.edu.cn/~boj/courses/linux_kernel/1_boot.html 目录 Linux 引导过程综述 BI ...

  9. Linux 内核引导参数简介

    概述 内核引导参数大体上可以分为两类:一类与设备无关.另一类与设备有关.与设备有关的引导参数多如牛毛,需要你自己阅读内核中的相应驱动程序源码以获取其能够接受的引导参数.比如,如果你想知道可以向 AHA ...

随机推荐

  1. TortoiseGit使用手册

    1 安装 1.1 32位系统 1.2 64位系统 2 配置 2.1 设置语言 2.2 配置用户信息 2.3 生成ssh-key(仅限第一次使用) 2.4 初始化仓库(尚未使用git管理的项目) 2.5 ...

  2. JAVA NIO——Buffer和FileChannel

    Java NIO和IO的主要区别 IO NIO 面向流 面向缓冲 阻塞IO 非阻塞IO 无 选择器 示例: import java.io.FileInputStream; import java.io ...

  3. android源码中,在系统多媒体数据库中增加一个字段

    由于项目需求,在系统多媒体管理数据库里的存储图像文件的表中需要新增加一个字段,源码在:项目\packages\providers\MediaProvider\MediaProvider.java下,在 ...

  4. C# 正则表达式小坑 -- not enough

    今天遇到了一个奇怪的报错: 相关的代码是这样的: Regex regex = new Regex("(?<=wwwroot\\).*?$"); 然后把这段正则复制到任何正则测 ...

  5. DPI

    [iOS]查找数组NSArray中是否包含指定的元素 http://blog.csdn.net/zyq527758142/article/details/51278172 Dpi(每平方英寸像素数目) ...

  6. 。linux桌面与命令行

    1.输入用户名和密码登录到系统2.vi /etc/inittab3.修改id:后对应的值为5(桌面模式),id:后对应的值改成3(命令行模式)先用命令#startx启动到桌面模式,然后 Ctrl + ...

  7. 【问题】AndroidStudio导入项目一直卡在Building gradle project infod的最快速解决方案

    原因 AndroidStudio导入项目一直卡在Building gradle project info的原因, 是因为导入的这个项目使用的gradle版本与本地已经拥有的gradle版本不一致,导致 ...

  8. queen8

    八皇后问题 八皇后问题的数学模型:如何能够在 8×8 的国际象棋棋盘上放置八个皇后,使得任何一个皇后都无法直接吃掉其他的皇后?为了达到此目的,任两个皇后都不能处于同一条横行.纵行或斜线上.八皇后问题可 ...

  9. Docker镜像文件存储结构

    docker相关文件存放在:/var/lib/docker目录下 镜像的存储结构主要分两部分,一是镜像ID之间的关联,一是镜像ID与镜像名称之间的关联,前者的结构体叫Graph,后者叫TagStore ...

  10. Maven安装与使用

    1.安装Maven 1)官网下载Maven : http://maven.apache.org/download.cgi,解压下载文件 2)配置环境变量 3)验证是否已经安装成功:打开cmd,输入mv ...