[flashrom] [PATCH] Hack libpci not to exit(1) during init if PCI does not work

Carl-Daniel Hailfinger c-d.hailfinger.devel.2006 at gmx.net
Sat Jul 2 21:14:20 CEST 2011


This patch is for testing only, and not for immediate merge.

libpci unhelpfully calls exit(1) instead of reporting an error if init
fails.
Fortunately, that part of libpci has not changed since the year 2000, so
we can use a really evil hack to avoid that.
We supply an alternative error printing function (which does not
exit(1)) and this function detects which error is happening and hacks
internal libpci structures in a way that avoids a later segfault due to
NULL pointer dereference.

We MUST absolutely make sure that pci_init() in libpci will not change
or this hack will explode spectacularly. Once we decide that this hack
is the way to go, notifying the libpci maintainer is essential.

Apply this patch, then compile flashrom with
make CONFIG_DUMMY=no CONFIG_INTERNAL=o CONFIG_SERPROG=no
CONFIG_RAYER_SPI=no CONFIG_NIC3COM=no CONFIG_GFXNVIDIA=no
CONFIG_SATASII=no CONFIG_FT2232_SPI=no CONFIG_DRKAISER=no
CONFIG_NICREALTEK=no CONFIG_NICINTEL_SPI=no CONFIG_BUSPIRATE_SPI=no
CONFIG_OGP_SPI=no CONFIG_SATAMV=no CONFIG_NICINTEL=yes

To check if the hack works, run "flashrom -V" and respond to this mail
with the output. You should get a message near the end which says that
programmer initialization failed.

Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006 at gmx.net>

Index: flashrom-libpci_hack_avoid_exit1_during_init/pcidev.c
===================================================================
--- flashrom-libpci_hack_avoid_exit1_during_init/pcidev.c	(Revision 1362)
+++ flashrom-libpci_hack_avoid_exit1_during_init/pcidev.c	(Arbeitskopie)
@@ -21,6 +21,8 @@
 
 #include <stdlib.h>
 #include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
 #include "flash.h"
 #include "programmer.h"
 
@@ -188,6 +190,58 @@
 	return 0;
 }
 
+/* Ugliest hack ever in flashrom! Should work for all libpci versions released
+ * in the year 2000 or later. Checked to make sense until at least version
+ * 3.1.8-test1.
+ */
+static void fake_libpci_method_init(struct pci_access *foo)
+{
+	msg_pinfo("Working around another pcilib crash\n");
+	return;
+}
+
+static struct {
+  char *name;	/* name in all libpci versions */
+  char *dummy1; /* Only present in some libpci versions */
+  void *dummy2;
+  void (*init1)(struct pci_access *); /* init in older versions */
+  void (*init2)(struct pci_access *); /* init in newer versions */
+  void *dummy3;
+  void *dummy4;
+  void *dummy5;
+  void *dummy6;
+  void *dummy7;
+  void *dummy8;
+  void *dummy9;
+  void *dummy10;
+} fake_libpci_methods = {
+	.name = "None",
+	.init1 = &fake_libpci_method_init,
+	.init2 = &fake_libpci_method_init,
+};
+
+static int pci_init_failed = 0;
+
+static void my_libpci_generic_error(char *msg, ...)
+{
+	va_list ap;
+
+	msg_pinfo("pcilib: ");
+	va_start(ap, msg);
+	vprintf(msg, ap);
+	va_end(ap);
+	msg_pinfo("\n");
+	if (!strcmp(msg, "Cannot find any working access method.")) {
+		/* Workaround for crash, very ugly. */
+		msg_pinfo("Working around pcilib crash\n");
+		pacc->methods = (void *)&fake_libpci_methods;
+		pci_init_failed = 1;
+	} else {
+		/* Any error in libpci would result in exit(1) by default. */
+		exit(1);
+	}
+}
+
 uintptr_t pcidev_init(int bar, const struct pcidev_status *devs)
 {
 	struct pci_dev *dev;
@@ -198,7 +252,14 @@
 	uintptr_t addr = 0, curaddr = 0;
 
 	pacc = pci_alloc();     /* Get the pci_access structure */
+	pacc->error = &my_libpci_generic_error;
 	pci_init(pacc);         /* Initialize the PCI library */
+	/* pci_init returns void, so we have to hack it. */
+	if (pci_init_failed) {
+		/* Yes, technically we would have to free stuff... */
+		return 1;
+	}
+
 	pci_scan_bus(pacc);     /* We want to get the list of devices */
 	pci_filter_init(pacc, &filter);
 


-- 
http://www.hailfinger.org/





More information about the flashrom mailing list