/* Translate an OF filesystem path (separated by backslashes), into a GRUB path (separated by forward slashes). */ static void grub_translate_ieee1275_path (char *filepath) { char *backslash; backslash = grub_strchr (filepath, '\\'); while (backslash != 0) { *backslash = '/'; backslash = grub_strchr (filepath, '\\'); } }
void grub_machine_init (void) { char args[256]; grub_ssize_t actual; grub_ieee1275_init (); grub_console_init_early (); #ifdef __i386__ grub_get_extended_memory (); #endif grub_claim_heap (); grub_console_init_lately (); grub_ofdisk_init (); /* Process commandline. */ if (grub_ieee1275_get_property (grub_ieee1275_chosen, "bootargs", &args, sizeof args, &actual) == 0 && actual > 1) { int i = 0; while (i < actual) { char *command = &args[i]; char *end; char *val; end = grub_strchr (command, ';'); if (end == 0) i = actual; /* No more commands after this one. */ else { *end = '\0'; i += end - command + 1; while (grub_isspace(args[i])) i++; } /* Process command. */ val = grub_strchr (command, '='); if (val) { *val = '\0'; grub_env_set (command, val + 1); } } } grub_install_get_time_ms (ieee1275_get_time_ms); }
static grub_err_t grub_rescue_parse_line (char *line, grub_reader_getline_t getline, void *closure) { char *name; int n; grub_command_t cmd; char **args; if (grub_parser_split_cmdline (line, getline, closure, &n, &args) || n < 0) return grub_errno; if (n == 0) return GRUB_ERR_NONE; /* In case of an assignment set the environment accordingly instead of calling a function. */ if (n == 1 && grub_strchr (line, '=')) { char *val = grub_strchr (args[0], '='); val[0] = 0; grub_env_set (args[0], val + 1); val[0] = '='; goto quit; } /* Get the command name. */ name = args[0]; /* If nothing is specified, restart. */ if (*name == '\0') goto quit; cmd = grub_command_find (name); if (cmd) { (cmd->func) (cmd, n - 1, &args[1]); } else { grub_printf ("Unknown command `%s'\n", name); if (grub_command_find ("help")) grub_printf ("Try `help' for usage\n"); } quit: grub_free (args[0]); grub_free (args); return grub_errno; }
/* Get the device path of the Open Firmware node name `path'. */ static char * grub_ieee1275_get_devname (const char *path) { char *colon = grub_strchr (path, ':'); char *newpath = 0; int pathlen = grub_strlen (path); auto int match_alias (struct grub_ieee1275_devalias *alias); int match_alias (struct grub_ieee1275_devalias *curalias) { /* briQ firmware can change capitalization in /chosen/bootpath. */ if (! grub_strncasecmp (curalias->path, path, pathlen)) { newpath = grub_strdup (curalias->name); return 1; } return 0; } if (colon) pathlen = (int)(colon - path); /* Try to find an alias for this device. */ grub_devalias_iterate (match_alias); if (! newpath) newpath = grub_strndup (path, pathlen); return newpath; }
/* Helper for match_devices. */ static int match_devices_iter (const char *name, void *data) { struct match_devices_ctx *ctx = data; char **t; char *buffer; /* skip partitions if asked to. */ if (ctx->noparts && grub_strchr (name, ',')) return 0; buffer = grub_xasprintf ("(%s)", name); if (! buffer) return 1; grub_dprintf ("expand", "matching: %s\n", buffer); if (regexec (ctx->regexp, buffer, 0, 0, 0)) { grub_dprintf ("expand", "not matched\n"); grub_free (buffer); return 0; } t = grub_realloc (ctx->devs, sizeof (char*) * (ctx->ndev + 2)); if (! t) { grub_free (buffer); return 1; } ctx->devs = t; ctx->devs[ctx->ndev++] = buffer; ctx->devs[ctx->ndev] = 0; return 0; }
/* Construct a new box widget using ABSPATTERN to find the pixmap files for it, storing the new box instance at *BOXPTR. PATTERN should be of the form: "(hd0,0)/somewhere/style*.png". The '*' then gets substituted with the various pixmap names that the box uses. */ static grub_err_t recreate_box_absolute (grub_gfxmenu_box_t *boxptr, const char *abspattern) { char *prefix; char *suffix; char *star; grub_gfxmenu_box_t box; star = grub_strchr (abspattern, '*'); if (! star) return grub_error (GRUB_ERR_BAD_ARGUMENT, "missing `*' in box pixmap pattern `%s'", abspattern); /* Prefix: Get the part before the '*'. */ prefix = grub_malloc (star - abspattern + 1); if (! prefix) return grub_errno; grub_memcpy (prefix, abspattern, star - abspattern); prefix[star - abspattern] = '\0'; /* Suffix: Everything after the '*' is the suffix. */ suffix = star + 1; box = grub_gfxmenu_create_box (prefix, suffix); grub_free (prefix); if (! box) return grub_errno; if (*boxptr) (*boxptr)->destroy (*boxptr); *boxptr = box; return grub_errno; }
grub_err_t grub_rescue_parse_line (char *line, grub_reader_getline_t getline, void *getline_data) { char *name; int n; grub_command_t cmd; char **args; if (grub_parser_split_cmdline (line, getline, getline_data, &n, &args) || n < 0) return grub_errno; if (n == 0) return GRUB_ERR_NONE; /* In case of an assignment set the environment accordingly instead of calling a function. */ if (n == 1) { char *val = grub_strchr (args[0], '='); if (val) { val[0] = 0; grub_env_set (args[0], val + 1); val[0] = '='; goto quit; } } /* Get the command name. */ name = args[0]; /* If nothing is specified, restart. */ if (*name == '\0') goto quit; cmd = grub_command_find (name); if (cmd) { (cmd->func) (cmd, n - 1, &args[1]); } else { grub_printf_ (N_("Unknown command `%s'.\n"), name); if (grub_command_find ("help")) grub_printf ("Try `help' for usage\n"); } quit: /* Arguments are returned in single memory chunk separated by zeroes */ grub_free (args[0]); grub_free (args); return grub_errno; }
/* Get the device arguments of the Open Firmware node name `path'. */ static char * grub_ieee1275_get_devargs (const char *path) { char *colon = grub_strchr (path, ':'); if (! colon) return 0; return grub_strdup (colon + 1); }
grub_command_t grub_command_find (char *cmdline) { char *first_space; grub_command_t cmd; int count = 0; first_space = grub_strchr (cmdline, ' '); if (first_space) *first_space = '\0'; again: for (cmd = grub_command_list; cmd; cmd = cmd->next) if (grub_strcmp (cmdline, cmd->name) == 0) break; if (! cmd) grub_error (GRUB_ERR_UNKNOWN_COMMAND, "unknown command `%s'", cmdline); else if (cmd->flags & GRUB_COMMAND_FLAG_NOT_LOADED) { /* Automatically load the command. */ if (count == 0) { grub_dl_t mod; char *module_name; module_name = grub_strdup (cmd->module_name); if (module_name) { mod = grub_dl_load (module_name); if (mod) { grub_dl_ref (mod); count++; grub_free (module_name); goto again; } grub_free (module_name); } } /* This module seems broken. */ grub_unregister_command (cmdline); grub_error (GRUB_ERR_UNKNOWN_COMMAND, "unknown command `%s'", cmdline); cmd = 0; } if (first_space) *first_space = ' '; return cmd; }
static void grub_parse_cmdline (void) { grub_ssize_t actual; char args[256]; if (grub_ieee1275_get_property (grub_ieee1275_chosen, "bootargs", &args, sizeof args, &actual) == 0 && actual > 1) { int i = 0; while (i < actual) { char *command = &args[i]; char *end; char *val; end = grub_strchr (command, ';'); if (end == 0) i = actual; /* No more commands after this one. */ else { *end = '\0'; i += end - command + 1; while (grub_isspace(args[i])) i++; } /* Process command. */ val = grub_strchr (command, '='); if (val) { *val = '\0'; grub_env_set (command, val + 1); } } } }
char * grub_menu_next_field (char *name, char c) { char *p; p = grub_strchr (name, c); if (p) { *(p++) = '\0'; } return p; }
static grub_err_t grub_cmd_next (grub_extcmd_context_t ctxt, int argc, char **args) { struct grub_arg_list *state = ctxt->state; char *p, *root = NULL, *part_name = NULL, *part_guid = NULL; /* TODO: Add a uuid parser and a command line flag for providing type. */ grub_gpt_part_type_t part_type = GRUB_GPT_PARTITION_TYPE_USR_X86_64; if (!state[NEXT_SET_DEVICE].set || !state[NEXT_SET_UUID].set) { grub_error (GRUB_ERR_INVALID_COMMAND, N_("-d and -u are required")); goto done; } if (argc == 0) root = grub_strdup (grub_env_get ("root")); else if (argc == 1) root = grub_strdup (args[0]); else { grub_error (GRUB_ERR_BAD_ARGUMENT, N_("unexpected arguments")); goto done; } if (!root) goto done; /* To make using $root practical strip off the partition name. */ p = grub_strchr (root, ','); if (p) *p = '\0'; if (grub_find_next (root, &part_type, &part_name, &part_guid)) goto done; if (grub_env_set (state[NEXT_SET_DEVICE].arg, part_name)) goto done; if (grub_env_set (state[NEXT_SET_UUID].arg, part_guid)) goto done; grub_errno = GRUB_ERR_NONE; done: grub_free (root); grub_free (part_name); grub_free (part_guid); return grub_errno; }
grub_autolist_t grub_autolist_load (const char *name) { grub_autolist_t result = 0; const char *prefix; prefix = grub_env_get ("prefix"); if (prefix) { char *filename; filename = grub_xasprintf ("%s/%s", prefix, name); if (filename) { grub_file_t file; file = grub_file_open (filename); if (file) { char *buf = NULL; for (;; grub_free (buf)) { char *p; buf = grub_getline (file); if (! buf) break; if (! grub_isgraph (buf[0])) continue; p = grub_strchr (buf, ':'); if (! p) continue; *p = '\0'; while (*++p == ' ') ; insert_item (&result, buf, p); } grub_file_close (file); } grub_free (filename); } } return result; }
int grub_parse_color_name_pair (grub_uint8_t *color, const char *name) { int result = 1; grub_uint8_t fg, bg; char *fg_name, *bg_name; /* nothing specified by user */ if (name == NULL) return result; fg_name = grub_strdup (name); if (fg_name == NULL) { /* "out of memory" message was printed by grub_strdup() */ grub_wait_after_message (); return result; } bg_name = grub_strchr (fg_name, '/'); if (bg_name == NULL) { grub_printf_ (N_("Warning: syntax error (missing slash) in `%s'\n"), fg_name); grub_wait_after_message (); goto free_and_return; } *(bg_name++) = '\0'; if (parse_color_name (&fg, fg_name) == -1) { grub_printf_ (N_("Warning: invalid foreground color `%s'\n"), fg_name); grub_wait_after_message (); goto free_and_return; } if (parse_color_name (&bg, bg_name) == -1) { grub_printf_ (N_("Warning: invalid background color `%s'\n"), bg_name); grub_wait_after_message (); goto free_and_return; } *color = (bg << 4) | fg; result = 0; free_and_return: grub_free (fg_name); return result; }
static grub_err_t grub_gettext_init_ext (struct grub_gettext_context *ctx, const char *locale, const char *locale_dir, const char *prefix) { const char *part1, *part2; grub_err_t err; grub_gettext_delete_list (ctx); if (!locale || locale[0] == 0) return 0; part1 = locale_dir; part2 = ""; if (!part1 || part1[0] == 0) { part1 = prefix; part2 = "/locale"; } if (!part1 || part1[0] == 0) return 0; err = grub_mofile_open_lang (ctx, part1, part2, locale); /* ll_CC didn't work, so try ll. */ if (err) { char *lang = grub_strdup (locale); char *underscore = lang ? grub_strchr (lang, '_') : 0; if (underscore) { *underscore = '\0'; grub_errno = GRUB_ERR_NONE; err = grub_mofile_open_lang (ctx, part1, part2, lang); } grub_free (lang); } if (locale[0] == 'e' && locale[1] == 'n' && (locale[2] == '\0' || locale[2] == '_')) grub_errno = err = GRUB_ERR_NONE; return err; }
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; }
void grub_machine_set_prefix (void) { if (grub_prefix[0] != '(') { char bootpath[IEEE1275_MAX_PATH_LEN]; char *prefix, *path, *colon; grub_ssize_t actual; if (grub_ieee1275_get_property (grub_ieee1275_chosen, "bootpath", &bootpath, sizeof (bootpath), &actual)) { /* Should never happen. */ grub_printf ("/chosen/bootpath property missing!\n"); grub_env_set ("prefix", ""); return; } /* Transform an OF device path to a GRUB path. */ colon = grub_strchr (bootpath, ':'); if (colon) { char *part = colon + 1; /* Consistently provide numbered partitions to GRUB. OpenBOOT traditionally uses alphabetical partition specifiers. */ if (part[0] >= 'a' && part[0] <= 'z') part[0] = '1' + (part[0] - 'a'); } prefix = grub_ieee1275_encode_devname (bootpath); path = grub_xasprintf("%s%s", prefix, grub_prefix); grub_strcpy (grub_prefix, path); grub_free (path); grub_free (prefix); } grub_env_set ("prefix", grub_prefix); }
/* Get the device path of the Open Firmware node name `path'. */ static char * grub_ieee1275_get_devname (const char *path) { char *colon = grub_strchr (path, ':'); struct grub_ieee1275_get_devname_closure c; c.path = path; c.newpath = 0; c.pathlen = grub_strlen (path); if (colon) c.pathlen = (int)(colon - path); /* Try to find an alias for this device. */ grub_devalias_iterate (match_alias, &c); if (! c.newpath) c.newpath = grub_strndup (path, c.pathlen); return c.newpath; }
/* Helper for grub_parser_execute. */ static grub_err_t grub_parser_execute_getline (char **line, int cont __attribute__ ((unused)), void *data) { char **source = data; char *p; if (!*source) { *line = 0; return 0; } p = grub_strchr (*source, '\n'); if (p) *line = grub_strndup (*source, p - *source); else *line = grub_strdup (*source); *source = p ? p + 1 : 0; return 0; }
/* Load all loadable kexts placed under DIRNAME and matching OSBUNDLEREQUIRED */ grub_err_t grub_xnu_scan_dir_for_kexts (char *dirname, char *osbundlerequired, int maxrecursion) { grub_device_t dev; char *device_name; grub_fs_t fs; const char *path; if (! grub_xnu_heap_size) return grub_error (GRUB_ERR_BAD_OS, "no xnu kernel loaded"); device_name = grub_file_get_device_name (dirname); dev = grub_device_open (device_name); if (dev) { struct grub_xnu_scan_dir_for_kexts_closure c; fs = grub_fs_probe (dev); path = grub_strchr (dirname, ')'); if (! path) path = dirname; else path++; c.dirname = dirname; c.osbundlerequired = osbundlerequired; c.maxrecursion = maxrecursion; if (fs) (fs->dir) (dev, path, grub_xnu_scan_dir_for_kexts_hook, 0); grub_device_close (dev); } grub_free (device_name); return GRUB_ERR_NONE; }
/* Print the information on the device NAME. */ grub_err_t grub_normal_print_device_info (const char *name) { grub_device_t dev; char *p; p = grub_strchr (name, ','); if (p) { grub_xputs ("\t"); grub_printf_ (N_("Partition %s:"), name); grub_xputs (" "); } else { grub_printf_ (N_("Device %s:"), name); grub_xputs (" "); } dev = grub_device_open (name); if (! dev) grub_printf ("%s", _("Filesystem cannot be accessed")); else if (dev->disk) { grub_fs_t fs; fs = grub_fs_probe (dev); /* Ignore all errors. */ grub_errno = 0; if (fs) { grub_printf_ (N_("Filesystem type %s"), fs->name); if (fs->label) { char *label; (fs->label) (dev, &label); if (grub_errno == GRUB_ERR_NONE) { if (label && grub_strlen (label)) { grub_xputs (" "); grub_printf_ (N_("- Label \"%s\""), label); } grub_free (label); } grub_errno = GRUB_ERR_NONE; } if (fs->mtime) { grub_int32_t tm; struct grub_datetime datetime; (fs->mtime) (dev, &tm); if (grub_errno == GRUB_ERR_NONE) { grub_unixtime2datetime (tm, &datetime); grub_xputs (" "); grub_printf_ (N_("- Last modification time %d-%02d-%02d " "%02d:%02d:%02d %s"), datetime.year, datetime.month, datetime.day, datetime.hour, datetime.minute, datetime.second, grub_get_weekday_name (&datetime)); } grub_errno = GRUB_ERR_NONE; } if (fs->uuid) { char *uuid; (fs->uuid) (dev, &uuid); if (grub_errno == GRUB_ERR_NONE) { if (uuid && grub_strlen (uuid)) grub_printf (", UUID %s", uuid); grub_free (uuid); } grub_errno = GRUB_ERR_NONE; } } else if (! dev->disk->has_partitions || dev->disk->partition) grub_printf ("%s", _("Unknown filesystem")); else grub_printf ("%s", _("Partition table")); grub_device_close (dev); } grub_xputs ("\n"); return grub_errno; }
/* Parse a test expression starting from *argn. */ static int test_parse (char **args, int *argn, int argc) { int ret = 0, discard = 0, invert = 0; int file_exists; struct grub_dirhook_info file_info; auto void update_val (int val); auto void get_fileinfo (char *pathname); /* Take care of discarding and inverting. */ void update_val (int val) { if (! discard) ret = invert ? ! val : val; invert = discard = 0; } /* Check if file exists and fetch its information. */ void get_fileinfo (char *path) { char *filename, *pathname; char *device_name; grub_fs_t fs; grub_device_t dev; /* A hook for iterating directories. */ auto int find_file (const char *cur_filename, const struct grub_dirhook_info *info); int find_file (const char *cur_filename, const struct grub_dirhook_info *info) { if ((info->case_insensitive ? grub_strcasecmp (cur_filename, filename) : grub_strcmp (cur_filename, filename)) == 0) { file_info = *info; file_exists = 1; return 1; } return 0; } file_exists = 0; device_name = grub_file_get_device_name (path); dev = grub_device_open (device_name); if (! dev) { grub_free (device_name); return; } fs = grub_fs_probe (dev); if (! fs) { grub_free (device_name); grub_device_close (dev); return; } pathname = grub_strchr (path, ')'); if (! pathname) pathname = path; else pathname++; /* Remove trailing '/'. */ while (*pathname && pathname[grub_strlen (pathname) - 1] == '/') pathname[grub_strlen (pathname) - 1] = 0; /* Split into path and filename. */ filename = grub_strrchr (pathname, '/'); if (! filename) { path = grub_strdup ("/"); filename = pathname; } else { filename++; path = grub_strdup (pathname); path[filename - pathname] = 0; } /* It's the whole device. */ if (! *pathname) { file_exists = 1; grub_memset (&file_info, 0, sizeof (file_info)); /* Root is always a directory. */ file_info.dir = 1; /* Fetch writing time. */ file_info.mtimeset = 0; if (fs->mtime) { if (! fs->mtime (dev, &file_info.mtime)) file_info.mtimeset = 1; grub_errno = GRUB_ERR_NONE; } } else (fs->dir) (dev, path, find_file); grub_device_close (dev); grub_free (path); grub_free (device_name); }
static grub_err_t grub_cmd_nativedisk (grub_command_t cmd __attribute__ ((unused)), int argc, char **args_in) { char *uuid_root = 0, *uuid_prefix, *prefdev = 0; const char *prefix = 0; const char *path_prefix = 0; int mods_loaded = 0; grub_dl_t *mods; const char **args; int i; if (argc == 0) { argc = ARRAY_SIZE (modnames_def); args = modnames_def; } else args = (const char **) args_in; prefix = grub_env_get ("prefix"); if (! prefix) return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("variable `%s' isn't set"), "prefix"); if (prefix) path_prefix = (prefix[0] == '(') ? grub_strchr (prefix, ')') : NULL; if (path_prefix) path_prefix++; else path_prefix = prefix; mods = grub_malloc (argc * sizeof (mods[0])); if (!mods) return grub_errno; if (get_uuid (NULL, &uuid_root, 0)) return grub_errno; prefdev = grub_file_get_device_name (prefix); if (grub_errno) { grub_print_error (); prefdev = 0; } if (get_uuid (prefdev, &uuid_prefix, 0)) { grub_free (uuid_root); return grub_errno; } grub_dprintf ("nativedisk", "uuid_prefix = %s, uuid_root = %s\n", uuid_prefix, uuid_root); for (mods_loaded = 0; mods_loaded < argc; mods_loaded++) { char *filename; grub_dl_t mod; grub_file_t file = NULL; grub_ssize_t size; void *core = 0; mod = grub_dl_get (args[mods_loaded]); if (mod) { mods[mods_loaded] = 0; continue; } filename = grub_xasprintf ("%s/" GRUB_TARGET_CPU "-" GRUB_PLATFORM "/%s.mod", prefix, args[mods_loaded]); if (! filename) goto fail; file = grub_file_open (filename); grub_free (filename); if (! file) goto fail; size = grub_file_size (file); core = grub_malloc (size); if (! core) { grub_file_close (file); goto fail; } if (grub_file_read (file, core, size) != (grub_ssize_t) size) { grub_file_close (file); grub_free (core); goto fail; } grub_file_close (file); mods[mods_loaded] = grub_dl_load_core_noinit (core, size); if (! mods[mods_loaded]) goto fail; } for (i = 0; i < argc; i++) if (mods[i]) grub_dl_init (mods[i]); if (uuid_prefix || uuid_root) { struct search_ctx ctx; grub_fs_autoload_hook_t saved_autoload; /* No need to autoload FS since obviously we already have the necessary fs modules. */ saved_autoload = grub_fs_autoload_hook; grub_fs_autoload_hook = 0; ctx.root_uuid = uuid_root; ctx.prefix_uuid = uuid_prefix; ctx.prefix_path = path_prefix; ctx.prefix_found = !uuid_prefix; ctx.root_found = !uuid_root; /* FIXME: try to guess the correct values. */ grub_device_iterate (iterate_device, &ctx); grub_fs_autoload_hook = saved_autoload; } grub_free (uuid_root); grub_free (uuid_prefix); return GRUB_ERR_NONE; fail: grub_free (uuid_root); grub_free (uuid_prefix); for (i = 0; i < mods_loaded; i++) if (mods[i]) { mods[i]->fini = 0; grub_dl_unload (mods[i]); } return grub_errno; }
/* Read the file crypto.lst for auto-loading. */ void read_crypto_list (const char *prefix) { char *filename; grub_file_t file; char *buf = NULL; if (!prefix) { grub_errno = GRUB_ERR_NONE; return; } filename = grub_xasprintf ("%s/" GRUB_TARGET_CPU "-" GRUB_PLATFORM "/crypto.lst", prefix); if (!filename) { grub_errno = GRUB_ERR_NONE; return; } file = grub_file_open (filename); grub_free (filename); if (!file) { grub_errno = GRUB_ERR_NONE; return; } /* Override previous crypto.lst. */ grub_crypto_spec_free (); for (;; grub_free (buf)) { char *p, *name; struct load_spec *cur; buf = grub_file_getline (file); if (! buf) break; name = buf; while (grub_isspace (name[0])) name++; p = grub_strchr (name, ':'); if (! p) continue; *p = '\0'; p++; while (*p == ' ' || *p == '\t') p++; cur = grub_malloc (sizeof (*cur)); if (!cur) { grub_errno = GRUB_ERR_NONE; continue; } cur->name = grub_strdup (name); if (! name) { grub_errno = GRUB_ERR_NONE; grub_free (cur); continue; } cur->modname = grub_strdup (p); if (! cur->modname) { grub_errno = GRUB_ERR_NONE; grub_free (cur); grub_free (cur->name); continue; } cur->next = crypto_specs; crypto_specs = cur; } grub_file_close (file); grub_errno = GRUB_ERR_NONE; grub_crypto_autoload_hook = grub_crypto_autoload; }
static char * grub_ieee1275_parse_args (const char *path, enum grub_ieee1275_parse_type ptype) { char type[64]; /* XXX check size. */ char *device = grub_ieee1275_get_devname (path); char *args = grub_ieee1275_get_devargs (path); char *ret = 0; grub_ieee1275_phandle_t dev; if (!args) /* Shouldn't happen. */ return 0; /* We need to know what type of device it is in order to parse the full file path properly. */ if (grub_ieee1275_finddevice (device, &dev)) { grub_error (GRUB_ERR_UNKNOWN_DEVICE, "Device %s not found\n", device); goto fail; } if (grub_ieee1275_get_property (dev, "device_type", &type, sizeof type, 0)) { grub_error (GRUB_ERR_UNKNOWN_DEVICE, "Device %s lacks a device_type property\n", device); goto fail; } if (!grub_strcmp ("block", type)) { /* The syntax of the device arguments is defined in the CHRP and PReP IEEE1275 bindings: "[partition][,[filename]]". */ char *comma = grub_strchr (args, ','); if (ptype == GRUB_PARSE_FILENAME) { if (comma) { char *filepath = comma + 1; ret = grub_malloc (grub_strlen (filepath) + 1); /* Make sure filepath has leading backslash. */ if (filepath[0] != '\\') grub_sprintf (ret, "\\%s", filepath); else grub_strcpy (ret, filepath); } } else if (ptype == GRUB_PARSE_PARTITION) { if (!comma) ret = grub_strdup (args); else ret = grub_strndup (args, (grub_size_t)(comma - args)); } } else { /* XXX Handle net devices by configuring & registering a grub_net_dev here, then return its name? Example path: "net:<server ip>,<file name>,<client ip>,<gateway ip>,<bootp retries>,<tftp retries>". */ grub_printf ("Unsupported type %s for device %s\n", type, device); } fail: grub_free (device); grub_free (args); return ret; }
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; 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) { struct grub_ls_list_files_ctx ctx = { .dirname = dirname, .all = all, .human = human }; if (longlist) (fs->dir) (dev, path, print_files_long, &ctx); else (fs->dir) (dev, path, print_files, &ctx); 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, &ctx); else print_files (p, &info, &ctx); 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; }
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; } }
/* Load extension DIRNAME. (extensions are directories in xnu) */ grub_err_t grub_xnu_load_kext_from_dir (char *dirname, char *osbundlerequired, int maxrecursion) { grub_device_t dev; char *newdirname; char *newpath; char *device_name; grub_fs_t fs; const char *path; char *binsuffix; grub_file_t binfile; newdirname = grub_malloc (grub_strlen (dirname) + 20); if (! newdirname) return grub_error (GRUB_ERR_OUT_OF_MEMORY, "couldn't allocate buffer"); grub_strcpy (newdirname, dirname); newdirname[grub_strlen (dirname)] = '/'; newdirname[grub_strlen (dirname) + 1] = 0; device_name = grub_file_get_device_name (dirname); dev = grub_device_open (device_name); if (dev) { struct grub_xnu_load_kext_from_dir_closure c; fs = grub_fs_probe (dev); path = grub_strchr (dirname, ')'); if (! path) path = dirname; else path++; newpath = grub_strchr (newdirname, ')'); if (! newpath) newpath = newdirname; else newpath++; c.dirname = dirname; c.osbundlerequired = osbundlerequired; c.maxrecursion = maxrecursion; c.usemacos = 0; c.plistname = 0; c.newdirname = newdirname; /* Look at the directory. */ if (fs) (fs->dir) (dev, path, grub_xnu_load_kext_from_dir_hook, &c); if (c.plistname && grub_xnu_check_os_bundle_required (c.plistname, osbundlerequired, &binsuffix)) { if (binsuffix) { /* Open the binary. */ char *binname = grub_malloc (grub_strlen (dirname) + grub_strlen (binsuffix) + sizeof ("/MacOS/")); grub_strcpy (binname, dirname); if (c.usemacos) grub_strcpy (binname + grub_strlen (binname), "/MacOS/"); else grub_strcpy (binname + grub_strlen (binname), "/"); grub_strcpy (binname + grub_strlen (binname), binsuffix); grub_dprintf ("xnu", "%s:%s\n", c.plistname, binname); binfile = grub_gzfile_open (binname, 1); if (! binfile) grub_errno = GRUB_ERR_NONE; /* Load the extension. */ grub_xnu_load_driver (c.plistname, binfile); grub_free (binname); grub_free (binsuffix); } else { grub_dprintf ("xnu", "%s:0\n", c.plistname); grub_xnu_load_driver (c.plistname, 0); } } grub_free (c.plistname); grub_device_close (dev); } grub_free (device_name); return GRUB_ERR_NONE; }
static grub_err_t grub_cpio_dir (grub_device_t device, const char *path, int (*hook) (const char *filename, const struct grub_dirhook_info *info)) { struct grub_cpio_data *data; grub_uint32_t ofs; char *prev, *name; const char *np; int len; grub_dl_ref (my_mod); prev = 0; data = grub_cpio_mount (device->disk); if (!data) goto fail; np = path + 1; len = grub_strlen (path) - 1; data->hofs = 0; while (1) { if (grub_cpio_find_file (data, &name, &ofs)) goto fail; if (!ofs) break; if (grub_memcmp (np, name, len) == 0) { char *p, *n; n = name + len; if (*n == '/') n++; p = grub_strchr (name + len, '/'); if (p) *p = 0; if ((!prev) || (grub_strcmp (prev, name) != 0)) { struct grub_dirhook_info info; grub_memset (&info, 0, sizeof (info)); info.dir = (p != NULL); hook (name + len, &info); if (prev) grub_free (prev); prev = name; } else grub_free (name); } data->hofs = ofs; } fail: if (prev) grub_free (prev); if (data) grub_free (data); grub_dl_unref (my_mod); return grub_errno; }
/* Load .kext. */ static grub_err_t grub_xnu_load_driver (char *infoplistname, grub_file_t binaryfile) { grub_macho_t macho; grub_err_t err; grub_file_t infoplist; struct grub_xnu_extheader *exthead; int neededspace = sizeof (*exthead); grub_uint8_t *buf; grub_size_t infoplistsize = 0, machosize = 0; char *name, *nameend; int namelen; name = get_name_ptr (infoplistname); nameend = grub_strchr (name, '/'); if (nameend) namelen = nameend - name; else namelen = grub_strlen (name); neededspace += namelen + 1; if (! grub_xnu_heap_size) return grub_error (GRUB_ERR_BAD_OS, "no xnu kernel loaded"); /* Compute the needed space. */ if (binaryfile) { macho = grub_macho_file (binaryfile); if (! macho || ! grub_macho_contains_macho32 (macho)) { if (macho) grub_macho_close (macho); return grub_error (GRUB_ERR_BAD_OS, "extension doesn't contain suitable architecture"); } if (grub_xnu_is_64bit) machosize = grub_macho_filesize64 (macho); else machosize = grub_macho_filesize32 (macho); neededspace += machosize; } else macho = 0; if (infoplistname) infoplist = grub_gzfile_open (infoplistname, 1); else infoplist = 0; grub_errno = GRUB_ERR_NONE; if (infoplist) { infoplistsize = grub_file_size (infoplist); neededspace += infoplistsize + 1; } else infoplistsize = 0; /* Allocate the space. */ err = grub_xnu_align_heap (GRUB_XNU_PAGESIZE); if (err) return err; buf = grub_xnu_heap_malloc (neededspace); exthead = (struct grub_xnu_extheader *) buf; grub_memset (exthead, 0, sizeof (*exthead)); buf += sizeof (*exthead); /* Load the binary. */ if (macho) { exthead->binaryaddr = (buf - (grub_uint8_t *) grub_xnu_heap_start) + grub_xnu_heap_will_be_at; exthead->binarysize = machosize; if (grub_xnu_is_64bit) err = grub_macho_readfile64 (macho, buf); else err = grub_macho_readfile32 (macho, buf); if (err) { grub_macho_close (macho); return err; } grub_macho_close (macho); buf += machosize; } grub_errno = GRUB_ERR_NONE; /* Load the plist. */ if (infoplist) { exthead->infoplistaddr = (buf - (grub_uint8_t *) grub_xnu_heap_start) + grub_xnu_heap_will_be_at; exthead->infoplistsize = infoplistsize + 1; if (grub_file_read (infoplist, buf, infoplistsize) != (grub_ssize_t) (infoplistsize)) { grub_file_close (infoplist); grub_error_push (); return grub_error (GRUB_ERR_BAD_OS, "couldn't read file %s: ", infoplistname); } grub_file_close (infoplist); buf[infoplistsize] = 0; buf += infoplistsize + 1; } grub_errno = GRUB_ERR_NONE; exthead->nameaddr = (buf - (grub_uint8_t *) grub_xnu_heap_start) + grub_xnu_heap_will_be_at; exthead->namesize = namelen + 1; grub_memcpy (buf, name, namelen); buf[namelen] = 0; buf += namelen + 1; /* Announce to kernel */ return grub_xnu_register_memory ("Driver-", &driversnum, exthead, neededspace); }