Index: efibootmgr/Makefile
===================================================================
--- efibootmgr/Makefile (nonexistent)
+++ efibootmgr/Makefile (revision 15)
@@ -0,0 +1,56 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url = $(DOWNLOAD_SERVER)/sources/packages/a/efibootmgr
+
+versions = 18
+pkgname = efibootmgr
+suffix = tar.xz
+
+tarballs = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s = $(addsuffix .sha1sum, $(tarballs))
+
+patches = $(CURDIR)/patches/efibootmgr-18-wrong-check-reconnect.patch
+
+.NOTPARALLEL: $(patches)
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s) $(patches)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+ @echo -e "\n======= Downloading source tarballs =======" ; \
+ for tarball in $(tarballs) ; do \
+ echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+ done ; wait
+
+$(sha1s): $(tarballs)
+ @for sha in $@ ; do \
+ echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+ echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+ touch $$sha ; \
+ echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+ sha1sum --check $$sha ; ret="$$?" ; \
+ if [ "$$ret" == "1" ]; then \
+ echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+ exit 1 ; \
+ fi ; \
+ done
+
+$(patches): $(sha1s)
+ @echo -e "\n======= Create Patches =======\n" ; \
+ ( cd create-18-wrong-check-reconnect-patch ; ./create.patch.sh ) ; \
+ echo -e "\n"
+
+download_clean:
+ @rm -f $(tarballs) $(sha1s) $(patches)
Index: efibootmgr/create-18-wrong-check-reconnect-patch/create.patch.sh
===================================================================
--- efibootmgr/create-18-wrong-check-reconnect-patch/create.patch.sh (nonexistent)
+++ efibootmgr/create-18-wrong-check-reconnect-patch/create.patch.sh (revision 15)
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+VERSION=18
+
+tar --files-from=file.list -xJvf ../efibootmgr-$VERSION.tar.xz
+mv efibootmgr-$VERSION efibootmgr-$VERSION-orig
+
+cp -rf ./efibootmgr-$VERSION-new ./efibootmgr-$VERSION
+
+diff --unified -Nr efibootmgr-$VERSION-orig efibootmgr-$VERSION > efibootmgr-$VERSION-wrong-check-reconnect.patch
+
+mv efibootmgr-$VERSION-wrong-check-reconnect.patch ../patches
+
+rm -rf ./efibootmgr-$VERSION
+rm -rf ./efibootmgr-$VERSION-orig
Property changes on: efibootmgr/create-18-wrong-check-reconnect-patch/create.patch.sh
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: efibootmgr/create-18-wrong-check-reconnect-patch/efibootmgr-18-new/src/efibootmgr.c
===================================================================
--- efibootmgr/create-18-wrong-check-reconnect-patch/efibootmgr-18-new/src/efibootmgr.c (nonexistent)
+++ efibootmgr/create-18-wrong-check-reconnect-patch/efibootmgr-18-new/src/efibootmgr.c (revision 15)
@@ -0,0 +1,1994 @@
+/*
+ efibootmgr.c - Manipulates EFI variables as exported in /sys/firmware/efi/
+ efivars or vars (previously /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/EFI/<vendor>/<loader>.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 ??
+
+*/
+
+#include "fix_coverity.h"
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <efivar.h>
+#include <efiboot.h>
+#include <inttypes.h>
+
+#include "list.h"
+#include "efi.h"
+#include "parse_loader_data.h"
+#include "efibootmgr.h"
+#include "error.h"
+
+#ifndef EFIBOOTMGR_VERSION
+#define EFIBOOTMGR_VERSION "unknown (fix Makefile!)"
+#endif
+
+int verbose;
+
+typedef struct _var_entry {
+ char *name;
+ efi_guid_t guid;
+ uint8_t *data;
+ size_t data_size;
+ uint32_t attributes;
+ uint16_t num;
+ list_t list;
+} var_entry_t;
+
+/* global variables */
+static LIST_HEAD(entry_list);
+static LIST_HEAD(blk_list);
+efibootmgr_opt_t opts;
+
+static void
+free_vars(list_t *head)
+{
+ list_t *pos, *n;
+ var_entry_t *entry;
+
+ list_for_each_safe(pos, n, head) {
+ entry = list_entry(pos, var_entry_t, list);
+ if (entry->name)
+ free(entry->name);
+ if (entry->data)
+ free(entry->data);
+ list_del(&(entry->list));
+ free(entry);
+ }
+}
+
+static void
+read_vars(char **namelist,
+ list_t *head)
+{
+ var_entry_t *entry;
+ int i, rc;
+
+ if (!namelist)
+ return;
+
+ for (i=0; namelist[i] != NULL; i++) {
+ if (namelist[i]) {
+ entry = calloc(1, sizeof(var_entry_t));
+ if (!entry) {
+ efi_error("calloc(1, %zd) failed",
+ sizeof(var_entry_t));
+ goto err;
+ }
+
+ rc = efi_get_variable(EFI_GLOBAL_GUID, namelist[i],
+ &entry->data, &entry->data_size,
+ &entry->attributes);
+ if (rc < 0) {
+ warning("Skipping unreadable variable \"%s\"",
+ namelist[i]);
+ free(entry);
+ continue;
+ }
+
+ /* latest apple firmware sets high bit which appears
+ * invalid to the linux kernel if we write it back so
+ * lets zero it out if it is set since it would be
+ * invalid to set it anyway */
+ entry->attributes = entry->attributes & ~(1 << 31);
+
+ entry->name = strdup(namelist[i]);
+ if (!entry->name) {
+ efi_error("strdup(\"%s\") failed", namelist[i]);
+ goto err;
+ }
+ entry->guid = EFI_GLOBAL_GUID;
+ list_add_tail(&entry->list, head);
+ }
+ }
+ return;
+err:
+ exit(1);
+}
+
+static void
+free_array(char **array)
+{
+ int i;
+
+ if (!array)
+ return;
+
+ for (i = 0; array[i] != NULL; i++)
+ free(array[i]);
+
+ free(array);
+}
+
+static int
+compare(const void *a, const void *b)
+{
+ int rc = -1;
+ uint16_t n1, n2;
+ memcpy(&n1, a, sizeof(n1));
+ memcpy(&n2, b, sizeof(n2));
+ if (n1 < n2) rc = -1;
+ if (n1 == n2) rc = 0;
+ if (n1 > n2) rc = 1;
+ return rc;
+}
+
+
+/*
+ Return an available variable number,
+ or -1 on failure.
+*/
+static int
+find_free_var(list_t *var_list)
+{
+ int num_vars=0, i=0, found;
+ uint16_t *vars, free_number;
+ list_t *pos;
+ var_entry_t *entry;
+
+ list_for_each(pos, var_list)
+ num_vars++;
+
+ if (num_vars == 0)
+ return 0;
+
+ vars = calloc(1, sizeof(uint16_t) * num_vars);
+ if (!vars) {
+ efi_error("calloc(1, %zd) failed", sizeof(uint16_t) * num_vars);
+ return -1;
+ }
+
+ list_for_each(pos, var_list) {
+ entry = list_entry(pos, var_entry_t, list);
+ vars[i] = entry->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, var_list) {
+ entry = list_entry(pos, var_entry_t, list);
+ if (entry->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 *var_list)
+{
+ list_t *pos;
+ var_entry_t *entry;
+ efi_load_option *load_option;
+ const unsigned char *desc;
+
+ list_for_each(pos, var_list) {
+ entry = list_entry(pos, var_entry_t, list);
+ load_option = (efi_load_option *)entry->data;
+ desc = efi_loadopt_desc(load_option, entry->data_size);
+ if (!strcmp((char *)opts.label, (char *)desc))
+ warnx("** Warning ** : %s has same label %s",
+ entry->name, opts.label);
+ }
+}
+
+static var_entry_t *
+make_var(const char *prefix, list_t *var_list)
+{
+ var_entry_t *entry = NULL;
+ int free_number;
+ list_t *pos;
+ int rc;
+ uint8_t *extra_args = NULL;
+ ssize_t extra_args_size = 0;
+ ssize_t needed=0, sz;
+
+ if (opts.num == -1) {
+ free_number = find_free_var(var_list);
+ } else {
+ list_for_each(pos, var_list) {
+ entry = list_entry(pos, var_entry_t, list);
+ if (entry->num == opts.num)
+ errx(40,
+ "Cannot create %s%04X: already exists.",
+ prefix, opts.num);
+ }
+ free_number = opts.num;
+ }
+
+ if (free_number == -1) {
+ efi_error("efibootmgr: no available %s variables", prefix);
+ return NULL;
+ }
+
+ /* Create a new var_entry_t object
+ and populate it.
+ */
+ entry = calloc(1, sizeof(*entry));
+ if (!entry) {
+ efi_error("calloc(1, %zd) failed", sizeof(*entry));
+ return NULL;
+ }
+
+ sz = get_extra_args(NULL, 0);
+ if (sz < 0) {
+ efi_error("get_extra_args() failed");
+ goto err;
+ }
+ extra_args_size = sz;
+
+ entry->data = NULL;
+ entry->data_size = 0;
+ needed = make_linux_load_option(&entry->data, &entry->data_size,
+ NULL, sz);
+ if (needed < 0) {
+ efi_error("make_linux_load_option() failed");
+ goto err;
+ }
+ entry->data_size = needed;
+ entry->data = malloc(needed);
+ if (!entry->data) {
+ efi_error("malloc(%zd) failed", needed);
+ goto err;
+ }
+
+ extra_args = entry->data + needed - extra_args_size;
+ sz = get_extra_args(extra_args, extra_args_size);
+ if (sz < 0) {
+ efi_error("get_extra_args() failed");
+ goto err;
+ }
+ sz = make_linux_load_option(&entry->data, &entry->data_size,
+ extra_args, extra_args_size);
+ if (sz < 0) {
+ efi_error("make_linux_load_option failed");
+ goto err;
+ }
+
+ entry->num = free_number;
+ entry->guid = EFI_GLOBAL_GUID;
+ rc = asprintf(&entry->name, "%s%04X", prefix, free_number);
+ if (rc < 0) {
+ efi_error("asprintf failed");
+ goto err;
+ }
+ entry->attributes = EFI_VARIABLE_NON_VOLATILE |
+ EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_RUNTIME_ACCESS;
+ rc = efi_set_variable(entry->guid, entry->name, entry->data,
+ entry->data_size, entry->attributes, 0644);
+ if (rc < 0) {
+ efi_error("efi_set_variable failed");
+ goto err;
+ }
+ list_add_tail(&entry->list, var_list);
+ return entry;
+err:
+ if (entry) {
+ if (entry->data)
+ free(entry->data);
+ if (entry->name) {
+ efi_error("Could not set variable %s", entry->name);
+ free(entry->name);
+ } else {
+ efi_error("Could not set variable");
+ }
+ free(entry);
+ }
+ return NULL;
+}
+
+static int
+read_order(const char *name, var_entry_t **order)
+{
+ int rc;
+ var_entry_t *new = NULL, *bo = NULL;
+
+ if (*order == NULL) {
+ new = calloc(1, sizeof (**order));
+ if (!new) {
+ efi_error("calloc(1, %zd) failed",
+ sizeof (**order));
+ return -1;
+ }
+ *order = bo = new;
+ } else {
+ bo = *order;
+ }
+
+ rc = efi_get_variable(EFI_GLOBAL_GUID, name,
+ &bo->data, &bo->data_size, &bo->attributes);
+ if (rc < 0 && new != NULL) {
+ efi_error("efi_get_variable failed");
+ free(new);
+ *order = NULL;
+ bo = NULL;
+ }
+
+ if (bo) {
+ /* latest apple firmware sets high bit which appears invalid
+ * to the linux kernel if we write it back so lets zero it out
+ * if it is set since it would be invalid to set it anyway */
+ bo->attributes = bo->attributes & ~(1 << 31);
+ }
+ return rc;
+}
+
+static int
+set_u16(const char *name, uint16_t num)
+{
+ return efi_set_variable(EFI_GLOBAL_GUID, name, (uint8_t *)&num,
+ sizeof (num), EFI_VARIABLE_NON_VOLATILE |
+ EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_RUNTIME_ACCESS,
+ 0644);
+}
+
+static int
+add_to_order(const char *name, uint16_t num, uint16_t insert_at)
+{
+ var_entry_t *order = NULL;
+ uint64_t new_data_size;
+ uint16_t *new_data, *old_data;
+ int rc;
+
+ rc = read_order(name, &order);
+ if (rc < 0) {
+ if (errno == ENOENT)
+ rc = set_u16(name, num);
+ return rc;
+ }
+
+ /* We've now got an array (in order->data) of the order. Copy over
+ * any entries that should precede, add our entry, and then copy the
+ * rest of the old array.
+ */
+ old_data = (uint16_t *)order->data;
+ new_data_size = order->data_size + sizeof(uint16_t);
+ new_data = malloc(new_data_size);
+ if (!new_data)
+ return -1;
+
+ if (insert_at != 0) {
+ if (insert_at > order->data_size)
+ insert_at = order->data_size;
+ memcpy(new_data, old_data, insert_at * sizeof(uint16_t));
+ }
+ new_data[insert_at] = num;
+ if (order->data_size - insert_at * sizeof(uint16_t) > 0) {
+ memcpy(new_data + insert_at + 1, old_data + insert_at,
+ order->data_size - insert_at * sizeof(uint16_t));
+ }
+
+ /* Now new_data has what we need */
+ free(order->data);
+ order->data = (uint8_t *)new_data;
+ order->data_size = new_data_size;
+
+ rc = efi_set_variable(EFI_GLOBAL_GUID, name, order->data,
+ order->data_size, order->attributes, 0644);
+ free(order->data);
+ free(order);
+ return rc;
+}
+
+static int
+remove_dupes_from_order(char *name)
+{
+ var_entry_t *order = NULL;
+ uint64_t new_data_size;
+ uint16_t *new_data, *old_data;
+ unsigned int old_i,new_i;
+ int rc;
+
+ rc = read_order(name, &order);
+ if (rc < 0) {
+ if (errno == ENOENT)
+ rc = 0;
+ return rc;
+ }
+
+ old_data = (uint16_t *)(order->data);
+ /* Start with the same size */
+ new_data_size = order->data_size;
+ new_data = malloc(new_data_size);
+ if (!new_data)
+ return -1;
+
+ unsigned int old_max = order->data_size / sizeof(*new_data);
+ for (old_i = 0, new_i = 0; old_i < old_max; old_i++) {
+ int copies = 0;
+ unsigned int j;
+ for (j = 0; j < new_i; j++) {
+ if (new_data[j] == old_data[old_i]) {
+ copies++;
+ break;
+ }
+ }
+ if (copies == 0) {
+ /* Copy this value */
+ new_data[new_i] = old_data[old_i];
+ new_i++;
+ }
+ }
+ /* Adjust the size if we didn't copy everything. */
+ new_data_size = sizeof(new_data[0]) * new_i;
+
+ /* Now new_data has what we need */
+ free(order->data);
+ order->data = (uint8_t *)new_data;
+ order->data_size = new_data_size;
+ efi_del_variable(EFI_GLOBAL_GUID, name);
+ rc = efi_set_variable(EFI_GLOBAL_GUID, name, order->data,
+ order->data_size, order->attributes,
+ 0644);
+ free(order->data);
+ free(order);
+ return rc;
+}
+
+static int
+remove_from_order(const char *name, uint16_t num)
+{
+ var_entry_t *order = NULL;
+ uint16_t *data;
+ unsigned int old_i,new_i;
+ int rc;
+
+ rc = read_order(name, &order);
+ if (rc < 0) {
+ if (errno == ENOENT)
+ rc = 0;
+ return rc;
+ }
+
+ /* We've now got an array (in order->data) of the
+ order. Squeeze out any instance of the entry we're
+ deleting by shifting the remainder down.
+ */
+ data = (uint16_t *)(order->data);
+
+ for (old_i=0,new_i=0;
+ old_i < order->data_size / sizeof(data[0]);
+ old_i++) {
+ if (data[old_i] != num) {
+ if (new_i != old_i)
+ data[new_i] = data[old_i];
+ new_i++;
+ }
+ }
+
+ /* If nothing removed, no need to update the order variable */
+ if (new_i == old_i)
+ goto all_done;
+
+ /* *Order should have nothing when new_i == 0 */
+ if (new_i == 0) {
+ efi_del_variable(EFI_GLOBAL_GUID, name);
+ goto all_done;
+ }
+
+ order->data_size = sizeof(data[0]) * new_i;
+ rc = efi_set_variable(EFI_GLOBAL_GUID, name, order->data,
+ order->data_size, order->attributes,
+ 0644);
+all_done:
+ free(order->data);
+ free(order);
+ return rc;
+}
+
+static int
+read_u16(const char *name)
+{
+ efi_guid_t guid = EFI_GLOBAL_GUID;
+ uint16_t *data = NULL;
+ size_t data_size = 0;
+ uint32_t attributes = 0;
+ int rc;
+
+ rc = efi_get_variable(guid, name, (uint8_t **)&data, &data_size,
+ &attributes);
+ if (rc < 0)
+ return rc;
+ if (data_size != 2) {
+ if (data != NULL)
+ free(data);
+ errno = EINVAL;
+ return -1;
+ }
+
+ rc = data[0];
+ free(data);
+ return rc;
+}
+
+static int
+hex_could_be_lower_case(uint16_t num)
+{
+ return ((((num & 0x000f) >> 0) > 9) ||
+ (((num & 0x00f0) >> 4) > 9) ||
+ (((num & 0x0f00) >> 8) > 9) ||
+ (((num & 0xf000) >> 12) > 9));
+}
+
+static int
+delete_var(const char *prefix, uint16_t num)
+{
+ int rc;
+ char name[16];
+ list_t *pos, *n;
+ var_entry_t *entry;
+
+ snprintf(name, sizeof(name), "%s%04X", prefix, num);
+ rc = efi_del_variable(EFI_GLOBAL_GUID, name);
+ if (rc < 0)
+ efi_error("Could not delete %s%04X", prefix, num);
+
+ /* For backwards compatibility, try to delete abcdef entries as well */
+ if (rc < 0 && errno == ENOENT && hex_could_be_lower_case(num)) {
+ snprintf(name, sizeof(name), "%s%04x", prefix, num);
+ rc = efi_del_variable(EFI_GLOBAL_GUID, name);
+ if (rc < 0 && errno != ENOENT)
+ efi_error("Could not delete %s%04x", prefix, num);
+ }
+
+ if (rc < 0)
+ return rc;
+ else
+ efi_error_clear();
+
+ snprintf(name, sizeof(name), "%sOrder", prefix);
+
+ list_for_each_safe(pos, n, &entry_list) {
+ entry = list_entry(pos, var_entry_t, list);
+ if (entry->num == num) {
+ rc = remove_from_order(name, num);
+ if (rc < 0) {
+ efi_error("remove_from_order(%s,%d) failed",
+ name, num);
+ return rc;
+ }
+ list_del(&(entry->list));
+ free(entry->name);
+ free(entry->data);
+ memset(entry, 0, sizeof(*entry));
+ free(entry);
+ break; /* short-circuit since it was found */
+ }
+ }
+ return 0;
+}
+
+static int
+delete_label(const char *prefix, const unsigned char *label)
+{
+ list_t *pos;
+ var_entry_t *boot;
+ int num_deleted = 0;
+ int rc;
+ efi_load_option *load_option;
+ const unsigned char *desc;
+
+ list_for_each(pos, &entry_list) {
+ boot = list_entry(pos, var_entry_t, list);
+ load_option = (efi_load_option *)boot->data;
+ desc = efi_loadopt_desc(load_option, boot->data_size);
+
+ if (strcmp((char *)desc, (char *)label) == 0) {
+ rc = delete_var(prefix,boot->num);
+ if (rc < 0) {
+ efi_error("Could not delete %s%04x", prefix, boot->num);
+ return rc;
+ } else {
+ num_deleted++;
+ }
+ }
+ }
+
+ if (num_deleted == 0) {
+ efi_error("Could not delete %s", label);
+ return -1;
+ }
+
+ return 0;
+}
+
+static void
+set_var_nums(const char *prefix, list_t *list)
+{
+ list_t *pos;
+ var_entry_t *var;
+ int num=0, rc;
+ char *name;
+ int warn=0;
+ size_t plen = strlen(prefix);
+ char fmt[30];
+
+ fmt[0] = '\0';
+ strcat(fmt, prefix);
+ strcat(fmt, "%04X-%*s");
+
+ list_for_each(pos, list) {
+ var = list_entry(pos, var_entry_t, list);
+ rc = sscanf(var->name, fmt, &num);
+ if (rc == 1) {
+ char *snum;
+ var->num = num;
+ name = var->name; /* shorter name */
+ snum = name + plen;
+ if ((isalpha(snum[0]) && islower(snum[0])) ||
+ (isalpha(snum[1]) && islower(snum[1])) ||
+ (isalpha(snum[2]) && islower(snum[2])) ||
+ (isalpha(snum[3]) && islower(snum[3]))) {
+ fprintf(stderr,
+ "** Warning ** : %.8s is not UEFI Spec compliant (lowercase hex in name)\n",
+ name);
+ warn++;
+ }
+ }
+ }
+ if (warn)
+ warningx("** Warning ** : please recreate these using efibootmgr to remove this warning.");
+}
+
+static void
+print_order(const char *name, uint16_t *order, int length)
+{
+ int i;
+ printf("%s: ", name);
+ for (i=0; i<length; i++) {
+ printf("%04X", order[i]);
+ if (i < (length-1))
+ printf(",");
+ }
+ printf("\n");
+}
+
+static int
+is_current_entry(int b)
+{
+ list_t *pos;
+ var_entry_t *entry;
+
+ list_for_each(pos, &entry_list) {
+ entry = list_entry(pos, var_entry_t, list);
+ if (entry->num == b)
+ return 1;
+ }
+ return 0;
+}
+
+static void
+print_error_arrow(char *buffer, off_t offset, char *fmt, ...)
+{
+ va_list ap;
+ size_t size;
+ unsigned int i;
+
+ va_start(ap, fmt);
+ size = vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ fprintf(stderr, "%s\n", buffer);
+
+ for (i = 0; i < size + 2; i++)
+ fprintf(stderr, " ");
+ for (i = 0; i < offset; i++)
+ fprintf(stderr, " ");
+ fprintf(stderr, "^\n");
+}
+
+static int
+parse_order(const char *prefix, char *buffer, uint16_t **order, size_t *length)
+{
+ uint16_t *data;
+ size_t data_size;
+ size_t len = strlen(buffer);
+ intptr_t end = (intptr_t)buffer + len + 1;
+
+ int num = 0;
+ char *buf = buffer;
+ while ((intptr_t)buf < end) {
+ size_t comma = strcspn(buf, ",");
+ if (comma == 0) {
+ off_t offset = (intptr_t)buf - (intptr_t)buffer;
+ print_error_arrow(buffer, offset, "Malformed %s order",
+ prefix);
+ exit(8);
+ } else {
+ num++;
+ }
+ buf += comma + 1;
+ }
+
+ if (num == 0) {
+ *order = NULL;
+ *length = 0;
+ return 0;
+ }
+
+ data = calloc(num, sizeof (*data));
+ if (!data)
+ return -1;
+ data_size = num * sizeof (*data);
+
+ int i = 0;
+ buf = buffer;
+ while ((intptr_t)buf < end) {
+ unsigned long result = 0;
+ size_t comma = strcspn(buf, ",");
+
+ buf[comma] = '\0';
+ char *endptr = NULL;
+ result = strtoul(buf, &endptr, 16);
+ if ((result == ULONG_MAX && errno == ERANGE) ||
+ (endptr && *endptr != '\0')) {
+ off_t offset = (intptr_t)endptr - (intptr_t)buffer;
+ print_error_arrow(buffer, offset, "Invalid %s order",
+ prefix);
+ free(data);
+ exit(8);
+ }
+ if (result > 0xffff) {
+ off_t offset = (intptr_t)buf - (intptr_t)buffer;
+ warnx("Invalid %s order entry value: %lX", prefix,
+ result);
+ print_error_arrow(buffer, offset, "Invalid %s order",
+ prefix);
+ free(data);
+ exit(8);
+ }
+
+ /* make sure this is an existing entry */
+ if (!is_current_entry(result)) {
+ off_t offset = (intptr_t)buf - (intptr_t)buffer;
+ print_error_arrow(buffer, offset,
+ "Invalid %s order entry value",
+ prefix);
+ warnx("entry %04lX does not exist", result);
+ free(data);
+ exit(8);
+ }
+
+ data[i++] = result;
+ buf[comma] = ',';
+ buf += comma + 1;
+ }
+
+ *order = data;
+ *length = data_size;
+ return num;
+}
+
+static int
+construct_order(const char *name, char *order, int keep,
+ uint16_t **ret_data, size_t *ret_data_size)
+{
+ var_entry_t bo;
+ int rc;
+ uint16_t *data = NULL;
+ size_t data_size = 0;
+
+ rc = parse_order(name, order, (uint16_t **)&data, &data_size);
+ if (rc < 0 || data_size == 0) {
+ if (data) /* this can't actually happen, but covscan believes */
+ free(data);
+ return rc;
+ }
+
+ if (!keep) {
+ *ret_data = data;
+ *ret_data_size = data_size;
+ return 0;
+ }
+
+ rc = efi_get_variable(EFI_GLOBAL_GUID, name,
+ &bo.data, &bo.data_size, &bo.attributes);
+ if (rc < 0) {
+ *ret_data = data;
+ *ret_data_size = data_size;
+ return 0;
+ }
+
+ /* latest apple firmware sets high bit which appears invalid
+ * to the linux kernel if we write it back so lets zero it out
+ * if it is set since it would be invalid to set it anyway */
+ bo.attributes = bo.attributes & ~(1 << 31);
+
+ size_t new_data_size = data_size + bo.data_size;
+ uint16_t *new_data = calloc(1, new_data_size);
+ if (!new_data) {
+ if (data)
+ free(data);
+ return -1;
+ }
+
+ memcpy(new_data, data, data_size);
+ memcpy(new_data + (data_size / sizeof (*new_data)), bo.data,
+ bo.data_size);
+
+ free(bo.data);
+ free(data);
+
+ int new_data_start = data_size / sizeof (uint16_t);
+ int new_data_end = new_data_size / sizeof (uint16_t);
+ int i;
+ for (i = 0; i < new_data_start; i++) {
+ int j;
+ for (j = new_data_start; j < new_data_end; j++) {
+ if (new_data[i] == new_data[j]) {
+ memcpy(new_data + j, new_data + j + 1,
+ sizeof (uint16_t) * (new_data_end-j+1));
+ new_data_end -= 1;
+ break;
+ }
+ }
+ }
+ *ret_data = new_data;
+ *ret_data_size = new_data_end * sizeof (uint16_t);
+ return 0;
+}
+
+static int
+set_order(const char *order_name, const char *prefix, int keep_old_entries)
+{
+ uint8_t *data = NULL;
+ size_t data_size = 0;
+ char *name;
+ int rc;
+
+ if (!opts.order)
+ return 0;
+
+ rc = construct_order(order_name, opts.order, keep_old_entries,
+ (uint16_t **)&data, &data_size);
+ if (rc < 0 || data_size == 0) {
+ if (data) /* this can't happen, but clang analyzer believes */
+ free(data);
+ return rc;
+ }
+
+ rc = asprintf(&name, "%sOrder", prefix);
+ if (rc < 0)
+ goto err;
+
+ rc = efi_set_variable(EFI_GLOBAL_GUID, name, data, data_size,
+ EFI_VARIABLE_NON_VOLATILE |
+ EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_RUNTIME_ACCESS,
+ 0644);
+ free(name);
+err:
+ free(data);
+ return rc;
+}
+
+#define ev_bits(val, mask, shift) \
+ (((val) & ((mask) << (shift))) >> (shift))
+
+static inline char *
+ucs2_to_utf8(const uint16_t * const chars, ssize_t limit)
+{
+ ssize_t i, j;
+ char *ret;
+
+ ret = alloca(limit * 6 + 1);
+ if (!ret)
+ return NULL;
+ memset(ret, 0, limit * 6 +1);
+
+ for (i=0, j=0; i < (limit >= 0 ? limit : i+1) && chars[i]; i++,j++) {
+ if (chars[i] <= 0x7f) {
+ ret[j] = chars[i];
+ } else if (chars[i] > 0x7f && chars[i] <= 0x7ff) {
+ ret[j++] = 0xc0 | ev_bits(chars[i], 0x1f, 6);
+ ret[j] = 0x80 | ev_bits(chars[i], 0x3f, 0);
+ } else if (chars[i] > 0x7ff) {
+ ret[j++] = 0xe0 | ev_bits(chars[i], 0xf, 12);
+ ret[j++] = 0x80 | ev_bits(chars[i], 0x3f, 6);
+ ret[j] = 0x80| ev_bits(chars[i], 0x3f, 0);
+ }
+ }
+ ret[j] = '\0';
+ return strdup(ret);
+}
+
+static void
+show_var_path(efi_load_option *load_option, size_t boot_data_size)
+{
+ char *text_path = NULL;
+ size_t text_path_len = 0;
+ uint16_t pathlen;
+ ssize_t rc;
+ efidp dp = NULL;
+ unsigned char *optional_data = NULL;
+ size_t optional_data_len=0;
+ bool is_shim = false;
+ const char * const shim_path_segments[] = {
+ "/File(\\EFI\\", "\\shim", ".efi)", NULL
+ };
+
+ pathlen = efi_loadopt_pathlen(load_option,
+ boot_data_size);
+ dp = efi_loadopt_path(load_option, boot_data_size);
+ rc = efidp_format_device_path((unsigned char *)text_path,
+ text_path_len, dp, pathlen);
+ if (rc < 0) {
+ warning("Could not parse device path");
+ return;
+ }
+ rc += 1;
+
+ text_path_len = rc;
+ text_path = calloc(1, rc);
+ if (!text_path) {
+ warning("Could not parse device path");
+ return;
+ }
+
+ rc = efidp_format_device_path((unsigned char *)text_path,
+ text_path_len, dp, pathlen);
+ if (rc >= 0) {
+ printf("\t%s", text_path);
+
+ char *a = text_path;
+ for (int i = 0; a && shim_path_segments[i] != NULL; i++) {
+ a = strstr(a, shim_path_segments[i]);
+ if (a)
+ a += strlen(shim_path_segments[i]);
+ }
+ if (a && a[0] == '\0')
+ is_shim = true;
+ }
+
+ free(text_path);
+ if (rc < 0) {
+ warning("Could not parse device path");
+ return;
+ }
+
+ /* Print optional data */
+ rc = efi_loadopt_optional_data(load_option, boot_data_size,
+ &optional_data, &optional_data_len);
+ if (rc < 0) {
+ warning("Could not parse optional data");
+ return;
+ }
+
+ typedef ssize_t (*parser_t)(char *buffer, size_t buffer_size,
+ uint8_t *p, uint64_t length);
+ parser_t parser = NULL;
+ if (is_shim && optional_data_len) {
+ char *a = ucs2_to_utf8((uint16_t*)optional_data,
+ optional_data_len/2);
+ if (!a) {
+ warning("Could not parse optional data");
+ return;
+ }
+ text_path = calloc(1, sizeof(" File(.")
+ + strlen(a)
+ + strlen(")"));
+ if (!text_path) {
+ free(a);
+ warning("Could not parse optional data");
+ return;
+ }
+ char *b;
+
+ b = stpcpy(text_path, " File(.");
+ b = stpcpy(b, a);
+ stpcpy(b, ")");
+ free(a);
+ } else if (opts.unicode) {
+ text_path = ucs2_to_utf8((uint16_t*)optional_data,
+ optional_data_len/2);
+ if (!text_path) {
+ warning("Could not parse optional data");
+ return;
+ }
+ } else if (optional_data_len == sizeof(efi_guid_t)) {
+ parser = parse_efi_guid;
+ } else {
+ parser = parse_raw_text;
+ }
+
+ if (parser) {
+ rc = parser(NULL, 0, optional_data, optional_data_len);
+ if (rc < 0) {
+ warning("Could not parse optional data");
+ return;
+ }
+ rc += 1;
+ text_path_len = rc;
+ text_path = calloc(1, rc);
+ if (!text_path) {
+ warning("Could not parse optional data");
+ return;
+ }
+ rc = parser(text_path, text_path_len,
+ optional_data, optional_data_len);
+ if (rc < 0) {
+ warning("Could not parse device path");
+ free(text_path);
+ return;
+ }
+ }
+ printf("%s", text_path);
+ free(text_path);
+ printf("\n");
+
+ const_efidp node = dp;
+ if (opts.verbose >= 1)
+ printf(" dp: ");
+ for (rc = 1; opts.verbose >= 1 && rc > 0; ) {
+ ssize_t sz;
+ const_efidp next = NULL;
+ const uint8_t * const data = (const uint8_t * const)node;
+
+ rc = efidp_next_node(node, &next);
+ if (rc < 0) {
+ warning("Could not iterate device path");
+ return;
+ }
+
+ sz = efidp_node_size(node);
+ if (sz <= 0) {
+ warning("Could not iterate device path");
+ return;
+ }
+
+ for (ssize_t j = 0; j < sz; j++)
+ printf("%02hhx%s", data[j], j == sz - 1 ? "" : " ");
+ printf("%s", rc == 0 ? "\n" : " / ");
+
+ node = next;
+ }
+ if (opts.verbose >= 1 && optional_data_len)
+ printf(" data: ");
+ for (unsigned int j = 0; opts.verbose >= 1 && j < optional_data_len; j++)
+ printf("%02hhx%s", optional_data[j], j == optional_data_len - 1 ? "\n" : " ");
+}
+
+static void
+show_vars(const char *prefix)
+{
+ list_t *pos;
+ var_entry_t *boot;
+ const unsigned char *description;
+ efi_load_option *load_option;
+
+ list_for_each(pos, &entry_list) {
+ boot = list_entry(pos, var_entry_t, list);
+ load_option = (efi_load_option *)boot->data;
+ description = efi_loadopt_desc(load_option, boot->data_size);
+ if (boot->name)
+ printf("%s", boot->name);
+ else
+ printf("%s%04X", prefix, boot->num);
+
+ printf("%c ", (efi_loadopt_attrs(load_option)
+ & LOAD_OPTION_ACTIVE) ? '*' : ' ');
+ printf("%s", description);
+
+ show_var_path(load_option, boot->data_size);
+
+ fflush(stdout);
+ }
+}
+
+static void
+show_order(const char *name)
+{
+ int rc;
+ var_entry_t *order = NULL;
+ uint16_t *data;
+
+ rc = read_order(name, &order);
+ cond_warning(opts.verbose >= 2 && rc < 0,
+ "Could not read variable '%s'", name);
+
+ if (rc < 0) {
+ if (errno == ENOENT) {
+ if (!strcmp(name, "BootOrder"))
+ printf("No BootOrder is set; firmware will attempt recovery\n");
+ else
+ printf("No %s is set\n", name);
+ } else
+ perror("show_order()");
+ return;
+ }
+
+ /* We've now got an array (in order->data) of the order. First add
+ * our entry, then copy the old array.
+ */
+ data = (uint16_t *)order->data;
+ if (order->data_size) {
+ print_order(name, data,
+ order->data_size / sizeof(uint16_t));
+ free(order->data);
+ }
+ free(order);
+}
+
+static var_entry_t *
+get_entry(list_t *entries, uint16_t num)
+{
+ list_t *pos;
+ var_entry_t *entry = NULL;
+
+ list_for_each(pos, entries) {
+ entry = list_entry(pos, var_entry_t, list);
+ if (entry->num != num) {
+ entry = NULL;
+ continue;
+ }
+ }
+
+ return entry;
+}
+
+static int
+update_entry_attr(var_entry_t *entry, uint64_t attr, bool set)
+{
+ efi_load_option *load_option;
+ uint64_t attrs;
+ int rc;
+
+ load_option = (efi_load_option *)entry->data;
+ attrs = efi_loadopt_attrs(load_option);
+
+ if ((set && (attrs & attr)) || (!set && !(attrs & attr)))
+ return 0;
+
+ if (set)
+ efi_loadopt_attr_set(load_option, attr);
+ else
+ efi_loadopt_attr_clear(load_option, attr);
+
+ rc = efi_set_variable(entry->guid, entry->name,
+ entry->data, entry->data_size,
+ entry->attributes, 0644);
+ if (rc < 0) {
+ char *guid = NULL;
+ int err = errno;
+
+ efi_guid_to_str(&entry->guid, &guid);
+ errno = err;
+ efi_error("efi_set_variable(%s,%s,...)",
+ guid, entry->name);
+ }
+
+ return rc;
+}
+
+static int
+set_active_state(const char *prefix)
+{
+ var_entry_t *entry;
+
+ entry = get_entry(&entry_list, opts.num);
+ if (!entry) {
+ /* if we reach here then the number supplied was not found */
+ warnx("%s entry %x not found", prefix, opts.num);
+ errno = ENOENT;
+ return -1;
+ }
+
+ return update_entry_attr(entry, LOAD_OPTION_ACTIVE, opts.active);
+}
+
+static int
+set_force_reconnect(const char *prefix)
+{
+ var_entry_t *entry;
+
+ entry = get_entry(&entry_list, opts.num);
+ if (!entry) {
+ /* if we reach here then the number supplied was not found */
+ warnx("%s entry %x not found", prefix, opts.num);
+ errno = ENOENT;
+ return -1;
+ }
+
+ return update_entry_attr(entry, LOAD_OPTION_FORCE_RECONNECT,
+ opts.reconnect > 0);
+}
+
+static int
+get_mirror(int which, int *below4g, int *above4g, int *mirrorstatus)
+{
+ int rc;
+ uint8_t *data;
+ ADDRESS_RANGE_MIRROR_VARIABLE_DATA *abm;
+ size_t data_size;
+ uint32_t attributes;
+ char *name;
+
+ if (which)
+ name = ADDRESS_RANGE_MIRROR_VARIABLE_REQUEST;
+ else
+ name = ADDRESS_RANGE_MIRROR_VARIABLE_CURRENT;
+
+ rc = efi_get_variable(ADDRESS_RANGE_MIRROR_VARIABLE_GUID, name,
+ &data, &data_size, &attributes);
+ if (rc == 0) {
+ abm = (ADDRESS_RANGE_MIRROR_VARIABLE_DATA *)data;
+ if (!which && abm->mirror_version != MIRROR_VERSION) {
+ rc = 2;
+ }
+ *below4g = abm->mirror_memory_below_4gb;
+ *above4g = abm->mirror_amount_above_4gb;
+ *mirrorstatus = abm->mirror_status;
+ free(data);
+ } else {
+ cond_warning(opts.verbose >= 2,
+ "Could not read variable '%s'", name);
+ errno = 0;
+ }
+ return rc;
+}
+
+static int
+set_mirror(int below4g, int above4g)
+{
+ int s, status, rc;
+ uint8_t *data;
+ ADDRESS_RANGE_MIRROR_VARIABLE_DATA abm;
+ size_t data_size;
+ uint32_t attributes;
+ int oldbelow4g, oldabove4g;
+
+ if ((s = get_mirror(0, &oldbelow4g, &oldabove4g, &status)) != 0) {
+ if (s == 2)
+ warningx("** Warning ** : unrecognised version for memory mirror i/f");
+ else
+ warningx("** Warning ** : platform does not support memory mirror");
+ return s;
+ }
+
+ below4g = opts.set_mirror_lo ? below4g : oldbelow4g;
+ above4g = opts.set_mirror_hi ? above4g : oldabove4g;
+ if (oldbelow4g == below4g && oldabove4g == above4g)
+ return 0;
+
+ data = (uint8_t *)&abm;
+ data_size = sizeof (abm);
+ attributes = EFI_VARIABLE_NON_VOLATILE
+ | EFI_VARIABLE_BOOTSERVICE_ACCESS
+ | EFI_VARIABLE_RUNTIME_ACCESS;
+
+ abm.mirror_version = MIRROR_VERSION;
+ abm.mirror_amount_above_4gb = above4g;
+ abm.mirror_memory_below_4gb = below4g;
+ abm.mirror_status = 0;
+ rc = efi_set_variable(ADDRESS_RANGE_MIRROR_VARIABLE_GUID,
+ ADDRESS_RANGE_MIRROR_VARIABLE_REQUEST, data,
+ data_size, attributes, 0644);
+ if (rc < 0)
+ efi_error("efi_set_variable() failed");
+ return rc;
+}
+
+static void
+show_mirror(void)
+{
+ int status;
+ int below4g = 0, above4g = 0;
+ int rbelow4g = 0, rabove4g = 0;
+
+ if (get_mirror(0, &below4g, &above4g, &status) == 0) {
+ if (status == 0) {
+ printf("MirroredPercentageAbove4G: %d.%.2d\n",
+ above4g/100, above4g%100);
+ printf("MirrorMemoryBelow4GB: %s\n",
+ below4g ? "true" : "false");
+ } else {
+ printf("MirrorStatus: ");
+ switch (status) {
+ case 1:
+ printf("Platform does not support address range mirror\n");
+ break;
+ case 2:
+ printf("Invalid version number\n");
+ break;
+ case 3:
+ printf("MirroredMemoryAbove4GB > 50.00%%\n");
+ break;
+ case 4:
+ printf("DIMM configuration does not allow mirror\n");
+ break;
+ case 5:
+ printf("OEM specific method\n");
+ break;
+ default:
+ printf("%u\n", status);
+ break;
+ }
+ printf("DesiredMirroredPercentageAbove4G: %d.%.2d\n",
+ above4g/100, above4g%100);
+ printf("DesiredMirrorMemoryBelow4GB: %s\n",
+ below4g ? "true" : "false");
+ }
+ }
+ if ((get_mirror(1, &rbelow4g, &rabove4g, &status) == 0) &&
+ (above4g != rabove4g || below4g != rbelow4g)) {
+ printf("RequestMirroredPercentageAbove4G: %d.%.2d\n",
+ rabove4g/100, rabove4g%100);
+ printf("RequestMirrorMemoryBelow4GB: %s\n",
+ rbelow4g ? "true" : "false");
+ }
+}
+
+static void
+usage()
+{
+ printf("efibootmgr version %s\n", EFIBOOTMGR_VERSION);
+ printf("usage: efibootmgr [options]\n");
+ printf("\t-a | --active Set bootnum active.\n");
+ printf("\t-A | --inactive Set bootnum inactive.\n");
+ printf("\t-b | --bootnum XXXX Modify BootXXXX (hex).\n");
+ printf("\t-B | --delete-bootnum Delete bootnum.\n");
+ printf("\t-c | --create Create new variable bootnum and add to bootorder at index (-I).\n");
+ printf("\t-C | --create-only Create new variable bootnum and do not add to bootorder.\n");
+ printf("\t-d | --disk disk Disk containing boot loader (defaults to /dev/sda).\n");
+ printf("\t-D | --remove-dups Remove duplicate values from BootOrder.\n");
+ printf("\t-e | --edd [1|3] Force boot entries to be created using EDD 1.0 or 3.0 info.\n");
+ printf("\t-E | --device num EDD 1.0 device number (defaults to 0x80).\n");
+ printf("\t --full-dev-path Use a full device path.\n");
+ printf("\t --file-dev-path Use an abbreviated File() device path.\n");
+ printf("\t-f | --reconnect Re-connect devices after driver is loaded.\n");
+ printf("\t-F | --no-reconnect Do not re-connect devices after driver is loaded.\n");
+ printf("\t-g | --gpt Force disk with invalid PMBR to be treated as GPT.\n");
+ printf("\t-i | --iface name Create a netboot entry for the named interface.\n");
+ printf("\t-I | --index number When creating an entry, insert it in bootorder at specified position (default: 0).\n");
+ printf("\t-l | --loader name (Defaults to \""DEFAULT_LOADER"\").\n");
+ printf("\t-L | --label label Boot manager display label (defaults to \"Linux\").\n");
+ printf("\t-m | --mirror-below-4G t|f Mirror memory below 4GB.\n");
+ printf("\t-M | --mirror-above-4G X Percentage memory to mirror above 4GB.\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 Partition containing loader (defaults to 1 on partitioned devices).\n");
+ printf("\t-q | --quiet Be quiet.\n");
+ printf("\t-r | --driver Operate on Driver variables, not Boot Variables.\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 Handle extra args as UCS-2 (default is ASCII).\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");
+ printf("\t-y | --sysprep Operate on SysPrep variables, not Boot Variables.\n");
+ printf("\t-@ | --append-binary-args file Append extra args from file (use \"-\" for stdin).\n");
+ printf("\t-h | --help Show help/usage.\n");
+}
+
+static void
+set_default_opts()
+{
+ memset(&opts, 0, sizeof(opts));
+ opts.num = -1; /* auto-detect */
+ opts.bootnext = -1; /* Don't set it */
+ opts.active = -1; /* Don't set it */
+ opts.reconnect = -1; /* Don't set it */
+ opts.timeout = -1; /* Don't set it */
+ opts.edd10_devicenum = 0x80;
+ opts.loader = DEFAULT_LOADER;
+ opts.label = (unsigned char *)"Linux";
+ opts.disk = "/dev/sda";
+ opts.part = -1;
+}
+
+static void
+parse_opts(int argc, char **argv)
+{
+ int c, rc;
+ unsigned int num;
+ int snum;
+ float fnum;
+ int option_index = 0;
+ long lindex;
+
+ 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'},
+ {"create-only", no_argument, 0, 'C'},
+ {"disk", required_argument, 0, 'd'},
+ {"remove-dups", no_argument, 0, 'D'},
+ {"edd", required_argument, 0, 'e'},
+ {"edd30", required_argument, 0, 'e'},
+ {"edd-device", required_argument, 0, 'E'},
+ {"full-dev-path", no_argument, 0, 0},
+ {"file-dev-path", no_argument, 0, 0},
+ {"reconnect", no_argument, 0, 'f'},
+ {"no-reconnect", no_argument, 0, 'F'},
+ {"gpt", no_argument, 0, 'g'},
+ {"iface", required_argument, 0, 'i'},
+ {"index", required_argument, 0, 'I'},
+ {"keep", no_argument, 0, 'k'},
+ {"loader", required_argument, 0, 'l'},
+ {"label", required_argument, 0, 'L'},
+ {"mirror-below-4G", required_argument, 0, 'm'},
+ {"mirror-above-4G", required_argument, 0, 'M'},
+ {"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'},
+ {"driver", no_argument, 0, 'r'},
+ {"timeout", required_argument, 0, 't'},
+ {"delete-timeout", no_argument, 0, 'T'},
+ {"unicode", no_argument, 0, 'u'},
+ {"UCS-2", no_argument, 0, 'u'},
+ {"verbose", optional_argument, 0, 'v'},
+ {"version", no_argument, 0, 'V'},
+ {"write-signature", no_argument, 0, 'w'},
+ {"sysprep", no_argument, 0, 'y'},
+ {"append-binary-args", required_argument, 0, '@'},
+ {"help", no_argument, 0, 'h'},
+ {0, 0, 0, 0}
+ };
+
+ c = getopt_long(argc, argv,
+ "aAb:BcCd:De:E:fFgi:kl:L:m:M:n:No:Op:qrt:Tuv::Vwy@:h",
+ long_options, &option_index);
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case '@':
+ opts.extra_opts_file = optarg;
+ break;
+ case 'a':
+ opts.active = 1;
+ break;
+ case 'A':
+ opts.active = 0;
+ break;
+ case 'B':
+ opts.delete = 1;
+ break;
+ case 'b': {
+ char *endptr = NULL;
+ unsigned long result;
+
+ if (!optarg) {
+ errorx(29, "--%s requires an argument",
+ long_options[option_index]);
+ break;
+ }
+
+ result = strtoul(optarg, &endptr, 16);
+ if ((result == ULONG_MAX && errno == ERANGE) ||
+ (endptr && *endptr != '\0')) {
+ off_t offset = (intptr_t)endptr
+ - (intptr_t)optarg;
+ print_error_arrow(optarg, offset,
+ "Invalid bootnum value");
+ conditional_error_reporter(opts.verbose >= 1,
+ 1);
+ exit(28);
+ }
+ if (result > 0xffff)
+ errorx(29, "Invalid bootnum value: %lX\n",
+ result);
+
+ opts.num = result;
+ break;
+ }
+ case 'c':
+ opts.create = 1;
+ break;
+ case 'C':
+ opts.create = 1;
+ opts.no_order = 1;
+ break;
+ case 'D':
+ opts.deduplicate = 1;
+ break;
+ case 'd':
+ opts.disk = optarg;
+ break;
+ case 'e':
+ rc = sscanf(optarg, "%d", &snum);
+ if (rc != 1)
+ errorx(30, "invalid numeric value %s\n",
+ optarg);
+
+ if (snum != EFIBOOTMGR_PATH_ABBREV_EDD10 &&
+ snum != EFIBOOTMGR_PATH_ABBREV_NONE)
+ errorx(31, "invalid EDD version %d\n", snum);
+
+ if (opts.abbreviate_path != EFIBOOTMGR_PATH_ABBREV_UNSPECIFIED &&
+ opts.abbreviate_path != snum)
+ errx(41, "contradicting --full-device-path/--file-device-path/-e options");
+
+ opts.abbreviate_path = snum;
+ break;
+ case 'E':
+ rc = sscanf(optarg, "%x", &num);
+ if (rc == 1)
+ opts.edd10_devicenum = num;
+ else
+ errorx(32, "invalid hex value %s\n", optarg);
+ break;
+ case 'f':
+ opts.reconnect = 1;
+ break;
+ case 'F':
+ opts.reconnect = 0;
+ break;
+ case 'g':
+ opts.forcegpt = 1;
+ break;
+
+ case 'h':
+ usage();
+ exit(0);
+ break;
+
+ case 'i':
+ opts.iface = optarg;
+ opts.ip_version = EFIBOOTMGR_IPV4;
+ opts.ip_addr_origin = EFIBOOTMGR_IPV4_ORIGIN_DHCP;
+ break;
+ case 'I':
+ if (!optarg) {
+ errorx(1, "--%s requires an argument",
+ long_options[option_index]);
+ }
+ lindex = atol(optarg);
+ if (lindex < 0 || lindex > UINT16_MAX) {
+ errorx(1, "invalid numeric value %s\n",
+ optarg);
+ }
+ opts.index = (uint16_t)lindex;
+ break;
+ case 'k':
+ opts.keep_old_entries = 1;
+ break;
+ case 'l':
+ opts.loader = optarg;
+ break;
+ case 'L':
+ opts.label = (unsigned char *)optarg;
+ opts.explicit_label = 1;
+ break;
+ case 'm':
+
+ if (!optarg) {
+ errorx(33, "--%s requires an argument",
+ long_options[option_index]);
+ break;
+ }
+
+ opts.set_mirror_lo = 1;
+
+ switch (optarg[0]) {
+ case '1': case 'y': case 't':
+ opts.below4g = 1;
+ break;
+ case '0': case 'n': case 'f':
+ opts.below4g = 0;
+ break;
+ default:
+ errorx(33, "invalid boolean value %s\n",
+ optarg);
+ }
+ break;
+ case 'M':
+ opts.set_mirror_hi = 1;
+ rc = sscanf(optarg, "%f", &fnum);
+ if (rc == 1 && fnum <= 50 && fnum >= 0)
+ /* percent to basis points */
+ opts.above4g = fnum * 100;
+ else
+ errorx(34, "invalid numeric value %s\n",
+ optarg);
+ break;
+ case 'N':
+ opts.delete_bootnext = 1;
+ break;
+ case 'n': {
+ char *endptr = NULL;
+ unsigned long result;
+
+ if (!optarg) {
+ errorx(36, "--%s requires an argument",
+ long_options[option_index]);
+ break;
+ }
+
+ result = strtoul(optarg, &endptr, 16);
+ if ((result == ULONG_MAX && errno == ERANGE) ||
+ (endptr && *endptr != '\0')) {
+ off_t offset = (intptr_t)endptr
+ - (intptr_t)optarg;
+ print_error_arrow(optarg, offset,
+ "Invalid BootNext value");
+ conditional_error_reporter(opts.verbose >= 1,
+ 1);
+ exit(35);
+ }
+ if (result > 0xffff)
+ errorx(36, "Invalid BootNext value: %lX\n",
+ result);
+ opts.bootnext = result;
+ break;
+ }
+ case 'o':
+ opts.order = optarg;
+ break;
+ case 'O':
+ opts.delete_order = 1;
+ break;
+ case 'p':
+ rc = sscanf(optarg, "%u", &num);
+ if (rc == 1)
+ opts.part = num;
+ else
+ errorx(37, "invalid numeric value %s\n",
+ optarg);
+ break;
+ case 'q':
+ opts.quiet = 1;
+ break;
+ case 'r':
+ opts.driver = 1;
+ break;
+ case 't':
+ rc = sscanf(optarg, "%u", &num);
+ if (rc == 1) {
+ opts.timeout = num;
+ opts.set_timeout = 1;
+ } else {
+ errorx(38, "invalid numeric value %s\n",
+ optarg);
+ }
+ break;
+ case 'T':
+ opts.delete_timeout = 1;
+ break;
+ case 'u':
+ opts.unicode = 1;
+ break;
+ case 'v':
+ opts.verbose += 1;
+ if (optarg) {
+ if (!strcmp(optarg, "v"))
+ opts.verbose = 1;
+ if (!strcmp(optarg, "vv"))
+ opts.verbose = 2;
+ rc = sscanf(optarg, "%u", &num);
+ if (rc == 1)
+ opts.verbose = num;
+ else
+ errorx(39,
+ "invalid numeric value %s\n",
+ optarg);
+ }
+ efi_set_verbose(opts.verbose - 1, stderr);
+ break;
+ case 'V':
+ opts.showversion = 1;
+ break;
+
+ case 'w':
+ opts.write_signature = 1;
+ break;
+
+ case 'y':
+ opts.sysprep = 1;
+ break;
+
+ default:
+ if (!strcmp(long_options[option_index].name, "full-dev-path")) {
+ if (opts.abbreviate_path != EFIBOOTMGR_PATH_ABBREV_UNSPECIFIED &&
+ opts.abbreviate_path != EFIBOOTMGR_PATH_ABBREV_NONE)
+ errx(41, "contradicting --full-dev-path/--file-dev-path/-e options");
+ opts.abbreviate_path = EFIBOOTMGR_PATH_ABBREV_NONE;
+ } else if (!strcmp(long_options[option_index].name, "file-dev-path")) {
+ if (opts.abbreviate_path != EFIBOOTMGR_PATH_ABBREV_UNSPECIFIED &&
+ opts.abbreviate_path != EFIBOOTMGR_PATH_ABBREV_FILE)
+ errx(41, "contradicting --full-dev-path/--file-dev-path/-e options");
+ opts.abbreviate_path = EFIBOOTMGR_PATH_ABBREV_FILE;
+ } else {
+ usage();
+ exit(1);
+ }
+ }
+ }
+
+ if (optind < argc) {
+ opts.argc = argc;
+ opts.argv = argv;
+ opts.optind = optind;
+ }
+}
+
+int
+main(int argc, char **argv)
+{
+ char **names = NULL;
+ var_entry_t *new_entry = NULL;
+ int num;
+ int ret = 0;
+ ebm_mode mode = boot;
+ char *prefices[] = {
+ "Boot",
+ "Driver",
+ "SysPrep",
+ };
+ char *order_name[] = {
+ "BootOrder",
+ "DriverOrder",
+ "SysPrepOrder"
+ };
+
+ set_default_opts();
+ parse_opts(argc, argv);
+ if (opts.showversion) {
+ printf("version %s\n", EFIBOOTMGR_VERSION);
+ return 0;
+ }
+
+ verbose = opts.verbose;
+
+ if (opts.sysprep && opts.driver)
+ errx(25, "--sysprep and --driver may not be used together.");
+
+ if (opts.sysprep || opts.driver) {
+ if (opts.bootnext >= 0 || opts.delete_bootnext)
+ errx(26, "%s mode does not support BootNext options.",
+ opts.sysprep ? "--sysprep": "--driver");
+
+ if (opts.timeout >= 0 || opts.delete_timeout)
+ errx(27, "%s mode does not support timeout options.",
+ opts.sysprep ? "--sysprep": "--driver");
+
+ if (opts.sysprep)
+ mode = sysprep;
+
+ if (opts.driver)
+ mode = driver;
+ }
+
+ if (!efi_variables_supported())
+ errorx(2, "EFI variables are not supported on this system.");
+
+
+ read_var_names(prefices[mode], &names);
+ read_vars(names, &entry_list);
+ set_var_nums(prefices[mode], &entry_list);
+
+ if (opts.delete) {
+ if (opts.num == -1 && opts.explicit_label == 0) {
+ errorx(3,
+ "You must specify an entry to delete (see the -b option or -L option).");
+ } else {
+ if (opts.num != -1) {
+ ret = delete_var(prefices[mode], opts.num);
+ if (ret < 0)
+ error(15, "Could not delete variable");
+ } else {
+ ret = delete_label(prefices[mode], opts.label);
+ if (ret < 0)
+ errorx(15, "Could not delete variable");
+ }
+ }
+ }
+
+ if (opts.active >= 0) {
+ if (opts.num == -1) {
+ errorx(4,
+ "You must specify a entry to activate (see the -b option)");
+ } else {
+ ret = set_active_state(prefices[mode]);
+ if (ret < 0)
+ error(16,
+ "Could not set active state for %s%04X",
+ prefices[mode], opts.num);
+ }
+ }
+
+ if (opts.reconnect >= 0) {
+ if (opts.num == -1) {
+ errorx(4,
+ "You must specify a driver entry to set re-connect on (see the -b option)");
+ } else {
+ ret = set_force_reconnect(prefices[mode]);
+ if (ret < 0)
+ error(16,
+ "Could not set re-connect for %s%04X",
+ prefices[mode], opts.num);
+ }
+ }
+
+ if (opts.create) {
+ warn_duplicate_name(&entry_list);
+ new_entry = make_var(prefices[mode], &entry_list);
+ if (!new_entry)
+ error(5, "Could not prepare %s variable",
+ prefices[mode]);
+
+ /* Put this boot var in the right Order variable */
+ if (new_entry && !opts.no_order) {
+ ret = add_to_order(order_name[mode], new_entry->num,
+ opts.index);
+ if (ret < 0)
+ error(6, "Could not add entry to %s",
+ order_name[mode]);
+ }
+ } else if (opts.index) {
+ error(1, "Index is meaningless without create");
+ }
+
+ if (opts.delete_order) {
+ ret = efi_del_variable(EFI_GLOBAL_GUID, order_name[mode]);
+ if (ret < 0 && errno != ENOENT)
+ error(7, "Could not remove entry from %s",
+ order_name[mode]);
+ }
+
+ if (opts.order) {
+ ret = set_order(order_name[mode], prefices[mode],
+ opts.keep_old_entries);
+ if (ret < 0)
+ error(8, "Could not set %s", order_name[mode]);
+ }
+
+ if (opts.deduplicate) {
+ ret = remove_dupes_from_order(order_name[mode]);
+ if (ret)
+ error(9, "Could not remove duplicates from %s order",
+ order_name[mode]);
+ }
+
+ if (opts.delete_bootnext) {
+ if (!is_current_entry(opts.delete_bootnext))
+ errorx(17, "Boot entry %04X does not exist",
+ opts.delete_bootnext);
+
+ ret = efi_del_variable(EFI_GLOBAL_GUID, "BootNext");
+ if (ret < 0)
+ error(10, "Could not delete BootNext");
+ }
+
+ if (opts.delete_timeout) {
+ ret = efi_del_variable(EFI_GLOBAL_GUID, "Timeout");
+ if (ret < 0)
+ error(11, "Could not delete Timeout");
+ }
+
+ if (opts.bootnext >= 0) {
+ if (!is_current_entry(opts.bootnext & 0xFFFF))
+ errorx(12, "Boot entry %X does not exist",
+ opts.bootnext);
+ ret = set_u16("BootNext", opts.bootnext & 0xFFFF);
+ if (ret < 0)
+ error(13, "Could not set BootNext");
+ }
+
+ if (opts.set_timeout) {
+ ret = set_u16("Timeout", opts.timeout);
+ if (ret < 0)
+ error(14, "Could not set Timeout");
+ }
+
+ if (opts.set_mirror_lo || opts.set_mirror_hi) {
+ ret=set_mirror(opts.below4g, opts.above4g);
+ }
+
+ if (!opts.quiet && ret == 0) {
+ switch (mode) {
+ case boot:
+ num = read_u16("BootNext");
+ cond_warning(opts.verbose >= 2 && num < 0,
+ "Could not read variable 'BootNext'");
+ if (num >= 0)
+ printf("BootNext: %04X\n", num);
+ num = read_u16("BootCurrent");
+ cond_warning(opts.verbose >= 2 && num < 0,
+ "Could not read variable 'BootCurrent'");
+ if (num >= 0)
+ printf("BootCurrent: %04X\n", num);
+ num = read_u16("Timeout");
+ cond_warning(opts.verbose >= 2 && num < 0,
+ "Could not read variable 'Timeout'");
+ if (num >= 0)
+ printf("Timeout: %u seconds\n", num);
+ show_order(order_name[mode]);
+ show_vars(prefices[mode]);
+ show_mirror();
+ break;
+ case driver:
+ case sysprep:
+ show_order(order_name[mode]);
+ show_vars(prefices[mode]);
+ break;
+ }
+ }
+ free_vars(&entry_list);
+ free_array(names);
+ if (ret)
+ return 1;
+ return 0;
+}
Index: efibootmgr/create-18-wrong-check-reconnect-patch/file.list
===================================================================
--- efibootmgr/create-18-wrong-check-reconnect-patch/file.list (nonexistent)
+++ efibootmgr/create-18-wrong-check-reconnect-patch/file.list (revision 15)
@@ -0,0 +1 @@
+efibootmgr-18/src/efibootmgr.c
Index: efibootmgr/patches/README
===================================================================
--- efibootmgr/patches/README (nonexistent)
+++ efibootmgr/patches/README (revision 15)
@@ -0,0 +1,6 @@
+
+/* begin *
+
+ TODO: Leave some comment here.
+
+ * end */
Index: efibootmgr/patches
===================================================================
--- efibootmgr/patches (nonexistent)
+++ efibootmgr/patches (revision 15)
Property changes on: efibootmgr/patches
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: efibootmgr
===================================================================
--- efibootmgr (nonexistent)
+++ efibootmgr (revision 15)
Property changes on: efibootmgr
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: efivar/Makefile
===================================================================
--- efivar/Makefile (nonexistent)
+++ efivar/Makefile (revision 15)
@@ -0,0 +1,56 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url = $(DOWNLOAD_SERVER)/sources/packages/a/efivar
+
+versions = 38
+pkgname = efivar
+suffix = tar.xz
+
+tarballs = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s = $(addsuffix .sha1sum, $(tarballs))
+
+patches = $(CURDIR)/patches/efivar-38-gnu-ld-2.36.patch
+
+.NOTPARALLEL: $(patches)
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s) $(patches)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+ @echo -e "\n======= Downloading source tarballs =======" ; \
+ for tarball in $(tarballs) ; do \
+ echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+ done ; wait
+
+$(sha1s): $(tarballs)
+ @for sha in $@ ; do \
+ echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+ echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+ touch $$sha ; \
+ echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+ sha1sum --check $$sha ; ret="$$?" ; \
+ if [ "$$ret" == "1" ]; then \
+ echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+ exit 1 ; \
+ fi ; \
+ done
+
+$(patches): $(sha1s)
+ @echo -e "\n======= Create Patches =======\n" ; \
+ ( cd create-38-gnu-ld-2.36-patch ; ./create.patch.sh ) ; \
+ echo -e "\n"
+
+download_clean:
+ @rm -f $(tarballs) $(sha1s) $(patches)
Index: efivar/create-38-gnu-ld-2.36-patch/create.patch.sh
===================================================================
--- efivar/create-38-gnu-ld-2.36-patch/create.patch.sh (nonexistent)
+++ efivar/create-38-gnu-ld-2.36-patch/create.patch.sh (revision 15)
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+VERSION=38
+
+tar --files-from=file.list -xJvf ../efivar-$VERSION.tar.xz
+mv efivar-$VERSION efivar-$VERSION-orig
+
+cp -rf ./efivar-$VERSION-new ./efivar-$VERSION
+
+diff --unified -Nr efivar-$VERSION-orig efivar-$VERSION > efivar-$VERSION-gnu-ld-2.36.patch
+
+mv efivar-$VERSION-gnu-ld-2.36.patch ../patches
+
+rm -rf ./efivar-$VERSION
+rm -rf ./efivar-$VERSION-orig
Property changes on: efivar/create-38-gnu-ld-2.36-patch/create.patch.sh
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: efivar/create-38-gnu-ld-2.36-patch/efivar-38-new/src/include/workarounds.mk
===================================================================
--- efivar/create-38-gnu-ld-2.36-patch/efivar-38-new/src/include/workarounds.mk (nonexistent)
+++ efivar/create-38-gnu-ld-2.36-patch/efivar-38-new/src/include/workarounds.mk (revision 15)
@@ -0,0 +1,24 @@
+# SPDX-License-Identifier: SPDX-License-Identifier: LGPL-2.1-or-later
+#
+# workarounds.mk - workarounds for weird stuff behavior
+
+LD_FLAVOR := $(shell $(LD) --version | grep -E '^(LLD|GNU ld)'|sed 's/ .*//g')
+LD_VERSION := $(shell $(LD) --version | grep -E '^(LLD|GNU ld)'|sed 's/.* //')
+# I haven't tested 2.36 here; 2.35 is definitely broken and 2.37 seems to work
+LD_DASH_T := $(shell \
+ if [ "x${LD_FLAVOR}" = xLLD ] ; then \
+ echo '-T' ; \
+ elif [ "x${LD_FLAVOR}" = xGNU ] ; then \
+ if echo "${LD_VERSION}" | grep -q -E '^2\.3[6789]|^2\.[456789]|^[3456789]|^[[:digit:]][[:digit:]]' ; then \
+ echo '-T' ; \
+ else \
+ echo "" ; \
+ fi ; \
+ else \
+ echo "Your linker is not supported" ; \
+ exit 1 ; \
+ fi)
+
+export LD_DASH_T
+
+# vim:ft=make
Index: efivar/create-38-gnu-ld-2.36-patch/file.list
===================================================================
--- efivar/create-38-gnu-ld-2.36-patch/file.list (nonexistent)
+++ efivar/create-38-gnu-ld-2.36-patch/file.list (revision 15)
@@ -0,0 +1 @@
+efivar-38/src/include/workarounds.mk
Index: efivar/patches/README
===================================================================
--- efivar/patches/README (nonexistent)
+++ efivar/patches/README (revision 15)
@@ -0,0 +1,6 @@
+
+/* begin *
+
+ TODO: Leave some comment here.
+
+ * end */
Index: efivar/patches
===================================================================
--- efivar/patches (nonexistent)
+++ efivar/patches (revision 15)
Property changes on: efivar/patches
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: efivar
===================================================================
--- efivar (nonexistent)
+++ efivar (revision 15)
Property changes on: efivar
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~