Add "name" field to struct device to allow human-readable hardware device
names.

Add "dev" pointer in struct net_device to tie network interfaces back to a
hardware device.

Force natural alignment of data types in __table() macros.  This seems to
prevent gcc from taking the unilateral decision to occasionally increase
their alignment (which screws up the table packing).
diff --git a/src/arch/i386/drivers/net/undi.c b/src/arch/i386/drivers/net/undi.c
index ac28c02..fee2095 100644
--- a/src/arch/i386/drivers/net/undi.c
+++ b/src/arch/i386/drivers/net/undi.c
@@ -19,6 +19,7 @@
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
+#include <vsprintf.h>
 #include <gpxe/pci.h>
 #include <undi.h>
 #include <undirom.h>
@@ -96,6 +97,8 @@
 	}
 
 	/* Add to device hierarchy */
+	snprintf ( undi->dev.name, sizeof ( undi->dev.name ),
+		   "UNDI%04x:%04x", undi->entry.segment, undi->entry.offset );
 	undi->dev.parent = &pci->dev;
 	INIT_LIST_HEAD ( &undi->dev.children );
 	list_add ( &undi->dev.siblings, &pci->dev.children );
diff --git a/src/arch/i386/drivers/net/undinet.c b/src/arch/i386/drivers/net/undinet.c
index 5ff9bd4..5041e3a 100644
--- a/src/arch/i386/drivers/net/undinet.c
+++ b/src/arch/i386/drivers/net/undinet.c
@@ -577,6 +577,7 @@
 		return -ENOMEM;
 	undinic = netdev->priv;
 	undi_set_drvdata ( undi, netdev );
+	netdev->dev = &undi->dev;
 	memset ( undinic, 0, sizeof ( *undinic ) );
 	undinic->entry = undi->entry;
 	DBGC ( undinic, "UNDINIC %p using UNDI %p\n", undinic, undi );
diff --git a/src/arch/i386/drivers/net/undionly.c b/src/arch/i386/drivers/net/undionly.c
index 5b8ff97..bd53e1d 100644
--- a/src/arch/i386/drivers/net/undionly.c
+++ b/src/arch/i386/drivers/net/undionly.c
@@ -58,6 +58,8 @@
 	}
 
 	/* Add to device hierarchy */
+	strncpy ( preloaded_undi.dev.name, "UNDI",
+		  ( sizeof ( preloaded_undi.dev.name ) - 1 ) );
 	preloaded_undi.dev.parent = &rootdev->dev;
 	list_add ( &preloaded_undi.dev.siblings, &rootdev->dev.children);
 	INIT_LIST_HEAD ( &preloaded_undi.dev.children );
@@ -91,6 +93,6 @@
 
 /** UNDI bus root device */
 struct root_device undi_root_device __root_device = {
-	.name = "UNDI",
+	.dev = { .name = "UNDI" },
 	.driver = &undi_root_driver,
 };
diff --git a/src/core/background.c b/src/core/background.c
index 1cec05a..e0dceae 100644
--- a/src/core/background.c
+++ b/src/core/background.c
@@ -1,7 +1,9 @@
 #include "background.h"
 
-static struct background backgrounds[0] __table_start ( background );
-static struct background backgrounds_end[0] __table_end ( background );
+static struct background backgrounds[0]
+	__table_start ( struct background, background );
+static struct background backgrounds_end[0]
+	__table_end ( struct background, background );
 
 /** @file */
 
diff --git a/src/core/console.c b/src/core/console.c
index 830f453..6f55d55 100644
--- a/src/core/console.c
+++ b/src/core/console.c
@@ -6,8 +6,10 @@
 
 #include "bios.h"
 
-static struct console_driver console_drivers[0] __table_start ( console );
-static struct console_driver console_drivers_end[0] __table_end ( console );
+static struct console_driver console_drivers[0]
+	__table_start ( struct console_driver, console );
+static struct console_driver console_drivers_end[0]
+	__table_end ( struct console_driver, console );
 
 /**
  * Write a single character to each console device.
diff --git a/src/core/dev.c b/src/core/dev.c
index 3d1fdd9..541a9eb 100644
--- a/src/core/dev.c
+++ b/src/core/dev.c
@@ -10,10 +10,14 @@
  */
 
 /* Linker symbols for the various tables */
