/* * GRUB -- GRand Unified Bootloader * Copyright (C) 2013 Free Software Foundation, Inc. * * GRUB is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GRUB is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GRUB. If not, see . */ #include #include #include #include #include #include #include #include #include #include static char * get_ofpathname (const char *dev) { size_t alloced = 4096; char *ret = xmalloc (alloced); size_t offset = 0; int fd; pid_t pid; pid = grub_util_exec_pipe ((const char * []){ "ofpathname", dev, NULL }, &fd); if (!pid) goto fail; FILE *fp = fdopen (fd, "r"); if (!fp) goto fail; while (!feof (fp)) { size_t r; if (alloced == offset) { alloced *= 2; ret = xrealloc (ret, alloced); } r = fread (ret + offset, 1, alloced - offset, fp); offset += r; } if (offset > 0 && ret[offset - 1] == '\n') offset--; if (offset > 0 && ret[offset - 1] == '\r') offset--; if (alloced == offset) { alloced++; ret = xrealloc (ret, alloced); } ret[offset] = '\0'; fclose (fp); return ret; fail: grub_util_error (_("couldn't find IEEE1275 device tree path for %s.\nYou will have to set `boot-device' variable manually"), dev); } static void grub_install_remove_efi_entries_by_distributor (const char *efi_distributor) { int fd; pid_t pid = grub_util_exec_pipe ((const char * []){ "efibootmgr", NULL }, &fd); char *line = NULL; size_t len = 0; if (!pid) { grub_util_warn (_("Unable to open stream from %s: %s"), "efibootmgr", strerror (errno)); return; } FILE *fp = fdopen (fd, "r"); if (!fp) { grub_util_warn (_("Unable to open stream from %s: %s"), "efibootmgr", strerror (errno)); return; } line = xmalloc (80); len = 80; while (1) { int ret; char *bootnum; ret = getline (&line, &len, fp); if (ret == -1) break; if (grub_memcmp (line, "Boot", sizeof ("Boot") - 1) != 0 || line[sizeof ("Boot") - 1] < '0' || line[sizeof ("Boot") - 1] > '9') continue; if (!strcasestr (line, efi_distributor)) continue; bootnum = line + sizeof ("Boot") - 1; bootnum[4] = '\0'; if (!verbosity) grub_util_exec ((const char * []){ "efibootmgr", "-q", "-b", bootnum, "-B", NULL }); else grub_util_exec ((const char * []){ "efibootmgr", "-b", bootnum, "-B", NULL }); } free (line); } void grub_install_register_efi (const char *efidir_disk, int efidir_part, const char *efifile_path, const char *efi_distributor) { if (grub_util_exec_redirect_null ((const char * []){ "efibootmgr", "--version", NULL })) { /* TRANSLATORS: This message is shown when required executable `%s' isn't found. */ grub_util_error (_("%s: not found"), "efibootmgr"); } /* On Linux, we need the efivars kernel modules. */ #ifdef __linux__ grub_util_exec ((const char * []){ "modprobe", "-q", "efivars", NULL }); #endif /* Delete old entries from the same distributor. */ grub_install_remove_efi_entries_by_distributor (efi_distributor); char *efidir_part_str = xasprintf ("%d", efidir_part); if (!verbosity) grub_util_exec ((const char * []){ "efibootmgr", "-q", "-c", "-d", efidir_disk, "-p", efidir_part_str, "-w", "-L", efi_distributor, "-l", efifile_path, NULL }); else grub_util_exec ((const char * []){ "efibootmgr", "-c", "-d", efidir_disk, "-p", efidir_part_str, "-w", "-L", efi_distributor, "-l", efifile_path, NULL }); free (efidir_part_str); } void grub_install_register_ieee1275 (int is_prep, const char *install_device, int partno, const char *relpath) { char *boot_device; if (grub_util_exec_redirect_null ((const char * []){ "ofpathname", "--version", NULL })) { /* TRANSLATORS: This message is shown when required executable `%s' isn't found. */ grub_util_error (_("%s: not found"), "ofpathname"); } /* Get the Open Firmware device tree path translation. */ if (!is_prep) { char *ptr; char *ofpath; const char *iptr; ofpath = get_ofpathname (install_device); boot_device = xmalloc (strlen (ofpath) + 1 + sizeof ("XXXXXXXXXXXXXXXXXXXX") + 1 + strlen (relpath) + 1); ptr = grub_stpcpy (boot_device, ofpath); *ptr++ = ':'; grub_snprintf (ptr, sizeof ("XXXXXXXXXXXXXXXXXXXX"), "%d", partno); ptr += strlen (ptr); *ptr++ = ','; for (iptr = relpath; *iptr; iptr++, ptr++) { if (*iptr == '/') *ptr = '\\'; else *ptr = *iptr; } *ptr = '\0'; } else boot_device = get_ofpathname (install_device); if (grub_util_exec ((const char * []){ "nvsetenv", "boot-device", boot_device, NULL })) { char *cmd = xasprintf ("setenv boot-device %s", boot_device); grub_util_error ("`nvsetenv' failed. \nYou will have to set `boot-device' variable manually. At the IEEE1275 prompt, type:\n %s\n", cmd); free (cmd); } free (boot_device); } void grub_install_sgi_setup (const char *install_device, const char *imgfile, const char *destname) { grub_util_exec ((const char * []){ "dvhtool", "-d", install_device, "--unix-to-vh", imgfile, destname, NULL }); grub_util_warn ("%s", _("You will have to set `SystemPartition' and `OSLoader' manually.")); }