📄 boot.c
字号:
printf (", C"); printf (", data=0x%x", data_len); if ((grub_read ((char *) RAW_ADDR (cur_addr), data_len) != data_len) && !errnum) errnum = ERR_EXEC_FORMAT; cur_addr += data_len; } if (!errnum) { memset ((char *) RAW_ADDR (cur_addr), 0, bss_len); cur_addr += bss_len; printf (", bss=0x%x", bss_len); } } else if (!errnum) errnum = ERR_EXEC_FORMAT; if (!errnum && pu.aout->a_syms && pu.aout->a_syms < (filemax - filepos)) { int symtab_err, orig_addr = cur_addr; /* we should align to a 4K boundary here for good measure */ if (align_4k) cur_addr = (cur_addr + 0xFFF) & 0xFFFFF000; mbi.syms.a.addr = cur_addr; *((int *) RAW_ADDR (cur_addr)) = pu.aout->a_syms; cur_addr += sizeof (int); printf (", symtab=0x%x", pu.aout->a_syms); if (grub_read ((char *) RAW_ADDR (cur_addr), pu.aout->a_syms) == pu.aout->a_syms) { cur_addr += pu.aout->a_syms; mbi.syms.a.tabsize = pu.aout->a_syms; if (grub_read ((char *) &i, sizeof (int)) == sizeof (int)) { *((int *) RAW_ADDR (cur_addr)) = i; cur_addr += sizeof (int); mbi.syms.a.strsize = i; i -= sizeof (int); printf (", strtab=0x%x", i); symtab_err = (grub_read ((char *) RAW_ADDR (cur_addr), i) != i); cur_addr += i; } else symtab_err = 1; } else symtab_err = 1; if (symtab_err) { printf ("(bad)"); cur_addr = orig_addr; mbi.syms.a.tabsize = 0; mbi.syms.a.strsize = 0; mbi.syms.a.addr = 0; } else mbi.flags |= MB_INFO_AOUT_SYMS; } } else /* ELF executable */ { unsigned loaded = 0, memaddr, memsiz, filesiz; Elf32_Phdr *phdr; /* reset this to zero for now */ cur_addr = 0; /* scan for program segments */ for (i = 0; i < pu.elf->e_phnum; i++) { phdr = (Elf32_Phdr *) (pu.elf->e_phoff + ((int) buffer) + (pu.elf->e_phentsize * i)); if (phdr->p_type == PT_LOAD) { /* offset into file */ grub_seek (phdr->p_offset); filesiz = phdr->p_filesz; if (type == KERNEL_TYPE_FREEBSD || type == KERNEL_TYPE_NETBSD) memaddr = RAW_ADDR (phdr->p_paddr & 0xFFFFFF); else memaddr = RAW_ADDR (phdr->p_paddr); memsiz = phdr->p_memsz; if (memaddr < RAW_ADDR (0x100000)) errnum = ERR_BELOW_1MB; /* If the memory range contains the entry address, get the physical address here. */ if (type == KERNEL_TYPE_MULTIBOOT && (unsigned) entry_addr >= phdr->p_vaddr && (unsigned) entry_addr < phdr->p_vaddr + memsiz) real_entry_addr = (entry_func) ((unsigned) entry_addr + memaddr - phdr->p_vaddr); /* make sure we only load what we're supposed to! */ if (filesiz > memsiz) filesiz = memsiz; /* mark memory as used */ if (cur_addr < memaddr + memsiz) cur_addr = memaddr + memsiz; printf (", <0x%x:0x%x:0x%x>", memaddr, filesiz, memsiz - filesiz); /* increment number of segments */ loaded++; /* load the segment */ if (memcheck (memaddr, memsiz) && grub_read ((char *) memaddr, filesiz) == filesiz) { if (memsiz > filesiz) memset ((char *) (memaddr + filesiz), 0, memsiz - filesiz); } else break; } } if (! errnum) { if (! loaded) errnum = ERR_EXEC_FORMAT; else { /* Load ELF symbols. */ Elf32_Shdr *shdr = NULL; int tab_size, sec_size; int symtab_err = 0; mbi.syms.e.num = pu.elf->e_shnum; mbi.syms.e.size = pu.elf->e_shentsize; mbi.syms.e.shndx = pu.elf->e_shstrndx; /* We should align to a 4K boundary here for good measure. */ if (align_4k) cur_addr = (cur_addr + 0xFFF) & 0xFFFFF000; tab_size = pu.elf->e_shentsize * pu.elf->e_shnum; grub_seek (pu.elf->e_shoff); if (grub_read ((char *) RAW_ADDR (cur_addr), tab_size) == tab_size) { mbi.syms.e.addr = cur_addr; shdr = (Elf32_Shdr *) mbi.syms.e.addr; cur_addr += tab_size; printf (", shtab=0x%x", cur_addr); for (i = 0; i < mbi.syms.e.num; i++) { /* This section is a loaded section, so we don't care. */ if (shdr[i].sh_addr != 0) continue; /* This section is empty, so we don't care. */ if (shdr[i].sh_size == 0) continue; /* Align the section to a sh_addralign bits boundary. */ cur_addr = ((cur_addr + shdr[i].sh_addralign) & - (int) shdr[i].sh_addralign); grub_seek (shdr[i].sh_offset); sec_size = shdr[i].sh_size; if (! (memcheck (cur_addr, sec_size) && (grub_read ((char *) RAW_ADDR (cur_addr), sec_size) == sec_size))) { symtab_err = 1; break; } shdr[i].sh_addr = cur_addr; cur_addr += sec_size; } } else symtab_err = 1; if (mbi.syms.e.addr < RAW_ADDR(0x10000)) symtab_err = 1; if (symtab_err) { printf ("(bad)"); mbi.syms.e.num = 0; mbi.syms.e.size = 0; mbi.syms.e.addr = 0; mbi.syms.e.shndx = 0; cur_addr = 0; } else mbi.flags |= MB_INFO_ELF_SHDR; } } } if (! errnum) { grub_printf (", entry=0x%x]\n", (unsigned) entry_addr); /* If the entry address is physically different from that of the ELF header, correct it here. */ if (real_entry_addr) entry_addr = real_entry_addr; } else { putchar ('\n'); type = KERNEL_TYPE_NONE; } grub_close (); /* Sanity check. */ if (suggested_type != KERNEL_TYPE_NONE && suggested_type != type) { errnum = ERR_EXEC_FORMAT; return KERNEL_TYPE_NONE; } return type;}intload_module (char *module, char *arg){ int len; /* if we are supposed to load on 4K boundaries */ cur_addr = (cur_addr + 0xFFF) & 0xFFFFF000; if (!grub_open (module)) return 0; len = grub_read ((char *) cur_addr, -1); if (! len) { grub_close (); return 0; } printf (" [Multiboot-module @ 0x%x, 0x%x bytes]\n", cur_addr, len); /* these two simply need to be set if any modules are loaded at all */ mbi.flags |= MB_INFO_MODS; mbi.mods_addr = (int) mll; mll[mbi.mods_count].cmdline = (int) arg; mll[mbi.mods_count].mod_start = cur_addr; cur_addr += len; mll[mbi.mods_count].mod_end = cur_addr; mll[mbi.mods_count].pad = 0; /* increment number of modules included */ mbi.mods_count++; grub_close (); return 1;}intload_initrd (char *initrd){ int len; unsigned long moveto; unsigned long max_addr; struct linux_kernel_header *lh = (struct linux_kernel_header *) (cur_addr - LINUX_SETUP_MOVE_SIZE); #ifndef NO_DECOMPRESSION no_decompression = 1;#endif if (! grub_open (initrd)) goto fail; len = grub_read ((char *) cur_addr, -1); if (! len) { grub_close (); goto fail; } if (linux_mem_size) moveto = linux_mem_size; else moveto = (mbi.mem_upper + 0x400) << 10; moveto = (moveto - len) & 0xfffff000; max_addr = (lh->header == LINUX_MAGIC_SIGNATURE && lh->version >= 0x0203 ? lh->initrd_addr_max : LINUX_INITRD_MAX_ADDRESS); if (moveto + len >= max_addr) moveto = (max_addr - len) & 0xfffff000; /* XXX: Linux 2.3.xx has a bug in the memory range check, so avoid the last page. XXX: Linux 2.2.xx has a bug in the memory range check, which is worse than that of Linux 2.3.xx, so avoid the last 64kb. *sigh* */ moveto -= 0x10000; memmove ((void *) RAW_ADDR (moveto), (void *) cur_addr, len); printf (" [Linux-initrd @ 0x%x, 0x%x bytes]\n", moveto, len); /* FIXME: Should check if the kernel supports INITRD. */ lh->ramdisk_image = RAW_ADDR (moveto); lh->ramdisk_size = len; grub_close (); fail: #ifndef NO_DECOMPRESSION no_decompression = 0;#endif return ! errnum;}#ifdef GRUB_UTIL/* Dummy function to fake the *BSD boot. */static voidbsd_boot_entry (int flags, int bootdev, int sym_start, int sym_end, int mem_upper, int mem_lower){ stop ();}#endif/* * All "*_boot" commands depend on the images being loaded into memory * correctly, the variables in this file being set up correctly, and * the root partition being set in the 'saved_drive' and 'saved_partition' * variables. */voidbsd_boot (kernel_t type, int bootdev, char *arg){ char *str; int clval = 0, i; struct bootinfo bi;#ifdef GRUB_UTIL entry_addr = (entry_func) bsd_boot_entry;#else stop_floppy ();#endif while (*(++arg) && *arg != ' '); str = arg; while (*str) { if (*str == '-') { while (*str && *str != ' ') { if (*str == 'C') clval |= RB_CDROM; if (*str == 'a') clval |= RB_ASKNAME; if (*str == 'b') clval |= RB_HALT; if (*str == 'c') clval |= RB_CONFIG; if (*str == 'd') clval |= RB_KDB; if (*str == 'D') clval |= RB_MULTIPLE; if (*str == 'g') clval |= RB_GDB; if (*str == 'h') clval |= RB_SERIAL; if (*str == 'm') clval |= RB_MUTE; if (*str == 'r') clval |= RB_DFLTROOT; if (*str == 's') clval |= RB_SINGLE; if (*str == 'v') clval |= RB_VERBOSE; str++; } continue; } str++; } if (type == KERNEL_TYPE_FREEBSD) { clval |= RB_BOOTINFO; bi.bi_version = BOOTINFO_VERSION; *arg = 0; while ((--arg) > (char *) MB_CMDLINE_BUF && *arg != '/'); if (*arg == '/') bi.bi_kernelname = arg + 1; else bi.bi_kernelname = 0; bi.bi_nfs_diskless = 0; bi.bi_n_bios_used = 0; /* this field is apparently unused */ for (i = 0; i < N_BIOS_GEOM; i++) { struct geometry geom; /* XXX Should check the return value. */ get_diskinfo (i + 0x80, &geom); /* FIXME: If HEADS or SECTORS is greater than 255, then this will break the geometry information. That is a drawback of BSD but not of GRUB. */ bi.bi_bios_geom[i] = (((geom.cylinders - 1) << 16) + (((geom.heads - 1) & 0xff) << 8) + (geom.sectors & 0xff)); } bi.bi_size = sizeof (struct bootinfo); bi.bi_memsizes_valid = 1; bi.bi_bios_dev = saved_drive; bi.bi_basemem = mbi.mem_lower; bi.bi_extmem = extended_memory; if (mbi.flags & MB_INFO_AOUT_SYMS) { bi.bi_symtab = mbi.syms.a.addr; bi.bi_esymtab = mbi.syms.a.addr + 4 + mbi.syms.a.tabsize + mbi.syms.a.strsize; }#if 0 else if (mbi.flags & MB_INFO_ELF_SHDR) { /* FIXME: Should check if a symbol table exists and, if exists, pass the table to BI. */ }#endif else { bi.bi_symtab = 0; bi.bi_esymtab = 0; } /* call entry point */ (*entry_addr) (clval, bootdev, 0, 0, 0, ((int) (&bi))); } else { /* * We now pass the various bootstrap parameters to the loaded * image via the argument list. * * This is the official list: * * arg0 = 8 (magic) * arg1 = boot flags * arg2 = boot device * arg3 = start of symbol table (0 if not loaded) * arg4 = end of symbol table (0 if not loaded) * arg5 = transfer address from image * arg6 = transfer address for next image pointer * arg7 = conventional memory size (640) * arg8 = extended memory size (8196) * * ...in actuality, we just pass the parameters used by the kernel. */ /* call entry point */ unsigned long end_mark; if (mbi.flags & MB_INFO_AOUT_SYMS) end_mark = (mbi.syms.a.addr + 4 + mbi.syms.a.tabsize + mbi.syms.a.strsize); else /* FIXME: it should be mbi.syms.e.size. */ end_mark = 0; (*entry_addr) (clval, bootdev, 0, end_mark, extended_memory, mbi.mem_lower); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -