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 != ',') 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); 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; }
static const char * grub_smbios_format_byte (char *buffer, grub_size_t size, const grub_uint8_t *structure, grub_uint8_t offset) { grub_snprintf (buffer, size, "%u", structure[offset]); return (const char *)buffer; }
/* * uboot_disk_iterate(): * Iterator over enumerated disk devices. */ static int uboot_disk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, grub_disk_pull_t pull) { char buf[16]; int count; switch (pull) { case GRUB_DISK_PULL_NONE: /* "hd" - built-in mass-storage */ for (count = 0 ; count < hd_num; count++) { grub_snprintf (buf, sizeof (buf) - 1, "hd%d", count); grub_dprintf ("ubootdisk", "iterating %s\n", buf); if (hook (buf, hook_data)) return 1; } break; default: return 0; } return 0; }
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; }
char * grub_partition_get_name (const grub_partition_t partition) { char *out = 0; int curlen = 0; grub_partition_t part; for (part = partition; part; part = part->parent) { /* Even on 64-bit machines this buffer is enough to hold longest number. */ char buf[grub_strlen (part->partmap->name) + 25]; int strl; grub_snprintf (buf, sizeof (buf), "%s%d", part->partmap->name, part->number + 1); strl = grub_strlen (buf); if (curlen) { out = grub_realloc (out, curlen + strl + 2); grub_memcpy (out + strl + 1, out, curlen); out[curlen + 1 + strl] = 0; grub_memcpy (out, buf, strl); out[strl] = ','; curlen = curlen + 1 + strl; } else { curlen = strl; out = grub_strdup (buf); } } return out; }
char *strerror(int errnum) { static char buf[sizeof("GRUB error 4294967296")]; grub_errno = GRUB_ERR_NONE; grub_snprintf(buf, sizeof(buf), "GRUB error %u", errnum); return buf; }
static char * make_install_device (void) { /* XXX: This should be enough. */ char dev[100], *ptr = dev; if (grub_prefix[0] != '(') { /* No hardcoded root partition - make it from the boot drive and the partition number encoded at the install time. */ if (grub_boot_drive == GRUB_BOOT_MACHINE_PXE_DL) { grub_strcpy (dev, "(pxe"); ptr += sizeof ("(pxe") - 1; } else { grub_snprintf (dev, sizeof (dev), "(%cd%u", (grub_boot_drive & 0x80) ? 'h' : 'f', grub_boot_drive & 0x7f); ptr += grub_strlen (ptr); if (grub_install_dos_part >= 0) grub_snprintf (ptr, sizeof (dev) - (ptr - dev), ",%u", grub_install_dos_part + 1); ptr += grub_strlen (ptr); if (grub_install_bsd_part >= 0) grub_snprintf (ptr, sizeof (dev) - (ptr - dev), ",%u", grub_install_bsd_part + 1); ptr += grub_strlen (ptr); } grub_snprintf (ptr, sizeof (dev) - (ptr - dev), ")%s", grub_prefix); grub_strcpy (grub_prefix, dev); } else if (grub_prefix[1] == ',' || grub_prefix[1] == ')') { /* We have a prefix, but still need to fill in the boot drive. */ grub_snprintf (dev, sizeof (dev), "(%cd%u%s", (grub_boot_drive & 0x80) ? 'h' : 'f', grub_boot_drive & 0x7f, grub_prefix + 1); grub_strcpy (grub_prefix, dev); } return grub_prefix; }
static const char * grub_smbios_format_word (char *buffer, grub_size_t size, const grub_uint8_t *structure, grub_uint8_t offset) { grub_uint16_t value = grub_get_unaligned16 (structure + offset); grub_snprintf (buffer, size, "%u", value); return (const char *)buffer; }
static const char * grub_smbios_format_qword (char *buffer, grub_size_t size, const grub_uint8_t *structure, grub_uint8_t offset) { grub_uint64_t value = grub_get_unaligned64 (structure + offset); grub_snprintf (buffer, size, "%" PRIuGRUB_UINT64_T, value); return (const char *)buffer; }
static void printf_test (void) { char real[512]; char expected[512]; grub_snprintf (real, sizeof (real), "%d %d %d", 1, 2, 3); snprintf (expected, sizeof (expected), "%d %d %d", 1, 2, 3); grub_test_assert (strcmp (real, expected) == 0); grub_snprintf (real, sizeof (real), "%3$d %2$d %1$d", 1, 2, 3); snprintf (expected, sizeof (expected), "%3$d %2$d %1$d", 1, 2, 3); grub_test_assert (strcmp (real, expected) == 0); grub_snprintf (real, sizeof (real), "%d %lld %d", 1, 2LL, 3); snprintf (expected, sizeof (expected), "%d %lld %d", 1, 2LL, 3); grub_test_assert (strcmp (real, expected) == 0); grub_snprintf (real, sizeof (real), "%3$d %2$lld %1$d", 1, 2LL, 3); snprintf (expected, sizeof (expected), "%3$d %2$lld %1$d", 1, 2LL, 3); grub_test_assert (strcmp (real, expected) == 0); }
static int grub_biosdisk_call_hook (int (*hook) (const char *name), int drive) { char name[10]; grub_snprintf (name, sizeof (name), (drive & 0x80) ? "hd%d" : "fd%d", drive & (~0x80)); return hook (name); }
static int grub_efidisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, grub_disk_pull_t pull) { struct grub_efidisk_data *d; char buf[16]; int count; switch (pull) { case GRUB_DISK_PULL_NONE: for (d = hd_devices, count = 0; d; d = d->next, count++) { grub_snprintf (buf, sizeof (buf), "hd%d", count); grub_dprintf ("efidisk", "iterating %s\n", buf); if (hook (buf, hook_data)) return 1; } break; case GRUB_DISK_PULL_REMOVABLE: for (d = fd_devices, count = 0; d; d = d->next, count++) { grub_snprintf (buf, sizeof (buf), "fd%d", count); grub_dprintf ("efidisk", "iterating %s\n", buf); if (hook (buf, hook_data)) return 1; } for (d = cd_devices, count = 0; d; d = d->next, count++) { grub_snprintf (buf, sizeof (buf), "cd%d", count); grub_dprintf ("efidisk", "iterating %s\n", buf); if (hook (buf, hook_data)) return 1; } break; default: return 0; } return 0; }
static inline void save_number(const char *fmt, int number, int len) { if (len < 30) len = 30; /* actually log10(MAX_INT)+1 */ get_space((unsigned) len + 1); (void) grub_snprintf(out_buff + out_used, len + 1, fmt, number); out_used += grub_strlen(out_buff + out_used); }
/* Set current timeout in the variable "timeout". */ void grub_menu_set_timeout (int timeout) { /* Ignore TIMEOUT if it is zero, because it will be unset really soon. */ if (timeout > 0) { char buf[16]; grub_snprintf (buf, sizeof (buf), "%d", timeout); grub_env_set ("timeout", buf); } }
static inline void save_text(const char *fmt, const char *s, int len) { grub_size_t s_len = grub_strlen(s); if (len > (int) s_len) s_len = len; get_space(s_len + 1); (void) grub_snprintf(out_buff + out_used, s_len + 1, fmt, s); out_used += grub_strlen(out_buff + out_used); }
static grub_err_t card_open (const struct grub_net_card *dev) { int status; struct grub_ofnetcard_data *data = dev->data; char path[grub_strlen (data->path) + grub_strlen (":speed=auto,duplex=auto,1.1.1.1,dummy,1.1.1.1,1.1.1.1,5,5,1.1.1.1,512") + 1]; /* The full string will prevent a bootp packet to be sent. Just put some valid ip in there. */ grub_snprintf (path, sizeof (path), "%s%s", data->path, ":speed=auto,duplex=auto,1.1.1.1,dummy,1.1.1.1,1.1.1.1,5,5,1.1.1.1,512"); status = grub_ieee1275_open (path, &(data->handle)); if (status) return grub_error (GRUB_ERR_IO, "Couldn't open network card."); return GRUB_ERR_NONE; }
static int grub_biosdisk_call_hook (int (*hook) (const char *name, void *closure), void *closure, int drive) { char name[10]; struct grub_biosdisk_data *data; data = get_drive_geom (drive); if (! data) return 0; grub_snprintf (name, sizeof (name), (drive & 0x80) ? "hd%d" : "fd%d", drive & (~0x80)); if (hook (name, closure)) return 1; if (drive == grub_boot_drive) { if (hook ("boot", closure)) return 1; } return 0; }
static grub_err_t grub_cmd_read (grub_extcmd_t cmd, int argc, char **argv) { grub_target_addr_t addr; grub_uint32_t value = 0; char buf[sizeof ("XXXXXXXX")]; if (argc != 1) return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid number of arguments"); addr = grub_strtoul (argv[0], 0, 0); switch (cmd->cmd->name[sizeof ("in") - 1]) { case 'l': value = grub_inl (addr); break; case 'w': value = grub_inw (addr); break; case 'b': value = grub_inb (addr); break; } if (cmd->state[0].set) { grub_snprintf (buf, sizeof (buf), "%x", value); grub_env_set (cmd->state[0].arg, buf); } else grub_printf ("0x%x\n", value); return 0; }
static grub_err_t grub_cmd_read (grub_extcmd_context_t ctxt, int argc, char **argv) { grub_addr_t addr; grub_uint32_t value = 0; char buf[sizeof ("XXXXXXXX")]; if (argc != 1) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); addr = grub_strtoul (argv[0], 0, 0); switch (ctxt->extcmd->cmd->name[sizeof ("read_") - 1]) { case 'd': value = *((volatile grub_uint32_t *) addr); break; case 'w': value = *((volatile grub_uint16_t *) addr); break; case 'b': value = *((volatile grub_uint8_t *) addr); break; } if (ctxt->state[0].set) { grub_snprintf (buf, sizeof (buf), "%x", value); grub_env_set (ctxt->state[0].arg, buf); } else grub_printf ("0x%x\n", value); return 0; }
static int NESTED_FUNC_ATTR grub_setpci_iter (grub_pci_device_t dev, grub_pci_id_t pciid) { grub_uint32_t regval = 0; grub_pci_address_t addr; if ((pciid & pciid_check_mask) != pciid_check_value) return 0; if (check_bus && grub_pci_get_bus (dev) != bus) return 0; if (check_device && grub_pci_get_device (dev) != device) return 0; if (check_function && grub_pci_get_function (dev) != function) return 0; addr = grub_pci_make_address (dev, regaddr); switch (regsize) { case 1: regval = grub_pci_read_byte (addr); break; case 2: regval = grub_pci_read_word (addr); break; case 4: regval = grub_pci_read (addr); break; } if (varname) { char buf[sizeof ("XXXXXXXX")]; grub_snprintf (buf, sizeof (buf), "%x", regval); grub_env_set (varname, buf); return 1; } if (!write_mask) { grub_printf ("Register %x of %d:%d.%d is %x\n", regaddr, grub_pci_get_bus (dev), grub_pci_get_device (dev), grub_pci_get_function (dev), regval); return 0; } regval = (regval & ~write_mask) | regwrite; switch (regsize) { case 1: grub_pci_write_byte (addr, regval); break; case 2: grub_pci_write_word (addr, regval); break; case 4: grub_pci_write (addr, regval); break; } 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; 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); } }
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); } }
static void set_position (grub_uitree_t root, grub_uitree_t node) { char buf[12], *p, *pos; grub_widget_t screen, widget; int v; int horizontal; int right, bottom; pos = grub_uitree_get_prop (grub_widget_current_node->parent, "popup"); if (! pos) pos = ""; else if (! grub_strcmp (pos, "abs")) return; horizontal = 0; p = grub_uitree_get_prop (grub_widget_current_node->parent, "direction"); if ((p) && ((! grub_strcmp (p, "left_to_right")) || (! grub_strcmp (p, "right_to_left")))) horizontal = 1; screen = root->data; widget = grub_widget_current_node->data; right = (horizontal) ? -1 : (widget->org_x * 2 + widget->width <= screen->width); if (! grub_strcmp (pos, "right")) right = 1; else if (! grub_strcmp (pos, "left")) right = 0; if (right == 0) { p = "attach_right"; v = screen->width - widget->org_x; } else { p = "attach_left"; v = widget->org_x; if (right > 0) v += widget->width; } grub_snprintf (buf, sizeof (buf), "%d/%d", v, v); grub_uitree_set_prop (node, p, buf); bottom = (! horizontal) ? -1 : (widget->org_y * 2 + widget->height <= screen->height); if (! grub_strcmp (pos, "bottom")) bottom = 1; else if (! grub_strcmp (pos, "top")) bottom = 0; if (bottom == 0) { p = "attach_bottom"; v = screen->height - widget->org_y; } else { p = "attach_top"; v = widget->org_y; if (bottom > 0) v += widget->height; } grub_snprintf (buf, sizeof (buf), "%d/%d", v, v); grub_uitree_set_prop (node, p, buf); }
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; } }
/* Execute a single command line. */ grub_err_t grub_script_execute_cmdline (struct grub_script_cmd *cmd) { struct grub_script_cmdline *cmdline = (struct grub_script_cmdline *) cmd; struct grub_script_arglist *arglist; char **args = 0; int i = 0; grub_command_t grubcmd; grub_err_t ret = 0; int argcount = 0; grub_script_function_t func = 0; char errnobuf[18]; char *cmdname; /* Lookup the command. */ cmdname = grub_script_execute_argument_to_string (cmdline->arglist->arg); grubcmd = grub_command_find (cmdname); if (! grubcmd) { grub_errno = GRUB_ERR_NONE; /* It's not a GRUB command, try all functions. */ func = grub_script_function_find (cmdname); if (! func) { /* As a last resort, try if it is an assignment. */ char *assign = grub_strdup (cmdname); char *eq = grub_strchr (assign, '='); if (eq) { /* This was set because the command was not found. */ grub_errno = GRUB_ERR_NONE; /* Create two strings and set the variable. */ *eq = '\0'; eq++; grub_env_set (assign, eq); } grub_free (assign); grub_snprintf (errnobuf, sizeof (errnobuf), "%d", grub_errno); grub_env_set ("?", errnobuf); grub_print_error (); return 0; } } grub_free (cmdname); if (cmdline->arglist->next) { argcount = cmdline->arglist->argcount - 1; /* Create argv from the arguments. */ args = grub_malloc (sizeof (char *) * argcount); for (arglist = cmdline->arglist->next; arglist; arglist = arglist->next) { char *str; str = grub_script_execute_argument_to_string (arglist->arg); args[i++] = str; } } /* Execute the GRUB command or function. */ if (grubcmd) ret = (grubcmd->func) (grubcmd, argcount, args); else ret = grub_script_function_call (func, argcount, args); /* Free arguments. */ for (i = 0; i < argcount; i++) grub_free (args[i]); grub_free (args); if (grub_errno == GRUB_ERR_TEST_FAILURE) grub_errno = GRUB_ERR_NONE; grub_print_error (); grub_snprintf (errnobuf, sizeof (errnobuf), "%d", ret); grub_env_set ("?", errnobuf); return ret; }
/* Helper for grub_ls_list_files. */ static int print_files_long (const char *filename, const struct grub_dirhook_info *info, void *data) { struct grub_ls_list_files_ctx *ctx = data; if ((! ctx->all) && (filename[0] == '.')) return 0; if (! info->dir) { grub_file_t file; char *pathname; if (ctx->dirname[grub_strlen (ctx->dirname) - 1] == '/') pathname = grub_xasprintf ("%s%s", ctx->dirname, filename); else pathname = grub_xasprintf ("%s/%s", ctx->dirname, filename); if (!pathname) return 1; /* XXX: For ext2fs symlinks are detected as files while they should be reported as directories. */ grub_file_filter_disable_compression (); file = grub_file_open (pathname); if (! file) { grub_errno = 0; grub_free (pathname); return 0; } if (! ctx->human) grub_printf ("%-12llu", (unsigned long long) file->size); else { grub_uint64_t fsize = file->size * 100ULL; grub_uint64_t fsz = file->size; int units = 0; char buf[20]; while (fsz / 1024) { fsize = (fsize + 512) / 1024; fsz /= 1024; units++; } if (units) { grub_uint64_t whole, fraction; whole = grub_divmod64 (fsize, 100, &fraction); grub_snprintf (buf, sizeof (buf), "%" PRIuGRUB_UINT64_T ".%02" PRIuGRUB_UINT64_T "%c", whole, fraction, grub_human_sizes[units]); grub_printf ("%-12s", buf); } else grub_printf ("%-12llu", (unsigned long long) file->size); } grub_file_close (file); grub_free (pathname); } else grub_printf ("%-12s", _("DIR")); if (info->mtimeset) { struct grub_datetime datetime; grub_unixtime2datetime (info->mtime, &datetime); if (ctx->human) grub_printf (" %d-%02d-%02d %02d:%02d:%02d %-11s ", datetime.year, datetime.month, datetime.day, datetime.hour, datetime.minute, datetime.second, grub_get_weekday_name (&datetime)); else grub_printf (" %04d%02d%02d%02d%02d%02d ", datetime.year, datetime.month, datetime.day, datetime.hour, datetime.minute, datetime.second); } grub_printf ("%s%s\n", filename, info->dir ? "/" : ""); return 0; }
struct grub_net_network_level_interface * grub_net_configure_by_dhcp_ack (const char *name, struct grub_net_card *card, grub_net_interface_flags_t flags, const struct grub_net_bootp_packet *bp, grub_size_t size, int is_def, char **device, char **path) { grub_net_network_level_address_t addr; grub_net_link_level_address_t hwaddr; struct grub_net_network_level_interface *inter; int mask = -1; char server_ip[sizeof ("xxx.xxx.xxx.xxx")]; addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; addr.ipv4 = bp->your_ip; if (device) *device = 0; if (path) *path = 0; grub_memcpy (hwaddr.mac, bp->mac_addr, bp->hw_len < sizeof (hwaddr.mac) ? bp->hw_len : sizeof (hwaddr.mac)); hwaddr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; inter = grub_net_add_addr (name, card, &addr, &hwaddr, flags); if (!inter) return 0; #if 0 /* This is likely based on misunderstanding. gateway_ip refers to address of BOOTP relay and should not be used after BOOTP transaction is complete. See RFC1542, 3.4 Interpretation of the 'giaddr' field */ if (bp->gateway_ip) { grub_net_network_level_netaddress_t target; grub_net_network_level_address_t gw; char *rname; target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; target.ipv4.base = bp->server_ip; target.ipv4.masksize = 32; gw.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; gw.ipv4 = bp->gateway_ip; rname = grub_xasprintf ("%s:gw", name); if (rname) grub_net_add_route_gw (rname, target, gw); grub_free (rname); target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; target.ipv4.base = bp->gateway_ip; target.ipv4.masksize = 32; grub_net_add_route (name, target, inter); } #endif if (size > OFFSET_OF (boot_file, bp)) grub_env_set_net_property (name, "boot_file", bp->boot_file, sizeof (bp->boot_file)); if (bp->server_ip) { grub_snprintf (server_ip, sizeof (server_ip), "%d.%d.%d.%d", ((grub_uint8_t *) &bp->server_ip)[0], ((grub_uint8_t *) &bp->server_ip)[1], ((grub_uint8_t *) &bp->server_ip)[2], ((grub_uint8_t *) &bp->server_ip)[3]); grub_env_set_net_property (name, "next_server", server_ip, sizeof (server_ip)); grub_print_error (); } if (is_def) grub_net_default_server = 0; if (is_def && !grub_net_default_server && bp->server_ip) { grub_net_default_server = grub_strdup (server_ip); grub_print_error (); } if (is_def) { grub_env_set ("net_default_interface", name); grub_env_export ("net_default_interface"); } if (device && !*device && bp->server_ip) { *device = grub_xasprintf ("tftp,%s", server_ip); grub_print_error (); } if (size > OFFSET_OF (server_name, bp) && bp->server_name[0]) { grub_env_set_net_property (name, "dhcp_server_name", bp->server_name, sizeof (bp->server_name)); if (is_def && !grub_net_default_server) { grub_net_default_server = grub_strdup (bp->server_name); grub_print_error (); } if (device && !*device) { *device = grub_xasprintf ("tftp,%s", bp->server_name); grub_print_error (); } } if (size > OFFSET_OF (boot_file, bp) && path) { *path = grub_strndup (bp->boot_file, sizeof (bp->boot_file)); grub_print_error (); if (*path) { char *slash; slash = grub_strrchr (*path, '/'); if (slash) *slash = 0; else **path = 0; } } if (size > OFFSET_OF (vendor, bp)) parse_dhcp_vendor (name, &bp->vendor, size - OFFSET_OF (vendor, bp), &mask); grub_net_add_ipv4_local (inter, mask); inter->dhcp_ack = grub_malloc (size); if (inter->dhcp_ack) { grub_memcpy (inter->dhcp_ack, bp, size); inter->dhcp_acklen = size; } else grub_errno = GRUB_ERR_NONE; return inter; }
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); }
static grub_err_t prepare_xen_module_params (struct xen_boot_binary *module, void *xen_boot_fdt) { int retval, chosen_node = 0, module_node = 0; char module_name[FDT_NODE_NAME_MAX_SIZE]; retval = grub_snprintf (module_name, FDT_NODE_NAME_MAX_SIZE, "module@%lx", xen_boot_address_align (module->start, module->align)); grub_dprintf ("xen_loader", "Module node name %s \n", module_name); if (retval < (int) sizeof ("module@")) return grub_error (GRUB_ERR_IO, N_("failed to get FDT")); chosen_node = grub_fdt_find_subnode (xen_boot_fdt, 0, "chosen"); if (chosen_node < 0) chosen_node = grub_fdt_add_subnode (xen_boot_fdt, 0, "chosen"); if (chosen_node < 1) return grub_error (GRUB_ERR_IO, "failed to get chosen node in FDT"); module_node = grub_fdt_find_subnode (xen_boot_fdt, chosen_node, module_name); if (module_node < 0) module_node = grub_fdt_add_subnode (xen_boot_fdt, chosen_node, module_name); retval = grub_fdt_set_prop (xen_boot_fdt, module_node, "compatible", module->node_info.compat_string, (grub_uint32_t) module-> node_info.compat_string_size); if (retval) return grub_error (GRUB_ERR_IO, "failed to update FDT"); grub_dprintf ("xen_loader", "Module %s compatible = %s size = 0x%lx\n", module->name, module->node_info.compat_string, module->node_info.compat_string_size); retval = grub_fdt_set_reg64 (xen_boot_fdt, module_node, xen_boot_address_align (module->start, module->align), module->size); if (retval) return grub_error (GRUB_ERR_IO, "failed to update FDT"); if (module->cmdline && module->cmdline_size > 0) { grub_dprintf ("xen_loader", "Module %s cmdline : %s @ %p size:%d\n", module->name, module->cmdline, module->cmdline, module->cmdline_size); retval = grub_fdt_set_prop (xen_boot_fdt, module_node, "bootargs", module->cmdline, module->cmdline_size + 1); if (retval) return grub_error (GRUB_ERR_IO, "failed to update FDT"); } else { grub_dprintf ("xen_loader", "Module %s has not bootargs!\n", module->name); } return GRUB_ERR_NONE; }
static grub_err_t grub_ls_list_files (char *dirname, int longlist, int all, int human) { char *device_name; grub_fs_t fs; const char *path; grub_device_t dev; auto int print_files (const char *filename, const struct grub_dirhook_info *info); auto int print_files_long (const char *filename, const struct grub_dirhook_info *info); int print_files (const char *filename, const struct grub_dirhook_info *info) { if (all || filename[0] != '.') grub_printf ("%s%s ", filename, info->dir ? "/" : ""); return 0; } int print_files_long (const char *filename, const struct grub_dirhook_info *info) { if ((! all) && (filename[0] == '.')) return 0; if (! info->dir) { grub_file_t file; char *pathname; if (dirname[grub_strlen (dirname) - 1] == '/') pathname = grub_xasprintf ("%s%s", dirname, filename); else pathname = grub_xasprintf ("%s/%s", dirname, filename); if (!pathname) return 1; /* XXX: For ext2fs symlinks are detected as files while they should be reported as directories. */ grub_file_filter_disable_compression (); file = grub_file_open (pathname); if (! file) { grub_errno = 0; grub_free (pathname); return 0; } if (! human) grub_printf ("%-12llu", (unsigned long long) file->size); else { grub_uint64_t fsize = file->size * 100ULL; grub_uint64_t fsz = file->size; int units = 0; char buf[20]; while (fsz / 1024) { fsize = (fsize + 512) / 1024; fsz /= 1024; units++; } if (units) { grub_uint64_t whole, fraction; whole = grub_divmod64 (fsize, 100, &fraction); grub_snprintf (buf, sizeof (buf), "%" PRIuGRUB_UINT64_T ".%02" PRIuGRUB_UINT64_T "%c", whole, fraction, grub_human_sizes[units]); grub_printf ("%-12s", buf); } else grub_printf ("%-12llu", (unsigned long long) file->size); } grub_file_close (file); grub_free (pathname); } else grub_printf ("%-12s", _("DIR")); if (info->mtimeset) { struct grub_datetime datetime; grub_unixtime2datetime (info->mtime, &datetime); if (human) grub_printf (" %d-%02d-%02d %02d:%02d:%02d %-11s ", datetime.year, datetime.month, datetime.day, datetime.hour, datetime.minute, datetime.second, grub_get_weekday_name (&datetime)); else grub_printf (" %04d%02d%02d%02d%02d%02d ", datetime.year, datetime.month, datetime.day, datetime.hour, datetime.minute, datetime.second); } grub_printf ("%s%s\n", filename, info->dir ? "/" : ""); return 0; } device_name = grub_file_get_device_name (dirname); dev = grub_device_open (device_name); if (! dev) goto fail; fs = grub_fs_probe (dev); path = grub_strchr (dirname, ')'); if (! path) path = dirname; else path++; if (! path && ! device_name) { grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid argument"); goto fail; } if (! *path) { if (grub_errno == GRUB_ERR_UNKNOWN_FS) grub_errno = GRUB_ERR_NONE; grub_normal_print_device_info (device_name); } else if (fs) { if (longlist) (fs->dir) (dev, path, print_files_long); else (fs->dir) (dev, path, print_files); if (grub_errno == GRUB_ERR_BAD_FILE_TYPE && path[grub_strlen (path) - 1] != '/') { /* PATH might be a regular file. */ char *p; grub_file_t file; struct grub_dirhook_info info; grub_errno = 0; grub_file_filter_disable_compression (); file = grub_file_open (dirname); if (! file) goto fail; grub_file_close (file); p = grub_strrchr (dirname, '/') + 1; dirname = grub_strndup (dirname, p - dirname); if (! dirname) goto fail; all = 1; grub_memset (&info, 0, sizeof (info)); if (longlist) print_files_long (p, &info); else print_files (p, &info); grub_free (dirname); } if (grub_errno == GRUB_ERR_NONE) grub_xputs ("\n"); grub_refresh (); } fail: if (dev) grub_device_close (dev); grub_free (device_name); return 0; }