Imported Debian patch 0.5.4-1
[debian/efibootmgr] / src / lib / efi.c.orig
diff --git a/src/lib/efi.c.orig b/src/lib/efi.c.orig
deleted file mode 100644 (file)
index 2257e9f..0000000
+++ /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 <Matt_Domsch@dell.com>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <stdint.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <unistd.h>
-#include <dirent.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <sys/ioctl.h>
-#include <linux/sockios.h>
-#include <net/if.h>
-#include <pci/pci.h>
-#include <linux/ethtool.h>
-#include "efi.h"
-#include "efichar.h"
-#include "scsi_ioctls.h"
-#include "disk.h"
-#include "efibootmgr.h"
-#include "efivars_procfs.h"
-#include "efivars_sysfs.h"
-#include "list.h"
-
-static struct efivar_kernel_calls *fs_kernel_calls;
-
-EFI_DEVICE_PATH *
-load_option_path(EFI_LOAD_OPTION *option)
-{
-       char *p = (char *) option;
-       return (EFI_DEVICE_PATH *)
-               (p + sizeof(uint32_t) /* Attributes */
-                + sizeof(uint16_t)   /* FilePathListLength*/
-                + efichar_strsize(option->description)); /* Description */
-}
-
-char *
-efi_guid_unparse(efi_guid_t *guid, char *out)
-{
-       sprintf(out, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
-               guid->b[3], guid->b[2], guid->b[1], guid->b[0],
-               guid->b[5], guid->b[4], guid->b[7], guid->b[6],
-               guid->b[8], guid->b[9], guid->b[10], guid->b[11],
-               guid->b[12], guid->b[13], guid->b[14], guid->b[15]);
-        return out;
-}
-
-void
-set_fs_kernel_calls()
-{
-       char name[PATH_MAX];
-       DIR *dir;
-       snprintf(name, PATH_MAX, "%s", SYSFS_DIR_EFI_VARS);
-       dir = opendir(name);
-       if (dir) {
-               closedir(dir);
-               fs_kernel_calls = &sysfs_kernel_calls;
-               return;
-       }
-
-       snprintf(name, PATH_MAX, "%s", PROCFS_DIR_EFI_VARS);
-       dir = opendir(name);
-       if (dir) {
-               closedir(dir);
-               fs_kernel_calls = &procfs_kernel_calls;
-               return;
-       }
-       fprintf(stderr, "Fatal: Couldn't open either sysfs or procfs directories for accessing EFI variables.\n");
-       fprintf(stderr, "Try 'modprobe efivars' as root.\n");
-       exit(1);
-}
-
-
-
-static efi_status_t
-write_variable_to_file(efi_variable_t *var)
-{
-       int fd, byteswritten;
-       if (!var || !opts.testfile) return EFI_INVALID_PARAMETER;
-
-       printf("Test mode: Writing to %s\n", opts.testfile);
-       fd = creat(opts.testfile, S_IRWXU);
-       if (fd == -1) {
-               perror("Couldn't write to testfile");
-               return EFI_INVALID_PARAMETER;
-       }
-
-       byteswritten = write(fd, var, sizeof(*var));
-       if (byteswritten == -1) {
-               perror("Writing to testfile");
-
-       }
-       close(fd);
-       return EFI_SUCCESS;
-}
-
-efi_status_t
-read_variable(const char *name, efi_variable_t *var)
-{
-       if (!name || !var) return EFI_INVALID_PARAMETER;
-       return fs_kernel_calls->read(name, var);
-}
-
-efi_status_t
-create_variable(efi_variable_t *var)
-{
-       if (!var) return EFI_INVALID_PARAMETER;
-       if (opts.testfile) return write_variable_to_file(var);
-       return fs_kernel_calls->create(var);
-}
-
-efi_status_t
-delete_variable(efi_variable_t *var)
-{
-       if (!var) return EFI_INVALID_PARAMETER;
-       if (opts.testfile) return write_variable_to_file(var);
-       return fs_kernel_calls->delete(var);
-}
-
-
-efi_status_t
-edit_variable(efi_variable_t *var)
-{
-       char name[PATH_MAX];
-       if (!var) return EFI_INVALID_PARAMETER;
-       if (opts.testfile) return write_variable_to_file(var);
-
-       variable_to_name(var, name);
-       return fs_kernel_calls->edit(name, var);
-}
-
-efi_status_t
-create_or_edit_variable(efi_variable_t *var)
-{
-       efi_variable_t testvar;
-       char name[PATH_MAX];
-
-       memcpy(&testvar, var, sizeof(*var));
-       variable_to_name(var, name);
-
-       if (read_variable(name, &testvar) == EFI_SUCCESS)
-               return edit_variable(var);
-       else
-               return create_variable(var);
-}
-
-static int
-select_boot_var_names(const struct dirent *d)
-{
-       if (!strncmp(d->d_name, "Boot", 4) &&
-           isxdigit(d->d_name[4]) && isxdigit(d->d_name[5]) &&
-           isxdigit(d->d_name[6]) && isxdigit(d->d_name[7]) &&
-           d->d_name[8] == '-')
-               return 1;
-       return 0;
-}
-
-int
-read_boot_var_names(struct dirent ***namelist)
-{
-       if (!fs_kernel_calls || !namelist) return -1;
-       return scandir(fs_kernel_calls->path,
-                      namelist, select_boot_var_names,
-                      alphasort);
-}
-
-
-static int
-get_edd_version()
-{
-       efi_status_t status;
-       efi_variable_t var;
-       efi_guid_t guid = BLKX_UNKNOWN_GUID;
-       char name[80], text_guid[40];
-       ACPI_DEVICE_PATH *path = (ACPI_DEVICE_PATH *)&(var.Data);
-       int rc = 0;
-
-       /* Allow global user option override */
-
-       switch (opts.edd_version)
-       {
-       case 0: /* No EDD information */
-               return 0;
-               break;
-       case 1: /* EDD 1.0 */
-               return 1;
-               break;
-       case 3: /* EDD 3.0 */
-               return 3;
-               break;
-       default:
-               break;
-       }
-
-
-       memset(&var, 0, sizeof(efi_variable_t));
-       efi_guid_unparse(&guid, text_guid);
-       sprintf(name, "blk0-%s", text_guid);
-
-       status = read_variable(name, &var);
-       if (status != EFI_SUCCESS) {
-               return 0;
-       }
-       if (path->type == 2 && path->subtype == 1) rc = 3;
-       else rc = 1;
-       return rc;
-}
-
-/*
-  EFI_DEVICE_PATH, 0x01 (Hardware), 0x04 (Vendor), length 0x0018
-  This needs to know what EFI device has the boot device.
-*/
-static uint16_t
-make_edd10_device_path(void *dest, uint32_t hardware_device)
-{
-       VENDOR_DEVICE_PATH *hw;
-       char buffer[EDD10_HARDWARE_VENDOR_PATH_LENGTH];
-       efi_guid_t guid = EDD10_HARDWARE_VENDOR_PATH_GUID;
-       uint32_t *data;
-       memset(buffer, 0, sizeof(buffer));
-       hw = (VENDOR_DEVICE_PATH *)buffer;
-       data = (uint32_t *)hw->data;
-       hw->type = 0x01; /* Hardware Device Path */
-       hw->subtype = 0x04; /* Vendor */
-       hw->length = EDD10_HARDWARE_VENDOR_PATH_LENGTH;
-       memcpy(&(hw->vendor_guid), &guid, sizeof(guid));
-       *data = hardware_device;
-       memcpy(dest, buffer, hw->length);
-       return hw->length;
-}
-
-static uint16_t
-make_end_device_path(void *dest)
-{
-       END_DEVICE_PATH p;
-       memset(&p, 0, sizeof(p));
-       p.type = 0x7F; /* End of Hardware Device Path */
-       p.subtype = 0xFF; /* End Entire Device Path */
-       p.length = sizeof(p);
-       memcpy(dest, &p, p.length);
-       return p.length;
-}
-
-static uint16_t
-make_acpi_device_path(void *dest, uint32_t _HID, uint32_t _UID)
-{
-       ACPI_DEVICE_PATH p;
-       memset(&p, 0, sizeof(p));
-       p.type = 2;
-       p.subtype = 1;
-       p.length = sizeof(p);
-       p._HID = _HID;
-       p._UID = _UID;
-       memcpy(dest, &p, p.length);
-       return p.length;
-}
-
-static uint16_t
-make_mac_addr_device_path(void *dest, char *mac, uint8_t iftype)
-{
-
-        int i;
-       MAC_ADDR_DEVICE_PATH p;
-       memset(&p, 0, sizeof(p));
-       p.type = 3;
-       p.subtype = 11;
-       p.length = sizeof(p);
-       for (i=0; i < 14; i++) {
-               p.macaddr[i] = mac[i];
-       }
-       p.iftype = iftype;
-       memcpy(dest, &p, p.length);
-       return p.length;
-}
-
-struct device
-{
-       struct pci_dev *pci_dev;
-       struct list_head node;
-};
-
-static struct device *
-is_parent_bridge(struct pci_dev *p, unsigned int target_bus)
-{
-       struct device *d;
-       unsigned int primary, secondary;
-
-       if ( (pci_read_word(p, PCI_HEADER_TYPE) & 0x7f) != PCI_HEADER_TYPE_BRIDGE)
-               return NULL;
-
-       primary=pci_read_byte(p, PCI_PRIMARY_BUS);
-       secondary=pci_read_byte(p, PCI_SECONDARY_BUS);
-
-
-       if (secondary != target_bus)
-               return NULL;
-
-       d = malloc(sizeof(struct device));
-       if (!d)
-               return NULL;
-       memset(d, 0, sizeof(*d));
-       INIT_LIST_HEAD(&d->node);
-
-       d->pci_dev = p;
-
-       return d;
-}
-
-static struct device *
-find_parent(struct pci_access *pacc, unsigned int target_bus)
-{
-       struct device *dev;
-       struct pci_dev *p;
-
-       for (p=pacc->devices; p; p=p->next) {
-               dev = is_parent_bridge(p, target_bus);
-               if (dev)
-                       return dev;
-       }
-       return NULL;
-}
-
-static uint16_t
-make_one_pci_device_path(void *dest, uint8_t device, uint8_t function)
-{
-       PCI_DEVICE_PATH p;
-       memset(&p, 0, sizeof(p));
-       p.type = 1;
-       p.subtype = 1;
-       p.length   = sizeof(p);
-       p.device   = device;
-       p.function = function;
-       memcpy(dest, &p, p.length);
-       return p.length;
-}
-
-static uint16_t
-make_pci_device_path(void *dest, uint8_t bus, uint8_t device, uint8_t function)
-{
-       struct device *dev;
-       struct pci_access *pacc;
-       struct list_head *pos, *n;
-       LIST_HEAD(pci_parent_list);
-       char *p = dest;
-
-       pacc = pci_alloc();
-       if (!pacc)
-               return 0;
-
-       pci_init(pacc);
-       pci_scan_bus(pacc);
-
-       do {
-               dev = find_parent(pacc, bus);
-               if (dev) {
-                       list_add(&pci_parent_list, &dev->node);
-                       bus = dev->pci_dev->bus;
-               }
-       } while (dev && bus);
-
-
-       list_for_each_safe(pos, n, &pci_parent_list) {
-               dev = list_entry(pos, struct device, node);
-               p += make_one_pci_device_path(p,
-                                             dev->pci_dev->dev,
-                                             dev->pci_dev->func);
-               list_del(&dev->node);
-               free(dev);
-       }
-
-       p += make_one_pci_device_path(p, device, function);
-
-       pci_cleanup(pacc);
-
-       return ((void *)p - dest);
-}
-
-static uint16_t
-make_scsi_device_path(void *dest, uint16_t id, uint16_t lun)
-{
-       SCSI_DEVICE_PATH p;
-       memset(&p, 0, sizeof(p));
-       p.type = 3;
-       p.subtype = 2;
-       p.length   = sizeof(p);
-       p.id       = id;
-       p.lun      = lun;
-       memcpy(dest, &p, p.length);
-       return p.length;
-}
-
-static uint16_t
-make_harddrive_device_path(void *dest, uint32_t num, uint64_t start, uint64_t size,
-                          uint8_t *signature,
-                          uint8_t mbr_type, uint8_t signature_type)
-{
-       HARDDRIVE_DEVICE_PATH p;
-       memset(&p, 0, sizeof(p));
-       p.type = 4;
-       p.subtype = 1;
-       p.length   = sizeof(p);
-       p.part_num = num;
-       p.start = start;
-       p.size = size;
-       if (signature) memcpy(p.signature, signature, 16);
-       p.mbr_type = mbr_type;
-       p.signature_type = signature_type;
-       memcpy(dest, &p, p.length);
-       return p.length;
-}
-
-static uint16_t
-make_file_path_device_path(void *dest, efi_char16_t *name)
-{
-       FILE_PATH_DEVICE_PATH *p;
-       char buffer[1024];
-       int namelen  = efichar_strlen(name, -1);
-       int namesize = efichar_strsize(name);
-
-       memset(buffer, 0, sizeof(buffer));
-       p = (FILE_PATH_DEVICE_PATH *)buffer;
-       p->type      = 4;
-       p->subtype   = 4;
-       p->length    = 4 + namesize;
-       efichar_strncpy(p->path_name,
-                       name, namelen);
-
-       memcpy(dest, buffer, p->length);
-       return p->length;
-
-}
-
-
-
-static long
-make_edd30_device_path(int fd, void *buffer)
-{
-       int rc=0;
-       unsigned char bus=0, device=0, function=0;
-       Scsi_Idlun idlun;
-       unsigned char host=0, channel=0, id=0, lun=0;
-       char *p = buffer;
-
-
-       rc = disk_get_pci(fd, &bus, &device, &function);
-       if (rc) return 0;
-
-       memset(&idlun, 0, sizeof(idlun));
-       rc = get_scsi_idlun(fd, &idlun);
-       if (rc) return 0;
-       idlun_to_components(&idlun, &host, &channel, &id, &lun);
-
-       p += make_acpi_device_path      (p, EISAID_PNP0A03, bus);
-       p += make_pci_device_path       (p, bus, device, function);
-       p += make_scsi_device_path      (p, id, lun);
-       return ((void *)p - buffer);
-}
-
-/**
- * make_disk_load_option()
- * @disk disk
- *
- * Returns 0 on error, length of load option created on success.
- */
-char *make_disk_load_option(char *p, char *disk)
-{
-    int disk_fd=0;
-    char buffer[80];
-    char signature[16];
-    int rc, edd_version=0;
-    uint8_t mbr_type=0, signature_type=0;
-    uint64_t start=0, size=0;
-    efi_char16_t os_loader_path[40];
-
-    memset(signature, 0, sizeof(signature));
-
-    disk_fd = open(opts.disk, O_RDWR);
-    if (disk_fd == -1) {
-        sprintf(buffer, "Could not open disk %s", opts.disk);
-       perror(buffer);
-       return 0;
-    }
-
-    if (opts.edd_version) {
-        edd_version = get_edd_version();
-
-       if (edd_version == 3) {
-           p += make_edd30_device_path(disk_fd, p);
-       }
-       else if (edd_version == 1) {
-           p += make_edd10_device_path(p, opts.edd10_devicenum);
-       }
-    }
-
-    rc = disk_get_partition_info (disk_fd, opts.part,
-                                 &start, &size, signature,
-                                 &mbr_type, &signature_type);
-
-    close(disk_fd);
-
-    if (rc) {
-        fprintf(stderr, "Error: no partition information on disk %s.\n"
-               "       Cowardly refusing to create a boot option.\n",
-               opts.disk);
-       return 0;
-    }
-
-    p += make_harddrive_device_path (p, opts.part,
-                                    start, size,
-                                    signature,
-                                    mbr_type, signature_type);
-
-    efichar_from_char(os_loader_path, opts.loader, sizeof(os_loader_path));
-    p += make_file_path_device_path (p, os_loader_path);
-    p += make_end_device_path       (p);
-
-    return(p);
-}
-
-/**
- * make_net_load_option()
- * @data - load option returned
- *
- * Returns NULL on error, or p advanced by length of load option
- * created on success.
- */
-char *make_net_load_option(char *p, char *iface)
-{
-    /* copied pretty much verbatim from the ethtool source */
-    int fd = 0, err; 
-    int bus, slot, func;
-    struct ifreq ifr;
-    struct ethtool_drvinfo drvinfo;
-
-    memset(&ifr, 0, sizeof(ifr));
-    strcpy(ifr.ifr_name, iface);
-    drvinfo.cmd = ETHTOOL_GDRVINFO;
-    ifr.ifr_data = (caddr_t)&drvinfo;
-    /* Open control socket */
-    fd = socket(AF_INET, SOCK_DGRAM, 0);
-    if (fd < 0) {
-        perror("Cannot get control socket");
-       goto out;
-    }
-    err = ioctl(fd, SIOCETHTOOL, &ifr);
-    if (err < 0) {
-        perror("Cannot get driver information");
-       goto out;
-    }
-
-    /* The domain part was added in 2.6 kernels.  Test for that first. */
-    err = sscanf(drvinfo.bus_info, "%*x:%2x:%2x.%x", &bus, &slot, &func);
-    if (err != 3) {
-           err = sscanf(drvinfo.bus_info, "%2x:%2x.%x", &bus, &slot, &func);
-           if (err != 3) {
-                   perror("Couldn't parse device location string.");
-                   goto out;
-           }
-    }
-
-    err = ioctl(fd, SIOCGIFHWADDR, &ifr);
-    if (err < 0) {
-        perror("Cannot get hardware address.");
-       goto out;
-    }
-
-    p += make_acpi_device_path(p, opts.acpi_hid, opts.acpi_uid);
-    p += make_pci_device_path(p, bus, (uint8_t)slot, (uint8_t)func);
-    p += make_mac_addr_device_path(p, ifr.ifr_ifru.ifru_hwaddr.sa_data, 0);
-    p += make_end_device_path       (p);
-    return(p);
- out:
-    return NULL;
-}
-
-/**
- * make_linux_load_option()
- * @data - load option returned
- *
- * Returns 0 on error, length of load option created on success.
- */
-static unsigned long
-make_linux_load_option(void *data)
-{
-       EFI_LOAD_OPTION *load_option = data;
-       char *p = data, *q;
-       efi_char16_t description[64];
-       unsigned long datasize=0;
-
-       /* Write Attributes */
-       if (opts.active) load_option->attributes = LOAD_OPTION_ACTIVE;
-       else             load_option->attributes = 0;
-
-       p += sizeof(uint32_t);
-       /* skip writing file_path_list_length */
-       p += sizeof(uint16_t);
-       /* Write description.  This is the text that appears on the screen for the load option. */
-       memset(description, 0, sizeof(description));
-       efichar_from_char(description, opts.label, sizeof(description));
-       efichar_strncpy(load_option->description, description, sizeof(description));
-       p += efichar_strsize(load_option->description);
-
-       q = p;
-
-       if (opts.iface) {
-             p = (char *)make_net_load_option(p, opts.iface);
-       }
-       else {
-             p = (char *)make_disk_load_option(p, opts.iface);
-       }
-       if (p == NULL)
-               return 0;
-
-       load_option->file_path_list_length = p - q;
-
-       datasize = (uint8_t *)p - (uint8_t *)data;
-       return datasize;
-}
-
-/*
- * append_extra_args()
- * appends all arguments from argv[] not snarfed by getopt
- * as one long string onto data, up to maxchars.  allow for nulls
- */
-
-static unsigned long
-append_extra_args_ascii(void *data, unsigned long maxchars)
-{
-       char *p = data;
-       int i, appended=0;
-       unsigned long usedchars=0;
-       if (!data) return 0;
-
-
-       for (i=opts.optind; i < opts.argc && usedchars < maxchars; i++) {
-               p = strncpy(p, opts.argv[i], maxchars-usedchars-1);
-               p += strlen(p);
-               appended=1;
-
-               usedchars = p - (char *)data;
-
-               /* Put a space between args */
-               if (i < (opts.argc-1)) {
-
-                       p = strncpy(p, " ", maxchars-usedchars-1);
-                       p += strlen(p);
-                       usedchars = p - (char *)data;
-               }
-
-       }
-       /* Remember the NULL */
-       if (appended) return strlen(data) + 1;
-       return 0;
-}
-
-static unsigned long
-append_extra_args_unicode(void *data, unsigned long maxchars)
-{
-       char *p = data;
-       int i, appended=0;
-       unsigned long usedchars=0;
-       if (!data) return 0;
-
-
-       for (i=opts.optind; i < opts.argc && usedchars < maxchars; i++) {
-               p += efichar_from_char((efi_char16_t *)p, opts.argv[i],
-                                      maxchars-usedchars);
-               usedchars = efichar_strsize(data) - sizeof(efi_char16_t);
-               appended=1;
-
-               /* Put a space between args */
-               if (i < (opts.argc-1)) {
-                       p += efichar_from_char((efi_char16_t *)p, " ",
-                                              maxchars-usedchars);
-                       usedchars = efichar_strsize(data) -
-                               sizeof(efi_char16_t);
-               }
-       }
-
-       if (appended) return efichar_strsize( (efi_char16_t *)data );
-       return 0;
-}
-
-
-static unsigned long
-append_extra_args(void *data, unsigned long maxchars)
-{
-       if (opts.unicode)
-         return append_extra_args_unicode(data, maxchars);
-       else
-         return append_extra_args_ascii(data, maxchars);
-}
-
-
-
-int
-make_linux_efi_variable(efi_variable_t *var,
-                       unsigned int free_number)
-{
-       efi_guid_t guid = EFI_GLOBAL_VARIABLE;
-       char buffer[16];
-       unsigned char *optional_data=NULL;
-       unsigned long load_option_size = 0, opt_data_size=0;
-
-       memset(buffer,    0, sizeof(buffer));
-
-       /* VariableName needs to be BootXXXX */
-       sprintf(buffer, "Boot%04X", free_number);
-
-       efichar_from_char(var->VariableName, buffer, 1024);
-
-       memcpy(&(var->VendorGuid), &guid, sizeof(guid));
-       var->Attributes =
-               EFI_VARIABLE_NON_VOLATILE |
-               EFI_VARIABLE_BOOTSERVICE_ACCESS |
-               EFI_VARIABLE_RUNTIME_ACCESS;
-
-       /* Set Data[] and DataSize */
-
-       load_option_size =  make_linux_load_option(var->Data);
-
-       if (!load_option_size) return 0;
-
-       /* Set OptionalData (passed as binary to the called app) */
-       optional_data = var->Data + load_option_size;
-       opt_data_size = append_extra_args(optional_data,
-                                 sizeof(var->Data) - load_option_size);
-       var->DataSize = load_option_size + opt_data_size;
-       return var->DataSize;
-}
-
-
-int
-variable_to_name(efi_variable_t *var, char *name)
-{
-       char *p = name;
-       efichar_to_char(p, var->VariableName, PATH_MAX);
-       p += strlen(p);
-       p += sprintf(p, "-");
-       efi_guid_unparse(&var->VendorGuid, p);
-       return strlen(name);
-}