static void grub_bsd_get_device (grub_uint32_t * biosdev, grub_uint32_t * unit, grub_uint32_t * slice, grub_uint32_t * part) { grub_device_t dev; #ifdef GRUB_MACHINE_PCBIOS *biosdev = grub_get_root_biosnumber () & 0xff; #else *biosdev = 0xff; #endif *unit = (*biosdev & 0x7f); *slice = 0xff; *part = 0xff; dev = grub_device_open (0); if (dev && dev->disk && dev->disk->partition) { if (dev->disk->partition->parent) { *part = dev->disk->partition->number; *slice = dev->disk->partition->parent->number + 1; } else *slice = dev->disk->partition->number + 1; } if (dev) grub_device_close (dev); }
void grub_multiboot_set_bootdev (void) { grub_device_t dev; slice = ~0; part = ~0; #ifdef GRUB_MACHINE_PCBIOS biosdev = grub_get_root_biosnumber (); #else biosdev = 0xffffffff; #endif if (biosdev == 0xffffffff) return; dev = grub_device_open (0); if (dev && dev->disk && dev->disk->partition) { if (dev->disk->partition->parent) { part = dev->disk->partition->number; slice = dev->disk->partition->parent->number; } else slice = dev->disk->partition->number; } if (dev) grub_device_close (dev); bootdev_set = 1; }
void iterate_directory(const char *dirname, int (*callback)(const char *filename, const struct grub_dirhook_info *info)) { char *device_name; grub_device_t device; grub_errno = GRUB_ERR_NONE; device_name = grub_file_get_device_name(dirname); device = grub_device_open(device_name); if (device) { grub_fs_t fs = grub_fs_probe(device); if (fs) fs->dir(device, dirname, callback); grub_device_close(device); } grub_free(device_name); }
static int iterate_disk (const char *disk_name, void *closure) { struct grub_device_iterate_closure *c = closure; grub_device_t dev; if (c->hook (disk_name, c->closure)) return 1; dev = grub_device_open (disk_name); if (! dev) { grub_errno = GRUB_ERR_NONE; return 0; } if (dev->disk && dev->disk->has_partitions) { struct part_ent *p; int ret = 0; c->ents = NULL; (void) grub_partition_iterate (dev->disk, iterate_partition, c); grub_device_close (dev); grub_errno = GRUB_ERR_NONE; p = c->ents; while (p != NULL) { struct part_ent *next = p->next; if (!ret) ret = c->hook (p->name, c->closure); grub_free (p->name); grub_free (p); p = next; } return ret; } grub_device_close (dev); return 0; }
/* Helper for grub_device_iterate. */ static int iterate_disk (const char *disk_name, void *data) { struct grub_device_iterate_ctx *ctx = data; grub_device_t dev; if (ctx->hook (disk_name, ctx->hook_data)) return 1; dev = grub_device_open (disk_name); if (! dev) { grub_errno = GRUB_ERR_NONE; return 0; } if (dev->disk) { struct part_ent *p; int ret = 0; ctx->ents = NULL; (void) grub_partition_iterate (dev->disk, iterate_partition, ctx); grub_device_close (dev); grub_errno = GRUB_ERR_NONE; p = ctx->ents; while (p != NULL) { struct part_ent *next = p->next; if (!ret) ret = ctx->hook (p->name, ctx->hook_data); grub_free (p->name); grub_free (p); p = next; } return ret; } grub_device_close (dev); return 0; }
static grub_device_t find_device (struct grub_btrfs_data *data, grub_uint64_t id, int do_rescan) { grub_device_t dev_found = NULL; auto int hook (const char *name); int hook (const char *name) { grub_device_t dev; grub_err_t err; struct grub_btrfs_superblock sb; dev = grub_device_open (name); if (!dev) return 0; if (!dev->disk) { grub_device_close (dev); return 0; } err = read_sblock (dev->disk, &sb); if (err == GRUB_ERR_BAD_FS) { grub_device_close (dev); grub_errno = GRUB_ERR_NONE; return 0; } if (err) { grub_device_close (dev); grub_print_error (); return 0; } if (grub_memcmp (data->sblock.uuid, sb.uuid, sizeof (sb.uuid)) != 0 || sb.this_device.device_id != id) { grub_device_close (dev); return 0; } dev_found = dev; return 1; }
static int grub_get_root_biosnumber_default (void) { char *biosnum; int ret = -1; grub_device_t dev; biosnum = grub_env_get ("biosnum"); if (biosnum) return grub_strtoul (biosnum, 0, 0); dev = grub_device_open (0); if (dev && dev->disk && dev->disk->dev && dev->disk->dev->id == GRUB_DISK_DEVICE_BIOSDISK_ID) ret = (int) dev->disk->id; if (dev) grub_device_close (dev); return ret; }
/* 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; }
/* 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 void read_file (char *pathname, int (*hook) (grub_off_t ofs, char *buf, int len)) { static char buf[BUF_SIZE]; grub_file_t file; grub_off_t ofs, len; if ((pathname[0] == '-') && (pathname[1] == 0)) { grub_device_t dev; dev = grub_device_open (0); if ((! dev) || (! dev->disk)) grub_util_error (_("can\'t open device")); grub_util_info ("total sectors : %lld", (unsigned long long) dev->disk->total_sectors); if (! leng) leng = (dev->disk->total_sectors << GRUB_DISK_SECTOR_BITS) - skip; while (leng) { grub_size_t len; len = (leng > BUF_SIZE) ? BUF_SIZE : leng; if (grub_disk_read (dev->disk, 0, skip, len, buf)) grub_util_error (_("disk read fails at offset %lld, length %d"), skip, len); if (hook (skip, buf, len)) break; skip += len; leng -= len; } grub_device_close (dev); return; } grub_file_filter_disable_compression (); file = grub_file_open (pathname); if (!file) { grub_util_error (_("cannot open file %s:%s"), pathname, grub_errmsg); return; } grub_util_info ("file size : %lld", (unsigned long long) file->size); if (skip > file->size) { grub_util_error (_("invalid skip value %lld"), (unsigned long long) skip); return; } ofs = skip; len = file->size - skip; if ((leng) && (leng < len)) len = leng; file->offset = skip; while (len) { grub_ssize_t sz; sz = grub_file_read (file, buf, (len > BUF_SIZE) ? BUF_SIZE : len); if (sz < 0) { grub_util_error (_("read error at offset %llu: %s"), ofs, grub_errmsg); break; } if ((sz == 0) || (hook (ofs, buf, sz))) break; ofs += sz; len -= sz; } grub_file_close (file); }
static grub_err_t grub_cmd_freedos (grub_command_t cmd __attribute__ ((unused)), int argc, char *argv[]) { grub_file_t file = 0; grub_err_t err; void *bs, *kernelsys; grub_size_t kernelsyssize; grub_device_t dev; if (argc == 0) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); grub_dl_ref (my_mod); rel = grub_relocator_new (); if (!rel) goto fail; file = grub_file_open (argv[0]); if (! file) goto fail; { grub_relocator_chunk_t ch; err = grub_relocator_alloc_chunk_addr (rel, &ch, GRUB_FREEDOS_BPB_ADDR, GRUB_DISK_SECTOR_SIZE); if (err) goto fail; bs = get_virtual_current_address (ch); } ebx = grub_get_root_biosnumber (); dev = grub_device_open (0); if (dev && dev->disk) { err = grub_disk_read (dev->disk, 0, 0, GRUB_DISK_SECTOR_SIZE, bs); if (err) { grub_device_close (dev); goto fail; } grub_chainloader_patch_bpb (bs, dev, ebx); } if (dev) grub_device_close (dev); kernelsyssize = grub_file_size (file); if (kernelsyssize > GRUB_FREEDOS_MAX_SIZE) { grub_error (GRUB_ERR_BAD_OS, N_("the size of `%s' is too large"), argv[0]); goto fail; } { grub_relocator_chunk_t ch; err = grub_relocator_alloc_chunk_addr (rel, &ch, GRUB_FREEDOS_ADDR, kernelsyssize); if (err) goto fail; kernelsys = get_virtual_current_address (ch); } if (grub_file_read (file, kernelsys, kernelsyssize) != (grub_ssize_t) kernelsyssize) goto fail; grub_loader_set (grub_freedos_boot, grub_freedos_unload, 1); return GRUB_ERR_NONE; fail: if (file) grub_file_close (file); grub_freedos_unload (); return grub_errno; }
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; }
/* 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_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; }
static grub_err_t get_uuid (const char *name, char **uuid, int getnative) { grub_device_t dev; grub_fs_t fs = 0; *uuid = 0; dev = grub_device_open (name); if (!dev) return grub_errno; if (!dev->disk) { grub_dprintf ("nativedisk", "Skipping non-disk\n"); grub_device_close (dev); return 0; } switch (dev->disk->dev->id) { /* Firmware disks. */ case GRUB_DISK_DEVICE_BIOSDISK_ID: case GRUB_DISK_DEVICE_OFDISK_ID: case GRUB_DISK_DEVICE_EFIDISK_ID: case GRUB_DISK_DEVICE_NAND_ID: case GRUB_DISK_DEVICE_ARCDISK_ID: case GRUB_DISK_DEVICE_HOSTDISK_ID: case GRUB_DISK_DEVICE_UBOOTDISK_ID: break; /* Native disks. */ case GRUB_DISK_DEVICE_ATA_ID: case GRUB_DISK_DEVICE_SCSI_ID: case GRUB_DISK_DEVICE_XEN: if (getnative) break; /* Virtual disks. */ /* GRUB dynamically generated files. */ case GRUB_DISK_DEVICE_PROCFS_ID: /* To access through host OS routines (grub-emu only). */ case GRUB_DISK_DEVICE_HOST_ID: /* To access coreboot roms. */ case GRUB_DISK_DEVICE_CBFSDISK_ID: /* GRUB-only memdisk. Can't match any of firmware devices. */ case GRUB_DISK_DEVICE_MEMDISK_ID: grub_dprintf ("nativedisk", "Skipping native disk %s\n", dev->disk->name); grub_device_close (dev); return 0; /* FIXME: those probably need special handling. */ case GRUB_DISK_DEVICE_LOOPBACK_ID: case GRUB_DISK_DEVICE_DISKFILTER_ID: case GRUB_DISK_DEVICE_CRYPTODISK_ID: break; } if (dev) fs = grub_fs_probe (dev); if (!fs) { grub_device_close (dev); return grub_errno; } if (!fs->uuid || fs->uuid (dev, uuid) || !*uuid) { grub_device_close (dev); if (!grub_errno) grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, N_("%s does not support UUIDs"), fs->name); return grub_errno; } grub_device_close (dev); return GRUB_ERR_NONE; }
static grub_err_t grub_find_next (const char *disk_name, const grub_gpt_part_type_t *part_type, char **part_name, char **part_guid) { struct grub_gpt_partentry *part, *part_found = NULL; grub_device_t dev = NULL; grub_gpt_t gpt = NULL; grub_uint32_t i, part_index; dev = grub_device_open (disk_name); if (!dev) goto done; gpt = grub_gpt_read (dev->disk); if (!gpt) goto done; if (grub_gpt_repair (dev->disk, gpt)) goto done; for (i = 0; (part = grub_gpt_get_partentry (gpt, i)) != NULL; i++) { if (grub_memcmp (part_type, &part->type, sizeof (*part_type)) == 0) { unsigned int priority, tries_left, successful, old_priority = 0; priority = grub_gptprio_priority (part); tries_left = grub_gptprio_tries_left (part); successful = grub_gptprio_successful (part); if (part_found) old_priority = grub_gptprio_priority (part_found); if ((tries_left || successful) && priority > old_priority) { part_index = i; part_found = part; } } } if (!part_found) { grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("no such partition")); goto done; } if (grub_gptprio_tries_left (part_found)) { unsigned int tries_left = grub_gptprio_tries_left (part_found); grub_gptprio_set_tries_left (part_found, tries_left - 1); if (grub_gpt_update (gpt)) goto done; if (grub_gpt_write (dev->disk, gpt)) goto done; } *part_name = grub_xasprintf ("%s,gpt%u", disk_name, part_index + 1); if (!*part_name) goto done; *part_guid = grub_gpt_guid_to_str (&part_found->guid); if (!*part_guid) goto done; grub_errno = GRUB_ERR_NONE; done: grub_gpt_free (gpt); if (dev) grub_device_close (dev); return grub_errno; }
static grub_err_t grub_cmd_ntldr (grub_command_t cmd __attribute__ ((unused)), int argc, char *argv[]) { grub_file_t file = 0; grub_err_t err; void *bs, *ntldr; grub_size_t ntldrsize; grub_device_t dev; if (argc == 0) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); grub_dl_ref (my_mod); rel = grub_relocator_new (); if (!rel) goto fail; file = grub_file_open (argv[0]); if (! file) goto fail; { grub_relocator_chunk_t ch; err = grub_relocator_alloc_chunk_addr (rel, &ch, 0x7C00, GRUB_DISK_SECTOR_SIZE); if (err) goto fail; bs = get_virtual_current_address (ch); } edx = grub_get_root_biosnumber (); dev = grub_device_open (0); if (dev && dev->disk) { err = grub_disk_read (dev->disk, 0, 0, GRUB_DISK_SECTOR_SIZE, bs); if (err) { grub_device_close (dev); goto fail; } grub_chainloader_patch_bpb (bs, dev, edx); } if (dev) grub_device_close (dev); ntldrsize = grub_file_size (file); { grub_relocator_chunk_t ch; err = grub_relocator_alloc_chunk_addr (rel, &ch, GRUB_NTLDR_SEGMENT << 4, ntldrsize); if (err) goto fail; ntldr = get_virtual_current_address (ch); } if (grub_file_read (file, ntldr, ntldrsize) != (grub_ssize_t) ntldrsize) goto fail; grub_loader_set (grub_ntldr_boot, grub_ntldr_unload, 1); /* Begin TCG Extension */ if (grub_TPM_isAvailable()) grub_TPM_measureFile( argv[0], TPM_LOADED_FILES_PCR ); /* End TCG Extension */ return GRUB_ERR_NONE; fail: if (file) grub_file_close (file); grub_ntldr_unload (); return grub_errno; }
/* Helper for FUNC_NAME. */ static int iterate_device (const char *name, void *data) { struct search_ctx *ctx = data; int found = 0; /* Skip floppy drives when requested. */ if (ctx->no_floppy && name[0] == 'f' && name[1] == 'd' && name[2] >= '0' && name[2] <= '9') return 0; #ifdef DO_SEARCH_FS_UUID #define compare_fn grub_strcasecmp #else #define compare_fn grub_strcmp #endif #ifdef DO_SEARCH_FILE { char *buf; grub_file_t file; buf = grub_xasprintf ("(%s)%s", name, ctx->key); if (! buf) return 1; grub_file_filter_disable_compression (); file = grub_file_open (buf); if (file) { found = 1; grub_file_close (file); } grub_free (buf); } #elif defined(DO_SEARCH_PART_UUID) { grub_device_t dev; char *quid; dev = grub_device_open (name); if (dev) { if (grub_gpt_part_uuid (dev, &quid) == GRUB_ERR_NONE) { if (grub_strcasecmp (quid, ctx->key) == 0) found = 1; grub_free (quid); } grub_device_close (dev); } } #elif defined(DO_SEARCH_PART_LABEL) { grub_device_t dev; char *quid; dev = grub_device_open (name); if (dev) { if (grub_gpt_part_label (dev, &quid) == GRUB_ERR_NONE) { if (grub_strcmp (quid, ctx->key) == 0) found = 1; grub_free (quid); } grub_device_close (dev); } } #else { /* SEARCH_FS_UUID or SEARCH_LABEL */ grub_device_t dev; grub_fs_t fs; char *quid; dev = grub_device_open (name); if (dev) { fs = grub_fs_probe (dev); #ifdef DO_SEARCH_FS_UUID #define read_fn uuid #else #define read_fn label #endif if (fs && fs->read_fn) { fs->read_fn (dev, &quid); if (grub_errno == GRUB_ERR_NONE && quid) { if (compare_fn (quid, ctx->key) == 0) found = 1; grub_free (quid); } } grub_device_close (dev); } } #endif if (!ctx->is_cache && found && ctx->count == 0) { struct cache_entry *cache_ent; cache_ent = grub_malloc (sizeof (*cache_ent)); if (cache_ent) { cache_ent->key = grub_strdup (ctx->key); cache_ent->value = grub_strdup (name); if (cache_ent->value && cache_ent->key) { cache_ent->next = cache; cache = cache_ent; } else { grub_free (cache_ent->value); grub_free (cache_ent->key); grub_free (cache_ent); grub_errno = GRUB_ERR_NONE; } } else grub_errno = GRUB_ERR_NONE; } if (found) { ctx->count++; if (ctx->var) grub_env_set (ctx->var, name); else grub_printf (" %s", name); } grub_errno = GRUB_ERR_NONE; return (found && ctx->var); }
static void grub_chainloader_cmd (const char *filename, grub_chainloader_flags_t flags) { grub_file_t file = 0; grub_uint16_t signature; grub_device_t dev; int drive = -1; void *part_addr = 0; grub_dl_ref (my_mod); file = grub_file_open (filename); if (! file) goto fail; /* Read the first block. */ if (grub_file_read (file, (void *) 0x7C00, GRUB_DISK_SECTOR_SIZE) != GRUB_DISK_SECTOR_SIZE) { if (grub_errno == GRUB_ERR_NONE) grub_error (GRUB_ERR_BAD_OS, "too small"); goto fail; } /* Check the signature. */ signature = *((grub_uint16_t *) (0x7C00 + GRUB_DISK_SECTOR_SIZE - 2)); if (signature != grub_le_to_cpu16 (0xaa55) && ! (flags & GRUB_CHAINLOADER_FORCE)) { grub_error (GRUB_ERR_BAD_OS, "invalid signature"); goto fail; } grub_file_close (file); /* Obtain the partition table from the root device. */ drive = grub_get_root_biosnumber (); dev = grub_device_open (0); if (dev && dev->disk && dev->disk->partition) { grub_disk_t disk = dev->disk; if (disk) { grub_partition_t p = disk->partition; if (p && grub_strcmp (p->partmap->name, "msdos") == 0) { disk->partition = p->parent; grub_disk_read (disk, p->offset, 446, 64, (void *) GRUB_MEMORY_MACHINE_PART_TABLE_ADDR); part_addr = (void *) (GRUB_MEMORY_MACHINE_PART_TABLE_ADDR + (p->index << 4)); disk->partition = p; } } } if (dev) grub_device_close (dev); /* Ignore errors. Perhaps it's not fatal. */ grub_errno = GRUB_ERR_NONE; boot_drive = drive; boot_part_addr = part_addr; grub_loader_set (grub_chainloader_boot, grub_chainloader_unload, 1); return; fail: if (file) grub_file_close (file); grub_dl_unref (my_mod); }
static grub_err_t grub_cmd_ntldr (grub_command_t cmd __attribute__ ((unused)), int argc, char *argv[]) { grub_file_t file = 0; grub_err_t err; void *bs, *ntldr; grub_size_t ntldrsize; grub_device_t dev; if (argc == 0) return grub_error (GRUB_ERR_BAD_ARGUMENT, "no file specified"); grub_dl_ref (my_mod); rel = grub_relocator_new (); if (!rel) goto fail; file = grub_file_open (argv[0]); if (! file) goto fail; { grub_relocator_chunk_t ch; err = grub_relocator_alloc_chunk_addr (rel, &ch, 0x7C00, GRUB_DISK_SECTOR_SIZE); if (err) goto fail; bs = get_virtual_current_address (ch); } edx = grub_get_root_biosnumber (); dev = grub_device_open (0); if (dev && dev->disk) { err = grub_disk_read (dev->disk, 0, 0, GRUB_DISK_SECTOR_SIZE, bs); if (err) { grub_device_close (dev); goto fail; } } if (dev) grub_device_close (dev); ntldrsize = grub_file_size (file); { grub_relocator_chunk_t ch; err = grub_relocator_alloc_chunk_addr (rel, &ch, GRUB_NTLDR_SEGMENT << 4, ntldrsize); if (err) goto fail; ntldr = get_virtual_current_address (ch); } if (grub_file_read (file, ntldr, ntldrsize) != (grub_ssize_t) ntldrsize) goto fail; grub_loader_set (grub_ntldr_boot, grub_ntldr_unload, 1); return GRUB_ERR_NONE; fail: if (file) grub_file_close (file); grub_ntldr_unload (); return grub_errno; }
/* 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; }
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); }
static grub_err_t grub_cmd_probe (grub_extcmd_context_t ctxt, int argc, char **args) { struct grub_arg_list *state = ctxt->state; grub_device_t dev; grub_fs_t fs; char *ptr; grub_err_t err; if (argc < 1) return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required"); ptr = args[0] + grub_strlen (args[0]) - 1; if (args[0][0] == '(' && *ptr == ')') { *ptr = 0; dev = grub_device_open (args[0] + 1); *ptr = ')'; } else dev = grub_device_open (args[0]); if (! dev) return grub_errno; if (state[1].set) { const char *val = "none"; if (dev->net) val = dev->net->protocol->name; if (dev->disk) val = dev->disk->dev->name; if (state[0].set) grub_env_set (state[0].arg, val); else grub_printf ("%s", val); grub_device_close (dev); return GRUB_ERR_NONE; } if (state[2].set) { const char *val = "none"; if (dev->disk && dev->disk->partition) val = dev->disk->partition->partmap->name; if (state[0].set) grub_env_set (state[0].arg, val); else grub_printf ("%s", val); grub_device_close (dev); return GRUB_ERR_NONE; } fs = grub_fs_probe (dev); if (! fs) return grub_errno; if (state[3].set) { if (state[0].set) grub_env_set (state[0].arg, fs->name); else grub_printf ("%s", fs->name); grub_device_close (dev); return GRUB_ERR_NONE; } if (state[4].set) { char *uuid; if (! fs->uuid) return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, N_("%s does not support UUIDs"), fs->name); err = fs->uuid (dev, &uuid); if (err) return err; if (! uuid) return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, N_("%s does not support UUIDs"), fs->name); if (state[0].set) grub_env_set (state[0].arg, uuid); else grub_printf ("%s", uuid); grub_free (uuid); grub_device_close (dev); return GRUB_ERR_NONE; } if (state[5].set) { char *label; if (! fs->label) return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, N_("filesystem `%s' does not support labels"), fs->name); err = fs->label (dev, &label); if (err) return err; if (! label) return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, N_("filesystem `%s' does not support labels"), fs->name); if (state[0].set) grub_env_set (state[0].arg, label); else grub_printf ("%s", label); grub_free (label); grub_device_close (dev); return GRUB_ERR_NONE; } grub_device_close (dev); return grub_error (GRUB_ERR_BAD_ARGUMENT, "unrecognised target"); }