⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mboot.c

📁 linux内核
💻 C
📖 第 1 页 / 共 3 页
字号:
                || 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, &regs, 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 + -