LoginSignup
11
9

More than 5 years have passed since last update.

Linux Boot Process(compressed)

Posted at

Processの流れは、MBR -> GRUB kernel -> Linux kernelとなる。
MBR/GRUB kernelはLinux Kernel Codeから分離してGNU GRUBで管理されている。GRUB

GRUB kernelの関数callstack
__start -> grub_main() -> ... -> grub_cmd_linux() -> grub_cmd_initrd() -> grub_linux_boot()

grub-2.00/grub-core/loader/i386/pc/linux.c
static grub_err_t
grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
        int argc, char *argv[])
{
  grub_file_t file = 0;
  struct linux_kernel_header lh;
  grub_uint8_t setup_sects;
  grub_size_t real_size;
  grub_ssize_t len;
  int i;
  char *grub_linux_prot_chunk;
  int grub_linux_is_bzimage;
  grub_addr_t grub_linux_prot_target;
  grub_err_t err;

  grub_dl_ref (my_mod);

  if (argc == 0)
    {
      grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
      goto fail;
    }

  file = grub_file_open (argv[0]);
         ^^^^^^^^^^^^^^^^^^^^^^^^!! read linux kernel file
  if (! file)
    goto fail;

 -> file openに成功後、612bytekernel header情報をlhreadし、version/signatureのチェックを行っている。

grub-2.00/grub-core/loader/i386/linux.c-
static grub_err_t
grub_linux_boot (void)
{
...
  state.ebp = state.edi = state.ebx = 0;
  state.esi = real_mode_target;
  state.esp = real_mode_target;
  state.eip = params->code32_start;
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^!! 命令ポインタにLinux Kernelのエントリポイントを設定。
  return grub_relocator32_boot (relocator, state, 0);
}

 o 圧縮Linux Kernelの解凍
   Boot Loaderから物理アドレスLinux Kernelエントリポイントへ制御が移った後、圧縮データ(Linux Kernel)の解凍ルーチンが開始。
   ここからLinux Kernelの仕事になるため、ソースコード的にはGRUBからLinuxへ移動。
arch/x86/boot/compressed/head_64.S
    __HEAD
    .code32
ENTRY(startup_32)
    cld
    /*
     * Test KEEP_SEGMENTS flag to see if the bootloader is asking
     * us to not reload segments
     */
    testb $(1<<6), BP_loadflags(%esi)
    jnz 1f

    cli
    movl    $(__KERNEL_DS), %eax
    movl    %eax, %ds
    movl    %eax, %es
    movl    %eax, %ss
1:
...

    /* Target address to relocate to for decompression */
    addl    $z_extract_offset, %ebx
                 ^^^^^^^^^^^^^^^^!! 解凍後のkernelを配置するためのoffset

    /* Set up the stack */
    leal    boot_stack_end(%ebx), %esp

    /* Zero EFLAGS */
    pushl   $0
    popfl

/*
 * Copy the compressed kernel to the end of our buffer
 * where decompression in place becomes safe.
 */
    pushl   %esi
    leal    (_bss-4)(%ebp), %esi
    leal    (_bss-4)(%ebx), %edi
    movl    $(_bss - startup_32), %ecx
    shrl    $2, %ecx
    std
    rep movsl
    cld
    popl    %esi

/*
 * Jump to the relocated address.
 */
    leal    relocated(%ebx), %eax
    jmp *%eax
ENDPROC(startup_32)

    .text
relocated:

  -> ここまでで自分自身(解凍ルーチンと圧縮kernel)をoffset先へ飛ばしている
     これ以降で圧縮kernelを解凍して移動前ベースへ配置する
     CPUモード32->64への切り替えはここでは省略

/*
 * Clear BSS (stack is currently empty)
 */
    xorl    %eax, %eax
    leal    _bss(%ebx), %edi
    leal    _ebss(%ebx), %ecx
    subl    %edi, %ecx
    shrl    $2, %ecx
    rep stosl

/*
 * Adjust our own GOT
 */
    leal    _got(%ebx), %edx
    leal    _egot(%ebx), %ecx
1:
    cmpl    %ecx, %edx
    jae 2f
    addl    %ebx, (%edx)
    addl    $4, %edx
    jmp 1b
2:

/*
 * Do the decompression, and jump to the new kernel..
 */
    leal    z_extract_offset_negative(%ebx), %ebp
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^!! minus offsetポイント
                /* push arguments for decompress_kernel: */
    pushl   %ebp        /* output address */
    pushl   $z_input_len    /* input_len */
    leal    input_data(%ebx), %eax
    pushl   %eax        /* input_data */
    leal    boot_heap(%ebx), %eax
    pushl   %eax        /* heap area */
    pushl   %esi        /* real mode pointer */
    call    decompress_kernel
                ^^^^^^^^^^^^^^^^^!! decompression starts here.
    addl    $20, %esp

  -> ここからstartup_64へjumpしてlinux kernel初期化が本格的に開始
     (ここまではすべてarch/x86/compressed/配下の処理)

[Note/Tips]
BIOS -> Boot Sector(512KB) -> Boot Loader -> Kernel

  • 調査はすべてx86コードをベースに行っているので、他のarchは対象外。

主なBoot Loaderは以下。
o LILO
o SYSLINUX
o GRUB/GRUB2

11
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
9