// File: bootmain.c// Line: 43-61/* readsect - read a single sector at @secno into @dst */staticvoidreadsect(void*dst,uint32_t secno) {// wait for disk to be readywaitdisk();outb(0x1F2,1); // count = 1outb(0x1F3, secno &0xFF);outb(0x1F4, (secno >>8) &0xFF);outb(0x1F5, (secno >>16) &0xFF);outb(0x1F6, ((secno >>24) &0xF) |0xE0);outb(0x1F7,0x20); // cmd 0x20 - read sectors// wait for disk to be readywaitdisk();// read a sectorinsl(0x1F0, dst, SECTSIZE /4);}
其中,waitdisk函数的代码为:
// File: bootmain.c// Line: 36-41/* waitdisk - wait for disk ready */staticvoidwaitdisk(void) {while ((inb(0x1F7)&0xC0) !=0x40) /* do nothing */;}
// File: elf.h// Line: 8-25/* file header */struct elfhdr {uint32_t e_magic; // must equal ELF_MAGICuint8_t e_elf[12];uint16_t e_type; // 1=relocatable, 2=executable, 3=shared object, 4=core imageuint16_t e_machine; // 3=x86, 4=68K, etc.uint32_t e_version; // file version, always 1uint32_t e_entry; // entry point if executableuint32_t e_phoff; // file position of program header or 0uint32_t e_shoff; // file position of section header or 0uint32_t e_flags; // architecture-specific flags, usually 0uint16_t e_ehsize; // size of this elf headeruint16_t e_phentsize; // size of an entry in program headeruint16_t e_phnum; // number of entries in program header or 0uint16_t e_shentsize; // size of an entry in section headeruint16_t e_shnum; // number of entries in section header or 0uint16_t e_shstrndx; // section number that contains section name strings};
问题分析
bootloader是如何加载ELF格式的OS
参考代码:
// File: bootmain.c// Line: 85-115/* bootmain - the entry of bootloader */voidbootmain(void) {// read the 1st page off diskreadseg((uintptr_t)ELFHDR, SECTSIZE *8,0);// is this a valid ELF?if (ELFHDR->e_magic != ELF_MAGIC) {goto bad; }struct proghdr *ph,*eph;// load each program segment (ignores ph flags) ph = (struct proghdr *)((uintptr_t)ELFHDR +ELFHDR->e_phoff); eph = ph +ELFHDR->e_phnum;for (; ph < eph; ph ++) {readseg(ph->p_va &0xFFFFFF,ph->p_memsz,ph->p_offset); }// call the entry point from the ELF header// note: does not return ((void (*)(void))(ELFHDR->e_entry &0xFFFFFF))();bad:outw(0x8A00,0x8A00);outw(0x8A00,0x8E00); /* do nothing */while (1);}