Message ID | 20140217160947.GO29329@ERROL.INI.CMU.EDU |
---|---|
State | New |
Headers | show |
On Mon, Feb 17, 2014 at 11:09:48AM -0500, Gabriel L. Somlo wrote: > On Fri, Feb 07, 2014 at 04:37:58PM +0100, Paolo Bonzini wrote: > >Il 06/02/2014 14:38, Gabriel L. Somlo ha scritto: > >>On Wed, Feb 05, 2014 at 08:02:25PM -0500, Kevin O'Connor wrote: > >>> Thanks. In general, though, it is preferred to make smbios changes at > >>> the QEMU layer. Indeed, going forward, I'd like to see all the smbios > >>> stuff moved up to QEMU. > >>> > >>> Is there something in these two patches that can't be done in QEMU? > >> > >> But anyhow, right now QEMU seems to be making relatively minor tweaks > >> to something that's firmly at home in SeaBIOS, which is why I sent my > >> patches to the latter... > > > >Yeah, that's correct. There's really no particular hook in QEMU to do this. > > Would it be OK to apply this in SeaBIOS now, so that 1. it can be > useful until whenever SMBIOS gets transferred/absorbed into QEMU, > and 2. it won't fall through the cracks when that transition happens ? Unfortunately, if we change the smbios in SeaBIOS, it will show up on all machine types that use the new version of SeaBIOS. We've had issues with this type of change before as various OSes react differently to the change. Gerd, what's your take on this change? -Kevin
On Mo, 2014-02-17 at 15:33 -0500, Kevin O'Connor wrote: > On Mon, Feb 17, 2014 at 11:09:48AM -0500, Gabriel L. Somlo wrote: > > On Fri, Feb 07, 2014 at 04:37:58PM +0100, Paolo Bonzini wrote: > > >Il 06/02/2014 14:38, Gabriel L. Somlo ha scritto: > > >>On Wed, Feb 05, 2014 at 08:02:25PM -0500, Kevin O'Connor wrote: > > >>> Thanks. In general, though, it is preferred to make smbios changes at > > >>> the QEMU layer. Indeed, going forward, I'd like to see all the smbios > > >>> stuff moved up to QEMU. > > >>> > > >>> Is there something in these two patches that can't be done in QEMU? > > >> > > >> But anyhow, right now QEMU seems to be making relatively minor tweaks > > >> to something that's firmly at home in SeaBIOS, which is why I sent my > > >> patches to the latter... > > > > > >Yeah, that's correct. There's really no particular hook in QEMU to do this. > > > > Would it be OK to apply this in SeaBIOS now, so that 1. it can be > > useful until whenever SMBIOS gets transferred/absorbed into QEMU, > > and 2. it won't fall through the cracks when that transition happens ? > > Unfortunately, if we change the smbios in SeaBIOS, it will show up on > all machine types that use the new version of SeaBIOS. We've had > issues with this type of change before as various OSes react > differently to the change. > > Gerd, what's your take on this change? I think we can do this in qemu, without touching seabios at all. The currently used fw_cfg interface allows to pass both individual fields and complete tables. In practice the individual fields interface is used for type0 and type1 table fields. I think the only way to pass complete tables is 'qemu -smbios file=<pregenerated-blob-here>'. If seabios finds a table provided by qemu it used it, otherwise it (possibly) generates its own. So we can smoothly switch over to qemu, table-by-table. You can have qemu provide type2+type17 tables, and leave everything else as-is. And when doing it in qemu it is easy to do it for new machine types only. cheers, Gerd
On Tue, Feb 18, 2014 at 11:21:33AM +0100, Gerd Hoffmann wrote: > > Unfortunately, if we change the smbios in SeaBIOS, it will show up on > > all machine types that use the new version of SeaBIOS. We've had > > issues with this type of change before as various OSes react > > differently to the change. > > > > Gerd, what's your take on this change? > > I think we can do this in qemu, without touching seabios at all. The > currently used fw_cfg interface allows to pass both individual fields > and complete tables. In practice the individual fields interface is > used for type0 and type1 table fields. I think the only way to pass > complete tables is 'qemu -smbios file=<pregenerated-blob-here>'. Using Fedora 20 live, I collected the SMBIOS table from the guest using "dmidecode --dump-bin", with the unpatched SeaBIOS (dmidecode_pc.bin), SeaBIOS with my patch applied (dmidecode_mac.bin), and again with unpatched SeaBIOS but with "-smbios file=dmidecode_mac.bin" on the QEMU command line (dmidecode_cmdline.bin). I then ran "dmidecode --from-dump" on the three binaries I collected, and here's what I got: $ diff dmi_pc.txt dmi_mac.txt 2c2 < Reading SMBIOS/DMI data from file dmidecode_pc.bin. --- > Reading SMBIOS/DMI data from file dmidecode_mac.bin. 4c4 < 10 structures occupying 298 bytes. --- > 11 structures occupying 326 bytes. 29a30,43 > Handle 0x0200, DMI type 2, 15 bytes > Base Board Information > Manufacturer: Bochs > Product Name: Not Specified > Version: Not Specified > Serial Number: Not Specified > Asset Tag: Not Specified > Features: > Board is a hosting board > Location In Chassis: Not Specified > Chassis Handle: 0x0300 > Type: Motherboard > Contained Object Handles: 0 > 73c87 < Handle 0x1100, DMI type 17, 21 bytes --- > Handle 0x1100, DMI type 17, 27 bytes 85a100,104 > Speed: Unknown > Manufacturer: Not Specified > Serial Number: Not Specified > Asset Tag: Not Specified > Part Number: Not Specified This looks as expected (we have a new Type 2 entry, and the Type 17 entry now has version 2.3 fields where it didn't use to before). However, when I compare unmodified SMBIOS against what I get when supplying the patched binary table via command line, I get this: $ diff dmi_pc.txt dmi_cmdline.txt 2c2 < Reading SMBIOS/DMI data from file dmidecode_pc.bin. --- > Reading SMBIOS/DMI data from file dmidecode_cmdline.bin. 4c4 < 10 structures occupying 298 bytes. --- > 11 structures occupying 657 bytes. 108,109c108,120 < Handle 0x7F00, DMI type 127, 4 bytes < End Of Table --- > Handle 0x5F4D, DMI type 95, 83 bytes > Unknown Type > Header and Data: > 5F 53 4D 5F 32 1F 02 04 4B 00 00 00 00 00 00 00 > 5F 44 4D 49 5F D2 46 01 20 00 00 00 0B 00 24 00 > 00 18 00 00 01 02 00 E8 03 00 08 00 00 00 00 00 > 00 00 00 04 01 00 FF FF 42 6F 63 68 73 00 42 6F > 63 68 73 00 30 31 2F 30 31 2F 32 30 31 31 00 00 > 01 1B 00 > Strings: > .... > > Invalid entry length (0). DMI table is broken! Stop. No Type 2, no extra fields for Type 17, and a corrupt table to boot. > If seabios finds a table provided by qemu it used it, otherwise it > (possibly) generates its own. So we can smoothly switch over to qemu, > table-by-table. You can have qemu provide type2+type17 tables, and > leave everything else as-is. And when doing it in qemu it is easy to do > it for new machine types only. Sending a patch against QEMU would have definitely been my first choice, by a wide margin :) But after studying the hw/i386/smbios.c source file in QEMU for a while, I walked away with the impression that all it really tries to do is edit a few of the Type 0 and Type 1 fields, and that the hand-over logic between QEMU and SeaBIOS is not ready for prime time yet. So I sent the patch to SeaBIOS, where it seems to do what I want it to :) I could try to hack at the QEMU smbios source file to try to find where the problem lies (at least why handover to SeaBIOS doesn't work as expected), but I'm not sure providing command line flags for inputting each record type individually is a scalable way to move forward. Perhaps if there were a DMI/SMBIOS compiler (the reverse action of "dmidecode --from-dump", something that would take a text "source" table and generate a .bin from it), we could focus on getting the "-smbios file=<foo>" bit working correctly, and we could provide instructions in the docs on how users can build their own smbios tables. But I couldn't find anything out there that would "compile" a smbios table from some type of human-readable (ascii) form... Any thoughts ? Thanks, --Gabriel PS. I tried the patched SeaBIOS (with v2.3 type17 and added type2) on XP, Windows7, and Linux, and all of them seemed happy and none of them seemed to mind... Just sayin' ;)
On Tue, Feb 18, 2014 at 02:17:29PM -0500, Gabriel L. Somlo wrote: > Sending a patch against QEMU would have definitely been my first > choice, by a wide margin :) But after studying the hw/i386/smbios.c > source file in QEMU for a while, I walked away with the impression > that all it really tries to do is edit a few of the Type 0 and Type 1 > fields, and that the hand-over logic between QEMU and SeaBIOS is not > ready for prime time yet. The current mechanism for passing smbios from QEMU to SeaBIOS is horrible. > So I sent the patch to SeaBIOS, where it seems to do what I want it to :) > > I could try to hack at the QEMU smbios source file to try to find > where the problem lies (at least why handover to SeaBIOS doesn't work > as expected), but I'm not sure providing command line flags for > inputting each record type individually is a scalable way to move > forward. In my opinion, generating the entire smbios table in QEMU and using the "romfile_loader" mechanism (see seabios src/fw/romfile_loader.c) would be the preferred solution. I understand that this is more than you signed up for. > Perhaps if there were a DMI/SMBIOS compiler (the reverse action of > "dmidecode --from-dump", something that would take a text "source" > table and generate a .bin from it), we could focus on getting the > "-smbios file=<foo>" bit working correctly, and we could provide > instructions in the docs on how users can build their own smbios > tables. > > But I couldn't find anything out there that would "compile" a smbios > table from some type of human-readable (ascii) form... > > Any thoughts ? > > Thanks, > --Gabriel > > PS. I tried the patched SeaBIOS (with v2.3 type17 and added type2) on > XP, Windows7, and Linux, and all of them seemed happy and none of them > seemed to mind... Just sayin' ;) Thanks for running tests. One thing that has bitten us in the past is OSes re-running license checks and/or popping up "new hardware" notifications on bios table changes. -Kevin
On 02/18/14 20:17, Gabriel L. Somlo wrote: > On Tue, Feb 18, 2014 at 11:21:33AM +0100, Gerd Hoffmann wrote: > Using Fedora 20 live, I collected the SMBIOS table from the guest > using "dmidecode --dump-bin", with the unpatched SeaBIOS > (dmidecode_pc.bin), SeaBIOS with my patch applied (dmidecode_mac.bin), > and again with unpatched SeaBIOS but with "-smbios file=dmidecode_mac.bin" > on the QEMU command line (dmidecode_cmdline.bin). [...] > However, when I compare unmodified SMBIOS against what I get when > supplying the patched binary table via command line, I get this: > > $ diff dmi_pc.txt dmi_cmdline.txt > 2c2 > < Reading SMBIOS/DMI data from file dmidecode_pc.bin. > --- > > Reading SMBIOS/DMI data from file dmidecode_cmdline.bin. > 4c4 > < 10 structures occupying 298 bytes. > --- > > 11 structures occupying 657 bytes. > 108,109c108,120 > < Handle 0x7F00, DMI type 127, 4 bytes > < End Of Table > --- > > Handle 0x5F4D, DMI type 95, 83 bytes > > Unknown Type > > Header and Data: > > 5F 53 4D 5F 32 1F 02 04 4B 00 00 00 00 00 00 00 > > 5F 44 4D 49 5F D2 46 01 20 00 00 00 0B 00 24 00 > > 00 18 00 00 01 02 00 E8 03 00 08 00 00 00 00 00 > > 00 00 00 04 01 00 FF FF 42 6F 63 68 73 00 42 6F > > 63 68 73 00 30 31 2F 30 31 2F 32 30 31 31 00 00 > > 01 1B 00 > > Strings: > > .... > > > > Invalid entry length (0). DMI table is broken! Stop. > > No Type 2, no extra fields for Type 17, and a corrupt table to boot. I had tested this qemu interface with my OVMF SMBIOS patches. It works. (I used a Type 3 table.) The problem in this case is that you can't just pass in a raw dump from dmidecode. You need to prefix it with "smbios_header": struct smbios_table { struct smbios_header header; uint8_t data[]; } QEMU_PACKED; struct smbios_header { uint16_t length; uint8_t type; } QEMU_PACKED; You need to set "type" to 1 (SMBIOS_TABLE_ENTRY), and set "length" so that it covers the entire "smbios_table" struct (ie. both header and payload, where payload is your SMBIOS table). "length" is little endian. Laszlo
On 02/18/14 22:08, Laszlo Ersek wrote: > On 02/18/14 20:17, Gabriel L. Somlo wrote: >> On Tue, Feb 18, 2014 at 11:21:33AM +0100, Gerd Hoffmann wrote: > >> Using Fedora 20 live, I collected the SMBIOS table from the guest >> using "dmidecode --dump-bin", with the unpatched SeaBIOS >> (dmidecode_pc.bin), SeaBIOS with my patch applied (dmidecode_mac.bin), >> and again with unpatched SeaBIOS but with "-smbios file=dmidecode_mac.bin" >> on the QEMU command line (dmidecode_cmdline.bin). > > [...] > >> However, when I compare unmodified SMBIOS against what I get when >> supplying the patched binary table via command line, I get this: >> >> $ diff dmi_pc.txt dmi_cmdline.txt >> 2c2 >> < Reading SMBIOS/DMI data from file dmidecode_pc.bin. >> --- >> > Reading SMBIOS/DMI data from file dmidecode_cmdline.bin. >> 4c4 >> < 10 structures occupying 298 bytes. >> --- >> > 11 structures occupying 657 bytes. >> 108,109c108,120 >> < Handle 0x7F00, DMI type 127, 4 bytes >> < End Of Table >> --- >> > Handle 0x5F4D, DMI type 95, 83 bytes >> > Unknown Type >> > Header and Data: >> > 5F 53 4D 5F 32 1F 02 04 4B 00 00 00 00 00 00 00 >> > 5F 44 4D 49 5F D2 46 01 20 00 00 00 0B 00 24 00 >> > 00 18 00 00 01 02 00 E8 03 00 08 00 00 00 00 00 >> > 00 00 00 04 01 00 FF FF 42 6F 63 68 73 00 42 6F >> > 63 68 73 00 30 31 2F 30 31 2F 32 30 31 31 00 00 >> > 01 1B 00 >> > Strings: >> > .... >> > >> > Invalid entry length (0). DMI table is broken! Stop. >> >> No Type 2, no extra fields for Type 17, and a corrupt table to boot. > > I had tested this qemu interface with my OVMF SMBIOS patches. It works. > (I used a Type 3 table.) > > The problem in this case is that you can't just pass in a raw dump from > dmidecode. You need to prefix it with "smbios_header": > > struct smbios_table { > struct smbios_header header; > uint8_t data[]; > } QEMU_PACKED; > > struct smbios_header { > uint16_t length; > uint8_t type; > } QEMU_PACKED; > > You need to set "type" to 1 (SMBIOS_TABLE_ENTRY), and set "length" so > that it covers the entire "smbios_table" struct (ie. both header and > payload, where payload is your SMBIOS table). "length" is little endian. Oh wait, scratch that, qemu should do this for you. But, I retested the thing (with my original Type 3 file), and it still seems to work. -smbios file=/home/virt-images/smbios/type3 000000 03 14 00 03 01 01 00 00 00 03 03 03 02 00 00 00 000010 00 00 00 00 52 65 64 20 48 61 74 00 00 Dumped in the OVMF guest: Handle 0x0000, DMI type 3, 20 bytes Chassis Information Manufacturer: Red Hat Type: Other Lock: Not Present Version: Not Specified Serial Number: Not Specified Asset Tag: Not Specified Boot-up State: Safe Power Supply State: Safe Thermal State: Safe Security Status: Unknown OEM Information: 0x00000000 Height: Unspecified Number Of Power Cords: Unspecified What was the exact command line you used? ... Ah, I think I understand. When you issued dmidecode --dump-bin, that dumped *all* of the tables. (--dump-bin is mutually exclusive with --type.) You can't pass multiple tables with one '-smbios file=XXX qemu option. You need separate binary dumps (one per table), and should pass them with one -smbios file=XXX option each. Thanks Laszlo
Hi, > In my opinion, generating the entire smbios table in QEMU and using > the "romfile_loader" mechanism (see seabios src/fw/romfile_loader.c) > would be the preferred solution. I understand that this is more than > you signed up for. Yes, this is where we should end up long-term. For the time being I think it is fine to use the existing mechanism to switch over table by table, and once we have the code to generate all tables in qemu we can switch over to an interface where we simply pass all tables as single blob. I think we don't even need the romfile_loader, or do have smbios tables pointers which need to be fixed up? cheers, Gerd
Hi, > However, when I compare unmodified SMBIOS against what I get when > supplying the patched binary table via command line, I get this: As Laszlo already sayed: one table per file. > > If seabios finds a table provided by qemu it used it, otherwise it > > (possibly) generates its own. So we can smoothly switch over to qemu, > > table-by-table. You can have qemu provide type2+type17 tables, and > > leave everything else as-is. And when doing it in qemu it is easy to do > > it for new machine types only. > > I could try to hack at the QEMU smbios source file to try to find > where the problem lies (at least why handover to SeaBIOS doesn't work > as expected), but I'm not sure providing command line flags for > inputting each record type individually is a scalable way to move > forward. Agree. qemu should simply autogenerate the entries (where it can). i.e. basically port seabios smbios_init_type_17 function to qemu, then hook the result into the smbios_entries array. The code to do that is in smbios_entry_add(). You probably want to factor that out ino a small helper function which is then called by both smbios_entry_add() and the type17 init function. cheers, Gerd
diff --git a/src/fw/smbios.c b/src/fw/smbios.c index 55c662a..5b76468 100644 --- a/src/fw/smbios.c +++ b/src/fw/smbios.c @@ -251,6 +251,41 @@ smbios_init_type_1(void *start) return end; } +/* Type 2 -- Base Board */ +static void * +smbios_init_type_2(void *start) +{ + struct smbios_type_2 *p = (struct smbios_type_2 *)start; + char *end = (char *)start + sizeof(struct smbios_type_2); + size_t size; + int str_index = 0; + + p->header.type = 2; + p->header.length = sizeof(struct smbios_type_2); + p->header.handle = 0x200; + + load_str_field_with_default(2, manufacturer_str, BUILD_APPNAME); + load_str_field_or_skip(2, product_str); + load_str_field_or_skip(2, version_str); + load_str_field_or_skip(2, serial_number_str); + load_str_field_or_skip(2, asset_tag_number_str); + load_str_field_or_skip(2, location_str); + + set_field_with_default(2, feature_flags, 0x01); /* Motherboard */ + set_field_with_default(2, chassis_handle, 0x300); /* T3 System Enclosure */ + set_field_with_default(2, board_type, 0x0a); /* Motherboard */ + set_field_with_default(2, contained_element_count, 0); + + *end = 0; + end++; + if (!str_index) { + *end = 0; + end++; + } + + return end; +} + /* Type 3 -- System Enclosure */ static void * smbios_init_type_3(void *start) @@ -417,6 +452,12 @@ smbios_init_type_17(void *start, u32 size_mb, int instance) set_field_with_default(17, memory_type, 0x07); /* RAM */ set_field_with_default(17, type_detail, 0); + set_field_with_default(17, speed, 0); /* unknown */ + load_str_field_or_skip(17, manufacturer_str); + load_str_field_or_skip(17, serial_number_str); + load_str_field_or_skip(17, asset_tag_number_str); + load_str_field_or_skip(17, part_number_str); + *end = 0; end++; if (!str_index) { @@ -540,6 +581,7 @@ smbios_setup(void) add_struct(0, p); add_struct(1, p); + add_struct(2, p); add_struct(3, p); int cpu_num; diff --git a/src/std/smbios.h b/src/std/smbios.h index 0513716..86a4c57 100644 --- a/src/std/smbios.h +++ b/src/std/smbios.h @@ -59,6 +59,22 @@ struct smbios_type_1 { u8 family_str; } PACKED; +/* SMBIOS type 2 - Base Board */ +struct smbios_type_2 { + struct smbios_structure_header header; + u8 manufacturer_str; + u8 product_str; + u8 version_str; + u8 serial_number_str; + u8 asset_tag_number_str; + u8 feature_flags; + u8 location_str; + u16 chassis_handle; + u8 board_type; + u8 contained_element_count; + // contained elements follow +} PACKED; + /* SMBIOS type 3 - System Enclosure (v2.3) */ struct smbios_type_3 { struct smbios_structure_header header; @@ -127,6 +143,12 @@ struct smbios_type_17 { u8 bank_locator_str; u8 memory_type; u16 type_detail; + /* v2.3 fields: */ + u16 speed; + u8 manufacturer_str; + u8 serial_number_str; + u8 asset_tag_number_str; + u8 part_number_str; } PACKED; /* SMBIOS type 19 - Memory Array Mapped Address */