2 efibootmgr.c - Manipulates EFI variables as exported in /proc/efi/vars
4 Copyright (C) 2001-2004 Dell, Inc. <Matt_Domsch@dell.com>
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 This must tie the EFI_DEVICE_PATH to /boot/efi/elilo.efi
22 The EFI_DEVICE_PATH will look something like:
23 ACPI device path, length 12 bytes
24 Hardware Device Path, PCI, length 6 bytes
25 Messaging Device Path, SCSI, length 8 bytes, or ATAPI, length ??
26 Media Device Path, Hard Drive, partition XX, length 30 bytes
27 Media Device Path, File Path, length ??
28 End of Hardware Device Path, length 4
29 Arguments passed to elilo, as UCS-2 characters, length ??
49 #include "unparse_path.h"
51 #include "efibootmgr.h"
54 #ifndef EFIBOOTMGR_VERSION
55 #define EFIBOOTMGR_VERSION "unknown (fix Makefile!)"
59 typedef struct _var_entry {
62 efi_variable_t var_data;
67 /* global variables */
68 static LIST_HEAD(boot_entry_list);
69 static LIST_HEAD(blk_list);
70 efibootmgr_opt_t opts;
73 var_num_from_name(const char *pattern, char *name, uint16_t *num)
75 sscanf(name, pattern, num);
79 fill_bootvar_name(char *dest, size_t len, const char *name)
81 efi_guid_t guid = EFI_GLOBAL_VARIABLE;
83 efi_guid_unparse(&guid, text_uuid);
84 snprintf(dest, len, "%s-%s", name, text_uuid);
88 fill_var(efi_variable_t *var, const char *name)
90 efi_guid_t guid = EFI_GLOBAL_VARIABLE;
92 efichar_from_char(var->VariableName, name, 1024);
93 memcpy(&var->VendorGuid, &guid, sizeof(guid));
94 var->Attributes = EFI_VARIABLE_NON_VOLATILE
95 | EFI_VARIABLE_BOOTSERVICE_ACCESS
96 | EFI_VARIABLE_RUNTIME_ACCESS;
100 free_vars(list_t *head)
105 list_for_each_safe(pos, n, head) {
106 boot = list_entry(pos, var_entry_t, list);
107 list_del(&(boot->list));
113 read_vars(struct dirent **namelist,
121 if (!namelist) return;
123 for (i=0; i < num_boot_names; i++)
126 entry = malloc(sizeof(var_entry_t));
128 memset(entry, 0, sizeof(var_entry_t));
130 status = read_variable(namelist[i]->d_name,
132 if (status != EFI_SUCCESS) break;
133 entry->name = namelist[i];
134 list_add_tail(&entry->list, head);
145 free_dirents(struct dirent **ptr, int num_dirents)
149 for (i=0; i < num_dirents; i++) {
161 compare(const void *a, const void *b)
165 memcpy(&n1, a, sizeof(n1));
166 memcpy(&n2, b, sizeof(n2));
167 if (n1 < n2) rc = -1;
168 if (n1 == n2) rc = 0;
175 Return an available boot variable number,
179 find_free_boot_var(list_t *boot_list)
181 int num_vars=0, i=0, found;
182 uint16_t *vars, free_number;
185 list_for_each(pos, boot_list) {
188 vars = malloc(sizeof(uint16_t) * num_vars);
189 if (!vars) return -1;
190 memset(vars, 0, sizeof(uint16_t) * num_vars);
192 list_for_each(pos, boot_list) {
193 boot = list_entry(pos, var_entry_t, list);
197 qsort(vars, i, sizeof(uint16_t), compare);
201 for (free_number = 0; free_number < num_vars && found; free_number++) {
203 list_for_each(pos, boot_list) {
204 boot = list_entry(pos, var_entry_t, list);
205 if (boot->num == free_number) {
212 if (found && num_vars) free_number = vars[num_vars-1] + 1;
219 warn_duplicate_name(list_t *boot_list)
223 EFI_LOAD_OPTION *load_option;
225 list_for_each(pos, boot_list) {
226 boot = list_entry(pos, var_entry_t, list);
227 load_option = (EFI_LOAD_OPTION *)
229 if (!efichar_char_strcmp(opts.label,
230 load_option->description)) {
231 fprintf(stderr, "** Warning ** : %.8s has same label %s\n",
240 make_boot_var(list_t *boot_list)
246 if (opts.bootnum == -1)
247 free_number = find_free_boot_var(boot_list);
249 list_for_each(pos, boot_list) {
250 boot = list_entry(pos, var_entry_t, list);
251 if (boot->num == opts.bootnum) {
252 fprintf(stderr, "** Warning ** : bootnum %04X "
253 "already exists\n", opts.bootnum);
257 free_number = opts.bootnum;
260 if (free_number == -1) return NULL;
262 /* Create a new var_entry_t object
266 boot = malloc(sizeof(*boot));
267 if (!boot) return NULL;
268 memset(boot, 0, sizeof(*boot));
269 boot->num = free_number;
270 if (!make_linux_efi_variable(&boot->var_data, free_number)) {
274 create_variable(&boot->var_data);
275 list_add_tail(&boot->list, boot_list);
282 read_boot(efi_variable_t *var, const char *name)
284 char name_guid[PATH_MAX];
286 memset(var, 0, sizeof(*var));
287 fill_bootvar_name(name_guid, sizeof(name_guid), name);
288 return read_variable(name_guid, var);
292 read_boot_order(efi_variable_t *boot_order)
296 status = read_boot(boot_order, "BootOrder");
297 if (status != EFI_SUCCESS && status != EFI_NOT_FOUND)
300 if (status == EFI_NOT_FOUND) {
301 fill_var(boot_order, "BootOrder");
308 add_to_boot_order(uint16_t num)
311 efi_variable_t boot_order;
312 uint64_t new_data_size;
313 uint16_t *new_data, *old_data;
315 status = read_boot_order(&boot_order);
316 if (status != EFI_SUCCESS) return status;
318 /* We've now got an array (in boot_order.Data) of the
319 boot order. First add our entry, then copy the old array.
321 old_data = (uint16_t *)&(boot_order.Data);
322 new_data_size = boot_order.DataSize + sizeof(uint16_t);
323 new_data = malloc(new_data_size);
326 memcpy(new_data+1, old_data, boot_order.DataSize);
328 /* Now new_data has what we need */
329 memcpy(&(boot_order.Data), new_data, new_data_size);
330 boot_order.DataSize = new_data_size;
331 return create_or_edit_variable(&boot_order);
336 remove_from_boot_order(uint16_t num)
339 efi_variable_t boot_order;
340 uint64_t new_data_size;
341 uint16_t *new_data, *old_data;
343 char boot_order_name[PATH_MAX];
345 status = read_boot_order(&boot_order);
346 if (status != EFI_SUCCESS) return status;
347 /* If it's empty, yea! */
348 if (!boot_order.DataSize) return EFI_SUCCESS;
350 fill_bootvar_name(boot_order_name, sizeof(boot_order_name),
353 /* We've now got an array (in boot_order.Data) of the
354 boot order. Simply copy the array, skipping the
355 entry we're deleting.
357 old_data = (uint16_t *)&(boot_order.Data);
358 /* Start with the same size */
359 new_data_size = boot_order.DataSize;
360 new_data = malloc(new_data_size);
361 for (old_i=0,new_i=0;
362 old_i < boot_order.DataSize / sizeof(uint16_t);
364 if (old_data[old_i] != num) {
365 /* Copy this value */
366 new_data[new_i] = old_data[old_i];
371 /* Now new_data has what we need */
372 new_data_size = new_i * sizeof(uint16_t);
373 memset(&(boot_order.Data), 0, boot_order.DataSize);
374 memcpy(&(boot_order.Data), new_data, new_data_size);
375 boot_order.DataSize = new_data_size;
377 return edit_variable(&boot_order);
381 delete_var(const char *name)
385 memset(&var, 0, sizeof(var));
386 fill_var(&var, name);
387 return delete_variable(&var);
391 read_boot_u16(const char *name)
395 uint16_t *n = (uint16_t *)(var.Data);
397 memset(&var, 0, sizeof(var));
398 status = read_boot(&var, name);
399 if (status) return -1;
404 set_boot_u16(const char *name, uint16_t num)
407 uint16_t *n = (uint16_t *)var.Data;
409 memset(&var, 0, sizeof(var));
411 fill_var(&var, name);
413 var.DataSize = sizeof(uint16_t);
414 return create_or_edit_variable(&var);
418 delete_boot_var(uint16_t num)
426 snprintf(name, sizeof(name), "Boot%04X", num);
427 memset(&var, 0, sizeof(var));
428 fill_var(&var, name);
429 status = delete_variable(&var);
431 /* For backwards compatibility, try to delete abcdef entries as well */
433 snprintf(name, sizeof(name), "Boot%04x", num);
434 memset(&var, 0, sizeof(var));
435 fill_var(&var, name);
436 status = delete_variable(&var);
440 fprintf (stderr,"\nboot entry: %X not found\n\n",num);
443 list_for_each_safe(pos, n, &boot_entry_list) {
444 boot = list_entry(pos, var_entry_t, list);
445 if (boot->num == num) {
446 status = remove_from_boot_order(num);
447 if (status) return status;
448 list_del(&(boot->list));
449 break; /* short-circuit since it was found */
457 set_var_nums(const char *pattern, list_t *list)
465 list_for_each(pos, list) {
466 var = list_entry(pos, var_entry_t, list);
467 rc = sscanf(var->name->d_name, pattern, &num);
470 name = var->name->d_name; /* shorter name */
471 if ((isalpha(name[4]) && islower(name[4])) ||
472 (isalpha(name[5]) && islower(name[5])) ||
473 (isalpha(name[6]) && islower(name[6])) ||
474 (isalpha(name[7]) && islower(name[7]))) {
475 fprintf(stderr, "** Warning ** : %.8s is not "
476 "EFI 1.10 compliant (lowercase hex in name)\n", name);
482 fprintf(stderr, "** Warning ** : please recreate these using efibootmgr to remove this warning.\n");
487 static efi_variable_t *
488 find_pci_scsi_disk_blk(int fd, int bus, int device, int func,
494 unsigned char host, channel, id, lun;
496 efi_variable_t *blk_var;
499 memset(&idlun, 0, sizeof(idlun));
500 rc = get_scsi_idlun(fd, &idlun);
503 rc = disk_get_size(fd, &size);
505 idlun_to_components(&idlun, &host, &channel, &id, &lun);
507 list_for_each(pos, blk_list) {
508 blk = list_entry(pos, var_entry_t, list);
509 blk_var = blk->var_data;
511 if (!compare_pci_scsi_disk_blk(blk_var,
513 host, channel, id, lun,
524 /* The right blkX variable contains:
525 1) the PCI and SCSI information for the disk passed in disk_name
526 2) Does not contain a partition field
530 static efi_variable_t *
531 find_disk_blk(char *disk_name, list_t *blk_list)
533 efi_variable_t *disk_blk = NULL;
535 unsigned char bus=0,device=0,func=0;
536 int interface_type=interface_type_unknown;
537 unsigned int controllernum=0, disknum=0;
538 unsigned char part=0;
540 fd = open(disk_name, O_RDONLY|O_DIRECT);
541 rc = disk_get_pci(fd, &bus, &device, &func);
543 fprintf(stderr, "disk_get_pci() failed.\n");
546 rc = disk_info_from_fd(fd,
552 fprintf(stderr, "disk_info_from_fd() failed.\n");
555 switch (interface_type)
558 return find_pci_scsi_disk_blk(fd,bus,device,func,blk_list);
561 return find_pci_ata_disk_blk(fd,bus,device,func,blk_list);
564 return find_pci_i2o_disk_blk(fd,bus,device,func,blk_list);
567 return find_pci_md_disk_blk(fd,bus,device,func,blk_list);
577 unparse_boot_order(uint16_t *order, int length)
580 printf("BootOrder: ");
581 for (i=0; i<length; i++) {
582 printf("%04X", order[i]);
590 is_current_boot_entry(int b)
595 list_for_each(pos, &boot_entry_list) {
596 boot = list_entry(pos, var_entry_t, list);
605 parse_boot_order(char *buffer, uint16_t *order, int length)
610 for (i=0; i<length && *buffer; i++) {
611 rc = sscanf(buffer, "%x", &num);
612 if (rc == 1) order[i] = num & 0xFFFF;
614 fprintf(stderr,"\nInvalid hex characters in boot order: %s\n\n",buffer);
617 /* make sure this is an existing boot entry */
618 if (!is_current_boot_entry(order[i])) {
619 fprintf (stderr,"\nboot entry %X does not exist\n\n",order[i]);
623 /* Advance to the comma */
624 while (*buffer && *buffer != ',') buffer++;
625 /* Advance through the comma(s) */
626 while (*buffer && *buffer == ',') buffer++;
634 efi_variable_t boot_order;
635 uint16_t *n = (uint16_t *)boot_order.Data;
637 if (!opts.bootorder) return EFI_SUCCESS;
639 memset(&boot_order, 0, sizeof(boot_order));
640 fill_var(&boot_order, "BootOrder");
642 boot_order.DataSize = parse_boot_order(opts.bootorder, n, 1024/sizeof(uint16_t)) * sizeof(uint16_t);
643 if (boot_order.DataSize < 0)
646 return create_or_edit_variable(&boot_order);
654 char description[80];
655 EFI_LOAD_OPTION *load_option;
656 EFI_DEVICE_PATH *path;
657 char text_path[1024], *p;
658 unsigned long optional_data_len=0;
660 list_for_each(pos, &boot_entry_list) {
661 boot = list_entry(pos, var_entry_t, list);
662 load_option = (EFI_LOAD_OPTION *)
664 efichar_to_char(description,
665 load_option->description, sizeof(description));
666 memset(text_path, 0, sizeof(text_path));
667 path = load_option_path(load_option);
669 printf("%.8s", boot->name->d_name);
671 printf("Boot%04X", boot->num);
673 if (load_option->attributes & LOAD_OPTION_ACTIVE)
676 printf("%s", description);
679 unparse_path(text_path, path,
680 load_option->file_path_list_length);
681 /* Print optional data */
683 boot->var_data.DataSize -
684 load_option->file_path_list_length -
685 ((char *)path - (char *)load_option);
686 if (optional_data_len) {
688 p += strlen(text_path);
689 unparse_raw_text(p, ((uint8_t *)path) +
690 load_option->file_path_list_length,
694 printf("\t%s", text_path);
706 efi_variable_t boot_order;
709 status = read_boot_order(&boot_order);
711 if (status != EFI_SUCCESS) {
712 perror("show_boot_order()");
716 /* We've now got an array (in boot_order.Data) of the
717 boot order. First add our entry, then copy the old array.
719 data = (uint16_t *)&(boot_order.Data);
720 if (boot_order.DataSize)
721 unparse_boot_order(data, boot_order.DataSize / sizeof(uint16_t));
730 EFI_LOAD_OPTION *load_option;
732 list_for_each(pos, &boot_entry_list) {
733 boot = list_entry(pos, var_entry_t, list);
734 load_option = (EFI_LOAD_OPTION *)
736 if (boot->num == opts.bootnum) {
737 if (opts.active == 1) {
738 if (load_option->attributes
739 & LOAD_OPTION_ACTIVE) return EFI_SUCCESS;
741 load_option->attributes
742 |= LOAD_OPTION_ACTIVE;
743 return edit_variable(&boot->var_data);
746 else if (opts.active == 0) {
747 if (!(load_option->attributes
748 & LOAD_OPTION_ACTIVE))
751 load_option->attributes
752 &= ~LOAD_OPTION_ACTIVE;
753 return edit_variable(&boot->var_data);
758 /* if we reach here then the bootnumber supplied was not found */
759 fprintf(stderr,"\nboot entry %x not found\n\n",opts.bootnum);
760 return EFI_NOT_FOUND;
769 printf("efibootmgr version %s\n", EFIBOOTMGR_VERSION);
770 printf("usage: efibootmgr [options]\n");
771 printf("\t-a | --active sets bootnum active\n");
772 printf("\t-A | --inactive sets bootnum inactive\n");
773 printf("\t-b | --bootnum XXXX modify BootXXXX (hex)\n");
774 printf("\t-B | --delete-bootnum delete bootnum (hex)\n");
775 printf("\t-c | --create create new variable bootnum and add to bootorder\n");
776 printf("\t-d | --disk disk (defaults to /dev/sda) containing loader\n");
777 printf("\t-e | --edd [1|3|-1] force EDD 1.0 or 3.0 creation variables, or guess\n");
778 printf("\t-E | --device num EDD 1.0 device number (defaults to 0x80)\n");
779 printf("\t-g | --gpt force disk with invalid PMBR to be treated as GPT\n");
780 printf("\t-H | --acpi_hid XXXX set the ACPI HID (used with -i)\n");
781 printf("\t-i | --iface name create a netboot entry for the named interface\n");
782 printf("\t-l | --loader name (defaults to \\elilo.efi)\n");
783 printf("\t-L | --label label Boot manager display label (defaults to \"Linux\")\n");
784 printf("\t-n | --bootnext XXXX set BootNext to XXXX (hex)\n");
785 printf("\t-N | --delete-bootnext delete BootNext\n");
786 printf("\t-o | --bootorder XXXX,YYYY,ZZZZ,... explicitly set BootOrder (hex)\n");
787 printf("\t-O | --delete-bootorder delete BootOrder\n");
788 printf("\t-p | --part part (defaults to 1) containing loader\n");
789 printf("\t-q | --quiet be quiet\n");
790 printf("\t | --test filename don't write to NVRAM, write to filename.\n");
791 printf("\t-t | --timeout seconds set boot manager timeout waiting for user input.\n");
792 printf("\t-T | --delete-timeout delete Timeout.\n");
793 printf("\t-u | --unicode | --UCS-2 pass extra args as UCS-2 (default is ASCII)\n");
794 printf("\t-U | --acpi_uid XXXX set the ACPI UID (used with -i)\n");
795 printf("\t-v | --verbose print additional information\n");
796 printf("\t-V | --version return version and exit\n");
797 printf("\t-w | --write-signature write unique sig to MBR if needed\n");
798 printf("\t-@ | --append-binary-args file append extra args from file (use \"-\" for stdin)\n");
804 memset(&opts, 0, sizeof(opts));
805 opts.bootnum = -1; /* auto-detect */
806 opts.bootnext = -1; /* Don't set it */
807 opts.active = -1; /* Don't set it */
808 opts.timeout = -1; /* Don't set it */
809 opts.edd10_devicenum = 0x80;
810 opts.loader = "\\elilo.efi";
811 opts.label = "Linux";
812 opts.disk = "/dev/sda";
820 parse_opts(int argc, char **argv)
823 int option_index = 0;
827 static struct option long_options[] =
828 /* name, has_arg, flag, val */
830 {"active", no_argument, 0, 'a'},
831 {"inactive", no_argument, 0, 'A'},
832 {"bootnum", required_argument, 0, 'b'},
833 {"delete-bootnum", no_argument, 0, 'B'},
834 {"create", no_argument, 0, 'c'},
835 {"disk", required_argument, 0, 'd'},
836 {"iface", required_argument, 0, 'i'},
837 {"acpi_hid", required_argument, 0, 'H'},
838 {"edd-device", required_argument, 0, 'E'},
839 {"edd30", required_argument, 0, 'e'},
840 {"gpt", no_argument, 0, 'g'},
841 {"loader", required_argument, 0, 'l'},
842 {"label", required_argument, 0, 'L'},
843 {"bootnext", required_argument, 0, 'n'},
844 {"delete-bootnext", no_argument, 0, 'N'},
845 {"bootorder", required_argument, 0, 'o'},
846 {"delete-bootorder", no_argument, 0, 'O'},
847 {"part", required_argument, 0, 'p'},
848 {"quiet", no_argument, 0, 'q'},
849 {"test", required_argument, 0, 1},
850 {"timeout", required_argument, 0, 't'},
851 {"delete-timeout", no_argument, 0, 'T'},
852 {"unicode", no_argument, 0, 'u'},
853 {"UCS-2", no_argument, 0, 'u'},
854 {"acpi_uid", required_argument, 0, 'U'},
855 {"verbose", optional_argument, 0, 'v'},
856 {"version", no_argument, 0, 'V'},
857 {"write-signature", no_argument, 0, 'w'},
858 {"append-binary-args", required_argument, 0, '@'},
862 c = getopt_long (argc, argv,
863 "AaBb:cd:e:E:gH:i:l:L:n:No:Op:qt:TuU:v::Vw@:",
864 long_options, &option_index);
871 opts.extra_opts_file = optarg;
880 opts.delete_boot = 1;
883 rc = sscanf(optarg, "%X", &num);
884 if (rc == 1) opts.bootnum = num;
886 fprintf (stderr,"invalid hex value %s\n",optarg);
897 rc = sscanf(optarg, "%d", &num);
898 if (rc == 1) opts.edd_version = num;
900 fprintf (stderr,"invalid numeric value %s\n",optarg);
905 rc = sscanf(optarg, "%x", &num);
906 if (rc == 1) opts.edd10_devicenum = num;
908 fprintf (stderr,"invalid hex value %s\n",optarg);
916 rc = sscanf(optarg, "%x", &num);
917 if (rc == 1) opts.acpi_hid = num;
919 fprintf (stderr,"invalid hex value %s\n",optarg);
927 opts.loader = optarg;
933 opts.delete_bootnext = 1;
936 rc = sscanf(optarg, "%x", &num);
937 if (rc == 1) opts.bootnext = num;
939 fprintf (stderr,"invalid hex value %s\n",optarg);
944 opts.bootorder = optarg;
947 opts.delete_bootorder = 1;
950 rc = sscanf(optarg, "%u", &num);
951 if (rc == 1) opts.part = num;
953 fprintf (stderr,"invalid numeric value %s\n",optarg);
961 opts.testfile = optarg;
964 rc = sscanf(optarg, "%u", &num);
967 opts.set_timeout = 1;
970 fprintf (stderr,"invalid numeric value %s\n",optarg);
975 opts.delete_timeout = 1;
982 rc = sscanf(optarg, "%x", &num);
983 if (rc == 1) opts.acpi_uid = num;
985 fprintf (stderr,"invalid hex value %s\n",optarg);
992 if (!strcmp(optarg, "v")) opts.verbose = 2;
993 if (!strcmp(optarg, "vv")) opts.verbose = 3;
994 rc = sscanf(optarg, "%d", &num);
995 if (rc == 1) opts.verbose = num;
997 fprintf (stderr,"invalid numeric value %s\n",optarg);
1003 opts.showversion = 1;
1007 opts.write_signature = 1;
1016 if (optind < argc) {
1019 opts.optind = optind;
1025 main(int argc, char **argv)
1027 struct dirent **boot_names = NULL;
1028 var_entry_t *new_boot = NULL;
1029 int num, num_boot_names=0;
1033 parse_opts(argc, argv);
1034 if (opts.showversion) {
1035 printf("version %s\n", EFIBOOTMGR_VERSION);
1039 if (opts.iface && opts.acpi_hid == -1 && opts.acpi_uid == -1) {
1040 fprintf(stderr, "\nYou must specify the ACPI HID and UID when using -i.\n\n");
1045 set_fs_kernel_calls();
1047 if (!opts.testfile) {
1048 num_boot_names = read_boot_var_names(&boot_names);
1049 read_vars(boot_names, num_boot_names, &boot_entry_list);
1050 set_var_nums("Boot%04X-%*s", &boot_entry_list);
1052 if (opts.delete_boot) {
1053 if (opts.bootnum == -1) {
1054 fprintf(stderr, "\nYou must specify a boot entry to delete (see the -b option).\n\n");
1058 ret = delete_boot_var(opts.bootnum);
1061 if (opts.active >= 0) {
1062 if (opts.bootnum == -1) {
1063 fprintf(stderr, "\nYou must specify a boot entry to delete (see the -b option).\n\n");
1067 ret=set_active_state();
1072 warn_duplicate_name(&boot_entry_list);
1073 new_boot = make_boot_var(&boot_entry_list);
1077 /* Put this boot var in the right BootOrder */
1078 if (!opts.testfile && new_boot)
1079 ret=add_to_boot_order(new_boot->num);
1082 if (!opts.testfile) {
1084 if (opts.delete_bootorder) {
1085 ret=delete_var("BootOrder");
1088 if (opts.bootorder) {
1089 ret=set_boot_order();
1093 if (opts.delete_bootnext) {
1094 ret=delete_var("BootNext");
1097 if (opts.delete_timeout) {
1098 ret=delete_var("Timeout");
1101 if (opts.bootnext >= 0) {
1102 if (!is_current_boot_entry(opts.bootnext & 0xFFFF)){
1103 fprintf (stderr,"\n\nboot entry %X does not exist\n\n",
1107 ret=set_boot_u16("BootNext", opts.bootnext & 0xFFFF);
1110 if (opts.set_timeout) {
1111 ret=set_boot_u16("Timeout", opts.timeout);
1114 if (!opts.quiet && ret == 0) {
1115 num = read_boot_u16("BootNext");
1117 printf("BootNext: %04X\n", num);
1119 num = read_boot_u16("BootCurrent");
1121 printf("BootCurrent: %04X\n", num);
1123 num = read_boot_u16("Timeout");
1125 printf("Timeout: %u seconds\n", num);
1131 free_dirents(boot_names, num_boot_names);
1132 free_vars(&boot_entry_list);