👋
grub2からstart_kernelまでの道のり
grub 2.00からstart_kernelまでの道のり
ジャンプ箇所を見ていきます。
/grub-core/boot/i386/pc/boot.S
LOCAL(copy_buffer):
/*
* We need to save %cx and %si because the startup code in
* kernel uses them without initializing them.
*/
pusha
pushw %ds
movw $0x100, %cx
movw %bx, %ds
xorw %si, %si
movw $GRUB_BOOT_MACHINE_KERNEL_ADDR, %di
movw %si, %es
cld
rep
movsw
popw %ds
popa
/* boot kernel */
jmp *(kernel_address)
jmp *(kernel_address)
0x08000にジャンプします。
↓
/grub-core/boot/i386/pc/diskboot.S
LOCAL(bootit):
/* print a newline */
MSG(notification_done)
popw %dx /* this makes sure %dl is our "boot" drive */
ljmp $0, $(GRUB_BOOT_MACHINE_KERNEL_ADDR + 0x200)
ljmpで0x82000へジャンプ
0x82000の算出の仕方
#define GRUB_BOOT_MACHINE_KERNEL_ADDR (grub_boot_machine_kernel_seg << 4)
#grub_boot_machine_kernel_seg 0x800
0x800 << 4 すると0x8000となります。
0x8000 + 0x200 = 0x82000
↓
/grub-core/boot/i386/pc/startup_raw.S
core.img = diskboot.S + startup_raw.S
movl $0x100000, %esi
movl $GRUB_BOOT_MACHINE_KERNEL_ADDR, %edi
cld
rep
movsb
/* jump to the real address */
movl $multiboot_trampoline, %eax
jmp *%eax
multiboot_trampoline:
/* fill the boot information */
movl %edx, LOCAL(boot_dev)
shrl $24, %edx
/* enter the usual booting */
call prot_to_real
.code16
jmp LOCAL (codestart)
.code32
post_reed_solomon:
#ifdef ENABLE_LZMA
movl $GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR, %edi
#ifdef __APPLE__
movl $decompressor_end, %esi
#else
movl $LOCAL(decompressor_end), %esi
#endif
pushl %edi
movl LOCAL (uncompressed_size), %ecx
leal (%edi, %ecx), %ebx
/* Don't remove this push: it's an argument. */
push %ecx
call _LzmaDecodeA
pop %ecx
/* _LzmaDecodeA clears DF, so no need to run cld */
popl %esi
#endif
movl LOCAL(boot_dev), %edx
movl $prot_to_real, %edi
movl $real_to_prot, %ecx
movl $LOCAL(realidt), %eax
jmp *%esi
$GRUB_BOOT_MACHINE_KERNEL_ADDR = 0x100000
jmp *%esi
0x100000へジャンプ
↓
/grub-core/kern/i386/pc/startup.S
↓
/grub-core/kern/main.c
↓
/grub-core/loader/i386/linux.c grub_linux_boot()
↓
/grub-core/lib/i386/relocator.c grub_relocator32_boot()
linuxカーネルは0x100000に置かれている。
カーネルを0x1000000にコピーして、0x1000000へジャンプする。
↓
head_64.S startup_32()
x86_64_start_kernel
x86_64_start_reservations
start_kernel
grub起動 分かりやすい。
Discussion