👋

grub2からstart_kernelまでの道のり

2023/01/14に公開

grub 2.00からstart_kernelまでの道のり
ジャンプ箇所を見ていきます。

/grub-core/boot/i386/pc/boot.S

https://elixir.bootlin.com/grub/2.00/source/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

https://elixir.bootlin.com/grub/2.00/source/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

https://elixir.bootlin.com/grub/2.00/source/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
https://elixir.bootlin.com/grub/2.00/source/grub-core/kern/i386/pc/startup.S

/grub-core/kern/main.c
https://elixir.bootlin.com/grub/2.00/source/grub-core/kern/main.c

/grub-core/loader/i386/linux.c grub_linux_boot()
https://elixir.bootlin.com/grub/2.00/source/grub-core/loader/i386/linux.c#L373

/grub-core/lib/i386/relocator.c grub_relocator32_boot()
linuxカーネルは0x100000に置かれている。
カーネルを0x1000000にコピーして、0x1000000へジャンプする。
https://elixir.bootlin.com/grub/2.00/source/grub-core/lib/i386/relocator.c#L157

head_64.S startup_32()

x86_64_start_kernel

x86_64_start_reservations

start_kernel

https://vvl.me/2021/03/x86-linux-image-bootstrap-reboot-misc/

grub起動 分かりやすい。
https://qiita.com/taichitk/items/b3b69705be0e270e9f6e

https://web.njit.edu/~sohna/cs680/lec2-booting.pdf

https://www.binss.me/blog/boot-process-of-linux-grub/

Discussion