[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [Patch][0/2][BIOS] Support BCV table
Hi, 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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |