📄 grub-mkimage.c
字号:
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, char *prefix, 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, prefix, &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'}, {"prefix", required_argument, 0, 'p'}, {"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\-p, --prefix=DIR set grub_prefix directory [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, DEFAULT_DIRECTORY, PACKAGE_BUGREPORT); exit (status);}intmain (int argc, char *argv[]){ FILE *fp; char *output = NULL; char *dir = NULL; char *prefix = NULL; progname = "grub-mkimage"; while (1) { int c = getopt_long (argc, argv, "d:p: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 'p': if (prefix) free (prefix); prefix = 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, prefix ? : DEFAULT_DIRECTORY, fp, argv + optind); fclose (fp); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -