Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
Please login to access the resource
openSUSE:Leap:15.2:Staging:F
efibootmgr
efibootmgr-delete-multiple.diff
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File efibootmgr-delete-multiple.diff of Package efibootmgr
From 21741160071c83e4ae6b9fa268947abfd0d3405f Mon Sep 17 00:00:00 2001 From: Raymund Will <rw@suse.com> Date: Fri, 3 Mar 2017 18:47:44 +0100 Subject: [PATCH] Extended Delete References: bsc#870211, bsc#945705 Delete boot entries not only by number. but alse based on - partition UUID, optionally restricted by loader or - disk and partition, again optionally restricted by loader. This does unfortunately require an API-change of efivar! Signed-off-by: Raymund Will <rw@suse.com> --- src/efibootmgr.c | 187 ++++++++++++++++++++++++++++++++++++++++++++++- src/include/efibootmgr.h | 3 +- 2 files changed, 185 insertions(+), 5 deletions(-) diff --git a/src/efibootmgr.c b/src/efibootmgr.c index 20d71e2..93663cb 100644 --- a/src/efibootmgr.c +++ b/src/efibootmgr.c @@ -608,6 +608,146 @@ delete_var(const char *prefix, uint16_t num) return 0; } +static int +delete_by_uuid(const char *prefix, char *uuid_str, char *loader) +{ + int count = 0; + list_t *pos, *tmp; + var_entry_t *entry; + const unsigned char *description; + efi_load_option *load_option; + efidp path = NULL; + char text_path[1024]; + + list_for_each_safe(pos, tmp, &entry_list) { + uint16_t pathlen; + ssize_t rc; + + entry = list_entry(pos, var_entry_t, list); + load_option = (efi_load_option *)entry->data; + pathlen = efi_loadopt_pathlen(load_option, + entry->data_size); + path = efi_loadopt_path(load_option, entry->data_size); + rc = efidp_format_device_path(text_path, 1024, + path, pathlen); + + if (rc < 0 || rc > 1024) + error(20, "Could not parse device path"); + + if (strlen(text_path) == 0) + continue; + if (strcasestr(text_path, uuid_str) == NULL) + continue; + if (loader && strcasestr(text_path, loader) == NULL) + continue; + /* found! */ + if (opts.verbose) { + description = efi_loadopt_desc(load_option, + entry->data_size); + printf("Delete %s%04X %s\t%s\n", + prefix, entry->num, description, text_path); + } + if (delete_var(prefix, entry->num) != 0) + return -1; + count++; + } + if (count==0) { + /* Nothing changed => exit early */ + exit(0); + } + return 0; +} + +static int +delete_by_dpl(const char *prefix, char *disk, uint32_t part, char *loader) +{ + int fd, rc; + uint64_t start, size; + efi_guid_t signature; + char sigstr[40]; + char *sigstrp = sigstr; + uint8_t mbr_type, signature_type; + + if (disk == NULL && part == 0 && loader == NULL) + errx(42, "Cowardly refusing to delete ALL %s entries.", + prefix); + if (disk == NULL) { + /* foreach d in gpt_disks + * delete_by_dpl(prefix, d, part, loader) + */ + errx(42, "Future extension."); + } + if (part == 0) { + /* foreach p in partions_on_gpt_disk + * delete_by_dpl(prefix, disk, p, loader) + */ + errx(42, "Future extension."); + } + memset((char *)&signature, 0, sizeof(signature)); + + fd = open(disk, O_RDONLY|O_DIRECT); + if (fd == -1) + error(42, "Could not open disk %s", disk); + rc = efi_disk_get_partition_info(fd, part, &start, &size, + (uint8_t*)&signature, &mbr_type, &signature_type); + close(fd); + + if (rc) + return -1; + if (mbr_type != 0x02) { + errx(42, "Cowardly refusing non-GPT disk %s", disk); + } + + efi_guid_to_str(&signature, &sigstrp); + + if (opts.verbose && !loader) { + printf("About to delete all entries referring to UUID %s\n", + sigstr); + } else if ( opts.delete != 15) { + printf("About to delete all entries referring to loader %s\n" + " on UUID %s\n", + loader, sigstr); + } + return delete_by_uuid(prefix,sigstr,loader); +} + +/* verbatim copy of same function in efivar/src/creator.c */ +static char * +tilt_slashes(char *s) +{ + char *p; + for (p = s; *p; p++) + if (*p == '/') + *p = '\\'; + return s; +} + +static int +check_uuid(const char *s) +{ + /* algorithm derived from efivar/src/guid.h */ + size_t 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 *prefix, list_t *list) { @@ -1215,7 +1355,9 @@ 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\n"); + printf("\t-B | --delete-bootnum delete bootnum (specified with -b)\n"); + printf("\t --delete delete entry by bootnum (-b), by UUID (-P)\n"); + printf("\t or by disk+partition[+file] (-d -p -l)\n"); printf("\t-c | --create create new variable bootnum and add to bootorder\n"); printf("\t-C | --create-only create new variable bootnum and do not add to bootorder\n"); printf("\t-D | --remove-dups remove duplicate values from BootOrder\n"); @@ -1242,6 +1384,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-t | --timeout seconds set boot manager timeout waiting for user input.\n"); printf("\t-T | --delete-timeout delete Timeout.\n"); @@ -1267,6 +1410,7 @@ set_default_opts() opts.label = (unsigned char *)"Linux"; opts.disk = "/dev/sda"; opts.part = 1; + opts.part_uuid = NULL; } static void @@ -1288,6 +1432,7 @@ parse_opts(int argc, char **argv) {"delete-bootnum", no_argument, 0, 'B'}, {"create", no_argument, 0, 'c'}, {"create-only", no_argument, 0, 'C'}, + {"delete", no_argument, 0, 2}, {"remove-dups", no_argument, 0, 'D'}, {"disk", required_argument, 0, 'd'}, {"iface", required_argument, 0, 'i'}, @@ -1320,7 +1465,7 @@ parse_opts(int argc, char **argv) }; c = getopt_long (argc, argv, - "AaBb:cCDd:e:E:gH:i:l:L:M:m:n:No:Op:qt:TuU:v::Vw" + "AaBb:cCDd:e:E:gH:i:l:L:M:m:n:No:Op:P:qt:TuU:v::Vw" "@:hry", long_options, &option_index); if (c == -1) @@ -1368,11 +1513,16 @@ parse_opts(int argc, char **argv) opts.create = 1; opts.no_order = 1; break; + case 2: + opts.delete |= 1; + break; case 'D': opts.deduplicate = 1; break; case 'd': opts.disk = optarg; + if (opts.delete) + opts.delete |= 2; break; case 'e': rc = sscanf(optarg, "%u", &num); @@ -1410,6 +1560,9 @@ parse_opts(int argc, char **argv) break; case 'l': opts.loader = optarg; + tilt_slashes(opts.loader); + if (opts.delete) + opts.delete |= 8; break; case 'L': opts.label = (unsigned char *)optarg; @@ -1474,6 +1627,17 @@ parse_opts(int argc, char **argv) else errorx(37, "invalid numeric value %s\n", optarg); + if (opts.delete) + 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; @@ -1595,9 +1759,24 @@ main(int argc, char **argv) set_var_nums(prefices[mode], &entry_list); if (opts.delete) { - if (opts.num == -1) + if (opts.part_uuid) { + ret = delete_by_uuid(prefices[mode], opts.part_uuid, + (opts.delete & 8) ? opts.loader : NULL); + if (ret < 0) + error(42, "Could not delete variable(s)"); + } else if (opts.delete & 2) { + ret = delete_by_dpl(prefices[mode], + (opts.delete & 2) ? opts.disk : NULL, + (opts.delete & 4) ? opts.part : 0, + (opts.delete & 8) ? opts.loader : NULL); + if (ret < 0) + error(42, "Could not delete variable(s)"); + } else if (opts.delete > 1) + errorx(3, "Disk and partition must be specified " + "(see the --delete option)."); + else if (opts.num == -1) errorx(3, "You must specify an entry to delete " - "(see the -b option)."); + "(e.g. with the -b option)."); else { ret = delete_var(prefices[mode], opts.num); if (ret < 0) diff --git a/src/include/efibootmgr.h b/src/include/efibootmgr.h index d692d0c..d2d90dc 100644 --- a/src/include/efibootmgr.h +++ b/src/include/efibootmgr.h @@ -60,6 +60,7 @@ typedef struct { int keep_old_entries; char *testfile; char *extra_opts_file; + char *part_uuid; uint32_t part; int edd_version; uint32_t edd10_devicenum; @@ -70,7 +71,7 @@ typedef struct { int below4g; int above4g; int deduplicate; - unsigned int delete:1; + unsigned int delete:4; unsigned int delete_order:1; unsigned int delete_bootnext:1; unsigned int quiet:1; -- 2.6.6
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor