首页 > 代码库 > xv6/bootasm.S + xv6/bootmain.c
xv6/bootasm.S + xv6/bootmain.c
xv6/bootasm.S
1 #include "asm.h" 2 #include "memlayout.h" 3 #include "mmu.h" 4 5 # Start the first CPU: switch to 32-bit protected mode, jump into C. 6 # The BIOS loads this code from the first sector of the hard disk into 7 # memory at physical address 0x7c00 and starts executing in real mode 8 # with %cs=0 %ip=7c00. 9 10 .code16 # Assemble for 16-bit mode11 .globl start12 start:13 cli # BIOS enabled interrupts; disable14 15 # Zero data segment registers DS, ES, and SS.16 xorw %ax,%ax # Set %ax to zero17 movw %ax,%ds # -> Data Segment18 movw %ax,%es # -> Extra Segment19 movw %ax,%ss # -> Stack Segment20 21 # Physical address line A20 is tied to zero so that the first PCs22 # with 2 MB would run software that assumed 1 MB. Undo that.23 seta20.1:24 inb $0x64,%al # Wait for not busy25 testb $0x2,%al26 jnz seta20.127 28 movb $0xd1,%al # 0xd1 -> port 0x6429 outb %al,$0x6430 31 seta20.2:32 inb $0x64,%al # Wait for not busy33 testb $0x2,%al34 jnz seta20.235 36 movb $0xdf,%al # 0xdf -> port 0x6037 outb %al,$0x6038 39 # Switch from real to protected mode. Use a bootstrap GDT that makes40 # virtual addresses map directly to physical addresses so that the41 # effective memory map doesn’t change during the transition.42 lgdt gdtdesc43 movl %cr0, %eax44 orl $CR0_PE, %eax45 movl %eax, %cr046 47 48 49 50 51 # Complete transition to 32-bit protected mode by using long jmp52 # to reload %cs and %eip. The segment descriptors are set up with no53 # translation, so that the mapping is still the identity mapping.54 ljmp $(SEG_KCODE<<3), $start3255 56 .code32 # Tell assembler to generate 32-bit code now.57 start32:58 # Set up the protected-mode data segment registers59 movw $(SEG_KDATA<<3), %ax # Our data segment selector60 movw %ax, %ds # -> DS: Data Segment61 movw %ax, %es # -> ES: Extra Segment62 movw %ax, %ss # -> SS: Stack Segment63 movw $0, %ax # Zero segments not ready for use64 movw %ax, %fs # -> FS65 movw %ax, %gs # -> GS66 67 # Set up the stack pointer and call into C.68 movl $start, %esp69 call bootmain70 71 # If bootmain returns (it shouldn’t), trigger a Bochs72 # breakpoint if running under Bochs, then loop.73 movw $0x8a00, %ax # 0x8a00 -> port 0x8a0074 movw %ax, %dx75 outw %ax, %dx76 movw $0x8ae0, %ax # 0x8ae0 -> port 0x8a0077 outw %ax, %dx78 spin:79 jmp spin80 81 # Bootstrap GDT82 .p2align 2 # force 4 byte alignment83 gdt:84 SEG_NULLASM # null seg85 SEG_ASM(STA_X|STA_R, 0x0, 0xffffffff) # code seg86 SEG_ASM(STA_W, 0x0, 0xffffffff) # data seg87 88 gdtdesc:89 .word (gdtdesc - gdt - 1) # sizeof(gdt) - 190 .long gdt # address gdt
xv6/bootmain.c
1 // Boot loader. 2 // 3 // Part of the boot sector, along with bootasm.S, which calls bootmain(). 4 // bootasm.S has put the processor into protected 32-bit mode. 5 // bootmain() loads an ELF kernel image from the disk starting at 6 // sector 1 and then jumps to the kernel entry routine. 7 8 #include "types.h" 9 #include "elf.h"10 #include "x86.h"11 #include "memlayout.h"12 13 #define SECTSIZE 51214 15 void readseg(uchar*, uint, uint);16 17 void18 bootmain(void)19 {20 struct elfhdr *elf;21 struct proghdr *ph, *eph;22 void (*entry)(void);23 uchar* pa;24 25 elf = (struct elfhdr*)0x10000; // scratch space26 27 // Read 1st page off disk28 readseg((uchar*)elf, 4096, 0);29 30 // Is this an ELF executable?31 if(elf->magic != ELF_MAGIC)32 return; // let bootasm.S handle error33 34 // Load each program segment (ignores ph flags).35 ph = (struct proghdr*)((uchar*)elf + elf->phoff);36 eph = ph + elf->phnum;37 for(; ph < eph; ph++){38 pa = (uchar*)ph->paddr;39 readseg(pa, ph->filesz, ph->off);40 if(ph->memsz > ph->filesz)41 stosb(pa + ph->filesz, 0, ph->memsz - ph->filesz);42 }43 44 // Call the entry point from the ELF header.45 // Does not return!46 entry = (void(*)(void))(elf->entry);47 entry();48 }49 50 51 void52 waitdisk(void)53 {54 // Wait for disk ready.55 while((inb(0x1F7) & 0xC0) != 0x40)56 ;57 }58 59 // Read a single sector at offset into dst.60 void61 readsect(void *dst, uint offset)62 {63 // Issue command.64 waitdisk();65 outb(0x1F2, 1); // count = 166 outb(0x1F3, offset);67 outb(0x1F4, offset >> 8);68 outb(0x1F5, offset >> 16);69 outb(0x1F6, (offset >> 24) | 0xE0);70 outb(0x1F7, 0x20); // cmd 0x20 - read sectors71 72 // Read data.73 waitdisk();74 insl(0x1F0, dst, SECTSIZE/4);75 }76 77 // Read ’count’ bytes at ’offset’ from kernel into physical address ’pa’.78 // Might copy more than asked.79 void80 readseg(uchar* pa, uint count, uint offset)81 {82 uchar* epa;83 84 epa = pa + count;85 86 // Round down to sector boundary.87 pa -= offset % SECTSIZE;88 89 // Translate from bytes to sectors; kernel starts at sector 1.90 offset = (offset / SECTSIZE) + 1;91 92 // If this is too slow, we could read lots of sectors at a time.93 // We’d write more to memory than asked, but it doesn’t matter --94 // we load in increasing order.95 for(; pa < epa; pa += SECTSIZE, offset++)96 readsect(pa, offset);97 }
xv6/bootasm.S + xv6/bootmain.c
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。