238d4840e2f9613c6392e16cb88e7f413cae41c4
[grub.git] / util / grub-mkrescue.c
1 /*
2  *  Make GRUB rescue image
3  *
4  *  GRUB  --  GRand Unified Bootloader
5  *  Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010  Free Software Foundation, Inc.
6  *
7  *  GRUB is free software: you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation, either version 3 of the License, or
10  *  (at your option) any later version.
11  *
12  *  GRUB is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include <config.h>
22
23 #include <grub/util/install.h>
24 #include <grub/util/misc.h>
25 #include <grub/emu/exec.h>
26 #include <grub/emu/config.h>
27 #include <grub/emu/hostdisk.h>
28 #pragma GCC diagnostic ignored "-Wmissing-prototypes"
29 #pragma GCC diagnostic ignored "-Wmissing-declarations"
30 #include <argp.h>
31 #pragma GCC diagnostic error "-Wmissing-prototypes"
32 #pragma GCC diagnostic error "-Wmissing-declarations"
33
34 #include <sys/types.h>
35 #include <sys/wait.h>
36
37 #include <string.h>
38 #include <time.h>
39
40 static char *source_dirs[GRUB_INSTALL_PLATFORM_MAX];
41 static char *rom_directory;
42 static char *label_font;
43 static char *label_color;
44 static char *label_bgcolor;
45 static char *product_name;
46 static char *product_version;
47 static char *output_image;
48 static char *xorriso;
49 static char *boot_grub;
50 static int xorriso_argc;
51 static int xorriso_arg_alloc;
52 static char **xorriso_argv;
53 static char *iso_uuid;
54 static char *iso9660_dir;
55
56 static void
57 xorriso_push (const char *val)
58 {
59   if (xorriso_arg_alloc <= xorriso_argc + 1)
60     {
61       xorriso_arg_alloc = 2 * (4 + xorriso_argc);
62       xorriso_argv = xrealloc (xorriso_argv,
63                                sizeof (xorriso_argv[0])
64                                * xorriso_arg_alloc);
65     }
66   xorriso_argv[xorriso_argc++] = xstrdup (val);
67 }
68
69 static void
70 xorriso_link (const char *from, const char *to)
71 {
72   char *tof = grub_util_path_concat (2, iso9660_dir, to);
73   char *val = xasprintf ("%s=%s", from, tof);
74   xorriso_push (val);
75   free (val);
76   free (tof);
77 }
78
79 enum
80   {
81     OPTION_OUTPUT = 'o',
82     OPTION_ROM_DIRECTORY = 0x301,
83     OPTION_XORRISO,
84     OPTION_GLUE_EFI,
85     OPTION_RENDER_LABEL,
86     OPTION_LABEL_FONT,
87     OPTION_LABEL_COLOR,
88     OPTION_LABEL_BGCOLOR,
89     OPTION_PRODUCT_NAME,
90     OPTION_PRODUCT_VERSION,
91     OPTION_SPARC_BOOT,
92     OPTION_ARCS_BOOT
93   };
94
95 static struct argp_option options[] = {
96   GRUB_INSTALL_OPTIONS,
97   {"output", 'o', N_("FILE"),
98    0, N_("save output in FILE [required]"), 2},
99   {"rom-directory", OPTION_ROM_DIRECTORY, N_("DIR"),
100    0, N_("save ROM images in DIR [optional]"), 2},
101   {"xorriso", OPTION_XORRISO, N_("FILE"),
102    /* TRANSLATORS: xorriso is a program for creating ISOs and burning CDs.  */
103    0, N_("use FILE as xorriso [optional]"), 2},
104   {"grub-glue-efi", OPTION_GLUE_EFI, N_("FILE"), OPTION_HIDDEN, 0, 2},
105   {"grub-render-label", OPTION_RENDER_LABEL, N_("FILE"), OPTION_HIDDEN, 0, 2},
106   {"label-font", OPTION_LABEL_FONT, N_("FILE"), 0, N_("use FILE as font for label"), 2},
107   {"label-color", OPTION_LABEL_COLOR, N_("COLOR"), 0, N_("use COLOR for label"), 2},
108   {"label-bgcolor", OPTION_LABEL_BGCOLOR, N_("COLOR"), 0, N_("use COLOR for label background"), 2},
109   {"product-name", OPTION_PRODUCT_NAME, N_("STRING"), 0, N_("use STRING as product name"), 2},
110   {"product-version", OPTION_PRODUCT_VERSION, N_("STRING"), 0, N_("use STRING as product version"), 2},
111   {"sparc-boot", OPTION_SPARC_BOOT, 0, 0, N_("enable sparc boot. Disables HFS+, APM, ARCS and boot as disk image for i386-pc"), 2},
112   {"arcs-boot", OPTION_ARCS_BOOT, 0, 0, N_("enable ARCS (big-endian mips machines, mostly SGI) boot. Disables HFS+, APM, sparc64 and boot as disk image for i386-pc"), 2},
113   {0, 0, 0, 0, 0, 0}
114 };
115
116 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
117
118 static char *
119 help_filter (int key, const char *text, void *input __attribute__ ((unused)))
120 {
121   switch (key)
122     {
123     case ARGP_KEY_HELP_PRE_DOC:
124       /* TRANSLATORS: it generates one single image which is bootable through any method. */
125       return strdup (_("Make GRUB CD-ROM, disk, pendrive and floppy bootable image."));
126     case ARGP_KEY_HELP_POST_DOC:
127       {
128         char *p1, *out;
129
130         p1 = xasprintf (_("Generates a bootable CD/USB/floppy image.  Arguments other than options to this program"
131       " are passed to xorriso, and indicate source files, source directories, or any of the "
132       "mkisofs options listed by the output of `%s'."), "xorriso -as mkisofs -help");
133         out = xasprintf ("%s\n\n%s\n\n%s", p1,
134           _("Option -- switches to native xorriso command mode."),
135           _("Mail xorriso support requests to <bug-xorriso@gnu.org>."));
136         free (p1);
137         return out;
138       }
139     default:
140       return grub_install_help_filter (key, text, input);
141     }
142 }
143
144 #pragma GCC diagnostic error "-Wformat-nonliteral"
145
146 enum {
147   SYS_AREA_AUTO,
148   SYS_AREA_COMMON,
149   SYS_AREA_SPARC,
150   SYS_AREA_ARCS
151 } system_area = SYS_AREA_AUTO;
152
153 static error_t 
154 argp_parser (int key, char *arg, struct argp_state *state)
155 {
156   if (grub_install_parse (key, arg))
157     return 0;
158   switch (key)
159     {
160     case OPTION_OUTPUT:
161       free (output_image);
162       output_image = xstrdup (arg);
163       return 0;
164     case OPTION_ROM_DIRECTORY:
165       free (rom_directory);
166       rom_directory = xstrdup (arg);
167       return 0;
168
169       /*
170        FIXME:
171     # Intentionally undocumented
172     --grub-mkimage-extra)
173         mkimage_extra_arg="$mkimage_extra_arg `argument $option "$@"`"; shift ;;
174     --grub-mkimage-extra=*)
175         mkimage_extra_arg="$mkimage_extra_arg `echo "$option" | sed 's/--grub-mkimage-extra=//'`" ;;
176       */
177     case OPTION_SPARC_BOOT:
178       system_area = SYS_AREA_SPARC;
179       return 0;
180     case OPTION_ARCS_BOOT:
181       system_area = SYS_AREA_ARCS;
182       return 0;
183     case OPTION_PRODUCT_NAME:
184       free (product_name);
185       product_name = xstrdup (arg);
186       return 0;
187     case OPTION_PRODUCT_VERSION:
188       free (product_version);
189       product_version = xstrdup (arg);
190       return 0;
191       /* Accept and ignore for compatibility.  */
192     case OPTION_GLUE_EFI:
193     case OPTION_RENDER_LABEL:
194       return 0;
195     case OPTION_LABEL_FONT:
196       free (label_font);
197       label_font = xstrdup (arg);
198       return 0;
199
200     case OPTION_LABEL_COLOR:
201       free (label_color);
202       label_color = xstrdup (arg);
203       return 0;
204
205     case OPTION_LABEL_BGCOLOR:
206       free (label_bgcolor);
207       label_bgcolor = xstrdup (arg);
208       return 0;
209
210     case OPTION_XORRISO:
211       free (xorriso);
212       xorriso = xstrdup (arg);
213       return 0;
214
215     default:
216       return ARGP_ERR_UNKNOWN;
217     }
218 }
219
220 struct argp argp = {
221   options, argp_parser, N_("[OPTION] SOURCE..."),
222   NULL, NULL, help_filter, NULL
223 };
224
225 static void
226 write_part (FILE *f, const char *srcdir)
227 {
228   FILE *in;
229   char *inname = grub_util_path_concat (2, srcdir, "partmap.lst");
230   char buf[260];
231   in = grub_util_fopen (inname, "rb");
232   if (!in)
233     return;
234   while (fgets (buf, 256, in))
235     {
236       char *ptr;
237       for (ptr = buf + strlen (buf) - 1;
238            ptr >= buf && (*ptr == '\n' || *ptr == '\r');
239            ptr--);
240       ptr[1] = '\0';
241       fprintf (f, "insmod %s\n", buf);
242     }
243   fclose (in);
244 }
245
246 static void
247 make_image_abs (enum grub_install_plat plat,
248                 const char *mkimage_target,
249                 const char *output)
250 {
251   char *load_cfg;
252   FILE *load_cfg_f;
253
254   if (!source_dirs[plat])
255     return;
256
257   grub_util_info (N_("enabling %s support ..."),
258                   mkimage_target);
259
260   load_cfg = grub_util_make_temporary_file ();
261
262   load_cfg_f = grub_util_fopen (load_cfg, "wb");
263   fprintf (load_cfg_f, "search --fs-uuid --set=root %s\n", iso_uuid);
264   fprintf (load_cfg_f, "set prefix=(${root})/boot/grub\n");
265
266   write_part (load_cfg_f, source_dirs[plat]);
267   fclose (load_cfg_f);
268
269   grub_install_push_module ("search");
270   grub_install_push_module ("iso9660");
271   grub_install_make_image_wrap (source_dirs[plat], "/boot/grub", output,
272                                 0, load_cfg,
273                                 mkimage_target, 0);
274   grub_install_pop_module ();
275   grub_install_pop_module ();
276   grub_util_unlink (load_cfg);
277 }
278
279 static void
280 make_image (enum grub_install_plat plat,
281             const char *mkimage_target,
282             const char *output_sub)
283 {
284   char *out = grub_util_path_concat (2, boot_grub, output_sub);
285   make_image_abs (plat, mkimage_target, out);
286   free (out);
287 }
288
289 static void
290 make_image_fwdisk_abs (enum grub_install_plat plat,
291                        const char *mkimage_target,
292                        const char *output)
293 {
294   char *load_cfg;
295   FILE *load_cfg_f;
296
297   if (!source_dirs[plat])
298     return;
299
300   grub_util_info (N_("enabling %s support ..."),
301                   mkimage_target);
302
303   load_cfg = grub_util_make_temporary_file ();
304
305   load_cfg_f = grub_util_fopen (load_cfg, "wb");
306   write_part (load_cfg_f, source_dirs[plat]);
307   fclose (load_cfg_f);
308
309   grub_install_push_module ("iso9660");
310   grub_install_make_image_wrap (source_dirs[plat], "()/boot/grub", output,
311                                 0, load_cfg, mkimage_target, 0);
312   grub_install_pop_module ();
313   grub_util_unlink (load_cfg);
314 }
315
316 static int
317 check_xorriso (const char *val)
318 {
319   const char *argv[5];
320   int fd;
321   pid_t pid;
322   FILE *mdadm;
323   char *buf = NULL;
324   size_t len = 0;
325   int ret = 0;
326
327   argv[0] = xorriso;
328   argv[1] = "-as";
329   argv[2] = "mkisofs";
330   argv[3] = "-help";
331   argv[4] = NULL;
332
333   pid = grub_util_exec_pipe_stderr (argv, &fd);
334
335   if (!pid)
336     return 0;
337
338   /* Parent.  Read mdadm's output.  */
339   mdadm = fdopen (fd, "r");
340   if (! mdadm)
341     return 0;
342
343   while (getline (&buf, &len, mdadm) > 0)
344     {
345       if (grub_strstr (buf, val))
346         ret = 1;
347     }
348
349   close (fd);
350   waitpid (pid, NULL, 0);
351   free (buf);
352   return ret;
353 }
354
355 static void
356 make_image_fwdisk (enum grub_install_plat plat,
357                    const char *mkimage_target,
358                    const char *output_sub)
359 {
360   char *out = grub_util_path_concat (2, boot_grub, output_sub);
361   make_image_fwdisk_abs (plat, mkimage_target, out);
362   free (out);
363 }
364
365 static int
366 option_is_end (const struct argp_option *opt)
367 {
368   return !opt->key && !opt->name && !opt->doc && !opt->group;
369 }
370
371
372 static int
373 args_to_eat (const char *arg)
374 {
375   int j;
376
377   if (arg[0] != '-')
378     return 0;
379
380   if (arg[1] == '-')
381     {
382       for (j = 0; !option_is_end(&options[j]); j++)
383         {
384           size_t len = strlen (options[j].name);
385           if (strncmp (arg + 2, options[j].name, len) == 0)
386             {
387               if (arg[2 + len] == '=')
388                 return 1;
389               if (arg[2 + len] == '\0' && options[j].arg)
390                 return 2;
391               if (arg[2 + len] == '\0')
392                 return 1;
393             }
394         }
395       if (strcmp (arg, "--help") == 0)
396         return 1;
397       if (strcmp (arg, "--usage") == 0)
398         return 1;
399       if (strcmp (arg, "--version") == 0)
400         return 1;
401       return 0;
402     }
403   if (arg[2] && arg[3])
404     return 0;
405   for (j = 0; !option_is_end(&options[j]); j++)
406     {
407       if (options[j].key > 0 && options[j].key < 128 && arg[1] == options[j].key)
408         {
409           if (options[j].arg)
410             return 2;
411           return 1;
412         }
413       if (arg[1] == '?')
414         return 1;
415     }
416   return 0;
417 }
418
419 int
420 main (int argc, char *argv[])
421 {
422   char *romdir;
423   char *sysarea_img = NULL;
424   const char *pkgdatadir;
425   int argp_argc;
426   char **argp_argv;
427   int xorriso_tail_argc;
428   char **xorriso_tail_argv;
429
430   grub_util_host_init (&argc, &argv);
431   grub_util_disable_fd_syncs ();
432
433   pkgdatadir = grub_util_get_pkgdatadir ();
434
435   product_name = xstrdup (PACKAGE_NAME);
436   product_version = xstrdup (PACKAGE_VERSION);
437   xorriso = xstrdup ("xorriso");
438   label_font = grub_util_path_concat (2, pkgdatadir, "unicode.pf2");
439
440   argp_argv = xmalloc (sizeof (argp_argv[0]) * argc);
441   xorriso_tail_argv = xmalloc (sizeof (argp_argv[0]) * argc);
442
443   xorriso_tail_argc = 0;
444   /* Program name */
445   argp_argv[0] = argv[0];
446   argp_argc = 1;
447
448   /* argp doesn't allow us to catch unknwon arguments,
449      so catch them before passing to argp
450    */
451   {
452     int i;
453     for (i = 1; i < argc; i++)
454       {
455         if (strcmp (argv[i], "-output") == 0) {
456           argp_argv[argp_argc++] = (char *) "--output";
457           i++;
458           argp_argv[argp_argc++] = argv[i];
459           continue;
460         }
461         switch (args_to_eat (argv[i]))
462           {
463           case 2:
464             argp_argv[argp_argc++] = argv[i++];
465             /* Fallthrough  */
466           case 1:
467             argp_argv[argp_argc++] = argv[i];
468             break;
469           case 0:
470             xorriso_tail_argv[xorriso_tail_argc++] = argv[i];
471             break;
472           }
473       }
474   }
475
476   argp_parse (&argp, argp_argc, argp_argv, 0, 0, 0);
477
478   if (!output_image)
479     grub_util_error ("%s", _("output file must be specified"));
480
481   grub_init_all ();
482   grub_hostfs_init ();
483   grub_host_init ();
484
485   xorriso_push (xorriso);
486   xorriso_push ("-as");
487   xorriso_push ("mkisofs");
488   xorriso_push ("-graft-points");
489   
490   iso9660_dir = grub_util_make_temporary_dir ();
491   grub_util_info ("temporary iso9660 dir is `%s'", iso9660_dir);
492   boot_grub = grub_util_path_concat (3, iso9660_dir, "boot", "grub");
493   grub_install_mkdir_p (boot_grub);
494   romdir = grub_util_path_concat (2, boot_grub, "roms");
495   grub_util_mkdir (romdir);
496
497   if (!grub_install_source_directory)
498     {
499       const char *pkglibdir = grub_util_get_pkglibdir ();
500       enum grub_install_plat plat;
501
502       for (plat = 0; plat < GRUB_INSTALL_PLATFORM_MAX; plat++)
503         {
504           char *platdir = grub_util_path_concat (2, pkglibdir,
505                                                  grub_install_get_platform_name (plat));
506
507           if (!grub_util_is_directory (platdir))
508             {
509               free (platdir);
510               continue;
511             }
512           source_dirs[plat] = platdir;
513           grub_install_copy_files (platdir,
514                                    boot_grub, plat);
515         }
516     }
517   else
518     {
519       enum grub_install_plat plat;
520       plat = grub_install_get_target (grub_install_source_directory);
521       grub_install_copy_files (grub_install_source_directory,
522                                boot_grub, plat);
523       source_dirs[plat] = xstrdup (grub_install_source_directory);
524     }
525   if (system_area == SYS_AREA_AUTO || grub_install_source_directory)
526     {
527       if (source_dirs[GRUB_INSTALL_PLATFORM_I386_PC]
528           || source_dirs[GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275]
529           || source_dirs[GRUB_INSTALL_PLATFORM_I386_EFI]
530           || source_dirs[GRUB_INSTALL_PLATFORM_IA64_EFI]
531           || source_dirs[GRUB_INSTALL_PLATFORM_ARM_EFI]
532           || source_dirs[GRUB_INSTALL_PLATFORM_ARM64_EFI]
533           || source_dirs[GRUB_INSTALL_PLATFORM_X86_64_EFI])
534         system_area = SYS_AREA_COMMON;
535       else if (source_dirs[GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275])
536         system_area = SYS_AREA_SPARC;
537       else if (source_dirs[GRUB_INSTALL_PLATFORM_MIPS_ARC])
538         system_area = SYS_AREA_ARCS;
539     }
540
541   /* obtain date-based UUID.  */
542   {
543     time_t tim;
544     struct tm *tmm;
545     tim = time (NULL);
546     tmm = gmtime (&tim);
547     iso_uuid = xmalloc (55);
548     grub_snprintf (iso_uuid, 50,
549                    "%04d-%02d-%02d-%02d-%02d-%02d-00",
550                    tmm->tm_year + 1900,
551                    tmm->tm_mon + 1,
552                    tmm->tm_mday,
553                    tmm->tm_hour,
554                    tmm->tm_min,
555                    tmm->tm_sec);
556   }
557   {
558     char *uuid_out = xmalloc (strlen (iso_uuid) + 1 + 40);
559     char *optr;
560     const char *iptr;
561     optr = grub_stpcpy (uuid_out, "--modification-date=");
562     for (iptr = iso_uuid; *iptr; iptr++)
563       if (*iptr != '-')
564         *optr++ = *iptr;
565     *optr = '\0';
566     xorriso_push (uuid_out);
567     free (uuid_out);
568   }
569
570   /* build BIOS core.img.  */
571   if (source_dirs[GRUB_INSTALL_PLATFORM_I386_PC])
572     {
573       char *load_cfg;
574       FILE *load_cfg_f;
575       char *output = grub_util_path_concat (3, boot_grub, "i386-pc", "eltorito.img");
576       load_cfg = grub_util_make_temporary_file ();
577
578       grub_util_info (N_("enabling %s support ..."), "BIOS");
579       load_cfg_f = grub_util_fopen (load_cfg, "wb");
580       write_part (load_cfg_f, source_dirs[GRUB_INSTALL_PLATFORM_I386_PC]);
581       fclose (load_cfg_f);
582
583       grub_install_push_module ("biosdisk");
584       grub_install_push_module ("iso9660");
585       grub_install_make_image_wrap (source_dirs[GRUB_INSTALL_PLATFORM_I386_PC],
586                                     "/boot/grub", output,
587                                     0, load_cfg,
588                                     "i386-pc-eltorito", 0);
589
590       xorriso_push ("-b");
591       xorriso_push ("boot/grub/i386-pc/eltorito.img");
592       xorriso_push ("-no-emul-boot");
593       xorriso_push ("-boot-load-size");
594       xorriso_push ("4");
595       xorriso_push ("-boot-info-table");
596       if (system_area == SYS_AREA_COMMON)
597         {
598           if (check_xorriso ("grub2-boot-info"))
599             {
600               char *boot_hybrid = grub_util_path_concat (2, source_dirs[GRUB_INSTALL_PLATFORM_I386_PC],
601                                                          "boot_hybrid.img");
602               xorriso_push ("--grub2-boot-info");
603               xorriso_push ("--grub2-mbr");
604               xorriso_push (boot_hybrid);
605             }
606           else
607             {
608               FILE *sa, *bi;
609               size_t sz;
610               char buf[512];
611               char *bin = grub_util_path_concat (2, source_dirs[GRUB_INSTALL_PLATFORM_I386_PC],
612                                                  "boot.img");
613               grub_util_warn ("%s", _("Your xorriso doesn't support `--grub2-boot-info'. Some features are disabled. Please use xorriso 1.2.9 or later."));
614               sysarea_img = grub_util_make_temporary_file ();
615               sa = grub_util_fopen (sysarea_img, "wb");
616               if (!sa)
617                 grub_util_error (_("cannot open `%s': %s"), sysarea_img,
618                                  strerror (errno));
619               bi = grub_util_fopen (bin, "rb");
620               if (!bi)
621                 grub_util_error (_("cannot open `%s': %s"), bin,
622                                  strerror (errno));
623               if (fread (buf, 1, 512, bi) != 512)
624                 grub_util_error (_("cannot read `%s': %s"), bin,
625                                  strerror (errno));
626               fclose (bi);
627               fwrite (buf, 1, 512, sa);
628               
629               grub_install_make_image_wrap_file (source_dirs[GRUB_INSTALL_PLATFORM_I386_PC],
630                                                  "/boot/grub", sa, sysarea_img,
631                                                  0, load_cfg,
632                                                  "i386-pc", 0);
633               sz = ftello (sa);
634               fflush (sa);
635               grub_util_fd_sync (fileno (sa));
636               fclose (sa);
637               
638               if (sz > 32768)
639                 {
640                   grub_util_warn ("%s", _("Your xorriso doesn't support `--grub2-boot-info'. Your core image is too big. Boot as disk is disabled. Please use xorriso 1.2.9 or later."));
641                 }
642               else
643                 {
644                   xorriso_push ("-G");
645                   xorriso_push (sysarea_img);
646                 }
647             }
648         }
649       grub_install_pop_module ();
650       grub_install_pop_module ();
651       grub_util_unlink (load_cfg);
652     }
653
654   /** build multiboot core.img */
655   grub_install_push_module ("pata");
656   grub_install_push_module ("ahci");
657   grub_install_push_module ("at_keyboard");
658   make_image (GRUB_INSTALL_PLATFORM_I386_MULTIBOOT, "i386-multiboot", "i386-multiboot/core.elf");
659   grub_install_pop_module ();
660   grub_install_pop_module ();
661   grub_install_pop_module ();
662
663   make_image_fwdisk (GRUB_INSTALL_PLATFORM_I386_IEEE1275, "i386-ieee1275", "ofwx86.elf");
664
665   char *core_services = NULL;
666
667   if (source_dirs[GRUB_INSTALL_PLATFORM_I386_EFI]
668       || source_dirs[GRUB_INSTALL_PLATFORM_X86_64_EFI]
669       || source_dirs[GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275])
670     {
671       char *mach_ker, *sv, *label, *label_text;
672       FILE *f;
673       core_services = grub_util_path_concat (4, iso9660_dir, "System", "Library", "CoreServices");
674       grub_install_mkdir_p (core_services);
675
676       mach_ker = grub_util_path_concat (2, iso9660_dir, "mach_kernel");
677       f = grub_util_fopen (mach_ker, "wb");
678       fclose (f);
679       free (mach_ker);
680
681       sv = grub_util_path_concat (2, core_services, "SystemVersion.plist");
682       f = grub_util_fopen (sv, "wb");
683       fprintf (f, "<plist version=\"1.0\">\n"
684                "<dict>\n"
685                "        <key>ProductBuildVersion</key>\n"
686                "        <string></string>\n"
687                "        <key>ProductName</key>\n"
688                "        <string>%s</string>\n"
689                "        <key>ProductVersion</key>\n"
690                "        <string>%s</string>\n"
691                "</dict>\n"
692                "</plist>\n", product_name, product_version);
693       fclose (f);
694       free (sv);
695       label = grub_util_path_concat (2, core_services, ".disk_label");
696       char *label_string = xasprintf ("%s %s", product_name, product_version);
697       grub_util_render_label (label_font, label_bgcolor ? : "white",
698                               label_color ? : "black", label_string, label);
699       free (label);
700       label_text = grub_util_path_concat (2, core_services, ".disk_label.contentDetails");
701       f = grub_util_fopen (label_text, "wb");
702       fprintf (f, "%s\n", label_string);
703       fclose (f);
704       free (label_string);
705       free (label_text);
706       if (system_area == SYS_AREA_COMMON)
707         {
708           xorriso_push ("-hfsplus");
709           xorriso_push ("-apm-block-size");
710           xorriso_push ("2048");
711           xorriso_push ("-hfsplus-file-creator-type");
712           xorriso_push ("chrp");
713           xorriso_push ("tbxj");
714           xorriso_push ("/System/Library/CoreServices/.disk_label");
715
716           if (source_dirs[GRUB_INSTALL_PLATFORM_I386_EFI]
717               || source_dirs[GRUB_INSTALL_PLATFORM_X86_64_EFI])
718             {
719               xorriso_push ("-hfs-bless-by");
720               xorriso_push ("i");
721               xorriso_push ("/System/Library/CoreServices/boot.efi");
722             }
723         }
724     }
725
726   if (source_dirs[GRUB_INSTALL_PLATFORM_I386_EFI]
727       || source_dirs[GRUB_INSTALL_PLATFORM_X86_64_EFI]
728       || source_dirs[GRUB_INSTALL_PLATFORM_IA64_EFI]
729       || source_dirs[GRUB_INSTALL_PLATFORM_ARM_EFI]
730       || source_dirs[GRUB_INSTALL_PLATFORM_ARM64_EFI])
731     {
732       char *efidir = grub_util_make_temporary_dir ();
733       char *efidir_efi = grub_util_path_concat (2, efidir, "efi");
734       char *efidir_efi_boot = grub_util_path_concat (3, efidir, "efi", "boot");
735       char *imgname, *img32, *img64, *img_mac = NULL;
736       char *efiimgfat;
737       grub_install_mkdir_p (efidir_efi_boot);
738
739       grub_install_push_module ("part_gpt");
740       grub_install_push_module ("part_msdos");
741
742       imgname = grub_util_path_concat (2, efidir_efi_boot, "bootia64.efi");
743       make_image_fwdisk_abs (GRUB_INSTALL_PLATFORM_IA64_EFI, "ia64-efi", imgname);
744       free (imgname);
745
746       grub_install_push_module ("part_apple");
747       img64 = grub_util_path_concat (2, efidir_efi_boot, "bootx64.efi");
748       make_image_fwdisk_abs (GRUB_INSTALL_PLATFORM_X86_64_EFI, "x86_64-efi", img64);
749       grub_install_pop_module ();
750
751       grub_install_push_module ("part_apple");
752       img32 = grub_util_path_concat (2, efidir_efi_boot, "bootia32.efi");
753       make_image_fwdisk_abs (GRUB_INSTALL_PLATFORM_I386_EFI, "i386-efi", img32);
754       grub_install_pop_module ();
755
756       imgname = grub_util_path_concat (2, efidir_efi_boot, "bootarm.efi");
757       make_image_fwdisk_abs (GRUB_INSTALL_PLATFORM_ARM_EFI, "arm-efi", imgname);
758       free (imgname);
759
760       imgname = grub_util_path_concat (2, efidir_efi_boot, "bootaa64.efi");
761       make_image_fwdisk_abs (GRUB_INSTALL_PLATFORM_ARM64_EFI, "arm64-efi",
762                              imgname);
763       free (imgname);
764
765       if (source_dirs[GRUB_INSTALL_PLATFORM_I386_EFI])
766         {
767           imgname = grub_util_path_concat (2, efidir_efi_boot, "boot.efi");
768           /* For old macs. Suggested by Peter Jones.  */
769           grub_install_copy_file (img32, imgname, 1);
770         }
771
772       if (source_dirs[GRUB_INSTALL_PLATFORM_I386_EFI]
773           || source_dirs[GRUB_INSTALL_PLATFORM_X86_64_EFI])
774         img_mac = grub_util_path_concat (2, core_services, "boot.efi");
775
776       if (source_dirs[GRUB_INSTALL_PLATFORM_I386_EFI]
777           && source_dirs[GRUB_INSTALL_PLATFORM_X86_64_EFI])
778         grub_util_glue_efi (img32, img64, img_mac);
779       else if (source_dirs[GRUB_INSTALL_PLATFORM_X86_64_EFI])
780         grub_install_copy_file (img64, img_mac, 1);
781       else if (source_dirs[GRUB_INSTALL_PLATFORM_I386_EFI])
782         grub_install_copy_file (img32, img_mac, 1);
783
784       free (img_mac);
785       free (img32);
786       free (img64);
787       free (efidir_efi_boot);
788
789       efiimgfat = grub_util_path_concat (2, iso9660_dir, "efi.img");
790       int rv;
791       rv = grub_util_exec ((const char * []) { "mformat", "-C", "-f", "2880", "-L", "16", "-i",
792             efiimgfat, "::", NULL });
793       if (rv != 0)
794         grub_util_error ("`%s` invocation failed\n", "mformat");
795       rv = grub_util_exec ((const char * []) { "mcopy", "-s", "-i", efiimgfat, efidir_efi, "::/", NULL });
796       if (rv != 0)
797         grub_util_error ("`%s` invocation failed\n", "mformat");
798       xorriso_push ("--efi-boot");
799       xorriso_push ("efi.img");
800       xorriso_push ("-efi-boot-part");
801       xorriso_push ("--efi-boot-image");
802
803       grub_util_unlink_recursive (efidir);
804       free (efiimgfat);
805       free (efidir_efi);
806       free (efidir);
807       grub_install_pop_module ();
808       grub_install_pop_module ();
809     }
810
811   grub_install_push_module ("part_apple");
812   make_image_fwdisk (GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275, "powerpc-ieee1275", "powerpc-ieee1275/core.elf");
813   grub_install_pop_module ();
814
815   if (source_dirs[GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275])
816     {
817       char *grub_chrp = grub_util_path_concat (2, source_dirs[GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275],
818                                                "grub.chrp");
819       char *bisrc = grub_util_path_concat (2, source_dirs[GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275],
820                                            "bootinfo.txt");
821       char *bootx = grub_util_path_concat (2, core_services, "BootX");
822       char *ppc_chrp = grub_util_path_concat (3, iso9660_dir, "ppc", "chrp");
823       char *bitgt = grub_util_path_concat (3, iso9660_dir, "ppc", "bootinfo.txt");
824       grub_install_copy_file (grub_chrp, bootx, 1);
825       grub_install_mkdir_p (ppc_chrp);
826       grub_install_copy_file (bisrc, bitgt, 1);
827       xorriso_link ("/System/Library/CoreServices/grub.elf", "/boot/grub/powerpc-ieee1275/core.elf");
828       xorriso_link ("/boot/grub/powerpc.elf", "/boot/grub/powerpc-ieee1275/core.elf");
829       /* FIXME: add PreP */
830       if (system_area == SYS_AREA_COMMON)
831         {
832           xorriso_push ("-hfsplus-file-creator-type");
833           xorriso_push ("chrp");
834           xorriso_push ("tbxi");
835           xorriso_push ("/System/Library/CoreServices/BootX");
836           xorriso_push ("-hfs-bless-by");
837           xorriso_push ("p");
838           xorriso_push ("/System/Library/CoreServices");
839         }
840       xorriso_push ("-sysid");
841       xorriso_push ("PPC");
842     }
843
844   make_image_fwdisk (GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275,
845                      "sparc64-ieee1275-cdcore", "sparc64-ieee1275/core.img");
846
847   if (source_dirs[GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275]
848       && system_area == SYS_AREA_SPARC)
849     {
850       char *cdboot;
851       FILE *in, *out;
852       char buf[512];
853       sysarea_img = grub_util_make_temporary_file ();
854       cdboot = grub_util_path_concat (2, source_dirs[GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275],
855                                       "cdboot.img");
856       in = grub_util_fopen (cdboot, "rb");
857       if (!in)
858         grub_util_error (_("cannot open `%s': %s"), cdboot,
859                          strerror (errno));
860       out = grub_util_fopen (sysarea_img, "wb");
861       if (!out)
862         grub_util_error (_("cannot open `%s': %s"), sysarea_img,
863                          strerror (errno));
864       memset (buf, 0, 512);
865       fwrite (buf, 1, 512, out);
866       if (fread (buf, 1, 512, in) != 512)
867         grub_util_error (_("cannot read `%s': %s"), cdboot,
868                          strerror (errno));
869       fwrite (buf, 1, 512, out);
870       fclose (in);
871       fclose (out);
872       xorriso_push ("-G");
873       xorriso_push (sysarea_img);
874       xorriso_push ("-B");
875       xorriso_push (",");
876       xorriso_push ("--grub2-sparc-core");
877       xorriso_push ("/boot/grub/sparc64-ieee1275/core.img");
878     }
879
880   make_image_fwdisk (GRUB_INSTALL_PLATFORM_MIPS_ARC, "mips-arc", "mips-arc/core.img");
881
882   if (source_dirs[GRUB_INSTALL_PLATFORM_MIPS_ARC])
883     {
884       xorriso_link ("/boot/grub/mips-arc/grub", "/boot/grub/mips-arc/core.img");
885       xorriso_link ("/boot/grub/mips-arc/sashARCS", "/boot/grub/mips-arc/core.img");
886       xorriso_link ("/boot/grub/mips-arc/sash", "/boot/grub/mips-arc/core.img");
887     }
888   if (source_dirs[GRUB_INSTALL_PLATFORM_MIPS_ARC] && system_area == SYS_AREA_ARCS)
889     {
890       xorriso_push ("-mips-boot");
891       xorriso_push ("/boot/grub/mips-arc/sashARCS");
892       xorriso_push ("-mips-boot");
893       xorriso_push ("/boot/grub/mips-arc/sash");
894       xorriso_push ("-mips-boot");
895       xorriso_push ("/boot/grub/mips-arc/grub");
896     }
897
898   make_image_fwdisk (GRUB_INSTALL_PLATFORM_MIPSEL_ARC, "mipsel-arc", "arc.exe");
899
900   grub_install_push_module ("pata");
901   make_image (GRUB_INSTALL_PLATFORM_MIPSEL_QEMU_MIPS, "mipsel-qemu_mips-elf", "roms/mipsel-qemu_mips.elf");
902
903   make_image (GRUB_INSTALL_PLATFORM_MIPSEL_LOONGSON, "mipsel-loongson-elf", "loongson.elf");
904
905   make_image (GRUB_INSTALL_PLATFORM_MIPSEL_LOONGSON, "mipsel-yeeloong-flash", "mipsel-yeeloong.bin");
906   make_image (GRUB_INSTALL_PLATFORM_MIPSEL_LOONGSON, "mipsel-fuloong2f-flash", "mipsel-fuloong2f.bin");
907
908   make_image (GRUB_INSTALL_PLATFORM_MIPS_QEMU_MIPS, "mips-qemu_mips-elf", "roms/mips-qemu_mips.elf");
909
910   grub_install_push_module ("at_keyboard");
911
912   make_image (GRUB_INSTALL_PLATFORM_I386_QEMU, "i386-qemu", "roms/qemu.img");
913
914   grub_install_push_module ("ahci");
915
916   make_image (GRUB_INSTALL_PLATFORM_I386_COREBOOT, "i386-coreboot", "roms/coreboot.elf");
917   grub_install_pop_module ();
918   grub_install_pop_module ();
919   grub_install_pop_module ();
920
921   if (rom_directory)
922     {
923       const struct
924       {
925         enum grub_install_plat plat;
926         const char *from, *to;
927       } roms[] =
928           {
929             {GRUB_INSTALL_PLATFORM_MIPSEL_QEMU_MIPS, "roms/mipsel-qemu_mips.elf", "mipsel-qemu_mips.elf"},
930             {GRUB_INSTALL_PLATFORM_MIPSEL_LOONGSON, "loongson.elf", "mipsel-loongson.elf"},
931             {GRUB_INSTALL_PLATFORM_MIPSEL_LOONGSON, "roms/mipsel-yeeloong.bin", "mipsel-yeeloong.bin"},
932             {GRUB_INSTALL_PLATFORM_MIPSEL_LOONGSON, "roms/mipsel-fulong.bin", "mipsel-fulong.bin"},
933             {GRUB_INSTALL_PLATFORM_MIPS_QEMU_MIPS, "roms/mips-qemu_mips.elf", "mips-qemu_mips.elf"},
934             {GRUB_INSTALL_PLATFORM_I386_QEMU, "roms/qemu.img", "qemu.img"},
935             {GRUB_INSTALL_PLATFORM_I386_COREBOOT, "roms/coreboot.elf", "coreboot.elf"},
936           };
937       grub_size_t i;
938       for (i = 0; i < ARRAY_SIZE (roms); i++)
939         {
940           char *from = grub_util_path_concat (2, boot_grub, roms[i].from);
941           char *to = grub_util_path_concat (2, rom_directory, roms[i].to);
942           grub_install_copy_file (from, to, 0);
943         }
944     }
945
946   xorriso_push ("--protective-msdos-label");
947   xorriso_push ("-o");
948   xorriso_push (output_image);
949   xorriso_push ("-r");
950   xorriso_push (iso9660_dir);
951   xorriso_push ("--sort-weight");
952   xorriso_push ("0");
953   xorriso_push ("/");
954   xorriso_push ("--sort-weight");
955   xorriso_push ("1");
956   xorriso_push ("/boot");
957   int i;
958   for (i = 0; i < xorriso_tail_argc; i++)
959     xorriso_push (xorriso_tail_argv[i]);
960
961   xorriso_argv[xorriso_argc] = NULL;
962
963   grub_util_exec ((const char *const *)xorriso_argv);
964
965   grub_util_unlink_recursive (iso9660_dir);
966
967   if (sysarea_img)
968     grub_util_unlink (sysarea_img);
969
970   free (core_services);
971   free (romdir);
972   return 0;
973 }