📄 mboot.c
字号:
|| ehdr->e_version != EV_CURRENT || ehdr->e_phentsize != sizeof (Elf32_Phdr)) { printf("Warning: funny-looking ELF header.\n"); } phdr = (Elf32_Phdr *)(load_addr + ehdr->e_phoff); /* Obey the program headers to load the kernel */ for(i = 0; i < ehdr->e_phnum; i++) { /* How much is in this segment? */ run_size = phdr[i].p_memsz; if (phdr[i].p_type != PT_LOAD) seg_size = 0; else seg_size = (size_t)phdr[i].p_filesz; /* Where is it in the loaded file? */ seg_addr = load_addr + phdr[i].p_offset; if (seg_addr + seg_size > load_addr + load_size) { printf("Fatal: ELF load segment runs off the " "end of the file.\n"); exit(1); } /* Skip segments that don't take up any memory */ if (run_size == 0) continue; /* Place the segment where it wants to be */ run_addr = phdr[i].p_paddr; place_kernel_section(run_addr, run_size); /* Put it on the relocation list */ if (seg_size < run_size) { /* Set up the kernel BSS too */ if (seg_size > 0) add_section(run_addr, seg_addr, seg_size); bss_size = run_size - seg_size; add_section(run_addr + seg_size, NULL, bss_size); } else { /* No BSS */ add_section(run_addr, seg_addr, run_size); } } /* Done! */ return ehdr->e_entry; } } /* This is not a multiboot kernel */ printf("Fatal: not a multiboot kernel.\n"); exit(1);}static void load_module(struct mod_list *mod, char *cmdline) /* Load a multiboot module and allocate a memory area for it */{ char *load_addr, *p; size_t load_size, run_addr; printf("Module: %s\n", cmdline); load_addr = 0; load_size = 0; p = strchr(cmdline, ' '); if (p != NULL) *p = 0; load_file(cmdline, &load_addr, &load_size); if (p != NULL) *p = ' '; /* Decide where it's going to live */ run_addr = place_module_section(load_size, X86_PAGE_SIZE); if (run_addr == 0) { printf("Fatal: can't find space for this module.\n"); exit(1); } add_section(run_addr, load_addr, load_size); /* Remember where we put it */ mod->mod_start = run_addr; mod->mod_end = run_addr + load_size; mod->pad = 0;#ifdef DEBUG printf("Placed module (%#8.8x+%#x)\n", run_addr, load_size);#endif}/* * Code for shuffling sections into place and booting the new kernel */static void trampoline_start(section_t *secs, int sec_count, size_t mbi_run_addr, size_t entry) /* Final shuffle-and-boot code. Running on the stack; no external code * or data can be relied on. */{ int i; struct lidt_operand idt; /* SYSLINUX has set up SS, DS and ES as 32-bit 0--4G data segments, * but doesn't specify FS and GS. Multiboot wants them all to be * the same, so we'd better do that before we overwrite the GDT. */ asm volatile("movl %ds, %ecx; movl %ecx, %fs; movl %ecx, %gs"); /* Turn off interrupts */ asm volatile("cli"); /* SYSLINUX has set up an IDT at 0x100000 that does all the * comboot calls, and we're about to overwrite it. The Multiboot * spec says that the kernel must set up its own IDT before turning * on interrupts, but it's still entitled to use BIOS calls, so we'll * put the IDT back to the BIOS one at the base of memory. */ idt.base = 0; idt.limit = 0x800; asm volatile("lidt %0" : : "m" (idt)); /* Now, shuffle the sections */ for (i = 0; i < sec_count; i++) { if (secs[i].src == NULL) { /* asm bzero() code from com32/lib/memset.c */ char *q = (char *) secs[i].dest; size_t nl = secs[i].size >> 2; asm volatile("cld ; rep ; stosl ; movl %3,%0 ; rep ; stosb" : "+c" (nl), "+D" (q) : "a" (0x0U), "r" (secs[i].size & 3)); } else { /* asm memmove() code from com32/lib/memmove.c */ const char *p = secs[i].src; char *q = (char *) secs[i].dest; size_t n = secs[i].size; if ( q < p ) { asm volatile("cld ; rep ; movsb" : "+c" (n), "+S" (p), "+D" (q)); } else { p += (n-1); q += (n-1); asm volatile("std ; rep ; movsb" : "+c" (n), "+S" (p), "+D" (q)); } } } /* Now set up the last tiny bit of Multiboot environment... */ asm volatile( /* A20 is already enabled. * CR0 already has PG cleared and PE set. * EFLAGS already has VM and IF cleared. * ESP is the kernels' problem. * GDTR is the kernel's problem. * CS is already a 32-bit, 0--4G code segments. * DS, ES, FS and GS are already 32-bit, 0--4G data segments. * EBX must point to the MBI: */ "movl %0, %%ebx;" /* EAX must be the Multiboot magic number. */ "movl $0x2badb002, %%eax;" /* Start the kernel. */ "jmp *%1" : : "m" (mbi_run_addr), "r" (entry)); }static void trampoline_end(void) {}static void boot(size_t mbi_run_addr, size_t entry) /* Tidy up SYSLINUX, shuffle memory and boot the kernel */{ com32sys_t regs; section_t *tr_sections; void (*trampoline)(section_t *, int, size_t, size_t); size_t trampoline_size; /* Make sure the relocations are safe. */ reorder_sections(); /* Copy the shuffle-and-boot code and the array of relocations * onto the memory we previously used for malloc() heap. This is * safe because it's not the source or the destination of any * copies, and there'll be no more library calls after the copy. */ tr_sections = ((section_t *) section_addr) + section_count; trampoline = (void *) (tr_sections + section_count); trampoline_size = (void *)&trampoline_end - (void *)&trampoline_start;#ifdef DEBUG printf("tr_sections: %p\n" "trampoline: %p\n" "trampoline_size: %#8.8x\n" "max_run_addr: %#8.8x\n", tr_sections, trampoline, trampoline_size, max_run_addr);#endif printf("Booting: MBI=%#8.8x, entry=%#8.8x\n", mbi_run_addr, entry); memmove(tr_sections, section_addr, section_count * sizeof (section_t)); memmove(trampoline, trampoline_start, trampoline_size); /* Tell SYSLINUX to clean up */ regs.eax.l = 0x000c; /* "Perform final cleanup" */ regs.edx.l = 0; /* "Normal cleanup" */ __intcall(0x22, ®s, NULL); /* Into the unknown */ trampoline(tr_sections, section_count, mbi_run_addr, entry);}int main(int argc, char **argv) /* Parse the command-line and invoke loaders */{ struct multiboot_info *mbi; struct mod_list *modp; int modules; int mbi_reloc_offset; char *p; size_t mbi_run_addr, mbi_size, entry; int i; /* Say hello */ console_ansi_std(); printf("%s. %s\n", version_string, copyright_string); if (argc < 2 || !strcmp(argv[1], module_separator)) { printf("Fatal: No kernel filename!\n"); exit(1); }#ifdef DEBUG printf("_end: %p\n" "argv[1]: %p\n" "next_load_addr: %p\n" "section_addr %p\n" "__mem_end: %p\n" "argv[0]: %p\n", &_end, argv[1], next_load_addr, section_addr, __mem_end, argv[0]);#endif /* How much space will the MBI need? */ modules = 0; mbi_size = sizeof(struct multiboot_info) + strlen(version_string) + 5; for (i = 1 ; i < argc ; i++) { if (!strcmp(argv[i], module_separator)) { modules++; mbi_size += sizeof(struct mod_list) + 1; } else { mbi_size += strlen(argv[i]) + 1; } } /* Allocate space in the load buffer for the MBI, all the command * lines, and all the module details. */ mbi = (struct multiboot_info *)next_load_addr; next_load_addr += mbi_size; if (next_load_addr > section_addr) { printf("Fatal: out of memory allocating for boot metadata.\n"); exit(1); } memset(mbi, 0, sizeof (struct multiboot_info)); p = (char *)(mbi + 1); mbi->flags = MB_INFO_CMDLINE | MB_INFO_BOOT_LOADER_NAME; /* Figure out the memory map. * N.B. Must happen before place_section() is called */ init_mmap(mbi); mbi_run_addr = place_low_section(mbi_size, 4); if (mbi_run_addr == 0) { printf("Fatal: can't find space for the MBI!\n"); exit(1); } mbi_reloc_offset = (size_t)mbi - mbi_run_addr; add_section(mbi_run_addr, (void *)mbi, mbi_size); /* Module info structs */ modp = (struct mod_list *) (((size_t)p + 3) & ~3); if (modules > 0) mbi->flags |= MB_INFO_MODS; mbi->mods_count = modules; mbi->mods_addr = ((size_t)modp) - mbi_reloc_offset; p = (char *)(modp + modules); /* Command lines: first kernel, then modules */ mbi->cmdline = ((size_t)p) - mbi_reloc_offset; modules = 0; for (i = 1 ; i < argc ; i++) { if (!strcmp(argv[i], module_separator)) { *p++ = '\0'; modp[modules++].cmdline = ((size_t)p) - mbi_reloc_offset; } else { strcpy(p, argv[i]); p += strlen(argv[i]); *p++ = ' '; } } *p++ = '\0'; /* Bootloader ID */ strcpy(p, version_string); mbi->boot_loader_name = ((size_t)p) - mbi_reloc_offset; p += strlen(version_string) + 1; /* Now, do all the loading, and boot it */ entry = load_kernel((char *)(mbi->cmdline + mbi_reloc_offset)); for (i=0; i<modules; i++) { load_module(&(modp[i]), (char *)(modp[i].cmdline + mbi_reloc_offset)); } boot(mbi_run_addr, entry); return 1;}/* * EOF */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -