FreeBSD操作系统的boot2阶段

php中文网
发布: 2016-06-07 15:24:52
原创
1375人浏览过

FreeBSD操作系统的boot2阶段 2007-04-27 来源:FreeBSD 作者: 关键词: 系统FreeBSDBSD操作SD 也许你想知道,为什么 boot2 是在 boot0 之后,而不是在boot1之后。事实上,也有一个512字节的文件 boot1 存放在目录 /boot 里,那是用来从一张软盘引导系统的。从

FreeBSD操作系统的boot2阶段

2007-04-27      来源:FreeBSD         作者:

关键词:   系统      FreeBSD      BSD      操作      SD   

也许你想知道,为什么boot2 是在boot0 之后,而不是在boot1之后。事实上,也有一个512字节的文件boot1 存放在目录/boot 里,那是用来从一张软盘引导系统的。从软盘引导时,boot1 起着boot0 对硬盘引导相同的作用:它找到boot2 并运行之。

你可能已经看到有一文件/boot/mbr 。这是boot0 的简化版本。mbr 中的代码不会显示菜单让用户选择,而只是简单的引导被标志的分区。

实现boot2 的代码存放在目录sys/boot/i386/boot2/ 里,对应的可执行文件在/boot 里。在/boot 里的文件boot0 boot2 不会在引导过程中使用,只有boot0cfg 这样的工具才会使用它们。boot0 的内容应在MBR中才能生效。boot2 位于可引导的FreeBSD分区的开始。这些位置不受文件系统控制,所以它们不可用ls 之类的命令查看。

boot2 的主要任务是装载文件/boot/loader ,那是引导过程的第三阶段。在boot2 中的代码不能使用诸如<span>open()</span> <span>read()</span> 之类的例程函数,因为内核还没有被加载。而应当扫描硬盘,读取文件系统结构,找到文件/boot/loader ,用BIOS的功能将它读入内存,然后从其入口点开始执行之。

除此之外,boot2 还可提示用户进行选择,loader可以从其它磁盘、系统单元、分区装载。

boot2 的二进制代码用特殊的方式产生:

<span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><tt>sys/boot/i386/boot2/Makefile</tt>
<br />
boot2: boot2.ldr boot2.bin ${BTX}/btx/btx<br />
    btxld -v -E ${ORG2} -f bin -b ${BTX}/btx/btx -l boot2.ldr /<br />
        -o boot2.ld -P 1 boot2.bin<br />
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
登录后复制

这个Makefile片断表明btxld (8) 被用来链接二进制代码。BTX表示引导扩展器(BooT eXtender)是给程序(称为客户(client))提供保护模式环境、并与客户程序相链接的一段代码。所以boot2 是一个BTX客户,使用BTX提供的服务。

工具btxld 是链接器,它将两个二进制代码链接在一起。btxld (8)ld (1) 的区别是ld 通常将两个目标文件链接成一个动态链接库或可执行文件,而btxld 则将一个目标文件与BTX链接起来,产生适合于放在分区首部的二进制代码,以实现系统引导。

boot0 执行跳转至BTX的入口点。然后,BTX将处理器切换至保护模式,并准备一个简单的环境,然后调用客户。这个环境包括:

  • 虚拟8086模式。这意味着btx是虚拟8086的监视程序。实模式指令,如pushf, popf, cli, sti, if,均可被客户调用。

  • 建立中断描述符表(Interrupt Descriptor Table, IDT),使得所有的硬件中断可被缺省的BIOS程序处理。建立中断0x30,这是系统调用关口。

    阶跃AI
    阶跃AI

    阶跃星辰旗下AI智能问答搜索助手

    阶跃AI 291
    查看详情 阶跃AI
  • 两个系统调用<span>exec</span> <span>exit</span> 的定义如下:

    <span><span><tt>sys/boot/i386/btx/lib/btxsys.s:</tt>
    <br />
            .set INT_SYS,0x30       # 中断号<br />
    #<br />
    # System call: exit<br />
    #<br />
    __exit:     xorl %eax,%eax          # BTX系统调用0x0<br />
            int $INT_SYS            #<br />
    #<br />
    # System call: exec<br />
    #<br />
    __exec:     movl $0x1,%eax          # BTX系统调用0x1<br />
            int $INT_SYS            #<br />
    </span>
    </span>
    
    登录后复制

BTX建立全局描述符表(Global Descriptor Table, GDT):

