hvmloader: Pass BDF to PCI option ROMs.
authorKeir Fraser <keir.fraser@citrix.com>
Mon, 24 Nov 2008 13:57:48 +0000 (13:57 +0000)
committerKeir Fraser <keir.fraser@citrix.com>
Mon, 24 Nov 2008 13:57:48 +0000 (13:57 +0000)
Signed-off-by: Shan Haitao <Haitao.shan@intel.com>
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
tools/firmware/hvmloader/hvmloader.c
tools/firmware/rombios/rombios.c

index 5f5620070cf3440be215ecd0d8df7d8a1cc76d5d..ec066cbf685ed415c8dcdf74cb68d01b912d07ab 100644 (file)
@@ -323,13 +323,14 @@ static void pci_setup(void)
 
 /*
  * Scan the list of Option ROMs at @roms for one which supports 
- * PCI (@vendor_id, @device_id). If one is found, copy it to @dest and
- * return its size rounded up to a multiple 2kB. This function will not
- * copy ROMs beyond address 0xE0000.
+ * PCI (@vendor_id, @device_id) found at slot @devfn. If one is found,
+ * copy it to @dest and return its size rounded up to a multiple 2kB. This
+ * function will not copy ROMs beyond address 0xE0000.
  */
 #define round_option_rom(x) (((x) + 2047) & ~2047)
 static int scan_option_rom(
-    uint16_t vendor_id, uint16_t device_id, void *roms, uint32_t dest)
+    uint8_t devfn, uint16_t vendor_id, uint16_t device_id,
+    void *roms, uint32_t dest)
 {
     struct option_rom_header *rom;
     struct option_rom_pnp_header *pnph;
@@ -395,7 +396,7 @@ static int scan_option_rom(
         printf(" - Product name: %s\n",
                (char *)rom + pnph->product_name_offset);
 
-    if ( (dest + rom->rom_size * 512) > 0xe0000u )
+    if ( (dest + rom->rom_size * 512 + 1) > 0xe0000u )
     {
         printf("Option ROM size %x exceeds available space\n",
                rom->rom_size * 512);
@@ -404,7 +405,8 @@ static int scan_option_rom(
 
     orom_ids[nr_roms++] = vendor_id | ((uint32_t)device_id << 16);
     memcpy((void *)dest, rom, rom->rom_size * 512);
-    return round_option_rom(rom->rom_size * 512);
+    *(uint8_t *)(dest + rom->rom_size * 512) = devfn;
+    return round_option_rom(rom->rom_size * 512 + 1);
 }
 
 /*
@@ -414,7 +416,7 @@ static int scan_option_rom(
  */
 static int scan_etherboot_nic(uint32_t copy_rom_dest)
 {
-    uint32_t devfn;
+    uint8_t devfn;
     uint16_t class, vendor_id, device_id;
 
     for ( devfn = 0; devfn < 128; devfn++ )
@@ -428,7 +430,7 @@ static int scan_etherboot_nic(uint32_t copy_rom_dest)
              (device_id != 0xffff) &&
              (class == 0x0200) )
             return scan_option_rom(
-                vendor_id, device_id, etherboot, copy_rom_dest);
+                devfn, vendor_id, device_id, etherboot, copy_rom_dest);
     }
 
     return 0;
@@ -440,9 +442,9 @@ static int scan_etherboot_nic(uint32_t copy_rom_dest)
  */
 static int pci_load_option_roms(uint32_t rom_base_addr)
 {
-    uint32_t devfn, option_rom_addr, rom_phys_addr = rom_base_addr;
+    uint32_t option_rom_addr, rom_phys_addr = rom_base_addr;
     uint16_t vendor_id, device_id;
-    uint8_t class;
+    uint8_t devfn, class;
 
     for ( devfn = 0; devfn < 128; devfn++ )
     {
@@ -468,8 +470,8 @@ static int pci_load_option_roms(uint32_t rom_base_addr)
         pci_writel(devfn, PCI_ROM_ADDRESS, option_rom_addr | 0x1);
 
         rom_phys_addr += scan_option_rom(
-            vendor_id, device_id, (void *)(option_rom_addr & ~2047),
-            rom_phys_addr);
+            devfn, vendor_id, device_id,
+            (void *)(option_rom_addr & ~2047), rom_phys_addr);
 
         /* Restore the default original value of Expansion Bar */
         pci_writel(devfn, PCI_ROM_ADDRESS, option_rom_addr);
index 0edd37176567fecd3e6c89224fcfa97c670c435d..05ee9875c6ca491087484509bcb9396def214f33 100644 (file)
@@ -9677,20 +9677,35 @@ block_count_rounded:
   pop ds
   pop ax
 #endif
-  xor  bx, bx   ;; Restore DS back to 0000:
-  mov  ds, bx
   push ax       ;; Save AX
   push di       ;; Save DI
   ;; Push addr of ROM entry point
   push cx       ;; Push seg
   push #0x0003  ;; Push offset
 
+  ;; Get the BDF into ax before invoking the option ROM
+  mov  bl, [2]
+  mov  al, bl
+  shr  al, #7
+  cmp  al, #1
+  jne  fetch_bdf
+  mov  ax, ds ;; Increment the DS since rom size larger than an segment
+  add  ax, #0x1000
+  mov  ds, ax
+fetch_bdf:
+  shl  bx, #9
+  xor  ax, ax
+  mov  al, [bx]
+
   ;; Point ES:DI at "$PnP", which tells the ROM that we are a PnP BIOS.  
   ;; That should stop it grabbing INT 19h; we will use its BEV instead.
-  mov  ax, #0xf000
-  mov  es, ax
+  mov  bx, #0xf000
+  mov  es, bx
   lea  di, pnp_string 
 
+  xor  bx, bx   ;; Restore DS back to 0000:
+  mov  ds, bx
+
   mov  bp, sp   ;; Call ROM init routine using seg:off on stack
   db   0xff     ;; call_far ss:[bp+0]
   db   0x5e