[Preface] A Hope That My Crude Remarks May Draw Forth By Abler People
[前言]拋磚引玉
Boot loader: 1st stage, don't need to depend on kernel
Bootstrap: 2nd stage, related about kernel image not part of the kernel code, do kernel uncompressing ...etc
Exercise3:
- Something needed to know
- Addressing methodology and its adv/disadv in real-mode/16-bit protected mode/32-bit protected mode
- Trace boot loader:
- .globl start : 為0x7c00
- 16bit ASM section is on
- cli ; cld;
- Set %ds,%es,%ss to 0
- %cs is 0 set by BIOS CS:IP = 0000:7c00
- Enable A20
- lgdt gdtdesc //load global descriptor table
- set %cr0 to Enable Protected mode
- 16 bit ASM is off
- ljmp $0xb866,$0x87c32
- CS is replaced as #8 slot at gdt table (PROT_MODE_CSEG)and plus 0xb866 base.
- immed is 0x87c32
- set %ds,%es,%fs,%gs,%ss as #10 at gdt table(PROT_MODE_DSEG)
- set esp as 0x7c00 to form stack base address ; stack address: [ss:esp]
- call bootmain(void)
- call readseg((uint32_t) ELFHDR, SECTSIZE*8, 0); read in ELF headers
- call readseg to read in every program header.
- jump to kernel.
- ((void (*)(void)) (ELFHDR->e_entry))();
- #
- Trace readseg
- end_pa = pa + memsize
- round down it-physical address for loading program into ram by pa&= 0x(FFFFFE00) // ~(SECTSIZE-1)
- Translate offset into Sector number
- Note: The offset must start from #1, #0 is the boot sec
- Read enough data by pa and sector number
- Because paging is not enable, just direct map into memory. by $PROT_MODE_DSEG, %ax
- #
- Trace readsect
- do IDE HardDisk read in data.
- Reply for its questions
- At what point does the processor start executing 32-bit code? What exactly causes the switch from 16- to 32-bit mode?
- before long jump, and set cr0's 1st bit to 1
- What is the last instruction of the boot loader executed, and what is the first instruction of the kernel it just loaded?
- Last instruction in boot loader
- In "C": ((void (*)(void)) (ELFHDR->e_entry))();
- In "GAS": call *0x10018 to jmp at kernel's entry point 0x10000c
- 0x10018 is the byte address of at ELFHDR's #24 byte.
- First Instruction in Kernel
- movw $0x1234,0x472 //warm boot
- Where is the first instruction of the kernel?
- At kern/entry.S . .globl entry
- 0x10000c
- 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?
- 由ELF info 穿針引線。
- #man elf
- readelf -l obj/kern/kernel
- From its ELF header
- get Program header's start offset: e_phoff
- get how many are the program headers: e_phnum
- 由program header
- readelf -l obj/kern/kernel
- From program headers to do readseg
- ph->p_pa : the address for prgram segment loaded into ram
- On systems for which physical addressing is relevant, this member is reserved for the segment's physical address. Under BSD this member is not used and must be zero.
- ph->p_memsz:
- This member holds the number of bytes in the memory image of the segment. It may be zero.
- ph->p_offset
- This member holds the offset from the beginning of the file at which the first byte of the segment resides.
- Discussion
- Calling conventions gcc at i386
- Saved by Caller
- eax : contain return value
- ecx: possibly trashed
- edx: possibly trashed
- Saved by Callee
- ebp
- ebx
- esi
- edi
- must be saved before call
- Sample
- In bootmain, why did it need following instructions?
- push %ebp #x86 gcc calling convention
- mov %esp,%ebp #x86 gcc calling convention
- push %edi
- push %ebx
- In readseg, ...
- push %ebp #x86 gcc calling convention
- mov %esp,%ebp #x86 gcc calling convention
- push %edi
- After Lesson:
- Drivers. How did it execute IDE device I/O
- Ans: Not Yet.
- How to decide program headers?
- LOAD //PT_LOAD
- LOAD //PT_LOAD
- GNU_STACK .//PT_GNU_SACK
- Ans: By session's default orgnization.
- In program header,
- Why is memsz and filesz? Loading it totally is not better?
- Why is GNU_Stack's Memsize zero?
- Program Headers:
- Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
- LOAD 0x001000 0xf0100000 0x00100000 0x075b9 0x075b9 R E 0x1000
- LOAD 0x009000 0xf0108000 0x00108000 0x0a300 0x0a960 RW 0x1000
- GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0x4
- ljmp: how did it decide to do TSS related stuff
- Guess: by segment descriptor's field.
- References:
Exercise4:
- Just Read The C Programming Language K&R chap5.
- Address Arithmetic. The Byte added to l-value is by its type.
- c = (int *) ((char *) c + 1); //added by 1
- b = (int *) a + 1;//added by 4
Exercise5:
- Something needed to know
- Change boo/Makefrag的-Ttext : 0x7c000 for link address
- VMA: Link address. Expected address for it to rum.
- LMA: Load address. Expected address for it to load into memory.
- objdump -h:Display the contents of the section headers -See VMA/LMA.
- objdump -f: Display the contents of the section headers -See entry_point for execution start address
- objdump -f obj/boot/boot.out
- start address 0x00007c00
- objdump -h obj/boot/boot.out
- VMA:0x00007c00
- LMA:0x00007c00
- Modify boot/Makefrag -Ttext to 0x8C00
- Error happaned at ljmp $PROT_MODE_CSEG, $protcseg @ boot/boot.S
- .Ttext .text/.org tell assembler its start address 0x8C00 , but BIOS load it into 0x7C00 that .gdt related data follow 0x7C00, at 0x7c64. When executing ljmp error happened instruction, it will use 0x8c64 by .Ttext claimed, but in reality it is loaded at 0x7C64 by BIOS.
- After Lesson:
- Modify -Ttext0x7900. How and Why did it change VMA/LAM not just only entry(.start)?
- Ans: Not Yet.
- How did CPU's chip view reject to execute ljmp instruction if gdt field was something wrong?
- Ans: Not Yet.
Exercise6:
- Something needed to know
- Set 1st break point at 0x7c00
- examine 0x100000
- Set 2nd breakpoint at 0x10000c
- examine 0x100000
- Addresses for obj/kern/kernel
- VMA:0xf0100000
- LMA: 0x00100000
- Entry: 0x10000c
- Result
- BIOS enter Bootloader
- x/8h 0x100000: 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000
- Bootloader enter OS Kernel
- x/8h 0x100000: 0xb002 0x1bad 0x0000 0x0000 0x4ffe 0xe452 0xc766 0x7205
- x8h 0x10000c: 0xc766 0x7205 0x0004 0x3400 0xb812 0x0000 0x0011 0x220f
- Discussion: Why are they different?
- By LMA's value
- bootloader load kernel by claim form program header of kernel's elf info.
- readelf -l obj/kern/kernel
- Elf file type is EXEC (Executable file)
Entry point 0x10000c
VMA:0xf0100000
LMA:0x100000
No comments:
Post a Comment
歡迎正面積極的討論。