/* Return a new heap-allocated string representing to absolute path to the file referred to by PATH. If PATH is an absolute path, then the returned path is a copy of PATH. If PATH is a relative path, then BASE is with PATH used to construct the absolute path. */ char * grub_resolve_relative_path (const char *base, const char *path) { char *abspath; char *canonpath; char *p; grub_size_t l; /* If PATH is an absolute path, then just use it as is. */ if (path[0] == '/' || path[0] == '(') return canonicalize_path (path); abspath = grub_malloc (grub_strlen (base) + grub_strlen (path) + 3); if (! abspath) return 0; /* Concatenate BASE and PATH. */ p = grub_stpcpy (abspath, base); l = grub_strlen (abspath); if (l == 0 || abspath[l-1] != '/') { *p = '/'; p++; *p = 0; } grub_stpcpy (p, path); canonpath = canonicalize_path (abspath); if (! canonpath) return abspath; grub_free (abspath); return canonpath; }
static struct ofdisk_hash_ent * ofdisk_hash_add_real (char *devpath) { struct ofdisk_hash_ent *p; struct ofdisk_hash_ent **head = &ofdisk_hash[ofdisk_hash_fn(devpath)]; const char *iptr; char *optr; p = grub_zalloc (sizeof (*p)); if (!p) return NULL; p->devpath = devpath; p->grub_devpath = grub_malloc (sizeof ("ieee1275/") + 2 * grub_strlen (p->devpath)); if (!p->grub_devpath) { grub_free (p); return NULL; } if (! grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_PARTITION_0)) { p->open_path = grub_malloc (grub_strlen (p->devpath) + 3); if (!p->open_path) { grub_free (p->grub_devpath); grub_free (p); return NULL; } optr = grub_stpcpy (p->open_path, p->devpath); *optr++ = ':'; *optr++ = '0'; *optr = '\0'; } else p->open_path = p->devpath; optr = grub_stpcpy (p->grub_devpath, "ieee1275/"); for (iptr = p->devpath; *iptr; ) { if (*iptr == ',') *optr++ = '\\'; *optr++ = *iptr++; } *optr = 0; p->next = *head; *head = p; return p; }
int putvar (const char *str, grub_size_t len) { const char *var; grub_size_t i; for (i = 0; i < nallowed_strings; i++) if (grub_strncmp (allowed_strings[i], str, len) == 0 && allowed_strings[i][len] == 0) { break; } if (i == nallowed_strings) return 0; /* Enough for any number. */ if (len == 1 && str[0] == '#') { grub_snprintf (ptr, 30, "%u", scope->argv.argc); ptr += grub_strlen (ptr); return 0; } var = grub_env_get (allowed_strings[i]); if (var) ptr = grub_stpcpy (ptr, var); return 0; }
grub_err_t grub_multiboot_init_mbi (int argc, char *argv[]) { grub_ssize_t len = 0; char *p; int i; grub_multiboot_free_mbi (); for (i = 0; i < argc; i++) len += grub_strlen (argv[i]) + 1; if (len == 0) len = 1; cmdline = p = grub_malloc (len); if (! cmdline) return grub_errno; cmdline_size = len; for (i = 0; i < argc; i++) { p = grub_stpcpy (p, argv[i]); *(p++) = ' '; } /* Remove the space after the last word. */ if (p != cmdline) p--; *p = '\0'; return GRUB_ERR_NONE; }
static int grub_ofdisk_iterate (int (*hook) (const char *name), grub_disk_pull_t pull) { unsigned i; if (pull != GRUB_DISK_PULL_NONE) return 0; scan (); for (i = 0; i < ARRAY_SIZE (ofdisk_hash); i++) { static struct ofdisk_hash_ent *ent; for (ent = ofdisk_hash[i]; ent; ent = ent->next) { if (!ent->shortest) continue; if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_OFDISK_SDCARD_ONLY)) { grub_ieee1275_phandle_t dev; char tmp[8]; if (grub_ieee1275_finddevice (ent->devpath, &dev)) { grub_dprintf ("disk", "finddevice (%s) failed\n", ent->devpath); continue; } if (grub_ieee1275_get_property (dev, "iconname", tmp, sizeof tmp, 0)) { grub_dprintf ("disk", "get iconname failed\n"); continue; } if (grub_strcmp (tmp, "sdmmc") != 0) { grub_dprintf ("disk", "device is not an SD card\n"); continue; } } if (grub_strncmp (ent->shortest, "cdrom", 5) == 0) continue; { char buffer[sizeof ("ieee1275/") + grub_strlen (ent->shortest)]; char *ptr; ptr = grub_stpcpy (buffer, "ieee1275/"); grub_strcpy (ptr, ent->shortest); if (hook (buffer)) return 1; } } } return 0; }
grub_err_t grub_multiboot_add_module (grub_addr_t start, grub_size_t size, int argc, char *argv[]) { struct module *newmod; char *p; grub_ssize_t len = 0; int i; newmod = grub_malloc (sizeof (*newmod)); if (!newmod) return grub_errno; newmod->start = start; newmod->size = size; for (i = 0; i < argc; i++) len += grub_strlen (argv[i]) + 1; if (len == 0) len = 1; newmod->cmdline = p = grub_malloc (len); if (! newmod->cmdline) { grub_free (newmod); return grub_errno; } newmod->cmdline_size = len; total_modcmd += ALIGN_UP (len, 4); for (i = 0; i < argc; i++) { p = grub_stpcpy (p, argv[i]); *(p++) = ' '; } /* Remove the space after the last word. */ if (p != newmod->cmdline) p--; *p = '\0'; if (modules_last) modules_last->next = newmod; else { modules = newmod; modules_last->next = NULL; } modules_last = newmod; modcnt++; return GRUB_ERR_NONE; }
/* Try to load an icon for the specified CLASS_NAME in the directory DIR. Returns 0 if the icon could not be loaded, or returns a pointer to a new bitmap if it was successful. */ static struct grub_video_bitmap * try_loading_icon (grub_gfxmenu_icon_manager_t mgr, const char *dir, const char *class_name) { char *path, *ptr; path = grub_malloc (grub_strlen (dir) + grub_strlen (class_name) + grub_strlen (icon_extension) + 3); if (! path) return 0; ptr = grub_stpcpy (path, dir); if (path == ptr || ptr[-1] != '/') *ptr++ = '/'; ptr = grub_stpcpy (ptr, class_name); ptr = grub_stpcpy (ptr, icon_extension); *ptr = '\0'; struct grub_video_bitmap *raw_bitmap; grub_video_bitmap_load (&raw_bitmap, path); grub_free (path); grub_errno = GRUB_ERR_NONE; /* Critical to clear the error!! */ if (! raw_bitmap) return 0; struct grub_video_bitmap *scaled_bitmap; grub_video_bitmap_create_scaled (&scaled_bitmap, mgr->icon_width, mgr->icon_height, raw_bitmap, GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST); grub_video_bitmap_destroy (raw_bitmap); if (! scaled_bitmap) return 0; return scaled_bitmap; }
char * grub_util_get_devmapper_grub_dev (const char *os_dev) { char *uuid, *optr; char *grub_dev; uuid = get_dm_uuid (os_dev); if (!uuid) return NULL; if (strncmp (uuid, "LVM-", sizeof ("LVM-") - 1) == 0) { unsigned i; int dashes[] = { 0, 6, 10, 14, 18, 22, 26, 32, 38, 42, 46, 50, 54, 58}; grub_dev = xmalloc (grub_strlen (uuid) + 40); optr = grub_stpcpy (grub_dev, "lvmid/"); for (i = 0; i < ARRAY_SIZE (dashes) - 1; i++) { memcpy (optr, uuid + sizeof ("LVM-") - 1 + dashes[i], dashes[i+1] - dashes[i]); optr += dashes[i+1] - dashes[i]; *optr++ = '-'; } optr = stpcpy (optr, uuid + sizeof ("LVM-") - 1 + dashes[i]); *optr = '\0'; grub_dev[sizeof("lvmid/xxxxxx-xxxx-xxxx-xxxx-xxxx-xxxx-xxxxxx") - 1] = '/'; free (uuid); return grub_dev; } if (strncmp (uuid, "CRYPT-LUKS1-", sizeof ("CRYPT-LUKS1-") - 1) == 0) { char *dash; dash = grub_strchr (uuid + sizeof ("CRYPT-LUKS1-") - 1, '-'); if (dash) *dash = 0; grub_dev = grub_xasprintf ("cryptouuid/%s", uuid + sizeof ("CRYPT-LUKS1-") - 1); grub_free (uuid); return grub_dev; } grub_free (uuid); return NULL; }
/* Create the tag containing the cmdline and the address of the module data. */ static grub_err_t grub_mb2_tag_module_create (grub_addr_t modaddr, grub_size_t modsize, char *type, int key, int argc, char *argv[]) { struct multiboot_tag_module *module; grub_ssize_t argslen = 0; grub_err_t err; char *p; grub_addr_t module_addr; int i; /* Allocate enough space for the arguments and spaces between them. */ for (i = 0; i < argc; i++) argslen += grub_strlen (argv[i]) + 1; /* Note: includes implicit 1-byte cmdline. */ err = grub_mb2_tag_alloc (&module_addr, key, sizeof (struct multiboot_tag_module) + argslen); if (err) return grub_errno; module = (struct multiboot_tag_module *) module_addr; module->addr = modaddr; module->size = modsize; grub_strcpy(module->type, type); /* Fill in the command line. */ p = module->cmdline; for (i = 0; i < argc; i++) { p = grub_stpcpy (p, argv[i]); *p++ = ' '; } module->cmdline[argslen] = '\0'; return GRUB_ERR_NONE; }
static void probe (const char *path, char **device_names, char delim) { char **drives_names = NULL; char **curdev, **curdrive; char *grub_path = NULL; int ndev = 0; if (path != NULL) { grub_path = canonicalize_file_name (path); if (! grub_path) grub_util_error (_("failed to get canonical path of `%s'"), path); device_names = grub_guess_root_devices (grub_path); free (grub_path); } if (! device_names) grub_util_error (_("cannot find a device for %s (is /dev mounted?)"), path); if (print == PRINT_DEVICE) { for (curdev = device_names; *curdev; curdev++) { printf ("%s", *curdev); putchar (delim); } return; } if (print == PRINT_DISK) { for (curdev = device_names; *curdev; curdev++) { char *disk; disk = grub_util_get_os_disk (*curdev); if (!disk) { grub_print_error (); continue; } printf ("%s", disk); putchar (delim); } return; } for (curdev = device_names; *curdev; curdev++) { grub_util_pull_device (*curdev); ndev++; } drives_names = xmalloc (sizeof (drives_names[0]) * (ndev + 1)); for (curdev = device_names, curdrive = drives_names; *curdev; curdev++, curdrive++) { *curdrive = grub_util_get_grub_dev (*curdev); if (! *curdrive) grub_util_error (_("cannot find a GRUB drive for %s. Check your device.map"), *curdev); } *curdrive = 0; if (print == PRINT_DRIVE) { for (curdrive = drives_names; *curdrive; curdrive++) { printf ("(%s)", *curdrive); putchar (delim); } goto end; } if (print == PRINT_ZERO_CHECK) { for (curdev = drives_names; *curdev; curdev++) { grub_device_t dev = NULL; grub_uint32_t buffer[32768]; grub_disk_addr_t addr; grub_disk_addr_t dsize; grub_util_info ("opening %s", *curdev); dev = grub_device_open (*curdev); if (! dev || !dev->disk) grub_util_error ("%s", grub_errmsg); dsize = grub_disk_get_size (dev->disk); for (addr = 0; addr < dsize; addr += sizeof (buffer) / GRUB_DISK_SECTOR_SIZE) { grub_size_t sz = sizeof (buffer); grub_uint32_t *ptr; if (sizeof (buffer) / GRUB_DISK_SECTOR_SIZE > dsize - addr) sz = (dsize - addr) * GRUB_DISK_SECTOR_SIZE; grub_disk_read (dev->disk, addr, 0, sz, buffer); for (ptr = buffer; ptr < buffer + sz / sizeof (*buffer); ptr++) if (*ptr) { grub_printf ("false\n"); grub_device_close (dev); goto end; } } grub_device_close (dev); } grub_printf ("true\n"); } if (print == PRINT_FS || print == PRINT_FS_UUID || print == PRINT_FS_LABEL) { grub_device_t dev = NULL; grub_fs_t fs; grub_util_info ("opening %s", drives_names[0]); dev = grub_device_open (drives_names[0]); if (! dev) grub_util_error ("%s", grub_errmsg); fs = grub_fs_probe (dev); if (! fs) grub_util_error ("%s", grub_errmsg); if (print == PRINT_FS) { printf ("%s", fs->name); putchar (delim); } else if (print == PRINT_FS_UUID) { char *uuid; if (! fs->uuid) grub_util_error (_("%s does not support UUIDs"), fs->name); if (fs->uuid (dev, &uuid) != GRUB_ERR_NONE) grub_util_error ("%s", grub_errmsg); printf ("%s", uuid); putchar (delim); } else if (print == PRINT_FS_LABEL) { char *label; if (! fs->label) grub_util_error (_("filesystem `%s' does not support labels"), fs->name); if (fs->label (dev, &label) != GRUB_ERR_NONE) grub_util_error ("%s", grub_errmsg); printf ("%s", label); putchar (delim); } grub_device_close (dev); goto end; } for (curdrive = drives_names, curdev = device_names; *curdrive; curdrive++, curdev++) { grub_device_t dev = NULL; grub_util_info ("opening %s", *curdrive); dev = grub_device_open (*curdrive); if (! dev) grub_util_error ("%s", grub_errmsg); if (print == PRINT_HINT_STR) { const char *osdev = grub_util_biosdisk_get_osdev (dev->disk); const char *ofpath = osdev ? grub_util_devname_to_ofpath (osdev) : 0; char *biosname, *bare, *efi; const char *map; if (ofpath) { char *tmp = xmalloc (strlen (ofpath) + sizeof ("ieee1275/")); char *p; p = grub_stpcpy (tmp, "ieee1275/"); strcpy (p, ofpath); printf ("--hint-ieee1275='"); print_full_name (tmp, dev); printf ("' "); free (tmp); } biosname = guess_bios_drive (*curdev); if (biosname) { printf ("--hint-bios="); print_full_name (biosname, dev); printf (" "); } free (biosname); efi = guess_efi_drive (*curdev); if (efi) { printf ("--hint-efi="); print_full_name (efi, dev); printf (" "); } free (efi); bare = guess_baremetal_drive (*curdev); if (bare) { printf ("--hint-baremetal="); print_full_name (bare, dev); printf (" "); } free (bare); /* FIXME: Add ARC hint. */ map = grub_util_biosdisk_get_compatibility_hint (dev->disk); if (map) { printf ("--hint='"); print_full_name (map, dev); printf ("' "); } if (curdrive[1]) printf (" "); else printf ("\n"); grub_device_close (dev); continue; } if ((print == PRINT_COMPATIBILITY_HINT || print == PRINT_BIOS_HINT || print == PRINT_IEEE1275_HINT || print == PRINT_BAREMETAL_HINT || print == PRINT_EFI_HINT || print == PRINT_ARC_HINT) && dev->disk->dev->id != GRUB_DISK_DEVICE_HOSTDISK_ID) { print_full_name (dev->disk->name, dev); putchar (delim); continue; } if (print == PRINT_COMPATIBILITY_HINT) { const char *map; char *biosname; map = grub_util_biosdisk_get_compatibility_hint (dev->disk); if (map) { print_full_name (map, dev); putchar (delim); grub_device_close (dev); /* Compatibility hint is one device only. */ break; } biosname = guess_bios_drive (*curdev); if (biosname) { print_full_name (biosname, dev); putchar (delim); } free (biosname); grub_device_close (dev); /* Compatibility hint is one device only. */ if (biosname) break; continue; } if (print == PRINT_BIOS_HINT) { char *biosname; biosname = guess_bios_drive (*curdev); if (biosname) { print_full_name (biosname, dev); putchar (delim); } free (biosname); grub_device_close (dev); continue; } if (print == PRINT_IEEE1275_HINT) { const char *osdev = grub_util_biosdisk_get_osdev (dev->disk); const char *ofpath = grub_util_devname_to_ofpath (osdev); const char *map; map = grub_util_biosdisk_get_compatibility_hint (dev->disk); if (map) { print_full_name (map, dev); putchar (delim); } if (ofpath) { char *tmp = xmalloc (strlen (ofpath) + sizeof ("ieee1275/")); char *p; p = grub_stpcpy (tmp, "ieee1275/"); strcpy (p, ofpath); print_full_name (tmp, dev); free (tmp); putchar (delim); } grub_device_close (dev); continue; } if (print == PRINT_EFI_HINT) { char *biosname; const char *map; biosname = guess_efi_drive (*curdev); map = grub_util_biosdisk_get_compatibility_hint (dev->disk); if (map) { print_full_name (map, dev); putchar (delim); } if (biosname) { print_full_name (biosname, dev); putchar (delim); } free (biosname); grub_device_close (dev); continue; } if (print == PRINT_BAREMETAL_HINT) { char *biosname; const char *map; biosname = guess_baremetal_drive (*curdev); map = grub_util_biosdisk_get_compatibility_hint (dev->disk); if (map) { print_full_name (map, dev); putchar (delim); } if (biosname) { print_full_name (biosname, dev); putchar (delim); } free (biosname); grub_device_close (dev); continue; } if (print == PRINT_ARC_HINT) { const char *map; map = grub_util_biosdisk_get_compatibility_hint (dev->disk); if (map) { print_full_name (map, dev); putchar (delim); } /* FIXME */ grub_device_close (dev); continue; } if (print == PRINT_ABSTRACTION) { probe_abstraction (dev->disk); putchar (delim); grub_device_close (dev); continue; } if (print == PRINT_CRYPTODISK_UUID) { probe_cryptodisk_uuid (dev->disk); putchar (delim); grub_device_close (dev); continue; } if (print == PRINT_PARTMAP) { /* Check if dev->disk itself is contained in a partmap. */ probe_partmap (dev->disk); putchar (delim); grub_device_close (dev); continue; } if (print == PRINT_MSDOS_PARTTYPE) { if (dev->disk->partition && strcmp(dev->disk->partition->partmap->name, "msdos") == 0) printf ("%02x", dev->disk->partition->msdostype); putchar (delim); grub_device_close (dev); continue; } if (print == PRINT_GPT_PARTTYPE) { if (dev->disk->partition && strcmp (dev->disk->partition->partmap->name, "gpt") == 0) { struct grub_gpt_partentry gptdata; grub_partition_t p = dev->disk->partition; dev->disk->partition = dev->disk->partition->parent; if (grub_disk_read (dev->disk, p->offset, p->index, sizeof (gptdata), &gptdata) == 0) { grub_gpt_part_type_t gpttype; gpttype.data1 = grub_le_to_cpu32 (gptdata.type.data1); gpttype.data2 = grub_le_to_cpu16 (gptdata.type.data2); gpttype.data3 = grub_le_to_cpu16 (gptdata.type.data3); grub_memcpy (gpttype.data4, gptdata.type.data4, 8); grub_printf ("%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", gpttype.data1, gpttype.data2, gpttype.data3, gpttype.data4[0], gpttype.data4[1], gpttype.data4[2], gpttype.data4[3], gpttype.data4[4], gpttype.data4[5], gpttype.data4[6], gpttype.data4[7]); } dev->disk->partition = p; } putchar (delim); grub_device_close (dev); continue; } } end: for (curdrive = drives_names; *curdrive; curdrive++) free (*curdrive); free (drives_names); }
char * grub_legacy_parse (const char *buf, char **entryname, char **suffix) { const char *ptr; const char *cmdname; unsigned i, cmdnum; char *args[ARRAY_SIZE (legacy_commands[0].argt)]; *suffix = NULL; for (ptr = buf; *ptr && grub_isspace (*ptr); ptr++); if (!*ptr || *ptr == '#') { char *ret; int len = grub_strlen (buf); ret = grub_malloc (len + 2); grub_memcpy (ret, buf, len); if (len && ret[len - 1] == '\n') ret[len] = 0; else { ret[len] = '\n'; ret[len + 1] = 0; } return ret; } cmdname = ptr; for (ptr = buf; *ptr && !grub_isspace (*ptr) && *ptr != '='; ptr++); for (cmdnum = 0; cmdnum < ARRAY_SIZE (legacy_commands); cmdnum++) if (grub_strncmp (legacy_commands[cmdnum].name, cmdname, ptr - cmdname) == 0 && legacy_commands[cmdnum].name[ptr - cmdname] == 0 && (!(*entryname != NULL && (legacy_commands[cmdnum].flags & FLAG_NO_MENUENTRY))) && (!(*entryname == NULL && (legacy_commands[cmdnum].flags & FLAG_MENUENTRY_ONLY)))) break; if (cmdnum == ARRAY_SIZE (legacy_commands)) return grub_xasprintf ("# Unsupported legacy command: %s\n", buf); for (; grub_isspace (*ptr) || *ptr == '='; ptr++); if (legacy_commands[cmdnum].flags & FLAG_TITLE) { const char *ptr2; ptr2 = ptr + grub_strlen (ptr); while (ptr2 > ptr && grub_isspace (*(ptr2 - 1))) ptr2--; *entryname = grub_strndup (ptr, ptr2 - ptr); return NULL; } if (legacy_commands[cmdnum].flags & FLAG_TERMINAL) { int dumb = 0, lines = 24; #ifdef TODO int no_echo = 0, no_edit = 0; #endif int hercules = 0; int console = 0, serial = 0, graphics = 0; /* Big enough for any possible resulting command. */ char outbuf[512] = ""; char *outptr; while (*ptr) { /* "[--timeout=SECS] [--silent]" " [console] [serial] [hercules]"*/ if (grub_memcmp (ptr, "--dumb", sizeof ("--dumb") - 1) == 0) dumb = 1; #ifdef TODO if (grub_memcmp (ptr, "--no-echo", sizeof ("--no-echo") - 1) == 0) no_echo = 1; if (grub_memcmp (ptr, "--no-edit", sizeof ("--no-edit") - 1) == 0) no_edit = 1; #endif if (grub_memcmp (ptr, "--lines=", sizeof ("--lines=") - 1) == 0) { lines = grub_strtoul (ptr + sizeof ("--lines=") - 1, 0, 0); if (grub_errno) { lines = 24; grub_errno = GRUB_ERR_NONE; } } if (grub_memcmp (ptr, "console", sizeof ("console") - 1) == 0) console = 1; if (grub_memcmp (ptr, "serial", sizeof ("serial") - 1) == 0) serial = 1; if (grub_memcmp (ptr, "hercules", sizeof ("hercules") - 1) == 0) hercules = 1; if (grub_memcmp (ptr, "graphics", sizeof ("graphics") - 1) == 0) graphics = 1; while (*ptr && !grub_isspace (*ptr)) ptr++; while (*ptr && grub_isspace (*ptr)) ptr++; } if (!console && !serial && !hercules && !graphics) return grub_strdup ("terminal_input; terminal_output; terminfo\n"); outptr = outbuf; if (graphics) outptr = grub_stpcpy (outptr, "insmod all_video; "); outptr = grub_stpcpy (outptr, "terminal_input "); if (serial) outptr = grub_stpcpy (outptr, "serial "); if (console || hercules || graphics) outptr = grub_stpcpy (outptr, "console "); outptr = grub_stpcpy (outptr, "; terminal_output "); if (serial) outptr = grub_stpcpy (outptr, "serial "); if (console) outptr = grub_stpcpy (outptr, "console "); if (hercules) outptr = grub_stpcpy (outptr, "mda_text "); if (graphics) outptr = grub_stpcpy (outptr, "gfxterm "); outptr = grub_stpcpy (outptr, "; "); *outptr = '\0'; if (serial) { grub_snprintf (outptr, outbuf + sizeof (outbuf) - outptr, "terminfo serial -g 80x%d %s; ", lines, dumb ? "dumb" : "vt100"); outptr += grub_strlen (outptr); } grub_strcpy (outptr, "\n"); return grub_strdup (outbuf); } grub_memset (args, 0, sizeof (args)); { int hold_arg = 0; const char *curarg = NULL; for (i = 0; i < legacy_commands[cmdnum].argc; i++) { grub_size_t curarglen; if (hold_arg) { ptr = curarg; hold_arg = 0; } for (; grub_isspace (*ptr); ptr++); curarg = ptr; if (!*curarg) break; for (; *ptr && !grub_isspace (*ptr); ptr++); if (i != legacy_commands[cmdnum].argc - 1 || (legacy_commands[cmdnum].flags & FLAG_IGNORE_REST)) curarglen = ptr - curarg; else { curarglen = grub_strlen (curarg); while (curarglen > 0 && grub_isspace (curarg[curarglen - 1])) curarglen--; } if (*ptr) ptr++; switch (legacy_commands[cmdnum].argt[i]) { case TYPE_FILE_NO_CONSUME: hold_arg = 1; case TYPE_PARTITION: case TYPE_FILE: args[i] = adjust_file (curarg, curarglen); break; case TYPE_REST_VERBATIM: { char *outptr, *outptr0; int overhead = 3; ptr = curarg; while (*ptr) { for (; *ptr && grub_isspace (*ptr); ptr++); for (; *ptr && !grub_isspace (*ptr); ptr++) if (*ptr == '\'') overhead += 3; if (*ptr) ptr++; overhead += 3; } outptr0 = args[i] = grub_malloc (overhead + (ptr - curarg)); if (!outptr0) return NULL; ptr = curarg; outptr = outptr0; while (*ptr) { for (; *ptr && grub_isspace (*ptr); ptr++); if (outptr != outptr0) *outptr++ = ' '; *outptr++ = '\''; for (; *ptr && !grub_isspace (*ptr); ptr++) { if (*ptr == '\'') { *outptr++ = '\''; *outptr++ = '\\'; *outptr++ = '\''; *outptr++ = '\''; } else *outptr++ = *ptr; } *outptr++ = '\''; if (*ptr) ptr++; } *outptr++ = 0; } break; case TYPE_VERBATIM: args[i] = grub_legacy_escape (curarg, curarglen); break; case TYPE_WITH_CONFIGFILE_OPTION: case TYPE_FORCE_OPTION: case TYPE_NOAPM_OPTION: case TYPE_TYPE_OR_NOMEM_OPTION: case TYPE_OPTION: if (is_option (legacy_commands[cmdnum].argt[i], curarg, curarglen)) { args[i] = grub_strndup (curarg, curarglen); break; } args[i] = grub_strdup (""); hold_arg = 1; break; case TYPE_INT: { const char *brk; int base = 10; brk = curarg; if (brk[0] == '0' && brk[1] == 'x') { base = 16; brk += 2; } else if (brk[0] == '0') base = 8; for (; *brk && brk < curarg + curarglen; brk++) { if (base == 8 && (*brk == '8' || *brk == '9')) break; if (grub_isdigit (*brk)) continue; if (base != 16) break; if (!(*brk >= 'a' && *brk <= 'f') && !(*brk >= 'A' && *brk <= 'F')) break; } if (brk == curarg) args[i] = grub_strdup ("0"); else args[i] = grub_strndup (curarg, brk - curarg); } break; case TYPE_VBE_MODE: { unsigned mod; struct grub_vesa_mode_table_entry *modedesc; mod = grub_strtoul (curarg, 0, 0); if (grub_errno) { mod = 0; grub_errno = GRUB_ERR_NONE; } if (mod < GRUB_VESA_MODE_TABLE_START || mod > GRUB_VESA_MODE_TABLE_END) { args[i] = grub_strdup ("auto"); break; } modedesc = &grub_vesa_mode_table[mod - GRUB_VESA_MODE_TABLE_START]; if (!modedesc->width) { args[i] = grub_strdup ("auto"); break; } args[i] = grub_xasprintf ("%ux%ux%u", modedesc->width, modedesc->height, modedesc->depth); break; } case TYPE_BOOL: if (curarglen == 2 && curarg[0] == 'o' && curarg[1] == 'n') args[i] = grub_strdup ("1"); else args[i] = grub_strdup ("0"); break; } } } while (legacy_commands[cmdnum].argc > 0 && args[legacy_commands[cmdnum].argc - 1] == NULL && (legacy_commands[cmdnum].flags & FLAG_FALLBACK_AVAILABLE) && args[legacy_commands[cmdnum + 1].argc] == NULL) cmdnum++; for (; i < legacy_commands[cmdnum].argc; i++) switch (legacy_commands[cmdnum].argt[i]) { case TYPE_FILE_NO_CONSUME: case TYPE_PARTITION: case TYPE_FILE: case TYPE_REST_VERBATIM: case TYPE_VERBATIM: case TYPE_WITH_CONFIGFILE_OPTION: case TYPE_FORCE_OPTION: case TYPE_NOAPM_OPTION: case TYPE_TYPE_OR_NOMEM_OPTION: case TYPE_OPTION: args[i] = grub_strdup (""); break; case TYPE_BOOL: case TYPE_INT: args[i] = grub_strdup ("0"); break; case TYPE_VBE_MODE: args[i] = grub_strdup ("auto"); break; } if (legacy_commands[cmdnum].flags & FLAG_COLOR_INVERT) { char *corig = args[legacy_commands[cmdnum].argc - 1]; char *slash = grub_strchr (corig, '/'); char *invert; grub_size_t len; len = grub_strlen (corig); if (!slash) { grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid color specification `%s'"), args[0]); return NULL; } invert = grub_malloc (len + 1); if (!invert) return NULL; grub_memcpy (invert, slash + 1, len - (slash - corig) - 1); invert[len - (slash - args[0]) - 1] = '/'; grub_memcpy (invert + len - (slash - corig), corig, slash - corig); invert[len] = 0; args[legacy_commands[cmdnum].argc] = invert; } if (legacy_commands[cmdnum].suffix) { *suffix = grub_xasprintf (legacy_commands[cmdnum].suffix, args[legacy_commands[cmdnum].suffixarg]); if (*suffix) return NULL; } { char *ret = grub_xasprintf (legacy_commands[cmdnum].map, args[0], args[1], args[2], args[3]); grub_free (args[0]); grub_free (args[1]); grub_free (args[2]); grub_free (args[3]); return ret; } }
static char * adjust_file (const char *in, grub_size_t len) { const char *comma, *ptr, *rest; char *ret, *outptr; int overhead = 0; int part = -1, subpart = -1; if (in[0] != '(') return grub_legacy_escape (in, len); for (ptr = in + 1; ptr < in + len && *ptr && *ptr != ')' && *ptr != ','; ptr++) if (*ptr == '\'' || *ptr == '\\') overhead++; comma = ptr; if (*comma == ')' && comma - in == 3 && in[1] == 'n' && in[2] == 'd') { rest = comma + 1; for (ptr = rest; ptr < in + len && *ptr; ptr++) if (*ptr == '\'' || *ptr == '\\') overhead++; ret = grub_malloc (ptr - in + overhead + 15); if (!ret) return NULL; outptr = grub_stpcpy (ret, "(tftp)");; for (ptr = rest; ptr < in + len; ptr++) { if (*ptr == '\'' || *ptr == '\\') *outptr++ = '\\'; *outptr++ = *ptr; } *outptr = 0; return ret; } if (*comma != ',') return grub_legacy_escape (in, len); part = grub_strtoull (comma + 1, (char **) &rest, 0); if (rest[0] == ',' && rest[1] >= 'a' && rest[1] <= 'z') { subpart = rest[1] - 'a'; rest += 2; } for (ptr = rest; ptr < in + len && *ptr; ptr++) if (*ptr == '\'' || *ptr == '\\') overhead++; /* 35 is enough for any 2 numbers. */ ret = grub_malloc (ptr - in + overhead + 35 + 5); if (!ret) return NULL; outptr = ret; for (ptr = in; ptr < in + len && ptr <= comma; ptr++) { if (*ptr == '\'' || *ptr == '\\') *outptr++ = '\\'; *outptr++ = *ptr; } if (subpart != -1) grub_snprintf (outptr, 35, "%d,%d", part + 1, subpart + 1); else grub_snprintf (outptr, 35, "%d", part + 1); while (*outptr) outptr++; for (ptr = rest; ptr < in + len; ptr++) { if (*ptr == '\'' || *ptr == '\\') *outptr++ = '\\'; *outptr++ = *ptr; } *outptr = 0; return ret; }
/* Run a menu entry. */ static void grub_menu_execute_entry(grub_menu_entry_t entry, int auto_boot) { grub_err_t err = GRUB_ERR_NONE; int errs_before; grub_menu_t menu = NULL; char *optr, *buf, *oldchosen = NULL, *olddefault = NULL; const char *ptr, *chosen, *def; grub_size_t sz = 0; if (entry->restricted) err = grub_auth_check_authentication (entry->users); if (err) { grub_print_error (); grub_errno = GRUB_ERR_NONE; return; } errs_before = grub_err_printed_errors; chosen = grub_env_get ("chosen"); def = grub_env_get ("default"); if (entry->submenu) { grub_env_context_open (); menu = grub_zalloc (sizeof (*menu)); if (! menu) return; grub_env_set_menu (menu); if (auto_boot) grub_env_set ("timeout", "0"); } for (ptr = entry->id; *ptr; ptr++) sz += (*ptr == '>') ? 2 : 1; if (chosen) { oldchosen = grub_strdup (chosen); if (!oldchosen) grub_print_error (); } if (def) { olddefault = grub_strdup (def); if (!olddefault) grub_print_error (); } sz++; if (chosen) sz += grub_strlen (chosen); sz++; buf = grub_malloc (sz); if (!buf) grub_print_error (); else { optr = buf; if (chosen) { optr = grub_stpcpy (optr, chosen); *optr++ = '>'; } for (ptr = entry->id; *ptr; ptr++) { if (*ptr == '>') *optr++ = '>'; *optr++ = *ptr; } *optr = 0; grub_env_set ("chosen", buf); grub_env_export ("chosen"); grub_free (buf); } for (ptr = def; ptr && *ptr; ptr++) { if (ptr[0] == '>' && ptr[1] == '>') { ptr++; continue; } if (ptr[0] == '>') break; } if (ptr && ptr[0] && ptr[1]) grub_env_set ("default", ptr + 1); else grub_env_unset ("default"); grub_script_execute_sourcecode (entry->sourcecode, entry->argc, entry->args); if (errs_before != grub_err_printed_errors) grub_wait_after_message (); if (grub_errno == GRUB_ERR_NONE && grub_loader_is_loaded ()) /* Implicit execution of boot, only if something is loaded. */ grub_command_execute ("boot", 0, 0); if (entry->submenu) { if (menu && menu->size) { grub_show_menu (menu, 1, auto_boot); grub_normal_free_menu (menu); } grub_env_context_close (); } if (oldchosen) grub_env_set ("chosen", oldchosen); else grub_env_unset ("chosen"); if (olddefault) grub_env_set ("default", olddefault); else grub_env_unset ("default"); grub_env_unset ("timeout"); }
static grub_err_t handle_symlink (struct grub_archelp_data *data, struct grub_archelp_ops *arcops, const char *fn, char **name, grub_uint32_t mode, int *restart) { grub_size_t flen; char *target; char *ptr; char *lastslash; grub_size_t prefixlen; char *rest; char *linktarget; grub_size_t linktarget_len; *restart = 0; if ((mode & GRUB_ARCHELP_ATTR_TYPE) != GRUB_ARCHELP_ATTR_LNK || !arcops->get_link_target) return GRUB_ERR_NONE; flen = grub_strlen (fn); if (grub_memcmp (*name, fn, flen) != 0 || ((*name)[flen] != 0 && (*name)[flen] != '/')) return GRUB_ERR_NONE; rest = *name + flen; lastslash = rest; if (*rest) rest++; while (lastslash >= *name && *lastslash != '/') lastslash--; if (lastslash >= *name) prefixlen = lastslash - *name; else prefixlen = 0; if (prefixlen) prefixlen++; linktarget = arcops->get_link_target (data); if (!linktarget) return grub_errno; if (linktarget[0] == '\0') return GRUB_ERR_NONE; linktarget_len = grub_strlen (linktarget); target = grub_malloc (linktarget_len + grub_strlen (*name) + 2); if (!target) return grub_errno; grub_strcpy (target + prefixlen, linktarget); grub_free (linktarget); if (target[prefixlen] == '/') { ptr = grub_stpcpy (target, target + prefixlen); ptr = grub_stpcpy (ptr, rest); *ptr = 0; grub_dprintf ("archelp", "symlink redirected %s to %s\n", *name, target); grub_free (*name); canonicalize (target); *name = target; *restart = 1; return GRUB_ERR_NONE; } if (prefixlen) { grub_memcpy (target, *name, prefixlen); target[prefixlen-1] = '/'; } grub_strcpy (target + prefixlen + linktarget_len, rest); grub_dprintf ("archelp", "symlink redirected %s to %s\n", *name, target); grub_free (*name); canonicalize (target); *name = target; *restart = 1; return GRUB_ERR_NONE; }
static grub_err_t handle_symlink (struct grub_cpio_data *data, const char *fn, char **name, grub_uint32_t mode, int *restart) { grub_size_t flen; char *target; #ifndef MODE_USTAR grub_err_t err; #endif char *ptr; char *lastslash; grub_size_t prefixlen; char *rest; grub_size_t size; *restart = 0; if ((mode & ATTR_TYPE) != ATTR_LNK) return GRUB_ERR_NONE; flen = grub_strlen (fn); if (grub_memcmp (*name, fn, flen) != 0 || ((*name)[flen] != 0 && (*name)[flen] != '/')) return GRUB_ERR_NONE; rest = *name + flen; lastslash = rest; if (*rest) rest++; while (lastslash >= *name && *lastslash != '/') lastslash--; if (lastslash >= *name) prefixlen = lastslash - *name; else prefixlen = 0; if (prefixlen) prefixlen++; #ifdef MODE_USTAR size = grub_strlen (data->linkname); #else size = data->size; #endif if (size == 0) return GRUB_ERR_NONE; target = grub_malloc (size + grub_strlen (*name) + 2); if (!target) return grub_errno; #ifdef MODE_USTAR grub_memcpy (target + prefixlen, data->linkname, size); #else err = grub_disk_read (data->disk, 0, data->dofs, data->size, target + prefixlen); if (err) return err; #endif if (target[prefixlen] == '/') { grub_memmove (target, target + prefixlen, size); ptr = target + size; ptr = grub_stpcpy (ptr, rest); *ptr = 0; grub_dprintf ("cpio", "symlink redirected %s to %s\n", *name, target); grub_free (*name); canonicalize (target); *name = target; *restart = 1; return GRUB_ERR_NONE; } if (prefixlen) { grub_memcpy (target, *name, prefixlen); target[prefixlen-1] = '/'; } ptr = target + prefixlen + size; ptr = grub_stpcpy (ptr, rest); *ptr = 0; grub_dprintf ("cpio", "symlink redirected %s to %s\n", *name, target); grub_free (*name); canonicalize (target); *name = target; *restart = 1; return GRUB_ERR_NONE; }
/* Load a font and add it to the beginning of the global font list. Returns 0 upon success, nonzero upon failure. */ grub_font_t grub_font_load (const char *filename) { grub_file_t file = 0; struct font_file_section section; char magic[4]; grub_font_t font = 0; #if FONT_DEBUG >= 1 grub_dprintf ("font", "add_font(%s)\n", filename); #endif if (filename[0] == '(' || filename[0] == '/' || filename[0] == '+') file = grub_buffile_open (filename, 1024); else { const char *prefix = grub_env_get ("prefix"); char *fullname, *ptr; if (!prefix) { grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("variable `%s' isn't set"), "prefix"); goto fail; } fullname = grub_malloc (grub_strlen (prefix) + grub_strlen (filename) + 1 + sizeof ("/fonts/") + sizeof (".pf2")); if (!fullname) goto fail; ptr = grub_stpcpy (fullname, prefix); ptr = grub_stpcpy (ptr, "/fonts/"); ptr = grub_stpcpy (ptr, filename); ptr = grub_stpcpy (ptr, ".pf2"); *ptr = 0; file = grub_buffile_open (fullname, 1024); grub_free (fullname); } if (!file) goto fail; #if FONT_DEBUG >= 3 grub_dprintf ("font", "file opened\n"); #endif /* Read the FILE section. It indicates the file format. */ if (open_section (file, §ion) != 0) goto fail; #if FONT_DEBUG >= 3 grub_dprintf ("font", "opened FILE section\n"); #endif if (grub_memcmp (section.name, FONT_FORMAT_SECTION_NAMES_FILE, sizeof (FONT_FORMAT_SECTION_NAMES_FILE) - 1) != 0) { grub_error (GRUB_ERR_BAD_FONT, "font file format error: 1st section must be FILE"); goto fail; } #if FONT_DEBUG >= 3 grub_dprintf ("font", "section name ok\n"); #endif if (section.length != 4) { grub_error (GRUB_ERR_BAD_FONT, "font file format error (file type ID length is %d " "but should be 4)", section.length); goto fail; } #if FONT_DEBUG >= 3 grub_dprintf ("font", "section length ok\n"); #endif /* Check the file format type code. */ if (grub_file_read (file, magic, 4) != 4) goto fail; #if FONT_DEBUG >= 3 grub_dprintf ("font", "read magic ok\n"); #endif if (grub_memcmp (magic, FONT_FORMAT_PFF2_MAGIC, 4) != 0) { grub_error (GRUB_ERR_BAD_FONT, "invalid font magic %x %x %x %x", magic[0], magic[1], magic[2], magic[3]); goto fail; } #if FONT_DEBUG >= 3 grub_dprintf ("font", "compare magic ok\n"); #endif /* Allocate the font object. */ font = (grub_font_t) grub_zalloc (sizeof (struct grub_font)); if (!font) goto fail; font_init (font); font->file = file; #if FONT_DEBUG >= 3 grub_dprintf ("font", "allocate font ok; loading font info\n"); #endif /* Load the font information. */ while (1) { if (open_section (file, §ion) != 0) { if (section.eof) break; /* Done reading the font file. */ else goto fail; } #if FONT_DEBUG >= 2 grub_dprintf ("font", "opened section %c%c%c%c ok\n", section.name[0], section.name[1], section.name[2], section.name[3]); #endif if (grub_memcmp (section.name, FONT_FORMAT_SECTION_NAMES_FONT_NAME, sizeof (FONT_FORMAT_SECTION_NAMES_FONT_NAME) - 1) == 0) { font->name = read_section_as_string (§ion); if (!font->name) goto fail; } else if (grub_memcmp (section.name, FONT_FORMAT_SECTION_NAMES_POINT_SIZE, sizeof (FONT_FORMAT_SECTION_NAMES_POINT_SIZE) - 1) == 0) { if (read_section_as_short (§ion, &font->point_size) != 0) goto fail; } else if (grub_memcmp (section.name, FONT_FORMAT_SECTION_NAMES_WEIGHT, sizeof (FONT_FORMAT_SECTION_NAMES_WEIGHT) - 1) == 0) { char *wt; wt = read_section_as_string (§ion); if (!wt) continue; /* Convert the weight string 'normal' or 'bold' into a number. */ if (grub_strcmp (wt, "normal") == 0) font->weight = FONT_WEIGHT_NORMAL; else if (grub_strcmp (wt, "bold") == 0) font->weight = FONT_WEIGHT_BOLD; grub_free (wt); } else if (grub_memcmp (section.name, FONT_FORMAT_SECTION_NAMES_MAX_CHAR_WIDTH, sizeof (FONT_FORMAT_SECTION_NAMES_MAX_CHAR_WIDTH) - 1) == 0) { if (read_section_as_short (§ion, &font->max_char_width) != 0) goto fail; } else if (grub_memcmp (section.name, FONT_FORMAT_SECTION_NAMES_MAX_CHAR_HEIGHT, sizeof (FONT_FORMAT_SECTION_NAMES_MAX_CHAR_HEIGHT) - 1) == 0) { if (read_section_as_short (§ion, &font->max_char_height) != 0) goto fail; } else if (grub_memcmp (section.name, FONT_FORMAT_SECTION_NAMES_ASCENT, sizeof (FONT_FORMAT_SECTION_NAMES_ASCENT) - 1) == 0) { if (read_section_as_short (§ion, &font->ascent) != 0) goto fail; } else if (grub_memcmp (section.name, FONT_FORMAT_SECTION_NAMES_DESCENT, sizeof (FONT_FORMAT_SECTION_NAMES_DESCENT) - 1) == 0) { if (read_section_as_short (§ion, &font->descent) != 0) goto fail; } else if (grub_memcmp (section.name, FONT_FORMAT_SECTION_NAMES_CHAR_INDEX, sizeof (FONT_FORMAT_SECTION_NAMES_CHAR_INDEX) - 1) == 0) { if (load_font_index (file, section.length, font) != 0) goto fail; } else if (grub_memcmp (section.name, FONT_FORMAT_SECTION_NAMES_DATA, sizeof (FONT_FORMAT_SECTION_NAMES_DATA) - 1) == 0) { /* When the DATA section marker is reached, we stop reading. */ break; } else { /* Unhandled section type, simply skip past it. */ #if FONT_DEBUG >= 3 grub_dprintf ("font", "Unhandled section type, skipping.\n"); #endif grub_off_t section_end = grub_file_tell (file) + section.length; if ((int) grub_file_seek (file, section_end) == -1) goto fail; } } if (!font->name) { grub_dprintf ("font", "Font has no name.\n"); font->name = grub_strdup ("Unknown"); } #if FONT_DEBUG >= 1 grub_dprintf ("font", "Loaded font `%s'.\n" "Ascent=%d Descent=%d MaxW=%d MaxH=%d Number of characters=%d.\n", font->name, font->ascent, font->descent, font->max_char_width, font->max_char_height, font->num_chars); #endif if (font->max_char_width == 0 || font->max_char_height == 0 || font->num_chars == 0 || font->char_index == 0 || font->ascent == 0 || font->descent == 0) { grub_error (GRUB_ERR_BAD_FONT, "invalid font file: missing some required data"); goto fail; } /* Add the font to the global font registry. */ if (register_font (font) != 0) goto fail; return font; fail: if (file) grub_file_close (file); if (font) font->file = 0; free_font (font); return 0; }
static void scan (void) { auto int dev_iterate_real (const char *name, const char *path); int dev_iterate_real (const char *name, const char *path) { struct ofdisk_hash_ent *op; grub_dprintf ("disk", "disk name = %s, path = %s\n", name, path); op = ofdisk_hash_find (path); if (!op) { char *name_dup = grub_strdup (name); char *can = grub_strdup (path); if (!name_dup || !can) { grub_errno = GRUB_ERR_NONE; grub_free (name_dup); grub_free (can); return 0; } op = ofdisk_hash_add (name_dup, can); } return 0; } auto int dev_iterate_alias (struct grub_ieee1275_devalias *alias); int dev_iterate_alias (struct grub_ieee1275_devalias *alias) { if (grub_strcmp (alias->type, "block") != 0) return 0; return dev_iterate_real (alias->name, alias->path); } auto int dev_iterate (struct grub_ieee1275_devalias *alias); int dev_iterate (struct grub_ieee1275_devalias *alias) { if (grub_strcmp (alias->type, "vscsi") == 0) { static grub_ieee1275_ihandle_t ihandle; struct set_color_args { struct grub_ieee1275_common_hdr common; grub_ieee1275_cell_t method; grub_ieee1275_cell_t ihandle; grub_ieee1275_cell_t catch_result; grub_ieee1275_cell_t nentries; grub_ieee1275_cell_t table; } args; char *buf, *bufptr; unsigned i; if (grub_ieee1275_open (alias->path, &ihandle)) return 0; INIT_IEEE1275_COMMON (&args.common, "call-method", 2, 3); args.method = (grub_ieee1275_cell_t) "vscsi-report-luns"; args.ihandle = ihandle; args.table = 0; args.nentries = 0; if (IEEE1275_CALL_ENTRY_FN (&args) == -1) { grub_ieee1275_close (ihandle); return 0; } buf = grub_malloc (grub_strlen (alias->path) + 32); if (!buf) return 0; bufptr = grub_stpcpy (buf, alias->path); for (i = 0; i < args.nentries; i++) { grub_uint64_t *ptr; ptr = *(grub_uint64_t **) (args.table + 4 + 8 * i); while (*ptr) { grub_snprintf (bufptr, 32, "/disk@%" PRIxGRUB_UINT64_T, *ptr++); if (dev_iterate_real (buf, buf)) return 1; } } grub_ieee1275_close (ihandle); grub_free (buf); return 0; } if (!grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_TREE_SCANNING_FOR_DISKS) && grub_strcmp (alias->type, "block") == 0) return dev_iterate_real (alias->path, alias->path); return grub_children_iterate (alias->path, dev_iterate); } grub_devalias_iterate (dev_iterate_alias); grub_children_iterate ("/", dev_iterate); }
/* Eliminate "." and ".." path elements from PATH. A new heap-allocated string is returned. */ static char * canonicalize_path (const char *path) { int i; const char *p; char *newpath = 0; /* Count the path components in path. */ int components = 1; for (p = path; *p; p++) if (*p == '/') components++; char **path_array = grub_malloc (components * sizeof (*path_array)); if (! path_array) return 0; /* Initialize array elements to NULL pointers; in case once of the allocations fails, the cleanup code can just call grub_free() for all pointers in the array. */ for (i = 0; i < components; i++) path_array[i] = 0; /* Parse the path into path_array. */ p = path; for (i = 0; i < components && p; i++) { /* Find the end of the path element. */ const char *end = grub_strchr (p, '/'); if (!end) end = p + grub_strlen (p); /* Copy the element. */ path_array[i] = grub_new_substring (p, 0, end - p); if (! path_array[i]) goto cleanup; /* Advance p to point to the start of the next element, or NULL. */ if (*end) p = end + 1; else p = 0; } /* Eliminate '.' and '..' elements from the path array. */ int newpath_length = 0; for (i = components - 1; i >= 0; --i) { if (! grub_strcmp (path_array[i], ".")) { grub_free (path_array[i]); path_array[i] = 0; } else if (! grub_strcmp (path_array[i], "..") && i > 0) { /* Delete the '..' and the prior path element. */ grub_free (path_array[i]); path_array[i] = 0; --i; grub_free (path_array[i]); path_array[i] = 0; } else { newpath_length += grub_strlen (path_array[i]) + 1; } } /* Construct a new path string. */ newpath = grub_malloc (newpath_length + 1); if (! newpath) goto cleanup; newpath[0] = '\0'; char *newpath_end = newpath; int first = 1; for (i = 0; i < components; i++) { char *element = path_array[i]; if (element) { /* For all components but the first, prefix with a slash. */ if (! first) newpath_end = grub_stpcpy (newpath_end, "/"); newpath_end = grub_stpcpy (newpath_end, element); first = 0; } } cleanup: for (i = 0; i < components; i++) grub_free (path_array[i]); grub_free (path_array); return newpath; }
static void dev_iterate (const struct grub_ieee1275_devalias *alias) { if (grub_strcmp (alias->type, "vscsi") == 0) { static grub_ieee1275_ihandle_t ihandle; struct set_color_args { struct grub_ieee1275_common_hdr common; grub_ieee1275_cell_t method; grub_ieee1275_cell_t ihandle; grub_ieee1275_cell_t catch_result; grub_ieee1275_cell_t nentries; grub_ieee1275_cell_t table; } args; char *buf, *bufptr; unsigned i; if (grub_ieee1275_open (alias->path, &ihandle)) return; INIT_IEEE1275_COMMON (&args.common, "call-method", 2, 3); args.method = (grub_ieee1275_cell_t) "vscsi-report-luns"; args.ihandle = ihandle; args.table = 0; args.nentries = 0; if (IEEE1275_CALL_ENTRY_FN (&args) == -1 || args.catch_result) { grub_ieee1275_close (ihandle); return; } buf = grub_malloc (grub_strlen (alias->path) + 32); if (!buf) return; bufptr = grub_stpcpy (buf, alias->path); for (i = 0; i < args.nentries; i++) { grub_uint64_t *ptr; ptr = *(grub_uint64_t **) (args.table + 4 + 8 * i); while (*ptr) { grub_snprintf (bufptr, 32, "/disk@%" PRIxGRUB_UINT64_T, *ptr++); dev_iterate_real (buf, buf); } } grub_ieee1275_close (ihandle); grub_free (buf); return; } if (!grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_TREE_SCANNING_FOR_DISKS) && grub_strcmp (alias->type, "block") == 0) { dev_iterate_real (alias->path, alias->path); return; } { struct grub_ieee1275_devalias child; FOR_IEEE1275_DEVCHILDREN(alias->path, child) dev_iterate (&child); } }
/* Create a new box. If PIXMAPS_PREFIX and PIXMAPS_SUFFIX are both non-null, then an attempt is made to load the north, south, east, west, northwest, northeast, southeast, southwest, and center pixmaps. If either PIXMAPS_PREFIX or PIXMAPS_SUFFIX is 0, then no pixmaps are loaded, and the box has zero-width borders and is drawn transparent. */ grub_gfxmenu_box_t grub_gfxmenu_create_box (const char *pixmaps_prefix, const char *pixmaps_suffix) { unsigned i; grub_gfxmenu_box_t box; box = (grub_gfxmenu_box_t) grub_malloc (sizeof (*box)); if (! box) return 0; box->content_width = 0; box->content_height = 0; box->raw_pixmaps = (struct grub_video_bitmap **) grub_malloc (BOX_NUM_PIXMAPS * sizeof (struct grub_video_bitmap *)); box->scaled_pixmaps = (struct grub_video_bitmap **) grub_malloc (BOX_NUM_PIXMAPS * sizeof (struct grub_video_bitmap *)); /* Initialize all pixmap pointers to NULL so that proper destruction can be performed if an error is encountered partway through construction. */ for (i = 0; i < BOX_NUM_PIXMAPS; i++) box->raw_pixmaps[i] = 0; for (i = 0; i < BOX_NUM_PIXMAPS; i++) box->scaled_pixmaps[i] = 0; /* Load the pixmaps. */ for (i = 0; i < BOX_NUM_PIXMAPS; i++) { if (pixmaps_prefix && pixmaps_suffix) { char *path; char *path_end; path = grub_malloc (grub_strlen (pixmaps_prefix) + grub_strlen (box_pixmap_names[i]) + grub_strlen (pixmaps_suffix) + 1); if (! path) goto fail_and_destroy; /* Construct the specific path for this pixmap. */ path_end = grub_stpcpy (path, pixmaps_prefix); path_end = grub_stpcpy (path_end, box_pixmap_names[i]); path_end = grub_stpcpy (path_end, pixmaps_suffix); grub_video_bitmap_load (&box->raw_pixmaps[i], path); grub_free (path); /* Ignore missing pixmaps. */ grub_errno = GRUB_ERR_NONE; } } box->draw = draw; box->set_content_size = set_content_size; box->get_left_pad = get_left_pad; box->get_top_pad = get_top_pad; box->get_right_pad = get_right_pad; box->get_bottom_pad = get_bottom_pad; box->destroy = destroy; return box; fail_and_destroy: destroy (box); return 0; }
static void dev_iterate (const struct grub_ieee1275_devalias *alias) { if (grub_strcmp (alias->type, "vscsi") == 0) { static grub_ieee1275_ihandle_t ihandle; struct set_color_args { struct grub_ieee1275_common_hdr common; grub_ieee1275_cell_t method; grub_ieee1275_cell_t ihandle; grub_ieee1275_cell_t catch_result; grub_ieee1275_cell_t nentries; grub_ieee1275_cell_t table; } args; char *buf, *bufptr; unsigned i; if (grub_ieee1275_open (alias->path, &ihandle)) return; /* This method doesn't need memory allocation for the table. Open firmware takes care of all memory management and the result table stays in memory and is never freed. */ INIT_IEEE1275_COMMON (&args.common, "call-method", 2, 3); args.method = (grub_ieee1275_cell_t) "vscsi-report-luns"; args.ihandle = ihandle; args.table = 0; args.nentries = 0; if (IEEE1275_CALL_ENTRY_FN (&args) == -1 || args.catch_result) { grub_ieee1275_close (ihandle); return; } buf = grub_malloc (grub_strlen (alias->path) + 32); if (!buf) return; bufptr = grub_stpcpy (buf, alias->path); for (i = 0; i < args.nentries; i++) { grub_uint64_t *ptr; ptr = *(grub_uint64_t **) (args.table + 4 + 8 * i); while (*ptr) { grub_snprintf (bufptr, 32, "/disk@%" PRIxGRUB_UINT64_T, *ptr++); dev_iterate_real (buf, buf); } } grub_ieee1275_close (ihandle); grub_free (buf); return; } else if (grub_strcmp (alias->type, "sas_ioa") == 0) { /* The method returns the number of disks and a table where * each ID is 64-bit long. Example of sas paths: * /pci@80000002000001f/pci1014,034A@0/sas/disk@c05db70800 * /pci@80000002000001f/pci1014,034A@0/sas/disk@a05db70800 * /pci@80000002000001f/pci1014,034A@0/sas/disk@805db70800 */ struct sas_children { struct grub_ieee1275_common_hdr common; grub_ieee1275_cell_t method; grub_ieee1275_cell_t ihandle; grub_ieee1275_cell_t max; grub_ieee1275_cell_t table; grub_ieee1275_cell_t catch_result; grub_ieee1275_cell_t nentries; } args; char *buf, *bufptr; unsigned i; grub_uint64_t *table; grub_uint16_t table_size; grub_ieee1275_ihandle_t ihandle; buf = grub_malloc (grub_strlen (alias->path) + sizeof ("/disk@7766554433221100")); if (!buf) return; bufptr = grub_stpcpy (buf, alias->path); /* Power machines documentation specify 672 as maximum SAS disks in one system. Using a slightly larger value to be safe. */ table_size = 768; table = grub_malloc (table_size * sizeof (grub_uint64_t)); if (!table) { grub_free (buf); return; } if (grub_ieee1275_open (alias->path, &ihandle)) { grub_free (buf); grub_free (table); return; } INIT_IEEE1275_COMMON (&args.common, "call-method", 4, 2); args.method = (grub_ieee1275_cell_t) "get-sas-children"; args.ihandle = ihandle; args.max = table_size; args.table = (grub_ieee1275_cell_t) table; args.catch_result = 0; args.nentries = 0; if (IEEE1275_CALL_ENTRY_FN (&args) == -1) { grub_ieee1275_close (ihandle); grub_free (table); grub_free (buf); return; } for (i = 0; i < args.nentries; i++) { grub_snprintf (bufptr, sizeof ("/disk@7766554433221100"), "/disk@%" PRIxGRUB_UINT64_T, table[i]); dev_iterate_real (buf, buf); } grub_ieee1275_close (ihandle); grub_free (table); grub_free (buf); } if (!grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_TREE_SCANNING_FOR_DISKS) && grub_strcmp (alias->type, "block") == 0) { dev_iterate_real (alias->path, alias->path); return; } { struct grub_ieee1275_devalias child; FOR_IEEE1275_DEVCHILDREN(alias->path, child) dev_iterate (&child); } }