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.
Question
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.
lgdt gdtdesc
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
1
2
3
// call the entry point from the ELF header
// note: does not return!
((void(*)(void))(ELFHDR->e_entry))();
(gdb) b *0x7d6b
Breakpoint 1 at 0x7d6b
(gdb) c
Continuing.
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?
*0x001000c
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
1
2
3
4
5
6
7
// 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)
readseg(ph->p_pa,ph->p_memsz,ph->p_offset);
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.
1
2
3
4
5
6
7
8
# originalThe target architecture is assumed to be i8086
[f000:fff0] 0xffff0: ljmp $0xf000,$0xe05b
0x0000fff0 in ?? ()+ symbol-file obj/kern/kernel
(gdb) si
[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 5entering test_backtrace 4entering test_backtrace 3entering test_backtrace 2entering test_backtrace 1entering test_backtrace 0leaving test_backtrace 0leaving test_backtrace 1leaving test_backtrace 2leaving test_backtrace 3leaving test_backtrace 4leaving test_backtrace 5Welcome to the JOS kernel monitor!
Type 'help'for a list of commands.
K>
测试内存:
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).
The target architecture is assumed to be i8086
[f000:fff0] 0xffff0: ljmp $0xf000,$0xe05b
0x0000fff0 in ?? ()+ symbol-file obj/kern/kernel
(gdb) b *0x7c00
Breakpoint 1 at 0x7c00
(gdb) c
Continuing.
[ 0:7c00]=> 0x7c00: cli
Breakpoint 1, 0x00007c00 in ?? ()(gdb) x /8wx 0x00100000
0x100000: 0x00000000 0x00000000 0x00000000 0x00000000
0x100010: 0x00000000 0x00000000 0x00000000 0x00000000
(gdb) b*0x10000c
Breakpoint 2 at 0x10000c
(gdb) c
Continuing.
The target architecture is assumed to be i386=> 0x10000c: movw $0x1234,0x472
Breakpoint 2, 0x0010000c in ?? ()(gdb) x /8wx 0x00100000
0x100000: 0x1badb002 0x00000000 0xe4524ffe 0x7205c766
0x100010: 0x34000004 0x2000b812 0x220f0011 0xc0200fd8