Imported Debian patch 0.5.3-1 debian/0.5.3-1
authorBdale Garbee <bdale@gag.com>
Sun, 2 Apr 2006 06:00:02 +0000 (22:00 -0800)
committerBdale Garbee <bdale@gag.com>
Tue, 20 May 2008 05:06:22 +0000 (23:06 -0600)
20 files changed:
AUTHORS
Makefile
README
debian/changelog
debian/compat [new file with mode: 0644]
debian/control
debian/rules
doc/ChangeLog
src/efibootmgr/efibootmgr.c
src/efibootmgr/efibootmgr.c.orig [new file with mode: 0644]
src/include/efi.h
src/include/efibootmgr.h
src/lib/disk.c
src/lib/efi.c
src/lib/efi.c.orig [new file with mode: 0644]
src/lib/efivars_procfs.c
src/lib/efivars_sysfs.c
src/lib/gpt.c
src/man/man8/efibootmgr.8
src/man/man8/efibootmgr.8.docbook

diff --git a/AUTHORS b/AUTHORS
index 40dd42500e390a057dcbdfcd9f9bd145387f75c4..1bf3318c997828ea9c6de003fbdc05d453bbe888 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -20,3 +20,7 @@ Joshua Giles <Joshua_Giles@dell.com>
 Alex Williamson <alex.williamson@hp.com>
 - Patch to efi.c and efibootmgr.c for handling BootXXXX values
   using uppercase hex rather than lowercase, per EFI 1.10 spec.
+
+Rogerio Timmers <rogerio.timmers@hp.com>
+- add option -@  for passing extra variable options in from a file,
+  necessary for setting up some boot entries for Microsoft Windows.
index 23bc9d893b09e63c5145656733045584b0c4bc2f..a52eef2606a0c171b4a547528ee33af51b876c8f 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,14 +1,15 @@
   default: all
 
-  RELEASE_DATE := "08-Mar-2005"
+  RELEASE_DATE := "09-Nov-2005"
   RELEASE_MAJOR := 0
   RELEASE_MINOR := 5
-  RELEASE_SUBLEVEL := 1
+  RELEASE_SUBLEVEL := 3
   RELEASE_EXTRALEVEL :=
   RELEASE_NAME := efibootmgr
   RELEASE_STRING := $(RELEASE_NAME)-$(RELEASE_MAJOR).$(RELEASE_MINOR).$(RELEASE_SUBLEVEL)$(RELEASE_EXTRALEVEL)
 
-  CFLAGS += -DEFIBOOTMGR_VERSION=\"$(RELEASE_MAJOR).$(RELEASE_MINOR).$(RELEASE_SUBLEVEL)$(RELEASE_EXTRALEVEL)\" -Wall
+  CFLAGS += -DEFIBOOTMGR_VERSION=\"$(RELEASE_MAJOR).$(RELEASE_MINOR).$(RELEASE_SUBLEVEL)$(RELEASE_EXTRALEVEL)\" \
+           -Wall -g -D_FILE_OFFSET_BITS=64
 
   MODULES := src
 
diff --git a/README b/README
index 9ee586be5b94b95e3728f854fd7cef52a026841c..89a64454fc55bbdc3d585f3b0dc923e94fa81f2e 100644 (file)
--- a/README
+++ b/README
@@ -37,6 +37,8 @@ usage: efibootmgr [options]
        -v | --verbose         print additional information
        -V | --version         return version and exit
        -w | --write-signature  write unique sig to MBR if needed
+        -@ | --append-binary-args   append extra variable args from
+                                   file (use - to read from stdin).  
 
 
 Typical usage:
index 1ceec3d0beed15a1304421a2efb11ca323b5a125..1c8625121f0142b5a89202a38fcedba435bc541e 100644 (file)
@@ -1,3 +1,9 @@
+efibootmgr (0.5.3-1) unstable; urgency=low
+
+  * new upstream version, closes: #357884
+
+ -- Bdale Garbee <bdale@gag.com>  Sat,  1 Apr 2006 22:00:02 -0800
+
 efibootmgr (0.5.1-1) unstable; urgency=low
 
   * new upstream version. 
diff --git a/debian/compat b/debian/compat
new file mode 100644 (file)
index 0000000..7ed6ff8
--- /dev/null
@@ -0,0 +1 @@
+5
index baaa98b0e5c7e4bbed659f0479d510376d9b27f3..516728fa3bfd964f313b93e304217df10480b98e 100644 (file)
@@ -2,8 +2,8 @@ Source: efibootmgr
 Section: admin
 Priority: optional
 Maintainer: Bdale Garbee <bdale@gag.com>
-Build-Depends: debhelper (>> 3.0.0), docbook-to-man, pciutils-dev
-Standards-Version: 3.6.1.0
+Build-Depends: debhelper (>> 5), docbook-to-man, pciutils-dev
+Standards-Version: 3.6.2.2
 
 Package: efibootmgr
 Architecture: amd64 i386 ia64
index 6b0215789851b66c332bc6e31b4439cefd7a8fdf..4d06695c23958191bbf40de3ce070013449f7a7e 100755 (executable)
@@ -1,7 +1,5 @@
 #!/usr/bin/make -f
 
-export DH_COMPAT=3
-
 configure: configure-stamp
 configure-stamp:
        dh_testdir
index 2780443abbc4e6b1fa24382636d93c2122f6e8a1..eada84fd2df4fa0b296eba95cab451481243f671 100644 (file)
@@ -1,3 +1,33 @@
+* Wed Nov 9 2005 Matt Domsch <Matt_Domsch@dell.com>
+- released v0.5.2.2 as v0.5.3, no changes
+       
+* Thu Aug 11 2005 Matt Domsch <Matt_Domsch@dell.com>
+- applied patch from Rogerio Timmers which adds a new option -@ <file>,
+  which takes extra variable parameters from <file>, or - from stdin.
+  This lets you pass binary (non-unicode, non-ascii) formatted options to
+  your bootloader.
+- cleaned up Rogerio's patch some.
+- moved definition of _FILE_OFFSET_BITS=64 into Makefile and out of the
+  individual .c files.  This fixes a bug reported by Red Flag, where
+  variable data was getting incorrectly set with a 32-bit copy of
+  efibootmgr on a 32-bit kernel.
+- made efi_variable_t.DataSize be an unsigned long to match the kernel.
+  This lets a 32-bit copy of efibootmgr run on a 32-bit kernel.  This
+  means you've got to have a 32-bit efibootmgr on a 32-bit kernel, and a
+  64-bit efibootmgr on a 64-bit kernel, but since efi_status_t is also a
+  long, this was really going to be the case anyway.
+- valgrind caught the app exiting without freeing some malloc'd
+  structures, fix that.
+- v0.5.2.2 released for testing        
+
+
+* Fri May 20 2005 Matt Domsch <Matt_Domsch@dell.com>
+- applied patch from Andreas Schwab to properly parse PCI
+  domain:bus:device.fn info in netboot entries.  Fixed up return value
+  when creating network boot entries for nonexistant devices, so the
+  creation now fails, rather than succeeding with incorrect data.
+- v0.5.2 released
+
 * Tue Mar 08 2005 Matt Domsch <Matt_Domsch@dell.com>
 - applied patch from Alex Williamson for handling BootXXXX values
   using uppercase hex rather than lowercase, per EFI 1.10 spec.
index 5058f922baaad4c1dab4e5e1873ed62e12c6936e..7aeb1868e0e9bc7e1e780b92a6b3ab0fbd68a895 100644 (file)
@@ -96,6 +96,18 @@ fill_var(efi_variable_t *var, const char *name)
                | EFI_VARIABLE_RUNTIME_ACCESS;
 }
 
+static void
+free_vars(list_t *head)
+{
+       list_t *pos, *n;
+       var_entry_t *boot;
+
+       list_for_each_safe(pos, n, head) {
+               boot = list_entry(pos, var_entry_t, list);
+               list_del(&(boot->list));
+               free(boot);
+       }
+}
 
 static void
 read_vars(struct dirent **namelist,
@@ -750,6 +762,7 @@ usage()
        printf("\t-v | --verbose          print additional information\n");
        printf("\t-V | --version          return version and exit\n");
        printf("\t-w | --write-signature  write unique sig to MBR if needed\n");
+       printf("\t-@ | --append-binary-args file  append extra args from file (use \"-\" for stdin)\n");
 }
 
 static void
