WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

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

To: xen-devel <xen-devel@xxxxxxxxxxxxxxxxxxx>
Subject: [Xen-devel] [Patch][1/2][BIOS] Support BCV table
From: Akio Takebe <takebe_akio@xxxxxxxxxxxxxx>
Date: Thu, 26 Mar 2009 22:46:48 +0900
Delivery-date: Thu, 26 Mar 2009 06:47:19 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
In-reply-to: <49CB8652.3000801@xxxxxxxxxxxxxx>
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
References: <49CB85BC.3010806@xxxxxxxxxxxxxx> <49CB8652.3000801@xxxxxxxxxxxxxx>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Thunderbird 2.0.0.21 (X11/20090320)
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