File efibootmgr-delete-multiple.diff of Package efibootmgr
From: Raymund Will <rw@suse.com>
Subject: Delete boot entries based on partition UUID.
References: bsc#870211, bsc#945705
Signed-off-by: Raymund Will <rw@suse.com>
---
src/efibootmgr/efibootmgr.c | 149 +++++++++++++++++++++++++++++++++++++++++++-
src/include/efibootmgr.h | 2
2 files changed, 149 insertions(+), 2 deletions(-)
--- a/src/efibootmgr/efibootmgr.c
+++ b/src/efibootmgr/efibootmgr.c
@@ -467,6 +467,109 @@ delete_boot_var(uint16_t num)
return EFI_SUCCESS;
}
+static int
+delete_boot_uuid(char *uuid_str)
+{
+ int count = 0;
+ list_t *pos, *tmp;
+ var_entry_t *boot;
+ char description[80];
+ EFI_LOAD_OPTION *load_option;
+ EFI_DEVICE_PATH *path;
+ char text_path[1024];
+
+ list_for_each_safe(pos, tmp, &boot_entry_list) {
+ boot = list_entry(pos, var_entry_t, list);
+ load_option = (EFI_LOAD_OPTION *)boot->var_data.Data;
+ path = load_option_path(load_option);
+ memset(text_path, 0, sizeof(text_path));
+ unparse_path(text_path, path,
+ load_option->file_path_list_length);
+ if (strlen(text_path) == 0)
+ continue;
+ if (strcasestr(text_path, uuid_str) == NULL)
+ continue;
+ /* found! */
+ if (opts.verbose) {
+ efichar_to_char(description, load_option->description,
+ sizeof(description));
+ printf("Delete Boot%04X %s\t%s\n",
+ boot->num, description, text_path);
+ }
+ if (delete_boot_var(boot->num) != EFI_SUCCESS)
+ return -1;
+ count++;
+ }
+ if (count==0) {
+ /* Nothing changed => exit early */
+ exit(0);
+ }
+ return 0;
+}
+
+static int
+delete_boot_diskpart(char *disk, uint32_t part)
+{
+ int fd, rc;
+ uint64_t start, size;
+#define MLEN 80
+ char signature[16], sigstr[40], msg[MLEN+1];
+ uint8_t mbr_type, signature_type;
+
+ memset(signature, 0, sizeof(signature));
+
+ fd = open(disk, O_RDONLY|O_DIRECT);
+ if (fd == -1) {
+ snprintf(msg, MLEN, "Could not open disk %s", disk);
+ msg[MLEN] = 0;
+ perror(msg);
+ return -1;
+ }
+ rc = disk_get_partition_info(fd, part, &start, &size, signature,
+ &mbr_type, &signature_type);
+ close(fd);
+ if (rc)
+ return -1;
+ if (mbr_type != 0x02) {
+ snprintf(msg, MLEN, "Cowardly refusing non-GPT disk %s", disk);
+ msg[MLEN] = 0;
+ perror(msg);
+ return -1;
+ }
+ efi_guid_unparse((efi_guid_t *)signature, sigstr);
+
+ if (opts.verbose) {
+ printf("About to delete all entries referring to UUID %s\n",
+ sigstr);
+ }
+ return delete_boot_uuid(sigstr);
+}
+
+static int
+check_uuid(const char *s)
+{
+ /* algorithm derived from efivar-0.15/src/guid.h */
+ int len = 36;
+ unsigned int i;
+ if (strlen(s) != len)
+ return -1;
+ for (i = 0; i < len; i++) {
+ if (i == 8 || i == 13 || i == 18 || i == 23) {
+ if (s[i] != '-')
+ return -1;
+ continue;
+ }
+ if (s[i] >= '0' && s[i] <= '9')
+ continue;
+ /* "| 0x20" is tolower() without having to worry about
+ * locale concerns, since we know everything here must
+ * be within traditional ascii space. */
+ if ((s[i] | 0x20) >= 'a' && (s[i] | 0x20) <= 'f')
+ continue;
+ return -1;
+ }
+ return 0;
+}
static void
set_var_nums(const char *pattern, list_t *list)
@@ -786,8 +889,10 @@ usage()
printf("\t-a | --active sets bootnum active\n");
printf("\t-A | --inactive sets bootnum inactive\n");
printf("\t-b | --bootnum XXXX modify BootXXXX (hex)\n");
- printf("\t-B | --delete-bootnum delete bootnum (hex)\n");
+ printf("\t-B | --delete-bootnum delete bootnum (specified with -b)\n");
printf("\t-c | --create create new variable bootnum and add to bootorder\n");
+ printf("\t-C | --delete delete entry by bootnum (-b), by UUID (-P)\n");
+ printf("\t or by disk+partition (-d -p)\n");
printf("\t-d | --disk disk (defaults to /dev/sda) containing loader\n");
printf("\t-e | --edd [1|3|-1] force EDD 1.0 or 3.0 creation variables, or guess\n");
printf("\t-E | --device num EDD 1.0 device number (defaults to 0x80)\n");
@@ -801,6 +906,7 @@ usage()
printf("\t-o | --bootorder XXXX,YYYY,ZZZZ,... explicitly set BootOrder (hex)\n");
printf("\t-O | --delete-bootorder delete BootOrder\n");
printf("\t-p | --part part (defaults to 1) containing loader\n");
+ printf("\t-P | --part-uuid UUID select all variables for given partition UUID\n");
printf("\t-q | --quiet be quiet\n");
printf("\t | --test filename don't write to NVRAM, write to filename.\n");
printf("\t-t | --timeout seconds set boot manager timeout waiting for user input.\n");
@@ -829,6 +935,7 @@ set_default_opts()
opts.part = 1;
opts.acpi_hid = -1;
opts.acpi_uid = -1;
+ opts.part_uuid = NULL;
}
static void
@@ -847,6 +954,7 @@ parse_opts(int argc, char **argv)
{"bootnum", required_argument, 0, 'b'},
{"delete-bootnum", no_argument, 0, 'B'},
{"create", no_argument, 0, 'c'},
+ {"delete", no_argument, 0, 'C'},
{"disk", required_argument, 0, 'd'},
{"iface", required_argument, 0, 'i'},
{"acpi_hid", required_argument, 0, 'H'},
@@ -860,6 +968,7 @@ parse_opts(int argc, char **argv)
{"bootorder", required_argument, 0, 'o'},
{"delete-bootorder", no_argument, 0, 'O'},
{"part", required_argument, 0, 'p'},
+ {"part-uuid", required_argument, 0, 'P'},
{"quiet", no_argument, 0, 'q'},
{"test", required_argument, 0, 1},
{"timeout", required_argument, 0, 't'},
@@ -875,7 +984,8 @@ parse_opts(int argc, char **argv)
};
c = getopt_long (argc, argv,
- "AaBb:cd:e:E:gH:i:l:L:n:No:Op:qt:TuU:v::Vw@:",
+ "AaBb:cCd:e:E:gH:i:l:L:n:N"
+ "o:Op:P:qt:TuU:v::Vw@:",
long_options, &option_index);
if (c == -1)
break;
@@ -905,8 +1015,12 @@ parse_opts(int argc, char **argv)
case 'c':
opts.create = 1;
break;
+ case 'C':
+ opts.delete |= 1;
+ break;
case 'd':
opts.disk = optarg;
+ opts.delete |= 2;
break;
case 'e':
rc = sscanf(optarg, "%d", &num);
@@ -968,7 +1082,18 @@ parse_opts(int argc, char **argv)
fprintf (stderr,"invalid numeric value %s\n",optarg);
exit(1);
}
+ opts.delete |= 4;
break;
+ case 'P':
+ if ((rc=check_uuid(optarg)) < 0) {
+ fprintf(stderr,
+ "malformed partition UUID: %s (%d)\n",
+ optarg, rc);
+ exit(1);
+ }
+ opts.part_uuid = optarg;
+ break;
+
case 'q':
opts.quiet = 1;
break;
@@ -1073,6 +1198,26 @@ main(int argc, char **argv)
ret = delete_boot_var(opts.bootnum);
}
+ if (opts.delete & 1) {
+ if (opts.part_uuid) {
+ ret = delete_boot_uuid(opts.part_uuid);
+ if (ret < 0) {
+ fprintf(stderr, "\nCould not delete boot variables.\n\n");
+ return 1;
+ }
+ } else if (opts.delete & 6) {
+ ret = delete_boot_diskpart(opts.disk, opts.part);
+ if (ret < 0) {
+ fprintf(stderr, "\nCould not delete boot variables.\n\n");
+ return 1;
+ }
+ } else if (opts.bootnum != -1) {
+ ret = delete_boot_var(opts.bootnum);
+ } else {
+ fprintf(stderr, "\nYou must specify a boot entry to delete.\n\n");
+ return 1;
+ }
+ }
if (opts.active >= 0) {
if (opts.bootnum == -1) {
fprintf(stderr, "\nYou must specify a boot entry to delete (see the -b option).\n\n");
--- a/src/include/efibootmgr.h
+++ b/src/include/efibootmgr.h
@@ -32,6 +32,7 @@ typedef struct {
char *bootorder;
char *testfile;
char *extra_opts_file;
+ char *part_uuid;
uint32_t part;
int edd_version;
int edd10_devicenum;
@@ -39,6 +40,7 @@ typedef struct {
int bootnext;
int verbose;
int active;
+ int delete;
uint32_t acpi_hid;
uint32_t acpi_uid;
unsigned int delete_boot:1;