@@ -809,17 +822,21 @@ parse_opts(int argc, char **argv)
                        {"verbose",          optional_argument, 0, 'v'},
                        {"version",                no_argument, 0, 'V'},
                        {"write-signature",        no_argument, 0, 'w'},
+                       {"append-binary-args", required_argument, 0, '@'},
                        {0, 0, 0, 0}
                };
 
                c = getopt_long (argc, argv,
-                                "AaBb:cd:e:E:gH:i:l:L:n:No:Op:qt:TuU: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;
 
                switch (c)
                {
+               case '@':
+                       opts.extra_opts_file = optarg;
+                       break;
                case 'a':
                        opts.active = 1;
                        break;
@@ -1027,6 +1044,7 @@ main(int argc, char **argv)
                }
        }
        free_dirents(boot_names, num_boot_names);
+       free_vars(&boot_entry_list);
        return 0;
 }
 
diff --git a/src/efibootmgr/efibootmgr.c.orig b/src/efibootmgr/efibootmgr.c.orig
new file mode 100644 (file)
index 0000000..5a1a0d9
--- /dev/null
@@ -0,0 +1,1045 @@
+/*
+  efibootmgr.c - Manipulates EFI variables as exported in /proc/efi/vars
+
+  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
+    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
+
+
+  This must tie the EFI_DEVICE_PATH to /boot/efi/elilo.efi
+  The  EFI_DEVICE_PATH will look something like:
+    ACPI device path, length 12 bytes
+    Hardware Device Path, PCI, length 6 bytes
+    Messaging Device Path, SCSI, length 8 bytes, or ATAPI, length ??
+    Media Device Path, Hard Drive, partition XX, length 30 bytes
+    Media Device Path, File Path, length ??
+    End of Hardware Device Path, length 4
+    Arguments passed to elilo, as UCS-2 characters, length ??
+
+*/
+
+#define _GNU_SOURCE
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <stdint.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <getopt.h>
+#include "list.h"
+#include "efi.h"
+#include "efichar.h"
+#include "unparse_path.h"
+#include "disk.h"
+#include "efibootmgr.h"
+
+
+#ifndef EFIBOOTMGR_VERSION
+#define EFIBOOTMGR_VERSION "unknown (fix Makefile!)"
+#endif
+
+
+typedef struct _var_entry {
+       struct dirent *name;
+       uint16_t       num;
+       efi_variable_t var_data;
+       list_t         list;
+} var_entry_t;
+
+
+/* global variables */
+static LIST_HEAD(boot_entry_list);
+static LIST_HEAD(blk_list);
+efibootmgr_opt_t opts;
+
+static inline void
+var_num_from_name(const char *pattern, char *name, uint16_t *num)
+{
+       sscanf(name, pattern, num);
+}
+
+static void
+fill_bootvar_name(char *dest, size_t len, const char *name)
+{
+       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);
+}
+
+static void
+fill_var(efi_variable_t *var, const char *name)
+{
+       efi_guid_t guid = EFI_GLOBAL_VARIABLE;
+
+       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;
+}
+
+static void
+free_vars(list_t *head)
+{
+       list_t *pos, *n;
+       var_entry_t *boot;
+
+       list_for_each_safe(pos, n, head) {
+               boot = list_entry(pos, var_entry_t, list);
+               list_del(&(boot->list));
+               free(boot);
+       }
+}
+
+static void
+read_vars(struct dirent **namelist,
+         int num_boot_names,
+         list_t *head)
+{
+       efi_status_t status;
+       var_entry_t *entry;
+       int i;
+
+       if (!namelist) return;
+
+       for (i=0; i < num_boot_names; i++)
+       {
+               if (namelist[i]) {
+                       entry = malloc(sizeof(var_entry_t));
+                       if (!entry) return;
+                       memset(entry, 0, sizeof(var_entry_t));
+
+                       status = read_variable(namelist[i]->d_name,
+                                              &entry->var_data);
+                       if (status != EFI_SUCCESS) break;
+                       entry->name = namelist[i];
+                       list_add_tail(&entry->list, head);
+               }
+       }
+       return;
+}
+
+
+
+
+
+static void
+free_dirents(struct dirent **ptr, int num_dirents)
+{
+       int i;
+       if (!ptr) return;
+       for (i=0; i < num_dirents; i++) {
+               if (ptr[i]) {
+                       free(ptr[i]);
+                       ptr[i] = NULL;
+               }
+       }
+       free(ptr);
+}
+
+
+
+static int
+compare(const void *a, const void *b)
+{
+       int rc = -1;
+       uint32_t n1, n2;
+       memcpy(&n1, a, sizeof(n1));
+       memcpy(&n2, b, sizeof(n2));
+       if (n1 < n2) rc = -1;
+       if (n1 == n2) rc = 0;
+       if (n2 > n2) rc = 1;
+       return rc;
+}
+
+
+/*
+  Return an available boot variable number,
+  or -1 on failure.
+*/
+static int
+find_free_boot_var(list_t *boot_list)
+{
+       int num_vars=0, i=0, found;
+       uint16_t *vars, free_number;
+       list_t *pos;
+       var_entry_t *boot;
+       list_for_each(pos, boot_list) {
+               num_vars++;
+       }
+       vars = malloc(sizeof(uint16_t) * num_vars);
+       if (!vars) return -1;
+       memset(vars, 0, sizeof(uint16_t) * num_vars);
+
+       list_for_each(pos, boot_list) {
+               boot = list_entry(pos, var_entry_t, list);
+               vars[i] = boot->num;
+                       i++;
+       }
+       qsort(vars, i, sizeof(uint16_t), compare);
+       found = 1;
+
+       num_vars = i;
+       for (free_number = 0; free_number < num_vars && found; free_number++) {
+               found = 0;
+               list_for_each(pos, boot_list) {
+                       boot = list_entry(pos, var_entry_t, list);
+                       if (boot->num == free_number) {
+                               found = 1;
+                               break;
+                       }
+               }
+               if (!found) break;
+       }
+       if (found && num_vars) free_number = vars[num_vars-1] + 1;
+       free(vars);
+       return free_number;
+}
+
+
+static void
+warn_duplicate_name(list_t *boot_list)
+{
+       list_t *pos;
+       var_entry_t *boot;
+       EFI_LOAD_OPTION *load_option;
+
+       list_for_each(pos, boot_list) {
+               boot = list_entry(pos, var_entry_t, list);
+               load_option = (EFI_LOAD_OPTION *)
+                       boot->var_data.Data;
+               if (!efichar_char_strcmp(opts.label,
+                                        load_option->description)) {
+                       fprintf(stderr, "** Warning ** : %.8s has same label %s\n",
+                              boot->name->d_name,
+                              opts.label);
+               }
+       }
+}
+
+
+static var_entry_t *
+make_boot_var(list_t *boot_list)
+{
+       var_entry_t *boot;
+       int free_number;
+       list_t *pos;
+
+       if (opts.bootnum == -1)
+               free_number = find_free_boot_var(boot_list);
+       else {
+               list_for_each(pos, boot_list) {
+                       boot = list_entry(pos, var_entry_t, list);
+                       if (boot->num == opts.bootnum) {
+                               fprintf(stderr, "** Warning ** : bootnum %04X "
+                                       "already exists\n", opts.bootnum);
+                               return NULL;
+                       }
+               }
+               free_number = opts.bootnum;
+       }
+
+       if (free_number == -1) return NULL;
+
+       /* Create a new var_entry_t object
+          and populate it.
+       */
+
+       boot = malloc(sizeof(*boot));
+       if (!boot) return NULL;
+       memset(boot, 0, sizeof(*boot));
+       boot->num = free_number;
+       if (!make_linux_efi_variable(&boot->var_data, free_number)) {
+               free(boot);
+               return NULL;
+       }
+       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;
+
+       status = read_boot(boot_order, "BootOrder");
+       if (status != EFI_SUCCESS && status != EFI_NOT_FOUND)
+               return status;
+
+       if (status == EFI_NOT_FOUND) {
+               fill_var(boot_order, "BootOrder");
+       }
+       return EFI_SUCCESS;
+}
+
+
+static efi_status_t
+add_to_boot_order(uint16_t num)
+{
+       efi_status_t status;
+       efi_variable_t boot_order;
+       uint64_t new_data_size;
+       uint16_t *new_data, *old_data;
+
+       status = read_boot_order(&boot_order);
+       if (status != EFI_SUCCESS) return status;
+
+       /* We've now got an array (in boot_order.Data) of the
+          boot order.  First add our entry, then copy the old array.
+       */
+       old_data = (uint16_t *)&(boot_order.Data);
+       new_data_size = boot_order.DataSize + sizeof(uint16_t);
+       new_data = malloc(new_data_size);
+
+       new_data[0] = num;
+       memcpy(new_data+1, old_data, boot_order.DataSize);
+
+       /* Now new_data has what we need */
+       memcpy(&(boot_order.Data), new_data, new_data_size);
+       boot_order.DataSize = new_data_size;
+       return create_or_edit_variable(&boot_order);
+}
+
+
+static efi_status_t
+remove_from_boot_order(uint16_t num)
+{
+       efi_status_t status;
+       efi_variable_t 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.
+       */
+       old_data = (uint16_t *)&(boot_order.Data);
+       /* Start with the same size */
+       new_data_size = boot_order.DataSize;
+       new_data = malloc(new_data_size);
+       for (old_i=0,new_i=0;
+            old_i < boot_order.DataSize / sizeof(uint16_t);
+            old_i++) {
+               if (old_data[old_i] != num) {
+                               /* Copy this value */
+                       new_data[new_i] = old_data[old_i];
+                       new_i++;
+               }
+       }
+
+       /* Now new_data has what we need */
+       new_data_size = new_i * sizeof(uint16_t);
+       memset(&(boot_order.Data), 0, boot_order.DataSize);
+       memcpy(&(boot_order.Data), new_data, new_data_size);
+       boot_order.DataSize = new_data_size;
+
+       return edit_variable(&boot_order);
+}
+
+static efi_status_t
+delete_var(const char *name)
+{
+       efi_variable_t var;
+
+       memset(&var, 0, sizeof(var));
+       fill_var(&var, name);
+       return delete_variable(&var);
+}
+
+static int
+read_boot_u16(const char *name)
+{
+       efi_status_t status;
+       efi_variable_t var;
+       uint16_t *n = (uint16_t *)(var.Data);
+
+       memset(&var, 0, sizeof(var));
+       status = read_boot(&var, name);
+       if (status) return -1;
+       return *n;
+}
+
+static efi_status_t
+set_boot_u16(const char *name, uint16_t num)
+{
+       efi_variable_t var;
+       uint16_t *n = (uint16_t *)var.Data;
+
+       memset(&var, 0, sizeof(var));
+
+       fill_var(&var, name);
+       *n = num;
+       var.DataSize = sizeof(uint16_t);
+       return create_or_edit_variable(&var);
+}
+
+static efi_status_t
+delete_boot_var(uint16_t num)
+{
+       efi_status_t status;
+       efi_variable_t var;
+       char name[16];
+       list_t *pos, *n;
+       var_entry_t *boot;
+
+       snprintf(name, sizeof(name), "Boot%04X", num);
+       memset(&var, 0, sizeof(var));
+       fill_var(&var, name);
+       status = delete_variable(&var);
+
+       /* For backwards compatibility, try to delete abcdef entries as well */
+       if (status) {
+               snprintf(name, sizeof(name), "Boot%04x", num);
+               memset(&var, 0, sizeof(var));
+               fill_var(&var, name);
+               status = delete_variable(&var);
+       }
+
+       if (status) return status;
+       list_for_each_safe(pos, n, &boot_entry_list) {
+               boot = list_entry(pos, var_entry_t, list);
+               if (boot->num == num) {
+                       status = remove_from_boot_order(num);
+                       if (status) return status;
+                       list_del(&(boot->list));
+                       break; /* short-circuit since it was found */
+               }
+       }
+       return EFI_SUCCESS;
+}
+
+
+static void
+set_var_nums(const char *pattern, list_t *list)
+{
+       list_t *pos;
+       var_entry_t *var;
+       int num=0, rc;
+       char *name;
+       int warn=0;
+
+       list_for_each(pos, list) {
+               var = list_entry(pos, var_entry_t, list);
+               rc = sscanf(var->name->d_name, pattern, &num);
+               if (rc == 1) {
+                       var->num = num;
+                       name = var->name->d_name; /* shorter name */
+                       if ((isalpha(name[4]) && islower(name[4])) ||
+                           (isalpha(name[5]) && islower(name[5])) ||
+                           (isalpha(name[6]) && islower(name[6])) ||
+                           (isalpha(name[7]) && islower(name[7]))) {
+                               fprintf(stderr, "** Warning ** : %.8s is not "
+                                       "EFI 1.10 compliant (lowercase hex in name)\n", name);
+                               warn++;
+                       }
+               }
+       }
+       if (warn) {
+               fprintf(stderr, "** Warning ** : please recreate these using efibootmgr to remove this warning.\n");
+       }
+}
+
+#if 0
+static efi_variable_t *
+find_pci_scsi_disk_blk(int fd, int bus, int device, int func,
+                      list_t *blk_list)
+{
+       list_t *pos;
+       int rc;
+       Scsi_Idlun idlun;
+       unsigned char host, channel, id, lun;
+       var_entry_t *blk;
+       efi_variable_t *blk_var;
+       long size = 0;
+
+       memset(&idlun, 0, sizeof(idlun));
+       rc = get_scsi_idlun(fd, &idlun);
+       if (rc) return NULL;
+
+       rc = disk_get_size(fd, &size);
+
+       idlun_to_components(&idlun, &host, &channel, &id, &lun);
+
+       list_for_each(pos, blk_list) {
+               blk = list_entry(pos, var_entry_t, list);
+               blk_var = blk->var_data;
+
+               if (!compare_pci_scsi_disk_blk(blk_var,
+                                              bus, device, func,
+                                              host, channel, id, lun,
+                                              0, size)) {
+                       return blk_var;
+               }
+       }
+       return NULL;
+}
+
+
+
+
+/* The right blkX variable contains:
+   1) the PCI and SCSI information for the disk passed in disk_name
+   2) Does not contain a partition field 
+*/
+
+
+static efi_variable_t *
+find_disk_blk(char *disk_name, list_t *blk_list)
+{
+       efi_variable_t *disk_blk = NULL;
+       int fd, rc;
+       unsigned char bus=0,device=0,func=0;
+       int interface_type=interface_type_unknown;
+       unsigned int controllernum=0, disknum=0;
+       unsigned char part=0;
+
+       fd = open(disk_name, O_RDONLY|O_DIRECT);
+       rc = disk_get_pci(fd, &bus, &device, &func);
+       if (rc) {
+               fprintf(stderr, "disk_get_pci() failed.\n");
+               return NULL;
+       }
+       rc = disk_info_from_fd(fd,
+                              &interface_type,
+                              &controllernum,
+                              &disknum,
+                              &part);
+       if (rc) {
+               fprintf(stderr, "disk_info_from_fd() failed.\n");
+               return NULL;
+       }
+       switch (interface_type)
+       {
+       case scsi:
+               return find_pci_scsi_disk_blk(fd,bus,device,func,blk_list);
+               break;
+       case ata:
+               return find_pci_ata_disk_blk(fd,bus,device,func,blk_list);
+               break;
+       case i2o:
+               return find_pci_i2o_disk_blk(fd,bus,device,func,blk_list);
+               break;
+       case md:
+               return find_pci_md_disk_blk(fd,bus,device,func,blk_list);
+               break;
+       default:
+               break;
+       }
+       return NULL;
+}
+#endif
+
+static void
+unparse_boot_order(uint16_t *order, int length)
+{
+       int i;
+       printf("BootOrder: ");
+       for (i=0; i<length; i++) {
+               printf("%04X", order[i]);
+               if (i < (length-1))
+                       printf(",");
+       }
+       printf("\n");
+}
+
+static int
+parse_boot_order(char *buffer, uint16_t *order, int length)
+{
+       int i;
+       int num, rc;
+
+       for (i=0; i<length && *buffer; i++) {
+               rc = sscanf(buffer, "%x", &num);
+               if (rc == 1) order[i] = num & 0xFFFF;
+               /* Advance to the comma */ 
+               while (*buffer && *buffer != ',') buffer++;
+               /* Advance through the comma(s) */
+               while (*buffer && *buffer == ',') buffer++;
+       }
+       return i;
+}
+
+static efi_status_t
+set_boot_order()
+{
+       efi_variable_t boot_order;
+       uint16_t *n = (uint16_t *)boot_order.Data;
+
+       if (!opts.bootorder) return EFI_SUCCESS;
+
+       memset(&boot_order, 0, sizeof(boot_order));
+       fill_var(&boot_order, "BootOrder");
+
+       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
+show_boot_vars()
+{
+       list_t *pos;
+       var_entry_t *boot;
+       char description[80];
+       EFI_LOAD_OPTION *load_option;
+       EFI_DEVICE_PATH *path;
+       char text_path[1024], *p;
+       unsigned long optional_data_len=0;
+
+       list_for_each(pos, &boot_entry_list) {
+               boot = list_entry(pos, var_entry_t, list);
+               load_option = (EFI_LOAD_OPTION *)
+                       boot->var_data.Data;
+               efichar_to_char(description,
+                               load_option->description, sizeof(description));
+               memset(text_path, 0, sizeof(text_path));
+               path = load_option_path(load_option);
+               if (boot->name)
+                       printf("%.8s", boot->name->d_name);
+               else
+                       printf("Boot%04X", boot->num);
+
+               if (load_option->attributes & LOAD_OPTION_ACTIVE)
+                       printf("* ");
+               else    printf("  ");
+               printf("%s", description);
+
+               if (opts.verbose) {
+                       unparse_path(text_path, path,
+                                    load_option->file_path_list_length);
+                       /* Print optional data */
+                       optional_data_len =
+                               boot->var_data.DataSize -
+                               load_option->file_path_list_length -
+                               ((char *)path - (char *)load_option);
+                       if (optional_data_len) {
+                               p = text_path;
+                               p += strlen(text_path);
+                               unparse_raw_text(p, ((uint8_t *)path) +
+                                                load_option->file_path_list_length,
+                                                optional_data_len);
+                       }
+
+                       printf("\t%s", text_path);
+               }
+               printf("\n");
+       }
+}
+
+
+
+static void
+show_boot_order()
+{
+       efi_status_t status;
+       efi_variable_t boot_order;
+       uint16_t *data;
+
+       status = read_boot_order(&boot_order);
+
+       if (status != EFI_SUCCESS) {
+               perror("show_boot_order()");
+               return;
+       }
+
+       /* We've now got an array (in boot_order.Data) of the
+          boot order.  First add our entry, then copy the old array.
+       */
+       data = (uint16_t *)&(boot_order.Data);
+       if (boot_order.DataSize)
+               unparse_boot_order(data, boot_order.DataSize / sizeof(uint16_t));
+
+}
+
+static efi_status_t
+set_active_state()
+{
+       list_t *pos;
+       var_entry_t *boot;
+       EFI_LOAD_OPTION *load_option;
+
+       list_for_each(pos, &boot_entry_list) {
+               boot = list_entry(pos, var_entry_t, list);
+               load_option = (EFI_LOAD_OPTION *)
+                       boot->var_data.Data;
+               if (boot->num == opts.bootnum) {
+                       if (opts.active == 1) {
+                               if (load_option->attributes
+                                   & LOAD_OPTION_ACTIVE) return EFI_SUCCESS;
+                               else {
+                                       load_option->attributes
+                                               |= LOAD_OPTION_ACTIVE;
+                                       return edit_variable(&boot->var_data);
+                               }
+                       }
+                       else if (opts.active == 0) {
+                               if (!(load_option->attributes
+                                     & LOAD_OPTION_ACTIVE))
+                                       return EFI_SUCCESS;
+                               else {
+                                       load_option->attributes
+                                               &= ~LOAD_OPTION_ACTIVE;
+                                       return edit_variable(&boot->var_data);
+                               }
+                       }
+               }
+       }
+       return EFI_SUCCESS;
+}
+
+
+
+
+static void
+usage()
+{
+       printf("efibootmgr version %s\n", EFIBOOTMGR_VERSION);
+       printf("usage: efibootmgr [options]\n");
+       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-c | --create         create new variable bootnum and add to bootorder\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");
+       printf("\t-g | --gpt            force disk with invalid PMBR to be treated as GPT\n");
+       printf("\t-H | --acpi_hid XXXX  set the ACPI HID (used with -i)\n");
+       printf("\t-i | --iface name     create a netboot entry for the named interface\n");
+       printf("\t-l | --loader name     (defaults to \\elilo.efi)\n");
+       printf("\t-L | --label label     Boot manager display label (defaults to \"Linux\")\n");
+       printf("\t-n | --bootnext XXXX   set BootNext to XXXX (hex)\n");
+       printf("\t-N | --delete-bootnext delete BootNext\n");
+       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-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");
+       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");
+       printf("\t-V | --version          return version and exit\n");
+       printf("\t-w | --write-signature  write unique sig to MBR if needed\n");
+}
+
+static void
+set_default_opts()
+{
+       memset(&opts, 0, sizeof(opts));
+       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";
+       opts.disk            = "/dev/sda";
+       opts.iface           = NULL;
+       opts.part            = 1;
+       opts.acpi_hid        = -1;
+       opts.acpi_uid        = -1;
+}
+
+static void
+parse_opts(int argc, char **argv)
+{
+       int c, num, rc;
+       int option_index = 0;
+
+       while (1)
+       {
+               static struct option long_options[] =
+                       /* name, has_arg, flag, val */
+               {
+                       {"active",                 no_argument, 0, 'a'},
+                       {"inactive",               no_argument, 0, 'A'},
+                       {"bootnum",          required_argument, 0, 'b'},
+                       {"delete-bootnum",         no_argument, 0, 'B'},
+                       {"create",                 no_argument, 0, 'c'},
+                       {"disk",             required_argument, 0, 'd'},
+                       {"iface",            required_argument, 0, 'i'},
+                       {"acpi_hid",         required_argument, 0, 'H'},
+                       {"edd-device",       required_argument, 0, 'E'},
+                       {"edd30",            required_argument, 0, 'e'},
+                       {"gpt",                    no_argument, 0, 'g'},
+                       {"loader",           required_argument, 0, 'l'},
+                       {"label",            required_argument, 0, 'L'},
+                       {"bootnext",         required_argument, 0, 'n'},
+                       {"delete-bootnext",        no_argument, 0, 'N'},
+                       {"bootorder",        required_argument, 0, 'o'},
+                       {"delete-bootorder",       no_argument, 0, 'O'},
+                       {"part",             required_argument, 0, 'p'},
+                       {"quiet",                  no_argument, 0, 'q'},
+                       {"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'},
+                       {"verbose",          optional_argument, 0, 'v'},
+                       {"version",                no_argument, 0, 'V'},
+                       {"write-signature",        no_argument, 0, 'w'},
+                       {0, 0, 0, 0}
+               };
+
+               c = getopt_long (argc, argv,
+                                "AaBb:cd:e:E:gH:i:l:L:n:No:Op:qt:TuU:v::Vw",
+                                long_options, &option_index);
+               if (c == -1)
+                       break;
+
+               switch (c)
+               {
+               case 'a':
+                       opts.active = 1;
+                       break;
+               case 'A':
+                       opts.active = 0;
+                       break;
+               case 'B':
+                       opts.delete_boot = 1;
+                       break;
+               case 'b':
+                       rc = sscanf(optarg, "%X", &num);
+                       if (rc == 1) opts.bootnum = num;
+                       break;
+               case 'c':
+                       opts.create = 1;
+                       break;
+               case 'd':
+                       opts.disk = optarg;
+                       break;
+               case 'e':
+                       rc = sscanf(optarg, "%d", &num);
+                       if (rc == 1) opts.edd_version = num;
+                       break;
+               case 'E':
+                       rc = sscanf(optarg, "%x", &num);
+                       if (rc == 1) opts.edd10_devicenum = num;
+                       break;
+               case 'g':
+                       opts.forcegpt = 1;
+                       break;
+               case 'H':
+                       rc = sscanf(optarg, "%x", &num);
+                       if (rc == 1) opts.acpi_hid = num;
+                       break;
+               case 'i':
+                       opts.iface = optarg;
+                       break;
+               case 'l':
+                       opts.loader = optarg;
+                       break;
+               case 'L':
+                       opts.label = optarg;
+                       break;
+               case 'N':
+                       opts.delete_bootnext = 1;
+                       break;
+               case 'n':
+                       rc = sscanf(optarg, "%x", &num);
+                       if (rc == 1) opts.bootnext = num;
+                       break;
+               case 'o':
+                       opts.bootorder = optarg;
+                       break;
+               case 'O':
+                       opts.delete_bootorder = 1;
+                       break;
+               case 'p':
+                       rc = sscanf(optarg, "%u", &num);
+                       if (rc == 1) opts.part = num;
+                       break;
+               case 'q':
+                       opts.quiet = 1;
+                       break;
+               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;
+
+               case 'U':
+                       rc = sscanf(optarg, "%x", &num);
+                       if (rc == 1) opts.acpi_uid = num;
+                       break;
+               case 'v':
+                       opts.verbose = 1;
+                       if (optarg) {
+                               if (!strcmp(optarg, "v"))  opts.verbose = 2;
+                               if (!strcmp(optarg, "vv")) opts.verbose = 3;
+                               rc = sscanf(optarg, "%d", &num);
+                               if (rc == 1)  opts.verbose = num;
+                       }
+                       break;
+               case 'V':
+                       opts.showversion = 1;
+                       break;
+
+               case 'w':
+                       opts.write_signature = 1;
+                       break;
+
+               default:
+                       usage();
+                       exit(1);
+               }
+       }
+
+       if (optind < argc) {
+               opts.argc = argc;
+               opts.argv = argv;
+               opts.optind = optind;
+       }
+}
+
+
+int
+main(int argc, char **argv)
+{
+       struct dirent  **boot_names = NULL;
+       var_entry_t *new_boot = NULL;
+       int num, num_boot_names=0;
+
+       set_default_opts();
+       parse_opts(argc, argv);
+       if (opts.showversion) {
+               printf("version %s\n", EFIBOOTMGR_VERSION);
+               return 0;
+       }
+
+       if (opts.iface && opts.acpi_hid == -1 && opts.acpi_uid == -1) {
+               fprintf(stderr, "\nYou must specify the ACPI HID and UID when using -i.\n\n");
+               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);
+               set_var_nums("Boot%04X-%*s", &boot_entry_list);
+
+               if (opts.delete_boot) {
+                       if (opts.bootnum == -1)
+                               fprintf(stderr, "\nYou must specify a boot entry to delete (see the -b option).\n\n");
+                       else
+                               delete_boot_var(opts.bootnum);
+               }
+
+               if (opts.active >= 0) {
+                       set_active_state();
+               }
+       }
+
+       if (opts.create) {
+               warn_duplicate_name(&boot_entry_list);
+               new_boot = make_boot_var(&boot_entry_list);
+               /* Put this boot var in the right BootOrder */
+               if (!opts.testfile && new_boot)
+                       add_to_boot_order(new_boot->num);
+       }
+
+       if (!opts.testfile) {
+
+               if (opts.delete_bootorder) {
+                       delete_var("BootOrder");
+               }
+
+               if (opts.bootorder) {
+                       set_boot_order();
+               }
+
+
+               if (opts.delete_bootnext) {
+                       delete_var("BootNext");
+               }
+
+               if (opts.delete_timeout) {
+                       delete_var("Timeout");
+               }
+
+               if (opts.bootnext >= 0) {
+                       set_boot_u16("BootNext", opts.bootnext & 0xFFFF);
+               }
+
+               if (opts.set_timeout) {
+                       set_boot_u16("Timeout", opts.timeout);
+               }
+
+               if (!opts.quiet) {
+                       num = read_boot_u16("BootNext");
+                       if (num != -1 ) {
+                               printf("BootNext: %04X\n", num);
+                       }
+                       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();
+               }
+       }
+       free_dirents(boot_names, num_boot_names);
+       free_vars(&boot_entry_list);
+       return 0;
+}
+
index 5fc52ff48fdc678f34ad95503b725436c9ab3ec9..be667ae9cbe92bf7a24009a37a2c484bd73ec782 100644 (file)
@@ -98,7 +98,7 @@ typedef uint16_t efi_char16_t;                /* UNICODE character */
 typedef struct _efi_variable_t {
         efi_char16_t  VariableName[1024/sizeof(efi_char16_t)];
         efi_guid_t    VendorGuid;
-        uint64_t         DataSize;
+        unsigned long DataSize;
         uint8_t          Data[1024];
        efi_status_t  Status;
         uint32_t         Attributes;
index 3546834d5b5f2eff17bb679840ea78af0229f3e4..9ab6802a768bb2aff37e1d3f80c4297bdada6c49 100644 (file)
@@ -31,6 +31,7 @@ typedef struct {
        char *label;
        char *bootorder;
        char *testfile;
+       char *extra_opts_file;
        uint32_t part;
        int edd_version;
        int edd10_devicenum;
index 65810407ff95060132628e8b6762a03d8074d602..883864f4b06ceae0b172c6a09f0de232ca3c97f6 100644 (file)
@@ -18,8 +18,6 @@
     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#define _FILE_OFFSET_BITS 64
-
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
index ac782c9b0edc4c3d5c7afc70f32579bfa04aea25..7dd2ab3aa5d8d2c1a48231cce526d9359aaf0759 100644 (file)
@@ -548,7 +548,8 @@ char *make_disk_load_option(char *p, char *disk)
  * make_net_load_option()
  * @data - load option returned
  *
- * Returns 0 on error, length of load option created on success.
+ * Returns NULL on error, or p advanced by length of load option
+ * created on success.
  */
 char *make_net_load_option(char *p, char *iface)
 {
@@ -566,29 +567,37 @@ char *make_net_load_option(char *p, char *iface)
     fd = socket(AF_INET, SOCK_DGRAM, 0);
     if (fd < 0) {
         perror("Cannot get control socket");
+       goto out;
     }
     err = ioctl(fd, SIOCETHTOOL, &ifr);
     if (err < 0) {
         perror("Cannot get driver information");
+       goto out;
     }
 
-
-    err = sscanf(drvinfo.bus_info, "%2x:%2x.%x", &bus, &slot, &func);
-    if (err == 0) {
-        perror("Couldn't parse device location string.");
+    /* The domain part was added in 2.6 kernels.  Test for that first. */
+    err = sscanf(drvinfo.bus_info, "%*x:%2x:%2x.%x", &bus, &slot, &func);
+    if (err != 3) {
+           err = sscanf(drvinfo.bus_info, "%2x:%2x.%x", &bus, &slot, &func);
+           if (err != 3) {
+                   perror("Couldn't parse device location string.");
+                   goto out;
+           }
     }
 
-    p += make_acpi_device_path(p, opts.acpi_hid, opts.acpi_uid);
-    p += make_pci_device_path(p, bus, (uint8_t)slot, (uint8_t)func);
-
     err = ioctl(fd, SIOCGIFHWADDR, &ifr);
     if (err < 0) {
         perror("Cannot get hardware address.");
+       goto out;
     }
 
+    p += make_acpi_device_path(p, opts.acpi_hid, opts.acpi_uid);
+    p += make_pci_device_path(p, bus, (uint8_t)slot, (uint8_t)func);
     p += make_mac_addr_device_path(p, ifr.ifr_ifru.ifru_hwaddr.sa_data, 0);
     p += make_end_device_path       (p);
     return(p);
+ out:
+    return NULL;
 }
 
 /**
@@ -623,10 +632,11 @@ make_linux_load_option(void *data)
        if (opts.iface) {
              p = (char *)make_net_load_option(p, opts.iface);
        }
-
        else {
              p = (char *)make_disk_load_option(p, opts.iface);
        }
+       if (p == NULL)
+               return 0;
 
        load_option->file_path_list_length = p - q;
 
@@ -698,14 +708,57 @@ append_extra_args_unicode(void *data, unsigned long maxchars)
        return 0;
 }
 
+static unsigned long
+append_extra_args_file(void *data, unsigned long maxchars)
+{
+       char *p = data;
+       char *file = opts.extra_opts_file;
+       int fd = STDIN_FILENO;
+       ssize_t num_read=0;
+       unsigned long appended=0;
+
+       if (!data) return 0;
+
+       if (file && strncmp(file, "-", 1))
+               fd = open(file, O_RDONLY);
+
+       if (fd == -1) {
+               perror("Failed to open extra arguments file");
+               return 0;
+       }
+
+       do {
+               num_read = read(fd, p, maxchars - appended);
+               if (num_read < 0) {
+                       perror("Error reading extra arguments file");
+                       break;
+               }
+               else if (num_read>0) {
+                       appended += num_read;
+                       p += num_read;
+               }
+       } while (num_read > 0 && ((maxchars - appended) > 0));
+
+       if (fd != STDIN_FILENO)
+               close(fd);
+
+       return appended;
+}
+
 
 static unsigned long
 append_extra_args(void *data, unsigned long maxchars)
 {
-       if (opts.unicode)
-         return append_extra_args_unicode(data, maxchars);
+       unsigned long bytes_written=0;
+
+       if (opts.extra_opts_file)
+               bytes_written += append_extra_args_file(data, maxchars);
+
+       if  (opts.unicode)
+               bytes_written += append_extra_args_unicode(data, maxchars - bytes_written);
        else
-         return append_extra_args_ascii(data, maxchars);
+               bytes_written += append_extra_args_ascii(data, maxchars - bytes_written);
+       return bytes_written;
 }
 
 
diff --git a/src/lib/efi.c.orig b/src/lib/efi.c.orig
new file mode 100644 (file)
index 0000000..2257e9f
--- /dev/null
@@ -0,0 +1,765 @@
+/*
+  efivars_proc.[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
+ */
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <stdint.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <linux/sockios.h>
+#include <net/if.h>
+#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)
+{
+       char *p = (char *) option;
+       return (EFI_DEVICE_PATH *)
+               (p + sizeof(uint32_t) /* Attributes */
+                + sizeof(uint16_t)   /* FilePathListLength*/
+                + efichar_strsize(option->description)); /* Description */
+}
+
+char *
+efi_guid_unparse(efi_guid_t *guid, char *out)
+{
+       sprintf(out, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+               guid->b[3], guid->b[2], guid->b[1], guid->b[0],
+               guid->b[5], guid->b[4], guid->b[7], guid->b[6],
+               guid->b[8], guid->b[9], guid->b[10], guid->b[11],
+               guid->b[12], guid->b[13], guid->b[14], guid->b[15]);
+        return out;
+}
+
+void
+set_fs_kernel_calls()
+{
+       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;
+       }
+
+       snprintf(name, PATH_MAX, "%s", PROCFS_DIR_EFI_VARS);
+       dir = opendir(name);
+       if (dir) {
+               closedir(dir);
+               fs_kernel_calls = &procfs_kernel_calls;
+               return;
+       }
+       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)
+{
+       int fd, byteswritten;
+       if (!var || !opts.testfile) return EFI_INVALID_PARAMETER;
+
+       printf("Test mode: Writing to %s\n", opts.testfile);
+       fd = creat(opts.testfile, S_IRWXU);
+       if (fd == -1) {
+               perror("Couldn't write to testfile");
+               return EFI_INVALID_PARAMETER;
+       }
+
+       byteswritten = write(fd, var, sizeof(*var));
+       if (byteswritten == -1) {
+               perror("Writing to testfile");
+
+       }
+       close(fd);
+       return EFI_SUCCESS;
+}
+
+efi_status_t
+read_variable(const char *name, efi_variable_t *var)
+{
+       if (!name || !var) return EFI_INVALID_PARAMETER;
+       return fs_kernel_calls->read(name, var);
+}
+
+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);
+}
+
+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);
+}
+
+
+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);
+
+       variable_to_name(var, name);
+       return fs_kernel_calls->edit(name, var);
+}
+
+efi_status_t
+create_or_edit_variable(efi_variable_t *var)
+{
+       efi_variable_t testvar;
+       char name[PATH_MAX];
+
+       memcpy(&testvar, var, sizeof(*var));
+       variable_to_name(var, name);
+
+       if (read_variable(name, &testvar) == EFI_SUCCESS)
+               return edit_variable(var);
+       else
+               return create_variable(var);
+}
+
+static int
+select_boot_var_names(const struct dirent *d)
+{
+       if (!strncmp(d->d_name, "Boot", 4) &&
+           isxdigit(d->d_name[4]) && isxdigit(d->d_name[5]) &&
+           isxdigit(d->d_name[6]) && isxdigit(d->d_name[7]) &&
+           d->d_name[8] == '-')
+               return 1;
+       return 0;
+}
+
+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);
+}
+
+
+static int
+get_edd_version()
+{
+       efi_status_t status;
+       efi_variable_t var;
+       efi_guid_t guid = BLKX_UNKNOWN_GUID;
+       char name[80], text_guid[40];
+       ACPI_DEVICE_PATH *path = (ACPI_DEVICE_PATH *)&(var.Data);
+       int rc = 0;
+
+       /* Allow global user option override */
+
+       switch (opts.edd_version)
+       {
+       case 0: /* No EDD information */
+               return 0;
+               break;
+       case 1: /* EDD 1.0 */
+               return 1;
+               break;
+       case 3: /* EDD 3.0 */
+               return 3;
+               break;
+       default:
+               break;
+       }
+
+
+       memset(&var, 0, sizeof(efi_variable_t));
+       efi_guid_unparse(&guid, text_guid);
+       sprintf(name, "blk0-%s", text_guid);
+
+       status = read_variable(name, &var);
+       if (status != EFI_SUCCESS) {
+               return 0;
+       }
+       if (path->type == 2 && path->subtype == 1) rc = 3;
+       else rc = 1;
+       return rc;
+}
+
+/*
+  EFI_DEVICE_PATH, 0x01 (Hardware), 0x04 (Vendor), length 0x0018
+  This needs to know what EFI device has the boot device.
+*/
+static uint16_t
+make_edd10_device_path(void *dest, uint32_t hardware_device)
+{
+       VENDOR_DEVICE_PATH *hw;
+       char buffer[EDD10_HARDWARE_VENDOR_PATH_LENGTH];
+       efi_guid_t guid = EDD10_HARDWARE_VENDOR_PATH_GUID;
+       uint32_t *data;
+       memset(buffer, 0, sizeof(buffer));
+       hw = (VENDOR_DEVICE_PATH *)buffer;
+       data = (uint32_t *)hw->data;
+       hw->type = 0x01; /* Hardware Device Path */
+       hw->subtype = 0x04; /* Vendor */
+       hw->length = EDD10_HARDWARE_VENDOR_PATH_LENGTH;
+       memcpy(&(hw->vendor_guid), &guid, sizeof(guid));
+       *data = hardware_device;
+       memcpy(dest, buffer, hw->length);
+       return hw->length;
+}
+
+static uint16_t
+make_end_device_path(void *dest)
+{
+       END_DEVICE_PATH p;
+       memset(&p, 0, sizeof(p));
+       p.type = 0x7F; /* End of Hardware Device Path */
+       p.subtype = 0xFF; /* End Entire Device Path */
+       p.length = sizeof(p);
+       memcpy(dest, &p, p.length);
+       return p.length;
+}
+
+static uint16_t
+make_acpi_device_path(void *dest, uint32_t _HID, uint32_t _UID)
+{
+       ACPI_DEVICE_PATH p;
+       memset(&p, 0, sizeof(p));
+       p.type = 2;
+       p.subtype = 1;
+       p.length = sizeof(p);
+       p._HID = _HID;
+       p._UID = _UID;
+       memcpy(dest, &p, p.length);
+       return p.length;
+}
+
+static uint16_t
+make_mac_addr_device_path(void *dest, char *mac, uint8_t iftype)
+{
+
+        int i;
+       MAC_ADDR_DEVICE_PATH p;
+       memset(&p, 0, sizeof(p));
+       p.type = 3;
+       p.subtype = 11;
+       p.length = sizeof(p);
+       for (i=0; i < 14; i++) {
+               p.macaddr[i] = mac[i];
+       }
+       p.iftype = iftype;
+       memcpy(dest, &p, p.length);
+       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_one_pci_device_path(void *dest, uint8_t device, uint8_t function)
+{
+       PCI_DEVICE_PATH p;
+       memset(&p, 0, sizeof(p));
+       p.type = 1;
+       p.subtype = 1;
+       p.length   = sizeof(p);
+       p.device   = device;
+       p.function = function;
+       memcpy(dest, &p, p.length);
+       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)
+{
+       SCSI_DEVICE_PATH p;
+       memset(&p, 0, sizeof(p));
+       p.type = 3;
+       p.subtype = 2;
+       p.length   = sizeof(p);
+       p.id       = id;
+       p.lun      = lun;
+       memcpy(dest, &p, p.length);
+       return p.length;
+}
+
+static uint16_t
+make_harddrive_device_path(void *dest, uint32_t num, uint64_t start, uint64_t size,
+                          uint8_t *signature,
+                          uint8_t mbr_type, uint8_t signature_type)
+{
+       HARDDRIVE_DEVICE_PATH p;
+       memset(&p, 0, sizeof(p));
+       p.type = 4;
+       p.subtype = 1;
+       p.length   = sizeof(p);
+       p.part_num = num;
+       p.start = start;
+       p.size = size;
+       if (signature) memcpy(p.signature, signature, 16);
+       p.mbr_type = mbr_type;
+       p.signature_type = signature_type;
+       memcpy(dest, &p, p.length);
+       return p.length;
+}
+
+static uint16_t
+make_file_path_device_path(void *dest, efi_char16_t *name)
+{
+       FILE_PATH_DEVICE_PATH *p;
+       char buffer[1024];
+       int namelen  = efichar_strlen(name, -1);
+       int namesize = efichar_strsize(name);
+
+       memset(buffer, 0, sizeof(buffer));
+       p = (FILE_PATH_DEVICE_PATH *)buffer;
+       p->type      = 4;
+       p->subtype   = 4;
+       p->length    = 4 + namesize;
+       efichar_strncpy(p->path_name,
+                       name, namelen);
+
+       memcpy(dest, buffer, p->length);
+       return p->length;
+
+}
+
+
+
+static long
+make_edd30_device_path(int fd, void *buffer)
+{
+       int rc=0;
+       unsigned char bus=0, device=0, function=0;
+       Scsi_Idlun idlun;
+       unsigned char host=0, channel=0, id=0, lun=0;
+       char *p = buffer;
+
+
+       rc = disk_get_pci(fd, &bus, &device, &function);
+       if (rc) return 0;
+
+       memset(&idlun, 0, sizeof(idlun));
+       rc = get_scsi_idlun(fd, &idlun);
+       if (rc) return 0;
+       idlun_to_components(&idlun, &host, &channel, &id, &lun);
+
+       p += make_acpi_device_path      (p, EISAID_PNP0A03, bus);
+       p += make_pci_device_path       (p, bus, device, function);
+       p += make_scsi_device_path      (p, id, lun);
+       return ((void *)p - buffer);
+}
+
+/**
+ * make_disk_load_option()
+ * @disk disk
+ *
+ * Returns 0 on error, length of load option created on success.
+ */
+char *make_disk_load_option(char *p, char *disk)
+{
+    int disk_fd=0;
+    char buffer[80];
+    char signature[16];
+    int rc, edd_version=0;
+    uint8_t mbr_type=0, signature_type=0;
+    uint64_t start=0, size=0;
+    efi_char16_t os_loader_path[40];
+
+    memset(signature, 0, sizeof(signature));
+
+    disk_fd = open(opts.disk, O_RDWR);
+    if (disk_fd == -1) {
+        sprintf(buffer, "Could not open disk %s", opts.disk);
+       perror(buffer);
+       return 0;
+    }
+
+    if (opts.edd_version) {
+        edd_version = get_edd_version();
+
+       if (edd_version == 3) {
+           p += make_edd30_device_path(disk_fd, p);
+       }
+       else if (edd_version == 1) {
+           p += make_edd10_device_path(p, opts.edd10_devicenum);
+       }
+    }
+
+    rc = disk_get_partition_info (disk_fd, opts.part,
+                                 &start, &size, signature,
+                                 &mbr_type, &signature_type);
+
+    close(disk_fd);
+
+    if (rc) {
+        fprintf(stderr, "Error: no partition information on disk %s.\n"
+               "       Cowardly refusing to create a boot option.\n",
+               opts.disk);
+       return 0;
+    }
+
+    p += make_harddrive_device_path (p, opts.part,
+                                    start, size,
+                                    signature,
+                                    mbr_type, signature_type);
+
+    efichar_from_char(os_loader_path, opts.loader, sizeof(os_loader_path));
+    p += make_file_path_device_path (p, os_loader_path);
+    p += make_end_device_path       (p);
+
+    return(p);
+}
+
+/**
+ * make_net_load_option()
+ * @data - load option returned
+ *
+ * Returns NULL on error, or p advanced by length of load option
+ * created on success.
+ */
+char *make_net_load_option(char *p, char *iface)
+{
+    /* copied pretty much verbatim from the ethtool source */
+    int fd = 0, err; 
+    int bus, slot, func;
+    struct ifreq ifr;
+    struct ethtool_drvinfo drvinfo;
+
+    memset(&ifr, 0, sizeof(ifr));
+    strcpy(ifr.ifr_name, iface);
+    drvinfo.cmd = ETHTOOL_GDRVINFO;
+    ifr.ifr_data = (caddr_t)&drvinfo;
+    /* Open control socket */
+    fd = socket(AF_INET, SOCK_DGRAM, 0);
+    if (fd < 0) {
+        perror("Cannot get control socket");
+       goto out;
+    }
+    err = ioctl(fd, SIOCETHTOOL, &ifr);
+    if (err < 0) {
+        perror("Cannot get driver information");
+       goto out;
+    }
+
+    /* The domain part was added in 2.6 kernels.  Test for that first. */
+    err = sscanf(drvinfo.bus_info, "%*x:%2x:%2x.%x", &bus, &slot, &func);
+    if (err != 3) {
+           err = sscanf(drvinfo.bus_info, "%2x:%2x.%x", &bus, &slot, &func);
+           if (err != 3) {
+                   perror("Couldn't parse device location string.");
+                   goto out;
+           }
+    }
+
+    err = ioctl(fd, SIOCGIFHWADDR, &ifr);
+    if (err < 0) {
+        perror("Cannot get hardware address.");
+       goto out;
+    }
+
+    p += make_acpi_device_path(p, opts.acpi_hid, opts.acpi_uid);
+    p += make_pci_device_path(p, bus, (uint8_t)slot, (uint8_t)func);
+    p += make_mac_addr_device_path(p, ifr.ifr_ifru.ifru_hwaddr.sa_data, 0);
+    p += make_end_device_path       (p);
+    return(p);
+ out:
+    return NULL;
+}
+
+/**
+ * make_linux_load_option()
+ * @data - load option returned
+ *
+ * Returns 0 on error, length of load option created on success.
+ */
+static unsigned long
+make_linux_load_option(void *data)
+{
+       EFI_LOAD_OPTION *load_option = data;
+       char *p = data, *q;
+       efi_char16_t description[64];
+       unsigned long datasize=0;
+
+       /* Write Attributes */
+       if (opts.active) load_option->attributes = LOAD_OPTION_ACTIVE;
+       else             load_option->attributes = 0;
+
+       p += sizeof(uint32_t);
+       /* skip writing file_path_list_length */
+       p += sizeof(uint16_t);
+       /* Write description.  This is the text that appears on the screen for the load option. */
+       memset(description, 0, sizeof(description));
+       efichar_from_char(description, opts.label, sizeof(description));
+       efichar_strncpy(load_option->description, description, sizeof(description));
+       p += efichar_strsize(load_option->description);
+
+       q = p;
+
+       if (opts.iface) {
+             p = (char *)make_net_load_option(p, opts.iface);
+       }
+       else {
+             p = (char *)make_disk_load_option(p, opts.iface);
+       }
+       if (p == NULL)
+               return 0;
+
+       load_option->file_path_list_length = p - q;
+
+       datasize = (uint8_t *)p - (uint8_t *)data;
+       return datasize;
+}
+
+/*
+ * append_extra_args()
+ * appends all arguments from argv[] not snarfed by getopt
+ * as one long string onto data, up to maxchars.  allow for nulls
+ */
+
+static unsigned long
+append_extra_args_ascii(void *data, unsigned long maxchars)
+{
+       char *p = data;
+       int i, appended=0;
+       unsigned long usedchars=0;
+       if (!data) return 0;
+
+
+       for (i=opts.optind; i < opts.argc && usedchars < maxchars; i++) {
+               p = strncpy(p, opts.argv[i], maxchars-usedchars-1);
+               p += strlen(p);
+               appended=1;
+
+               usedchars = p - (char *)data;
+
+               /* Put a space between args */
+               if (i < (opts.argc-1)) {
+
+                       p = strncpy(p, " ", maxchars-usedchars-1);
+                       p += strlen(p);
+                       usedchars = p - (char *)data;
+               }
+
+       }
+       /* Remember the NULL */
+       if (appended) return strlen(data) + 1;
+       return 0;
+}
+
+static unsigned long
+append_extra_args_unicode(void *data, unsigned long maxchars)
+{
+       char *p = data;
+       int i, appended=0;
+       unsigned long usedchars=0;
+       if (!data) return 0;
+
+
+       for (i=opts.optind; i < opts.argc && usedchars < maxchars; i++) {
+               p += efichar_from_char((efi_char16_t *)p, opts.argv[i],
+                                      maxchars-usedchars);
+               usedchars = efichar_strsize(data) - sizeof(efi_char16_t);
+               appended=1;
+
+               /* Put a space between args */
+               if (i < (opts.argc-1)) {
+                       p += efichar_from_char((efi_char16_t *)p, " ",
+                                              maxchars-usedchars);
+                       usedchars = efichar_strsize(data) -
+                               sizeof(efi_char16_t);
+               }
+       }
+
+       if (appended) return efichar_strsize( (efi_char16_t *)data );
+       return 0;
+}
+
+
+static unsigned long
+append_extra_args(void *data, unsigned long maxchars)
+{
+       if (opts.unicode)
+         return append_extra_args_unicode(data, maxchars);
+       else
+         return append_extra_args_ascii(data, maxchars);
+}
+
+
+
+int
+make_linux_efi_variable(efi_variable_t *var,
+                       unsigned int free_number)
+{
+       efi_guid_t guid = EFI_GLOBAL_VARIABLE;
+       char buffer[16];
+       unsigned char *optional_data=NULL;
+       unsigned long load_option_size = 0, opt_data_size=0;
+
+       memset(buffer,    0, sizeof(buffer));
+
+       /* VariableName needs to be BootXXXX */
+       sprintf(buffer, "Boot%04X", free_number);
+
+       efichar_from_char(var->VariableName, buffer, 1024);
+
+       memcpy(&(var->VendorGuid), &guid, sizeof(guid));
+       var->Attributes =
+               EFI_VARIABLE_NON_VOLATILE |
+               EFI_VARIABLE_BOOTSERVICE_ACCESS |
+               EFI_VARIABLE_RUNTIME_ACCESS;
+
+       /* Set Data[] and DataSize */
+
+       load_option_size =  make_linux_load_option(var->Data);
+
+       if (!load_option_size) return 0;
+
+       /* Set OptionalData (passed as binary to the called app) */
+       optional_data = var->Data + load_option_size;
+       opt_data_size = append_extra_args(optional_data,
+                                 sizeof(var->Data) - load_option_size);
+       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);
+}
index 2ff5d6442f676dc0f2fd751e60b23d281a94d201..54fe2902179112878a2005281361403fabf2fb3b 100644 (file)
@@ -18,8 +18,6 @@
     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>
