#include "efiboot.h"
+bool HIDDEN
+is_pata(struct device *dev)
+{
+ if (!strncmp(dev->driver, "pata_", 5) ||
+ !strncmp(dev->driver, "ata_", 4))
+ return true;
+
+ if (dev->n_pci_devs > 0 &&
+ dev->pci_dev[dev->n_pci_devs - 1].driverlink) {
+ char *slash = dev->pci_dev[dev->n_pci_devs - 1].driverlink;
+
+ slash = strrchr(slash, '/');
+ if (slash &&
+ (!strncmp(slash, "/ata_", 5) ||
+ !strncmp(slash, "/pata_", 6)))
+ return true;
+ }
+
+ return false;
+}
+
/*
* support for old-school ATA devices
*
* 11:0 -> ../../devices/pci0000:00/0000:00:11.5/ata3/host2/target2:0:0/2:0:0:0/block/sr0
*/
static ssize_t
-parse_ata(struct device *dev, const char *current UNUSED)
+parse_ata(struct device *dev, const char *current)
{
+ uint32_t scsi_host, scsi_bus, scsi_device, scsi_target;
+ uint64_t scsi_lun;
+ int pos;
+
debug(DEBUG, "entry");
/* IDE disks can have up to 64 partitions, or 6 bits worth,
* and have one bit for the disk number.
dev->interface_type = ata;
set_part(dev, dev->minor & 0x3F);
} else {
- /*
- * If it isn't one of those majors, it isn't a PATA device.
- */
- return 0;
+ debug(DEBUG, "If this is ATA, it isn't using a traditional IDE inode.");
}
- if (!strncmp(dev->driver, "pata_", 5) ||
- !(strcmp(dev->driver, "ata_piix"))) {
+ if (is_pata(dev)) {
dev->interface_type = ata;
} else {
/*
return 0;
}
+ char *host = strstr(current, "/host");
+ if (!host)
+ return -1;
+
+ pos = parse_scsi_link(host + 1, &scsi_host,
+ &scsi_bus, &scsi_device,
+ &scsi_target, &scsi_lun);
+ if (pos < 0)
+ return -1;
+
+ dev->ata_info.scsi_host = scsi_host;
+ dev->ata_info.scsi_bus = scsi_bus;
+ dev->ata_info.scsi_device = scsi_device;
+ dev->ata_info.scsi_target = scsi_target;
+ dev->ata_info.scsi_lun = scsi_lun;
+
char *block = strstr(current, "/block/");
if (!block)
return -1;
return block + 1 - current;
}
+static ssize_t
+dp_create_ata(struct device *dev,
+ uint8_t *buf, ssize_t size, ssize_t off)
+{
+ ssize_t sz;
+
+ debug(DEBUG, "entry");
+
+ sz = efidp_make_atapi(buf + off, size ? size - off : 0,
+ dev->ata_info.scsi_device,
+ dev->ata_info.scsi_target - 1,
+ dev->ata_info.scsi_lun);
+ if (sz < 0)
+ efi_error("efidp_make_atapi() failed");
+
+ return sz;
+}
+
enum interface_type ata_iftypes[] = { ata, atapi, unknown };
struct dev_probe ata_parser = {
.iftypes = ata_iftypes,
.flags = DEV_PROVIDES_HD,
.parse = parse_ata,
- .create = NULL,
+ .create = dp_create_ata,
};
dev->pci_dev[i].pci_bus = bus;
dev->pci_dev[i].pci_device = device;
dev->pci_dev[i].pci_function = function;
+ char *tmp = strndup(current, devpart-current+1);
+ char *linkbuf = NULL;
+ if (!tmp) {
+ efi_error("could not allocate memory");
+ return -1;
+ }
+ tmp[devpart - current] = '\0';
+ rc = sysfs_readlink(&linkbuf, "class/block/%s/driver", tmp);
+ free(tmp);
+ if (rc < 0) {
+ efi_error("Could not find driver for pci device");
+ return -1;
+ }
+ dev->pci_dev[i].driverlink = strdup(linkbuf);
+ debug(DEBUG, "driver:%s\n", linkbuf);
dev->n_pci_devs += 1;
}
debug(DEBUG, "entry buf:%p size:%zd off:%zd", buf, size, off);
if (dev->pci_root.pci_root_acpi_uid_str) {
+ debug(DEBUG, "creating acpi_hid_ex dp hid:0x%08x uid:\"%s\"",
+ dev->pci_root.pci_root_acpi_hid,
+ dev->pci_root.pci_root_acpi_uid_str);
new = efidp_make_acpi_hid_ex(buf + off, size ? size - off : 0,
dev->pci_root.pci_root_acpi_hid,
0, 0, "",
return new;
}
} else {
+ debug(DEBUG, "creating acpi_hid dp hid:0x%08x uid:0x%0"PRIx64,
+ dev->pci_root.pci_root_acpi_hid,
+ dev->pci_root.pci_root_acpi_uid);
new = efidp_make_acpi_hid(buf + off, size ? size - off : 0,
dev->pci_root.pci_root_acpi_hid,
dev->pci_root.pci_root_acpi_uid);
off += new;
sz += new;
+ debug(DEBUG, "creating PCI device path nodes");
for (unsigned int i = 0; i < dev->n_pci_devs; i++) {
+ debug(DEBUG, "creating PCI device path node %u", i);
new = efidp_make_pci(buf + off, size ? size - off : 0,
dev->pci_dev[i].pci_device,
dev->pci_dev[i].pci_function);
{
int rc;
int sz = 0;
- int pos = 0;
+ int pos0 = 0, pos1 = 0;
char *spaces;
sz = strlen(current);
* So we start when current is:
* host4/port-4:0/end_device-4:0/target4:0:0/4:0:0:0/block/sdc/sdc1
*/
- uint32_t tosser0, tosser1;
+ uint32_t tosser0, tosser1, tosser2;
/* ignore a bunch of stuff
* host4/port-4:0
* or host4/port-4:0:0
*/
- debug(DEBUG, "searching for host4/port-4:0 or host4/port-4:0:0");
- rc = sscanf(current, "host%d/port-%d:%d%n", scsi_host, &tosser0,
- &tosser1, &pos);
- debug(DEBUG, "current:\"%s\" rc:%d pos:%d\n", current+sz, rc, pos);
- arrow(DEBUG, spaces, 9, pos, rc, 3);
- if (rc != 3)
- return -1;
- sz += pos;
- pos = 0;
-
- rc = sscanf(current + sz, ":%d%n", &tosser0, &pos);
- debug(DEBUG, "current:\"%s\" rc:%d pos:%d\n", current+sz, rc, pos);
- arrow(DEBUG, spaces, 9, pos, rc, 1);
- if (rc != 0 && rc != 1)
+ debug(DEBUG, "searching for host4/");
+ rc = sscanf(current, "host%d/%n", scsi_host, &pos0);
+ debug(DEBUG, "current:\"%s\" rc:%d pos0:%d\n", current+sz, rc, pos0);
+ arrow(DEBUG, spaces, 9, pos0, rc, 1);
+ if (rc != 1)
return -1;
- sz += pos;
- pos = 0;
-
- /* next:
- * /end_device-4:0
- * or /end_device-4:0:0
- * awesomely these are the exact same fields that go into port-blah,
- * but we don't care for now about any of them anyway.
- */
- debug(DEBUG, "searching for /end_device-4:0 or /end_device-4:0:0");
- rc = sscanf(current + sz, "/end_device-%d:%d%n", &tosser0, &tosser1, &pos);
- debug(DEBUG, "current:\"%s\" rc:%d pos:%d\n", current+sz, rc, pos);
- arrow(DEBUG, spaces, 9, pos, rc, 2);
- if (rc != 2)
+ sz += pos0;
+ pos0 = 0;
+
+ debug(DEBUG, "searching for port-4:0 or port-4:0:0");
+ rc = sscanf(current, "port-%d:%d%n:%d%n", &tosser0,
+ &tosser1, &pos0, &tosser2, &pos1);
+ debug(DEBUG, "current:\"%s\" rc:%d pos0:%d pos1:%d\n", current+sz, rc, pos0, pos1);
+ arrow(DEBUG, spaces, 9, pos0, rc, 2);
+ arrow(DEBUG, spaces, 9, pos1, rc, 3);
+ if (rc == 2 || rc == 3) {
+ sz += pos0;
+ pos0 = 0;
+
+ /* next:
+ * /end_device-4:0
+ * or /end_device-4:0:0
+ * awesomely these are the exact same fields that go into port-blah,
+ * but we don't care for now about any of them anyway.
+ */
+ debug(DEBUG, "searching for /end_device-4:0/ or /end_device-4:0:0/");
+ rc = sscanf(current + sz, "/end_device-%d:%d%n", &tosser0, &tosser1, &pos0);
+ debug(DEBUG, "current:\"%s\" rc:%d pos0:%d\n", current+sz, rc, pos0);
+ arrow(DEBUG, spaces, 9, pos0, rc, 2);
+ if (rc != 2)
+ return -1;
+ sz += pos0;
+ pos0 = 0;
+
+ rc = sscanf(current + sz, ":%d%n", &tosser0, &pos0);
+ debug(DEBUG, "current:\"%s\" rc:%d pos0:%d\n", current+sz, rc, pos0);
+ arrow(DEBUG, spaces, 9, pos0, rc, 2);
+ if (rc != 0 && rc != 1)
+ return -1;
+ sz += pos0;
+ pos0 = 0;
+
+ if (current[sz] == '/')
+ sz += 1;
+ } else if (rc != 0) {
return -1;
- sz += pos;
- pos = 0;
-
- rc = sscanf(current + sz, ":%d%n", &tosser0, &pos);
- debug(DEBUG, "current:\"%s\" rc:%d pos:%d\n", current+sz, rc, pos);
- arrow(DEBUG, spaces, 9, pos, rc, 2);
- if (rc != 0 && rc != 1)
- return -1;
- sz += pos;
- pos = 0;
+ }
/* now:
* /target4:0:0/
*/
uint64_t tosser3;
- debug(DEBUG, "searching for /target4:0:0/");
- rc = sscanf(current + sz, "/target%d:%d:%"PRIu64"/%n", &tosser0, &tosser1,
- &tosser3, &pos);
- debug(DEBUG, "current:\"%s\" rc:%d pos:%d\n", current+sz, rc, pos);
- arrow(DEBUG, spaces, 9, pos, rc, 3);
+ debug(DEBUG, "searching for target4:0:0/");
+ rc = sscanf(current + sz, "target%d:%d:%"PRIu64"/%n", &tosser0, &tosser1,
+ &tosser3, &pos0);
+ debug(DEBUG, "current:\"%s\" rc:%d pos0:%d\n", current+sz, rc, pos0);
+ arrow(DEBUG, spaces, 9, pos0, rc, 3);
if (rc != 3)
return -1;
- sz += pos;
- pos = 0;
+ sz += pos0;
+ pos0 = 0;
/* now:
* %d:%d:%d:%llu/
*/
debug(DEBUG, "searching for 4:0:0:0/");
rc = sscanf(current + sz, "%d:%d:%d:%"PRIu64"/%n",
- scsi_bus, scsi_device, scsi_target, scsi_lun, &pos);
- debug(DEBUG, "current:\"%s\" rc:%d pos:%d\n", current+sz, rc, pos);
- arrow(DEBUG, spaces, 9, pos, rc, 4);
+ scsi_bus, scsi_device, scsi_target, scsi_lun, &pos0);
+ debug(DEBUG, "current:\"%s\" rc:%d pos0:%d\n", current+sz, rc, pos0);
+ arrow(DEBUG, spaces, 9, pos0, rc, 4);
if (rc != 4)
return -1;
- sz += pos;
+ sz += pos0;
return sz;
}