/* * VAS_EBOOT -- GRand Unified Bootloader * Copyright (C) 2009 Free Software Foundation, Inc. * * VAS_EBOOT is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * VAS_EBOOT is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with VAS_EBOOT. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include VAS_EBOOT_MOD_LICENSE ("GPLv3+"); static const struct VasEBoot_arg_option options[] = { {"set", 's', 0, N_("Set a variable to return value."), N_("VARNAME"), ARG_TYPE_STRING}, /* TRANSLATORS: It's a driver that is currently in use to access the diven disk. */ {"driver", 'd', 0, N_("Determine driver."), 0, 0}, {"partmap", 'p', 0, N_("Determine partition map type."), 0, 0}, {"fs", 'f', 0, N_("Determine filesystem type."), 0, 0}, {"fs-uuid", 'u', 0, N_("Determine filesystem UUID."), 0, 0}, {"label", 'l', 0, N_("Determine filesystem label."), 0, 0}, {"part-uuid", 0, 0, N_("Determine partition UUID."), 0, 0}, {0, 0, 0, 0, 0, 0} }; static VasEBoot_err_t VasEBoot_cmd_probe (VasEBoot_extcmd_context_t ctxt, int argc, char **args) { struct VasEBoot_arg_list *state = ctxt->state; VasEBoot_device_t dev; VasEBoot_fs_t fs; char *ptr; VasEBoot_err_t err; if (argc < 1) return VasEBoot_error (VAS_EBOOT_ERR_BAD_ARGUMENT, "device name required"); ptr = args[0] + VasEBoot_strlen (args[0]) - 1; if (args[0][0] == '(' && *ptr == ')') { *ptr = 0; dev = VasEBoot_device_open (args[0] + 1); *ptr = ')'; } else dev = VasEBoot_device_open (args[0]); if (! dev) return VasEBoot_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) VasEBoot_env_set (state[0].arg, val); else VasEBoot_printf ("%s", val); VasEBoot_device_close (dev); return VAS_EBOOT_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) VasEBoot_env_set (state[0].arg, val); else VasEBoot_printf ("%s", val); VasEBoot_device_close (dev); return VAS_EBOOT_ERR_NONE; } if (state[6].set) { /* AAAABBBB-CCCC-DDDD-EEEE-FFFFFFFFFFFF + null terminator */ char val[37] = "none"; if (dev->disk && dev->disk->partition) { struct VasEBoot_partition *p = dev->disk->partition; VasEBoot_disk_t disk = VasEBoot_disk_open(dev->disk->name); if (!disk) { VasEBoot_device_close (dev); return VasEBoot_errno; } if (VasEBoot_strcmp(dev->disk->partition->partmap->name, "gpt") == 0) { struct VasEBoot_gpt_partentry entry; VasEBoot_guid_t *guid; if (VasEBoot_disk_read(disk, p->offset, p->index, sizeof(entry), &entry)) { VasEBoot_error_push (); VasEBoot_disk_close (disk); VasEBoot_device_close (dev); VasEBoot_error_pop (); return VasEBoot_errno; } guid = &entry.guid; guid->data1 = VasEBoot_le_to_cpu32 (guid->data1); guid->data2 = VasEBoot_le_to_cpu16 (guid->data2); guid->data3 = VasEBoot_le_to_cpu16 (guid->data3); VasEBoot_snprintf (val, sizeof(val), "%pG", guid); } else if (VasEBoot_strcmp(dev->disk->partition->partmap->name, "msdos") == 0) { VasEBoot_uint32_t nt_disk_sig; if (VasEBoot_disk_read(disk, 0, VAS_EBOOT_BOOT_MACHINE_WINDOWS_NT_MAGIC, sizeof(nt_disk_sig), &nt_disk_sig) == 0) VasEBoot_snprintf (val, sizeof(val), "%08x-%02x", VasEBoot_le_to_cpu32(nt_disk_sig), 1 + p->number); } VasEBoot_disk_close(disk); } if (state[0].set) VasEBoot_env_set (state[0].arg, val); else VasEBoot_printf ("%s", val); VasEBoot_device_close (dev); return VAS_EBOOT_ERR_NONE; } fs = VasEBoot_fs_probe (dev); if (! fs) { VasEBoot_error_push (); VasEBoot_device_close (dev); VasEBoot_error_pop (); return VasEBoot_errno; } if (state[3].set) { if (state[0].set) VasEBoot_env_set (state[0].arg, fs->name); else VasEBoot_printf ("%s", fs->name); VasEBoot_device_close (dev); return VAS_EBOOT_ERR_NONE; } if (state[4].set) { char *uuid; if (! fs->fs_uuid) { VasEBoot_device_close (dev); return VasEBoot_error (VAS_EBOOT_ERR_NOT_IMPLEMENTED_YET, N_("%s does not support UUIDs"), fs->name); } err = fs->fs_uuid (dev, &uuid); if (err) { VasEBoot_device_close (dev); return err; } if (! uuid) { VasEBoot_device_close (dev); return VasEBoot_error (VAS_EBOOT_ERR_NOT_IMPLEMENTED_YET, N_("%s does not support UUIDs"), fs->name); } if (state[0].set) VasEBoot_env_set (state[0].arg, uuid); else VasEBoot_printf ("%s", uuid); VasEBoot_free (uuid); VasEBoot_device_close (dev); return VAS_EBOOT_ERR_NONE; } if (state[5].set) { char *label; if (! fs->fs_label) { VasEBoot_device_close (dev); return VasEBoot_error (VAS_EBOOT_ERR_NOT_IMPLEMENTED_YET, N_("filesystem `%s' does not support labels"), fs->name); } err = fs->fs_label (dev, &label); if (err) { VasEBoot_device_close (dev); return err; } if (! label) { VasEBoot_device_close (dev); return VasEBoot_error (VAS_EBOOT_ERR_NOT_IMPLEMENTED_YET, N_("filesystem `%s' does not support labels"), fs->name); } if (state[0].set) VasEBoot_env_set (state[0].arg, label); else VasEBoot_printf ("%s", label); VasEBoot_free (label); VasEBoot_device_close (dev); return VAS_EBOOT_ERR_NONE; } VasEBoot_device_close (dev); return VasEBoot_error (VAS_EBOOT_ERR_BAD_ARGUMENT, "unrecognised target"); } static VasEBoot_extcmd_t cmd; VAS_EBOOT_MOD_INIT (probe) { cmd = VasEBoot_register_extcmd ("probe", VasEBoot_cmd_probe, 0, N_("DEVICE"), N_("Retrieve device info."), options); } VAS_EBOOT_MOD_FINI (probe) { VasEBoot_unregister_extcmd (cmd); }