#define _FILE_OFFSET_BITS 64
+typedef unsigned long long u64; /* hack to allow include of ethtool.h */
+
+#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <linux/sockios.h>
#include <net/if.h>
#include <pci/pci.h>
-typedef __u64 u64;
#include <linux/ethtool.h>
#include "efi.h"
#include "efichar.h"
static int
select_boot_var_names(const struct dirent *d)
{
- int num, rc;
- rc = sscanf(d->d_name, "Boot0%03x-%*s", &num);
- return rc;
+ 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
* make_net_load_option()
* @data - load option returned
*
- * Returns 0 on error, length of load option created on success.
+ * Returns NULL on error, or p advanced by length of load option
+ * created on success.
*/
char *make_net_load_option(char *p, char *iface)
{
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0) {
perror("Cannot get control socket");
+ goto out;
}
err = ioctl(fd, SIOCETHTOOL, &ifr);
if (err < 0) {
perror("Cannot get driver information");
+ goto out;
}
-
- err = sscanf(drvinfo.bus_info, "%2x:%2x.%x", &bus, &slot, &func);
- if (err == 0) {
- perror("Couldn't parse device location string.");
+ /* The domain part was added in 2.6 kernels. Test for that first. */
+ err = sscanf(drvinfo.bus_info, "%*x:%2x:%2x.%x", &bus, &slot, &func);
+ if (err != 3) {
+ err = sscanf(drvinfo.bus_info, "%2x:%2x.%x", &bus, &slot, &func);
+ if (err != 3) {
+ perror("Couldn't parse device location string.");
+ goto out;
+ }
}
- p += make_acpi_device_path(p, opts.acpi_hid, opts.acpi_uid);
- p += make_pci_device_path(p, bus, (uint8_t)slot, (uint8_t)func);
-
err = ioctl(fd, SIOCGIFHWADDR, &ifr);
if (err < 0) {
perror("Cannot get hardware address.");
+ goto out;
}
+ p += make_acpi_device_path(p, opts.acpi_hid, opts.acpi_uid);
+ p += make_pci_device_path(p, bus, (uint8_t)slot, (uint8_t)func);
p += make_mac_addr_device_path(p, ifr.ifr_ifru.ifru_hwaddr.sa_data, 0);
p += make_end_device_path (p);
return(p);
+ out:
+ return NULL;
}
/**
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;
return 0;
}
+static unsigned long
+append_extra_args_file(void *data, unsigned long maxchars)
+{
+ char *p = data;
+ char *file = opts.extra_opts_file;
+ int fd = STDIN_FILENO;
+ ssize_t num_read=0;
+ unsigned long appended=0;
+
+ if (!data) return 0;
+
+ if (file && strncmp(file, "-", 1))
+ fd = open(file, O_RDONLY);
+
+ if (fd == -1) {
+ perror("Failed to open extra arguments file");
+ return 0;
+ }
+
+ do {
+ num_read = read(fd, p, maxchars - appended);
+ if (num_read < 0) {
+ perror("Error reading extra arguments file");
+ break;
+ }
+ else if (num_read>0) {
+ appended += num_read;
+ p += num_read;
+ }
+ } while (num_read > 0 && ((maxchars - appended) > 0));
+
+ if (fd != STDIN_FILENO)
+ close(fd);
+
+ return appended;
+}
+
static unsigned long
append_extra_args(void *data, unsigned long maxchars)
{
- if (opts.unicode)
- return append_extra_args_unicode(data, maxchars);
+ unsigned long bytes_written=0;
+
+ if (opts.extra_opts_file)
+ bytes_written += append_extra_args_file(data, maxchars);
+
+ if (opts.unicode)
+ bytes_written += append_extra_args_unicode(data, maxchars - bytes_written);
else
- return append_extra_args_ascii(data, maxchars);
+ bytes_written += append_extra_args_ascii(data, maxchars - bytes_written);
+ return bytes_written;
}
memset(buffer, 0, sizeof(buffer));
/* VariableName needs to be BootXXXX */
- sprintf(buffer, "Boot%04x", free_number);
+ sprintf(buffer, "Boot%04X", free_number);
efichar_from_char(var->VariableName, buffer, 1024);