grub-mkrescue.c 32 KB

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