[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [Patch][1/2][BIOS] Support BCV table



Hi,

# Oops, the subject of the previous mail is wrong.:)
# I send again with correct subject. Sorry.

this patch is tools parts.

Signed-off-by: Akio Takebe <takebe_akio@xxxxxxxxxxxxxx>

Best Regards,

Akio Takebe
diff -r 0477f9061c8a tools/firmware/hvmloader/hvmloader.c
--- a/tools/firmware/hvmloader/hvmloader.c      Fri Mar 20 17:42:46 2009 +0000
+++ b/tools/firmware/hvmloader/hvmloader.c      Thu Mar 26 22:20:23 2009 +0900
@@ -477,10 +477,14 @@
 {
     uint32_t option_rom_addr, rom_phys_addr = rom_base_addr;
     uint16_t vendor_id, device_id;
-    uint8_t devfn, class;
+    uint8_t devfn, class, i;
 
-    for ( devfn = 0; devfn < 128; devfn++ )
-    {
+    for (i=0; i < MAX_PCI_BOOT; i++){
+        devfn = hvm_info->pci_sbdf[i];
+        if ( devfn ==0 )
+            continue;
+        printf("%s:devfn=%x \n",__func__, devfn);
+
         class     = pci_readb(devfn, PCI_CLASS_DEVICE + 1);
         vendor_id = pci_readw(devfn, PCI_VENDOR_ID);
         device_id = pci_readw(devfn, PCI_DEVICE_ID);
diff -r 0477f9061c8a tools/firmware/rombios/rombios.c
--- a/tools/firmware/rombios/rombios.c  Fri Mar 20 17:42:46 2009 +0000
+++ b/tools/firmware/rombios/rombios.c  Thu Mar 26 22:20:23 2009 +0900
@@ -187,18 +187,33 @@
 #define EBDA_SIZE          1              // In KiB
 #define BASE_MEM_IN_K   (640 - EBDA_SIZE)
 
-/* 256 bytes at 0x9ff00 -- 0x9ffff is used for the IPL boot table. */
+/* 256 bytes at 0x9ff00 -- 0x9ffaf is used for the IPL boot table. */
 #define IPL_TABLE_OFFSET     0x0300  /* offset from EBDA */
 #define IPL_TABLE_ENTRIES    8
 #define IPL_COUNT_OFFSET     0x0380  /* u16: number of valid table entries */
 #define IPL_SEQUENCE_OFFSET  0x0382  /* u16: next boot device */
 #define IPL_BOOTFIRST_OFFSET 0x0384  /* u16: user selected device */
-#define IPL_SIZE             0xff
+#define IPL_SIZE             0xaf
 #define IPL_TYPE_FLOPPY      0x01
 #define IPL_TYPE_HARDDISK    0x02
 #define IPL_TYPE_CDROM       0x03
 #define IPL_TYPE_BEV         0x80
 
+#define IPL_TYPE_BCV         IPL_TYPE_HARDDISK
+
+/* 256 bytes at 0x9ffb0 -- 0x9ffff is used for the BCV boot table. */
+#define BCV_TABLE_OFFSET     0x03b0  /* offset from EBDA */
+#define BCV_TABLE_ENTRIES    4
+#define BCV_COUNT_OFFSET     0x03f0  /* u16: number of valid table entries */
+#define BCV_SEQUENCE_OFFSET  0x03f2  /* u16: next boot device */
+#define BCV_BOOTFIRST_OFFSET 0x03f4  /* u16: user selected device */
+#define BCV_SIZE             0x4f
+
+#define BOOTDEV_FDD 0x1
+#define BOOTDEV_HDD 0x2
+#define BOOTDEV_CD  0x3
+#define BOOTDEV_NET 0x4
+#define BOOTDEV_BCV 0x5
 
   // Sanity Checks
 #if BX_USE_ATADRV && BX_CPU<3
@@ -2064,14 +2079,65 @@
 
 static char drivetypes[][10]={"", "Floppy","Hard Disk","CD-Rom", "Network"};
 
+/* initialize BCV talbe. BCV and IPL table are the same structure. */
 static void
-init_boot_vectors()
+init_boot_connection_vector()
 {
   ipl_entry_t e;
   Bit16u count = 0;
   Bit16u ss = get_SS();
   Bit16u ebda_seg = read_word(0x0040, 0x000E);
 
+  /* Clear out the BCV table. */
+  memsetb(ebda_seg, BCV_TABLE_OFFSET, 0, BCV_SIZE);
+
+  /* User selected device not set */
+  write_word(ebda_seg, BCV_BOOTFIRST_OFFSET, 0xFFFF);
+
+  /* First HDD */
+//  e.type = IPL_TYPE_HARDDISK; e.flags = 0; e.vector = 0; e.description = 0; 
e.reserved = 0;
+//  memcpyb(ebda_seg, BCV_TABLE_OFFSET + count * sizeof (e), ss, &e, sizeof 
(e));
+//  count++;
+
+  /* Remember how many devices we have */
+  write_word(ebda_seg, BCV_COUNT_OFFSET, count);
+  /* Not tried booting anything yet */
+  write_word(ebda_seg, BCV_SEQUENCE_OFFSET, 0xFFFF);
+}
+
+static Bit16u
+get_bcv_count()
+{
+  Bit16u count;
+  Bit16u ss = get_SS();
+  Bit16u ebda_seg = read_word(0x0040, 0x000E);
+  count = read_word(ebda_seg, BCV_COUNT_OFFSET);
+  return count;
+}
+
+static Bit8u
+get_bcv_entry(i, e)
+Bit16u i; ipl_entry_t *e;
+{
+  Bit16u count;
+  Bit16u ss = get_SS();
+  Bit16u ebda_seg = read_word(0x0040, 0x000E);
+  /* Get the count of boot devices, and refuse to overrun the array */
+  count = read_word(ebda_seg, BCV_COUNT_OFFSET);
+  if (i > count) return 0;
+  /* OK to read this device */
+  memcpyb(ss, e, ebda_seg, BCV_TABLE_OFFSET + i * sizeof (*e), sizeof (*e));
+  return 1;
+}
+
+static void
+init_boot_vectors()
+{
+  ipl_entry_t e;
+  Bit16u count = 0;
+  Bit16u ss = get_SS();
+  Bit16u ebda_seg = read_word(0x0040, 0x000E);
+
   /* Clear out the IPL table. */
   memsetb(ebda_seg, IPL_TABLE_OFFSET, 0, IPL_SIZE);
 
@@ -2106,13 +2172,23 @@
 Bit16u i; ipl_entry_t *e;
 {
   Bit16u count;
+  Bit16u j = i;
   Bit16u ss = get_SS();
   Bit16u ebda_seg = read_word(0x0040, 0x000E);
+
+  /* BCV device also use IPL_TYPE_HARDDISK. */
+  if(i == BOOTDEV_BCV)
+    j = BOOTDEV_HDD;
+
   /* Get the count of boot devices, and refuse to overrun the array */
   count = read_word(ebda_seg, IPL_COUNT_OFFSET);
-  if (i >= count) return 0;
+  if (j >= count) return 0;
+
+  /* Translate from CMOS runes to an IPL table offset by subtracting 1 */
+  j--;
+
   /* OK to read this device */
-  memcpyb(ss, e, ebda_seg, IPL_TABLE_OFFSET + i * sizeof (*e), sizeof (*e));
+  memcpyb(ss, e, ebda_seg, IPL_TABLE_OFFSET + j * sizeof (*e), sizeof (*e));
   return 1;
 }
 
@@ -2204,7 +2280,7 @@
   type = e->type;
   /* NIC appears as type 0x80 */
   if (type == IPL_TYPE_BEV) type = 0x4;
-  if (type == 0 || type > 0x4) BX_PANIC("Bad drive type\n");
+  if (type == 0 || type > 0x5) BX_PANIC("Bad drive type(%d)\n", type);
   printf("Booting from %s", drivetypes[type]);
   /* print product string if BEV */
   if (type == 4 && e->description != 0) {
@@ -2217,6 +2293,22 @@
   printf("...\n");
 }
 
+void
+print_bcv_device(bcv, bootdrv)
+  ipl_entry_t *bcv;
+  Bit8u  bootdrv;
+{
+  char description[33];
+  Bit16u ss = get_SS();
+
+  if (bcv->description != 0)
+  {
+    memcpyb(ss, &description, (Bit16u)(bcv->description >> 16), 
(Bit16u)(bcv->description & 0xffff), 32);
+    description[32] = 0;
+    printf(" [%S]", ss, description);
+  }
+  printf(" bootdrv[0x%x]\n", bootdrv);
+}
 //--------------------------------------------------------------------------
 // print_boot_failure
 //   displays the reason why boot failed
@@ -8207,8 +8299,12 @@
   Bit16u bootip;
   Bit16u status;
   Bit16u bootfirst;
+  Bit16u bcv_count;
+  Bit16u retry_count;
+  Bit16u hdcount, ata_hdcount;
 
   ipl_entry_t e;
+  ipl_entry_t bcv;
 
   // if BX_ELTORITO_BOOT is not defined, old behavior
   //   check bit 5 in CMOS reg 0x2d.  load either 0x00 or 0x80 into DL
@@ -8245,8 +8341,6 @@
     write_word(ebda_seg, IPL_SEQUENCE_OFFSET, 0xFFFF);
   } else if (bootdev == 0) BX_PANIC("No bootable device.\n");
 
-  /* Translate from CMOS runes to an IPL table offset by subtracting 1 */
-  bootdev -= 1;
 #else
   if (seq_nr ==2) BX_PANIC("No more boot devices.");
   if (!!(inb_cmos(0x2d) & 0x20) ^ (seq_nr == 1))
@@ -8255,11 +8349,10 @@
   else
     bootdev = 0x01;
 #endif
-
   /* Read the boot device from the IPL table */
-  if (get_boot_vector(bootdev, &e) == 0) {
-    BX_INFO("Invalid boot device (0x%x)\n", bootdev);
-    return;
+  if (get_boot_vector(bootdev, &e) == 0 ){
+      BX_INFO("Invalid boot device (0x%x)\n", bootdev);
+      return;
   }
 
   /* Do the loading, and set up vector as a far pointer to the boot
@@ -8269,8 +8362,37 @@
   switch(e.type) {
   case IPL_TYPE_FLOPPY: /* FDD */
   case IPL_TYPE_HARDDISK: /* HDD */
-
-    bootdrv = (e.type == IPL_TYPE_HARDDISK) ? 0x80 : 0x00;
+    ata_hdcount = read_byte(ebda_seg, &EbdaData->ata.hdcount);
+    hdcount     = read_byte(0x40,0x75);
+    bcv_count   = hdcount - ata_hdcount;
+    if ( bcv_count != get_bcv_count() || bcv_count < 0 )
+        BX_PANIC("Invaild hdcount(%d) ata_hdcount=%d bcv_count=%d\n",
+                  hdcount, ata_hdcount, get_bcv_count());
+
+    BX_INFO("hdcount(%d) ata_hdcount=%d bcv_count=%d\n",
+            hdcount, ata_hdcount, get_bcv_count());
+    if ( bootdev == BOOTDEV_BCV ) {
+      retry_count = bcv_count;
+      bootdrv = (0x80 + ata_hdcount);
+    } else {
+      if ( ata_hdcount == 0 && e.type == IPL_TYPE_HARDDISK) {
+          print_boot_failure(e.type, 1);
+          return;
+      }
+      retry_count = 1;
+      bootdrv = (e.type == IPL_TYPE_HARDDISK) ? 0x80 : 0x00;
+    }
+retry_type_hdd:
+    if ( retry_count == 0 ) {
+      return; /* boot fail with all bcv devices */
+    } else {
+      if ( bootdev == BOOTDEV_BCV ) {
+        bootdrv = bootdrv + (bcv_count - retry_count);
+        get_bcv_entry(bcv_count - retry_count, &bcv);
+        print_bcv_device(&bcv, bootdrv);
+      } 
+    }
+
     bootseg = 0x07c0;
     status = 0;
 
@@ -8306,7 +8428,8 @@
 
     if (status != 0) {
       print_boot_failure(e.type, 1);
-      return;
+      retry_count--;
+      goto retry_type_hdd;
     }
 
     /* Always check the signature on a HDD boot sector; on FDD, only do
@@ -8314,7 +8437,8 @@
     if ((e.type != IPL_TYPE_FLOPPY) || !((inb_cmos(0x38) & 0x01))) {
       if (read_word(bootseg,0x1fe) != 0xaa55) {
         print_boot_failure(e.type, 0);
-        return;
+        retry_count--;
+        goto retry_type_hdd;
       }
     }
 
@@ -8326,6 +8450,7 @@
     /* Canonicalize bootseg:bootip */
     bootip = (bootseg & 0x0fff) << 4;
     bootseg &= 0xf000;
+    printf("boot from [%x:%x]\n", bootseg, bootip);
   break;
 
 #if BX_ELTORITO_BOOT
@@ -10585,7 +10710,31 @@
   cli           ;; In case expansion ROM BIOS turns IF on
   add  sp, #2   ;; Pop offset value
   pop  cx       ;; Pop seg value (restore CX)
-  jmp   no_bev
+
+  ;; Found BCV device. Recode it in BCV table.
+  mov  bx, 0x001a   ;; 0x1A is the offset into ROM header that contains...
+  mov  di, 0x10[bx]            ;; Pointer to the product name string or zero 
if none
+
+  xor  bx, bx
+  mov  ds, bx
+  mov  bx, word ptr [0x40E]    ;; EBDA segment
+  mov  ds, bx                  ;; Go to the segment where the BCV table lives
+  mov  bx, BCV_COUNT_OFFSET    ;; Read the number of entries so far
+  cmp  bx, #BCV_TABLE_ENTRIES
+  je   no_bev                  ;; Get out if the table is full
+  shl  bx, #0x4                ;; Turn count into offset (entries are 16 bytes)
+  mov  BCV_TABLE_OFFSET+0[bx], #IPL_TYPE_BCV ;; This entry is a BCV device
+  mov  BCV_TABLE_OFFSET+6[bx], cx            ;; Build a far pointer from the 
segment...
+  mov  BCV_TABLE_OFFSET+4[bx], ax            ;; and the offset
+  cmp  di, #0x0000
+  je   no_prod_str1
+  mov  BCV_TABLE_OFFSET+0xA[bx], cx          ;; segment to descritption
+  mov  BCV_TABLE_OFFSET+0x8[bx], di          ;; pointer to descritption
+no_prod_str1:
+  shr  bx, #0x4                ;; Turn the offset back into a count
+  inc  bx                      ;; We have one more entry now
+  mov  BCV_COUNT_OFFSET, bx    ;; Remember that.
+  jmp  no_bev
 
 no_bcv:
   mov  ax, 0x1a[bx] ;; 0x1A is also the offset into the expansion header of...
@@ -10606,10 +10755,10 @@
   mov  IPL_TABLE_OFFSET+6[bx], cx            ;; Build a far pointer from the 
segment...
   mov  IPL_TABLE_OFFSET+4[bx], ax            ;; and the offset
   cmp  di, #0x0000
-  je   no_prod_str
+  je   no_prod_str2
   mov  0xA[bx], cx             ;; Build a far pointer from the segment...
   mov  8[bx], di               ;; and the offset
-no_prod_str:
+no_prod_str2:
   shr  bx, #0x4                ;; Turn the offset back into a count
   inc  bx                      ;; We have one more entry now
   mov  IPL_COUNT_OFFSET, bx    ;; Remember that.
@@ -11041,6 +11190,7 @@
 #endif
 
   call _init_boot_vectors
+  call _init_boot_connection_vector
 
   mov  cx, #(OPTIONROM_PHYSICAL_ADDRESS >> 4)  ;; init option roms
   mov  ax, #(OPTIONROM_PHYSICAL_END >> 4)
diff -r 0477f9061c8a tools/python/xen/xm/create.py
--- a/tools/python/xen/xm/create.py     Fri Mar 20 17:42:46 2009 +0000
+++ b/tools/python/xen/xm/create.py     Thu Mar 26 22:20:23 2009 +0900
@@ -323,7 +323,7 @@
           backend driver domain to use for the disk.
           The option may be repeated to add more than one disk.""")
 
-gopts.var('pci', 
val='BUS:DEV.FUNC[@VSLOT][,msitranslate=0|1][,power_mgmt=0|1]',
+gopts.var('pci', 
val='BUS:DEV.FUNC[@VSLOT][,msitranslate=0|1][,power_mgmt=0|1][,boot=0|1]',
           fn=append_value, default=[],
           use="""Add a PCI device to a domain, using given params (in hex).
           For example 'pci=c0:02.1'.
@@ -334,7 +334,12 @@
           translated from physical MSI, HVM only. Default is 1.
           The option may be repeated to add more than one pci device.
           If power_mgmt is set, the guest OS will be able to program the power
-          states D0-D3hot of the device, HVM only. Default=0.""")
+          states D0-D3hot of the device, HVM only. Default=0.
+          If boot option is set, the devices are handled as bootable devices.
+          boot option can add only 4 pci devices.
+          If boot is set, guest BIOS can boot OS from the pass-through devices.
+          The option is used by SAN/SAS boot.""")
+
 
 gopts.var('vscsi', val='PDEV,VDEV[,DOM]',
           fn=append_value, default=[],
@@ -704,7 +709,7 @@
         d = comma_sep_kv_to_dict(opts)
 
         def f(k):
-            if k not in ['msitranslate', 'power_mgmt']:
+            if k not in ['msitranslate', 'power_mgmt', 'boot']:
                 err('Invalid pci option: ' + k)
 
             config_pci_opts.append([k, d[k]])
diff -r 0477f9061c8a xen/include/public/hvm/hvm_info_table.h
--- a/xen/include/public/hvm/hvm_info_table.h   Fri Mar 20 17:42:46 2009 +0000
+++ b/xen/include/public/hvm/hvm_info_table.h   Thu Mar 26 22:20:23 2009 +0900
@@ -28,6 +28,8 @@
 #define HVM_INFO_PFN         0x09F
 #define HVM_INFO_OFFSET      0x800
 #define HVM_INFO_PADDR       ((HVM_INFO_PFN << 12) + HVM_INFO_OFFSET)
+
+#define MAX_PCI_BOOT 4
 
 struct hvm_info_table {
     char        signature[8]; /* "HVM INFO" */
@@ -64,6 +66,11 @@
      *    RAM above 4GB
      */
     uint32_t    high_mem_pgend;
+    /*
+     * SBDF of bootable pass-through devices
+     * It is used by hvmloader for loading option ROM.
+     */
+    uint32_t   pci_sbdf[MAX_PCI_BOOT];
 };
 
 #endif /* __XEN_PUBLIC_HVM_HVM_INFO_TABLE_H__ */
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.