Imported Debian patch 0.5.3-1
[debian/efibootmgr] / src / lib / efi.c
index ac782c9b0edc4c3d5c7afc70f32579bfa04aea25..7dd2ab3aa5d8d2c1a48231cce526d9359aaf0759 100644 (file)
@@ -548,7 +548,8 @@ char *make_disk_load_option(char *p, char *disk)
  * make_net_load_option()
  * @data - load option returned
  *
- * Returns 0 on error, length of load option created on success.
+ * Returns NULL on error, or p advanced by length of load option
+ * created on success.
  */
 char *make_net_load_option(char *p, char *iface)
 {
@@ -566,29 +567,37 @@ char *make_net_load_option(char *p, char *iface)
     fd = socket(AF_INET, SOCK_DGRAM, 0);
     if (fd < 0) {
         perror("Cannot get control socket");
+       goto out;
     }
     err = ioctl(fd, SIOCETHTOOL, &ifr);
     if (err < 0) {
         perror("Cannot get driver information");
+       goto out;
     }
 
-
-    err = sscanf(drvinfo.bus_info, "%2x:%2x.%x", &bus, &slot, &func);
-    if (err == 0) {
-        perror("Couldn't parse device location string.");
+    /* The domain part was added in 2.6 kernels.  Test for that first. */
+    err = sscanf(drvinfo.bus_info, "%*x:%2x:%2x.%x", &bus, &slot, &func);
+    if (err != 3) {
+           err = sscanf(drvinfo.bus_info, "%2x:%2x.%x", &bus, &slot, &func);
+           if (err != 3) {
+                   perror("Couldn't parse device location string.");
+                   goto out;
+           }
     }
 
-    p += make_acpi_device_path(p, opts.acpi_hid, opts.acpi_uid);
-    p += make_pci_device_path(p, bus, (uint8_t)slot, (uint8_t)func);
-
     err = ioctl(fd, SIOCGIFHWADDR, &ifr);
     if (err < 0) {
         perror("Cannot get hardware address.");
+       goto out;
     }
 
+    p += make_acpi_device_path(p, opts.acpi_hid, opts.acpi_uid);
+    p += make_pci_device_path(p, bus, (uint8_t)slot, (uint8_t)func);
     p += make_mac_addr_device_path(p, ifr.ifr_ifru.ifru_hwaddr.sa_data, 0);
     p += make_end_device_path       (p);
     return(p);
+ out:
+    return NULL;
 }
 
 /**
@@ -623,10 +632,11 @@ make_linux_load_option(void *data)
        if (opts.iface) {
              p = (char *)make_net_load_option(p, opts.iface);
        }
-
        else {
              p = (char *)make_disk_load_option(p, opts.iface);
        }
+       if (p == NULL)
+               return 0;
 
        load_option->file_path_list_length = p - q;
 
@@ -698,14 +708,57 @@ append_extra_args_unicode(void *data, unsigned long maxchars)
        return 0;
 }
 
+static unsigned long
+append_extra_args_file(void *data, unsigned long maxchars)
+{
+       char *p = data;
+       char *file = opts.extra_opts_file;
+       int fd = STDIN_FILENO;
+       ssize_t num_read=0;
+       unsigned long appended=0;
+
+       if (!data) return 0;
+
+       if (file && strncmp(file, "-", 1))
+               fd = open(file, O_RDONLY);
+
+       if (fd == -1) {
+               perror("Failed to open extra arguments file");
+               return 0;
+       }
+
+       do {
+               num_read = read(fd, p, maxchars - appended);
+               if (num_read < 0) {
+                       perror("Error reading extra arguments file");
+                       break;
+               }
+               else if (num_read>0) {
+                       appended += num_read;
+                       p += num_read;
+               }
+       } while (num_read > 0 && ((maxchars - appended) > 0));
+
+       if (fd != STDIN_FILENO)
+               close(fd);
+
+       return appended;
+}
+
 
 static unsigned long
 append_extra_args(void *data, unsigned long maxchars)
 {
-       if (opts.unicode)
-         return append_extra_args_unicode(data, maxchars);
+       unsigned long bytes_written=0;
+
+       if (opts.extra_opts_file)
+               bytes_written += append_extra_args_file(data, maxchars);
+
+       if  (opts.unicode)
+               bytes_written += append_extra_args_unicode(data, maxchars - bytes_written);
        else
-         return append_extra_args_ascii(data, maxchars);
+               bytes_written += append_extra_args_ascii(data, maxchars - bytes_written);
+       return bytes_written;
 }