From: Bdale Garbee Date: Mon, 25 Feb 2008 00:30:01 +0000 (-0700) Subject: Imported Debian patch 0.5.4-1 X-Git-Tag: debian/0.5.4-1^0 X-Git-Url: https://git.gag.com/?p=debian%2Fefibootmgr;a=commitdiff_plain;h=438378f384ede73602fcdfd288e45ac41d933bb0 Imported Debian patch 0.5.4-1 --- diff --git a/Makefile b/Makefile index 77e640d..c4fbee0 100644 --- a/Makefile +++ b/Makefile @@ -1,14 +1,14 @@ default: all - RELEASE_DATE := "09-Nov-2005" + RELEASE_DATE := "03-Jan-2008" RELEASE_MAJOR := 0 RELEASE_MINOR := 5 - RELEASE_SUBLEVEL := 3 + RELEASE_SUBLEVEL := 4 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)\" \ + CFLAGS = $(EXTRA_CFLAGS) -DEFIBOOTMGR_VERSION=\"$(RELEASE_MAJOR).$(RELEASE_MINOR).$(RELEASE_SUBLEVEL)$(RELEASE_EXTRALEVEL)\" \ -Wall -g -D_FILE_OFFSET_BITS=64 LDFLAGS += -lz @@ -58,7 +58,7 @@ cp -a ../$(RELEASE_NAME) ../$(RELEASE_STRING) find ../$(RELEASE_STRING) -name CVS -type d -depth -exec rm -rf \{\} \; sync; sync; sync; - cd ..; tar cvzf $(RELEASE_STRING).tar.gz $(RELEASE_STRING) + cd ..; tar cvzf $(RELEASE_STRING).tar.gz --exclude=.git --exclude=\*~ $(RELEASE_STRING) mv ../$(RELEASE_STRING).tar.gz . rm -rf ../$(RELEASE_STRING) diff --git a/debian/changelog b/debian/changelog index 5bb9b54..5d87232 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +efibootmgr (0.5.4-1) unstable; urgency=low + + * new upstream version + + -- Bdale Garbee Sun, 24 Feb 2008 17:30:01 -0700 + efibootmgr (0.5.3-3) unstable; urgency=low * fix FTBFS, closes: #450448 diff --git a/doc/ChangeLog b/doc/ChangeLog index eada84f..adfc17d 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,6 +1,99 @@ -* Wed Nov 9 2005 Matt Domsch -- released v0.5.2.2 as v0.5.3, no changes - +commit 6e6bf6fc7665851798a6c2c92893ebb629e42aff +Author: Matt Domsch +Date: Fri Jan 11 15:08:12 2008 -0600 + + replacing elilo < 3.6-6, not -5 + + per conversation with clumens. + +commit 4c1fd35da4d0478074e08c10225eb590576acf91 +Author: Matt Domsch +Date: Thu Jan 3 12:19:28 2008 -0600 + + RPM spec rewrite for Fedora inclusion + + efibootmgr is being split out of the elilo SRPM in Fedora, into its + own SRPM. + +commit 833cf4c1266ef72357948299008a22bfb80aa3f3 +Author: Matt Domsch +Date: Thu Jan 3 12:18:31 2008 -0600 + + Makefile cleanups + + bump version + + take an EXTRA_CFLAGS argument so rpmbuild can give us it's CFLAGS + without overriding ours. + + exclude .git and *~ files from the tarball. + +commit f0a8b91ba45ff4cf251805cc29aed4f8672c1801 +Author: Matt Domsch +Date: Thu Jan 3 12:16:35 2008 -0600 + + src/lib/efi.c: include linux/types.h + + patch from Fedora. + +commit f387d5c5bde5d7129e41638e92faa2d38b7ad5a1 +Author: Matt Domsch +Date: Thu Jan 3 12:15:18 2008 -0600 + + make sure GPT_HEADER_SIGNATURE is a 64-bit value + + patch from Debian / Ubuntu 0.5.3-3ubuntu1. + +commit 7b53efa45112f28e97451bdc16e6c6a68740bd79 +Author: Matt Domsch +Date: Mon Nov 12 13:31:32 2007 -0600 + + avoid more unaligned access warnings + +commit 048197821f9ae2ef9e0c2bd4065649e72332e2dc +Author: Matt Domsch +Date: Mon Nov 12 12:25:42 2007 -0600 + + cleanup a few unaligned access warnings + +commit fa3942b34f1533659af8fe3f6fffb3b4acf4ee10 +Author: Matt Domsch +Date: Mon Nov 12 12:12:37 2007 -0600 + + cleanup exit values a little + +commit c7e236783a79b6977df0ba03db0f92fabffc4b31 +Author: Doug Chapman +Date: Mon Nov 12 11:32:12 2007 -0500 + + patch to make efibootmgr have non-zero exit code on errors + + We have some automated tools that use efibootmgr which are having a hard + time detecting when efibootmgr fails since it exits with 0 on many + failures. This patch catches (most) errors and exits with non-zero. I + also added several error messages for to make it more obvious what was + wrong with the command line arguments. + + Signed-off-by: Matt Domsch + +commit ecd3c24cb6bee5072ff6d1292456ee3b2cc91019 +Author: Matt Domsch +Date: Mon Jul 9 16:47:50 2007 +0000 + + add -lz to libs, needed when libpci happens to need it + +commit e192a055e0803263b71f89db732de73d5cf4de9b +Author: Matt Domsch +Date: Mon Jul 9 16:23:34 2007 +0000 + + apply patch from Dave Jiang to enable cross-building + +commit 0ee8ecc10109b91d0a77098d5596f56780c862d8 +Author: Matt Domsch +Date: Thu Aug 11 17:37:04 2005 +0000 + + v0.5.2.2 + * Thu Aug 11 2005 Matt Domsch - applied patch from Rogerio Timmers which adds a new option -@ , which takes extra variable parameters from , or - from stdin. diff --git a/efibootmgr.spec b/efibootmgr.spec index 5a8b832..6990bcd 100644 --- a/efibootmgr.spec +++ b/efibootmgr.spec @@ -1,38 +1,52 @@ Summary: EFI Boot Manager Name: efibootmgr -Version: 0.5.0 -Release: 0 +Version: 0.5.4 +Release: 1%{?dist} Group: System Environment/Base -Copyright: GPL -Vendor: Dell linux.dell.com -Packager: Matt Domsch +License: GPLv2+ +URL: http://linux.dell.com/%{name}/ +BuildRequires: pciutils-devel, zlib-devel +BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXXXX) +# EFI/UEFI don't exist on PPC +ExclusiveArch: i386 x86_64 ia64 +# for RHEL / Fedora when efibootmgr was part of the elilo package +Conflicts: elilo < 3.6-6 +Obsoletes: elilo < 3.6-6 -Source0: http://linux.dell.com/efibootmgr/permalink/efibootmgr-%{version}.tar.gz -Source1: http://linux.dell.com/efibootmgr/permalink/efibootmgr-%{version}.tar.gz.sign +Source0: http://linux.dell.com/%{name}/permalink/%{name}-%{version}.tar.gz %description -efibootmgr displays and allows the user to edit the Intel Extensible +%{name} displays and allows the user to edit the Intel Extensible Firmware Interface (EFI) Boot Manager variables. Additional information about EFI can be found at -http://developer.intel.com/technology/efi/efi.htm. +http://developer.intel.com/technology/efi/efi.htm and http://uefi.org/. %prep -%setup +%setup -q %build -make +make %{?_smp_mflags} EXTRA_CFLAGS='%{optflags}' %install -install --group=root --owner=root --mode 555 src/efibootmgr/efibootmgr $RPM_BUILD_ROOT/usr/sbin -install --group=root --owner=root --mode 444 src/man/man8/efibootmgr.8 $RPM_BUILD_ROOT/usr/share/man/man8 +rm -rf %{buildroot} +mkdir -p %{buildroot}%{_sbindir} %{buildroot}%{_mandir}/man8 +install -p --mode 755 src/%{name}/%{name} %{buildroot}%{_sbindir} +gzip -9 -c src/man/man8/%{name}.8 > src/man/man8/%{name}.8.gz +touch -r src/man/man8/%{name}.8 src/man/man8/%{name}.8.gz +install -p --mode 644 src/man/man8/%{name}.8.gz %{buildroot}%{_mandir}/man8 -%files -/usr/sbin/efibootmgr -/usr/share/man/man8/efibootmgr.8 -%doc README -%doc INSTALL +%clean +rm -rf %{buildroot} +%files +%defattr(-,root,root,-) +%{_sbindir}/%{name} +%{_mandir}/man8/%{name}.8.gz +%doc README INSTALL COPYING %changelog +* Thu Jan 3 2008 Matt Domsch 0.5.4-1 +- split efibootmgr into its own RPM for Fedora/RHEL. + * Thu Aug 24 2004 Matt Domsch - new home linux.dell.com diff --git a/src/efibootmgr/efibootmgr.c b/src/efibootmgr/efibootmgr.c index 7aeb186..5db0d9e 100644 --- a/src/efibootmgr/efibootmgr.c +++ b/src/efibootmgr/efibootmgr.c @@ -436,7 +436,10 @@ delete_boot_var(uint16_t num) status = delete_variable(&var); } - if (status) return status; + if (status) { + fprintf (stderr,"\nboot entry: %X not found\n\n",num); + return status; + } list_for_each_safe(pos, n, &boot_entry_list) { boot = list_entry(pos, var_entry_t, list); if (boot->num == num) { @@ -583,6 +586,21 @@ unparse_boot_order(uint16_t *order, int length) printf("\n"); } +static int +is_current_boot_entry(int b) +{ + list_t *pos; + var_entry_t *boot; + + list_for_each(pos, &boot_entry_list) { + boot = list_entry(pos, var_entry_t, list); + if (boot->num == b) + return 1; + } + return 0; +} + + static int parse_boot_order(char *buffer, uint16_t *order, int length) { @@ -592,6 +610,16 @@ parse_boot_order(char *buffer, uint16_t *order, int length) for (i=0; i= 0) { - set_active_state(); + if (opts.bootnum == -1) { + fprintf(stderr, "\nYou must specify a boot entry to delete (see the -b option).\n\n"); + return 1; + } + else + ret=set_active_state(); } } if (opts.create) { warn_duplicate_name(&boot_entry_list); new_boot = make_boot_var(&boot_entry_list); + if (!new_boot) + return 1; + /* Put this boot var in the right BootOrder */ if (!opts.testfile && new_boot) - add_to_boot_order(new_boot->num); + ret=add_to_boot_order(new_boot->num); } if (!opts.testfile) { if (opts.delete_bootorder) { - delete_var("BootOrder"); + ret=delete_var("BootOrder"); } if (opts.bootorder) { - set_boot_order(); + ret=set_boot_order(); } if (opts.delete_bootnext) { - delete_var("BootNext"); + ret=delete_var("BootNext"); } if (opts.delete_timeout) { - delete_var("Timeout"); + ret=delete_var("Timeout"); } if (opts.bootnext >= 0) { - set_boot_u16("BootNext", opts.bootnext & 0xFFFF); + if (!is_current_boot_entry(opts.bootnext & 0xFFFF)){ + fprintf (stderr,"\n\nboot entry %X does not exist\n\n", + opts.bootnext); + return 1; + } + ret=set_boot_u16("BootNext", opts.bootnext & 0xFFFF); } if (opts.set_timeout) { - set_boot_u16("Timeout", opts.timeout); + ret=set_boot_u16("Timeout", opts.timeout); } - if (!opts.quiet) { + if (!opts.quiet && ret == 0) { num = read_boot_u16("BootNext"); if (num != -1 ) { printf("BootNext: %04X\n", num); @@ -1045,6 +1130,8 @@ main(int argc, char **argv) } free_dirents(boot_names, num_boot_names); free_vars(&boot_entry_list); + if (ret) + return 1; return 0; } diff --git a/src/efibootmgr/efibootmgr.c.orig b/src/efibootmgr/efibootmgr.c.orig deleted file mode 100644 index 5a1a0d9..0000000 --- a/src/efibootmgr/efibootmgr.c.orig +++ /dev/null @@ -1,1045 +0,0 @@ -/* - efibootmgr.c - Manipulates EFI variables as exported in /proc/efi/vars - - Copyright (C) 2001-2004 Dell, Inc. - - 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#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; ivar_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; -} - diff --git a/src/efibootmgr/module.mk b/src/efibootmgr/module.mk index dac4907..790e2e4 100644 --- a/src/efibootmgr/module.mk +++ b/src/efibootmgr/module.mk @@ -11,7 +11,7 @@ efibootmgr_LIBS := crc32.o disk.o efi.o efichar.o gpt.o scsi_ioctls.o \ efibootmgr_LIBDIR := src/lib efibootmgr_FULLLIB := \ $(patsubst %,$(efibootmgr_LIBDIR)/%,$(efibootmgr_LIBS)) -LIBS = -lpci +LIBS = -lpci -lz ALLDEPS += $(efibootmgr_FULLTARGET) CLEANLIST += $(efibootmgr_FULLTARGET) @@ -20,5 +20,5 @@ bindir_TARGETS += $(efibootmgr_FULLTARGET) $(efibootmgr_FULLTARGET): \ $(efibootmgr_FULLOBJECT) \ - $(efibootmgr_FULLLIB) \ - $(LIBS) + $(efibootmgr_FULLLIB) + $(CC) $(CFLAGS) $(LDFLAGS) $(efibootmgr_SRCDIR)/efibootmgr.c $^ $(LIBS) -o $@ diff --git a/src/lib/efi.c b/src/lib/efi.c index a760eb1..a4ce5cf 100644 --- a/src/lib/efi.c +++ b/src/lib/efi.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -721,7 +722,7 @@ append_extra_args_file(void *data, unsigned long maxchars) if (fd == -1) { perror("Failed to open extra arguments file"); - return 0; + exit(1); } do { diff --git a/src/lib/efi.c.orig b/src/lib/efi.c.orig deleted file mode 100644 index 2257e9f..0000000 --- a/src/lib/efi.c.orig +++ /dev/null @@ -1,765 +0,0 @@ -/* - efivars_proc.[ch] - Manipulates EFI variables as exported in /proc/efi/vars - - Copyright (C) 2001,2003 Dell Computer Corporation - - 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#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); -} diff --git a/src/lib/gpt.c b/src/lib/gpt.c index 02985f4..d90ddaf 100644 --- a/src/lib/gpt.c +++ b/src/lib/gpt.c @@ -624,9 +624,8 @@ gpt_disk_get_partition_info(int fd, memcpy(signature, &p->unique_partition_guid, sizeof (p->unique_partition_guid)); } else { - *start = 0; - *size = last_lba(fd) + 1; - memcpy(signature, &gpt->disk_guid, sizeof (gpt->disk_guid)); + fprintf (stderr,"partition %d is not valid\n", num); + return 1; } return 0; } diff --git a/src/lib/unparse_path.c b/src/lib/unparse_path.c index 3c28f1c..d123ae6 100644 --- a/src/lib/unparse_path.c +++ b/src/lib/unparse_path.c @@ -32,7 +32,8 @@ #include "unparse_path.h" #include "efichar.h" - +/* Avoid unaligned access warnings */ +#define get(buf, obj) *(typeof(obj) *)memcpy(buf, &obj, sizeof(obj)) void @@ -72,12 +73,11 @@ dump_raw_data(void *data, uint64_t length) unsigned long unparse_raw(char *buffer, uint8_t *p, uint64_t length) { - uint64_t i; unsigned char c; + uint64_t i; + char a[1]; char *q = buffer; for (i=0; i 127) c = '.'; - q += sprintf(q, "%02x", c); + q += sprintf(q, "%02x", get(a, p[i])); } return q - buffer; } @@ -112,10 +112,11 @@ static int unparse_acpi_path(char *buffer, EFI_DEVICE_PATH *path) { ACPI_DEVICE_PATH *acpi = (ACPI_DEVICE_PATH *)path; + char a[16], b[16]; switch (path->subtype) { case 1: - return sprintf(buffer, "ACPI(%x,%x)", acpi->_HID, acpi->_UID); + return sprintf(buffer, "ACPI(%x,%x)", get(a, acpi->_HID), get(b, acpi->_UID)); break; default: return unparse_raw(buffer, (uint8_t *)path, path->length); @@ -127,7 +128,8 @@ unparse_acpi_path(char *buffer, EFI_DEVICE_PATH *path) static int unparse_vendor_path(char *buffer, VENDOR_DEVICE_PATH *path) { - char text_guid[40], *p = buffer, *q = (uint8_t *)path + 20; + char text_guid[40], *p = buffer; + unsigned char *q = (uint8_t *)path + 20; efi_guid_unparse(&path->vendor_guid, text_guid); p += sprintf(p, "Vendor(%s,", text_guid); p += unparse_raw(p, q, path->length - 20); @@ -142,26 +144,27 @@ unparse_hardware_path(char *buffer, EFI_DEVICE_PATH *path) PCCARD_DEVICE_PATH *pccard = (PCCARD_DEVICE_PATH *)path; MEMORY_MAPPED_DEVICE_PATH *mm = (MEMORY_MAPPED_DEVICE_PATH *)path; CONTROLLER_DEVICE_PATH *ctlr = (CONTROLLER_DEVICE_PATH *)path; + char a[16], b[16], c[16]; switch (path->subtype) { case 1: - return sprintf(buffer, "PCI(%x,%x)", - pci->device, pci->function); + return sprintf(buffer, "PCI(%x,%x)", get(a, pci->device), get(b, pci->function)); break; case 2: - return sprintf(buffer, "PCCARD(%x)", pccard->socket); + return sprintf(buffer, "PCCARD(%x)", get(a, pccard->socket)); break; case 3: return sprintf(buffer, "MM(%x,%" PRIx64 ",%" PRIx64 ")", - mm->memory_type, - mm->start, mm->end); + get(a, mm->memory_type), + get(b, mm->start), + get(c, mm->end)); break; case 4: return unparse_vendor_path(buffer, (VENDOR_DEVICE_PATH *)path); break; case 5: - return sprintf(buffer, "Controller(%x)", ctlr->controller); + return sprintf(buffer, "Controller(%x)", get(a, ctlr->controller)); break; default: @@ -185,33 +188,35 @@ unparse_messaging_path(char *buffer, EFI_DEVICE_PATH *path) IPv4_DEVICE_PATH *ipv4 = (IPv4_DEVICE_PATH *)path; /* IPv6_DEVICE_PATH *ipv6 = (IPv6_DEVICE_PATH *)path; */ char *p = buffer; + char a[16], b[16], c[16], d[16], e[16]; switch (path->subtype) { case 1: return sprintf(buffer, "ATAPI(%x,%x,%x)", - atapi->primary_secondary, - atapi->slave_master, atapi->lun); + get(a, atapi->primary_secondary), + get(b, atapi->slave_master), + get(c, atapi->lun)); break; case 2: - return sprintf(buffer, "SCSI(%x,%x)", scsi->id, scsi->lun); + return sprintf(buffer, "SCSI(%x,%x)", get(a, scsi->id), get(b, scsi->lun)); break; case 3: - return sprintf(buffer, "FC(%" PRIx64 ",%" PRIx64 ")", fc->wwn, fc->lun); + return sprintf(buffer, "FC(%" PRIx64 ",%" PRIx64 ")", get(a, fc->wwn), get(b, fc->lun)); break; case 4: - return sprintf(buffer, "1394(%" PRIx64 ")", i1394->guid); + return sprintf(buffer, "1394(%" PRIx64 ")", get(a, i1394->guid)); break; case 5: - return sprintf(buffer, "USB(%x,%x)", usb->port, usb->endpoint); + return sprintf(buffer, "USB(%x,%x)", get(a, usb->port), get(b, usb->endpoint)); break; case 6: - return sprintf(buffer, "I2O(%x)", i2o->tid); + return sprintf(buffer, "I2O(%x)", get(a, i2o->tid)); break; case 11: p += sprintf(p, "MAC("); p += unparse_raw(p, mac->macaddr, 6); - p += sprintf(p, ",%hhx)", mac->iftype); + p += sprintf(p, ",%hhx)", get(a, mac->iftype)); return (int) (p - buffer); break; case 12: @@ -219,15 +224,15 @@ unparse_messaging_path(char *buffer, EFI_DEVICE_PATH *path) p += unparse_ipv4_port(p, ipv4->local_ip, ipv4->local_port); p += sprintf(p, "<->"); p += unparse_ipv4_port(p, ipv4->remote_ip, ipv4->remote_port); - p += sprintf(p, ",%hx, %hhx", ipv4->protocol, ipv4->static_addr); + p += sprintf(p, ",%hx, %hhx", get(a, ipv4->protocol), get(b, ipv4->static_addr)); return (int) (p - buffer); break; case 15: return sprintf(buffer, "USBClass(%hx,%hx,%hhx,%hhx,%hhx)", - usbclass->vendor, usbclass->product, - usbclass->class, usbclass->subclass, - usbclass->protocol); + get(a, usbclass->vendor), get(b, usbclass->product), + get(c, usbclass->class), get(d, usbclass->subclass), + get(e, usbclass->protocol)); break; default: return unparse_raw(buffer, (uint8_t *)path, path->length); @@ -241,13 +246,15 @@ unparse_media_hard_drive_path(char *buffer, EFI_DEVICE_PATH *path) { HARDDRIVE_DEVICE_PATH *hd = (HARDDRIVE_DEVICE_PATH *)path; char text_uuid[40], *sig=text_uuid; + char a[16], b[16], c[16]; switch (hd->signature_type) { case 0x00: sprintf(sig, "None"); break; case 0x01: - sprintf(sig, "%08x", *(uint32_t *)hd->signature); + sprintf(sig, "%08x", *(uint32_t *)memcpy(a, &hd->signature, + sizeof(hd->signature))); break; case 0x02: /* GPT */ efi_guid_unparse((efi_guid_t *)hd->signature, sig); @@ -257,7 +264,10 @@ unparse_media_hard_drive_path(char *buffer, EFI_DEVICE_PATH *path) } return sprintf(buffer, "HD(%x,%" PRIx64 ",%" PRIx64 ",%s)", - hd->part_num, hd->start, hd->size, sig); + get(a, hd->part_num), + get(b, hd->start), + get(c, hd->size), + sig); } @@ -272,6 +282,7 @@ unparse_media_path(char *buffer, EFI_DEVICE_PATH *path) char text_guid[40], *p = buffer; char file_name[80]; memset(file_name, 0, sizeof(file_name)); + char a[16], b[16], c[16]; switch (path->subtype) { case 1: @@ -279,7 +290,7 @@ unparse_media_path(char *buffer, EFI_DEVICE_PATH *path) break; case 2: return sprintf(buffer, "CD-ROM(%x,%" PRIx64 ",%" PRIx64 ")", - cdrom->boot_entry, cdrom->start, cdrom->size); + get(a, cdrom->boot_entry), get(b, cdrom->start), get(c, cdrom->size)); break; case 3: return unparse_vendor_path(buffer, (VENDOR_DEVICE_PATH *)path); @@ -302,9 +313,11 @@ static int unparse_bios_path(char *buffer, EFI_DEVICE_PATH *path) { BIOS_BOOT_SPEC_DEVICE_PATH *bios = (BIOS_BOOT_SPEC_DEVICE_PATH *)path; - char *p = buffer, *q = (uint8_t *)path + 8; + char *p = buffer; + unsigned char *q = (uint8_t *)path + 8; + char a[16], b[16]; p += sprintf(p, "BIOS(%x,%x,", - bios->device_type, bios->status_flag); + get(a, bios->device_type), get(b, bios->status_flag)); p += unparse_raw(p, q, path->length - 8); p += sprintf(p, ")"); return p - buffer;