Luc Verhaegen has uploaded this change for review.

View Change

add newer pci infrastructure

This code does not negatively affect existing pci support and existing
pci devices, it introduces parallel infrastructure which:
- allows users to define a private which could be device specific.
This avoids doing multiple lookups, which massively helps the ati spi
driver which will support hundreds of devices.
- uses linux sysfs pci infrastructure for enable/disable and mapping
resources. This circumvents the security restrictions surrounding
/dev/mem, but means that support for other operating systems still
needs to be cobbled together.
- looks up device names through libpci, keeping us from maintaining a
separate names list.

Change-Id: I59af37cba5cb78014e0714c654db2501151f605e
Signed-off-by: Luc Verhaegen <libv@skynet.be>
---
M pcidev.c
M programmer.h
2 files changed, 157 insertions(+), 0 deletions(-)

git pull ssh://review.coreboot.org:29418/flashrom refs/changes/78/29078/1
diff --git a/pcidev.c b/pcidev.c
index f5ad819..837b028 100644
--- a/pcidev.c
+++ b/pcidev.c
@@ -3,6 +3,7 @@
*
* Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
* Copyright (C) 2010, 2011 Carl-Daniel Hailfinger
+ * Copyright (C) 2018 Luc Verhaegen <libv@skynet.be>
*
* 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
@@ -333,3 +334,134 @@
register_undo_pci_write_long(dev, reg);
return pci_write_long(dev, reg, data);
}
+
+/*
+ * This is reinvented pci device matching and access infrastructure which:
+ * - allows users to define a private which could be device specific.
+ * This avoids doing multiple lookups, which massively helps the ati spi
+ * driver which will support hundreds of devices.
+ * - uses linux sysfs pci infrastructure for enable/disable and mapping
+ * resources. This circumvents the security restrictions surrounding
+ * /dev/mem, but means that support for other operating systems still
+ * needs to be cobbled together.
+ * - looks up device names through libpci, keeping us from maintaining a
+ * separate names list.
+ *
+ */
+
+/*
+ *
+ */
+static int
+flashrom_pci_device_shutdown(void *data)
+{
+ struct flashrom_pci_device *device = data;
+
+ if (!device->sysfs_path) {
+ msg_perr("%s: Tried to cleanup an invalid pci_device!\n"
+ "Please report a bug at flashrom@flashrom.org\n", __func__);
+ return 1;
+ }
+
+ free(device->sysfs_path);
+ device->sysfs_path = NULL;
+
+ free(device->name);
+ device->name = NULL;
+
+ device->private = NULL;
+ free(device);
+
+ return 0;
+}
+
+/*
+ *
+ */
+struct flashrom_pci_device *
+flashrom_pci_init(const struct flashrom_pci_match *matches)
+{
+ struct flashrom_pci_device *device;
+ struct pci_filter filter;
+ struct pci_dev *dev, *found_dev = NULL;
+ const struct flashrom_pci_match *found_match = NULL;
+ char *pcidev_bdf;
+ char buffer[1024], *name = NULL;
+ int i, found = 0;
+
+ if (pci_init_common())
+ return NULL;
+
+ pci_filter_init(pacc, &filter);
+
+ /* Filter by bb:dd.f (if supplied by the user). */
+ pcidev_bdf = extract_programmer_param("pci");
+ if (pcidev_bdf) {
+ char *msg;
+
+ if ((msg = pci_filter_parse_slot(&filter, pcidev_bdf))) {
+ msg_perr("Error: %s\n", msg);
+ return NULL;
+ }
+
+ free(pcidev_bdf);
+ }
+
+ for (dev = pacc->devices; dev; dev = dev->next)
+ if (pci_filter_match(&filter, dev)) {
+ for (i = 0; matches[i].vendor_id ; i++)
+ if ((dev->vendor_id == matches[i].vendor_id) &&
+ (dev->device_id == matches[i].device_id))
+ break;
+
+ if (!matches[i].vendor_id)
+ continue;
+
+
+ name = pci_lookup_name(pacc, buffer, sizeof(buffer),
+ PCI_LOOKUP_VENDOR | PCI_LOOKUP_DEVICE,
+ dev->vendor_id, dev->device_id);
+ if (name)
+ msg_pinfo("Detected %04x:%04x@%02x:%02x.%x \"%s\"\n",
+ dev->vendor_id, dev->device_id,
+ dev->bus, dev->dev, dev->func, name);
+ else
+ msg_pinfo("Detected %04x:%04x@%02x:%02x.%x \"%s\"\n",
+ dev->vendor_id, dev->device_id,
+ dev->bus, dev->dev, dev->func,
+ "<unknown pciids>");
+ found_dev = dev;
+ found_match = &matches[i];
+ found++;
+ }
+
+ /* Only continue if exactly one supported PCI dev has been found. */
+ if (!found) {
+ msg_perr("Error: No supported PCI device found.\n");
+ return NULL;
+ } else if (found > 1) {
+ msg_perr("Error: Multiple supported PCI devices found. Use 'flashrom -p xxxx:pci=bb:dd.f'\n"
+ "to explicitly select the card with the given BDF (PCI bus, device, function).\n");
+ return NULL;
+ }
+
+ device = calloc(1, sizeof(*device));
+
+ device->name = strdup(name);
+
+ device->device_id = found_dev->device_id;
+ device->vendor_id = found_dev->vendor_id;
+
+ device->pci = found_dev;
+
+ snprintf(buffer, sizeof(buffer) - 1,
+ "/sys/bus/pci/devices/%04x:%02x:%02x.%01x/",
+ 0, found_dev->bus, found_dev->dev, found_dev->func);
+ device->sysfs_path = strdup(buffer);
+
+ device->private = found_match->private;
+
+ register_shutdown(flashrom_pci_device_shutdown, device);
+
+ return device;
+}
diff --git a/programmer.h b/programmer.h
index 311992a..0a445fa 100644
--- a/programmer.h
+++ b/programmer.h
@@ -849,4 +849,29 @@
struct libusb_device_handle *usb_dev_get_by_vid_pid_number(
struct libusb_context *usb_ctx, uint16_t vid, uint16_t pid, unsigned int num);

+#if NEED_PCI == 1
+struct flashrom_pci_match {
+ uint16_t vendor_id;
+ uint16_t device_id;
+ const enum test_state status;
+ const void *private; /* programmer specific */
+};
+
+struct flashrom_pci_device {
+ char *name; /* created from pci info */
+
+ /* convenience copies */
+ uint16_t vendor_id;
+ uint16_t device_id;
+
+ struct pci_dev *pci;
+
+ char *sysfs_path; /* linux only, of course */
+
+ const void *private; /* programmer specific hook */
+};
+
+struct flashrom_pci_device *flashrom_pci_init(const struct flashrom_pci_match *matches);
+#endif /* NEED_PCI */
+
#endif /* !__PROGRAMMER_H__ */

To view, visit change 29078. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: flashrom
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: I59af37cba5cb78014e0714c654db2501151f605e
Gerrit-Change-Number: 29078
Gerrit-PatchSet: 1
Gerrit-Owner: Luc Verhaegen <libv@skynet.be>