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
|