index 642c5ad0566a2efece75f4cc9bde4e8cb409ba32..182c70fc7047b0831917c62fd0003ca8f385794d 100644 (file)
@@ -18,8 +18,6 @@
     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>
index 85aefedd6711f7534f2a59dbd9d519673c7f0461..02985f44c5509f78f92743ac69b700c9d3cf048e 100644 (file)
@@ -22,8 +22,6 @@
     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
 
-#define _FILE_OFFSET_BITS 64
-
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
@@ -236,6 +234,7 @@ read_lba(int fd, uint64_t lba, void *buffer, size_t bytes)
        lseek(fd, offset, SEEK_SET);
        bytesread = read(fd, aligned, bytes);
         memcpy(buffer, aligned, bytesread);
+        free(unaligned);
 
         /* Kludge.  This is necessary to read/write the last
            block of an odd-sized disk, until Linux 2.5.x kernel fixes.
index e65a6597653c150337c5ca87a25b1e40a8afff51..214ab89d1e92d879f9c7fd36049cca74dd315689 100644 (file)
@@ -3,13 +3,13 @@
 .\" <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" "06 February 2004" "" ""
+.TH "EFIBOOTMGR" "8" "11 August 2005" "" ""
 
 .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 \fIseconds\fB\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 ] [ \fB-@ \fIfile\fB\fR ]
 
 .SH "DESCRIPTION"
 .PP
@@ -93,10 +93,10 @@ Partition number containing the bootloader (defaults to 1)
 Quiet mode - supresses output.
 .TP
 \fB--test \fIfilename\fB\fR
-Don't write to NVRAM, write to \fIfilename\fR.
+Don't write to NVRAM, write to \fIfilename\fR\&.
 .TP
 \fB-t | --timeout \fIseconds\fB\fR
-Boot Manager timeout, in \fIseconds\fR.
+Boot Manager timeout, in \fIseconds\fR\&.
 .TP
 \fB-T | --delete-timeout\fR
 Delete Timeout variable.
@@ -116,6 +116,12 @@ Just print version string and exit.
 .TP
 \fB-w | --write-signature\fR
 write unique signature to the MBR if needed
+.TP
+\fB-@ | --append-binary-args \fR
+append extra variable args from file (use - to read
+from stdin).  Data in file is appended as command line
+arguments to the boot loader command, with no modification to
+the data, so you can pass any binary or text data necessary.
 .SH "EXAMPLES"
 .TP 3
 1. 
@@ -164,12 +170,12 @@ flag (* means active) and the name displayed on the screen.
 2. 
 .SS "CREATING A NEW BOOT OPTION"
 .PP
-An OS installer would call \fBefibootmgr -c\fR.
+An OS installer would call \fBefibootmgr -c\fR\&.
 This assumes that \fI/boot/efi\fR is your EFI System
-Partition, and is mounted at \fI/dev/sda1\fR.  This
+Partition, and is mounted at \fI/dev/sda1\fR\&.  This
 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.
+behavior.  The default OS Loader is \fIelilo.efi\fR\&.
 .TP 3
 3. 
 .SS "CHANGING THE BOOT ORDER"
@@ -212,7 +218,7 @@ You create the boot entry with:
 .SH "BUGS"
 .PP
 Please direct any bugs, features, patches, etc. to Matt Domsch
-<Matt_Domsch@dell.com>.
+<Matt_Domsch@dell.com>\&.
 .SH "AUTHOR"
 .PP
 This man page was generated by dann frazier <dannf@debian.org> for the 
index 0eec0f7dfa5c127159961c73d170fa60f8a30480..aef44443f81ef0c929b31e712b7e338c84388524 100644 (file)
@@ -1,4 +1,3 @@
-
 <!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN" [
 
 <!-- This manpage was compiled by dann frazier <email>dannf@debian.org</email>,
@@ -17,7 +16,7 @@
   <!ENTITY manfirstname "<firstname>dann</firstname>">
   <!ENTITY mansurname   "<surname>frazier</surname>">
   <!-- Please adjust the date whenever revising the manpage. -->
-  <!ENTITY mandate      "<date>2004-02-05</date>">
+  <!ENTITY mandate      "<date>2005-08-11</date>">
   <!-- SECTION should be 1-8, maybe with subsection. Other parameters are
        allowed: see man(7), man(1). -->
   <!ENTITY mansection   "<manvolnum>8</manvolnum>">
@@ -82,6 +81,7 @@
         <arg>-v</arg>
         <arg>-V</arg>
         <arg>-w</arg>
+        <arg>-@ <replaceable>file</replaceable></arg>
     </cmdsynopsis>
   </refsynopsisdiv>
   <refsect1>
           <para>write unique signature to the MBR if needed</para>
         </listitem>
       </varlistentry>
+      <varlistentry>
+        <term><option>-@</option> |
+        <option>--append-binary-args</option>
+         </term>
+        <listitem>
+          <para>append extra variable args from file (use - to read
+        from stdin).  Data in file is appended as command line
+        arguments to the boot loader command, with no modification to
+        the data, so you can pass any binary or text data necessary.</para>
+        </listitem>
+      </varlistentry>
     </variablelist>
+
   </refsect1>
 
   <refsect1>