- Patches to efibootmgr.c
- network boot entry creation in efi.c
+Joshua Giles <Joshua_Giles@dell.com>
+- walk the PCI path inserting parent bridge device path components for
+ network boot and EDD30 entries.
default: all
- RELEASE_DATE := "04-Sep-2003"
+ RELEASE_DATE := "09-Jun-2004"
RELEASE_MAJOR := 0
- RELEASE_MINOR := 4
- RELEASE_SUBLEVEL := 2
- RELEASE_EXTRALEVEL :=
+ RELEASE_MINOR := 5
+ RELEASE_SUBLEVEL := 0
+ RELEASE_EXTRALEVEL := -test4
RELEASE_NAME := efibootmgr
RELEASE_STRING := $(RELEASE_NAME)-$(RELEASE_MAJOR).$(RELEASE_MINOR).$(RELEASE_SUBLEVEL)$(RELEASE_EXTRALEVEL)
-O | --delete-bootorder delete BootOrder
-p | --part part (defaults to 1) containing loader
-q | --quiet be quiet
- -t | --test filename don't write to NVRAM, write to filename
+ --test filename don't write to NVRAM, write to filename
+ -t | --timeout seconds Boot manager timeout
+ -T | --delete-timeout delete Timeout value
-u | --unicode | --UCS-2 pass extra args as UCS-2 (default is ASCII)
-U | --acpi_uid XXXX set the ACPI UID (used with -i)
-v | --verbose print additional information
BootCurrent: 0004
BootNext: 0003
BootOrder: 0004,0000,0001,0002,0003
+ Timeout: 30 seconds
Boot0000* Diskette Drive(device:0)
Boot0001* CD-ROM Drive(device:FF)
Boot0002* Hard Drive(Device:80)/HD(Part1,Sig00112233)
boot manager after first use. This allows you to change the next boot
behavior without changing BootOrder.
+ Timeout - the time in seconds between when the boot manager appears
+ on the screen until when it automatically chooses the startup value
+ from BootNext or BootOrder.
+
Five boot entries (0000 - 0004), the active/inactive flag (* means
active), and the name displayed on the screen.
+* Wed Jun 07 2004 Matt Domsch <Matt_Domsch@dell.com>
+- Fixed bug where read_boot_order() would wrongly return EFI_NOT_FOUND
+ when it needed to create a new BootOrder variable. Reported by Micah Parrish.
+- Added code to recursively walk the PCI bus putting parent PCI bridges
+ in. This is necessary for Dell PowerEdge 3250 and 7250 servers and
+ Intel Tiger2 and Tiger4 platforms when creating PXE boot entries for
+ the onboard NICs, and if creating EDD30 boot path entries. Work by Matt
+ and Joshua Giles.
+ - Note, efibootmgr now requires libpci for building.
+- Released v0.5.0-test4
+
+* Sat Apr 24 2004 Matt Domsch <Matt_Domsch@dell.com>
+- Fixed reversed logic of create_or_edit_variable which prevented object
+ creation or editing on sysfs.
+- Removed debug printfs in sysfs read/write commands.
+- Released v0.5.0-test3
+
+* Thu Feb 04 2004 Matt Domsch <Matt_Domsch@dell.com>
+- removed -t short option for --test
+- added -t <timeout> and -T delete timeout options
+- updated man page and README about the timeout options
+- Released v0.5.0-test2
+
+* Tue Sep 09 2003 Matt Domsch <Matt_Domsch@dell.com>
+- Released v0.5.0-test1
+
+* Thu Sep 04 2003 Matt Domsch <Matt_Domsch@dell.com>
+- Seperated access to variables through /proc into efivars_procfs.[ch]
+- Added efivars_sysfs.h to access variables through sysfs.
+- Moved around some functions, cleaned up some duplication.
+
* Thu Sep 04 2003 Matt Domsch <Matt_Domsch@dell.com>
- released v0.4.2-test2 as v0.4.2 without additional changes.
/*
efibootmgr.c - Manipulates EFI variables as exported in /proc/efi/vars
- Copyright (C) 2001 Dell Computer Corporation <Matt_Domsch@dell.com>
+ Copyright (C) 2001-2004 Dell, Inc. <Matt_Domsch@dell.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
#include "disk.h"
#include "efibootmgr.h"
+
#ifndef EFIBOOTMGR_VERSION
#define EFIBOOTMGR_VERSION "unknown (fix Makefile!)"
#endif
sscanf(name, pattern, num);
}
-static int
-select_boot_var_names(const struct dirent *d)
+static void
+fill_bootvar_name(char *dest, size_t len, const char *name)
{
- int num, rc;
- rc = sscanf(d->d_name, "Boot0%03x-%*s", &num);
- return rc;
+ efi_guid_t guid = EFI_GLOBAL_VARIABLE;
+ char text_uuid[40];
+ efi_guid_unparse(&guid, text_uuid);
+ snprintf(dest, len, "%s-%s", name, text_uuid);
}
-#if 0
-static int
-select_blk_var_names(const struct dirent *d)
+static void
+fill_var(efi_variable_t *var, const char *name)
{
- int num;
- return sscanf(d->d_name, "blk%x-%*s", &num);
-}
-#endif
+ efi_guid_t guid = EFI_GLOBAL_VARIABLE;
-static int
-read_boot_var_names(struct dirent ***namelist)
-{
- int n;
- n = scandir(PROC_DIR_EFI_VARS, namelist, select_boot_var_names, alphasort);
- if (n < 0) {
- perror("scandir " PROC_DIR_EFI_VARS);
- fprintf(stderr, "You must 'modprobe efivars' before running efibootmgr.\n");
- }
- return n;
+ efichar_from_char(var->VariableName, name, 1024);
+ memcpy(&var->VendorGuid, &guid, sizeof(guid));
+ var->Attributes = EFI_VARIABLE_NON_VOLATILE
+ | EFI_VARIABLE_BOOTSERVICE_ACCESS
+ | EFI_VARIABLE_RUNTIME_ACCESS;
}
-#if 0
-static int
-read_blk_var_names(struct dirent ***namelist)
-{
- int n;
- n = scandir(PROC_DIR_EFI_VARS, namelist, select_blk_var_names, alphasort);
- if (n < 0)
- perror("scandir");
- return n;
-}
-
-static int
-dirent_list_length(struct dirent **namelist)
-{
- int i;
- if (!namelist) return 0;
- for (i=0; namelist[i]; i++);
- return i;
-}
-#endif
static void
read_vars(struct dirent **namelist,
free(boot);
return NULL;
}
- write_variable(&boot->var_data);
+ create_variable(&boot->var_data);
list_add_tail(&boot->list, boot_list);
return boot;
}
+
+
+static efi_status_t
+read_boot(efi_variable_t *var, const char *name)
+{
+ char name_guid[PATH_MAX];
+
+ memset(var, 0, sizeof(*var));
+ fill_bootvar_name(name_guid, sizeof(name_guid), name);
+ return read_variable(name_guid, var);
+}
+
static efi_status_t
read_boot_order(efi_variable_t *boot_order)
{
efi_status_t status;
- efi_guid_t guid = EFI_GLOBAL_VARIABLE;
- char boot_order_name[80], text_uuid[40];
- efi_guid_unparse(&guid, text_uuid);
-
- memset(boot_order, 0, sizeof(*boot_order));
- sprintf(boot_order_name, "BootOrder-%s", text_uuid);
- status = read_variable(boot_order_name, boot_order);
+ status = read_boot(boot_order, "BootOrder");
if (status != EFI_SUCCESS && status != EFI_NOT_FOUND)
return status;
if (status == EFI_NOT_FOUND) {
- /* Create it */
- efichar_from_char(boot_order->VariableName, "BootOrder",
- 1024);
- memcpy(&boot_order->VendorGuid, &guid, sizeof(guid));
- boot_order->Attributes = EFI_VARIABLE_NON_VOLATILE
- | EFI_VARIABLE_BOOTSERVICE_ACCESS
- | EFI_VARIABLE_RUNTIME_ACCESS;
- return status;
+ fill_var(boot_order, "BootOrder");
}
return EFI_SUCCESS;
}
-
-
static efi_status_t
add_to_boot_order(uint16_t num)
{
/* Now new_data has what we need */
memcpy(&(boot_order.Data), new_data, new_data_size);
boot_order.DataSize = new_data_size;
- return write_variable(&boot_order);
+ return create_or_edit_variable(&boot_order);
}
uint64_t new_data_size;
uint16_t *new_data, *old_data;
int old_i,new_i;
+ char boot_order_name[PATH_MAX];
status = read_boot_order(&boot_order);
if (status != EFI_SUCCESS) return status;
-
/* If it's empty, yea! */
if (!boot_order.DataSize) return EFI_SUCCESS;
+ fill_bootvar_name(boot_order_name, sizeof(boot_order_name),
+ "BootOrder");
+
/* We've now got an array (in boot_order.Data) of the
boot order. Simply copy the array, skipping the
entry we're deleting.
memcpy(&(boot_order.Data), new_data, new_data_size);
boot_order.DataSize = new_data_size;
- return write_variable(&boot_order);
+ return edit_variable(&boot_order);
}
-static int
-read_boot_current()
+static efi_status_t
+delete_var(const char *name)
{
- efi_status_t status;
- efi_variable_t boot_next;
- efi_guid_t guid = EFI_GLOBAL_VARIABLE;
- char boot_next_name[80], text_uuid[40];
- uint16_t *n = (uint16_t *)(boot_next.Data);
-
- efi_guid_unparse(&guid, text_uuid);
-
- memset(&boot_next, 0, sizeof(boot_next));
- sprintf(boot_next_name, "BootCurrent-%s", text_uuid);
-
- status = read_variable(boot_next_name, &boot_next);
- if (status) return -1;
+ efi_variable_t var;
- return *n;
+ memset(&var, 0, sizeof(var));
+ fill_var(&var, name);
+ return delete_variable(&var);
}
static int
-read_boot_next()
+read_boot_u16(const char *name)
{
efi_status_t status;
- efi_variable_t boot_next;
- efi_guid_t guid = EFI_GLOBAL_VARIABLE;
- char boot_next_name[80], text_uuid[40];
- uint16_t *n = (uint16_t *)(boot_next.Data);
-
- efi_guid_unparse(&guid, text_uuid);
-
- memset(&boot_next, 0, sizeof(boot_next));
- sprintf(boot_next_name, "BootNext-%s", text_uuid);
+ efi_variable_t var;
+ uint16_t *n = (uint16_t *)(var.Data);
- status = read_variable(boot_next_name, &boot_next);
+ memset(&var, 0, sizeof(var));
+ status = read_boot(&var, name);
if (status) return -1;
-
return *n;
}
-
static efi_status_t
-set_boot_next(uint16_t num)
+set_boot_u16(const char *name, uint16_t num)
{
efi_variable_t var;
- efi_guid_t guid = EFI_GLOBAL_VARIABLE;
uint16_t *n = (uint16_t *)var.Data;
memset(&var, 0, sizeof(var));
- efichar_from_char(var.VariableName, "BootNext",
- 1024);
- memcpy(&var.VendorGuid, &guid, sizeof(guid));
+ fill_var(&var, name);
*n = num;
var.DataSize = sizeof(uint16_t);
- var.Attributes = EFI_VARIABLE_NON_VOLATILE
- | EFI_VARIABLE_BOOTSERVICE_ACCESS
- | EFI_VARIABLE_RUNTIME_ACCESS;
- return write_variable(&var);
+ return create_or_edit_variable(&var);
}
-static efi_status_t
-delete_boot_next()
-{
- efi_variable_t var;
- efi_guid_t guid = EFI_GLOBAL_VARIABLE;
-
- memset(&var, 0, sizeof(var));
-
- efichar_from_char(var.VariableName, "BootNext",
- 1024);
- memcpy(&var.VendorGuid, &guid, sizeof(guid));
- return write_variable(&var);
-}
-
-
static efi_status_t
delete_boot_var(uint16_t num)
{
efi_status_t status;
efi_variable_t var;
- efi_guid_t guid = EFI_GLOBAL_VARIABLE;
- char name[80];
+ char name[16];
list_t *pos, *n;
var_entry_t *boot;
- sprintf(name, "Boot%04x", num);
+ snprintf(name, sizeof(name), "Boot%04x", num);
memset(&var, 0, sizeof(var));
-
- efichar_from_char(var.VariableName, name, 1024);
- memcpy(&var.VendorGuid, &guid, sizeof(guid));
- status = write_variable(&var);
+ fill_var(&var, name);
+ status = delete_variable(&var);
if (status) return status;
static efi_status_t
set_boot_order()
{
- efi_variable_t var;
- efi_guid_t guid = EFI_GLOBAL_VARIABLE;
- uint16_t *n = (uint16_t *)var.Data;
+ efi_variable_t boot_order;
+ uint16_t *n = (uint16_t *)boot_order.Data;
if (!opts.bootorder) return EFI_SUCCESS;
- memset(&var, 0, sizeof(var));
+ memset(&boot_order, 0, sizeof(boot_order));
+ fill_var(&boot_order, "BootOrder");
- efichar_from_char(var.VariableName, "BootOrder",
- 1024);
- memcpy(&var.VendorGuid, &guid, sizeof(guid));
- var.Attributes = EFI_VARIABLE_NON_VOLATILE
- | EFI_VARIABLE_BOOTSERVICE_ACCESS
- | EFI_VARIABLE_RUNTIME_ACCESS;
-
- var.DataSize = parse_boot_order(opts.bootorder, n, 1024/sizeof(uint16_t)) * sizeof(uint16_t);
- return write_variable(&var);
+ boot_order.DataSize = parse_boot_order(opts.bootorder, n, 1024/sizeof(uint16_t)) * sizeof(uint16_t);
+ return create_or_edit_variable(&boot_order);
}
static void
else {
load_option->attributes
|= LOAD_OPTION_ACTIVE;
- return write_variable(&boot->var_data);
+ return edit_variable(&boot->var_data);
}
}
else if (opts.active == 0) {
else {
load_option->attributes
&= ~LOAD_OPTION_ACTIVE;
- return write_variable(&boot->var_data);
+ return edit_variable(&boot->var_data);
}
}
}
-static efi_status_t
-delete_boot_order()
-{
- efi_variable_t var;
- efi_guid_t guid = EFI_GLOBAL_VARIABLE;
-
- memset(&var, 0, sizeof(var));
-
- efichar_from_char(var.VariableName, "BootOrder",
- 1024);
- memcpy(&var.VendorGuid, &guid, sizeof(guid));
- return write_variable(&var);
-}
-
static void
usage()
printf("\t-O | --delete-bootorder delete BootOrder\n");
printf("\t-p | --part part (defaults to 1) containing loader\n");
printf("\t-q | --quiet be quiet\n");
- printf("\t-t | --test filename don't write to NVRAM, write to filename.\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");
+ printf("\t-T | --delete-timeout delete Timeout.\n");
printf("\t-u | --unicode | --UCS-2 pass extra args as UCS-2 (default is ASCII)\n");
printf("\t-U | --acpi_uid XXXX set the ACPI UID (used with -i)\n");
printf("\t-v | --verbose print additional information\n");
opts.bootnum = -1; /* auto-detect */
opts.bootnext = -1; /* Don't set it */
opts.active = -1; /* Don't set it */
+ opts.timeout = -1; /* Don't set it */
opts.edd10_devicenum = 0x80;
opts.loader = "\\elilo.efi";
opts.label = "Linux";
{"create", no_argument, 0, 'c'},
{"disk", required_argument, 0, 'd'},
{"iface", required_argument, 0, 'i'},
- {"acpi_hid", required_argument, 0, 'H' },
+ {"acpi_hid", required_argument, 0, 'H'},
{"edd-device", required_argument, 0, 'E'},
{"edd30", required_argument, 0, 'e'},
{"gpt", no_argument, 0, 'g'},
{"delete-bootorder", no_argument, 0, 'O'},
{"part", required_argument, 0, 'p'},
{"quiet", no_argument, 0, 'q'},
- {"test", required_argument, 0, 't'},
+ {"test", required_argument, 0, 1},
+ {"timeout", required_argument, 0, 't'},
+ {"delete-timeout", no_argument, 0, 'T'},
{"unicode", no_argument, 0, 'u'},
{"UCS-2", no_argument, 0, 'u'},
- {"acpi_uid", required_argument, 0, 'U' },
+ {"acpi_uid", required_argument, 0, 'U'},
{"verbose", optional_argument, 0, 'v'},
{"version", no_argument, 0, 'V'},
{"write-signature", no_argument, 0, 'w'},
};
c = getopt_long (argc, argv,
- "AaBb:cd:e:E:gH:i:l:L:n:No:Op:qt:uU:v::Vw",
+ "AaBb:cd:e:E:gH:i:l:L:n:No:Op:qt:TuU:v::Vw",
long_options, &option_index);
if (c == -1)
break;
case 'q':
opts.quiet = 1;
break;
- case 't':
+ case 1:
opts.testfile = optarg;
break;
+ case 't':
+ rc = sscanf(optarg, "%u", &num);
+ if (rc == 1) {
+ opts.timeout = num;
+ opts.set_timeout = 1;
+ }
+ break;
+ case 'T':
+ opts.delete_timeout = 1;
+ break;
case 'u':
opts.unicode = 1;
break;
return 1;
}
+ if (!opts.testfile)
+ set_fs_kernel_calls();
+
if (!opts.testfile) {
num_boot_names = read_boot_var_names(&boot_names);
read_vars(boot_names, num_boot_names, &boot_entry_list);
if (!opts.testfile) {
if (opts.delete_bootorder) {
- delete_boot_order();
+ delete_var("BootOrder");
}
if (opts.bootorder) {
if (opts.delete_bootnext) {
- delete_boot_next();
+ delete_var("BootNext");
+ }
+
+ if (opts.delete_timeout) {
+ delete_var("Timeout");
}
if (opts.bootnext >= 0) {
- set_boot_next(opts.bootnext & 0xFFFF);
+ set_boot_u16("BootNext", opts.bootnext & 0xFFFF);
+ }
+
+ if (opts.set_timeout) {
+ set_boot_u16("Timeout", opts.timeout);
}
if (!opts.quiet) {
- num = read_boot_next();
+ num = read_boot_u16("BootNext");
if (num != -1 ) {
printf("BootNext: %04x\n", num);
}
- num = read_boot_current();
+ num = read_boot_u16("BootCurrent");
if (num != -1) {
printf("BootCurrent: %04x\n", num);
}
+ num = read_boot_u16("Timeout");
+ if (num != -1) {
+ printf("Timeout: %u seconds\n", num);
+ }
show_boot_order();
show_boot_vars();
}
efibootmgr_OBJECTS := efibootmgr.o
efibootmgr_TARGETS := efibootmgr
efibootmgr_FULLTARGET := \
- $(patsubst %, $(efibootmgr_SRCDIR)/%, $(efibootmgr_TARGETS))
+ $(patsubst %, $(efibootmgr_SRCDIR)/%, $(efibootmgr_TARGETS))
efibootmgr_FULLOBJECT := \
- $(patsubst %, $(efibootmgr_SRCDIR)/%, $(efibootmgr_OBJECT))
+ $(patsubst %, $(efibootmgr_SRCDIR)/%, $(efibootmgr_OBJECT))
efibootmgr_LIBS := crc32.o disk.o efi.o efichar.o gpt.o scsi_ioctls.o \
- unparse_path.o
+ unparse_path.o efivars_procfs.o efivars_sysfs.o
efibootmgr_LIBDIR := src/lib
efibootmgr_FULLLIB := \
- $(patsubst %,$(efibootmgr_LIBDIR)/%,$(efibootmgr_LIBS))
+ $(patsubst %,$(efibootmgr_LIBDIR)/%,$(efibootmgr_LIBS))
+LIBS = -lpci
-ALLDEPS += $(efibootmgr_FULLTARGET)
+ALLDEPS += $(efibootmgr_FULLTARGET)
CLEANLIST += $(efibootmgr_FULLTARGET)
CLEANLIST += $(efibootmgr_FULLOBJECT)
-bindir_TARGETS += $(efibootmgr_FULLTARGET)
+bindir_TARGETS += $(efibootmgr_FULLTARGET)
$(efibootmgr_FULLTARGET): \
- $(efibootmgr_FULLOBJECT) \
- $(efibootmgr_FULLLIB)
+ $(efibootmgr_FULLOBJECT) \
+ $(efibootmgr_FULLLIB) \
+ $(LIBS)
/*
- efi.[ch] - Manipulates EFI variables as exported in /proc/efi/vars
-
- Copyright (C) 2001 Dell Computer Corporation <Matt_Domsch@dell.com>
-
+ efi.[ch] - Extensible Firmware Interface definitions
+
+ Copyright (C) 2001, 2003 Dell Computer Corporation <Matt_Domsch@dell.com>
+
This program 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 2 of the License, or
* version 1.02, 12 December, 2000
*/
#include <stdint.h>
+#include <dirent.h>
#define BITS_PER_LONG (sizeof(unsigned long) * 8)
} __attribute__((packed)) END_DEVICE_PATH;
-/* Used for ACPI _HID */
-#define EISAID_PNP0A03 0xa0341d0
-
-#define PROC_DIR_EFI_VARS "/proc/efi/vars/"
+struct efivar_kernel_calls {
+ efi_status_t (*read)(const char *name, efi_variable_t *var);
+ efi_status_t (*edit)(const char *name, efi_variable_t *var);
+ efi_status_t (*create)(efi_variable_t *var);
+ efi_status_t (*delete)(efi_variable_t *var);
+ char *path;
+};
+/* Used for ACPI _HID */
+#define EISAID_PNP0A03 0xa0341d0
/* Exported functions */
-efi_status_t read_variable(char *name, efi_variable_t *var);
-efi_status_t write_variable(efi_variable_t *var);
-int make_linux_efi_variable(efi_variable_t *var,
+extern int make_linux_efi_variable(efi_variable_t *var,
unsigned int free_number);
-char * efi_guid_unparse(efi_guid_t *guid, char *out);
-EFI_DEVICE_PATH *load_option_path(EFI_LOAD_OPTION *option);
-
-
+extern char * efi_guid_unparse(efi_guid_t *guid, char *out);
+extern EFI_DEVICE_PATH *load_option_path(EFI_LOAD_OPTION *option);
+extern efi_status_t read_variable(const char *name, efi_variable_t *var);
+extern efi_status_t edit_variable(efi_variable_t *var);
+extern efi_status_t create_variable(efi_variable_t *var);
+extern efi_status_t delete_variable(efi_variable_t *var);
+extern efi_status_t create_or_edit_variable(efi_variable_t *var);
+extern void set_fs_kernel_calls();
+extern int read_boot_var_names(struct dirent ***namelist);
+extern int variable_to_name(efi_variable_t *var, char *name);
+extern int var_name_to_path(const char *name, char *path);
-#endif /* _ASM_IA64_EFI_H */
+#endif /* EFI_H */
unsigned int unicode:1;
unsigned int write_signature:1;
unsigned int forcegpt:1;
+ unsigned int set_timeout:1;
+ unsigned int delete_timeout:1;
+ unsigned short int timeout;
} efibootmgr_opt_t;
--- /dev/null
+/*
+ efivars_procfs.h - EFI Variables accessed through /proc/efi/vars
+
+ Copyright (C) 2003 Dell Computer Corporation <Matt_Domsch@dell.com>
+
+ This program 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 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef EFIVARS_PROCFS_H
+#define EFIVARS_PROCFS_H
+
+#include "efi.h"
+
+#define PROCFS_DIR_EFI_VARS "/proc/efi/vars"
+
+extern struct efivar_kernel_calls procfs_kernel_calls;
+
+#endif /* EFIVARS_PROCFS_H */
--- /dev/null
+/*
+ efivars_sysfs.h - EFI Variables accessed through /sys/firmware/efi/vars
+
+ Copyright (C) 2003 Dell Computer Corporation <Matt_Domsch@dell.com>
+
+ This program 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 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef EFIVARS_SYSFS_H
+#define EFIVARS_SYSFS_H
+
+#include "efi.h"
+
+#define SYSFS_DIR_EFI_VARS "/sys/firmware/efi/vars"
+
+extern struct efivar_kernel_calls sysfs_kernel_calls;
+
+#endif /* EFIVARS_SYSFS_H */
/*
- efi.[ch] - Manipulates EFI variables as exported in /proc/efi/vars
+ efivars_proc.[ch] - Manipulates EFI variables as exported in /proc/efi/vars
Copyright (C) 2001,2003 Dell Computer Corporation <Matt_Domsch@dell.com>
#include <sys/ioctl.h>
#include <linux/sockios.h>
#include <net/if.h>
-
-typedef unsigned long long u64; /* hack, so we may include kernel's ethtool.h */
-typedef __uint32_t u32; /* ditto */
-typedef __uint16_t u16; /* ditto */
-typedef __uint8_t u8; /* ditto */
-
+#include <pci/pci.h>
#include <linux/ethtool.h>
#include "efi.h"
#include "efichar.h"
#include "scsi_ioctls.h"
#include "disk.h"
#include "efibootmgr.h"
+#include "efivars_procfs.h"
+#include "efivars_sysfs.h"
+#include "list.h"
+
+static struct efivar_kernel_calls *fs_kernel_calls;
EFI_DEVICE_PATH *
load_option_path(EFI_LOAD_OPTION *option)
return out;
}
-
-efi_status_t
-read_variable(char *name, efi_variable_t *var)
+void
+set_fs_kernel_calls()
{
- int newnamesize;
- char *newname;
- int fd;
- size_t readsize;
- if (!name || !var) return EFI_INVALID_PARAMETER;
-
- newnamesize = strlen(PROC_DIR_EFI_VARS) + strlen(name) + 1;
- newname = malloc(newnamesize);
- if (!newname) return EFI_OUT_OF_RESOURCES;
- sprintf(newname, "%s%s", PROC_DIR_EFI_VARS,name);
- fd = open(newname, O_RDONLY);
- if (fd == -1) {
- free(newname);
- return EFI_NOT_FOUND;
+ char name[PATH_MAX];
+ DIR *dir;
+ snprintf(name, PATH_MAX, "%s", SYSFS_DIR_EFI_VARS);
+ dir = opendir(name);
+ if (dir) {
+ closedir(dir);
+ fs_kernel_calls = &sysfs_kernel_calls;
+ return;
}
- readsize = read(fd, var, sizeof(*var));
- if (readsize != sizeof(*var)) {
- free(newname);
- close(fd);
- return EFI_INVALID_PARAMETER;
+
+ snprintf(name, PATH_MAX, "%s", PROCFS_DIR_EFI_VARS);
+ dir = opendir(name);
+ if (dir) {
+ closedir(dir);
+ fs_kernel_calls = &procfs_kernel_calls;
+ return;
}
- close(fd);
- free(newname);
- return var->Status;
+ fprintf(stderr, "Fatal: Couldn't open either sysfs or procfs directories for accessing EFI variables.\n");
+ fprintf(stderr, "Try 'modprobe efivars' as root.\n");
+ exit(1);
}
+
+
static efi_status_t
write_variable_to_file(efi_variable_t *var)
{
close(fd);
return EFI_SUCCESS;
}
-/**
- * select_variable_names()
- * @d - dirent to compare against
- *
- * This ignores "." and ".." entries, and selects all others.
- */
-static int
-select_variable_names(const struct dirent *d)
+efi_status_t
+read_variable(const char *name, efi_variable_t *var)
{
- if (!strcmp(d->d_name, ".") ||
- !strcmp(d->d_name, ".."))
- return 0;
- return 1;
+ if (!name || !var) return EFI_INVALID_PARAMETER;
+ return fs_kernel_calls->read(name, var);
}
-/**
- * find_write_victim()
- * @var - variable to be written
- * @file - name of file to open for writing @var is returned.
- *
- * This ignores "." and ".." entries, and selects all others.
- */
-static char *
-find_write_victim(efi_variable_t *var, char file[PATH_MAX])
-{
- struct dirent **namelist = NULL;
- int i, n, found=0;
- char testname[PATH_MAX], *p;
-
- memset(testname, 0, sizeof(testname));
- n = scandir(PROC_DIR_EFI_VARS, &namelist,
- select_variable_names, alphasort);
- if (n < 0) {
- perror("scandir " PROC_DIR_EFI_VARS);
- fprintf(stderr, "You must 'modprobe efivars' first.\n");
- return NULL;
- }
+efi_status_t
+create_variable(efi_variable_t *var)
+{
+ if (!var) return EFI_INVALID_PARAMETER;
+ if (opts.testfile) return write_variable_to_file(var);
+ return fs_kernel_calls->create(var);
+}
- p = testname;
- efichar_to_char(p, var->VariableName, PATH_MAX);
- p += strlen(p);
- p += sprintf(p, "-");
- efi_guid_unparse(&var->VendorGuid, p);
+efi_status_t
+delete_variable(efi_variable_t *var)
+{
+ if (!var) return EFI_INVALID_PARAMETER;
+ if (opts.testfile) return write_variable_to_file(var);
+ return fs_kernel_calls->delete(var);
+}
- for (i=0; i<n; i++) {
- if (namelist[i] &&
- strncmp(testname, namelist[i]->d_name, sizeof(testname))) {
- found++;
- sprintf(file, "%s%s", PROC_DIR_EFI_VARS,
- namelist[i]->d_name);
- break;
- }
- }
- while (n--) {
- if (namelist[n]) {
- free(namelist[n]);
- namelist[n] = NULL;
- }
- }
- free(namelist);
+efi_status_t
+edit_variable(efi_variable_t *var)
+{
+ char name[PATH_MAX];
+ if (!var) return EFI_INVALID_PARAMETER;
+ if (opts.testfile) return write_variable_to_file(var);
- if (!found) return NULL;
- return file;
+ variable_to_name(var, name);
+ return fs_kernel_calls->edit(name, var);
}
-
efi_status_t
-write_variable(efi_variable_t *var)
+create_or_edit_variable(efi_variable_t *var)
{
- int fd;
- size_t writesize;
- char buffer[PATH_MAX], name[PATH_MAX], *p = NULL;
+ efi_variable_t testvar;
+ char name[PATH_MAX];
- if (!var) return EFI_INVALID_PARAMETER;
- if (opts.testfile) return write_variable_to_file(var);
- memset(buffer, 0, sizeof(buffer));
- memset(name, 0, sizeof(name));
+ memcpy(&testvar, var, sizeof(*var));
+ variable_to_name(var, name);
- p = find_write_victim(var, name);
- if (!p) return EFI_INVALID_PARAMETER;
+ if (read_variable(name, &testvar) == EFI_SUCCESS)
+ return edit_variable(var);
+ else
+ return create_variable(var);
+}
- fd = open(name, O_WRONLY);
- if (fd == -1) {
- sprintf(buffer, "write_variable():open(%s)", name);
- perror(buffer);
- return EFI_INVALID_PARAMETER;
- }
- writesize = write(fd, var, sizeof(*var));
- if (writesize != sizeof(*var)) {
-#if 0
- sprintf(buffer, "write_variable():write(%s)", name);
- perror(buffer);
- dump_raw_data(var, sizeof(*var));
-#endif
- close(fd);
- return EFI_INVALID_PARAMETER;
+static int
+select_boot_var_names(const struct dirent *d)
+{
+ int num, rc;
+ rc = sscanf(d->d_name, "Boot0%03x-%*s", &num);
+ return rc;
+}
- }
- close(fd);
- return EFI_SUCCESS;
+int
+read_boot_var_names(struct dirent ***namelist)
+{
+ if (!fs_kernel_calls || !namelist) return -1;
+ return scandir(fs_kernel_calls->path,
+ namelist, select_boot_var_names,
+ alphasort);
}
return p.length;
}
+struct device
+{
+ struct pci_dev *pci_dev;
+ struct list_head node;
+};
+
+static struct device *
+is_parent_bridge(struct pci_dev *p, unsigned int target_bus)
+{
+ struct device *d;
+ unsigned int primary, secondary;
+
+ if ( (pci_read_word(p, PCI_HEADER_TYPE) & 0x7f) != PCI_HEADER_TYPE_BRIDGE)
+ return NULL;
+
+ primary=pci_read_byte(p, PCI_PRIMARY_BUS);
+ secondary=pci_read_byte(p, PCI_SECONDARY_BUS);
+
+
+ if (secondary != target_bus)
+ return NULL;
+
+ d = malloc(sizeof(struct device));
+ if (!d)
+ return NULL;
+ memset(d, 0, sizeof(*d));
+ INIT_LIST_HEAD(&d->node);
+
+ d->pci_dev = p;
+
+ return d;
+}
+
+static struct device *
+find_parent(struct pci_access *pacc, unsigned int target_bus)
+{
+ struct device *dev;
+ struct pci_dev *p;
+
+ for (p=pacc->devices; p; p=p->next) {
+ dev = is_parent_bridge(p, target_bus);
+ if (dev)
+ return dev;
+ }
+ return NULL;
+}
+
static uint16_t
-make_pci_device_path(void *dest, uint8_t device, uint8_t function)
+make_one_pci_device_path(void *dest, uint8_t device, uint8_t function)
{
PCI_DEVICE_PATH p;
memset(&p, 0, sizeof(p));
return p.length;
}
+static uint16_t
+make_pci_device_path(void *dest, uint8_t bus, uint8_t device, uint8_t function)
+{
+ struct device *dev;
+ struct pci_access *pacc;
+ struct list_head *pos, *n;
+ LIST_HEAD(pci_parent_list);
+ char *p = dest;
+
+ pacc = pci_alloc();
+ if (!pacc)
+ return 0;
+
+ pci_init(pacc);
+ pci_scan_bus(pacc);
+
+ do {
+ dev = find_parent(pacc, bus);
+ if (dev) {
+ list_add(&pci_parent_list, &dev->node);
+ bus = dev->pci_dev->bus;
+ }
+ } while (dev && bus);
+
+
+ list_for_each_safe(pos, n, &pci_parent_list) {
+ dev = list_entry(pos, struct device, node);
+ p += make_one_pci_device_path(p,
+ dev->pci_dev->dev,
+ dev->pci_dev->func);
+ list_del(&dev->node);
+ free(dev);
+ }
+
+ p += make_one_pci_device_path(p, device, function);
+
+ pci_cleanup(pacc);
+
+ return ((void *)p - dest);
+}
+
static uint16_t
make_scsi_device_path(void *dest, uint16_t id, uint16_t lun)
{
idlun_to_components(&idlun, &host, &channel, &id, &lun);
p += make_acpi_device_path (p, EISAID_PNP0A03, bus);
- p += make_pci_device_path (p, device, function);
+ p += make_pci_device_path (p, bus, device, function);
p += make_scsi_device_path (p, id, lun);
return ((void *)p - buffer);
}
char *make_net_load_option(char *p, char *iface)
{
/* copied pretty much verbatim from the ethtool source */
- int fd = 0, err;
+ int fd = 0, err;
int bus, slot, func;
struct ifreq ifr;
struct ethtool_drvinfo drvinfo;
perror("Cannot get driver information");
}
+
err = sscanf(drvinfo.bus_info, "%2x:%2x.%x", &bus, &slot, &func);
if (err == 0) {
perror("Couldn't parse device location string.");
}
p += make_acpi_device_path(p, opts.acpi_hid, opts.acpi_uid);
- p += make_pci_device_path(p, (uint8_t)slot, (uint8_t)func);
+ p += make_pci_device_path(p, bus, (uint8_t)slot, (uint8_t)func);
err = ioctl(fd, SIOCGIFHWADDR, &ifr);
if (err < 0) {
p += make_mac_addr_device_path(p, ifr.ifr_ifru.ifru_hwaddr.sa_data, 0);
p += make_end_device_path (p);
-
return(p);
}
var->DataSize = load_option_size + opt_data_size;
return var->DataSize;
}
+
+
+int
+variable_to_name(efi_variable_t *var, char *name)
+{
+ char *p = name;
+ efichar_to_char(p, var->VariableName, PATH_MAX);
+ p += strlen(p);
+ p += sprintf(p, "-");
+ efi_guid_unparse(&var->VendorGuid, p);
+ return strlen(name);
+}
--- /dev/null
+/*
+ efivars_procfs.[ch] - Manipulates EFI variables as exported in /proc/efi/vars
+
+ Copyright (C) 2001,2003 Dell Computer Corporation <Matt_Domsch@dell.com>
+
+ This program 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 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#define _FILE_OFFSET_BITS 64
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <stdint.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <sys/types.h>
+#include <fcntl.h>
+
+#include "efi.h"
+#include "efichar.h"
+#include "efibootmgr.h"
+#include "efivars_procfs.h"
+
+static efi_status_t
+procfs_read_variable(const char *name, efi_variable_t *var)
+{
+ char filename[PATH_MAX];
+ int fd;
+ size_t readsize;
+ if (!name || !var) return EFI_INVALID_PARAMETER;
+
+ snprintf(filename, PATH_MAX-1, "%s/%s", PROCFS_DIR_EFI_VARS,name);
+ fd = open(filename, O_RDONLY);
+ if (fd == -1) {
+ return EFI_NOT_FOUND;
+ }
+ readsize = read(fd, var, sizeof(*var));
+ if (readsize != sizeof(*var)) {
+ close(fd);
+ return EFI_INVALID_PARAMETER;
+ }
+ close(fd);
+ return var->Status;
+}
+
+/**
+ * select_variable_names()
+ * @d - dirent to compare against
+ *
+ * This ignores "." and ".." entries, and selects all others.
+ */
+
+static int
+select_variable_names(const struct dirent *d)
+{
+ if (!strcmp(d->d_name, ".") ||
+ !strcmp(d->d_name, ".."))
+ return 0;
+ return 1;
+}
+
+/**
+ * find_write_victim()
+ * @var - variable to be written
+ * @file - name of file to open for writing @var is returned.
+ *
+ * This ignores "." and ".." entries, and selects all others.
+ */
+static char *
+find_write_victim(efi_variable_t *var, char file[PATH_MAX])
+{
+ struct dirent **namelist = NULL;
+ int i, n, found=0;
+ char testname[PATH_MAX], *p;
+
+ memset(testname, 0, sizeof(testname));
+ n = scandir(PROCFS_DIR_EFI_VARS, &namelist,
+ select_variable_names, alphasort);
+ if (n < 0)
+ return NULL;
+
+ p = testname;
+ efichar_to_char(p, var->VariableName, PATH_MAX);
+ p += strlen(p);
+ p += sprintf(p, "-");
+ efi_guid_unparse(&var->VendorGuid, p);
+
+ for (i=0; i<n; i++) {
+ if (namelist[i] &&
+ strncmp(testname, namelist[i]->d_name, sizeof(testname))) {
+ found++;
+ sprintf(file, "%s/%s", PROCFS_DIR_EFI_VARS,
+ namelist[i]->d_name);
+ break;
+ }
+ }
+
+ while (n--) {
+ if (namelist[n]) {
+ free(namelist[n]);
+ namelist[n] = NULL;
+ }
+ }
+ free(namelist);
+
+ if (!found) return NULL;
+ return file;
+}
+
+
+static efi_status_t
+procfs_write_variable(efi_variable_t *var)
+{
+ int fd;
+ size_t writesize;
+ char buffer[PATH_MAX], name[PATH_MAX], *p = NULL;
+
+ if (!var) return EFI_INVALID_PARAMETER;
+ memset(buffer, 0, sizeof(buffer));
+ memset(name, 0, sizeof(name));
+
+ p = find_write_victim(var, name);
+ if (!p) return EFI_INVALID_PARAMETER;
+
+ fd = open(name, O_WRONLY);
+ if (fd == -1) {
+ sprintf(buffer, "write_variable():open(%s)", name);
+ perror(buffer);
+ return EFI_INVALID_PARAMETER;
+ }
+ writesize = write(fd, var, sizeof(*var));
+ if (writesize != sizeof(*var)) {
+ close(fd);
+ return EFI_INVALID_PARAMETER;
+
+ }
+ close(fd);
+ return EFI_SUCCESS;
+}
+
+static efi_status_t
+procfs_delete_variable(efi_variable_t *var)
+{
+ if (!var) return EFI_INVALID_PARAMETER;
+ var->DataSize = 0;
+ var->Attributes = 0;
+ return procfs_write_variable(var);
+
+}
+
+static efi_status_t
+procfs_edit_variable(const char *unused, efi_variable_t *var)
+{
+ if (!var) return EFI_INVALID_PARAMETER;
+ return procfs_write_variable(var);
+
+}
+
+struct efivar_kernel_calls procfs_kernel_calls = {
+ .read = procfs_read_variable,
+ .edit = procfs_edit_variable,
+ .create = procfs_write_variable,
+ .delete = procfs_delete_variable,
+ .path = PROCFS_DIR_EFI_VARS,
+};
--- /dev/null
+/*
+ efivars_sysfs.[ch] - Manipulates EFI variables as exported in /sys/firmware/efi/vars
+
+ Copyright (C) 2001,2003 Dell Computer Corporation <Matt_Domsch@dell.com>
+
+ This program 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 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#define _FILE_OFFSET_BITS 64
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <stdint.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <sys/types.h>
+#include <fcntl.h>
+
+#include "efi.h"
+#include "efichar.h"
+#include "efibootmgr.h"
+#include "efivars_sysfs.h"
+
+static efi_status_t
+sysfs_read_variable(const char *name, efi_variable_t *var)
+{
+ char filename[PATH_MAX];
+ int fd;
+ size_t readsize;
+ char buffer[PATH_MAX+40];
+ if (!name || !var) return EFI_INVALID_PARAMETER;
+ memset(buffer, 0, sizeof(buffer));
+
+ snprintf(filename, PATH_MAX-1, "%s/%s/raw_var", SYSFS_DIR_EFI_VARS,name);
+ fd = open(filename, O_RDONLY);
+ if (fd == -1) {
+ return EFI_NOT_FOUND;
+ }
+ readsize = read(fd, var, sizeof(*var));
+ if (readsize != sizeof(*var)) {
+ close(fd);
+ return EFI_INVALID_PARAMETER;
+ }
+ close(fd);
+ return var->Status;
+}
+
+static efi_status_t
+sysfs_write_variable(const char *filename, efi_variable_t *var)
+{
+ int fd;
+ size_t writesize;
+ char buffer[PATH_MAX+40];
+
+ if (!filename || !var) return EFI_INVALID_PARAMETER;
+ memset(buffer, 0, sizeof(buffer));
+
+ fd = open(filename, O_WRONLY);
+ if (fd == -1) {
+ return EFI_INVALID_PARAMETER;
+ }
+ writesize = write(fd, var, sizeof(*var));
+ if (writesize != sizeof(*var)) {
+ close(fd);
+ return EFI_INVALID_PARAMETER;
+ }
+ close(fd);
+ return EFI_SUCCESS;
+}
+
+
+static efi_status_t
+sysfs_edit_variable(const char *name, efi_variable_t *var)
+{
+ char filename[PATH_MAX];
+ if (!var) return EFI_INVALID_PARAMETER;
+ snprintf(filename, PATH_MAX-1, "%s/%s/raw_var", SYSFS_DIR_EFI_VARS,name);
+ return sysfs_write_variable(filename, var);
+}
+
+static efi_status_t
+sysfs_create_variable(efi_variable_t *var)
+{
+ char filename[PATH_MAX];
+ if (!var) return EFI_INVALID_PARAMETER;
+ snprintf(filename, PATH_MAX-1, "%s/%s", SYSFS_DIR_EFI_VARS,"new_var");
+ return sysfs_write_variable(filename, var);
+}
+
+static efi_status_t
+sysfs_delete_variable(efi_variable_t *var)
+{
+ char filename[PATH_MAX];
+ if (!var) return EFI_INVALID_PARAMETER;
+ snprintf(filename, PATH_MAX-1, "%s/%s", SYSFS_DIR_EFI_VARS,"del_var");
+ return sysfs_write_variable(filename, var);
+}
+
+struct efivar_kernel_calls sysfs_kernel_calls = {
+ .read = sysfs_read_variable,
+ .edit = sysfs_edit_variable,
+ .create = sysfs_create_variable,
+ .delete = sysfs_delete_variable,
+ .path = SYSFS_DIR_EFI_VARS,
+};
#define BLKGETLASTSECT _IO(0x12,108) /* get last sector of block device */
#define BLKGETSIZE _IO(0x12,96) /* return device size */
#define BLKSSZGET _IO(0x12,104) /* get block device sector size */
-#define BLKGETSIZE64 _IOR(0x12,114,sizeof(uint64_t)) /* return device size in bytes (u64 *arg) */
+#define BLKGETSIZE64 _IOR(0x12,114,uint64_t) /* return device size in bytes (u64 *arg) */
struct blkdev_ioctl_param {
unsigned int block;
.\" <http://shell.ipoline.com/~elmert/comp/docbook2X/>
.\" Please send any bug reports, improvements, comments, patches,
.\" etc. to Steve Cheng <steve@ggi-project.org>.
-.TH "EFIBOOTMGR" "8" "11 August 2003" "" ""
+.TH "EFIBOOTMGR" "8" "06 February 2004" "" ""
+
.SH NAME
efibootmgr \- manipulate the EFI Boot Manager
.SH SYNOPSIS
-\fBefibootmgr\fR [ \fB-a\fR] [ \fB-A\fR] [ \fB-b \fIXXXX\fB\fR] [ \fB-B \fIXXXX\fB\fR] [ \fB-c\fR] [ \fB-d \fIDISK\fB\fR] [ \fB-e \fI1|3|-1\fB\fR] [ \fB-E \fINUM\fB\fR] [ \fB-g\fR] [ \fB-H \fIXXXX\fB\fR] [ \fB-i \fINAME\fB\fR] [ \fB-l \fINAME\fB\fR] [ \fB-L \fILABEL\fB\fR] [ \fB-n \fIXXXX\fB\fR] [ \fB-N\fR] [ \fB-o \fIXXXX\fB,\fIYYYY\fB,\fIZZZZ\fB\fR\fI ...\fR] [ \fB-O\fR] [ \fB-p \fIPART\fB\fR] [ \fB-q\fR] [ \fB-t\fR] [ \fB-u\fR] [ \fB-U \fIXXXX\fB\fR] [ \fB-v\fR] [ \fB-V\fR] [ \fB-w\fR]
+\fBefibootmgr\fR [ \fB-a\fR ] [ \fB-A\fR ] [ \fB-b \fIXXXX\fB\fR ] [ \fB-B \fIXXXX\fB\fR ] [ \fB-c\fR ] [ \fB-d \fIDISK\fB\fR ] [ \fB-e \fI1|3|-1\fB\fR ] [ \fB-E \fINUM\fB\fR ] [ \fB-g\fR ] [ \fB-H \fIXXXX\fB\fR ] [ \fB-i \fINAME\fB\fR ] [ \fB-l \fINAME\fB\fR ] [ \fB-L \fILABEL\fB\fR ] [ \fB-n \fIXXXX\fB\fR ] [ \fB-N\fR ] [ \fB-o \fIXXXX\fB,\fIYYYY\fB,\fIZZZZ\fB\fR\fI ...\fR ] [ \fB-O\fR ] [ \fB-p \fIPART\fB\fR ] [ \fB-q\fR ] [ \fB-t \fIseconds\fB\fR ] [ \fB-T\fR ] [ \fB-u\fR ] [ \fB-U \fIXXXX\fB\fR ] [ \fB-v\fR ] [ \fB-V\fR ] [ \fB-w\fR ]
.SH "DESCRIPTION"
.PP
.RS
.B "Note:"
efibootmgr requires that the kernel support access to EFI
-non-volatile variables (through \fI/proc/efi/vars\fR).
+non-volatile variables (through
+\fI/proc/efi/vars\fR on 2.4 kernels,
+\fI/sys/firmware/efi/vars\fR on 2.6 kernels).
\fBmodprobe efivars\fR should do the trick.
.RE
.SH "OPTIONS"
\fB-q | --quiet\fR
Quiet mode - supresses output.
.TP
-\fB-t | --test \fIfilename\fB\fR
+\fB--test \fIfilename\fB\fR
Don't write to NVRAM, write to \fIfilename\fR.
.TP
+\fB-t | --timeout \fIseconds\fB\fR
+Boot Manager timeout, in \fIseconds\fR.
+.TP
+\fB-T | --delete-timeout\fR
+Delete Timeout variable.
+.TP
\fB-u | --unicode | --UCS-2 \fR
pass extra command line arguments as UCS-2 (default is
ASCII)
\fB-w | --write-signature\fR
write unique signature to the MBR if needed
.SH "EXAMPLES"
-.TP 1.
+.TP 3
+1.
.SS "DISPLAYING THE CURRENT SETTINGS (MUST BE ROOT)."
.PP
[root@localhost ~]# efibootmgr
BootCurrent: 0004
BootNext: 0003
BootOrder: 0004,0000,0001,0002,0003
+Timeout: 30 seconds
Boot0000* Diskette Drive(device:0)
Boot0001* CD-ROM Drive(device:FF)
Boot0002* Hard Drive(Device:80)/HD(Part1,Sig00112233)
to change the next boot behavior without changing BootOrder.
.TP 0.2i
\(bu
+Timeout - the time in seconds between when the boot
+manager appears on the screen until when it
+automatically chooses the startup value from BootNext
+or BootOrder.
+.TP 0.2i
+\(bu
Five boot entries (0000 - 0004), along with the active/inactive
flag (* means active) and the name displayed on the screen.
.RE
-.TP 2.
+.TP 3
+2.
.SS "CREATING A NEW BOOT OPTION"
.PP
An OS installer would call \fBefibootmgr -c\fR.
creates a new boot option, called "Linux", and puts it at the top of
the boot order list. Options may be passed to modify the default
behavior. The default OS Loader is \fIelilo.efi\fR.
-.TP 3.
+.TP 3
+3.
.SS "CHANGING THE BOOT ORDER"
.PP
Assuming the configuration in Example #1,
\fBefibootmgr -o 3,4\fR could be called to specify
PXE boot first, then Linux boot.
-.TP 4.
+.TP 3
+4.
.SS "CHANGING THE BOOT ORDER FOR THE NEXT BOOT ONLY"
.PP
Assuming the configuration in Example #1,
\fBefibootmgr -n 4\fR could be called to specify
that the Linux entry be taken on next boot.
-.TP 5.
+.TP 3
+5.
.SS "DELETING A BOOT OPTION"
.PP
Assuming the configuration in Example #1,
\fBefibootmgr -b 4 -B\fR could be called to delete
entry 4 and remove it from the BootOrder.
-.TP 6.
+.TP 3
+6.
.SS "CREATING NETWORK BOOT ENTRIES"
.PP
A system administrator wants to create a boot option to network
<!ENTITY manfirstname "<firstname>dann</firstname>">
<!ENTITY mansurname "<surname>frazier</surname>">
<!-- Please adjust the date whenever revising the manpage. -->
- <!ENTITY mandate "<date>2003-08-11</date>">
+ <!ENTITY mandate "<date>2004-02-05</date>">
<!-- SECTION should be 1-8, maybe with subsection. Other parameters are
allowed: see man(7), man(1). -->
<!ENTITY mansection "<manvolnum>8</manvolnum>">
&mansurname;
</author>
<copyright>
- <year>2002, 2003</year>
+ <year>2002, 2003, 2004</year>
<holder>&manusername;</holder>
</copyright>
&mandate;
<arg>-O</arg>
<arg>-p <replaceable>PART</replaceable></arg>
<arg>-q</arg>
- <arg>-t</arg>
+ <arg>-t <replaceable>seconds</replaceable></arg>
+ <arg>-T</arg>
<arg>-u</arg>
<arg>-U <replaceable>XXXX</replaceable></arg>
<arg>-v</arg>
<note>
<para>
&manpackage; requires that the kernel support access to EFI
- non-volatile variables (through <filename>/proc/efi/vars</filename>).
+ non-volatile variables (through
+ <filename>/proc/efi/vars</filename> on 2.4 kernels,
+ <filename>/sys/firmware/efi/vars</filename> on 2.6 kernels).
<command>modprobe efivars</command> should do the trick.
</para>
</note>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>-t</option> | <option>--test</option> <replaceable>filename</replaceable></term>
+ <term><option>--test</option> <replaceable>filename</replaceable></term>
<listitem>
<para>Don't write to NVRAM, write to <replaceable>filename</replaceable>.</para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><option>-t</option> | <option>--timeout</option> <replaceable>seconds</replaceable></term>
+ <listitem>
+ <para>Boot Manager timeout, in <replaceable>seconds</replaceable>.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-T</option> | <option>--delete-timeout</option></term>
+ <listitem>
+ <para>Delete Timeout variable.</para>
+ </listitem>
+ </varlistentry>
<varlistentry>
<term><option>-u</option> | <option>--unicode</option> | <option>--UCS-2</option> </term>
<listitem>
BootCurrent: 0004
BootNext: 0003
BootOrder: 0004,0000,0001,0002,0003
+ Timeout: 30 seconds
Boot0000* Diskette Drive(device:0)
Boot0001* CD-ROM Drive(device:FF)
Boot0002* Hard Drive(Device:80)/HD(Part1,Sig00112233)
to change the next boot behavior without changing BootOrder.
</para>
</listitem>
+ <listitem>
+ <para>
+ Timeout - the time in seconds between when the boot
+ manager appears on the screen until when it
+ automatically chooses the startup value from BootNext
+ or BootOrder.
+ </para>
+ </listitem>
<listitem>
<para>
Five boot entries (0000 - 0004), along with the active/inactive