<span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><tt>sys/boot/i386/btx/btx/btx.s:</tt>
<br />
gdt:        .word 0x0,0x0,0x0,0x0       # 以空为入口<br />
        .word 0xffff,0x0,0x9a00,0xcf    # SEL_SCODE<br />
        .word 0xffff,0x0,0x9200,0xcf    # SEL_SDATA<br />
        .word 0xffff,0x0,0x9a00,0x0 # SEL_RCODE<br />
        .word 0xffff,0x0,0x9200,0x0 # SEL_RDATA<br />
        .word 0xffff,MEM_USR,0xfa00,0xcf# SEL_UCODE<br />
        .word 0xffff,MEM_USR,0xf200,0xcf# SEL_UDATA<br />
        .word _TSSLM,MEM_TSS,0x8900,0x0 # SEL_TSS<br />
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
登录后复制

客户的代码和数据始于地址MEM_USR(0xa000),选择符(selector) SEL_UCODE指向客户的数据段。选择符 SEL_UCODE 拥有第3级描述符权限(Descriptor Privilege Level, DPL),这是最低级权限。但是INT 0x30 指令的处理程序存储于另一个段里,这个段的选择符SEL_SCODE (supervisor code)由有着管理级权限。正如代码建立IDT(中断描述符表)时进行的操作那样:

<span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span>       mov $SEL_SCODE,%dh      # 段选择符<br />
init.2:     shr %bx             # 是否处理这个中断?<br />
        jnc init.3          # 否<br />
        mov %ax,(%di)           # 设置处理程序偏移量<br />
        mov %dh,0x2(%di)        # 设置处理程序选择符<br />
        mov %dl,0x5(%di)        # 设置 P:DPL:type<br />
        add $0x4,%ax            # 下一个中断处理程序<br />
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
登录后复制

所以,当客户调用 <span>__exec()</span> 时,代码将被以最高权限执行。这使得内核可以修改保护模式数据结构,如分页表(page tables)、全局描述符表(GDT)、中断描述符表(IDT)等。

boot2 定义了一个重要的数据结构:struct bootinfo 。这个结构由 boot2 初始化,然后被转送到loader,之后又被转入内核。这个结构的部分项目由boot2 设定,其余的由loader设定。这个结构中的信息包括内核文件名、BIOS提供的硬盘柱面/磁头/扇区数目信息、BIOS提供的引导设备的驱动器编号,可用的物理内存大小,envp 指针(环境指针)等。定义如下:

<span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><tt>/usr/include/machine/bootinfo.h</tt>
<br />
struct bootinfo {<br />
    u_int32_t   bi_version;<br />
    u_int32_t   bi_kernelname;      /* 用一个字节表示 * */<br />
    u_int32_t   bi_nfs_diskless;    /* struct nfs_diskless * */<br />
        /* 以上为常备项 */<br />
#define bi_endcommon    bi_n_bios_used<br />
    u_int32_t   bi_n_bios_used;<br />
    u_int32_t   bi_bios_geom[N_BIOS_GEOM];<br />
    u_int32_t   bi_size;<br />
    u_int8_t    bi_memsizes_valid;<br />
    u_int8_t    bi_bios_dev;        /* 引导设备的BIOS单元编号 */<br />
    u_int8_t    bi_pad[2];<br />
    u_int32_t   bi_basemem;<br />
    u_int32_t   bi_extmem;<br />
    u_int32_t   bi_symtab;      /* struct symtab * */<br />
    u_int32_t   bi_esymtab;     /* struct symtab * */<br />
        /* 以下项目仅高级bootloader提供 */<br />
    u_int32_t   bi_kernend;     /* 内核空间末端 */<br />
    u_int32_t   bi_envp;        /* 环境 */<br />
    u_int32_t   bi_modulep;     /* 预装载的模块 */<br />
};<br />
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
登录后复制

boot2 进入一个循环等待用户输入,然后调用<span>load()</span> 。如果用户不做任何输入,循环将在一段时间后结束,<span>load()</span> 将会装载缺省文件(/boot/loader )。函数 <span>ino_t lookup(char *filename)</span> <span>int xfsread(ino_t inode, void *buf, size_t nbyte)</span> 用来将文件内容读入内存。/boot/loader 是一个ELF格式二进制文件,不过它的头部被换成了a.out格式中的struct exec 结构。<span>load()</span> 扫描loader的ELF头部,装载/boot/loader 至内存,然后跳转至入口执行之:

<span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><span><tt>sys/boot/i386/boot2/boot2.c:</tt>
<br />
    __exec((caddr_t)addr, RB_BOOTINFO | (opts & RBX_MASK),<br />
       MAKEBOOTDEV(dev_maj[dsk.type], 0, dsk.slice, dsk.unit, dsk.part),<br />
       0, 0, 0, VTOP(&bootinfo));<br />
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
登录后复制


相关标签:
最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号