]> git.proxmox.com Git - grub2.git/blob - util/mkimage.c
* configure.ac: Check for lzma.h for enabling liblzma and allow
[grub2.git] / util / 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 #include <grub/osdep/hostfile.h>
47 #include <grub/util/install.h>
48
49 #define ALIGN_ADDR(x) (ALIGN_UP((x), image_target->voidp_sizeof))
50
51 #ifdef USE_LIBLZMA
52 #include <lzma.h>
53 #endif
54
55 #define TARGET_NO_FIELD 0xffffffff
56
57 struct grub_install_image_target_desc
58 {
59 const char *dirname;
60 const char *names[6];
61 grub_size_t voidp_sizeof;
62 int bigendian;
63 enum {
64 IMAGE_I386_PC, IMAGE_EFI, IMAGE_COREBOOT,
65 IMAGE_SPARC64_AOUT, IMAGE_SPARC64_RAW, IMAGE_SPARC64_CDCORE,
66 IMAGE_I386_IEEE1275,
67 IMAGE_LOONGSON_ELF, IMAGE_QEMU, IMAGE_PPC, IMAGE_YEELOONG_FLASH,
68 IMAGE_FULOONG2F_FLASH, IMAGE_I386_PC_PXE, IMAGE_MIPS_ARC,
69 IMAGE_QEMU_MIPS_FLASH, IMAGE_UBOOT, IMAGE_XEN
70 } id;
71 enum
72 {
73 PLATFORM_FLAGS_NONE = 0,
74 PLATFORM_FLAGS_DECOMPRESSORS = 2,
75 PLATFORM_FLAGS_MODULES_BEFORE_KERNEL = 4,
76 } flags;
77 unsigned total_module_size;
78 unsigned decompressor_compressed_size;
79 unsigned decompressor_uncompressed_size;
80 unsigned decompressor_uncompressed_addr;
81 unsigned link_align;
82 grub_uint16_t elf_target;
83 unsigned section_align;
84 signed vaddr_offset;
85 grub_uint64_t link_addr;
86 unsigned mod_gap, mod_align;
87 grub_compression_t default_compression;
88 grub_uint16_t pe_target;
89 };
90
91 #define EFI32_HEADER_SIZE ALIGN_UP (GRUB_PE32_MSDOS_STUB_SIZE \
92 + GRUB_PE32_SIGNATURE_SIZE \
93 + sizeof (struct grub_pe32_coff_header) \
94 + sizeof (struct grub_pe32_optional_header) \
95 + 4 * sizeof (struct grub_pe32_section_table), \
96 GRUB_PE32_SECTION_ALIGNMENT)
97
98 #define EFI64_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_pe64_optional_header) \
102 + 4 * sizeof (struct grub_pe32_section_table), \
103 GRUB_PE32_SECTION_ALIGNMENT)
104
105 static const struct grub_install_image_target_desc image_targets[] =
106 {
107 {
108 .dirname = "i386-coreboot",
109 .names = { "i386-coreboot", NULL },
110 .voidp_sizeof = 4,
111 .bigendian = 0,
112 .id = IMAGE_COREBOOT,
113 .flags = PLATFORM_FLAGS_NONE,
114 .total_module_size = TARGET_NO_FIELD,
115 .decompressor_compressed_size = TARGET_NO_FIELD,
116 .decompressor_uncompressed_size = TARGET_NO_FIELD,
117 .decompressor_uncompressed_addr = TARGET_NO_FIELD,
118 .section_align = 1,
119 .vaddr_offset = 0,
120 .link_addr = GRUB_KERNEL_I386_COREBOOT_LINK_ADDR,
121 .elf_target = EM_386,
122 .link_align = 4,
123 .mod_gap = GRUB_KERNEL_I386_COREBOOT_MOD_GAP,
124 .mod_align = GRUB_KERNEL_I386_COREBOOT_MOD_ALIGN
125 },
126 {
127 .dirname = "i386-multiboot",
128 .names = { "i386-multiboot", NULL},
129 .voidp_sizeof = 4,
130 .bigendian = 0,
131 .id = IMAGE_COREBOOT,
132 .flags = PLATFORM_FLAGS_NONE,
133 .total_module_size = TARGET_NO_FIELD,
134 .decompressor_compressed_size = TARGET_NO_FIELD,
135 .decompressor_uncompressed_size = TARGET_NO_FIELD,
136 .decompressor_uncompressed_addr = TARGET_NO_FIELD,
137 .section_align = 1,
138 .vaddr_offset = 0,
139 .link_addr = GRUB_KERNEL_I386_COREBOOT_LINK_ADDR,
140 .elf_target = EM_386,
141 .link_align = 4,
142 .mod_gap = GRUB_KERNEL_I386_COREBOOT_MOD_GAP,
143 .mod_align = GRUB_KERNEL_I386_COREBOOT_MOD_ALIGN
144 },
145 {
146 .dirname = "i386-pc",
147 .names = { "i386-pc", NULL },
148 .voidp_sizeof = 4,
149 .bigendian = 0,
150 .id = IMAGE_I386_PC,
151 .flags = PLATFORM_FLAGS_DECOMPRESSORS,
152 .total_module_size = TARGET_NO_FIELD,
153 .decompressor_compressed_size = GRUB_DECOMPRESSOR_I386_PC_COMPRESSED_SIZE,
154 .decompressor_uncompressed_size = GRUB_DECOMPRESSOR_I386_PC_UNCOMPRESSED_SIZE,
155 .decompressor_uncompressed_addr = TARGET_NO_FIELD,
156 .section_align = 1,
157 .vaddr_offset = 0,
158 .link_addr = GRUB_KERNEL_I386_PC_LINK_ADDR,
159 .default_compression = GRUB_COMPRESSION_LZMA
160 },
161 {
162 .dirname = "i386-pc",
163 .names = { "i386-pc-pxe", NULL },
164 .voidp_sizeof = 4,
165 .bigendian = 0,
166 .id = IMAGE_I386_PC_PXE,
167 .flags = PLATFORM_FLAGS_DECOMPRESSORS,
168 .total_module_size = TARGET_NO_FIELD,
169 .decompressor_compressed_size = GRUB_DECOMPRESSOR_I386_PC_COMPRESSED_SIZE,
170 .decompressor_uncompressed_size = GRUB_DECOMPRESSOR_I386_PC_UNCOMPRESSED_SIZE,
171 .decompressor_uncompressed_addr = TARGET_NO_FIELD,
172 .section_align = 1,
173 .vaddr_offset = 0,
174 .link_addr = GRUB_KERNEL_I386_PC_LINK_ADDR,
175 .default_compression = GRUB_COMPRESSION_LZMA
176 },
177 {
178 .dirname = "i386-efi",
179 .names = { "i386-efi", NULL },
180 .voidp_sizeof = 4,
181 .bigendian = 0,
182 .id = IMAGE_EFI,
183 .flags = PLATFORM_FLAGS_NONE,
184 .total_module_size = TARGET_NO_FIELD,
185 .decompressor_compressed_size = TARGET_NO_FIELD,
186 .decompressor_uncompressed_size = TARGET_NO_FIELD,
187 .decompressor_uncompressed_addr = TARGET_NO_FIELD,
188 .section_align = GRUB_PE32_SECTION_ALIGNMENT,
189 .vaddr_offset = EFI32_HEADER_SIZE,
190 .pe_target = GRUB_PE32_MACHINE_I386,
191 .elf_target = EM_386,
192 },
193 {
194 .dirname = "i386-ieee1275",
195 .names = { "i386-ieee1275", NULL },
196 .voidp_sizeof = 4,
197 .bigendian = 0,
198 .id = IMAGE_I386_IEEE1275,
199 .flags = PLATFORM_FLAGS_NONE,
200 .total_module_size = TARGET_NO_FIELD,
201 .decompressor_compressed_size = TARGET_NO_FIELD,
202 .decompressor_uncompressed_size = TARGET_NO_FIELD,
203 .decompressor_uncompressed_addr = TARGET_NO_FIELD,
204 .section_align = 1,
205 .vaddr_offset = 0,
206 .link_addr = GRUB_KERNEL_I386_IEEE1275_LINK_ADDR,
207 .elf_target = EM_386,
208 .mod_gap = GRUB_KERNEL_I386_IEEE1275_MOD_GAP,
209 .mod_align = GRUB_KERNEL_I386_IEEE1275_MOD_ALIGN,
210 .link_align = 4,
211 },
212 {
213 .dirname = "i386-qemu",
214 .names = { "i386-qemu", NULL },
215 .voidp_sizeof = 4,
216 .bigendian = 0,
217 .id = IMAGE_QEMU,
218 .flags = PLATFORM_FLAGS_NONE,
219 .total_module_size = TARGET_NO_FIELD,
220 .decompressor_compressed_size = TARGET_NO_FIELD,
221 .decompressor_uncompressed_size = TARGET_NO_FIELD,
222 .decompressor_uncompressed_addr = TARGET_NO_FIELD,
223 .section_align = 1,
224 .vaddr_offset = 0,
225 .link_addr = GRUB_KERNEL_I386_QEMU_LINK_ADDR
226 },
227 {
228 .dirname = "x86_64-efi",
229 .names = { "x86_64-efi", NULL },
230 .voidp_sizeof = 8,
231 .bigendian = 0,
232 .id = IMAGE_EFI,
233 .flags = PLATFORM_FLAGS_NONE,
234 .total_module_size = TARGET_NO_FIELD,
235 .decompressor_compressed_size = TARGET_NO_FIELD,
236 .decompressor_uncompressed_size = TARGET_NO_FIELD,
237 .decompressor_uncompressed_addr = TARGET_NO_FIELD,
238 .section_align = GRUB_PE32_SECTION_ALIGNMENT,
239 .vaddr_offset = EFI64_HEADER_SIZE,
240 .pe_target = GRUB_PE32_MACHINE_X86_64,
241 .elf_target = EM_X86_64,
242 },
243 {
244 .dirname = "i386-xen",
245 .names = { "i386-xen", NULL },
246 .voidp_sizeof = 4,
247 .bigendian = 0,
248 .id = IMAGE_XEN,
249 .flags = PLATFORM_FLAGS_NONE,
250 .total_module_size = TARGET_NO_FIELD,
251 .decompressor_compressed_size = TARGET_NO_FIELD,
252 .decompressor_uncompressed_size = TARGET_NO_FIELD,
253 .decompressor_uncompressed_addr = TARGET_NO_FIELD,
254 .section_align = 1,
255 .vaddr_offset = 0,
256 .link_addr = 0,
257 .elf_target = EM_386,
258 .mod_gap = GRUB_KERNEL_I386_XEN_MOD_GAP,
259 .mod_align = GRUB_KERNEL_I386_XEN_MOD_ALIGN,
260 .link_align = 4
261 },
262 {
263 .dirname = "x86_64-xen",
264 .names = { "x86_64-xen", NULL },
265 .voidp_sizeof = 8,
266 .bigendian = 0,
267 .id = IMAGE_XEN,
268 .flags = PLATFORM_FLAGS_NONE,
269 .total_module_size = TARGET_NO_FIELD,
270 .decompressor_compressed_size = TARGET_NO_FIELD,
271 .decompressor_uncompressed_size = TARGET_NO_FIELD,
272 .decompressor_uncompressed_addr = TARGET_NO_FIELD,
273 .section_align = 1,
274 .vaddr_offset = 0,
275 .link_addr = 0,
276 .elf_target = EM_X86_64,
277 .mod_gap = GRUB_KERNEL_X86_64_XEN_MOD_GAP,
278 .mod_align = GRUB_KERNEL_X86_64_XEN_MOD_ALIGN,
279 .link_align = 8
280 },
281 {
282 .dirname = "mipsel-loongson",
283 .names = { "mipsel-yeeloong-flash", NULL },
284 .voidp_sizeof = 4,
285 .bigendian = 0,
286 .id = IMAGE_YEELOONG_FLASH,
287 .flags = PLATFORM_FLAGS_DECOMPRESSORS,
288 .total_module_size = GRUB_KERNEL_MIPS_LOONGSON_TOTAL_MODULE_SIZE,
289 .decompressor_compressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_COMPRESSED_SIZE,
290 .decompressor_uncompressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_SIZE,
291 .decompressor_uncompressed_addr = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_ADDR,
292 .section_align = 1,
293 .vaddr_offset = 0,
294 .link_addr = GRUB_KERNEL_MIPS_LOONGSON_LINK_ADDR,
295 .elf_target = EM_MIPS,
296 .link_align = GRUB_KERNEL_MIPS_LOONGSON_LINK_ALIGN,
297 .default_compression = GRUB_COMPRESSION_NONE
298 },
299 {
300 .dirname = "mipsel-loongson",
301 .names = { "mipsel-fuloong2f-flash", NULL },
302 .voidp_sizeof = 4,
303 .bigendian = 0,
304 .id = IMAGE_FULOONG2F_FLASH,
305 .flags = PLATFORM_FLAGS_DECOMPRESSORS,
306 .total_module_size = GRUB_KERNEL_MIPS_LOONGSON_TOTAL_MODULE_SIZE,
307 .decompressor_compressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_COMPRESSED_SIZE,
308 .decompressor_uncompressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_SIZE,
309 .decompressor_uncompressed_addr = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_ADDR,
310 .section_align = 1,
311 .vaddr_offset = 0,
312 .link_addr = GRUB_KERNEL_MIPS_LOONGSON_LINK_ADDR,
313 .elf_target = EM_MIPS,
314 .link_align = GRUB_KERNEL_MIPS_LOONGSON_LINK_ALIGN,
315 .default_compression = GRUB_COMPRESSION_NONE
316 },
317 {
318 .dirname = "mipsel-loongson",
319 .names = { "mipsel-loongson-elf", "mipsel-yeeloong-elf",
320 "mipsel-fuloong2f-elf", "mipsel-fuloong2e-elf",
321 "mipsel-fuloong-elf", NULL },
322 .voidp_sizeof = 4,
323 .bigendian = 0,
324 .id = IMAGE_LOONGSON_ELF,
325 .flags = PLATFORM_FLAGS_DECOMPRESSORS,
326 .total_module_size = GRUB_KERNEL_MIPS_LOONGSON_TOTAL_MODULE_SIZE,
327 .decompressor_compressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_COMPRESSED_SIZE,
328 .decompressor_uncompressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_SIZE,
329 .decompressor_uncompressed_addr = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_ADDR,
330 .section_align = 1,
331 .vaddr_offset = 0,
332 .link_addr = GRUB_KERNEL_MIPS_LOONGSON_LINK_ADDR,
333 .elf_target = EM_MIPS,
334 .link_align = GRUB_KERNEL_MIPS_LOONGSON_LINK_ALIGN,
335 .default_compression = GRUB_COMPRESSION_NONE
336 },
337 {
338 .dirname = "powerpc-ieee1275",
339 .names = { "powerpc-ieee1275", NULL },
340 .voidp_sizeof = 4,
341 .bigendian = 1,
342 .id = IMAGE_PPC,
343 .flags = PLATFORM_FLAGS_NONE,
344 .total_module_size = TARGET_NO_FIELD,
345 .decompressor_compressed_size = TARGET_NO_FIELD,
346 .decompressor_uncompressed_size = TARGET_NO_FIELD,
347 .decompressor_uncompressed_addr = TARGET_NO_FIELD,
348 .section_align = 1,
349 .vaddr_offset = 0,
350 .link_addr = GRUB_KERNEL_POWERPC_IEEE1275_LINK_ADDR,
351 .elf_target = EM_PPC,
352 .mod_gap = GRUB_KERNEL_POWERPC_IEEE1275_MOD_GAP,
353 .mod_align = GRUB_KERNEL_POWERPC_IEEE1275_MOD_ALIGN,
354 .link_align = 4
355 },
356 {
357 .dirname = "sparc64-ieee1275",
358 .names = { "sparc64-ieee1275-raw", NULL },
359 .voidp_sizeof = 8,
360 .bigendian = 1,
361 .id = IMAGE_SPARC64_RAW,
362 .flags = PLATFORM_FLAGS_NONE,
363 .total_module_size = GRUB_KERNEL_SPARC64_IEEE1275_TOTAL_MODULE_SIZE,
364 .decompressor_compressed_size = TARGET_NO_FIELD,
365 .decompressor_uncompressed_size = TARGET_NO_FIELD,
366 .decompressor_uncompressed_addr = TARGET_NO_FIELD,
367 .section_align = 1,
368 .vaddr_offset = 0,
369 .link_addr = GRUB_KERNEL_SPARC64_IEEE1275_LINK_ADDR
370 },
371 {
372 .dirname = "sparc64-ieee1275",
373 .names = { "sparc64-ieee1275-cdcore", NULL },
374 .voidp_sizeof = 8,
375 .bigendian = 1,
376 .id = IMAGE_SPARC64_CDCORE,
377 .flags = PLATFORM_FLAGS_NONE,
378 .total_module_size = GRUB_KERNEL_SPARC64_IEEE1275_TOTAL_MODULE_SIZE,
379 .decompressor_compressed_size = TARGET_NO_FIELD,
380 .decompressor_uncompressed_size = TARGET_NO_FIELD,
381 .decompressor_uncompressed_addr = TARGET_NO_FIELD,
382 .section_align = 1,
383 .vaddr_offset = 0,
384 .link_addr = GRUB_KERNEL_SPARC64_IEEE1275_LINK_ADDR
385 },
386 {
387 .dirname = "sparc64-ieee1275",
388 .names = { "sparc64-ieee1275-aout", NULL },
389 .voidp_sizeof = 8,
390 .bigendian = 1,
391 .id = IMAGE_SPARC64_AOUT,
392 .flags = PLATFORM_FLAGS_NONE,
393 .total_module_size = GRUB_KERNEL_SPARC64_IEEE1275_TOTAL_MODULE_SIZE,
394 .decompressor_compressed_size = TARGET_NO_FIELD,
395 .decompressor_uncompressed_size = TARGET_NO_FIELD,
396 .decompressor_uncompressed_addr = TARGET_NO_FIELD,
397 .section_align = 1,
398 .vaddr_offset = 0,
399 .link_addr = GRUB_KERNEL_SPARC64_IEEE1275_LINK_ADDR
400 },
401 {
402 .dirname = "ia64-efi",
403 .names = {"ia64-efi", NULL},
404 .voidp_sizeof = 8,
405 .bigendian = 0,
406 .id = IMAGE_EFI,
407 .flags = PLATFORM_FLAGS_NONE,
408 .total_module_size = TARGET_NO_FIELD,
409 .decompressor_compressed_size = TARGET_NO_FIELD,
410 .decompressor_uncompressed_size = TARGET_NO_FIELD,
411 .decompressor_uncompressed_addr = TARGET_NO_FIELD,
412 .section_align = GRUB_PE32_SECTION_ALIGNMENT,
413 .vaddr_offset = EFI64_HEADER_SIZE,
414 .pe_target = GRUB_PE32_MACHINE_IA64,
415 .elf_target = EM_IA_64,
416 },
417 {
418 .dirname = "mips-arc",
419 .names = {"mips-arc", NULL},
420 .voidp_sizeof = 4,
421 .bigendian = 1,
422 .id = IMAGE_MIPS_ARC,
423 .flags = PLATFORM_FLAGS_DECOMPRESSORS,
424 .total_module_size = GRUB_KERNEL_MIPS_ARC_TOTAL_MODULE_SIZE,
425 .decompressor_compressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_COMPRESSED_SIZE,
426 .decompressor_uncompressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_SIZE,
427 .decompressor_uncompressed_addr = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_ADDR,
428 .section_align = 1,
429 .vaddr_offset = 0,
430 .link_addr = GRUB_KERNEL_MIPS_ARC_LINK_ADDR,
431 .elf_target = EM_MIPS,
432 .link_align = GRUB_KERNEL_MIPS_ARC_LINK_ALIGN,
433 .default_compression = GRUB_COMPRESSION_NONE
434 },
435 {
436 .dirname = "mipsel-arc",
437 .names = {"mipsel-arc", NULL},
438 .voidp_sizeof = 4,
439 .bigendian = 0,
440 .id = IMAGE_MIPS_ARC,
441 .flags = PLATFORM_FLAGS_DECOMPRESSORS,
442 .total_module_size = GRUB_KERNEL_MIPS_ARC_TOTAL_MODULE_SIZE,
443 .decompressor_compressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_COMPRESSED_SIZE,
444 .decompressor_uncompressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_SIZE,
445 .decompressor_uncompressed_addr = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_ADDR,
446 .section_align = 1,
447 .vaddr_offset = 0,
448 .link_addr = GRUB_KERNEL_MIPSEL_ARC_LINK_ADDR,
449 .elf_target = EM_MIPS,
450 .link_align = GRUB_KERNEL_MIPS_ARC_LINK_ALIGN,
451 .default_compression = GRUB_COMPRESSION_NONE
452 },
453 {
454 .dirname = "mipsel-qemu_mips",
455 .names = { "mipsel-qemu_mips-elf", NULL },
456 .voidp_sizeof = 4,
457 .bigendian = 0,
458 .id = IMAGE_LOONGSON_ELF,
459 .flags = PLATFORM_FLAGS_DECOMPRESSORS,
460 .total_module_size = GRUB_KERNEL_MIPS_QEMU_MIPS_TOTAL_MODULE_SIZE,
461 .decompressor_compressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_COMPRESSED_SIZE,
462 .decompressor_uncompressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_SIZE,
463 .decompressor_uncompressed_addr = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_ADDR,
464 .section_align = 1,
465 .vaddr_offset = 0,
466 .link_addr = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ADDR,
467 .elf_target = EM_MIPS,
468 .link_align = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ALIGN,
469 .default_compression = GRUB_COMPRESSION_NONE
470 },
471 {
472 .dirname = "mips-qemu_mips",
473 .names = { "mips-qemu_mips-flash", NULL },
474 .voidp_sizeof = 4,
475 .bigendian = 1,
476 .id = IMAGE_QEMU_MIPS_FLASH,
477 .flags = PLATFORM_FLAGS_DECOMPRESSORS,
478 .total_module_size = GRUB_KERNEL_MIPS_QEMU_MIPS_TOTAL_MODULE_SIZE,
479 .decompressor_compressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_COMPRESSED_SIZE,
480 .decompressor_uncompressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_SIZE,
481 .decompressor_uncompressed_addr = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_ADDR,
482 .section_align = 1,
483 .vaddr_offset = 0,
484 .link_addr = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ADDR,
485 .elf_target = EM_MIPS,
486 .link_align = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ALIGN,
487 .default_compression = GRUB_COMPRESSION_NONE
488 },
489 {
490 .dirname = "mipsel-qemu_mips",
491 .names = { "mipsel-qemu_mips-flash", NULL },
492 .voidp_sizeof = 4,
493 .bigendian = 0,
494 .id = IMAGE_QEMU_MIPS_FLASH,
495 .flags = PLATFORM_FLAGS_DECOMPRESSORS,
496 .total_module_size = GRUB_KERNEL_MIPS_QEMU_MIPS_TOTAL_MODULE_SIZE,
497 .decompressor_compressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_COMPRESSED_SIZE,
498 .decompressor_uncompressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_SIZE,
499 .decompressor_uncompressed_addr = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_ADDR,
500 .section_align = 1,
501 .vaddr_offset = 0,
502 .link_addr = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ADDR,
503 .elf_target = EM_MIPS,
504 .link_align = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ALIGN,
505 .default_compression = GRUB_COMPRESSION_NONE
506 },
507 {
508 .dirname = "mips-qemu_mips",
509 .names = { "mips-qemu_mips-elf", NULL },
510 .voidp_sizeof = 4,
511 .bigendian = 1,
512 .id = IMAGE_LOONGSON_ELF,
513 .flags = PLATFORM_FLAGS_DECOMPRESSORS,
514 .total_module_size = GRUB_KERNEL_MIPS_QEMU_MIPS_TOTAL_MODULE_SIZE,
515 .decompressor_compressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_COMPRESSED_SIZE,
516 .decompressor_uncompressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_SIZE,
517 .decompressor_uncompressed_addr = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_ADDR,
518 .section_align = 1,
519 .vaddr_offset = 0,
520 .link_addr = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ADDR,
521 .elf_target = EM_MIPS,
522 .link_align = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ALIGN,
523 .default_compression = GRUB_COMPRESSION_NONE
524 },
525 {
526 .dirname = "arm-uboot",
527 .names = { "arm-uboot", NULL },
528 .voidp_sizeof = 4,
529 .bigendian = 0,
530 .id = IMAGE_UBOOT,
531 .flags = PLATFORM_FLAGS_NONE,
532 .total_module_size = GRUB_KERNEL_ARM_UBOOT_TOTAL_MODULE_SIZE,
533 .decompressor_compressed_size = TARGET_NO_FIELD,
534 .decompressor_uncompressed_size = TARGET_NO_FIELD,
535 .decompressor_uncompressed_addr = TARGET_NO_FIELD,
536 .section_align = GRUB_KERNEL_ARM_UBOOT_MOD_ALIGN,
537 .vaddr_offset = 0,
538 .link_addr = GRUB_KERNEL_ARM_UBOOT_LINK_ADDR,
539 .elf_target = EM_ARM,
540 .mod_gap = GRUB_KERNEL_ARM_UBOOT_MOD_GAP,
541 .mod_align = GRUB_KERNEL_ARM_UBOOT_MOD_ALIGN,
542 .link_align = 4
543 },
544 {
545 .dirname = "arm-efi",
546 .names = { "arm-efi", NULL },
547 .voidp_sizeof = 4,
548 .bigendian = 0,
549 .id = IMAGE_EFI,
550 .flags = PLATFORM_FLAGS_NONE,
551 .total_module_size = TARGET_NO_FIELD,
552 .decompressor_compressed_size = TARGET_NO_FIELD,
553 .decompressor_uncompressed_size = TARGET_NO_FIELD,
554 .decompressor_uncompressed_addr = TARGET_NO_FIELD,
555 .section_align = GRUB_PE32_SECTION_ALIGNMENT,
556 .vaddr_offset = ALIGN_UP (GRUB_PE32_MSDOS_STUB_SIZE
557 + GRUB_PE32_SIGNATURE_SIZE
558 + sizeof (struct grub_pe32_coff_header)
559 + sizeof (struct grub_pe32_optional_header)
560 + 4 * sizeof (struct grub_pe32_section_table),
561 GRUB_PE32_SECTION_ALIGNMENT),
562 .pe_target = GRUB_PE32_MACHINE_ARMTHUMB_MIXED,
563 .elf_target = EM_ARM,
564 },
565 };
566
567 #define grub_target_to_host32(x) (grub_target_to_host32_real (image_target, (x)))
568 #define grub_host_to_target32(x) (grub_host_to_target32_real (image_target, (x)))
569 #define grub_target_to_host64(x) (grub_target_to_host64_real (image_target, (x)))
570 #define grub_host_to_target64(x) (grub_host_to_target64_real (image_target, (x)))
571 #define grub_host_to_target_addr(x) (grub_host_to_target_addr_real (image_target, (x)))
572 #define grub_target_to_host16(x) (grub_target_to_host16_real (image_target, (x)))
573 #define grub_host_to_target16(x) (grub_host_to_target16_real (image_target, (x)))
574
575 static inline grub_uint32_t
576 grub_target_to_host32_real (const struct grub_install_image_target_desc *image_target,
577 grub_uint32_t in)
578 {
579 if (image_target->bigendian)
580 return grub_be_to_cpu32 (in);
581 else
582 return grub_le_to_cpu32 (in);
583 }
584
585 static inline grub_uint64_t
586 grub_target_to_host64_real (const struct grub_install_image_target_desc *image_target,
587 grub_uint64_t in)
588 {
589 if (image_target->bigendian)
590 return grub_be_to_cpu64 (in);
591 else
592 return grub_le_to_cpu64 (in);
593 }
594
595 static inline grub_uint64_t
596 grub_host_to_target64_real (const struct grub_install_image_target_desc *image_target,
597 grub_uint64_t in)
598 {
599 if (image_target->bigendian)
600 return grub_cpu_to_be64 (in);
601 else
602 return grub_cpu_to_le64 (in);
603 }
604
605 static inline grub_uint32_t
606 grub_host_to_target32_real (const struct grub_install_image_target_desc *image_target,
607 grub_uint32_t in)
608 {
609 if (image_target->bigendian)
610 return grub_cpu_to_be32 (in);
611 else
612 return grub_cpu_to_le32 (in);
613 }
614
615 static inline grub_uint16_t
616 grub_target_to_host16_real (const struct grub_install_image_target_desc *image_target,
617 grub_uint16_t in)
618 {
619 if (image_target->bigendian)
620 return grub_be_to_cpu16 (in);
621 else
622 return grub_le_to_cpu16 (in);
623 }
624
625 static inline grub_uint16_t
626 grub_host_to_target16_real (const struct grub_install_image_target_desc *image_target,
627 grub_uint16_t in)
628 {
629 if (image_target->bigendian)
630 return grub_cpu_to_be16 (in);
631 else
632 return grub_cpu_to_le16 (in);
633 }
634
635 static inline grub_uint64_t
636 grub_host_to_target_addr_real (const struct grub_install_image_target_desc *image_target, grub_uint64_t in)
637 {
638 if (image_target->voidp_sizeof == 8)
639 return grub_host_to_target64_real (image_target, in);
640 else
641 return grub_host_to_target32_real (image_target, in);
642 }
643
644 static inline grub_uint64_t
645 grub_target_to_host_real (const struct grub_install_image_target_desc *image_target, grub_uint64_t in)
646 {
647 if (image_target->voidp_sizeof == 8)
648 return grub_target_to_host64_real (image_target, in);
649 else
650 return grub_target_to_host32_real (image_target, in);
651 }
652
653 #define GRUB_IEEE1275_NOTE_NAME "PowerPC"
654 #define GRUB_IEEE1275_NOTE_TYPE 0x1275
655
656 /* These structures are defined according to the CHRP binding to IEEE1275,
657 "Client Program Format" section. */
658
659 struct grub_ieee1275_note_desc
660 {
661 grub_uint32_t real_mode;
662 grub_uint32_t real_base;
663 grub_uint32_t real_size;
664 grub_uint32_t virt_base;
665 grub_uint32_t virt_size;
666 grub_uint32_t load_base;
667 };
668
669 struct grub_ieee1275_note
670 {
671 Elf32_Nhdr header;
672 char name[ALIGN_UP(sizeof (GRUB_IEEE1275_NOTE_NAME), 4)];
673 struct grub_ieee1275_note_desc descriptor;
674 };
675
676 #define GRUB_XEN_NOTE_NAME "Xen"
677
678 #define grub_target_to_host(val) grub_target_to_host_real(image_target, (val))
679
680 #include <grub/lib/LzmaEnc.h>
681
682 static void *SzAlloc(void *p __attribute__ ((unused)), size_t size) { return xmalloc(size); }
683 static void SzFree(void *p __attribute__ ((unused)), void *address) { free(address); }
684 static ISzAlloc g_Alloc = { SzAlloc, SzFree };
685
686 static void
687 compress_kernel_lzma (char *kernel_img, size_t kernel_size,
688 char **core_img, size_t *core_size)
689 {
690 CLzmaEncProps props;
691 unsigned char out_props[5];
692 size_t out_props_size = 5;
693
694 LzmaEncProps_Init(&props);
695 props.dictSize = 1 << 16;
696 props.lc = 3;
697 props.lp = 0;
698 props.pb = 2;
699 props.numThreads = 1;
700
701 *core_img = xmalloc (kernel_size);
702
703 *core_size = kernel_size;
704 if (LzmaEncode ((unsigned char *) *core_img, core_size,
705 (unsigned char *) kernel_img,
706 kernel_size,
707 &props, out_props, &out_props_size,
708 0, NULL, &g_Alloc, &g_Alloc) != SZ_OK)
709 grub_util_error ("%s", _("cannot compress the kernel image"));
710 }
711
712 #ifdef USE_LIBLZMA
713 static void
714 compress_kernel_xz (char *kernel_img, size_t kernel_size,
715 char **core_img, size_t *core_size)
716 {
717 lzma_stream strm = LZMA_STREAM_INIT;
718 lzma_ret xzret;
719 lzma_options_lzma lzopts = {
720 .dict_size = 1 << 16,
721 .preset_dict = NULL,
722 .preset_dict_size = 0,
723 .lc = 3,
724 .lp = 0,
725 .pb = 2,
726 .mode = LZMA_MODE_NORMAL,
727 .nice_len = 64,
728 .mf = LZMA_MF_BT4,
729 .depth = 0,
730 };
731 lzma_filter fltrs[] = {
732 { .id = LZMA_FILTER_LZMA2, .options = &lzopts},
733 { .id = LZMA_VLI_UNKNOWN, .options = NULL}
734 };
735
736 xzret = lzma_stream_encoder (&strm, fltrs, LZMA_CHECK_NONE);
737 if (xzret != LZMA_OK)
738 grub_util_error ("%s", _("cannot compress the kernel image"));
739
740 *core_img = xmalloc (kernel_size);
741
742 *core_size = kernel_size;
743 strm.next_in = (unsigned char *) kernel_img;
744 strm.avail_in = kernel_size;
745 strm.next_out = (unsigned char *) *core_img;
746 strm.avail_out = *core_size;
747
748 while (1)
749 {
750 xzret = lzma_code (&strm, LZMA_FINISH);
751 if (xzret == LZMA_OK)
752 continue;
753 if (xzret == LZMA_STREAM_END)
754 break;
755 grub_util_error ("%s", _("cannot compress the kernel image"));
756 }
757
758 *core_size -= strm.avail_out;
759 }
760 #endif
761
762 static void
763 compress_kernel (const struct grub_install_image_target_desc *image_target, char *kernel_img,
764 size_t kernel_size, char **core_img, size_t *core_size,
765 grub_compression_t comp)
766 {
767 if (image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS
768 && (comp == GRUB_COMPRESSION_LZMA))
769 {
770 compress_kernel_lzma (kernel_img, kernel_size, core_img,
771 core_size);
772 return;
773 }
774
775 #ifdef USE_LIBLZMA
776 if (image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS
777 && (comp == GRUB_COMPRESSION_XZ))
778 {
779 compress_kernel_xz (kernel_img, kernel_size, core_img,
780 core_size);
781 return;
782 }
783 #endif
784
785 if (image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS
786 && (comp != GRUB_COMPRESSION_NONE))
787 grub_util_error (_("unknown compression %d\n"), comp);
788
789 *core_img = xmalloc (kernel_size);
790 memcpy (*core_img, kernel_img, kernel_size);
791 *core_size = kernel_size;
792 }
793
794 struct fixup_block_list
795 {
796 struct fixup_block_list *next;
797 int state;
798 struct grub_pe32_fixup_block b;
799 };
800
801 #pragma GCC diagnostic ignored "-Wcast-align"
802
803 #define MKIMAGE_ELF32 1
804 #include "grub-mkimagexx.c"
805 #undef MKIMAGE_ELF32
806
807 #define MKIMAGE_ELF64 1
808 #include "grub-mkimagexx.c"
809 #undef MKIMAGE_ELF64
810
811 const struct grub_install_image_target_desc *
812 grub_install_get_image_target (const char *arg)
813 {
814 unsigned i, j;
815 for (i = 0; i < ARRAY_SIZE (image_targets); i++)
816 for (j = 0; image_targets[i].names[j]
817 && j < ARRAY_SIZE (image_targets[i].names); j++)
818 if (strcmp (arg, image_targets[i].names[j]) == 0)
819 return &image_targets[i];
820 return NULL;
821 }
822
823 const char *
824 grub_util_get_target_dirname (const struct grub_install_image_target_desc *t)
825 {
826 return t->dirname;
827 }
828
829 char *
830 grub_install_get_image_targets_string (void)
831 {
832 int format_len = 0;
833 char *formats;
834 char *ptr;
835 unsigned i;
836 for (i = 0; i < ARRAY_SIZE (image_targets); i++)
837 format_len += strlen (image_targets[i].names[0]) + 2;
838 ptr = formats = xmalloc (format_len);
839 for (i = 0; i < ARRAY_SIZE (image_targets); i++)
840 {
841 strcpy (ptr, image_targets[i].names[0]);
842 ptr += strlen (image_targets[i].names[0]);
843 *ptr++ = ',';
844 *ptr++ = ' ';
845 }
846 ptr[-2] = 0;
847
848 return formats;
849 }
850
851 void
852 grub_install_generate_image (const char *dir, const char *prefix,
853 FILE *out, const char *outname, char *mods[],
854 char *memdisk_path, char **pubkey_paths,
855 size_t npubkeys, char *config_path,
856 const struct grub_install_image_target_desc *image_target,
857 int note,
858 grub_compression_t comp)
859 {
860 char *kernel_img, *core_img;
861 size_t kernel_size, total_module_size, core_size, exec_size;
862 size_t memdisk_size = 0, config_size = 0, config_size_pure = 0;
863 size_t prefix_size = 0;
864 char *kernel_path;
865 size_t offset;
866 struct grub_util_path_list *path_list, *p, *next;
867 size_t bss_size;
868 grub_uint64_t start_address;
869 void *rel_section = 0;
870 size_t reloc_size = 0, align;
871 size_t decompress_size = 0;
872
873 if (comp == GRUB_COMPRESSION_AUTO)
874 comp = image_target->default_compression;
875
876 if (image_target->id == IMAGE_I386_PC
877 || image_target->id == IMAGE_I386_PC_PXE)
878 comp = GRUB_COMPRESSION_LZMA;
879
880 path_list = grub_util_resolve_dependencies (dir, "moddep.lst", mods);
881
882 kernel_path = grub_util_get_path (dir, "kernel.img");
883
884 if (image_target->voidp_sizeof == 8)
885 total_module_size = sizeof (struct grub_module_info64);
886 else
887 total_module_size = sizeof (struct grub_module_info32);
888
889 {
890 size_t i;
891 for (i = 0; i < npubkeys; i++)
892 {
893 size_t curs;
894 curs = ALIGN_ADDR (grub_util_get_image_size (pubkey_paths[i]));
895 grub_util_info ("the size of public key %zd is 0x%llx",
896 i, (unsigned long long) curs);
897 total_module_size += curs + sizeof (struct grub_module_header);
898 }
899 }
900
901 if (memdisk_path)
902 {
903 memdisk_size = ALIGN_UP(grub_util_get_image_size (memdisk_path), 512);
904 grub_util_info ("the size of memory disk is 0x%llx",
905 (unsigned long long) memdisk_size);
906 total_module_size += memdisk_size + sizeof (struct grub_module_header);
907 }
908
909 if (config_path)
910 {
911 config_size_pure = grub_util_get_image_size (config_path) + 1;
912 config_size = ALIGN_ADDR (config_size_pure);
913 grub_util_info ("the size of config file is 0x%llx",
914 (unsigned long long) config_size);
915 total_module_size += config_size + sizeof (struct grub_module_header);
916 }
917
918 if (prefix)
919 {
920 prefix_size = ALIGN_ADDR (strlen (prefix) + 1);
921 total_module_size += prefix_size + sizeof (struct grub_module_header);
922 }
923
924 for (p = path_list; p; p = p->next)
925 total_module_size += (ALIGN_ADDR (grub_util_get_image_size (p->name))
926 + sizeof (struct grub_module_header));
927
928 grub_util_info ("the total module size is 0x%llx",
929 (unsigned long long) total_module_size);
930
931 if (image_target->voidp_sizeof == 4)
932 kernel_img = load_image32 (kernel_path, &exec_size, &kernel_size, &bss_size,
933 total_module_size, &start_address, &rel_section,
934 &reloc_size, &align, image_target);
935 else
936 kernel_img = load_image64 (kernel_path, &exec_size, &kernel_size, &bss_size,
937 total_module_size, &start_address, &rel_section,
938 &reloc_size, &align, image_target);
939 if (image_target->id == IMAGE_XEN && align < 4096)
940 align = 4096;
941
942 if ((image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS)
943 && (image_target->total_module_size != TARGET_NO_FIELD))
944 *((grub_uint32_t *) (kernel_img + image_target->total_module_size))
945 = grub_host_to_target32 (total_module_size);
946
947 if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL)
948 memmove (kernel_img + total_module_size, kernel_img, kernel_size);
949
950 if (image_target->voidp_sizeof == 8)
951 {
952 /* Fill in the grub_module_info structure. */
953 struct grub_module_info64 *modinfo;
954 if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL)
955 modinfo = (struct grub_module_info64 *) kernel_img;
956 else
957 modinfo = (struct grub_module_info64 *) (kernel_img + kernel_size);
958 memset (modinfo, 0, sizeof (struct grub_module_info64));
959 modinfo->magic = grub_host_to_target32 (GRUB_MODULE_MAGIC);
960 modinfo->offset = grub_host_to_target_addr (sizeof (struct grub_module_info64));
961 modinfo->size = grub_host_to_target_addr (total_module_size);
962 if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL)
963 offset = sizeof (struct grub_module_info64);
964 else
965 offset = kernel_size + sizeof (struct grub_module_info64);
966 }
967 else
968 {
969 /* Fill in the grub_module_info structure. */
970 struct grub_module_info32 *modinfo;
971 if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL)
972 modinfo = (struct grub_module_info32 *) kernel_img;
973 else
974 modinfo = (struct grub_module_info32 *) (kernel_img + kernel_size);
975 memset (modinfo, 0, sizeof (struct grub_module_info32));
976 modinfo->magic = grub_host_to_target32 (GRUB_MODULE_MAGIC);
977 modinfo->offset = grub_host_to_target_addr (sizeof (struct grub_module_info32));
978 modinfo->size = grub_host_to_target_addr (total_module_size);
979 if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL)
980 offset = sizeof (struct grub_module_info32);
981 else
982 offset = kernel_size + sizeof (struct grub_module_info32);
983 }
984
985 for (p = path_list; p; p = p->next)
986 {
987 struct grub_module_header *header;
988 size_t mod_size, orig_size;
989
990 orig_size = grub_util_get_image_size (p->name);
991 mod_size = ALIGN_ADDR (orig_size);
992
993 header = (struct grub_module_header *) (kernel_img + offset);
994 memset (header, 0, sizeof (struct grub_module_header));
995 header->type = grub_host_to_target32 (OBJ_TYPE_ELF);
996 header->size = grub_host_to_target32 (mod_size + sizeof (*header));
997 offset += sizeof (*header);
998 memset (kernel_img + offset + orig_size, 0, mod_size - orig_size);
999
1000 grub_util_load_image (p->name, kernel_img + offset);
1001 offset += mod_size;
1002 }
1003
1004 {
1005 size_t i;
1006 for (i = 0; i < npubkeys; i++)
1007 {
1008 size_t curs;
1009 struct grub_module_header *header;
1010
1011 curs = grub_util_get_image_size (pubkey_paths[i]);
1012
1013 header = (struct grub_module_header *) (kernel_img + offset);
1014 memset (header, 0, sizeof (struct grub_module_header));
1015 header->type = grub_host_to_target32 (OBJ_TYPE_PUBKEY);
1016 header->size = grub_host_to_target32 (curs + sizeof (*header));
1017 offset += sizeof (*header);
1018
1019 grub_util_load_image (pubkey_paths[i], kernel_img + offset);
1020 offset += ALIGN_ADDR (curs);
1021 }
1022 }
1023
1024 if (memdisk_path)
1025 {
1026 struct grub_module_header *header;
1027
1028 header = (struct grub_module_header *) (kernel_img + offset);
1029 memset (header, 0, sizeof (struct grub_module_header));
1030 header->type = grub_host_to_target32 (OBJ_TYPE_MEMDISK);
1031 header->size = grub_host_to_target32 (memdisk_size + sizeof (*header));
1032 offset += sizeof (*header);
1033
1034 grub_util_load_image (memdisk_path, kernel_img + offset);
1035 offset += memdisk_size;
1036 }
1037
1038 if (config_path)
1039 {
1040 struct grub_module_header *header;
1041
1042 header = (struct grub_module_header *) (kernel_img + offset);
1043 memset (header, 0, sizeof (struct grub_module_header));
1044 header->type = grub_host_to_target32 (OBJ_TYPE_CONFIG);
1045 header->size = grub_host_to_target32 (config_size + sizeof (*header));
1046 offset += sizeof (*header);
1047
1048 grub_util_load_image (config_path, kernel_img + offset);
1049 *(kernel_img + offset + config_size_pure - 1) = 0;
1050 offset += config_size;
1051 }
1052
1053 if (prefix)
1054 {
1055 struct grub_module_header *header;
1056
1057 header = (struct grub_module_header *) (kernel_img + offset);
1058 memset (header, 0, sizeof (struct grub_module_header));
1059 header->type = grub_host_to_target32 (OBJ_TYPE_PREFIX);
1060 header->size = grub_host_to_target32 (prefix_size + sizeof (*header));
1061 offset += sizeof (*header);
1062
1063 grub_memset (kernel_img + offset, 0, prefix_size);
1064 grub_strcpy (kernel_img + offset, prefix);
1065 offset += prefix_size;
1066 }
1067
1068 grub_util_info ("kernel_img=%p, kernel_size=0x%llx", kernel_img,
1069 (unsigned long long) kernel_size);
1070 compress_kernel (image_target, kernel_img, kernel_size + total_module_size,
1071 &core_img, &core_size, comp);
1072 free (kernel_img);
1073
1074 grub_util_info ("the core size is 0x%llx", (unsigned long long) core_size);
1075
1076 if (!(image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS)
1077 && image_target->total_module_size != TARGET_NO_FIELD)
1078 *((grub_uint32_t *) (core_img + image_target->total_module_size))
1079 = grub_host_to_target32 (total_module_size);
1080
1081 if (image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS)
1082 {
1083 char *full_img;
1084 size_t full_size;
1085 char *decompress_path, *decompress_img;
1086 const char *name;
1087
1088 switch (comp)
1089 {
1090 case GRUB_COMPRESSION_XZ:
1091 name = "xz_decompress.img";
1092 break;
1093 case GRUB_COMPRESSION_LZMA:
1094 name = "lzma_decompress.img";
1095 break;
1096 case GRUB_COMPRESSION_NONE:
1097 name = "none_decompress.img";
1098 break;
1099 default:
1100 grub_util_error (_("unknown compression %d\n"), comp);
1101 }
1102
1103 decompress_path = grub_util_get_path (dir, name);
1104 decompress_size = grub_util_get_image_size (decompress_path);
1105 decompress_img = grub_util_read_image (decompress_path);
1106
1107 if ((image_target->id == IMAGE_I386_PC
1108 || image_target->id == IMAGE_I386_PC_PXE)
1109 && decompress_size > GRUB_KERNEL_I386_PC_LINK_ADDR - 0x8200)
1110 grub_util_error ("%s", _("Decompressor is too big"));
1111
1112 if (image_target->decompressor_compressed_size != TARGET_NO_FIELD)
1113 *((grub_uint32_t *) (decompress_img
1114 + image_target->decompressor_compressed_size))
1115 = grub_host_to_target32 (core_size);
1116
1117 if (image_target->decompressor_uncompressed_size != TARGET_NO_FIELD)
1118 *((grub_uint32_t *) (decompress_img
1119 + image_target->decompressor_uncompressed_size))
1120 = grub_host_to_target32 (kernel_size + total_module_size);
1121
1122 if (image_target->decompressor_uncompressed_addr != TARGET_NO_FIELD)
1123 {
1124 if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL)
1125 *((grub_uint32_t *) (decompress_img + image_target->decompressor_uncompressed_addr))
1126 = grub_host_to_target_addr (image_target->link_addr - total_module_size);
1127 else
1128 *((grub_uint32_t *) (decompress_img + image_target->decompressor_uncompressed_addr))
1129 = grub_host_to_target_addr (image_target->link_addr);
1130 }
1131 full_size = core_size + decompress_size;
1132
1133 full_img = xmalloc (full_size);
1134 memset (full_img, 0, full_size);
1135
1136 memcpy (full_img, decompress_img, decompress_size);
1137
1138 memcpy (full_img + decompress_size, core_img, core_size);
1139
1140 memset (full_img + decompress_size + core_size, 0,
1141 full_size - (decompress_size + core_size));
1142
1143 free (core_img);
1144 core_img = full_img;
1145 core_size = full_size;
1146 }
1147
1148 switch (image_target->id)
1149 {
1150 case IMAGE_I386_PC:
1151 case IMAGE_I386_PC_PXE:
1152 if (GRUB_KERNEL_I386_PC_LINK_ADDR + core_size > 0x78000
1153 || (core_size > (0xffff << GRUB_DISK_SECTOR_BITS))
1154 || (kernel_size + bss_size + GRUB_KERNEL_I386_PC_LINK_ADDR > 0x68000))
1155 grub_util_error (_("core image is too big (0x%x > 0x%x)"),
1156 GRUB_KERNEL_I386_PC_LINK_ADDR + (unsigned) core_size,
1157 0x78000);
1158 /* fallthrough */
1159 case IMAGE_COREBOOT:
1160 case IMAGE_QEMU:
1161 if (kernel_size + bss_size + GRUB_KERNEL_I386_PC_LINK_ADDR > 0x68000)
1162 grub_util_error (_("kernel image is too big (0x%x > 0x%x)"),
1163 (unsigned) kernel_size + (unsigned) bss_size
1164 + GRUB_KERNEL_I386_PC_LINK_ADDR,
1165 0x68000);
1166 break;
1167 case IMAGE_LOONGSON_ELF:
1168 case IMAGE_YEELOONG_FLASH:
1169 case IMAGE_FULOONG2F_FLASH:
1170 case IMAGE_EFI:
1171 case IMAGE_MIPS_ARC:
1172 case IMAGE_QEMU_MIPS_FLASH:
1173 case IMAGE_XEN:
1174 break;
1175 case IMAGE_SPARC64_AOUT:
1176 case IMAGE_SPARC64_RAW:
1177 case IMAGE_SPARC64_CDCORE:
1178 case IMAGE_I386_IEEE1275:
1179 case IMAGE_PPC:
1180 case IMAGE_UBOOT:
1181 break;
1182 }
1183
1184 switch (image_target->id)
1185 {
1186 case IMAGE_I386_PC:
1187 case IMAGE_I386_PC_PXE:
1188 {
1189 unsigned num;
1190 char *boot_path, *boot_img;
1191 size_t boot_size;
1192
1193 num = ((core_size + GRUB_DISK_SECTOR_SIZE - 1) >> GRUB_DISK_SECTOR_BITS);
1194 if (image_target->id == IMAGE_I386_PC_PXE)
1195 {
1196 char *pxeboot_path, *pxeboot_img;
1197 size_t pxeboot_size;
1198 grub_uint32_t *ptr;
1199
1200 pxeboot_path = grub_util_get_path (dir, "pxeboot.img");
1201 pxeboot_size = grub_util_get_image_size (pxeboot_path);
1202 pxeboot_img = grub_util_read_image (pxeboot_path);
1203
1204 grub_util_write_image (pxeboot_img, pxeboot_size, out,
1205 outname);
1206 free (pxeboot_img);
1207 free (pxeboot_path);
1208
1209 /* Remove Multiboot header to avoid confusing ipxe. */
1210 for (ptr = (grub_uint32_t *) core_img;
1211 ptr < (grub_uint32_t *) (core_img + MULTIBOOT_SEARCH); ptr++)
1212 if (*ptr == grub_host_to_target32 (MULTIBOOT_HEADER_MAGIC)
1213 && grub_target_to_host32 (ptr[0])
1214 + grub_target_to_host32 (ptr[1])
1215 + grub_target_to_host32 (ptr[2]) == 0)
1216 {
1217 *ptr = 0;
1218 break;
1219 }
1220 }
1221
1222 boot_path = grub_util_get_path (dir, "diskboot.img");
1223 boot_size = grub_util_get_image_size (boot_path);
1224 if (boot_size != GRUB_DISK_SECTOR_SIZE)
1225 grub_util_error (_("diskboot.img size must be %u bytes"),
1226 GRUB_DISK_SECTOR_SIZE);
1227
1228 boot_img = grub_util_read_image (boot_path);
1229
1230 {
1231 struct grub_pc_bios_boot_blocklist *block;
1232 block = (struct grub_pc_bios_boot_blocklist *) (boot_img
1233 + GRUB_DISK_SECTOR_SIZE
1234 - sizeof (*block));
1235 block->len = grub_host_to_target16 (num);
1236
1237 /* This is filled elsewhere. Verify it just in case. */
1238 assert (block->segment
1239 == grub_host_to_target16 (GRUB_BOOT_I386_PC_KERNEL_SEG
1240 + (GRUB_DISK_SECTOR_SIZE >> 4)));
1241 }
1242
1243 grub_util_write_image (boot_img, boot_size, out, outname);
1244 free (boot_img);
1245 free (boot_path);
1246 }
1247 break;
1248 case IMAGE_EFI:
1249 {
1250 void *pe_img;
1251 grub_uint8_t *header;
1252 void *sections;
1253 size_t pe_size;
1254 struct grub_pe32_coff_header *c;
1255 struct grub_pe32_section_table *text_section, *data_section;
1256 struct grub_pe32_section_table *mods_section, *reloc_section;
1257 static const grub_uint8_t stub[] = GRUB_PE32_MSDOS_STUB;
1258 int header_size;
1259 int reloc_addr;
1260
1261 if (image_target->voidp_sizeof == 4)
1262 header_size = EFI32_HEADER_SIZE;
1263 else
1264 header_size = EFI64_HEADER_SIZE;
1265
1266 reloc_addr = ALIGN_UP (header_size + core_size,
1267 image_target->section_align);
1268
1269 pe_size = ALIGN_UP (reloc_addr + reloc_size,
1270 image_target->section_align);
1271 pe_img = xmalloc (reloc_addr + reloc_size);
1272 memset (pe_img, 0, header_size);
1273 memcpy ((char *) pe_img + header_size, core_img, core_size);
1274 memcpy ((char *) pe_img + reloc_addr, rel_section, reloc_size);
1275 header = pe_img;
1276
1277 /* The magic. */
1278 memcpy (header, stub, GRUB_PE32_MSDOS_STUB_SIZE);
1279 memcpy (header + GRUB_PE32_MSDOS_STUB_SIZE, "PE\0\0",
1280 GRUB_PE32_SIGNATURE_SIZE);
1281
1282 /* The COFF file header. */
1283 c = (struct grub_pe32_coff_header *) (header + GRUB_PE32_MSDOS_STUB_SIZE
1284 + GRUB_PE32_SIGNATURE_SIZE);
1285 c->machine = grub_host_to_target16 (image_target->pe_target);
1286
1287 c->num_sections = grub_host_to_target16 (4);
1288 c->time = grub_host_to_target32 (time (0));
1289 c->characteristics = grub_host_to_target16 (GRUB_PE32_EXECUTABLE_IMAGE
1290 | GRUB_PE32_LINE_NUMS_STRIPPED
1291 | ((image_target->voidp_sizeof == 4)
1292 ? GRUB_PE32_32BIT_MACHINE
1293 : 0)
1294 | GRUB_PE32_LOCAL_SYMS_STRIPPED
1295 | GRUB_PE32_DEBUG_STRIPPED);
1296
1297 /* The PE Optional header. */
1298 if (image_target->voidp_sizeof == 4)
1299 {
1300 struct grub_pe32_optional_header *o;
1301
1302 c->optional_header_size = grub_host_to_target16 (sizeof (struct grub_pe32_optional_header));
1303
1304 o = (struct grub_pe32_optional_header *)
1305 (header + GRUB_PE32_MSDOS_STUB_SIZE + GRUB_PE32_SIGNATURE_SIZE
1306 + sizeof (struct grub_pe32_coff_header));
1307 o->magic = grub_host_to_target16 (GRUB_PE32_PE32_MAGIC);
1308 o->code_size = grub_host_to_target32 (exec_size);
1309 o->data_size = grub_cpu_to_le32 (reloc_addr - exec_size
1310 - header_size);
1311 o->bss_size = grub_cpu_to_le32 (bss_size);
1312 o->entry_addr = grub_cpu_to_le32 (start_address);
1313 o->code_base = grub_cpu_to_le32 (header_size);
1314
1315 o->data_base = grub_host_to_target32 (header_size + exec_size);
1316
1317 o->image_base = 0;
1318 o->section_alignment = grub_host_to_target32 (image_target->section_align);
1319 o->file_alignment = grub_host_to_target32 (image_target->section_align);
1320 o->image_size = grub_host_to_target32 (pe_size);
1321 o->header_size = grub_host_to_target32 (header_size);
1322 o->subsystem = grub_host_to_target16 (GRUB_PE32_SUBSYSTEM_EFI_APPLICATION);
1323
1324 /* Do these really matter? */
1325 o->stack_reserve_size = grub_host_to_target32 (0x10000);
1326 o->stack_commit_size = grub_host_to_target32 (0x10000);
1327 o->heap_reserve_size = grub_host_to_target32 (0x10000);
1328 o->heap_commit_size = grub_host_to_target32 (0x10000);
1329
1330 o->num_data_directories = grub_host_to_target32 (GRUB_PE32_NUM_DATA_DIRECTORIES);
1331
1332 o->base_relocation_table.rva = grub_host_to_target32 (reloc_addr);
1333 o->base_relocation_table.size = grub_host_to_target32 (reloc_size);
1334 sections = o + 1;
1335 }
1336 else
1337 {
1338 struct grub_pe64_optional_header *o;
1339
1340 c->optional_header_size = grub_host_to_target16 (sizeof (struct grub_pe64_optional_header));
1341
1342 o = (struct grub_pe64_optional_header *)
1343 (header + GRUB_PE32_MSDOS_STUB_SIZE + GRUB_PE32_SIGNATURE_SIZE
1344 + sizeof (struct grub_pe32_coff_header));
1345 o->magic = grub_host_to_target16 (GRUB_PE32_PE64_MAGIC);
1346 o->code_size = grub_host_to_target32 (exec_size);
1347 o->data_size = grub_cpu_to_le32 (reloc_addr - exec_size
1348 - header_size);
1349 o->bss_size = grub_cpu_to_le32 (bss_size);
1350 o->entry_addr = grub_cpu_to_le32 (start_address);
1351 o->code_base = grub_cpu_to_le32 (header_size);
1352 o->image_base = 0;
1353 o->section_alignment = grub_host_to_target32 (image_target->section_align);
1354 o->file_alignment = grub_host_to_target32 (image_target->section_align);
1355 o->image_size = grub_host_to_target32 (pe_size);
1356 o->header_size = grub_host_to_target32 (header_size);
1357 o->subsystem = grub_host_to_target16 (GRUB_PE32_SUBSYSTEM_EFI_APPLICATION);
1358
1359 /* Do these really matter? */
1360 o->stack_reserve_size = grub_host_to_target64 (0x10000);
1361 o->stack_commit_size = grub_host_to_target64 (0x10000);
1362 o->heap_reserve_size = grub_host_to_target64 (0x10000);
1363 o->heap_commit_size = grub_host_to_target64 (0x10000);
1364
1365 o->num_data_directories
1366 = grub_host_to_target32 (GRUB_PE32_NUM_DATA_DIRECTORIES);
1367
1368 o->base_relocation_table.rva = grub_host_to_target32 (reloc_addr);
1369 o->base_relocation_table.size = grub_host_to_target32 (reloc_size);
1370 sections = o + 1;
1371 }
1372 /* The sections. */
1373 text_section = sections;
1374 strcpy (text_section->name, ".text");
1375 text_section->virtual_size = grub_cpu_to_le32 (exec_size);
1376 text_section->virtual_address = grub_cpu_to_le32 (header_size);
1377 text_section->raw_data_size = grub_cpu_to_le32 (exec_size);
1378 text_section->raw_data_offset = grub_cpu_to_le32 (header_size);
1379 text_section->characteristics = grub_cpu_to_le32 (GRUB_PE32_SCN_CNT_CODE
1380 | GRUB_PE32_SCN_MEM_EXECUTE
1381 | GRUB_PE32_SCN_MEM_READ);
1382
1383 data_section = text_section + 1;
1384 strcpy (data_section->name, ".data");
1385 data_section->virtual_size = grub_cpu_to_le32 (kernel_size - exec_size);
1386 data_section->virtual_address = grub_cpu_to_le32 (header_size + exec_size);
1387 data_section->raw_data_size = grub_cpu_to_le32 (kernel_size - exec_size);
1388 data_section->raw_data_offset = grub_cpu_to_le32 (header_size + exec_size);
1389 data_section->characteristics
1390 = grub_cpu_to_le32 (GRUB_PE32_SCN_CNT_INITIALIZED_DATA
1391 | GRUB_PE32_SCN_MEM_READ
1392 | GRUB_PE32_SCN_MEM_WRITE);
1393
1394 #if 0
1395 bss_section = data_section + 1;
1396 strcpy (bss_section->name, ".bss");
1397 bss_section->virtual_size = grub_cpu_to_le32 (bss_size);
1398 bss_section->virtual_address = grub_cpu_to_le32 (header_size + kernel_size);
1399 bss_section->raw_data_size = 0;
1400 bss_section->raw_data_offset = 0;
1401 bss_section->characteristics
1402 = grub_cpu_to_le32 (GRUB_PE32_SCN_MEM_READ
1403 | GRUB_PE32_SCN_MEM_WRITE
1404 | GRUB_PE32_SCN_ALIGN_64BYTES
1405 | GRUB_PE32_SCN_CNT_INITIALIZED_DATA
1406 | 0x80);
1407 #endif
1408
1409 mods_section = data_section + 1;
1410 strcpy (mods_section->name, "mods");
1411 mods_section->virtual_size = grub_cpu_to_le32 (reloc_addr - kernel_size - header_size);
1412 mods_section->virtual_address = grub_cpu_to_le32 (header_size + kernel_size + bss_size);
1413 mods_section->raw_data_size = grub_cpu_to_le32 (reloc_addr - kernel_size - header_size);
1414 mods_section->raw_data_offset = grub_cpu_to_le32 (header_size + kernel_size);
1415 mods_section->characteristics
1416 = grub_cpu_to_le32 (GRUB_PE32_SCN_CNT_INITIALIZED_DATA
1417 | GRUB_PE32_SCN_MEM_READ
1418 | GRUB_PE32_SCN_MEM_WRITE);
1419
1420 reloc_section = mods_section + 1;
1421 strcpy (reloc_section->name, ".reloc");
1422 reloc_section->virtual_size = grub_cpu_to_le32 (reloc_size);
1423 reloc_section->virtual_address = grub_cpu_to_le32 (reloc_addr + bss_size);
1424 reloc_section->raw_data_size = grub_cpu_to_le32 (reloc_size);
1425 reloc_section->raw_data_offset = grub_cpu_to_le32 (reloc_addr);
1426 reloc_section->characteristics
1427 = grub_cpu_to_le32 (GRUB_PE32_SCN_CNT_INITIALIZED_DATA
1428 | GRUB_PE32_SCN_MEM_DISCARDABLE
1429 | GRUB_PE32_SCN_MEM_READ);
1430 free (core_img);
1431 core_img = pe_img;
1432 core_size = pe_size;
1433 }
1434 break;
1435 case IMAGE_QEMU:
1436 {
1437 char *rom_img;
1438 size_t rom_size;
1439 char *boot_path, *boot_img;
1440 size_t boot_size;
1441
1442 boot_path = grub_util_get_path (dir, "boot.img");
1443 boot_size = grub_util_get_image_size (boot_path);
1444 boot_img = grub_util_read_image (boot_path);
1445
1446 /* Rom sizes must be 64k-aligned. */
1447 rom_size = ALIGN_UP (core_size + boot_size, 64 * 1024);
1448
1449 rom_img = xmalloc (rom_size);
1450 memset (rom_img, 0, rom_size);
1451
1452 *((grub_int32_t *) (core_img + GRUB_KERNEL_I386_QEMU_CORE_ENTRY_ADDR))
1453 = grub_host_to_target32 ((grub_uint32_t) -rom_size);
1454
1455 memcpy (rom_img, core_img, core_size);
1456
1457 *((grub_int32_t *) (boot_img + GRUB_BOOT_I386_QEMU_CORE_ENTRY_ADDR))
1458 = grub_host_to_target32 ((grub_uint32_t) -rom_size);
1459
1460 memcpy (rom_img + rom_size - boot_size, boot_img, boot_size);
1461
1462 free (core_img);
1463 core_img = rom_img;
1464 core_size = rom_size;
1465
1466 free (boot_img);
1467 free (boot_path);
1468 }
1469 break;
1470 case IMAGE_SPARC64_AOUT:
1471 {
1472 void *aout_img;
1473 size_t aout_size;
1474 struct grub_aout32_header *aout_head;
1475
1476 aout_size = core_size + sizeof (*aout_head);
1477 aout_img = xmalloc (aout_size);
1478 aout_head = aout_img;
1479 grub_memset (aout_head, 0, sizeof (*aout_head));
1480 aout_head->a_midmag = grub_host_to_target32 ((AOUT_MID_SUN << 16)
1481 | AOUT32_OMAGIC);
1482 aout_head->a_text = grub_host_to_target32 (core_size);
1483 aout_head->a_entry
1484 = grub_host_to_target32 (GRUB_BOOT_SPARC64_IEEE1275_IMAGE_ADDRESS);
1485 memcpy ((char *) aout_img + sizeof (*aout_head), core_img, core_size);
1486
1487 free (core_img);
1488 core_img = aout_img;
1489 core_size = aout_size;
1490 }
1491 break;
1492 case IMAGE_SPARC64_RAW:
1493 {
1494 unsigned int num;
1495 char *boot_path, *boot_img;
1496 size_t boot_size;
1497
1498 num = ((core_size + GRUB_DISK_SECTOR_SIZE - 1) >> GRUB_DISK_SECTOR_BITS);
1499 num <<= GRUB_DISK_SECTOR_BITS;
1500
1501 boot_path = grub_util_get_path (dir, "diskboot.img");
1502 boot_size = grub_util_get_image_size (boot_path);
1503 if (boot_size != GRUB_DISK_SECTOR_SIZE)
1504 grub_util_error (_("diskboot.img size must be %u bytes"),
1505 GRUB_DISK_SECTOR_SIZE);
1506
1507 boot_img = grub_util_read_image (boot_path);
1508
1509 *((grub_uint32_t *) (boot_img + GRUB_DISK_SECTOR_SIZE
1510 - GRUB_BOOT_SPARC64_IEEE1275_LIST_SIZE + 8))
1511 = grub_host_to_target32 (num);
1512
1513 grub_util_write_image (boot_img, boot_size, out, outname);
1514 free (boot_img);
1515 free (boot_path);
1516 }
1517 break;
1518 case IMAGE_SPARC64_CDCORE:
1519 break;
1520 case IMAGE_YEELOONG_FLASH:
1521 case IMAGE_FULOONG2F_FLASH:
1522 {
1523 char *rom_img;
1524 size_t rom_size;
1525 char *boot_path, *boot_img;
1526 size_t boot_size;
1527 grub_uint8_t context[GRUB_MD_SHA512->contextsize];
1528 /* fwstart.img is the only part which can't be tested by using *-elf
1529 target. Check it against the checksum. */
1530 const grub_uint8_t yeeloong_fwstart_good_hash[512 / 8] =
1531 {
1532 0x5f, 0x67, 0x46, 0x57, 0x31, 0x30, 0xc5, 0x0a,
1533 0xe9, 0x98, 0x18, 0xc9, 0xf3, 0xca, 0x45, 0xa5,
1534 0x75, 0x64, 0x6b, 0xbb, 0x24, 0xcd, 0xb4, 0xbc,
1535 0xf2, 0x3e, 0x23, 0xf9, 0xc2, 0x6a, 0x8c, 0xde,
1536 0x3b, 0x94, 0x9c, 0xcc, 0xa5, 0xa7, 0x58, 0xb1,
1537 0xbe, 0x8b, 0x3d, 0x73, 0x98, 0x18, 0x7e, 0x68,
1538 0x5e, 0x5f, 0x23, 0x7d, 0x7a, 0xe8, 0x51, 0xf7,
1539 0x1a, 0xaf, 0x2f, 0x54, 0x11, 0x2e, 0x5c, 0x25
1540 };
1541 const grub_uint8_t fuloong2f_fwstart_good_hash[512 / 8] =
1542 {
1543 0x76, 0x9b, 0xad, 0x6e, 0xa2, 0x39, 0x47, 0x62,
1544 0x1f, 0xc9, 0x3a, 0x6d, 0x05, 0x5c, 0x43, 0x5c,
1545 0x29, 0x4a, 0x7e, 0x08, 0x2a, 0x31, 0x8f, 0x5d,
1546 0x02, 0x84, 0xa0, 0x85, 0xf2, 0xd1, 0xb9, 0x53,
1547 0xa2, 0xbc, 0xf2, 0xe1, 0x39, 0x1e, 0x51, 0xb5,
1548 0xaf, 0xec, 0x9e, 0xf2, 0xf1, 0xf3, 0x0a, 0x2f,
1549 0xe6, 0xf1, 0x08, 0x89, 0xbe, 0xbc, 0x73, 0xab,
1550 0x46, 0x50, 0xd6, 0x21, 0xce, 0x8e, 0x24, 0xa7
1551 };
1552 const grub_uint8_t *fwstart_good_hash;
1553
1554 if (image_target->id == IMAGE_FULOONG2F_FLASH)
1555 {
1556 fwstart_good_hash = fuloong2f_fwstart_good_hash;
1557 boot_path = grub_util_get_path (dir, "fwstart_fuloong2f.img");
1558 }
1559 else
1560 {
1561 fwstart_good_hash = yeeloong_fwstart_good_hash;
1562 boot_path = grub_util_get_path (dir, "fwstart.img");
1563 }
1564
1565 boot_size = grub_util_get_image_size (boot_path);
1566 boot_img = grub_util_read_image (boot_path);
1567
1568 grub_memset (context, 0, sizeof (context));
1569 GRUB_MD_SHA512->init (context);
1570 GRUB_MD_SHA512->write (context, boot_img, boot_size);
1571 GRUB_MD_SHA512->final (context);
1572 if (grub_memcmp (GRUB_MD_SHA512->read (context), fwstart_good_hash,
1573 GRUB_MD_SHA512->mdlen) != 0)
1574 /* TRANSLATORS: fwstart.img may still be good, just it wasn't checked. */
1575 grub_util_warn ("%s",
1576 _("fwstart.img doesn't match the known good version. "
1577 "proceed at your own risk"));
1578
1579 if (core_size + boot_size > 512 * 1024)
1580 grub_util_error ("%s", _("firmware image is too big"));
1581 rom_size = 512 * 1024;
1582
1583 rom_img = xmalloc (rom_size);
1584 memset (rom_img, 0, rom_size);
1585
1586 memcpy (rom_img, boot_img, boot_size);
1587
1588 memcpy (rom_img + boot_size, core_img, core_size);
1589
1590 memset (rom_img + boot_size + core_size, 0,
1591 rom_size - (boot_size + core_size));
1592
1593 free (core_img);
1594 core_img = rom_img;
1595 core_size = rom_size;
1596 }
1597 break;
1598 case IMAGE_QEMU_MIPS_FLASH:
1599 {
1600 char *rom_img;
1601 size_t rom_size;
1602
1603 if (core_size > 512 * 1024)
1604 grub_util_error ("%s", _("firmware image is too big"));
1605 rom_size = 512 * 1024;
1606
1607 rom_img = xmalloc (rom_size);
1608 memset (rom_img, 0, rom_size);
1609
1610 memcpy (rom_img, core_img, core_size);
1611
1612 memset (rom_img + core_size, 0,
1613 rom_size - core_size);
1614
1615 free (core_img);
1616 core_img = rom_img;
1617 core_size = rom_size;
1618 }
1619 break;
1620
1621 case IMAGE_UBOOT:
1622 {
1623 struct grub_uboot_image_header *hdr;
1624 GRUB_PROPERLY_ALIGNED_ARRAY (crc32_context, GRUB_MD_CRC32->contextsize);
1625
1626 hdr = xmalloc (core_size + sizeof (struct grub_uboot_image_header));
1627 memcpy (hdr + 1, core_img, core_size);
1628
1629 memset (hdr, 0, sizeof (*hdr));
1630 hdr->ih_magic = grub_cpu_to_be32_compile_time (GRUB_UBOOT_IH_MAGIC);
1631 hdr->ih_time = grub_cpu_to_be32 (time (0));
1632 hdr->ih_size = grub_cpu_to_be32 (core_size);
1633 hdr->ih_load = grub_cpu_to_be32 (image_target->link_addr);
1634 hdr->ih_ep = grub_cpu_to_be32 (image_target->link_addr);
1635 hdr->ih_type = GRUB_UBOOT_IH_TYPE_KERNEL;
1636 hdr->ih_os = GRUB_UBOOT_IH_OS_LINUX;
1637 hdr->ih_arch = GRUB_UBOOT_IH_ARCH_ARM;
1638 hdr->ih_comp = GRUB_UBOOT_IH_COMP_NONE;
1639
1640 GRUB_MD_CRC32->init(crc32_context);
1641 GRUB_MD_CRC32->write(crc32_context, hdr + 1, core_size);
1642 GRUB_MD_CRC32->final(crc32_context);
1643 hdr->ih_dcrc = grub_get_unaligned32 (GRUB_MD_CRC32->read (crc32_context));
1644
1645 GRUB_MD_CRC32->init(crc32_context);
1646 GRUB_MD_CRC32->write(crc32_context, hdr, sizeof (*hdr));
1647 GRUB_MD_CRC32->final(crc32_context);
1648 hdr->ih_hcrc = grub_get_unaligned32 (GRUB_MD_CRC32->read (crc32_context));
1649
1650 free (core_img);
1651 core_img = (char *) hdr;
1652 core_size += sizeof (struct grub_uboot_image_header);
1653 }
1654 break;
1655
1656 case IMAGE_MIPS_ARC:
1657 {
1658 char *ecoff_img;
1659 struct ecoff_header {
1660 grub_uint16_t magic;
1661 grub_uint16_t nsec;
1662 grub_uint32_t time;
1663 grub_uint32_t syms;
1664 grub_uint32_t nsyms;
1665 grub_uint16_t opt;
1666 grub_uint16_t flags;
1667 grub_uint16_t magic2;
1668 grub_uint16_t version;
1669 grub_uint32_t textsize;
1670 grub_uint32_t datasize;
1671 grub_uint32_t bsssize;
1672 grub_uint32_t entry;
1673 grub_uint32_t text_start;
1674 grub_uint32_t data_start;
1675 grub_uint32_t bss_start;
1676 grub_uint32_t gprmask;
1677 grub_uint32_t cprmask[4];
1678 grub_uint32_t gp_value;
1679 };
1680 struct ecoff_section
1681 {
1682 char name[8];
1683 grub_uint32_t paddr;
1684 grub_uint32_t vaddr;
1685 grub_uint32_t size;
1686 grub_uint32_t file_offset;
1687 grub_uint32_t reloc;
1688 grub_uint32_t gp;
1689 grub_uint16_t nreloc;
1690 grub_uint16_t ngp;
1691 grub_uint32_t flags;
1692 };
1693 struct ecoff_header *head;
1694 struct ecoff_section *section;
1695 grub_uint32_t target_addr;
1696 size_t program_size;
1697
1698 program_size = ALIGN_ADDR (core_size);
1699 if (comp == GRUB_COMPRESSION_NONE)
1700 target_addr = (image_target->link_addr - decompress_size);
1701 else
1702 target_addr = ALIGN_UP (image_target->link_addr
1703 + kernel_size + total_module_size, 32);
1704
1705 ecoff_img = xmalloc (program_size + sizeof (*head) + sizeof (*section));
1706 grub_memset (ecoff_img, 0, program_size + sizeof (*head) + sizeof (*section));
1707 head = (void *) ecoff_img;
1708 section = (void *) (head + 1);
1709 head->magic = image_target->bigendian ? grub_host_to_target16 (0x160)
1710 : grub_host_to_target16 (0x166);
1711 head->nsec = grub_host_to_target16 (1);
1712 head->time = grub_host_to_target32 (0);
1713 head->opt = grub_host_to_target16 (0x38);
1714 head->flags = image_target->bigendian
1715 ? grub_host_to_target16 (0x207)
1716 : grub_host_to_target16 (0x103);
1717 head->magic2 = grub_host_to_target16 (0x107);
1718 head->textsize = grub_host_to_target32 (program_size);
1719 head->entry = grub_host_to_target32 (target_addr);
1720 head->text_start = grub_host_to_target32 (target_addr);
1721 head->data_start = grub_host_to_target32 (target_addr + program_size);
1722 grub_memcpy (section->name, ".text", sizeof (".text") - 1);
1723 section->vaddr = grub_host_to_target32 (target_addr);
1724 section->size = grub_host_to_target32 (program_size);
1725 section->file_offset = grub_host_to_target32 (sizeof (*head) + sizeof (*section));
1726 if (!image_target->bigendian)
1727 {
1728 section->paddr = grub_host_to_target32 (0xaa60);
1729 section->flags = grub_host_to_target32 (0x20);
1730 }
1731 memcpy (section + 1, core_img, core_size);
1732 free (core_img);
1733 core_img = ecoff_img;
1734 core_size = program_size + sizeof (*head) + sizeof (*section);
1735 }
1736 break;
1737 case IMAGE_LOONGSON_ELF:
1738 case IMAGE_PPC:
1739 case IMAGE_XEN:
1740 case IMAGE_COREBOOT:
1741 case IMAGE_I386_IEEE1275:
1742 {
1743 grub_uint64_t target_addr;
1744 if (image_target->id == IMAGE_LOONGSON_ELF)
1745 {
1746 if (comp == GRUB_COMPRESSION_NONE)
1747 target_addr = (image_target->link_addr - decompress_size);
1748 else
1749 target_addr = ALIGN_UP (image_target->link_addr
1750 + kernel_size + total_module_size, 32);
1751 }
1752 else
1753 target_addr = image_target->link_addr;
1754 if (image_target->voidp_sizeof == 4)
1755 generate_elf32 (image_target, note, &core_img, &core_size,
1756 target_addr, align, kernel_size, bss_size);
1757 else
1758 generate_elf64 (image_target, note, &core_img, &core_size,
1759 target_addr, align, kernel_size, bss_size);
1760 }
1761 break;
1762 }
1763
1764 grub_util_write_image (core_img, core_size, out, outname);
1765 free (core_img);
1766 free (kernel_path);
1767
1768 while (path_list)
1769 {
1770 next = path_list->next;
1771 free ((void *) path_list->name);
1772 free (path_list);
1773 path_list = next;
1774 }
1775 }