-static struct bus_driver bus_drivers[0] __table_start ( bus_driver );
-static struct bus_driver bus_drivers_end[0] __table_end ( bus_driver );
-static struct device_driver device_drivers[0] __table_start ( device_driver );
-static struct device_driver device_drivers_end[0] __table_end (device_driver );
+static struct bus_driver bus_drivers[0]
+	__table_start ( struct bus_driver, bus_driver );
+static struct bus_driver bus_drivers_end[0]
+	__table_end ( struct bus_driver, bus_driver );
+static struct device_driver device_drivers[0]
+	__table_start ( struct device_driver, device_driver );
+static struct device_driver device_drivers_end[0]
+	__table_end ( struct device_driver, device_driver );
 
 /* Current attempted boot device */
 struct dev dev = {
diff --git a/src/core/device.c b/src/core/device.c
index 567d901..b1b148e 100644
--- a/src/core/device.c
+++ b/src/core/device.c
@@ -28,8 +28,10 @@
  *
  */
 
-static struct root_device root_devices[0] __table_start ( root_devices );
-static struct root_device root_devices_end[0] __table_end ( root_devices );
+static struct root_device root_devices[0]
+	__table_start ( struct root_device, root_devices );
+static struct root_device root_devices_end[0]
+	__table_end ( struct root_device, root_devices );
 
 /** Registered root devices */
 static LIST_HEAD ( devices );
@@ -43,10 +45,10 @@
 static int rootdev_probe ( struct root_device *rootdev ) {
 	int rc;
 
-	DBG ( "Adding %s root bus\n", rootdev->name );
+	DBG ( "Adding %s root bus\n", rootdev->dev.name );
 	if ( ( rc = rootdev->driver->probe ( rootdev ) ) != 0 ) {
 		DBG ( "Failed to add %s root bus: %s\n",
-		      rootdev->name, strerror ( rc ) );
+		      rootdev->dev.name, strerror ( rc ) );
 		return rc;
 	}
 
@@ -60,7 +62,7 @@
  */
 static void rootdev_remove ( struct root_device *rootdev ) {
 	rootdev->driver->remove ( rootdev );
-	DBG ( "Removed %s root bus\n", rootdev->name );
+	DBG ( "Removed %s root bus\n", rootdev->dev.name );
 }
 
 /**
diff --git a/src/core/exec.c b/src/core/exec.c
index 3340d18..61e7339 100644
--- a/src/core/exec.c
+++ b/src/core/exec.c
@@ -33,8 +33,10 @@
  *
  */
 
-static struct command commands[0] __table_start ( commands );
-static struct command commands_end[0] __table_end ( commands );
+static struct command commands[0]
+	__table_start ( struct command, commands );
+static struct command commands_end[0]
+	__table_end ( struct command, commands );
 
 /* Avoid dragging in getopt.o unless a command really uses it */
 int optind;
diff --git a/src/core/init.c b/src/core/init.c
index 3f41ddd..66b428f 100644
--- a/src/core/init.c
+++ b/src/core/init.c
@@ -9,8 +9,10 @@
 
 #include <gpxe/init.h>
 
-static struct init_fn init_fns[0] __table_start(init_fn);
-static struct init_fn init_fns_end[0] __table_end(init_fn);
+static struct init_fn init_fns[0]
+	__table_start ( struct init_fn, init_fn );
+static struct init_fn init_fns_end[0]
+	__table_end ( struct init_fn, init_fn );
 
 void call_init_fns ( void ) {
 	struct init_fn *init_fn;
diff --git a/src/core/resolv.c b/src/core/resolv.c
index 0737294..eb01a30 100644
--- a/src/core/resolv.c
+++ b/src/core/resolv.c
@@ -1,7 +1,9 @@
 #include "resolv.h"
 
-static struct resolver resolvers[0] __table_start(resolver);
-static struct resolver resolvers_end[0] __table_end(resolver);
+static struct resolver resolvers[0]
+	__table_start ( struct resolver, resolver );
+static struct resolver resolvers_end[0]
+	__table_end ( struct resolver, resolver );
 
 /*
  * Resolve a name (which may be just a dotted quad IP address) to an
diff --git a/src/core/settings.c b/src/core/settings.c
index 8009d37..5d36c30 100644
--- a/src/core/settings.c
+++ b/src/core/settings.c
@@ -34,16 +34,16 @@
  */
 
 /** Registered configuration setting types */
-static struct config_setting_type
-config_setting_types[0] __table_start ( config_setting_types );
-static struct config_setting_type
-config_setting_types_end[0] __table_end ( config_setting_types );
+static struct config_setting_type config_setting_types[0]
+	__table_start ( struct config_setting_type, config_setting_types );
+static struct config_setting_type config_setting_types_end[0]
+	__table_end ( struct config_setting_type, config_setting_types );
 
 /** Registered configuration settings */
-static struct config_setting
-config_settings[0] __table_start ( config_settings );
-static struct config_setting
-config_settings_end[0] __table_end ( config_settings );
+static struct config_setting config_settings[0]
+	__table_start ( struct config_setting, config_settings );
+static struct config_setting config_settings_end[0]
+	__table_end ( struct config_setting, config_settings );
 
 /**
  * Find configuration setting type
diff --git a/src/drivers/bus/isa.c b/src/drivers/bus/isa.c
index 7529f1a..d8b88fd 100644
--- a/src/drivers/bus/isa.c
+++ b/src/drivers/bus/isa.c
@@ -45,8 +45,10 @@
  * Symbols defined by linker
  *
  */
-static struct isa_driver isa_drivers[0] __table_start ( isa_driver );
-static struct isa_driver isa_drivers_end[0] __table_end ( isa_driver );
+static struct isa_driver isa_drivers[0]
+	__table_start ( struct isa_driver, isa_driver );
+static struct isa_driver isa_drivers_end[0]
+	__table_end ( struct isa_driver, isa_driver );
 
 /*
  * Increment a bus_loc structure to the next possible ISA location.
diff --git a/src/drivers/bus/pci.c b/src/drivers/bus/pci.c
index e7528e3..11a8e0a 100644
--- a/src/drivers/bus/pci.c
+++ b/src/drivers/bus/pci.c
@@ -23,6 +23,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
+#include <vsprintf.h>
 #include <gpxe/tables.h>
 #include <gpxe/device.h>
 #include <gpxe/pci.h>
@@ -33,8 +34,10 @@
  *
  */
 
-static struct pci_driver pci_drivers[0] __table_start ( pci_drivers );
-static struct pci_driver pci_drivers_end[0] __table_end ( pci_drivers );
+static struct pci_driver pci_drivers[0]
+	__table_start ( struct pci_driver, pci_drivers );
+static struct pci_driver pci_drivers_end[0]
+	__table_end ( struct pci_driver, pci_drivers );
 
 static void pcibus_remove ( struct root_device *rootdev );
 
@@ -194,8 +197,8 @@
 			     ( id->device != pci->device ) )
 				continue;
 			pci->driver = driver;
-			pci->name = id->name;
-			DBG ( "...using driver %s\n", pci->name );
+			pci->driver_name = id->name;
+			DBG ( "...using driver %s\n", pci->driver_name );
 			if ( ( rc = driver->probe ( pci, id ) ) != 0 ) {
 				DBG ( "......probe failed\n" );
 				continue;
@@ -276,6 +279,9 @@
 			pci_read_bases ( pci );
 
 			/* Add to device hierarchy */
+			snprintf ( pci->dev.name, sizeof ( pci->dev.name ),
+				   "PCI%02x:%02x.%x", bus,
+				   PCI_SLOT ( devfn ), PCI_FUNC ( devfn ) );
 			pci->dev.parent = &rootdev->dev;
 			list_add ( &pci->dev.siblings, &rootdev->dev.children);
 			INIT_LIST_HEAD ( &pci->dev.children );
@@ -325,6 +331,6 @@
 
 /** PCI bus root device */
 struct root_device pci_root_device __root_device = {
-	.name = "PCI",
+	.dev = { .name = "PCI" },
 	.driver = &pci_root_driver,
 };
diff --git a/src/drivers/net/dmfe.c b/src/drivers/net/dmfe.c
index 4a4ac7d..7320e90 100644
--- a/src/drivers/net/dmfe.c
+++ b/src/drivers/net/dmfe.c
@@ -457,7 +457,7 @@
 
 	BASE = pci->ioaddr;
 	printf("dmfe.c: Found %s Vendor=0x%hX Device=0x%hX\n",
-	       pci->name, pci->vendor, pci->device);
+	       pci->driver_name, pci->vendor, pci->device);
 
 	/* Read Chip revision */
 	pci_read_config_dword(pci, PCI_REVISION_ID, &dev_rev);
@@ -488,7 +488,7 @@
 		nic->node_addr[i] = db->srom[20 + i];
 
 	/* Print out some hardware info */
-	DBG ( "%s: %s at ioaddr %4.4lx\n", pci->name, eth_ntoa ( nic->node_addr ), BASE );
+	DBG ( "%s: %s at ioaddr %4.4lx\n", pci->driver_name, eth_ntoa ( nic->node_addr ), BASE );
 
 	/* Set the card as PCI Bus Master */
 	adjust_pci_device(pci);
diff --git a/src/drivers/net/forcedeth.c b/src/drivers/net/forcedeth.c
index 67f0c1e..2008c39 100644
--- a/src/drivers/net/forcedeth.c
+++ b/src/drivers/net/forcedeth.c
@@ -1246,7 +1246,7 @@
 		return 0;
 
 	printf("forcedeth.c: Found %s, vendor=0x%hX, device=0x%hX\n",
-	       pci->name, pci->vendor, pci->device);
+	       pci->driver_name, pci->vendor, pci->device);
 
 	pci_fill_nic ( nic, pci );
 
