The ability to boot from a CD-ROM came much later during the evolution of the PC, and as a result the PC architects took the opportunity to rethink the boot process slightly. As a result, the way a modern BIOS boots from a CD-ROM is a bit more complicated (and more powerful). CD-ROMs use a sector size of 2048 bytes instead of 512, and the BIOS can load a much larger boot image from the disk into memory (not just one sector) before transferring control to it. For more information, see the "El Torito" Bootable CD-ROM Format Specification.
将处理器由 real mode 切换为 protected mode， 使软件能够访问所有的 1MB 以上的物理地址空间。
Protected mode is described briefly in sections 1.2.7 and 1.2.8 of PC Assembly Language, and in great detail in the Intel architecture manuals.
Bootloader通过x86特殊I / O指令直接访问IDE磁盘设备寄存器，从硬盘读取内核。
what the particular I/O instructions here mean, check out the "IDE hard drive controller" section on the 6.828 reference page.
Be able to answer the following questions:
At what point does the processor start executing 32-bit code? What exactly causes the switch from 16- to 32-bit mode?
in boot / boot.S
# Switch from real to protected mode, using a bootstrap GDT
# and segment translation that makes virtual addresses
# identical to their physical addresses, so that the
# effective memory map does not change during the switch.
movl %cr0, %eax
orl $CR0_PE_ON, %eax
movl %eax, %cr0
What is the last instruction of the boot loader executed, and what is the first instruction of the kernel it just loaded?
in boot / main.c
// call the entry point from the ELF header
// note: does not return!
(gdb) b *0x7d6b
Breakpoint 1 at 0x7d6b
The target architecture is assumed to be i386=> 0x7d6b: call *0x10018
Breakpoint 1, 0x00007d6b in ?? ()(gdb)si=> 0x10000c: movw $0x1234,0x472
0x0010000c in ?? ()
可以看到接下来运行的地址为 0x001000c， 正好是 kernel 的入口地址。
Where is the first instruction of the kernel?
How does the boot loader decide how many sectors it must read in order to fetch the entire kernel from disk? Where does it find this information?
in boot / main.c
// load each program segment (ignores ph flags)
ph=(structProghdr*)((uint8_t*)ELFHDR+ELFHDR->e_phoff);eph=ph+ELFHDR->e_phnum;for(;ph<eph;ph++)// p_pa is the load address of this segment (as well
// as the physical address)
We set the link address by passing -Ttext 0x7C00 to the linker in boot/Makefrag, so the linker will produce the correct memory addresses in the generated code.
The target architecture is assumed to be i8086
[f000:fff0] 0xffff0: ljmp $0xf000,$0xe05b
0x0000fff0 in ?? ()
+ symbol-file obj/kern/kernel
[f000:e05b] 0xfe05b: cmpl $0x0,%cs:0x6ac8
0x0000e05b in ?? ()
*** Now run 'make gdb'.
qemu-system-i386 -nographic -drive file=obj/kern/kernel.img,index=0,media=disk,format=raw -serial mon:stdio -gdb tcp::26000 -D qemu.log -S
6828 decimal is XXX octal!
entering test_backtrace 5
entering test_backtrace 4
entering test_backtrace 3
entering test_backtrace 2
entering test_backtrace 1
entering test_backtrace 0
leaving test_backtrace 0
leaving test_backtrace 1
leaving test_backtrace 2
leaving test_backtrace 3
leaving test_backtrace 4
leaving test_backtrace 5
Welcome to the JOS kernel monitor!
Type 'help'for a list of commands.
examine memory using GDB's x command. The GDB manual has full details.
the command x/<N>x <ADDR> prints N words of memory at ADDR. (Note that both 'x's in the command are lowercase.) Warning: The size of a word is not a universal standard. In GNU assembly, a word is two bytes (the 'w' in xorw, which stands for word, means 2 bytes).