📄 grub-mkimage.c
字号:
Elf32_Word size = grub_le_to_cpu32 (s->sh_size); const char *name = strtab + grub_le_to_cpu32 (s->sh_name); if (align) { addr = align_address (current_address, align); if (current_address != addr) { grub_util_info ("padding %d bytes for the ELF section alignment", addr - current_address); write_padding (out, addr - current_address); current_address = addr; } } grub_util_info ("writing the text section %s at 0x%x", name, current_address); if (fwrite ((char *) e + offset, size, 1, out) != 1) grub_util_error ("write failed"); current_address += size; } addr = align_pe32_section (current_address); if (addr != current_address) { grub_util_info ("padding %d bytes for the PE32 section alignment", addr - current_address); write_padding (out, addr - current_address); } return addr;}/* Write data sections. */static Elf32_Addrwrite_data_sections (FILE *out, Elf32_Addr current_address, Elf32_Ehdr *e, Elf32_Shdr *sections, Elf32_Half section_entsize, Elf32_Half num_sections, const char *strtab){ Elf32_Half i; Elf32_Shdr *s; Elf32_Addr addr; for (i = 0, s = sections; i < num_sections; i++, s = (Elf32_Shdr *) ((char *) s + section_entsize)) if (is_data_section (s)) { Elf32_Word align = grub_le_to_cpu32 (s->sh_addralign); Elf32_Off offset = grub_le_to_cpu32 (s->sh_offset); Elf32_Word size = grub_le_to_cpu32 (s->sh_size); const char *name = strtab + grub_le_to_cpu32 (s->sh_name); if (align) { addr = align_address (current_address, align); if (current_address != addr) { grub_util_info ("padding %d bytes for the ELF section alignment", addr - current_address); write_padding (out, addr - current_address); current_address = addr; } } grub_util_info ("writing the data section %s at 0x%x", name, current_address); if (s->sh_type == grub_cpu_to_le32 (SHT_NOBITS)) write_padding (out, size); else if (fwrite ((char *) e + offset, size, 1, out) != 1) grub_util_error ("write failed"); current_address += size; } addr = align_pe32_section (current_address); if (addr != current_address) { grub_util_info ("padding %d bytes for the PE32 section alignment", addr - current_address); write_padding (out, addr - current_address); } return addr;}/* Write modules. */static Elf32_Addrmake_mods_section (FILE *out, Elf32_Addr current_address, const char *dir, char *mods[]){ struct grub_util_path_list *path_list; grub_size_t total_module_size; struct grub_util_path_list *p; struct grub_module_info modinfo; Elf32_Addr addr; path_list = grub_util_resolve_dependencies (dir, "moddep.lst", mods); total_module_size = sizeof (struct grub_module_info); for (p = path_list; p; p = p->next) { total_module_size += (grub_util_get_image_size (p->name) + sizeof (struct grub_module_header)); } grub_util_info ("the total module size is 0x%x", total_module_size); modinfo.magic = grub_cpu_to_le32 (GRUB_MODULE_MAGIC); modinfo.offset = grub_cpu_to_le32 (sizeof (modinfo)); modinfo.size = grub_cpu_to_le32 (total_module_size); if (fwrite (&modinfo, sizeof (modinfo), 1, out) != 1) grub_util_error ("write failed"); for (p = path_list; p; p = p->next) { struct grub_module_header header; size_t mod_size; char *mod_image; grub_util_info ("adding module %s", p->name); mod_size = grub_util_get_image_size (p->name); header.offset = grub_cpu_to_le32 (sizeof (header)); header.size = grub_cpu_to_le32 (mod_size + sizeof (header)); mod_image = grub_util_read_image (p->name); if (fwrite (&header, sizeof (header), 1, out) != 1 || fwrite (mod_image, mod_size, 1, out) != 1) grub_util_error ("write failed"); free (mod_image); } for (p = path_list; p; ) { struct grub_util_path_list *q; q = p->next; free (p); p = q; } current_address += total_module_size; addr = align_pe32_section (current_address); if (addr != current_address) { grub_util_info ("padding %d bytes for the PE32 section alignment", addr - current_address); write_padding (out, addr - current_address); } return addr;}/* Make a .reloc section. */static Elf32_Addrmake_reloc_section (FILE *out, Elf32_Addr current_address, Elf32_Ehdr *e, Elf32_Addr *section_addresses, Elf32_Shdr *sections, Elf32_Half section_entsize, Elf32_Half num_sections, const char *strtab){ Elf32_Half i; Elf32_Shdr *s; struct grub_pe32_fixup_block *fixup_block = 0; for (i = 0, s = sections; i < num_sections; i++, s = (Elf32_Shdr *) ((char *) s + section_entsize)) if (s->sh_type == grub_cpu_to_le32 (SHT_REL)) { Elf32_Rel *r; Elf32_Word rtab_size, r_size, num_rs; Elf32_Off rtab_offset; Elf32_Addr section_address; Elf32_Word j; grub_util_info ("translating the relocation section %s", strtab + grub_le_to_cpu32 (s->sh_name)); rtab_size = grub_le_to_cpu32 (s->sh_size); r_size = grub_le_to_cpu32 (s->sh_entsize); rtab_offset = grub_le_to_cpu32 (s->sh_offset); num_rs = rtab_size / r_size; section_address = section_addresses[grub_le_to_cpu32 (s->sh_info)]; for (j = 0, r = (Elf32_Rel *) ((char *) e + rtab_offset); j < num_rs; j++, r = (Elf32_Rel *) ((char *) r + r_size)) { Elf32_Word info; Elf32_Addr offset; offset = grub_le_to_cpu32 (r->r_offset); info = grub_le_to_cpu32 (r->r_info); /* Necessary to relocate only absolute addresses. */ if (ELF32_R_TYPE (info) == R_386_32) { Elf32_Addr addr; addr = section_address + offset; grub_util_info ("adding a relocation entry for 0x%x", addr); current_address = add_fixup_entry (&fixup_block, GRUB_PE32_REL_BASED_HIGHLOW, addr, 0, current_address, out); } } } current_address = add_fixup_entry (&fixup_block, 0, 0, 1, current_address, out); return current_address;}/* Create the header. */static voidmake_header (FILE *out, Elf32_Addr text_address, Elf32_Addr data_address, Elf32_Addr mods_address, Elf32_Addr reloc_address, Elf32_Addr end_address, Elf32_Addr start_address){ struct grub_pe32_header header; struct grub_pe32_coff_header *c; struct grub_pe32_optional_header *o; struct grub_pe32_section_table text_section, data_section; struct grub_pe32_section_table mods_section, reloc_section; /* The magic. */ memset (&header, 0, sizeof (header)); memcpy (header.msdos_stub, stub, sizeof (header.msdos_stub)); memcpy (header.signature, "PE\0\0", sizeof (header.signature)); /* The COFF file header. */ c = &header.coff_header; c->machine = grub_cpu_to_le16 (GRUB_PE32_MACHINE_I386); c->num_sections = grub_cpu_to_le16 (4); c->time = grub_cpu_to_le32 (time (0)); c->optional_header_size = grub_cpu_to_le16 (sizeof (header.optional_header)); c->characteristics = grub_cpu_to_le16 (GRUB_PE32_EXECUTABLE_IMAGE | GRUB_PE32_LINE_NUMS_STRIPPED | GRUB_PE32_LOCAL_SYMS_STRIPPED | GRUB_PE32_32BIT_MACHINE); /* The PE Optional header. */ o = &header.optional_header; o->magic = grub_cpu_to_le16 (GRUB_PE32_PE32_MAGIC); o->code_size = grub_cpu_to_le32 (data_address - text_address); o->data_size = grub_cpu_to_le32 (reloc_address - data_address); o->bss_size = 0; o->entry_addr = grub_cpu_to_le32 (start_address); o->code_base = grub_cpu_to_le32 (text_address); o->data_base = grub_cpu_to_le32 (data_address); o->image_base = 0; o->section_alignment = grub_cpu_to_le32 (GRUB_PE32_SECTION_ALIGNMENT); o->file_alignment = grub_cpu_to_le32 (GRUB_PE32_FILE_ALIGNMENT); o->image_size = grub_cpu_to_le32 (end_address); o->header_size = grub_cpu_to_le32 (text_address); o->subsystem = grub_cpu_to_le16 (GRUB_PE32_SUBSYSTEM_EFI_APPLICATION); /* Do these really matter? */ o->stack_reserve_size = grub_cpu_to_le32 (0x10000); o->stack_commit_size = grub_cpu_to_le32 (0x10000); o->heap_reserve_size = grub_cpu_to_le32 (0x10000); o->heap_commit_size = grub_cpu_to_le32 (0x10000); o->num_data_directories = grub_cpu_to_le32 (GRUB_PE32_NUM_DATA_DIRECTORIES); o->base_relocation_table.rva = grub_cpu_to_le32 (reloc_address); o->base_relocation_table.size = grub_cpu_to_le32 (end_address - reloc_address); /* The sections. */ memset (&text_section, 0, sizeof (text_section)); strcpy (text_section.name, ".text"); text_section.virtual_size = grub_cpu_to_le32 (data_address - text_address); text_section.virtual_address = grub_cpu_to_le32 (text_address); text_section.raw_data_size = grub_cpu_to_le32 (data_address - text_address); text_section.raw_data_offset = grub_cpu_to_le32 (text_address); text_section.characteristics = grub_cpu_to_le32 (GRUB_PE32_SCN_CNT_CODE | GRUB_PE32_SCN_MEM_EXECUTE | GRUB_PE32_SCN_MEM_READ); memset (&data_section, 0, sizeof (data_section)); strcpy (data_section.name, ".data"); data_section.virtual_size = grub_cpu_to_le32 (mods_address - data_address); data_section.virtual_address = grub_cpu_to_le32 (data_address); data_section.raw_data_size = grub_cpu_to_le32 (mods_address - data_address); data_section.raw_data_offset = grub_cpu_to_le32 (data_address); data_section.characteristics = grub_cpu_to_le32 (GRUB_PE32_SCN_CNT_INITIALIZED_DATA | GRUB_PE32_SCN_MEM_READ | GRUB_PE32_SCN_MEM_WRITE); memset (&mods_section, 0, sizeof (mods_section)); strcpy (mods_section.name, "mods"); mods_section.virtual_size = grub_cpu_to_le32 (reloc_address - mods_address); mods_section.virtual_address = grub_cpu_to_le32 (mods_address); mods_section.raw_data_size = grub_cpu_to_le32 (reloc_address - mods_address); mods_section.raw_data_offset = grub_cpu_to_le32 (mods_address); mods_section.characteristics = grub_cpu_to_le32 (GRUB_PE32_SCN_CNT_INITIALIZED_DATA | GRUB_PE32_SCN_MEM_READ | GRUB_PE32_SCN_MEM_WRITE); memset (&reloc_section, 0, sizeof (reloc_section)); strcpy (reloc_section.name, ".reloc"); reloc_section.virtual_size = grub_cpu_to_le32 (end_address - reloc_address); reloc_section.virtual_address = grub_cpu_to_le32 (reloc_address); reloc_section.raw_data_size = grub_cpu_to_le32 (end_address - reloc_address); reloc_section.raw_data_offset = grub_cpu_to_le32 (reloc_address); reloc_section.characteristics = grub_cpu_to_le32 (GRUB_PE32_SCN_CNT_INITIALIZED_DATA | GRUB_PE32_SCN_MEM_DISCARDABLE | GRUB_PE32_SCN_MEM_READ); /* Write them out. */ if (fseek (out, 0, SEEK_SET) < 0) grub_util_error ("seek failed"); if (fwrite (&header, sizeof (header), 1, out) != 1 || fwrite (&text_section, sizeof (text_section), 1, out) != 1 || fwrite (&data_section, sizeof (data_section), 1, out) != 1 || fwrite (&mods_section, sizeof (mods_section), 1, out) != 1 || fwrite (&reloc_section, sizeof (reloc_section), 1, out) != 1) grub_util_error ("write failed");}/* Convert an ELF relocatable object into an EFI Application (PE32). */voidconvert_elf (const char *dir, FILE *out, char *mods[]){ char *kernel_image; size_t kernel_size; const char *strtab; Elf32_Ehdr *e; Elf32_Shdr *sections; Elf32_Off section_offset; Elf32_Half section_entsize; Elf32_Half num_sections; Elf32_Addr *section_addresses; Elf32_Shdr *symtab_section; Elf32_Addr start_address; Elf32_Addr text_address, data_address, reloc_address, mods_address; Elf32_Addr end_address; /* Get the kernel image and check the format. */ kernel_image = read_kernel_module (dir, &kernel_size); e = (Elf32_Ehdr *) kernel_image; if (! check_elf_header (e, kernel_size)) grub_util_error ("invalid ELF header"); section_offset = grub_cpu_to_le32 (e->e_shoff); section_entsize = grub_cpu_to_le16 (e->e_shentsize); num_sections = grub_cpu_to_le16 (e->e_shnum); if (kernel_size < section_offset + section_entsize * num_sections) grub_util_error ("invalid ELF format"); sections = (Elf32_Shdr *) (kernel_image + section_offset); strtab = find_strtab (e, sections, section_entsize); /* Relocate sections then symbols in the virtual address space. */ section_addresses = locate_sections (sections, section_entsize, num_sections, strtab); symtab_section = find_symtab_section (sections, section_entsize, num_sections); if (! symtab_section) grub_util_error ("no symbol table"); start_address = relocate_symbols (e, sections, symtab_section, section_addresses, section_entsize, num_sections); if (start_address == 0) grub_util_error ("start symbol is not defined"); /* Resolve addresses in the virtual address space. */ relocate_addresses (e, sections, section_addresses, section_entsize, num_sections, strtab); /* Generate a PE32 image file. The strategy is to dump binary data first, then fill up the header. */ text_address = make_header_space (out); data_address = write_text_sections (out, text_address, e, sections, section_entsize, num_sections, strtab); mods_address = write_data_sections (out, data_address, e, sections, section_entsize, num_sections, strtab); reloc_address = make_mods_section (out, mods_address, dir, mods); end_address = make_reloc_section (out, reloc_address, e, section_addresses, sections, section_entsize, num_sections, strtab); make_header (out, text_address, data_address, mods_address, reloc_address, end_address, start_address); /* Clean up. */ free (section_addresses); free (kernel_image);}static struct option options[] = { {"directory", required_argument, 0, 'd'}, {"output", required_argument, 0, 'o'}, {"help", no_argument, 0, 'h'}, {"version", no_argument, 0, 'V'}, {"verbose", no_argument, 0, 'v'}, { 0, 0, 0, 0 } };static voidusage (int status){ if (status) fprintf (stderr, "Try ``grub-mkimage --help'' for more information.\n"); else printf ("\Usage: grub-mkimage -o FILE [OPTION]... [MODULES]\n\\n\Make a bootable image of GRUB.\n\\n\-d, --directory=DIR use images and modules under DIR [default=%s]\n\-o, --output=FILE output a generated image to FILE\n\-h, --help display this message and exit\n\-V, --version print version information and exit\n\-v, --verbose print verbose messages\n\\n\Report bugs to <%s>.\n\", GRUB_LIBDIR, PACKAGE_BUGREPORT); exit (status);}intmain (int argc, char *argv[]){ FILE *fp; char *output = NULL; char *dir = NULL; progname = "grub-mkimage"; while (1) { int c = getopt_long (argc, argv, "d:o:hVv", options, 0); if (c == -1) break; switch (c) { case 'd': if (dir) free (dir); dir = xstrdup (optarg); break; case 'h': usage (0); break; case 'o': if (output) free (output); output = xstrdup (optarg); break; case 'V': printf ("grub-mkimage (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION); return 0; case 'v': verbosity++; break; default: usage (1); break; } } if (! output) usage (1); fp = fopen (output, "wb"); if (! fp) grub_util_error ("cannot open %s", output); convert_elf (dir ? : GRUB_LIBDIR, fp, argv + optind); fclose (fp); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -