]> git.proxmox.com Git - grub2.git/blob - util/grub-mkimage.c
* util/grub-fstest.c: Fix several printf formats.
[grub2.git] / util / grub-mkimage.c
1 /* grub-mkimage.c - make a bootable image */
2 /*
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009,2010 Free Software Foundation, Inc.
5 *
6 * GRUB is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * GRUB is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include <config.h>
21 #include <grub/types.h>
22 #include <grub/elf.h>
23 #include <grub/aout.h>
24 #include <grub/i18n.h>
25 #include <grub/kernel.h>
26 #include <grub/disk.h>
27 #include <grub/emu/misc.h>
28 #include <grub/util/misc.h>
29 #include <grub/util/resolve.h>
30 #include <grub/misc.h>
31 #include <grub/offsets.h>
32 #include <grub/crypto.h>
33 #include <grub/dl.h>
34 #include <time.h>
35 #include <multiboot.h>
36
37 #include <stdio.h>
38 #include <unistd.h>
39 #include <string.h>
40 #include <stdlib.h>
41 #include <assert.h>
42 #include <grub/efi/pe32.h>
43 #include <grub/uboot/image.h>
44 #include <grub/arm/reloc.h>
45 #include <grub/ia64/reloc.h>
46
47 #define _GNU_SOURCE 1
48 #include <argp.h>
49
50 #include "progname.h"
51
52 #define ALIGN_ADDR(x) (ALIGN_UP((x), image_target->voidp_sizeof))
53
54 #ifdef HAVE_LIBLZMA
55 #include <lzma.h>
56 #endif
57
58 #define TARGET_NO_FIELD 0xffffffff
59
60 typedef enum {
61 COMPRESSION_AUTO, COMPRESSION_NONE, COMPRESSION_XZ, COMPRESSION_LZMA
62 } grub_compression_t;
63
64 struct image_target_desc
65 {
66 const char *dirname;
67 const char *names[6];
68 grub_size_t voidp_sizeof;
69 int bigendian;
70 enum {
71 IMAGE_I386_PC, IMAGE_EFI, IMAGE_COREBOOT,
72 IMAGE_SPARC64_AOUT, IMAGE_SPARC64_RAW, IMAGE_SPARC64_CDCORE,
73 IMAGE_I386_IEEE1275,
74 IMAGE_LOONGSON_ELF, IMAGE_QEMU, IMAGE_PPC, IMAGE_YEELOONG_FLASH,
75 IMAGE_FULOONG2F_FLASH, IMAGE_I386_PC_PXE, IMAGE_MIPS_ARC,
76 IMAGE_QEMU_MIPS_FLASH, IMAGE_UBOOT
77 } id;
78 enum
79 {
80 PLATFORM_FLAGS_NONE = 0,
81 PLATFORM_FLAGS_DECOMPRESSORS = 2,
82 PLATFORM_FLAGS_MODULES_BEFORE_KERNEL = 4,
83 } flags;
84 unsigned total_module_size;
85 unsigned decompressor_compressed_size;
86 unsigned decompressor_uncompressed_size;
87 unsigned decompressor_uncompressed_addr;
88 unsigned link_align;
89 grub_uint16_t elf_target;
90 unsigned section_align;
91 signed vaddr_offset;
92 grub_uint64_t link_addr;
93 unsigned mod_gap, mod_align;
94 grub_compression_t default_compression;
95 grub_uint16_t pe_target;
96 };
97
98 #define EFI32_HEADER_SIZE ALIGN_UP (GRUB_PE32_MSDOS_STUB_SIZE \
99 + GRUB_PE32_SIGNATURE_SIZE \
100 + sizeof (struct grub_pe32_coff_header) \
101 + sizeof (struct grub_pe32_optional_header) \
102 + 4 * sizeof (struct grub_pe32_section_table), \
103 GRUB_PE32_SECTION_ALIGNMENT)
104
105 #define EFI64_HEADER_SIZE ALIGN_UP (GRUB_PE32_MSDOS_STUB_SIZE \
106 + GRUB_PE32_SIGNATURE_SIZE \
107 + sizeof (struct grub_pe32_coff_header) \
108 + sizeof (struct grub_pe64_optional_header) \
109 + 4 * sizeof (struct grub_pe32_section_table), \
110 GRUB_PE32_SECTION_ALIGNMENT)
111
112 struct image_target_desc image_targets[] =
113 {
114 {
115 .dirname = "i386-coreboot",
116 .names = { "i386-coreboot", NULL },
117 .voidp_sizeof = 4,
118 .bigendian = 0,
119 .id = IMAGE_COREBOOT,
120 .flags = PLATFORM_FLAGS_NONE,
121 .total_module_size = TARGET_NO_FIELD,
122 .decompressor_compressed_size = TARGET_NO_FIELD,
123 .decompressor_uncompressed_size = TARGET_NO_FIELD,
124 .decompressor_uncompressed_addr = TARGET_NO_FIELD,
125 .section_align = 1,
126 .vaddr_offset = 0,
127 .link_addr = GRUB_KERNEL_I386_COREBOOT_LINK_ADDR,
128 .elf_target = EM_386,
129 .link_align = 4,
130 .mod_gap = GRUB_KERNEL_I386_COREBOOT_MOD_GAP,
131 .mod_align = GRUB_KERNEL_I386_COREBOOT_MOD_ALIGN
132 },
133 {
134 .dirname = "i386-multiboot",
135 .names = { "i386-multiboot", NULL},
136 .voidp_sizeof = 4,
137 .bigendian = 0,
138 .id = IMAGE_COREBOOT,
139 .flags = PLATFORM_FLAGS_NONE,
140 .total_module_size = TARGET_NO_FIELD,
141 .decompressor_compressed_size = TARGET_NO_FIELD,
142 .decompressor_uncompressed_size = TARGET_NO_FIELD,
143 .decompressor_uncompressed_addr = TARGET_NO_FIELD,
144 .section_align = 1,
145 .vaddr_offset = 0,
146 .link_addr = GRUB_KERNEL_I386_COREBOOT_LINK_ADDR,
147 .elf_target = EM_386,
148 .link_align = 4,
149 .mod_gap = GRUB_KERNEL_I386_COREBOOT_MOD_GAP,
150 .mod_align = GRUB_KERNEL_I386_COREBOOT_MOD_ALIGN
151 },
152 {
153 .dirname = "i386-pc",
154 .names = { "i386-pc", NULL },
155 .voidp_sizeof = 4,
156 .bigendian = 0,
157 .id = IMAGE_I386_PC,
158 .flags = PLATFORM_FLAGS_DECOMPRESSORS,
159 .total_module_size = TARGET_NO_FIELD,
160 .decompressor_compressed_size = GRUB_DECOMPRESSOR_I386_PC_COMPRESSED_SIZE,
161 .decompressor_uncompressed_size = GRUB_DECOMPRESSOR_I386_PC_UNCOMPRESSED_SIZE,
162 .decompressor_uncompressed_addr = TARGET_NO_FIELD,
163 .section_align = 1,
164 .vaddr_offset = 0,
165 .link_addr = GRUB_KERNEL_I386_PC_LINK_ADDR,
166 .default_compression = COMPRESSION_LZMA
167 },
168 {
169 .dirname = "i386-pc",
170 .names = { "i386-pc-pxe", NULL },
171 .voidp_sizeof = 4,
172 .bigendian = 0,
173 .id = IMAGE_I386_PC_PXE,
174 .flags = PLATFORM_FLAGS_DECOMPRESSORS,
175 .total_module_size = TARGET_NO_FIELD,
176 .decompressor_compressed_size = GRUB_DECOMPRESSOR_I386_PC_COMPRESSED_SIZE,
177 .decompressor_uncompressed_size = GRUB_DECOMPRESSOR_I386_PC_UNCOMPRESSED_SIZE,
178 .decompressor_uncompressed_addr = TARGET_NO_FIELD,
179 .section_align = 1,
180 .vaddr_offset = 0,
181 .link_addr = GRUB_KERNEL_I386_PC_LINK_ADDR,
182 .default_compression = COMPRESSION_LZMA
183 },
184 {
185 .dirname = "i386-efi",
186 .names = { "i386-efi", NULL },
187 .voidp_sizeof = 4,
188 .bigendian = 0,
189 .id = IMAGE_EFI,
190 .flags = PLATFORM_FLAGS_NONE,
191 .total_module_size = TARGET_NO_FIELD,
192 .decompressor_compressed_size = TARGET_NO_FIELD,
193 .decompressor_uncompressed_size = TARGET_NO_FIELD,
194 .decompressor_uncompressed_addr = TARGET_NO_FIELD,
195 .section_align = GRUB_PE32_SECTION_ALIGNMENT,
196 .vaddr_offset = EFI32_HEADER_SIZE,
197 .pe_target = GRUB_PE32_MACHINE_I386,
198 .elf_target = EM_386,
199 },
200 {
201 .dirname = "i386-ieee1275",
202 .names = { "i386-ieee1275", NULL },
203 .voidp_sizeof = 4,
204 .bigendian = 0,
205 .id = IMAGE_I386_IEEE1275,
206 .flags = PLATFORM_FLAGS_NONE,
207 .total_module_size = TARGET_NO_FIELD,
208 .decompressor_compressed_size = TARGET_NO_FIELD,
209 .decompressor_uncompressed_size = TARGET_NO_FIELD,
210 .decompressor_uncompressed_addr = TARGET_NO_FIELD,
211 .section_align = 1,
212 .vaddr_offset = 0,
213 .link_addr = GRUB_KERNEL_I386_IEEE1275_LINK_ADDR,
214 .elf_target = EM_386,
215 .mod_gap = GRUB_KERNEL_I386_IEEE1275_MOD_GAP,
216 .mod_align = GRUB_KERNEL_I386_IEEE1275_MOD_ALIGN,
217 .link_align = 4,
218 },
219 {
220 .dirname = "i386-qemu",
221 .names = { "i386-qemu", NULL },
222 .voidp_sizeof = 4,
223 .bigendian = 0,
224 .id = IMAGE_QEMU,
225 .flags = PLATFORM_FLAGS_NONE,
226 .total_module_size = TARGET_NO_FIELD,
227 .decompressor_compressed_size = TARGET_NO_FIELD,
228 .decompressor_uncompressed_size = TARGET_NO_FIELD,
229 .decompressor_uncompressed_addr = TARGET_NO_FIELD,
230 .section_align = 1,
231 .vaddr_offset = 0,
232 .link_addr = GRUB_KERNEL_I386_QEMU_LINK_ADDR
233 },
234 {
235 .dirname = "x86_64-efi",
236 .names = { "x86_64-efi", NULL },
237 .voidp_sizeof = 8,
238 .bigendian = 0,
239 .id = IMAGE_EFI,
240 .flags = PLATFORM_FLAGS_NONE,
241 .total_module_size = TARGET_NO_FIELD,
242 .decompressor_compressed_size = TARGET_NO_FIELD,
243 .decompressor_uncompressed_size = TARGET_NO_FIELD,
244 .decompressor_uncompressed_addr = TARGET_NO_FIELD,
245 .section_align = GRUB_PE32_SECTION_ALIGNMENT,
246 .vaddr_offset = EFI64_HEADER_SIZE,
247 .pe_target = GRUB_PE32_MACHINE_X86_64,
248 .elf_target = EM_X86_64,
249 },
250 {
251 .dirname = "mipsel-loongson",
252 .names = { "mipsel-yeeloong-flash", NULL },
253 .voidp_sizeof = 4,
254 .bigendian = 0,
255 .id = IMAGE_YEELOONG_FLASH,
256 .flags = PLATFORM_FLAGS_DECOMPRESSORS,
257 .total_module_size = GRUB_KERNEL_MIPS_LOONGSON_TOTAL_MODULE_SIZE,
258 .decompressor_compressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_COMPRESSED_SIZE,
259 .decompressor_uncompressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_SIZE,
260 .decompressor_uncompressed_addr = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_ADDR,
261 .section_align = 1,
262 .vaddr_offset = 0,
263 .link_addr = GRUB_KERNEL_MIPS_LOONGSON_LINK_ADDR,
264 .elf_target = EM_MIPS,
265 .link_align = GRUB_KERNEL_MIPS_LOONGSON_LINK_ALIGN,
266 .default_compression = COMPRESSION_NONE
267 },
268 {
269 .dirname = "mipsel-loongson",
270 .names = { "mipsel-fuloong2f-flash", NULL },
271 .voidp_sizeof = 4,
272 .bigendian = 0,
273 .id = IMAGE_FULOONG2F_FLASH,
274 .flags = PLATFORM_FLAGS_DECOMPRESSORS,
275 .total_module_size = GRUB_KERNEL_MIPS_LOONGSON_TOTAL_MODULE_SIZE,
276 .decompressor_compressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_COMPRESSED_SIZE,
277 .decompressor_uncompressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_SIZE,
278 .decompressor_uncompressed_addr = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_ADDR,
279 .section_align = 1,
280 .vaddr_offset = 0,
281 .link_addr = GRUB_KERNEL_MIPS_LOONGSON_LINK_ADDR,
282 .elf_target = EM_MIPS,
283 .link_align = GRUB_KERNEL_MIPS_LOONGSON_LINK_ALIGN,
284 .default_compression = COMPRESSION_NONE
285 },
286 {
287 .dirname = "mipsel-loongson",
288 .names = { "mipsel-loongson-elf", "mipsel-yeeloong-elf",
289 "mipsel-fuloong2f-elf", "mipsel-fuloong2e-elf",
290 "mipsel-fuloong-elf", NULL },
291 .voidp_sizeof = 4,
292 .bigendian = 0,
293 .id = IMAGE_LOONGSON_ELF,
294 .flags = PLATFORM_FLAGS_DECOMPRESSORS,
295 .total_module_size = GRUB_KERNEL_MIPS_LOONGSON_TOTAL_MODULE_SIZE,
296 .decompressor_compressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_COMPRESSED_SIZE,
297 .decompressor_uncompressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_SIZE,
298 .decompressor_uncompressed_addr = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_ADDR,
299 .section_align = 1,
300 .vaddr_offset = 0,
301 .link_addr = GRUB_KERNEL_MIPS_LOONGSON_LINK_ADDR,
302 .elf_target = EM_MIPS,
303 .link_align = GRUB_KERNEL_MIPS_LOONGSON_LINK_ALIGN,
304 .default_compression = COMPRESSION_NONE
305 },
306 {
307 .dirname = "powerpc-ieee1275",
308 .names = { "powerpc-ieee1275", NULL },
309 .voidp_sizeof = 4,
310 .bigendian = 1,
311 .id = IMAGE_PPC,
312 .flags = PLATFORM_FLAGS_NONE,
313 .total_module_size = TARGET_NO_FIELD,
314 .decompressor_compressed_size = TARGET_NO_FIELD,
315 .decompressor_uncompressed_size = TARGET_NO_FIELD,
316 .decompressor_uncompressed_addr = TARGET_NO_FIELD,
317 .section_align = 1,
318 .vaddr_offset = 0,
319 .link_addr = GRUB_KERNEL_POWERPC_IEEE1275_LINK_ADDR,
320 .elf_target = EM_PPC,
321 .mod_gap = GRUB_KERNEL_POWERPC_IEEE1275_MOD_GAP,
322 .mod_align = GRUB_KERNEL_POWERPC_IEEE1275_MOD_ALIGN,
323 .link_align = 4
324 },
325 {
326 .dirname = "sparc64-ieee1275",
327 .names = { "sparc64-ieee1275-raw", NULL },
328 .voidp_sizeof = 8,
329 .bigendian = 1,
330 .id = IMAGE_SPARC64_RAW,
331 .flags = PLATFORM_FLAGS_NONE,
332 .total_module_size = GRUB_KERNEL_SPARC64_IEEE1275_TOTAL_MODULE_SIZE,
333 .decompressor_compressed_size = TARGET_NO_FIELD,
334 .decompressor_uncompressed_size = TARGET_NO_FIELD,
335 .decompressor_uncompressed_addr = TARGET_NO_FIELD,
336 .section_align = 1,
337 .vaddr_offset = 0,
338 .link_addr = GRUB_KERNEL_SPARC64_IEEE1275_LINK_ADDR
339 },
340 {
341 .dirname = "sparc64-ieee1275",
342 .names = { "sparc64-ieee1275-cdcore", NULL },
343 .voidp_sizeof = 8,
344 .bigendian = 1,
345 .id = IMAGE_SPARC64_CDCORE,
346 .flags = PLATFORM_FLAGS_NONE,
347 .total_module_size = GRUB_KERNEL_SPARC64_IEEE1275_TOTAL_MODULE_SIZE,
348 .decompressor_compressed_size = TARGET_NO_FIELD,
349 .decompressor_uncompressed_size = TARGET_NO_FIELD,
350 .decompressor_uncompressed_addr = TARGET_NO_FIELD,
351 .section_align = 1,
352 .vaddr_offset = 0,
353 .link_addr = GRUB_KERNEL_SPARC64_IEEE1275_LINK_ADDR
354 },
355 {
356 .dirname = "sparc64-ieee1275",
357 .names = { "sparc64-ieee1275-aout", NULL },
358 .voidp_sizeof = 8,
359 .bigendian = 1,
360 .id = IMAGE_SPARC64_AOUT,
361 .flags = PLATFORM_FLAGS_NONE,
362 .total_module_size = GRUB_KERNEL_SPARC64_IEEE1275_TOTAL_MODULE_SIZE,
363 .decompressor_compressed_size = TARGET_NO_FIELD,
364 .decompressor_uncompressed_size = TARGET_NO_FIELD,
365 .decompressor_uncompressed_addr = TARGET_NO_FIELD,
366 .section_align = 1,
367 .vaddr_offset = 0,
368 .link_addr = GRUB_KERNEL_SPARC64_IEEE1275_LINK_ADDR
369 },
370 {
371 .dirname = "ia64-efi",
372 .names = {"ia64-efi", NULL},
373 .voidp_sizeof = 8,
374 .bigendian = 0,
375 .id = IMAGE_EFI,
376 .flags = PLATFORM_FLAGS_NONE,
377 .total_module_size = TARGET_NO_FIELD,
378 .decompressor_compressed_size = TARGET_NO_FIELD,
379 .decompressor_uncompressed_size = TARGET_NO_FIELD,
380 .decompressor_uncompressed_addr = TARGET_NO_FIELD,
381 .section_align = GRUB_PE32_SECTION_ALIGNMENT,
382 .vaddr_offset = EFI64_HEADER_SIZE,
383 .pe_target = GRUB_PE32_MACHINE_IA64,
384 .elf_target = EM_IA_64,
385 },
386 {
387 .dirname = "mips-arc",
388 .names = {"mips-arc", NULL},
389 .voidp_sizeof = 4,
390 .bigendian = 1,
391 .id = IMAGE_MIPS_ARC,
392 .flags = PLATFORM_FLAGS_DECOMPRESSORS,
393 .total_module_size = GRUB_KERNEL_MIPS_ARC_TOTAL_MODULE_SIZE,
394 .decompressor_compressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_COMPRESSED_SIZE,
395 .decompressor_uncompressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_SIZE,
396 .decompressor_uncompressed_addr = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_ADDR,
397 .section_align = 1,
398 .vaddr_offset = 0,
399 .link_addr = GRUB_KERNEL_MIPS_ARC_LINK_ADDR,
400 .elf_target = EM_MIPS,
401 .link_align = GRUB_KERNEL_MIPS_ARC_LINK_ALIGN,
402 .default_compression = COMPRESSION_NONE
403 },
404 {
405 .dirname = "mipsel-arc",
406 .names = {"mipsel-arc", NULL},
407 .voidp_sizeof = 4,
408 .bigendian = 0,
409 .id = IMAGE_MIPS_ARC,
410 .flags = PLATFORM_FLAGS_DECOMPRESSORS,
411 .total_module_size = GRUB_KERNEL_MIPS_ARC_TOTAL_MODULE_SIZE,
412 .decompressor_compressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_COMPRESSED_SIZE,
413 .decompressor_uncompressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_SIZE,
414 .decompressor_uncompressed_addr = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_ADDR,
415 .section_align = 1,
416 .vaddr_offset = 0,
417 .link_addr = GRUB_KERNEL_MIPSEL_ARC_LINK_ADDR,
418 .elf_target = EM_MIPS,
419 .link_align = GRUB_KERNEL_MIPS_ARC_LINK_ALIGN,
420 .default_compression = COMPRESSION_NONE
421 },
422 {
423 .dirname = "mipsel-qemu_mips",
424 .names = { "mipsel-qemu_mips-elf", NULL },
425 .voidp_sizeof = 4,
426 .bigendian = 0,
427 .id = IMAGE_LOONGSON_ELF,
428 .flags = PLATFORM_FLAGS_DECOMPRESSORS,
429 .total_module_size = GRUB_KERNEL_MIPS_QEMU_MIPS_TOTAL_MODULE_SIZE,
430 .decompressor_compressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_COMPRESSED_SIZE,
431 .decompressor_uncompressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_SIZE,
432 .decompressor_uncompressed_addr = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_ADDR,
433 .section_align = 1,
434 .vaddr_offset = 0,
435 .link_addr = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ADDR,
436 .elf_target = EM_MIPS,
437 .link_align = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ALIGN,
438 .default_compression = COMPRESSION_NONE
439 },
440 {
441 .dirname = "mips-qemu_mips",
442 .names = { "mips-qemu_mips-flash", NULL },
443 .voidp_sizeof = 4,
444 .bigendian = 1,
445 .id = IMAGE_QEMU_MIPS_FLASH,
446 .flags = PLATFORM_FLAGS_DECOMPRESSORS,
447 .total_module_size = GRUB_KERNEL_MIPS_QEMU_MIPS_TOTAL_MODULE_SIZE,
448 .decompressor_compressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_COMPRESSED_SIZE,
449 .decompressor_uncompressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_SIZE,
450 .decompressor_uncompressed_addr = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_ADDR,
451 .section_align = 1,
452 .vaddr_offset = 0,
453 .link_addr = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ADDR,
454 .elf_target = EM_MIPS,
455 .link_align = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ALIGN,
456 .default_compression = COMPRESSION_NONE
457 },
458 {
459 .dirname = "mipsel-qemu_mips",
460 .names = { "mipsel-qemu_mips-flash", NULL },
461 .voidp_sizeof = 4,
462 .bigendian = 0,
463 .id = IMAGE_QEMU_MIPS_FLASH,
464 .flags = PLATFORM_FLAGS_DECOMPRESSORS,
465 .total_module_size = GRUB_KERNEL_MIPS_QEMU_MIPS_TOTAL_MODULE_SIZE,
466 .decompressor_compressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_COMPRESSED_SIZE,
467 .decompressor_uncompressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_SIZE,
468 .decompressor_uncompressed_addr = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_ADDR,
469 .section_align = 1,
470 .vaddr_offset = 0,
471 .link_addr = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ADDR,
472 .elf_target = EM_MIPS,
473 .link_align = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ALIGN,
474 .default_compression = COMPRESSION_NONE
475 },
476 {
477 .dirname = "mips-qemu_mips",
478 .names = { "mips-qemu_mips-elf", NULL },
479 .voidp_sizeof = 4,
480 .bigendian = 1,
481 .id = IMAGE_LOONGSON_ELF,
482 .flags = PLATFORM_FLAGS_DECOMPRESSORS,
483 .total_module_size = GRUB_KERNEL_MIPS_QEMU_MIPS_TOTAL_MODULE_SIZE,
484 .decompressor_compressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_COMPRESSED_SIZE,
485 .decompressor_uncompressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_SIZE,
486 .decompressor_uncompressed_addr = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_ADDR,
487 .section_align = 1,
488 .vaddr_offset = 0,
489 .link_addr = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ADDR,
490 .elf_target = EM_MIPS,
491 .link_align = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ALIGN,
492 .default_compression = COMPRESSION_NONE
493 },
494 {
495 .dirname = "arm-uboot",
496 .names = { "arm-uboot", NULL },
497 .voidp_sizeof = 4,
498 .bigendian = 0,
499 .id = IMAGE_UBOOT,
500 .flags = PLATFORM_FLAGS_NONE,
501 .total_module_size = GRUB_KERNEL_ARM_UBOOT_TOTAL_MODULE_SIZE,
502 .decompressor_compressed_size = TARGET_NO_FIELD,
503 .decompressor_uncompressed_size = TARGET_NO_FIELD,
504 .decompressor_uncompressed_addr = TARGET_NO_FIELD,
505 .section_align = GRUB_KERNEL_ARM_UBOOT_MOD_ALIGN,
506 .vaddr_offset = 0,
507 .link_addr = GRUB_KERNEL_ARM_UBOOT_LINK_ADDR,
508 .elf_target = EM_ARM,
509 .mod_gap = GRUB_KERNEL_ARM_UBOOT_MOD_GAP,
510 .mod_align = GRUB_KERNEL_ARM_UBOOT_MOD_ALIGN,
511 .link_align = 4
512 },
513 {
514 .dirname = "arm-efi",
515 .names = { "arm-efi", NULL },
516 .voidp_sizeof = 4,
517 .bigendian = 0,
518 .id = IMAGE_EFI,
519 .flags = PLATFORM_FLAGS_NONE,
520 .total_module_size = TARGET_NO_FIELD,
521 .decompressor_compressed_size = TARGET_NO_FIELD,
522 .decompressor_uncompressed_size = TARGET_NO_FIELD,
523 .decompressor_uncompressed_addr = TARGET_NO_FIELD,
524 .section_align = GRUB_PE32_SECTION_ALIGNMENT,
525 .vaddr_offset = ALIGN_UP (GRUB_PE32_MSDOS_STUB_SIZE
526 + GRUB_PE32_SIGNATURE_SIZE
527 + sizeof (struct grub_pe32_coff_header)
528 + sizeof (struct grub_pe32_optional_header)
529 + 4 * sizeof (struct grub_pe32_section_table),
530 GRUB_PE32_SECTION_ALIGNMENT),
531 .pe_target = GRUB_PE32_MACHINE_ARMTHUMB_MIXED,
532 .elf_target = EM_ARM,
533 },
534 };
535
536 #define grub_target_to_host32(x) (grub_target_to_host32_real (image_target, (x)))
537 #define grub_host_to_target32(x) (grub_host_to_target32_real (image_target, (x)))
538 #define grub_target_to_host64(x) (grub_target_to_host64_real (image_target, (x)))
539 #define grub_host_to_target64(x) (grub_host_to_target64_real (image_target, (x)))
540 #define grub_host_to_target_addr(x) (grub_host_to_target_addr_real (image_target, (x)))
541 #define grub_target_to_host16(x) (grub_target_to_host16_real (image_target, (x)))
542 #define grub_host_to_target16(x) (grub_host_to_target16_real (image_target, (x)))
543
544 static inline grub_uint32_t
545 grub_target_to_host32_real (struct image_target_desc *image_target, grub_uint32_t in)
546 {
547 if (image_target->bigendian)
548 return grub_be_to_cpu32 (in);
549 else
550 return grub_le_to_cpu32 (in);
551 }
552
553 static inline grub_uint64_t
554 grub_target_to_host64_real (struct image_target_desc *image_target, grub_uint64_t in)
555 {
556 if (image_target->bigendian)
557 return grub_be_to_cpu64 (in);
558 else
559 return grub_le_to_cpu64 (in);
560 }
561
562 static inline grub_uint64_t
563 grub_host_to_target64_real (struct image_target_desc *image_target, grub_uint64_t in)
564 {
565 if (image_target->bigendian)
566 return grub_cpu_to_be64 (in);
567 else
568 return grub_cpu_to_le64 (in);
569 }
570
571 static inline grub_uint32_t
572 grub_host_to_target32_real (struct image_target_desc *image_target, grub_uint32_t in)
573 {
574 if (image_target->bigendian)
575 return grub_cpu_to_be32 (in);
576 else
577 return grub_cpu_to_le32 (in);
578 }
579
580 static inline grub_uint16_t
581 grub_target_to_host16_real (struct image_target_desc *image_target, grub_uint16_t in)
582 {
583 if (image_target->bigendian)
584 return grub_be_to_cpu16 (in);
585 else
586 return grub_le_to_cpu16 (in);
587 }
588
589 static inline grub_uint16_t
590 grub_host_to_target16_real (struct image_target_desc *image_target, grub_uint16_t in)
591 {
592 if (image_target->bigendian)
593 return grub_cpu_to_be16 (in);
594 else
595 return grub_cpu_to_le16 (in);
596 }
597
598 static inline grub_uint64_t
599 grub_host_to_target_addr_real (struct image_target_desc *image_target, grub_uint64_t in)
600 {
601 if (image_target->voidp_sizeof == 8)
602 return grub_host_to_target64_real (image_target, in);
603 else
604 return grub_host_to_target32_real (image_target, in);
605 }
606
607 static inline grub_uint64_t
608 grub_target_to_host_real (struct image_target_desc *image_target, grub_uint64_t in)
609 {
610 if (image_target->voidp_sizeof == 8)
611 return grub_target_to_host64_real (image_target, in);
612 else
613 return grub_target_to_host32_real (image_target, in);
614 }
615
616 #define GRUB_IEEE1275_NOTE_NAME "PowerPC"
617 #define GRUB_IEEE1275_NOTE_TYPE 0x1275
618
619 /* These structures are defined according to the CHRP binding to IEEE1275,
620 "Client Program Format" section. */
621
622 struct grub_ieee1275_note_hdr
623 {
624 grub_uint32_t namesz;
625 grub_uint32_t descsz;
626 grub_uint32_t type;
627 char name[sizeof (GRUB_IEEE1275_NOTE_NAME)];
628 };
629
630 struct grub_ieee1275_note_desc
631 {
632 grub_uint32_t real_mode;
633 grub_uint32_t real_base;
634 grub_uint32_t real_size;
635 grub_uint32_t virt_base;
636 grub_uint32_t virt_size;
637 grub_uint32_t load_base;
638 };
639
640 struct grub_ieee1275_note
641 {
642 struct grub_ieee1275_note_hdr header;
643 struct grub_ieee1275_note_desc descriptor;
644 };
645
646 #define grub_target_to_host(val) grub_target_to_host_real(image_target, (val))
647
648 #include <grub/lib/LzmaEnc.h>
649
650 static void *SzAlloc(void *p, size_t size) { p = p; return xmalloc(size); }
651 static void SzFree(void *p, void *address) { p = p; free(address); }
652 static ISzAlloc g_Alloc = { SzAlloc, SzFree };
653
654 static void
655 compress_kernel_lzma (char *kernel_img, size_t kernel_size,
656 char **core_img, size_t *core_size)
657 {
658 CLzmaEncProps props;
659 unsigned char out_props[5];
660 size_t out_props_size = 5;
661
662 LzmaEncProps_Init(&props);
663 props.dictSize = 1 << 16;
664 props.lc = 3;
665 props.lp = 0;
666 props.pb = 2;
667 props.numThreads = 1;
668
669 *core_img = xmalloc (kernel_size);
670
671 *core_size = kernel_size;
672 if (LzmaEncode ((unsigned char *) *core_img, core_size,
673 (unsigned char *) kernel_img,
674 kernel_size,
675 &props, out_props, &out_props_size,
676 0, NULL, &g_Alloc, &g_Alloc) != SZ_OK)
677 grub_util_error ("%s", _("cannot compress the kernel image"));
678 }
679
680 #ifdef HAVE_LIBLZMA
681 static void
682 compress_kernel_xz (char *kernel_img, size_t kernel_size,
683 char **core_img, size_t *core_size)
684 {
685 lzma_stream strm = LZMA_STREAM_INIT;
686 lzma_ret xzret;
687 lzma_options_lzma lzopts = {
688 .dict_size = 1 << 16,
689 .preset_dict = NULL,
690 .preset_dict_size = 0,
691 .lc = 3,
692 .lp = 0,
693 .pb = 2,
694 .mode = LZMA_MODE_NORMAL,
695 .nice_len = 64,
696 .mf = LZMA_MF_BT4,
697 .depth = 0,
698 };
699 lzma_filter fltrs[] = {
700 { .id = LZMA_FILTER_LZMA2, .options = &lzopts},
701 { .id = LZMA_VLI_UNKNOWN, .options = NULL}
702 };
703
704 xzret = lzma_stream_encoder (&strm, fltrs, LZMA_CHECK_NONE);
705 if (xzret != LZMA_OK)
706 grub_util_error ("%s", _("cannot compress the kernel image"));
707
708 *core_img = xmalloc (kernel_size);
709
710 *core_size = kernel_size;
711 strm.next_in = (unsigned char *) kernel_img;
712 strm.avail_in = kernel_size;
713 strm.next_out = (unsigned char *) *core_img;
714 strm.avail_out = *core_size;
715
716 while (1)
717 {
718 xzret = lzma_code (&strm, LZMA_FINISH);
719 if (xzret == LZMA_OK)
720 continue;
721 if (xzret == LZMA_STREAM_END)
722 break;
723 grub_util_error ("%s", _("cannot compress the kernel image"));
724 }
725
726 *core_size -= strm.avail_out;
727 }
728 #endif
729
730 static void
731 compress_kernel (struct image_target_desc *image_target, char *kernel_img,
732 size_t kernel_size, char **core_img, size_t *core_size,
733 grub_compression_t comp)
734 {
735 if (image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS
736 && (comp == COMPRESSION_LZMA))
737 {
738 compress_kernel_lzma (kernel_img, kernel_size, core_img,
739 core_size);
740 return;
741 }
742
743 #ifdef HAVE_LIBLZMA
744 if (image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS
745 && (comp == COMPRESSION_XZ))
746 {
747 compress_kernel_xz (kernel_img, kernel_size, core_img,
748 core_size);
749 return;
750 }
751 #endif
752
753 if (image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS
754 && (comp != COMPRESSION_NONE))
755 grub_util_error (_("unknown compression %d\n"), comp);
756
757 *core_img = xmalloc (kernel_size);
758 memcpy (*core_img, kernel_img, kernel_size);
759 *core_size = kernel_size;
760 }
761
762 struct fixup_block_list
763 {
764 struct fixup_block_list *next;
765 int state;
766 struct grub_pe32_fixup_block b;
767 };
768
769 #pragma GCC diagnostic ignored "-Wcast-align"
770
771 #define MKIMAGE_ELF32 1
772 #include "grub-mkimagexx.c"
773 #undef MKIMAGE_ELF32
774
775 #define MKIMAGE_ELF64 1
776 #include "grub-mkimagexx.c"
777 #undef MKIMAGE_ELF64
778
779 static void
780 generate_image (const char *dir, const char *prefix,
781 FILE *out, const char *outname, char *mods[],
782 char *memdisk_path, char **pubkey_paths, size_t npubkeys,
783 char *config_path, struct image_target_desc *image_target, int note,
784 grub_compression_t comp)
785 {
786 char *kernel_img, *core_img;
787 size_t kernel_size, total_module_size, core_size, exec_size;
788 size_t memdisk_size = 0, config_size = 0, config_size_pure = 0;
789 size_t prefix_size = 0;
790 char *kernel_path;
791 size_t offset;
792 struct grub_util_path_list *path_list, *p, *next;
793 grub_size_t bss_size;
794 grub_uint64_t start_address;
795 void *rel_section = 0;
796 grub_size_t reloc_size = 0, align;
797 size_t decompress_size = 0;
798
799 if (comp == COMPRESSION_AUTO)
800 comp = image_target->default_compression;
801
802 if (image_target->id == IMAGE_I386_PC
803 || image_target->id == IMAGE_I386_PC_PXE)
804 comp = COMPRESSION_LZMA;
805
806 path_list = grub_util_resolve_dependencies (dir, "moddep.lst", mods);
807
808 kernel_path = grub_util_get_path (dir, "kernel.img");
809
810 if (image_target->voidp_sizeof == 8)
811 total_module_size = sizeof (struct grub_module_info64);
812 else
813 total_module_size = sizeof (struct grub_module_info32);
814
815 {
816 size_t i;
817 for (i = 0; i < npubkeys; i++)
818 {
819 size_t curs;
820 curs = ALIGN_ADDR (grub_util_get_image_size (pubkey_paths[i]));
821 grub_util_info ("the size of public key %zd is 0x%llx",
822 i, (unsigned long long) curs);
823 total_module_size += curs + sizeof (struct grub_module_header);
824 }
825 }
826
827 if (memdisk_path)
828 {
829 memdisk_size = ALIGN_UP(grub_util_get_image_size (memdisk_path), 512);
830 grub_util_info ("the size of memory disk is 0x%llx",
831 (unsigned long long) memdisk_size);
832 total_module_size += memdisk_size + sizeof (struct grub_module_header);
833 }
834
835 if (config_path)
836 {
837 config_size_pure = grub_util_get_image_size (config_path) + 1;
838 config_size = ALIGN_ADDR (config_size_pure);
839 grub_util_info ("the size of config file is 0x%llx",
840 (unsigned long long) config_size);
841 total_module_size += config_size + sizeof (struct grub_module_header);
842 }
843
844 if (prefix)
845 {
846 prefix_size = ALIGN_ADDR (strlen (prefix) + 1);
847 total_module_size += prefix_size + sizeof (struct grub_module_header);
848 }
849
850 for (p = path_list; p; p = p->next)
851 total_module_size += (ALIGN_ADDR (grub_util_get_image_size (p->name))
852 + sizeof (struct grub_module_header));
853
854 grub_util_info ("the total module size is 0x%llx",
855 (unsigned long long) total_module_size);
856
857 if (image_target->voidp_sizeof == 4)
858 kernel_img = load_image32 (kernel_path, &exec_size, &kernel_size, &bss_size,
859 total_module_size, &start_address, &rel_section,
860 &reloc_size, &align, image_target);
861 else
862 kernel_img = load_image64 (kernel_path, &exec_size, &kernel_size, &bss_size,
863 total_module_size, &start_address, &rel_section,
864 &reloc_size, &align, image_target);
865
866 if ((image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS)
867 && (image_target->total_module_size != TARGET_NO_FIELD))
868 *((grub_uint32_t *) (kernel_img + image_target->total_module_size))
869 = grub_host_to_target32 (total_module_size);
870
871 if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL)
872 memmove (kernel_img + total_module_size, kernel_img, kernel_size);
873
874 if (image_target->voidp_sizeof == 8)
875 {
876 /* Fill in the grub_module_info structure. */
877 struct grub_module_info64 *modinfo;
878 if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL)
879 modinfo = (struct grub_module_info64 *) kernel_img;
880 else
881 modinfo = (struct grub_module_info64 *) (kernel_img + kernel_size);
882 memset (modinfo, 0, sizeof (struct grub_module_info64));
883 modinfo->magic = grub_host_to_target32 (GRUB_MODULE_MAGIC);
884 modinfo->offset = grub_host_to_target_addr (sizeof (struct grub_module_info64));
885 modinfo->size = grub_host_to_target_addr (total_module_size);
886 if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL)
887 offset = sizeof (struct grub_module_info64);
888 else
889 offset = kernel_size + sizeof (struct grub_module_info64);
890 }
891 else
892 {
893 /* Fill in the grub_module_info structure. */
894 struct grub_module_info32 *modinfo;
895 if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL)
896 modinfo = (struct grub_module_info32 *) kernel_img;
897 else
898 modinfo = (struct grub_module_info32 *) (kernel_img + kernel_size);
899 memset (modinfo, 0, sizeof (struct grub_module_info32));
900 modinfo->magic = grub_host_to_target32 (GRUB_MODULE_MAGIC);
901 modinfo->offset = grub_host_to_target_addr (sizeof (struct grub_module_info32));
902 modinfo->size = grub_host_to_target_addr (total_module_size);
903 if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL)
904 offset = sizeof (struct grub_module_info32);
905 else
906 offset = kernel_size + sizeof (struct grub_module_info32);
907 }
908
909 for (p = path_list; p; p = p->next)
910 {
911 struct grub_module_header *header;
912 size_t mod_size, orig_size;
913
914 orig_size = grub_util_get_image_size (p->name);
915 mod_size = ALIGN_ADDR (orig_size);
916
917 header = (struct grub_module_header *) (kernel_img + offset);
918 memset (header, 0, sizeof (struct grub_module_header));
919 header->type = grub_host_to_target32 (OBJ_TYPE_ELF);
920 header->size = grub_host_to_target32 (mod_size + sizeof (*header));
921 offset += sizeof (*header);
922 memset (kernel_img + offset + orig_size, 0, mod_size - orig_size);
923
924 grub_util_load_image (p->name, kernel_img + offset);
925 offset += mod_size;
926 }
927
928 {
929 size_t i;
930 for (i = 0; i < npubkeys; i++)
931 {
932 size_t curs;
933 struct grub_module_header *header;
934
935 curs = grub_util_get_image_size (pubkey_paths[i]);
936
937 header = (struct grub_module_header *) (kernel_img + offset);
938 memset (header, 0, sizeof (struct grub_module_header));
939 header->type = grub_host_to_target32 (OBJ_TYPE_PUBKEY);
940 header->size = grub_host_to_target32 (curs + sizeof (*header));
941 offset += sizeof (*header);
942
943 grub_util_load_image (pubkey_paths[i], kernel_img + offset);
944 offset += ALIGN_ADDR (curs);
945 }
946 }
947
948 if (memdisk_path)
949 {
950 struct grub_module_header *header;
951
952 header = (struct grub_module_header *) (kernel_img + offset);
953 memset (header, 0, sizeof (struct grub_module_header));
954 header->type = grub_host_to_target32 (OBJ_TYPE_MEMDISK);
955 header->size = grub_host_to_target32 (memdisk_size + sizeof (*header));
956 offset += sizeof (*header);
957
958 grub_util_load_image (memdisk_path, kernel_img + offset);
959 offset += memdisk_size;
960 }
961
962 if (config_path)
963 {
964 struct grub_module_header *header;
965
966 header = (struct grub_module_header *) (kernel_img + offset);
967 memset (header, 0, sizeof (struct grub_module_header));
968 header->type = grub_host_to_target32 (OBJ_TYPE_CONFIG);
969 header->size = grub_host_to_target32 (config_size + sizeof (*header));
970 offset += sizeof (*header);
971
972 grub_util_load_image (config_path, kernel_img + offset);
973 *(kernel_img + offset + config_size_pure - 1) = 0;
974 offset += config_size;
975 }
976
977 if (prefix)
978 {
979 struct grub_module_header *header;
980
981 header = (struct grub_module_header *) (kernel_img + offset);
982 memset (header, 0, sizeof (struct grub_module_header));
983 header->type = grub_host_to_target32 (OBJ_TYPE_PREFIX);
984 header->size = grub_host_to_target32 (prefix_size + sizeof (*header));
985 offset += sizeof (*header);
986
987 grub_memset (kernel_img + offset, 0, prefix_size);
988 grub_strcpy (kernel_img + offset, prefix);
989 offset += prefix_size;
990 }
991
992 grub_util_info ("kernel_img=%p, kernel_size=0x%llx", kernel_img,
993 (unsigned long long) kernel_size);
994 compress_kernel (image_target, kernel_img, kernel_size + total_module_size,
995 &core_img, &core_size, comp);
996 free (kernel_img);
997
998 grub_util_info ("the core size is 0x%llx", (unsigned long long) core_size);
999
1000 if (!(image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS)
1001 && image_target->total_module_size != TARGET_NO_FIELD)
1002 *((grub_uint32_t *) (core_img + image_target->total_module_size))
1003 = grub_host_to_target32 (total_module_size);
1004
1005 if (image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS)
1006 {
1007 char *full_img;
1008 size_t full_size;
1009 char *decompress_path, *decompress_img;
1010 const char *name;
1011
1012 switch (comp)
1013 {
1014 case COMPRESSION_XZ:
1015 name = "xz_decompress.img";
1016 break;
1017 case COMPRESSION_LZMA:
1018 name = "lzma_decompress.img";
1019 break;
1020 case COMPRESSION_NONE:
1021 name = "none_decompress.img";
1022 break;
1023 default:
1024 grub_util_error (_("unknown compression %d\n"), comp);
1025 }
1026
1027 decompress_path = grub_util_get_path (dir, name);
1028 decompress_size = grub_util_get_image_size (decompress_path);
1029 decompress_img = grub_util_read_image (decompress_path);
1030
1031 if ((image_target->id == IMAGE_I386_PC
1032 || image_target->id == IMAGE_I386_PC_PXE)
1033 && decompress_size > GRUB_KERNEL_I386_PC_LINK_ADDR - 0x8200)
1034 grub_util_error ("%s", _("Decompressor is too big"));
1035
1036 if (image_target->decompressor_compressed_size != TARGET_NO_FIELD)
1037 *((grub_uint32_t *) (decompress_img
1038 + image_target->decompressor_compressed_size))
1039 = grub_host_to_target32 (core_size);
1040
1041 if (image_target->decompressor_uncompressed_size != TARGET_NO_FIELD)
1042 *((grub_uint32_t *) (decompress_img
1043 + image_target->decompressor_uncompressed_size))
1044 = grub_host_to_target32 (kernel_size + total_module_size);
1045
1046 if (image_target->decompressor_uncompressed_addr != TARGET_NO_FIELD)
1047 {
1048 if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL)
1049 *((grub_uint32_t *) (decompress_img + image_target->decompressor_uncompressed_addr))
1050 = grub_host_to_target_addr (image_target->link_addr - total_module_size);
1051 else
1052 *((grub_uint32_t *) (decompress_img + image_target->decompressor_uncompressed_addr))
1053 = grub_host_to_target_addr (image_target->link_addr);
1054 }
1055 full_size = core_size + decompress_size;
1056
1057 full_img = xmalloc (full_size);
1058 memset (full_img, 0, full_size);
1059
1060 memcpy (full_img, decompress_img, decompress_size);
1061
1062 memcpy (full_img + decompress_size, core_img, core_size);
1063
1064 memset (full_img + decompress_size + core_size, 0,
1065 full_size - (decompress_size + core_size));
1066
1067 free (core_img);
1068 core_img = full_img;
1069 core_size = full_size;
1070 }
1071
1072 switch (image_target->id)
1073 {
1074 case IMAGE_I386_PC:
1075 case IMAGE_I386_PC_PXE:
1076 if (GRUB_KERNEL_I386_PC_LINK_ADDR + core_size > 0x78000
1077 || (core_size > (0xffff << GRUB_DISK_SECTOR_BITS))
1078 || (kernel_size + bss_size + GRUB_KERNEL_I386_PC_LINK_ADDR > 0x68000))
1079 grub_util_error (_("core image is too big (0x%x > 0x%x)"),
1080 GRUB_KERNEL_I386_PC_LINK_ADDR + (unsigned) core_size,
1081 0x78000);
1082 /* fallthrough */
1083 case IMAGE_COREBOOT:
1084 case IMAGE_QEMU:
1085 if (kernel_size + bss_size + GRUB_KERNEL_I386_PC_LINK_ADDR > 0x68000)
1086 grub_util_error (_("kernel image is too big (0x%x > 0x%x)"),
1087 (unsigned) kernel_size + (unsigned) bss_size
1088 + GRUB_KERNEL_I386_PC_LINK_ADDR,
1089 0x68000);
1090 break;
1091 case IMAGE_LOONGSON_ELF:
1092 case IMAGE_YEELOONG_FLASH:
1093 case IMAGE_FULOONG2F_FLASH:
1094 case IMAGE_EFI:
1095 case IMAGE_MIPS_ARC:
1096 case IMAGE_QEMU_MIPS_FLASH:
1097 break;
1098 case IMAGE_SPARC64_AOUT:
1099 case IMAGE_SPARC64_RAW:
1100 case IMAGE_SPARC64_CDCORE:
1101 case IMAGE_I386_IEEE1275:
1102 case IMAGE_PPC:
1103 case IMAGE_UBOOT:
1104 break;
1105 }
1106
1107 switch (image_target->id)
1108 {
1109 case IMAGE_I386_PC:
1110 case IMAGE_I386_PC_PXE:
1111 {
1112 unsigned num;
1113 char *boot_path, *boot_img;
1114 size_t boot_size;
1115
1116 num = ((core_size + GRUB_DISK_SECTOR_SIZE - 1) >> GRUB_DISK_SECTOR_BITS);
1117 if (image_target->id == IMAGE_I386_PC_PXE)
1118 {
1119 char *pxeboot_path, *pxeboot_img;
1120 size_t pxeboot_size;
1121 grub_uint32_t *ptr;
1122
1123 pxeboot_path = grub_util_get_path (dir, "pxeboot.img");
1124 pxeboot_size = grub_util_get_image_size (pxeboot_path);
1125 pxeboot_img = grub_util_read_image (pxeboot_path);
1126
1127 grub_util_write_image (pxeboot_img, pxeboot_size, out,
1128 outname);
1129 free (pxeboot_img);
1130 free (pxeboot_path);
1131
1132 /* Remove Multiboot header to avoid confusing ipxe. */
1133 for (ptr = (grub_uint32_t *) core_img;
1134 ptr < (grub_uint32_t *) (core_img + MULTIBOOT_SEARCH); ptr++)
1135 if (*ptr == grub_host_to_target32 (MULTIBOOT_HEADER_MAGIC)
1136 && grub_target_to_host32 (ptr[0])
1137 + grub_target_to_host32 (ptr[1])
1138 + grub_target_to_host32 (ptr[2]) == 0)
1139 {
1140 *ptr = 0;
1141 break;
1142 }
1143 }
1144
1145 boot_path = grub_util_get_path (dir, "diskboot.img");
1146 boot_size = grub_util_get_image_size (boot_path);
1147 if (boot_size != GRUB_DISK_SECTOR_SIZE)
1148 grub_util_error (_("diskboot.img size must be %u bytes"),
1149 GRUB_DISK_SECTOR_SIZE);
1150
1151 boot_img = grub_util_read_image (boot_path);
1152
1153 {
1154 struct grub_pc_bios_boot_blocklist *block;
1155 block = (struct grub_pc_bios_boot_blocklist *) (boot_img
1156 + GRUB_DISK_SECTOR_SIZE
1157 - sizeof (*block));
1158 block->len = grub_host_to_target16 (num);
1159
1160 /* This is filled elsewhere. Verify it just in case. */
1161 assert (block->segment
1162 == grub_host_to_target16 (GRUB_BOOT_I386_PC_KERNEL_SEG
1163 + (GRUB_DISK_SECTOR_SIZE >> 4)));
1164 }
1165
1166 grub_util_write_image (boot_img, boot_size, out, outname);
1167 free (boot_img);
1168 free (boot_path);
1169 }
1170 break;
1171 case IMAGE_EFI:
1172 {
1173 void *pe_img;
1174 grub_uint8_t *header;
1175 void *sections;
1176 size_t pe_size;
1177 struct grub_pe32_coff_header *c;
1178 struct grub_pe32_section_table *text_section, *data_section;
1179 struct grub_pe32_section_table *mods_section, *reloc_section;
1180 static const grub_uint8_t stub[] = GRUB_PE32_MSDOS_STUB;
1181 int header_size;
1182 int reloc_addr;
1183
1184 if (image_target->voidp_sizeof == 4)
1185 header_size = EFI32_HEADER_SIZE;
1186 else
1187 header_size = EFI64_HEADER_SIZE;
1188
1189 reloc_addr = ALIGN_UP (header_size + core_size,
1190 image_target->section_align);
1191
1192 pe_size = ALIGN_UP (reloc_addr + reloc_size,
1193 image_target->section_align);
1194 pe_img = xmalloc (reloc_addr + reloc_size);
1195 memset (pe_img, 0, header_size);
1196 memcpy ((char *) pe_img + header_size, core_img, core_size);
1197 memcpy ((char *) pe_img + reloc_addr, rel_section, reloc_size);
1198 header = pe_img;
1199
1200 /* The magic. */
1201 memcpy (header, stub, GRUB_PE32_MSDOS_STUB_SIZE);
1202 memcpy (header + GRUB_PE32_MSDOS_STUB_SIZE, "PE\0\0",
1203 GRUB_PE32_SIGNATURE_SIZE);
1204
1205 /* The COFF file header. */
1206 c = (struct grub_pe32_coff_header *) (header + GRUB_PE32_MSDOS_STUB_SIZE
1207 + GRUB_PE32_SIGNATURE_SIZE);
1208 c->machine = grub_host_to_target16 (image_target->pe_target);
1209
1210 c->num_sections = grub_host_to_target16 (4);
1211 c->time = grub_host_to_target32 (time (0));
1212 c->characteristics = grub_host_to_target16 (GRUB_PE32_EXECUTABLE_IMAGE
1213 | GRUB_PE32_LINE_NUMS_STRIPPED
1214 | ((image_target->voidp_sizeof == 4)
1215 ? GRUB_PE32_32BIT_MACHINE
1216 : 0)
1217 | GRUB_PE32_LOCAL_SYMS_STRIPPED
1218 | GRUB_PE32_DEBUG_STRIPPED);
1219
1220 /* The PE Optional header. */
1221 if (image_target->voidp_sizeof == 4)
1222 {
1223 struct grub_pe32_optional_header *o;
1224
1225 c->optional_header_size = grub_host_to_target16 (sizeof (struct grub_pe32_optional_header));
1226
1227 o = (struct grub_pe32_optional_header *)
1228 (header + GRUB_PE32_MSDOS_STUB_SIZE + GRUB_PE32_SIGNATURE_SIZE
1229 + sizeof (struct grub_pe32_coff_header));
1230 o->magic = grub_host_to_target16 (GRUB_PE32_PE32_MAGIC);
1231 o->code_size = grub_host_to_target32 (exec_size);
1232 o->data_size = grub_cpu_to_le32 (reloc_addr - exec_size
1233 - header_size);
1234 o->bss_size = grub_cpu_to_le32 (bss_size);
1235 o->entry_addr = grub_cpu_to_le32 (start_address);
1236 o->code_base = grub_cpu_to_le32 (header_size);
1237
1238 o->data_base = grub_host_to_target32 (header_size + exec_size);
1239
1240 o->image_base = 0;
1241 o->section_alignment = grub_host_to_target32 (image_target->section_align);
1242 o->file_alignment = grub_host_to_target32 (image_target->section_align);
1243 o->image_size = grub_host_to_target32 (pe_size);
1244 o->header_size = grub_host_to_target32 (header_size);
1245 o->subsystem = grub_host_to_target16 (GRUB_PE32_SUBSYSTEM_EFI_APPLICATION);
1246
1247 /* Do these really matter? */
1248 o->stack_reserve_size = grub_host_to_target32 (0x10000);
1249 o->stack_commit_size = grub_host_to_target32 (0x10000);
1250 o->heap_reserve_size = grub_host_to_target32 (0x10000);
1251 o->heap_commit_size = grub_host_to_target32 (0x10000);
1252
1253 o->num_data_directories = grub_host_to_target32 (GRUB_PE32_NUM_DATA_DIRECTORIES);
1254
1255 o->base_relocation_table.rva = grub_host_to_target32 (reloc_addr);
1256 o->base_relocation_table.size = grub_host_to_target32 (reloc_size);
1257 sections = o + 1;
1258 }
1259 else
1260 {
1261 struct grub_pe64_optional_header *o;
1262
1263 c->optional_header_size = grub_host_to_target16 (sizeof (struct grub_pe64_optional_header));
1264
1265 o = (struct grub_pe64_optional_header *)
1266 (header + GRUB_PE32_MSDOS_STUB_SIZE + GRUB_PE32_SIGNATURE_SIZE
1267 + sizeof (struct grub_pe32_coff_header));
1268 o->magic = grub_host_to_target16 (GRUB_PE32_PE64_MAGIC);
1269 o->code_size = grub_host_to_target32 (exec_size);
1270 o->data_size = grub_cpu_to_le32 (reloc_addr - exec_size
1271 - header_size);
1272 o->bss_size = grub_cpu_to_le32 (bss_size);
1273 o->entry_addr = grub_cpu_to_le32 (start_address);
1274 o->code_base = grub_cpu_to_le32 (header_size);
1275 o->image_base = 0;
1276 o->section_alignment = grub_host_to_target32 (image_target->section_align);
1277 o->file_alignment = grub_host_to_target32 (image_target->section_align);
1278 o->image_size = grub_host_to_target32 (pe_size);
1279 o->header_size = grub_host_to_target32 (header_size);
1280 o->subsystem = grub_host_to_target16 (GRUB_PE32_SUBSYSTEM_EFI_APPLICATION);
1281
1282 /* Do these really matter? */
1283 o->stack_reserve_size = grub_host_to_target64 (0x10000);
1284 o->stack_commit_size = grub_host_to_target64 (0x10000);
1285 o->heap_reserve_size = grub_host_to_target64 (0x10000);
1286 o->heap_commit_size = grub_host_to_target64 (0x10000);
1287
1288 o->num_data_directories
1289 = grub_host_to_target32 (GRUB_PE32_NUM_DATA_DIRECTORIES);
1290
1291 o->base_relocation_table.rva = grub_host_to_target32 (reloc_addr);
1292 o->base_relocation_table.size = grub_host_to_target32 (reloc_size);
1293 sections = o + 1;
1294 }
1295 /* The sections. */
1296 text_section = sections;
1297 strcpy (text_section->name, ".text");
1298 text_section->virtual_size = grub_cpu_to_le32 (exec_size);
1299 text_section->virtual_address = grub_cpu_to_le32 (header_size);
1300 text_section->raw_data_size = grub_cpu_to_le32 (exec_size);
1301 text_section->raw_data_offset = grub_cpu_to_le32 (header_size);
1302 text_section->characteristics = grub_cpu_to_le32 (GRUB_PE32_SCN_CNT_CODE
1303 | GRUB_PE32_SCN_MEM_EXECUTE
1304 | GRUB_PE32_SCN_MEM_READ);
1305
1306 data_section = text_section + 1;
1307 strcpy (data_section->name, ".data");
1308 data_section->virtual_size = grub_cpu_to_le32 (kernel_size - exec_size);
1309 data_section->virtual_address = grub_cpu_to_le32 (header_size + exec_size);
1310 data_section->raw_data_size = grub_cpu_to_le32 (kernel_size - exec_size);
1311 data_section->raw_data_offset = grub_cpu_to_le32 (header_size + exec_size);
1312 data_section->characteristics
1313 = grub_cpu_to_le32 (GRUB_PE32_SCN_CNT_INITIALIZED_DATA
1314 | GRUB_PE32_SCN_MEM_READ
1315 | GRUB_PE32_SCN_MEM_WRITE);
1316
1317 #if 0
1318 bss_section = data_section + 1;
1319 strcpy (bss_section->name, ".bss");
1320 bss_section->virtual_size = grub_cpu_to_le32 (bss_size);
1321 bss_section->virtual_address = grub_cpu_to_le32 (header_size + kernel_size);
1322 bss_section->raw_data_size = 0;
1323 bss_section->raw_data_offset = 0;
1324 bss_section->characteristics
1325 = grub_cpu_to_le32 (GRUB_PE32_SCN_MEM_READ
1326 | GRUB_PE32_SCN_MEM_WRITE
1327 | GRUB_PE32_SCN_ALIGN_64BYTES
1328 | GRUB_PE32_SCN_CNT_INITIALIZED_DATA
1329 | 0x80);
1330 #endif
1331
1332 mods_section = data_section + 1;
1333 strcpy (mods_section->name, "mods");
1334 mods_section->virtual_size = grub_cpu_to_le32 (reloc_addr - kernel_size - header_size);
1335 mods_section->virtual_address = grub_cpu_to_le32 (header_size + kernel_size + bss_size);
1336 mods_section->raw_data_size = grub_cpu_to_le32 (reloc_addr - kernel_size - header_size);
1337 mods_section->raw_data_offset = grub_cpu_to_le32 (header_size + kernel_size);
1338 mods_section->characteristics
1339 = grub_cpu_to_le32 (GRUB_PE32_SCN_CNT_INITIALIZED_DATA
1340 | GRUB_PE32_SCN_MEM_READ
1341 | GRUB_PE32_SCN_MEM_WRITE);
1342
1343 reloc_section = mods_section + 1;
1344 strcpy (reloc_section->name, ".reloc");
1345 reloc_section->virtual_size = grub_cpu_to_le32 (reloc_size);
1346 reloc_section->virtual_address = grub_cpu_to_le32 (reloc_addr + bss_size);
1347 reloc_section->raw_data_size = grub_cpu_to_le32 (reloc_size);
1348 reloc_section->raw_data_offset = grub_cpu_to_le32 (reloc_addr);
1349 reloc_section->characteristics
1350 = grub_cpu_to_le32 (GRUB_PE32_SCN_CNT_INITIALIZED_DATA
1351 | GRUB_PE32_SCN_MEM_DISCARDABLE
1352 | GRUB_PE32_SCN_MEM_READ);
1353 free (core_img);
1354 core_img = pe_img;
1355 core_size = pe_size;
1356 }
1357 break;
1358 case IMAGE_QEMU:
1359 {
1360 char *rom_img;
1361 size_t rom_size;
1362 char *boot_path, *boot_img;
1363 size_t boot_size;
1364
1365 boot_path = grub_util_get_path (dir, "boot.img");
1366 boot_size = grub_util_get_image_size (boot_path);
1367 boot_img = grub_util_read_image (boot_path);
1368
1369 /* Rom sizes must be 64k-aligned. */
1370 rom_size = ALIGN_UP (core_size + boot_size, 64 * 1024);
1371
1372 rom_img = xmalloc (rom_size);
1373 memset (rom_img, 0, rom_size);
1374
1375 *((grub_int32_t *) (core_img + GRUB_KERNEL_I386_QEMU_CORE_ENTRY_ADDR))
1376 = grub_host_to_target32 ((grub_uint32_t) -rom_size);
1377
1378 memcpy (rom_img, core_img, core_size);
1379
1380 *((grub_int32_t *) (boot_img + GRUB_BOOT_I386_QEMU_CORE_ENTRY_ADDR))
1381 = grub_host_to_target32 ((grub_uint32_t) -rom_size);
1382
1383 memcpy (rom_img + rom_size - boot_size, boot_img, boot_size);
1384
1385 free (core_img);
1386 core_img = rom_img;
1387 core_size = rom_size;
1388
1389 free (boot_img);
1390 free (boot_path);
1391 }
1392 break;
1393 case IMAGE_SPARC64_AOUT:
1394 {
1395 void *aout_img;
1396 size_t aout_size;
1397 struct grub_aout32_header *aout_head;
1398
1399 aout_size = core_size + sizeof (*aout_head);
1400 aout_img = xmalloc (aout_size);
1401 aout_head = aout_img;
1402 grub_memset (aout_head, 0, sizeof (*aout_head));
1403 aout_head->a_midmag = grub_host_to_target32 ((AOUT_MID_SUN << 16)
1404 | AOUT32_OMAGIC);
1405 aout_head->a_text = grub_host_to_target32 (core_size);
1406 aout_head->a_entry
1407 = grub_host_to_target32 (GRUB_BOOT_SPARC64_IEEE1275_IMAGE_ADDRESS);
1408 memcpy ((char *) aout_img + sizeof (*aout_head), core_img, core_size);
1409
1410 free (core_img);
1411 core_img = aout_img;
1412 core_size = aout_size;
1413 }
1414 break;
1415 case IMAGE_SPARC64_RAW:
1416 {
1417 unsigned int num;
1418 char *boot_path, *boot_img;
1419 size_t boot_size;
1420
1421 num = ((core_size + GRUB_DISK_SECTOR_SIZE - 1) >> GRUB_DISK_SECTOR_BITS);
1422 num <<= GRUB_DISK_SECTOR_BITS;
1423
1424 boot_path = grub_util_get_path (dir, "diskboot.img");
1425 boot_size = grub_util_get_image_size (boot_path);
1426 if (boot_size != GRUB_DISK_SECTOR_SIZE)
1427 grub_util_error (_("diskboot.img size must be %u bytes"),
1428 GRUB_DISK_SECTOR_SIZE);
1429
1430 boot_img = grub_util_read_image (boot_path);
1431
1432 *((grub_uint32_t *) (boot_img + GRUB_DISK_SECTOR_SIZE
1433 - GRUB_BOOT_SPARC64_IEEE1275_LIST_SIZE + 8))
1434 = grub_host_to_target32 (num);
1435
1436 grub_util_write_image (boot_img, boot_size, out, outname);
1437 free (boot_img);
1438 free (boot_path);
1439 }
1440 break;
1441 case IMAGE_SPARC64_CDCORE:
1442 break;
1443 case IMAGE_YEELOONG_FLASH:
1444 case IMAGE_FULOONG2F_FLASH:
1445 {
1446 char *rom_img;
1447 size_t rom_size;
1448 char *boot_path, *boot_img;
1449 size_t boot_size;
1450 grub_uint8_t context[GRUB_MD_SHA512->contextsize];
1451 /* fwstart.img is the only part which can't be tested by using *-elf
1452 target. Check it against the checksum. */
1453 const grub_uint8_t yeeloong_fwstart_good_hash[512 / 8] =
1454 {
1455 0x5f, 0x67, 0x46, 0x57, 0x31, 0x30, 0xc5, 0x0a,
1456 0xe9, 0x98, 0x18, 0xc9, 0xf3, 0xca, 0x45, 0xa5,
1457 0x75, 0x64, 0x6b, 0xbb, 0x24, 0xcd, 0xb4, 0xbc,
1458 0xf2, 0x3e, 0x23, 0xf9, 0xc2, 0x6a, 0x8c, 0xde,
1459 0x3b, 0x94, 0x9c, 0xcc, 0xa5, 0xa7, 0x58, 0xb1,
1460 0xbe, 0x8b, 0x3d, 0x73, 0x98, 0x18, 0x7e, 0x68,
1461 0x5e, 0x5f, 0x23, 0x7d, 0x7a, 0xe8, 0x51, 0xf7,
1462 0x1a, 0xaf, 0x2f, 0x54, 0x11, 0x2e, 0x5c, 0x25
1463 };
1464 const grub_uint8_t fuloong2f_fwstart_good_hash[512 / 8] =
1465 {
1466 0x76, 0x9b, 0xad, 0x6e, 0xa2, 0x39, 0x47, 0x62,
1467 0x1f, 0xc9, 0x3a, 0x6d, 0x05, 0x5c, 0x43, 0x5c,
1468 0x29, 0x4a, 0x7e, 0x08, 0x2a, 0x31, 0x8f, 0x5d,
1469 0x02, 0x84, 0xa0, 0x85, 0xf2, 0xd1, 0xb9, 0x53,
1470 0xa2, 0xbc, 0xf2, 0xe1, 0x39, 0x1e, 0x51, 0xb5,
1471 0xaf, 0xec, 0x9e, 0xf2, 0xf1, 0xf3, 0x0a, 0x2f,
1472 0xe6, 0xf1, 0x08, 0x89, 0xbe, 0xbc, 0x73, 0xab,
1473 0x46, 0x50, 0xd6, 0x21, 0xce, 0x8e, 0x24, 0xa7
1474 };
1475 const grub_uint8_t *fwstart_good_hash;
1476
1477 if (image_target->id == IMAGE_FULOONG2F_FLASH)
1478 {
1479 fwstart_good_hash = fuloong2f_fwstart_good_hash;
1480 boot_path = grub_util_get_path (dir, "fwstart_fuloong2f.img");
1481 }
1482 else
1483 {
1484 fwstart_good_hash = yeeloong_fwstart_good_hash;
1485 boot_path = grub_util_get_path (dir, "fwstart.img");
1486 }
1487
1488 boot_size = grub_util_get_image_size (boot_path);
1489 boot_img = grub_util_read_image (boot_path);
1490
1491 grub_memset (context, 0, sizeof (context));
1492 GRUB_MD_SHA512->init (context);
1493 GRUB_MD_SHA512->write (context, boot_img, boot_size);
1494 GRUB_MD_SHA512->final (context);
1495 if (grub_memcmp (GRUB_MD_SHA512->read (context), fwstart_good_hash,
1496 GRUB_MD_SHA512->mdlen) != 0)
1497 /* TRANSLATORS: fwstart.img may still be good, just it wasn't checked. */
1498 grub_util_warn ("%s",
1499 _("fwstart.img doesn't match the known good version. "
1500 "proceed at your own risk"));
1501
1502 if (core_size + boot_size > 512 * 1024)
1503 grub_util_error ("%s", _("firmware image is too big"));
1504 rom_size = 512 * 1024;
1505
1506 rom_img = xmalloc (rom_size);
1507 memset (rom_img, 0, rom_size);
1508
1509 memcpy (rom_img, boot_img, boot_size);
1510
1511 memcpy (rom_img + boot_size, core_img, core_size);
1512
1513 memset (rom_img + boot_size + core_size, 0,
1514 rom_size - (boot_size + core_size));
1515
1516 free (core_img);
1517 core_img = rom_img;
1518 core_size = rom_size;
1519 }
1520 break;
1521 case IMAGE_QEMU_MIPS_FLASH:
1522 {
1523 char *rom_img;
1524 size_t rom_size;
1525
1526 if (core_size > 512 * 1024)
1527 grub_util_error ("%s", _("firmware image is too big"));
1528 rom_size = 512 * 1024;
1529
1530 rom_img = xmalloc (rom_size);
1531 memset (rom_img, 0, rom_size);
1532
1533 memcpy (rom_img, core_img, core_size);
1534
1535 memset (rom_img + core_size, 0,
1536 rom_size - core_size);
1537
1538 free (core_img);
1539 core_img = rom_img;
1540 core_size = rom_size;
1541 }
1542 break;
1543
1544 case IMAGE_UBOOT:
1545 {
1546 struct grub_uboot_image_header *hdr;
1547 GRUB_PROPERLY_ALIGNED_ARRAY (crc32_context, GRUB_MD_CRC32->contextsize);
1548
1549 hdr = xmalloc (core_size + sizeof (struct grub_uboot_image_header));
1550 memcpy (hdr + 1, core_img, core_size);
1551
1552 memset (hdr, 0, sizeof (*hdr));
1553 hdr->ih_magic = grub_cpu_to_be32_compile_time (GRUB_UBOOT_IH_MAGIC);
1554 hdr->ih_time = grub_cpu_to_be32 (time (0));
1555 hdr->ih_size = grub_cpu_to_be32 (core_size);
1556 hdr->ih_load = grub_cpu_to_be32 (image_target->link_addr);
1557 hdr->ih_ep = grub_cpu_to_be32 (image_target->link_addr);
1558 hdr->ih_type = GRUB_UBOOT_IH_TYPE_KERNEL;
1559 hdr->ih_os = GRUB_UBOOT_IH_OS_LINUX;
1560 hdr->ih_arch = GRUB_UBOOT_IH_ARCH_ARM;
1561 hdr->ih_comp = GRUB_UBOOT_IH_COMP_NONE;
1562
1563 GRUB_MD_CRC32->init(crc32_context);
1564 GRUB_MD_CRC32->write(crc32_context, hdr + 1, core_size);
1565 GRUB_MD_CRC32->final(crc32_context);
1566 hdr->ih_dcrc = grub_get_unaligned32 (GRUB_MD_CRC32->read (crc32_context));
1567
1568 GRUB_MD_CRC32->init(crc32_context);
1569 GRUB_MD_CRC32->write(crc32_context, hdr, sizeof (*hdr));
1570 GRUB_MD_CRC32->final(crc32_context);
1571 hdr->ih_hcrc = grub_get_unaligned32 (GRUB_MD_CRC32->read (crc32_context));
1572
1573 free (core_img);
1574 core_img = (char *) hdr;
1575 core_size += sizeof (struct grub_uboot_image_header);
1576 }
1577 break;
1578
1579 case IMAGE_MIPS_ARC:
1580 {
1581 char *ecoff_img;
1582 struct ecoff_header {
1583 grub_uint16_t magic;
1584 grub_uint16_t nsec;
1585 grub_uint32_t time;
1586 grub_uint32_t syms;
1587 grub_uint32_t nsyms;
1588 grub_uint16_t opt;
1589 grub_uint16_t flags;
1590 grub_uint16_t magic2;
1591 grub_uint16_t version;
1592 grub_uint32_t textsize;
1593 grub_uint32_t datasize;
1594 grub_uint32_t bsssize;
1595 grub_uint32_t entry;
1596 grub_uint32_t text_start;
1597 grub_uint32_t data_start;
1598 grub_uint32_t bss_start;
1599 grub_uint32_t gprmask;
1600 grub_uint32_t cprmask[4];
1601 grub_uint32_t gp_value;
1602 };
1603 struct ecoff_section
1604 {
1605 char name[8];
1606 grub_uint32_t paddr;
1607 grub_uint32_t vaddr;
1608 grub_uint32_t size;
1609 grub_uint32_t file_offset;
1610 grub_uint32_t reloc;
1611 grub_uint32_t gp;
1612 grub_uint16_t nreloc;
1613 grub_uint16_t ngp;
1614 grub_uint32_t flags;
1615 };
1616 struct ecoff_header *head;
1617 struct ecoff_section *section;
1618 grub_uint32_t target_addr;
1619 size_t program_size;
1620
1621 program_size = ALIGN_ADDR (core_size);
1622 if (comp == COMPRESSION_NONE)
1623 target_addr = (image_target->link_addr - decompress_size);
1624 else
1625 target_addr = ALIGN_UP (image_target->link_addr
1626 + kernel_size + total_module_size, 32);
1627
1628 ecoff_img = xmalloc (program_size + sizeof (*head) + sizeof (*section));
1629 grub_memset (ecoff_img, 0, program_size + sizeof (*head) + sizeof (*section));
1630 head = (void *) ecoff_img;
1631 section = (void *) (head + 1);
1632 head->magic = image_target->bigendian ? grub_host_to_target16 (0x160)
1633 : grub_host_to_target16 (0x166);
1634 head->nsec = grub_host_to_target16 (1);
1635 head->time = grub_host_to_target32 (0);
1636 head->opt = grub_host_to_target16 (0x38);
1637 head->flags = image_target->bigendian
1638 ? grub_host_to_target16 (0x207)
1639 : grub_host_to_target16 (0x103);
1640 head->magic2 = grub_host_to_target16 (0x107);
1641 head->textsize = grub_host_to_target32 (program_size);
1642 head->entry = grub_host_to_target32 (target_addr);
1643 head->text_start = grub_host_to_target32 (target_addr);
1644 head->data_start = grub_host_to_target32 (target_addr + program_size);
1645 grub_memcpy (section->name, ".text", sizeof (".text") - 1);
1646 section->vaddr = grub_host_to_target32 (target_addr);
1647 section->size = grub_host_to_target32 (program_size);
1648 section->file_offset = grub_host_to_target32 (sizeof (*head) + sizeof (*section));
1649 if (!image_target->bigendian)
1650 {
1651 section->paddr = grub_host_to_target32 (0xaa60);
1652 section->flags = grub_host_to_target32 (0x20);
1653 }
1654 memcpy (section + 1, core_img, core_size);
1655 free (core_img);
1656 core_img = ecoff_img;
1657 core_size = program_size + sizeof (*head) + sizeof (*section);
1658 }
1659 break;
1660 case IMAGE_LOONGSON_ELF:
1661 case IMAGE_PPC:
1662 case IMAGE_COREBOOT:
1663 case IMAGE_I386_IEEE1275:
1664 {
1665 char *elf_img;
1666 size_t program_size;
1667 Elf32_Ehdr *ehdr;
1668 Elf32_Phdr *phdr;
1669 grub_uint32_t target_addr;
1670 int header_size, footer_size = 0;
1671 int phnum = 1;
1672
1673 if (image_target->id != IMAGE_LOONGSON_ELF)
1674 phnum += 2;
1675
1676 if (note)
1677 {
1678 phnum++;
1679 footer_size += sizeof (struct grub_ieee1275_note);
1680 }
1681 header_size = ALIGN_ADDR (sizeof (*ehdr) + phnum * sizeof (*phdr));
1682
1683 program_size = ALIGN_ADDR (core_size);
1684
1685 elf_img = xmalloc (program_size + header_size + footer_size);
1686 memset (elf_img, 0, program_size + header_size);
1687 memcpy (elf_img + header_size, core_img, core_size);
1688 ehdr = (void *) elf_img;
1689 phdr = (void *) (elf_img + sizeof (*ehdr));
1690 memcpy (ehdr->e_ident, ELFMAG, SELFMAG);
1691 ehdr->e_ident[EI_CLASS] = ELFCLASS32;
1692 if (!image_target->bigendian)
1693 ehdr->e_ident[EI_DATA] = ELFDATA2LSB;
1694 else
1695 ehdr->e_ident[EI_DATA] = ELFDATA2MSB;
1696 ehdr->e_ident[EI_VERSION] = EV_CURRENT;
1697 ehdr->e_ident[EI_OSABI] = ELFOSABI_NONE;
1698 ehdr->e_type = grub_host_to_target16 (ET_EXEC);
1699 ehdr->e_machine = grub_host_to_target16 (image_target->elf_target);
1700 ehdr->e_version = grub_host_to_target32 (EV_CURRENT);
1701
1702 ehdr->e_phoff = grub_host_to_target32 ((char *) phdr - (char *) ehdr);
1703 ehdr->e_phentsize = grub_host_to_target16 (sizeof (*phdr));
1704 ehdr->e_phnum = grub_host_to_target16 (phnum);
1705
1706 /* No section headers. */
1707 ehdr->e_shoff = grub_host_to_target32 (0);
1708 if (image_target->id == IMAGE_LOONGSON_ELF)
1709 ehdr->e_shentsize = grub_host_to_target16 (0);
1710 else
1711 ehdr->e_shentsize = grub_host_to_target16 (sizeof (Elf32_Shdr));
1712 ehdr->e_shnum = grub_host_to_target16 (0);
1713 ehdr->e_shstrndx = grub_host_to_target16 (0);
1714
1715 ehdr->e_ehsize = grub_host_to_target16 (sizeof (*ehdr));
1716
1717 phdr->p_type = grub_host_to_target32 (PT_LOAD);
1718 phdr->p_offset = grub_host_to_target32 (header_size);
1719 phdr->p_flags = grub_host_to_target32 (PF_R | PF_W | PF_X);
1720
1721 if (image_target->id == IMAGE_LOONGSON_ELF)
1722 {
1723 if (comp == COMPRESSION_NONE)
1724 target_addr = (image_target->link_addr - decompress_size);
1725 else
1726 target_addr = ALIGN_UP (image_target->link_addr
1727 + kernel_size + total_module_size, 32);
1728 }
1729 else
1730 target_addr = image_target->link_addr;
1731 ehdr->e_entry = grub_host_to_target32 (target_addr);
1732 phdr->p_vaddr = grub_host_to_target32 (target_addr);
1733 phdr->p_paddr = grub_host_to_target32 (target_addr);
1734 phdr->p_align = grub_host_to_target32 (align > image_target->link_align ? align : image_target->link_align);
1735 if (image_target->id == IMAGE_LOONGSON_ELF)
1736 ehdr->e_flags = grub_host_to_target32 (0x1000 | EF_MIPS_NOREORDER
1737 | EF_MIPS_PIC | EF_MIPS_CPIC);
1738 else
1739 ehdr->e_flags = 0;
1740 if (image_target->id == IMAGE_LOONGSON_ELF)
1741 {
1742 phdr->p_filesz = grub_host_to_target32 (core_size);
1743 phdr->p_memsz = grub_host_to_target32 (core_size);
1744 }
1745 else
1746 {
1747 grub_uint32_t target_addr_mods;
1748 phdr->p_filesz = grub_host_to_target32 (kernel_size);
1749 phdr->p_memsz = grub_host_to_target32 (kernel_size + bss_size);
1750
1751 phdr++;
1752 phdr->p_type = grub_host_to_target32 (PT_GNU_STACK);
1753 phdr->p_offset = grub_host_to_target32 (header_size + kernel_size);
1754 phdr->p_paddr = phdr->p_vaddr = phdr->p_filesz = phdr->p_memsz = 0;
1755 phdr->p_flags = grub_host_to_target32 (PF_R | PF_W | PF_X);
1756 phdr->p_align = grub_host_to_target32 (image_target->link_align);
1757
1758 phdr++;
1759 phdr->p_type = grub_host_to_target32 (PT_LOAD);
1760 phdr->p_offset = grub_host_to_target32 (header_size + kernel_size);
1761 phdr->p_flags = grub_host_to_target32 (PF_R | PF_W | PF_X);
1762 phdr->p_filesz = phdr->p_memsz
1763 = grub_host_to_target32 (core_size - kernel_size);
1764
1765 if (image_target->id == IMAGE_COREBOOT)
1766 target_addr_mods = GRUB_KERNEL_I386_COREBOOT_MODULES_ADDR;
1767 else
1768 target_addr_mods = ALIGN_UP (target_addr + kernel_size + bss_size
1769 + image_target->mod_gap,
1770 image_target->mod_align);
1771 phdr->p_vaddr = grub_host_to_target32 (target_addr_mods);
1772 phdr->p_paddr = grub_host_to_target32 (target_addr_mods);
1773 phdr->p_align = grub_host_to_target32 (image_target->link_align);
1774 }
1775
1776 if (note)
1777 {
1778 int note_size = sizeof (struct grub_ieee1275_note);
1779 struct grub_ieee1275_note *note_ptr = (struct grub_ieee1275_note *)
1780 (elf_img + program_size + header_size);
1781
1782 grub_util_info ("adding CHRP NOTE segment");
1783
1784 note_ptr->header.namesz = grub_host_to_target32 (sizeof (GRUB_IEEE1275_NOTE_NAME));
1785 note_ptr->header.descsz = grub_host_to_target32 (note_size);
1786 note_ptr->header.type = grub_host_to_target32 (GRUB_IEEE1275_NOTE_TYPE);
1787 strcpy (note_ptr->header.name, GRUB_IEEE1275_NOTE_NAME);
1788 note_ptr->descriptor.real_mode = grub_host_to_target32 (0xffffffff);
1789 note_ptr->descriptor.real_base = grub_host_to_target32 (0x00c00000);
1790 note_ptr->descriptor.real_size = grub_host_to_target32 (0xffffffff);
1791 note_ptr->descriptor.virt_base = grub_host_to_target32 (0xffffffff);
1792 note_ptr->descriptor.virt_size = grub_host_to_target32 (0xffffffff);
1793 note_ptr->descriptor.load_base = grub_host_to_target32 (0x00004000);
1794
1795 phdr++;
1796 phdr->p_type = grub_host_to_target32 (PT_NOTE);
1797 phdr->p_flags = grub_host_to_target32 (PF_R);
1798 phdr->p_align = grub_host_to_target32 (image_target->voidp_sizeof);
1799 phdr->p_vaddr = 0;
1800 phdr->p_paddr = 0;
1801 phdr->p_filesz = grub_host_to_target32 (note_size);
1802 phdr->p_memsz = 0;
1803 phdr->p_offset = grub_host_to_target32 (header_size + program_size);
1804 }
1805
1806 free (core_img);
1807 core_img = elf_img;
1808 core_size = program_size + header_size + footer_size;
1809 }
1810 break;
1811 }
1812
1813 grub_util_write_image (core_img, core_size, out, outname);
1814 free (core_img);
1815 free (kernel_path);
1816
1817 while (path_list)
1818 {
1819 next = path_list->next;
1820 free ((void *) path_list->name);
1821 free (path_list);
1822 path_list = next;
1823 }
1824 }
1825
1826 \f
1827
1828 static struct argp_option options[] = {
1829 {"directory", 'd', N_("DIR"), 0,
1830 /* TRANSLATORS: platform here isn't identifier. It can be translated. */
1831 N_("use images and modules under DIR [default=%s/<platform>]"), 0},
1832 {"prefix", 'p', N_("DIR"), 0, N_("set prefix directory [default=%s]"), 0},
1833 {"memdisk", 'm', N_("FILE"), 0,
1834 /* TRANSLATORS: "memdisk" here isn't an identifier, it can be translated.
1835 "embed" is a verb (command description). "*/
1836 N_("embed FILE as a memdisk image\n"
1837 "Implies `-p (memdisk)/boot/grub' but prefix can be overridden by "
1838 "later options"), 0},
1839 /* TRANSLATORS: "embed" is a verb (command description). "*/
1840 {"config", 'c', N_("FILE"), 0, N_("embed FILE as an early config"), 0},
1841 /* TRANSLATORS: "embed" is a verb (command description). "*/
1842 {"pubkey", 'k', N_("FILE"), 0, N_("embed FILE as public key for signature checking"), 0},
1843 /* TRANSLATORS: NOTE is a name of segment. */
1844 {"note", 'n', 0, 0, N_("add NOTE segment for CHRP IEEE1275"), 0},
1845 {"output", 'o', N_("FILE"), 0, N_("output a generated image to FILE [default=stdout]"), 0},
1846 {"format", 'O', N_("FORMAT"), 0, 0, 0},
1847 {"compression", 'C', "(xz|none|auto)", 0, N_("choose the compression to use for core image"), 0},
1848 {"verbose", 'v', 0, 0, N_("print verbose messages."), 0},
1849 { 0, 0, 0, 0, 0, 0 }
1850 };
1851
1852 static char *
1853 help_filter (int key, const char *text, void *input __attribute__ ((unused)))
1854 {
1855 switch (key)
1856 {
1857 case 'd':
1858 return xasprintf (text, GRUB_PKGLIBDIR);
1859 case 'p':
1860 return xasprintf (text, DEFAULT_DIRECTORY);
1861 case 'O':
1862 {
1863 int format_len = 0;
1864 char *formats;
1865 char *ptr;
1866 char *ret;
1867 unsigned i;
1868 for (i = 0; i < ARRAY_SIZE (image_targets); i++)
1869 format_len += strlen (image_targets[i].names[0]) + 2;
1870 ptr = formats = xmalloc (format_len);
1871 for (i = 0; i < ARRAY_SIZE (image_targets); i++)
1872 {
1873 strcpy (ptr, image_targets[i].names[0]);
1874 ptr += strlen (image_targets[i].names[0]);
1875 *ptr++ = ',';
1876 *ptr++ = ' ';
1877 }
1878 ptr[-2] = 0;
1879 ret = xasprintf ("%s\n%s %s", _("generate an image in FORMAT"),
1880 _("available formats:"), formats);
1881 free (formats);
1882 return ret;
1883 }
1884 default:
1885 return (char *) text;
1886 }
1887 }
1888
1889 struct arguments
1890 {
1891 size_t nmodules;
1892 size_t modules_max;
1893 char **modules;
1894 char *output;
1895 char *dir;
1896 char *prefix;
1897 char *memdisk;
1898 char **pubkeys;
1899 size_t npubkeys;
1900 char *font;
1901 char *config;
1902 int note;
1903 struct image_target_desc *image_target;
1904 grub_compression_t comp;
1905 };
1906
1907 static error_t
1908 argp_parser (int key, char *arg, struct argp_state *state)
1909 {
1910 /* Get the input argument from argp_parse, which we
1911 know is a pointer to our arguments structure. */
1912 struct arguments *arguments = state->input;
1913
1914 switch (key)
1915 {
1916 case 'o':
1917 if (arguments->output)
1918 free (arguments->output);
1919
1920 arguments->output = xstrdup (arg);
1921 break;
1922
1923 case 'O':
1924 {
1925 unsigned i, j;
1926 for (i = 0; i < ARRAY_SIZE (image_targets); i++)
1927 for (j = 0; image_targets[i].names[j]
1928 && j < ARRAY_SIZE (image_targets[i].names); j++)
1929 if (strcmp (arg, image_targets[i].names[j]) == 0)
1930 arguments->image_target = &image_targets[i];
1931 if (!arguments->image_target)
1932 {
1933 printf (_("unknown target format %s\n"), arg);
1934 argp_usage (state);
1935 exit (1);
1936 }
1937 break;
1938 }
1939 case 'd':
1940 if (arguments->dir)
1941 free (arguments->dir);
1942
1943 arguments->dir = xstrdup (arg);
1944 break;
1945
1946 case 'n':
1947 arguments->note = 1;
1948 break;
1949
1950 case 'm':
1951 if (arguments->memdisk)
1952 free (arguments->memdisk);
1953
1954 arguments->memdisk = xstrdup (arg);
1955
1956 if (arguments->prefix)
1957 free (arguments->prefix);
1958
1959 arguments->prefix = xstrdup ("(memdisk)/boot/grub");
1960 break;
1961
1962 case 'k':
1963 arguments->pubkeys = xrealloc (arguments->pubkeys,
1964 sizeof (arguments->pubkeys[0])
1965 * (arguments->npubkeys + 1));
1966 arguments->pubkeys[arguments->npubkeys++] = xstrdup (arg);
1967 break;
1968
1969 case 'c':
1970 if (arguments->config)
1971 free (arguments->config);
1972
1973 arguments->config = xstrdup (arg);
1974 break;
1975
1976 case 'C':
1977 if (grub_strcmp (arg, "xz") == 0)
1978 {
1979 #ifdef HAVE_LIBLZMA
1980 arguments->comp = COMPRESSION_XZ;
1981 #else
1982 grub_util_error ("%s",
1983 _("grub-mkimage is compiled without XZ support"));
1984 #endif
1985 }
1986 else if (grub_strcmp (arg, "none") == 0)
1987 arguments->comp = COMPRESSION_NONE;
1988 else if (grub_strcmp (arg, "auto") == 0)
1989 arguments->comp = COMPRESSION_AUTO;
1990 else
1991 grub_util_error (_("Unknown compression format %s"), arg);
1992 break;
1993
1994 case 'p':
1995 if (arguments->prefix)
1996 free (arguments->prefix);
1997
1998 arguments->prefix = xstrdup (arg);
1999 break;
2000
2001 case 'v':
2002 verbosity++;
2003 break;
2004 case ARGP_KEY_ARG:
2005 assert (arguments->nmodules < arguments->modules_max);
2006 arguments->modules[arguments->nmodules++] = xstrdup(arg);
2007 break;
2008
2009 default:
2010 return ARGP_ERR_UNKNOWN;
2011 }
2012 return 0;
2013 }
2014
2015 static struct argp argp = {
2016 options, argp_parser, N_("[OPTION]... [MODULES]"),
2017 N_("Make a bootable image of GRUB."),
2018 NULL, help_filter, NULL
2019 };
2020
2021 int
2022 main (int argc, char *argv[])
2023 {
2024 FILE *fp = stdout;
2025 struct arguments arguments;
2026
2027 set_program_name (argv[0]);
2028
2029 grub_util_init_nls ();
2030
2031 memset (&arguments, 0, sizeof (struct arguments));
2032 arguments.comp = COMPRESSION_AUTO;
2033 arguments.modules_max = argc + 1;
2034 arguments.modules = xmalloc ((arguments.modules_max + 1)
2035 * sizeof (arguments.modules[0]));
2036 memset (arguments.modules, 0, (arguments.modules_max + 1)
2037 * sizeof (arguments.modules[0]));
2038
2039 if (argp_parse (&argp, argc, argv, 0, 0, &arguments) != 0)
2040 {
2041 fprintf (stderr, "%s", _("Error in parsing command line arguments\n"));
2042 exit(1);
2043 }
2044
2045 if (!arguments.image_target)
2046 {
2047 char *program = xstrdup(program_name);
2048 printf ("%s\n", _("Target format not specified (use the -O option)."));
2049 argp_help (&argp, stderr, ARGP_HELP_STD_USAGE, program);
2050 free (program);
2051 exit(1);
2052 }
2053
2054 if (arguments.output)
2055 {
2056 fp = fopen (arguments.output, "wb");
2057 if (! fp)
2058 grub_util_error (_("cannot open `%s': %s"), arguments.output,
2059 strerror (errno));
2060 }
2061
2062 if (!arguments.dir)
2063 {
2064 arguments.dir = xmalloc (sizeof (GRUB_PKGLIBDIR)
2065 + grub_strlen (arguments.image_target->dirname)
2066 + 1);
2067 memcpy (arguments.dir, GRUB_PKGLIBDIR,
2068 sizeof (GRUB_PKGLIBDIR) - 1);
2069 *(arguments.dir + sizeof (GRUB_PKGLIBDIR) - 1) = '/';
2070 strcpy (arguments.dir + sizeof (GRUB_PKGLIBDIR),
2071 arguments.image_target->dirname);
2072 }
2073
2074 generate_image (arguments.dir, arguments.prefix ? : DEFAULT_DIRECTORY, fp,
2075 arguments.output,
2076 arguments.modules, arguments.memdisk, arguments.pubkeys,
2077 arguments.npubkeys, arguments.config,
2078 arguments.image_target, arguments.note, arguments.comp);
2079
2080 fflush (fp);
2081 fsync (fileno (fp));
2082 fclose (fp);
2083
2084 if (arguments.dir)
2085 free (arguments.dir);
2086
2087 if (arguments.output)
2088 free (arguments.output);
2089
2090 return 0;
2091 }