@@ -1306,7 +1306,7 @@
 	}
 #endif
 
-	DBG ( "%s: MAC Address %s\n", pci->name, eth_ntoa ( nic->node_addr ) );
+	DBG ( "%s: MAC Address %s\n", pci->driver_name, eth_ntoa ( nic->node_addr ) );
 
  	/* disable WOL */
 	writel(0, base + NvRegWakeUpFlags);
@@ -1381,7 +1381,7 @@
  		id2 = (id2 & PHYID2_OUI_MASK) >> PHYID2_OUI_SHFT;
  		dprintf
 			(("%s: open: Found PHY %hX:%hX at address %d.\n",
-			  pci->name, id1, id2, i));
+			  pci->driver_name, id1, id2, i));
  		np->phyaddr = i;
  		np->phy_oui = id1 | id2;
  		break;
@@ -1391,7 +1391,7 @@
  		 * test loopback? Very odd, but can be correct.
  		 */
  		printf
-			("%s: open: Could not find a valid PHY.\n", pci->name);
+			("%s: open: Could not find a valid PHY.\n", pci->driver_name);
  	}
 	
  	if (i != 32) {
@@ -1400,7 +1400,7 @@
  	}
 	
 	dprintf(("%s: forcedeth.c: subsystem: %hX:%hX bound to %s\n",
-		 pci->name, pci->vendor, pci->dev_id, pci->name));
+		 pci->driver_name, pci->vendor, pci->dev_id, pci->driver_name));
 	if(!forcedeth_reset(nic)) return 0; // no valid link
 
 	/* point to NIC specific routines */
diff --git a/src/drivers/net/legacy.c b/src/drivers/net/legacy.c
index 091cdcc..73d1d78 100644
--- a/src/drivers/net/legacy.c
+++ b/src/drivers/net/legacy.c
@@ -84,6 +84,7 @@
 	netdev->priv = &nic;
 	memset ( &nic, 0, sizeof ( nic ) );
 	pci_set_drvdata ( pci, netdev );
+	netdev->dev = &pci->dev;
 
 	netdev->open = legacy_open;
 	netdev->close = legacy_close;
diff --git a/src/drivers/net/mtd80x.c b/src/drivers/net/mtd80x.c
index 767aead..d6dc5bc 100644
--- a/src/drivers/net/mtd80x.c
+++ b/src/drivers/net/mtd80x.c
@@ -677,7 +677,7 @@
     pci_fill_nic ( nic, pci );
     adjust_pci_device(pci);
 
-    mtdx.nic_name = pci->name;
+    mtdx.nic_name = pci->driver_name;
     mtdx.dev_id = pci->device;
     mtdx.ioaddr = nic->ioaddr;
 
diff --git a/src/drivers/net/natsemi.c b/src/drivers/net/natsemi.c
index d8b1d20..b58cb67 100644
--- a/src/drivers/net/natsemi.c
+++ b/src/drivers/net/natsemi.c
@@ -262,7 +262,7 @@
     ioaddr     = pci->ioaddr;
     vendor     = pci->vendor;
     dev_id     = pci->device;
-    nic_name   = pci->name;
+    nic_name   = pci->driver_name;
 
     /* natsemi has a non-standard PM control register
      * in PCI config space.  Some boards apparently need
diff --git a/src/drivers/net/ns83820.c b/src/drivers/net/ns83820.c
index d14f670..33358a0 100755
--- a/src/drivers/net/ns83820.c
+++ b/src/drivers/net/ns83820.c
@@ -821,7 +821,7 @@
 		return 0;
 
 	printf("ns83820.c: Found %s, vendor=0x%hX, device=0x%hX\n",
-	       pci->name, pci->vendor, pci->device);
+	       pci->driver_name, pci->vendor, pci->device);
 
 	/* point to private storage */
 	ns = &nsx;
@@ -860,12 +860,12 @@
 	ns->CFG_cache = readl(ns->base + CFG);
 
 	if ((ns->CFG_cache & CFG_PCI64_DET)) {
-		printf("%s: detected 64 bit PCI data bus.\n", pci->name);
+		printf("%s: detected 64 bit PCI data bus.\n", pci->driver_name);
 		/*dev->CFG_cache |= CFG_DATA64_EN; */
 		if (!(ns->CFG_cache & CFG_DATA64_EN))
 			printf
 			    ("%s: EEPROM did not enable 64 bit bus.  Disabled.\n",
-			     pci->name);
+			     pci->driver_name);
 	} else
 		ns->CFG_cache &= ~(CFG_DATA64_EN);
 
