到此loader的使命已经完成:加载内核,跳进保护模式。下面就要把工作交给内核了。这个主要讲下转交控制权,本来控制权在loader,说转交控制权也就是jmp到内核执行呵呵。不过内核是采用ELF文件格式,所以我们首先要根据ELF文件信息把kernel.bin转移到正确的位置。
接着上阶段步骤开始:
用光盘中工具ELFParser打开kernel.bin得到ELF header,program header
------------ ELF Header ---------------
e_ident 7Fh, "ELF", 1h, 1h, 1h, ...
e_type 2 Executable file
e_machine 3 80386
e_version 1
e_entry 8048060 H Entry point.
e_phoff 34 H
e_shoff A8 H
e_flags 0
e_ehsize 34 H
e_phentsize 20 H
e_phnum 1
e_shentsize 28 H
e_shnum 4 H
e_shstrndx 3 H
------------- Program Header 0 -------------
p_type 1 H PT_LOAD
p_offset 0 H
p_vaddr 8048000 H
p_paddr 8048000 H
p_filesz 6D H
p_memsz 6D H
p_flags 5 H
p_align 1000 H
------------- Section Header 0 -------------
sh_name 0 H
sh_type 0 H SHT_NULL
sh_flags 0 H Unknown
sh_addr 0 H Position in Mem.
sh_offset 0 H Position in file.
sh_size 0 H
sh_link 0 H
sh_info 0 H
sh_addralign 0 H
sh_entsize 0 H
------------- Section Header 1 -------------
sh_name B H .text
sh_type 1 H SHT_PROGBITS
sh_flags 6 H SHF_ALLOC & SHF_EXECINSTR
sh_addr 8048060 H Position in Mem.
sh_offset 60 H Position in file.
sh_size D H
sh_link 0 H
sh_info 0 H
sh_addralign 10 H
sh_entsize 0 H
------------- Section Header 2 -------------
sh_name 11 H .comment
sh_type 1 H SHT_PROGBITS
sh_flags 0 H Unknown
sh_addr 0 H Position in Mem.
sh_offset 6D H Position in file.
sh_size 1F H
sh_link 0 H
sh_info 0 H
sh_addralign 1 H
sh_entsize 0 H
------------- Section Header 3 -------------
sh_name 1 H .shstrtab
sh_type 3 H SHT_STRTAB
sh_flags 0 H Unknown
sh_addr 0 H Position in Mem.
sh_offset 8C H Position in file.
sh_size 1A H
sh_link 0 H
sh_info 0 H
sh_addralign 1 H
sh_entsize 0 H
---------------------------------------
p_addr为段在内存中的虚拟地址,我们发现他是8048000 ,内存已超过128M,所以我们需要重新定位内核
nasm -f elf -o kernel.o kernel.asm
ld -s -Ttext 0x30400 -o kernel.bin kernel.o
再重新用ELFParser看下:
==================================================================
C:\Documents and Settings\Administrator.CASIT-B2FCB2224\桌面\MyOS5\kernel.bin
==================================================================
------------ ELF Header ---------------
e_ident 7Fh, "ELF", 1h, 1h, 1h, ...
e_type 2 Executable file
e_machine 3 80386
e_version 1
e_entry 30400 H Entry point.
e_phoff 34 H
e_shoff 448 H
e_flags 0
e_ehsize 34 H
e_phentsize 20 H
e_phnum 1
e_shentsize 28 H
e_shnum 4 H
e_shstrndx 3 H
------------- Program Header 0 -------------
p_type 1 H PT_LOAD
p_offset 0 H
p_vaddr 30000 H
p_paddr 30000 H
p_filesz 40D H
p_memsz 40D H
p_flags 5 H
p_align 1000 H
------------- Section Header 0 -------------
sh_name 0 H
sh_type 0 H SHT_NULL
sh_flags 0 H Unknown
sh_addr 0 H Position in Mem.
sh_offset 0 H Position in file.
sh_size 0 H
sh_link 0 H
sh_info 0 H
sh_addralign 0 H
sh_entsize 0 H
------------- Section Header 1 -------------
sh_name B H .text
sh_type 1 H SHT_PROGBITS
sh_flags 6 H SHF_ALLOC & SHF_EXECINSTR
sh_addr 30400 H Position in Mem.
sh_offset 400 H Position in file.
sh_size D H
sh_link 0 H
sh_info 0 H
sh_addralign 10 H
sh_entsize 0 H
------------- Section Header 2 -------------
sh_name 11 H .comment
sh_type 1 H SHT_PROGBITS
sh_flags 0 H Unknown
sh_addr 0 H Position in Mem.
sh_offset 40D H Position in file.
sh_size 1F H
sh_link 0 H
sh_info 0 H
sh_addralign 1 H
sh_entsize 0 H
------------- Section Header 3 -------------
sh_name 1 H .shstrtab
sh_type 3 H SHT_STRTAB
sh_flags 0 H Unknown
sh_addr 0 H Position in Mem.
sh_offset 42C H Position in file.
sh_size 1A H
sh_link 0 H
sh_info 0 H
sh_addralign 1 H
sh_entsize 0 H
---------------------------------------
下面就根据ELF文件信息将kernel.bin转移到正确的位置,找出每个program header,根据其信息进行内存复制。
; InitKernel ---------------------------------------------------------------------------------
; 将 KERNEL.BIN 的内容经过整理对齐后放到新的位置
; --------------------------------------------------------------------------------------------
InitKernel: ; 遍历每一个 Program Header,根据 Program Header 中的信息来确定把什么放进内存,放到什么位置,以及放多少。
xor esi, esi
mov cx, word [BaseOfKernelFilePhyAddr + 2Ch]; ┓ ecx <- pELFHdr->e_phnum
movzx ecx, cx ; ┛
mov esi, [BaseOfKernelFilePhyAddr + 1Ch] ; esi <- pELFHdr->e_phoff
add esi, BaseOfKernelFilePhyAddr ; esi <- OffsetOfKernel + pELFHdr->e_phoff
.Begin:
mov eax, [esi + 0]
cmp eax, 0 ; PT_NULL
jz .NoAction
push dword [esi + 010h] ; size ┓
mov eax, [esi + 04h] ; ┃
add eax, BaseOfKernelFilePhyAddr ; ┣ ::memcpy( (void*)(pPHdr->p_vaddr),
push eax ; src ┃ uchCode + pPHdr->p_offset,
push dword [esi + 08h] ; dst ┃ pPHdr->p_filesz;
call MemCpy ; ┃
add esp, 12 ; ┛
.NoAction:
add esi, 020h ; esi += pELFHdr->e_phentsize
dec ecx
jnz .Begin
ret
; InitKernel ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
好了,跳转:
jmp SelectorFlatC:KernelEntryPointPhyAddr ; 正式进入内核 *
阅读(814) | 评论(0) | 转发(0) |