platform.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. /*
  2. * GRUB -- GRand Unified Bootloader
  3. * Copyright (C) 2013 Free Software Foundation, Inc.
  4. *
  5. * GRUB is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * GRUB is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include <config.h>
  19. #include <grub/util/install.h>
  20. #include <grub/emu/hostdisk.h>
  21. #include <grub/util/misc.h>
  22. #include <grub/misc.h>
  23. #include <grub/i18n.h>
  24. #include <grub/emu/exec.h>
  25. #include <sys/types.h>
  26. #include <dirent.h>
  27. #include <string.h>
  28. #include <errno.h>
  29. static char *
  30. get_ofpathname (const char *dev)
  31. {
  32. size_t alloced = 4096;
  33. char *ret = xmalloc (alloced);
  34. size_t offset = 0;
  35. int fd;
  36. pid_t pid;
  37. pid = grub_util_exec_pipe ((const char * []){ "ofpathname", dev, NULL }, &fd);
  38. if (!pid)
  39. goto fail;
  40. FILE *fp = fdopen (fd, "r");
  41. if (!fp)
  42. goto fail;
  43. while (!feof (fp))
  44. {
  45. size_t r;
  46. if (alloced == offset)
  47. {
  48. alloced *= 2;
  49. ret = xrealloc (ret, alloced);
  50. }
  51. r = fread (ret + offset, 1, alloced - offset, fp);
  52. offset += r;
  53. }
  54. if (offset > 0 && ret[offset - 1] == '\n')
  55. offset--;
  56. if (offset > 0 && ret[offset - 1] == '\r')
  57. offset--;
  58. if (alloced == offset)
  59. {
  60. alloced++;
  61. ret = xrealloc (ret, alloced);
  62. }
  63. ret[offset] = '\0';
  64. fclose (fp);
  65. return ret;
  66. fail:
  67. grub_util_error (_("couldn't find IEEE1275 device path for %s.\nYou will have to set `boot-device' variable manually"),
  68. dev);
  69. }
  70. static int
  71. grub_install_remove_efi_entries_by_distributor (const char *efi_distributor)
  72. {
  73. int fd;
  74. pid_t pid = grub_util_exec_pipe ((const char * []){ "efibootmgr", NULL }, &fd);
  75. char *line = NULL;
  76. size_t len = 0;
  77. int rc = 0;
  78. if (!pid)
  79. {
  80. grub_util_warn (_("Unable to open stream from %s: %s"),
  81. "efibootmgr", strerror (errno));
  82. return errno;
  83. }
  84. FILE *fp = fdopen (fd, "r");
  85. if (!fp)
  86. {
  87. grub_util_warn (_("Unable to open stream from %s: %s"),
  88. "efibootmgr", strerror (errno));
  89. return errno;
  90. }
  91. line = xmalloc (80);
  92. len = 80;
  93. while (1)
  94. {
  95. int ret;
  96. char *bootnum;
  97. ret = getline (&line, &len, fp);
  98. if (ret == -1)
  99. break;
  100. if (grub_memcmp (line, "Boot", sizeof ("Boot") - 1) != 0
  101. || line[sizeof ("Boot") - 1] < '0'
  102. || line[sizeof ("Boot") - 1] > '9')
  103. continue;
  104. if (!strcasestr (line, efi_distributor))
  105. continue;
  106. bootnum = line + sizeof ("Boot") - 1;
  107. bootnum[4] = '\0';
  108. if (!verbosity)
  109. rc = grub_util_exec ((const char * []){ "efibootmgr", "-q",
  110. "-b", bootnum, "-B", NULL });
  111. else
  112. rc = grub_util_exec ((const char * []){ "efibootmgr",
  113. "-b", bootnum, "-B", NULL });
  114. }
  115. free (line);
  116. return rc;
  117. }
  118. int
  119. grub_install_register_efi (grub_device_t efidir_grub_dev,
  120. const char *efifile_path,
  121. const char *efi_distributor)
  122. {
  123. const char * efidir_disk;
  124. int efidir_part;
  125. int ret;
  126. efidir_disk = grub_util_biosdisk_get_osdev (efidir_grub_dev->disk);
  127. efidir_part = efidir_grub_dev->disk->partition ? efidir_grub_dev->disk->partition->number + 1 : 1;
  128. if (grub_util_exec_redirect_null ((const char * []){ "efibootmgr", "--version", NULL }))
  129. {
  130. /* TRANSLATORS: This message is shown when required executable `%s'
  131. isn't found. */
  132. grub_util_error (_("%s: not found"), "efibootmgr");
  133. }
  134. /* On Linux, we need the efivars kernel modules. */
  135. #ifdef __linux__
  136. grub_util_exec ((const char * []){ "modprobe", "-q", "efivars", NULL });
  137. #endif
  138. /* Delete old entries from the same distributor. */
  139. ret = grub_install_remove_efi_entries_by_distributor (efi_distributor);
  140. if (ret)
  141. return ret;
  142. char *efidir_part_str = xasprintf ("%d", efidir_part);
  143. if (!verbosity)
  144. ret = grub_util_exec ((const char * []){ "efibootmgr", "-q",
  145. "-c", "-d", efidir_disk,
  146. "-p", efidir_part_str, "-w",
  147. "-L", efi_distributor, "-l",
  148. efifile_path, NULL });
  149. else
  150. ret = grub_util_exec ((const char * []){ "efibootmgr",
  151. "-c", "-d", efidir_disk,
  152. "-p", efidir_part_str, "-w",
  153. "-L", efi_distributor, "-l",
  154. efifile_path, NULL });
  155. free (efidir_part_str);
  156. return ret;
  157. }
  158. void
  159. grub_install_register_ieee1275 (int is_prep, const char *install_device,
  160. int partno, const char *relpath)
  161. {
  162. char *boot_device;
  163. if (grub_util_exec_redirect_null ((const char * []){ "ofpathname", "--version", NULL }))
  164. {
  165. /* TRANSLATORS: This message is shown when required executable `%s'
  166. isn't found. */
  167. grub_util_error (_("%s: not found"), "ofpathname");
  168. }
  169. /* Get the Open Firmware device tree path translation. */
  170. if (!is_prep)
  171. {
  172. char *ptr;
  173. char *ofpath;
  174. const char *iptr;
  175. ofpath = get_ofpathname (install_device);
  176. boot_device = xmalloc (strlen (ofpath) + 1
  177. + sizeof ("XXXXXXXXXXXXXXXXXXXX")
  178. + 1 + strlen (relpath) + 1);
  179. ptr = grub_stpcpy (boot_device, ofpath);
  180. *ptr++ = ':';
  181. grub_snprintf (ptr, sizeof ("XXXXXXXXXXXXXXXXXXXX"), "%d",
  182. partno);
  183. ptr += strlen (ptr);
  184. *ptr++ = ',';
  185. for (iptr = relpath; *iptr; iptr++, ptr++)
  186. {
  187. if (*iptr == '/')
  188. *ptr = '\\';
  189. else
  190. *ptr = *iptr;
  191. }
  192. *ptr = '\0';
  193. }
  194. else
  195. boot_device = get_ofpathname (install_device);
  196. if (grub_util_exec ((const char * []){ "nvsetenv", "boot-device",
  197. boot_device, NULL }))
  198. {
  199. char *cmd = xasprintf ("setenv boot-device %s", boot_device);
  200. grub_util_error (_("`nvsetenv' failed. \nYou will have to set `boot-device' variable manually. At the IEEE1275 prompt, type:\n %s\n"),
  201. cmd);
  202. free (cmd);
  203. }
  204. free (boot_device);
  205. }
  206. void
  207. grub_install_sgi_setup (const char *install_device,
  208. const char *imgfile, const char *destname)
  209. {
  210. grub_util_exec ((const char * []){ "dvhtool", "-d",
  211. install_device, "--unix-to-vh",
  212. imgfile, destname, NULL });
  213. grub_util_warn ("%s", _("You will have to set `SystemPartition' and `OSLoader' manually."));
  214. }