Bug#594967: Bug #594967: [poulsbo] grub-pc Hangs After "Welcome to GRUB!"

Colin Watson cjwatson at debian.org
Mon Jan 3 11:48:27 UTC 2011


On Mon, Jan 03, 2011 at 11:04:17AM +0000, Steve McIntyre wrote:
> On Mon, Jan 03, 2011 at 12:13:01AM +0000, Colin Watson wrote:
> >Whoops, I forgot to right-shift the header word.  Can you try 4.iso
> >instead, at the same location?  I also made it handle PCI-to-CardBus
> >bridges the same way as PCI-to-PCI bridges since that's what pciutils
> >does.
> >
> >(In addition to 'set debug=pci', I'd recommend also doing 'set pager=1'
> >so that lspci's output will be paged.)
> 
> 4.iso:
> 
>   grub> set debug=pci
>   grub> set pager=1
>   grub> lspci
>   bus/pci.c:92: bus 0x0
>   00:00.0 8086:8100 [0600] Host Bridge
>   00:02.0 8086:8108 [0300] VGA Controller
>   00:1b.0 8086:811b [0403] Multimedia device
>   bus/pci.c:143: bridge range 0x2-0x2
>   00:1c.0 8086:8110 [0604] PCI-PCI Bridge
>   bus/pci.c:143: bridge range 0x3-0x3
>   00:1c.1 8086:8112 [0604] PCI-PCI Bridge
>   00:1d.0 8086:8114 [0c03] USB Controller
>   00:1d.1 8086:8115 [0c03] USB Controller
>   00:1d.2 8086:8116 [0c03] USB Controller
>   00:1d.7 8086:8117 [0c03] USB Controller [PI 20]
>   00:1f.0 8086:8119 [0601] ISA Bridge
>   00:1f.1 8086:811a [0101] IDE Controller [PI 80]
>   bus/pci.c:92: bus 0x2
>   02:00.0 10ec:8136 [0200] Ethernet Controller
>   bus/pci.c:92: bus 0x3
>   03:00.0 168c:001c [0200] Ethernet Controller
>   grub>

This looks right to me.  Excellent.  Vladimir, how does this patch look,
on top of my previous one?  (This is edited slightly relative to what
Steve tested, to make sure that the bus number never overflows
bus_present; this will never happen on x86 but might happen on other
architectures.  I've smoke-tested this change.)

2011-01-03  Colin Watson  <cjwatson at ubuntu.com>

	* grub-core/bus/pci.c (grub_pci_iterate): Only scan bus 0 plus any
	buses linked by PCI-to-PCI or PCI-to-CardBus bridges.
	* include/grub/pci.h: Add definitions for bridges.

=== modified file 'grub-core/bus/pci.c'
--- grub-core/bus/pci.c	2010-06-30 00:30:05 +0000
+++ grub-core/bus/pci.c	2011-01-03 00:05:27 +0000
@@ -20,6 +20,7 @@
 #include <grub/dl.h>
 #include <grub/pci.h>
 #include <grub/mm.h>
+#include <grub/misc.h>
 
 /* FIXME: correctly support 64-bit architectures.  */
 /* #if GRUB_TARGET_SIZEOF_VOID_P == 4 */
@@ -78,9 +79,18 @@ grub_pci_iterate (grub_pci_iteratefunc_t
   grub_pci_address_t addr;
   grub_pci_id_t id;
   grub_uint32_t hdr;
+  grub_uint8_t bus_present[(GRUB_PCI_NUM_BUS + 7) / 8];
+
+  grub_memset (bus_present, 0, sizeof (bus_present));
+  bus_present[0] = 1; /* bus 0 is always enabled */
 
   for (dev.bus = 0; dev.bus < GRUB_PCI_NUM_BUS; dev.bus++)
     {
+      if (!(bus_present[dev.bus / 8] & (1 << (dev.bus % 8))))
+	continue;
+
+      grub_dprintf ("pci", "bus 0x%x\n", dev.bus);
+
       for (dev.device = 0; dev.device < GRUB_PCI_NUM_DEVICES; dev.device++)
 	{
 	  for (dev.function = 0; dev.function < 8; dev.function++)
@@ -112,6 +119,38 @@ grub_pci_iterate (grub_pci_iteratefunc_t
 		continue;
 #endif
 
+	      /* On bus 0, look for PCI-to-PCI bridges and mark all buses
+	         within their ranges as present.  */
+	      if (dev.bus == 0)
+		{
+		  addr = grub_pci_make_address (dev, GRUB_PCI_REG_CACHELINE);
+		  hdr = grub_pci_read (addr);
+
+		  switch ((hdr >> 16) & 0x7F) {
+		    case GRUB_PCI_HEADER_PCI_BRIDGE:
+		    case GRUB_PCI_HEADER_CARDBUS_BRIDGE:
+		      {
+			grub_uint32_t bus_numbers;
+			grub_uint32_t secondary, subordinate, i;
+
+			addr = grub_pci_make_address
+			  (dev, GRUB_PCI_REG_SEC_LAT_TIMER);
+			bus_numbers = grub_pci_read (addr);
+			secondary = (bus_numbers >> 8) & 0xFF;
+			subordinate = (bus_numbers >> 16) & 0xFF;
+
+			grub_dprintf ("pci", "bridge range 0x%x-0x%x\n",
+				      secondary, subordinate);
+
+			for (i = secondary;
+			     i <= subordinate && i < GRUB_PCI_NUM_BUS; i++)
+			  bus_present[i / 8] |= (1 << (i % 8));
+
+			break;
+		      }
+		  }
+		}
+
 	      if (hook (dev, id))
 		return;
 

=== modified file 'include/grub/pci.h'
--- include/grub/pci.h	2010-08-11 02:18:07 +0000
+++ include/grub/pci.h	2011-01-02 17:32:28 +0000
@@ -68,6 +68,24 @@
 #define  GRUB_PCI_REG_MIN_GNT      0x3e
 #define  GRUB_PCI_REG_MAX_LAT      0x3f
 
+/* Alternative register meanings if header type is 1 (PCI-to-PCI bridge).  */
+#define  GRUB_PCI_REG_SEC_LAT_TIMER     0x18
+#define  GRUB_PCI_REG_SUB_BUS_NUMBER    0x19
+#define  GRUB_PCI_REG_SEC_BUS_NUMBER    0x1a
+#define  GRUB_PCI_REG_PRI_BUS_NUMBER    0x1b
+#define  GRUB_PCI_REG_SEC_STATUS        0x1c
+#define  GRUB_PCI_REG_IO_LIMIT          0x1e
+#define  GRUB_PCI_REG_IO_BASE           0x1f
+#define  GRUB_PCI_REG_MEM_LIMIT         0x20
+#define  GRUB_PCI_REG_MEM_BASE          0x22
+#define  GRUB_PCI_REG_PF_MEM_LIMIT      0x24
+#define  GRUB_PCI_REG_PF_MEM_BASE       0x26
+#define  GRUB_PCI_REG_PF_MEM_BASE_HI    0x28
+#define  GRUB_PCI_REG_PF_MEM_LIMIT_HI   0x2c
+#define  GRUB_PCI_REG_IO_LIMIT_HI       0x30
+#define  GRUB_PCI_REG_IO_BASE_HI        0x32
+#define  GRUB_PCI_REG_BRIDGE_CONTROL    0x3c
+
 #define  GRUB_PCI_COMMAND_IO_ENABLED    0x0001
 #define  GRUB_PCI_COMMAND_MEM_ENABLED   0x0002
 #define  GRUB_PCI_COMMAND_BUS_MASTER    0x0004
@@ -82,6 +100,10 @@
 #define  GRUB_PCI_STATUS_DEVSEL_TIMING_MASK 0x0600
 #define  GRUB_PCI_CLASS_SUBCLASS_VGA  0x0300
 
+#define  GRUB_PCI_HEADER_GENERAL        0x0
+#define  GRUB_PCI_HEADER_PCI_BRIDGE     0x1
+#define  GRUB_PCI_HEADER_CARDBUS_BRIDGE 0x2
+
 #ifndef ASM_FILE
 typedef grub_uint32_t grub_pci_id_t;
 

Thanks,

-- 
Colin Watson                                       [cjwatson at debian.org]





More information about the Pkg-grub-devel mailing list