@@ -895,7 +895,7 @@
 
 	/* setup optical transceiver if we have one */
 	if (ns->CFG_cache & CFG_TBI_EN) {
-		dprintf(("%s: enabling optical transceiver\n", pci->name));
+		dprintf(("%s: enabling optical transceiver\n", pci->driver_name));
 		writel(readl(ns->base + GPIOR) | 0x3e8, ns->base + GPIOR);
 
 		/* setup auto negotiation feature advertisement */
@@ -916,7 +916,7 @@
 
 	/* FIXME: reset_phy is defaulted to 0, should we reset anyway? */
 	if (reset_phy) {
-		dprintf(("%s: resetting phy\n", pci->name));
+		dprintf(("%s: resetting phy\n", pci->driver_name));
 		writel(ns->CFG_cache | CFG_PHY_RST, ns->base + CFG);
 		writel(ns->CFG_cache, ns->base + CFG);
 	}
@@ -981,11 +981,11 @@
 	ns83820_getmac(nic, nic->node_addr);
 
 	if (using_dac) {
-		dprintf(("%s: using 64 bit addressing.\n", pci->name));
+		dprintf(("%s: using 64 bit addressing.\n", pci->driver_name));
 	}
 
 	dprintf(("%s: DP83820 %d.%d: %! io=0x%hX\n",
-		 pci->name,
+		 pci->driver_name,
 		 (unsigned) readl(ns->base + SRR) >> 8,
 		 (unsigned) readl(ns->base + SRR) & 0xff,
 		 nic->node_addr, pci->ioaddr));
diff --git a/src/drivers/net/pcnet32.c b/src/drivers/net/pcnet32.c
index 179e3ca..8997603 100644
--- a/src/drivers/net/pcnet32.c
+++ b/src/drivers/net/pcnet32.c
@@ -678,7 +678,7 @@
 	/* BASE is used throughout to address the card */
 	ioaddr = pci->ioaddr;
 	printf("pcnet32.c: Found %s, Vendor=0x%hX Device=0x%hX\n",
-	       pci->name, pci->vendor, pci->device);
+	       pci->driver_name, pci->vendor, pci->device);
 
 	nic->irqno  = 0;
 	pci_fill_nic ( nic, pci );
diff --git a/src/drivers/net/pnic.c b/src/drivers/net/pnic.c
index c74e7b5..75d08ac 100644
--- a/src/drivers/net/pnic.c
+++ b/src/drivers/net/pnic.c
@@ -234,6 +234,7 @@
 	}
 	pnic = netdev->priv;
 	pci_set_drvdata ( pci, netdev );
+	netdev->dev = &pci->dev;
 	pnic->ioaddr = pci->ioaddr;
 
 	/* API version check */
diff --git a/src/drivers/net/r8169.c b/src/drivers/net/r8169.c
index 3ec1f09..c806ccd 100644
--- a/src/drivers/net/r8169.c
+++ b/src/drivers/net/r8169.c
@@ -884,7 +884,7 @@
 	int option = -1, Cap10_100 = 0, Cap1000 = 0;
 
 	printf ( "r8169.c: Found %s, Vendor=%hX Device=%hX\n",
-	       pci->name, pci->vendor, pci->device );
+	       pci->driver_name, pci->vendor, pci->device );
 
 	board_idx++;
 
@@ -899,11 +899,11 @@
 	for (i = 0; i < MAC_ADDR_LEN; i++)
 		nic->node_addr[i] = RTL_R8(MAC0 + i);
 
-	DBG ( "%s: Identified chip type is '%s'.\n", pci->name,
+	DBG ( "%s: Identified chip type is '%s'.\n", pci->driver_name,
 		 rtl_chip_info[tpc->chipset].name );
 
 	/* Print out some hardware info */
-	DBG ( "%s: %s at IOAddr %#hX, ", pci->name, eth_ntoa ( nic->node_addr ),
+	DBG ( "%s: %s at IOAddr %#hX, ", pci->driver_name, eth_ntoa ( nic->node_addr ),
 	       ioaddr );
 
 	/* Config PHY */
@@ -965,7 +965,7 @@
 			RTL8169_WRITE_GMII_REG(ioaddr, PHY_1000_CTRL_REG,
 					       Cap1000);
 		} else {
-			DBG ( "%s: Auto-negotiation Enabled.\n",  pci->name );
+			DBG ( "%s: Auto-negotiation Enabled.\n",  pci->driver_name );
 
 			// enable 10/100 Full/Half Mode, leave PHY_AUTO_NEGO_REG bit4:0 unchanged
 			RTL8169_WRITE_GMII_REG(ioaddr, PHY_AUTO_NEGO_REG,
@@ -1016,7 +1016,7 @@
 		udelay(100);
 		printf
 		    ("%s: 1000Mbps Full-duplex operation, TBI Link %s!\n",
-		     pci->name,
+		     pci->driver_name,
 		     (RTL_R32(TBICSR) & TBILinkOK) ? "OK" : "Failed");
 
 	}
diff --git a/src/drivers/net/rtl8139.c b/src/drivers/net/rtl8139.c
index a25755c..08130b2 100644
--- a/src/drivers/net/rtl8139.c
+++ b/src/drivers/net/rtl8139.c
@@ -532,6 +532,7 @@
 	}
 	rtl = netdev->priv;
 	pci_set_drvdata ( pci, netdev );
+	netdev->dev = &pci->dev;
 	memset ( rtl, 0, sizeof ( *rtl ) );
 	rtl->ioaddr = pci->ioaddr;
 
diff --git a/src/drivers/net/sundance.c b/src/drivers/net/sundance.c
index 16272b7..99ba611 100644
--- a/src/drivers/net/sundance.c
+++ b/src/drivers/net/sundance.c
@@ -581,7 +581,7 @@
 	/* BASE is used throughout to address the card */
 	BASE = pci->ioaddr;
 	printf(" sundance.c: Found %s Vendor=0x%hX Device=0x%hX\n",
-	       pci->name, pci->vendor, pci->device);
+	       pci->driver_name, pci->vendor, pci->device);
 
 	/* Get the MAC Address by reading the EEPROM */
 	for (i = 0; i < 3; i++) {
@@ -603,7 +603,7 @@
 	/* point to private storage */
 	sdc = &sdx;
 
-	sdc->nic_name = pci->name;
+	sdc->nic_name = pci->driver_name;
 	sdc->mtu = mtu;
 
 	pci_read_config_byte(pci, PCI_REVISION_ID, &sdc->pci_rev_id);
@@ -611,7 +611,7 @@
 	DBG ( "Device revision id: %hx\n", sdc->pci_rev_id );
 
 	/* Print out some hardware info */
-	DBG ( "%s: %s at ioaddr %hX, ", pci->name, nic->node_addr, BASE);
+	DBG ( "%s: %s at ioaddr %hX, ", pci->driver_name, nic->node_addr, BASE);
 
 	sdc->mii_preamble_required = 0;
 	if (1) {
diff --git a/src/drivers/net/tlan.c b/src/drivers/net/tlan.c
index e1ff564..1059320 100644
--- a/src/drivers/net/tlan.c
+++ b/src/drivers/net/tlan.c
@@ -809,7 +809,7 @@
 
 	priv->vendor_id = pci->vendor;
 	priv->dev_id = pci->device;
-	priv->nic_name = pci->name;
+	priv->nic_name = pci->driver_name;
 	priv->eoc = 0;
 
 	err = 0;
@@ -820,10 +820,10 @@
 				       (u8 *) & nic->node_addr[i]);
 	if (err) {
   	    printf ( "TLAN: %s: Error reading MAC from eeprom: %d\n",
-		    pci->name, err);
+		    pci->driver_name, err);
 	} else {
 	    DBG ( "%s: %s at ioaddr %#lX, ", 
-		  pci->name, eth_ntoa ( nic->node_addr ), pci->ioaddr );
+		  pci->driver_name, eth_ntoa ( nic->node_addr ), pci->ioaddr );
 	}
 
 	priv->tlanRev = TLan_DioRead8(BASE, TLAN_DEF_REVISION);
diff --git a/src/drivers/net/tulip.c b/src/drivers/net/tulip.c
index f5fdbaa..4b52584 100644
--- a/src/drivers/net/tulip.c
+++ b/src/drivers/net/tulip.c
@@ -1252,7 +1252,7 @@
 
     tp->vendor_id  = pci->vendor;
     tp->dev_id     = pci->device;
-    tp->nic_name   = pci->name;
+    tp->nic_name   = pci->driver_name;
 
     tp->if_port = 0;
     tp->default_port = 0;
diff --git a/src/drivers/net/via-velocity.c b/src/drivers/net/via-velocity.c
index 78a45ca..740cc30 100644
--- a/src/drivers/net/via-velocity.c
+++ b/src/drivers/net/via-velocity.c
@@ -673,7 +673,7 @@
 	struct mac_regs *regs;
 
 	printf("via-velocity.c: Found %s Vendor=0x%hX Device=0x%hX\n",
-	       pci->name, pci->vendor, pci->device);
+	       pci->driver_name, pci->vendor, pci->device);
 
 	/* point to private storage */
 	vptr = &vptx;
@@ -705,9 +705,9 @@
 	for (i = 0; i < 6; i++)
 		nic->node_addr[i] = readb(&regs->PAR[i]);
 
-	DBG ( "%s: %s at ioaddr %#hX\n", pci->name, eth_ntoa ( nic->node_addr ), BASE );
+	DBG ( "%s: %s at ioaddr %#hX\n", pci->driver_name, eth_ntoa ( nic->node_addr ), BASE );
 
-	velocity_get_options(&vptr->options, 0, pci->name);
+	velocity_get_options(&vptr->options, 0, pci->driver_name);
 
 	/* 
 	 *      Mask out the options cannot be set to the chip
diff --git a/src/hci/shell.c b/src/hci/shell.c
index 2a9bfca..95662b5 100644
--- a/src/hci/shell.c
+++ b/src/hci/shell.c
@@ -29,8 +29,10 @@
  *
  */
 
-static struct command commands[0] __table_start ( commands );
-static struct command commands_end[0] __table_end ( commands );
+static struct command commands[0]
+	__table_start ( struct command, commands );
+static struct command commands_end[0]
+	__table_end ( struct command, commands );
 
 /** The shell prompt string */
 static const char shell_prompt[] = "gPXE> ";
diff --git a/src/hci/strerror.c b/src/hci/strerror.c
index b012ccc..fbaf52a 100644
--- a/src/hci/strerror.c
+++ b/src/hci/strerror.c
@@ -18,8 +18,10 @@
  *
  */
 
-static struct errortab errortab_start[0] __table_start(errortab);
-static struct errortab errortab_end[0] __table_end(errortab);
+static struct errortab errortab_start[0]
+	__table_start ( struct errortab, errortab );
+static struct errortab errortab_end[0]
+	__table_end ( struct errortab, errortab );
 
 /**
  * Retrieve string representation of error number.
diff --git a/src/hci/tui/settings_ui.c b/src/hci/tui/settings_ui.c
index 7be6f91..112eade 100644
--- a/src/hci/tui/settings_ui.c
+++ b/src/hci/tui/settings_ui.c
@@ -81,10 +81,10 @@
 };
 
 /** Registered configuration settings */
-static struct config_setting
-config_settings[0] __table_start ( config_settings );
-static struct config_setting
-config_settings_end[0] __table_end ( config_settings );
+static struct config_setting config_settings[0]
+	__table_start ( struct config_setting, config_settings );
+static struct config_setting config_settings_end[0]
+	__table_end ( struct config_setting, config_settings );
 #define NUM_SETTINGS ( ( unsigned ) ( config_settings_end - config_settings ) )
 
 /**
diff --git a/src/include/background.h b/src/include/background.h
index 40706cd..6f39d39 100644
--- a/src/include/background.h
+++ b/src/include/background.h
@@ -40,7 +40,7 @@
 };
 
 /** A member of the background protocols table */
-#define __background __table ( background, 01 )
+#define __background __table ( struct background, background, 01 )
 
 /* Functions in background.c */
 
diff --git a/src/include/console.h b/src/include/console.h
index 78bbf5d..f38d4ec 100644
--- a/src/include/console.h
+++ b/src/include/console.h
@@ -93,7 +93,7 @@
  * @endcode
  *
  */
-#define __console_driver __table ( console, 01 )
+#define __console_driver __table ( struct console_driver, console, 01 )
 
 /* Function prototypes */
 
diff --git a/src/include/dev.h b/src/include/dev.h
index 6edfc63..77452ad 100644
--- a/src/include/dev.h
+++ b/src/include/dev.h
@@ -155,7 +155,7 @@
 	const char * ( *name_device ) ( struct bus_dev *bus_dev );
 };
 
-#define __bus_driver __table ( bus_driver, 01 )
+#define __bus_driver __table ( struct bus_driver, bus_driver, 01 )
 
 /*
  * A structure fully describing the bus-independent parts of a
@@ -181,7 +181,7 @@
 	int ( * load ) ( struct type_dev *type_dev, struct buffer *buffer );
 };
 
-#define __type_driver __table ( type_driver, 01 )
+#define __type_driver __table ( struct type_driver, type_driver, 01 )
 
 /*
  * A driver for a device.
@@ -198,7 +198,7 @@
 			     struct bus_dev *bus_dev );
 };
 
-#define __device_driver __table ( device_driver, 01 )
+#define __device_driver __table ( struct device_driver, device_driver, 01 )
 
 #if 0
 #define DRIVER(_name,_type_driver,_bus_driver,_bus_info,	 	      \
diff --git a/src/include/gpxe/arp.h b/src/include/gpxe/arp.h
index 8ff1cff..1c702b0 100644
--- a/src/include/gpxe/arp.h
+++ b/src/include/gpxe/arp.h
@@ -27,7 +27,8 @@
 };
 
 /** Declare an ARP protocol */
-#define __arp_net_protocol __table ( arp_net_protocols, 01 )
+#define __arp_net_protocol \
+	__table ( struct arp_net_protocol, arp_net_protocols, 01 )
 
 extern int arp_resolve ( struct net_device *netdev,
 			 struct net_protocol *net_protocol,
diff --git a/src/include/gpxe/command.h b/src/include/gpxe/command.h
index 95f6c5e..5d8057a 100644
--- a/src/include/gpxe/command.h
+++ b/src/include/gpxe/command.h
@@ -17,6 +17,6 @@
 	int ( * exec ) ( int argc, char **argv );
 };
 
-#define __command __table ( commands, 01 )
+#define __command __table ( struct command, commands, 01 )
 
 #endif /* _GPXE_COMMAND_H */
diff --git a/src/include/gpxe/device.h b/src/include/gpxe/device.h
index 43bbf60..9f670cf 100644
--- a/src/include/gpxe/device.h
+++ b/src/include/gpxe/device.h
@@ -13,6 +13,8 @@
 
 /** A hardware device */
 struct device {
+	/** Name */
+	char name[16];
 	/** Devices on the same bus */
 	struct list_head siblings;
 	/** Devices attached to this device */
@@ -28,8 +30,6 @@
  *
  */
 struct root_device {
-	/** Name */
-	const char *name;
 	/** Device chain
 	 *
 	 * A root device has a NULL parent field.
@@ -62,7 +62,7 @@
 };
 
 /** Declare a root device */
-#define __root_device __table ( root_devices, 01 )
+#define __root_device __table ( struct root_device, root_devices, 01 )
 
 extern int probe_devices ( void );
 extern void remove_devices ( void );
diff --git a/src/include/gpxe/errortab.h b/src/include/gpxe/errortab.h
index 1ca7fe5..470f7e7 100644
--- a/src/include/gpxe/errortab.h
+++ b/src/include/gpxe/errortab.h
@@ -15,6 +15,6 @@
 	const char *text;
 };
 
-#define __errortab __table ( errortab, 01 )
+#define __errortab __table ( struct errortab, errortab, 01 )
 
 #endif /* _GPXE_ERRORTAB_H */
diff --git a/src/include/gpxe/init.h b/src/include/gpxe/init.h
index 3881da4..0a2eb0b 100644
--- a/src/include/gpxe/init.h
+++ b/src/include/gpxe/init.h
@@ -46,7 +46,7 @@
 /* Macro for creating an initialisation function table entry */
 #define INIT_FN( init_order, init_func, reset_func, exit_func )	\
 	struct init_fn PREFIX_OBJECT(init_fn__)			\
-	    __table ( init_fn, init_order ) = {			\
+	    __table ( struct init_fn, init_fn, init_order ) = {	\
 		.init = init_func,				\
 		.reset = reset_func,				\
 		.exit = exit_func,				\
diff --git a/src/include/gpxe/netdevice.h b/src/include/gpxe/netdevice.h
index e1dddd6..b029d16 100644
--- a/src/include/gpxe/netdevice.h
+++ b/src/include/gpxe/netdevice.h
@@ -16,6 +16,7 @@
 struct net_device;
 struct net_protocol;
 struct ll_protocol;
+struct device;
 
 /** Maximum length of a link-layer address */
 #define MAX_LL_ADDR_LEN 6
@@ -140,6 +141,8 @@
 	struct list_head list;
 	/** Name of this network device */
 	char name[8];
+	/** Underlying hardware device */
+	struct device *dev;
 	/** List of persistent reference holders */
 	struct list_head references;
 
@@ -219,10 +222,10 @@
 #define NETDEV_OPEN 0x0001
 
 /** Declare a link-layer protocol */
-#define __ll_protocol  __table ( ll_protocols, 01 )
+#define __ll_protocol  __table ( struct ll_protocol, ll_protocols, 01 )
 
 /** Declare a network-layer protocol */
-#define __net_protocol __table ( net_protocols, 01 )
+#define __net_protocol __table ( struct net_protocol, net_protocols, 01 )
 
 extern struct list_head net_devices;
 
diff --git a/src/include/gpxe/pci.h b/src/include/gpxe/pci.h
index a27d6f1..8269dfa 100644
--- a/src/include/gpxe/pci.h
+++ b/src/include/gpxe/pci.h
@@ -277,8 +277,8 @@
 	 * field.
 	 */
 	void *priv;
-	/** Device name */
-	const char *name;
+	/** Driver name */
+	const char *driver_name;
 };
 
 /** A PCI driver */
@@ -305,7 +305,7 @@
 };
 
 /** Declare a PCI driver */
-#define __pci_driver __table ( pci_drivers, 01 )
+#define __pci_driver __table ( struct pci_driver, pci_drivers, 01 )
 
 #define PCI_DEVFN( slot, func )	( ( (slot) << 3 ) | (func) )
 #define PCI_SLOT( devfn )	( ( (devfn) >> 3 ) & 0x1f )
diff --git a/src/include/gpxe/settings.h b/src/include/gpxe/settings.h
index d5be524..f30bbfb 100644
--- a/src/include/gpxe/settings.h
+++ b/src/include/gpxe/settings.h
@@ -66,7 +66,8 @@
 };
 
 /** Declare a configuration setting type */
-#define	__config_setting_type __table ( config_setting_types, 01 )
+#define	__config_setting_type \
+	__table ( struct config_setting_type, config_setting_types, 01 )
 
 /**
  * A configuration setting
@@ -98,7 +99,7 @@
 };
 
 /** Declare a configuration setting */
-#define	__config_setting __table ( config_settings, 01 )
+#define	__config_setting __table ( struct config_setting, config_settings, 01 )
 
 /**
  * Show value of setting
diff --git a/src/include/gpxe/tables.h b/src/include/gpxe/tables.h
index 385bb52..b2c56ab 100644
--- a/src/include/gpxe/tables.h
+++ b/src/include/gpxe/tables.h
@@ -165,16 +165,17 @@
  */
 
 #ifdef DOXYGEN
-#define __attribute__(x)
+#define __attribute__( x )
 #endif
 
-#define __table_str(x) #x
-#define __table_section(table,idx) \
-	__section__ ( ".tbl." __table_str(table) "." __table_str(idx) )
+#define __table_str( x ) #x
+#define __table_section( table, idx ) \
+	__section__ ( ".tbl." __table_str ( table ) "." __table_str ( idx ) )
 
-#define __table_section_start(table) __table_section(table,00)
-#define __table_section_end(table) __table_section(table,99)
+#define __table_section_start( table ) __table_section ( table, 00 )
+#define __table_section_end( table ) __table_section ( table, 99 )
 
+#define __natural_alignment( type ) __aligned__ ( __alignof__ ( type ) )
 
 /**
  * Linker table entry.
@@ -191,8 +192,9 @@
  * @endcode
  *
  */
-#define __table(table,idx) \
-	__attribute__ (( __table_section(table,idx) ))
+#define __table( type, table, idx )				\
+	__attribute__ (( __table_section ( table, idx ),	\
+			 __natural_alignment ( type ) ))
 
 /**
  * Linker table start marker.
@@ -207,8 +209,7 @@
  * @endcode
  *
  */
-#define __table_start(table) \
-	__attribute__ (( __table_section_start(table) ))
+#define __table_start( type, table ) __table ( type, table, 00 )
 
 /**
  * Linker table end marker.
@@ -223,7 +224,6 @@
  * @endcode
  *
  */
-#define __table_end(table) \
-	__attribute__ (( __table_section_end(table) ))
+#define __table_end( type, table ) __table ( type, table, 99 )
 
 #endif /* _GPXE_TABLES_H */
diff --git a/src/include/gpxe/tcpip.h b/src/include/gpxe/tcpip.h
index 1fdb8b7..2508d5f 100644
--- a/src/include/gpxe/tcpip.h
+++ b/src/include/gpxe/tcpip.h
@@ -99,10 +99,12 @@
 };
 
 /** Declare a TCP/IP transport-layer protocol */
-#define	__tcpip_protocol __table ( tcpip_protocols, 01 )
+#define	__tcpip_protocol \
+	__table ( struct tcpip_protocol, tcpip_protocols, 01 )
 
 /** Declare a TCP/IP network-layer protocol */
-#define	__tcpip_net_protocol __table ( tcpip_net_protocols, 01 )
+#define	__tcpip_net_protocol \
+	__table ( struct tcpip_net_protocol, tcpip_net_protocols, 01 )
 
 extern int tcpip_rx ( struct pk_buff *pkb, uint8_t tcpip_proto,
 		      struct sockaddr_tcpip *st_src,
diff --git a/src/include/image.h b/src/include/image.h
index 3483fe0..b86f324 100644
--- a/src/include/image.h
+++ b/src/include/image.h
@@ -13,10 +13,10 @@
 	int ( * boot ) ( void *context );
 };
 
-#define __image_start		__table_start(image)
-#define __image			__table(image,01)
-#define __default_image		__table(image,02)
-#define __image_end		__table_end(image)
+#define __image_start		__table_start ( struct image, image )
+#define __image			__table ( struct image, image, 01 )
+#define __default_image		__table ( struct image, image, 02 )
+#define __image_end		__table_end ( struct image, image )
 
 /* Functions in image.c */
 
diff --git a/src/include/isa.h b/src/include/isa.h
index eacbb8e..3726561 100644
--- a/src/include/isa.h
+++ b/src/include/isa.h
@@ -54,7 +54,7 @@
  *
  */
 #define ISA_DRIVER( _name, _probe_addrs, _probe_addr, _mfg_id, _prod_id )   \
-struct isa_driver _name __table(isa_driver,01 ) = {			    \
+struct isa_driver _name __table ( struct isa_driver, isa_driver, 01 ) = {   \
 	.probe_addrs = _probe_addrs,					    \
 	.addr_count = sizeof ( _probe_addrs ) / sizeof ( _probe_addrs[0] ), \
 	.probe_addr = _probe_addr,					    \
diff --git a/src/include/proto.h b/src/include/proto.h
index 7bceef9..c16229e 100644
--- a/src/include/proto.h
+++ b/src/include/proto.h
@@ -18,11 +18,11 @@
  * should use __protocol.
  *
  */
-#define __protocol_start		__table_start(protocol)
-#define __protocol			__table(protocol,01)
-#define __default_protocol_start	__table(protocol,02)
-#define __default_protocol		__table(protocol,03)
-#define __protocol_end			__table_end(protocol)
+#define __protocol_start	 __table_start ( struct protocol, protocol )
+#define __protocol		 __table ( struct protocol, protocol, 01 )
+#define __default_protocol_start __table ( struct protocol, protocol, 02 )
+#define __default_protocol	 __table ( struct protocol, protocol, 03 )
+#define __protocol_end		 __table_end ( struct protocol, protocol )
 
 /*
  * Functions in proto.c
diff --git a/src/include/resolv.h b/src/include/resolv.h
index e97fd1e..714d39e 100644
--- a/src/include/resolv.h
+++ b/src/include/resolv.h
@@ -9,7 +9,7 @@
 	int ( * resolv ) ( struct in_addr *address, const char *name );
 };
 
-#define __resolver __table(resolver,01)
+#define __resolver __table ( struct resolver, resolver, 01 )
 
 extern int resolv ( struct in_addr *address, const char *name );
 
diff --git a/src/net/arp.c b/src/net/arp.c
index fea81d7..897906b 100644
--- a/src/net/arp.c
+++ b/src/net/arp.c
@@ -38,9 +38,9 @@
 
 /** Registered ARP protocols */
 static struct arp_net_protocol arp_net_protocols[0]
-	__table_start ( arp_net_protocols );
+	__table_start ( struct arp_net_protocol, arp_net_protocols );
 static struct arp_net_protocol arp_net_protocols_end[0]
-	__table_end ( arp_net_protocols );
+	__table_end ( struct arp_net_protocol, arp_net_protocols );
 
 /** An ARP cache entry */
 struct arp_entry {
diff --git a/src/net/netdevice.c b/src/net/netdevice.c
index 8c95afd..d8de81b 100644
--- a/src/net/netdevice.c
+++ b/src/net/netdevice.c
@@ -27,6 +27,7 @@
 #include <gpxe/tables.h>
 #include <gpxe/process.h>
 #include <gpxe/init.h>
+#include <gpxe/device.h>
 #include <gpxe/netdevice.h>
 
 /** @file
@@ -36,8 +37,10 @@
  */
 
 /** Registered network-layer protocols */
-static struct net_protocol net_protocols[0] __table_start ( net_protocols );
-static struct net_protocol net_protocols_end[0] __table_end ( net_protocols );
+static struct net_protocol net_protocols[0]
+	__table_start ( struct net_protocol, net_protocols );
+static struct net_protocol net_protocols_end[0]
+	__table_end ( struct net_protocol, net_protocols );
 
 /** List of network devices */
 struct list_head net_devices = LIST_HEAD_INIT ( net_devices );
@@ -200,8 +203,9 @@
 
 	/* Add to device list */
 	list_add_tail ( &netdev->list, &net_devices );
-	DBGC ( netdev, "NETDEV %p registered as %s (%s)\n",
-	       netdev, netdev->name, netdev_hwaddr ( netdev ) );
+	DBGC ( netdev, "NETDEV %p registered as %s (phys %s hwaddr %s)\n",
+	       netdev, netdev->name, netdev->dev->name,
+	       netdev_hwaddr ( netdev ) );
 
 	return 0;
 }
diff --git a/src/net/tcpip.c b/src/net/tcpip.c
index eec9ee9..00f81cd 100644
--- a/src/net/tcpip.c
+++ b/src/net/tcpip.c
@@ -15,16 +15,16 @@
  */
 
 /** Registered network-layer protocols that support TCP/IP */
-static struct tcpip_net_protocol
-tcpip_net_protocols[0] __table_start ( tcpip_net_protocols );
-static struct tcpip_net_protocol
-tcpip_net_protocols_end[0] __table_end ( tcpip_net_protocols );
+static struct tcpip_net_protocol tcpip_net_protocols[0]
+	__table_start ( struct tcpip_net_protocol, tcpip_net_protocols );
+static struct tcpip_net_protocol tcpip_net_protocols_end[0]
+	__table_end ( struct tcpip_net_protocol, tcpip_net_protocols );
 
 /** Registered transport-layer protocols that support TCP/IP */
-static struct tcpip_protocol
-tcpip_protocols[0]__table_start ( tcpip_protocols );
-static struct tcpip_protocol
-tcpip_protocols_end[0] __table_end ( tcpip_protocols );
+static struct tcpip_protocol tcpip_protocols[0]
+	__table_start ( struct tcpip_protocol, tcpip_protocols );
+static struct tcpip_protocol tcpip_protocols_end[0]
+	__table_end ( struct tcpip_protocol, tcpip_protocols );
 
 /** Process a received TCP/IP packet
  *
diff --git a/src/usr/ifmgmt.c b/src/usr/ifmgmt.c
index 3268416..7b9d847 100644
--- a/src/usr/ifmgmt.c
+++ b/src/usr/ifmgmt.c
@@ -19,6 +19,7 @@
 #include <string.h>
 #include <vsprintf.h>
 #include <gpxe/netdevice.h>
+#include <gpxe/device.h>
 #include <usr/ifmgmt.h>
 
 /** @file
@@ -60,7 +61,7 @@
  * @v netdev		Network device
  */
 void ifstat ( struct net_device *netdev ) {
-	printf ( "%s %s %s\n",
-		 netdev->name, netdev_hwaddr ( netdev ),
+	printf ( "%s: %s on %s (%s)\n",
+		 netdev->name, netdev_hwaddr ( netdev ), netdev->dev->name,
 		 ( ( netdev->state & NETDEV_OPEN ) ? "open" : "closed" ) );
 }