电脑技术学习

FreeBSD操作系统的boot2阶段

dn001

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

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

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

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

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

sys/boot/i386/boot2/boot2.c:
  __exec((CADdr_t)addr, RB_BOOTINFO | (opts & RBX_MASK),
    MAKEBOOTDEV(dev_maj[dsk.type], 0, dsk.slice, dsk.unit, dsk.part),
    0, 0, 0, VTOP(&bootinfo));

标签: