All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 3/3] SMBIOS table passthrough support
@ 2012-02-21  2:56 Ross Philipson
  0 siblings, 0 replies; only message in thread
From: Ross Philipson @ 2012-02-21  2:56 UTC (permalink / raw)
  To: xen-devel

[-- Attachment #1: Type: text/plain, Size: 860 bytes --]

SMBIOS tables are written into the HVM parameter and information page. The SMBIOS tables would normally come from system firmware where they are written by the xen toolstack. In general though, there is no limitation on where the tables come from other than their following the DMTF standards. In the SMBIOS building code in hvmloader, passed in tables are searched for and take precedence over default values when found.

Three new tables were added (types 2, 22 and 39) but are disabled by default. A set of flags is used to specify inclusion of new tables so that the existing default set is preserved. In addition to the pre-defined table types, OEM specific tables (types 128 - 255) can also be written in. Any number of OEM tables can be passed in and will be surfaced in the HVM SMBIOS.

Signed-off-by: Ross Philipson <ross.philipson@citrix.com>


[-- Attachment #2: smbios-passthrough-03.patch --]
[-- Type: application/octet-stream, Size: 14595 bytes --]

diff -r 0900b1c905f1 tools/firmware/hvmloader/smbios.c
--- a/tools/firmware/hvmloader/smbios.c	Mon Feb 20 18:58:07 2012 +0000
+++ b/tools/firmware/hvmloader/smbios.c	Mon Feb 20 20:56:58 2012 -0500
@@ -49,6 +49,8 @@
 smbios_type_1_init(void *start, const char *xen_version, 
                    uint8_t uuid[16]);
 static void *
+smbios_type_2_init(void *start);
+static void *
 smbios_type_3_init(void *start);
 static void *
 smbios_type_4_init(void *start, unsigned int cpu_number,
@@ -64,8 +66,14 @@
 static void *
 smbios_type_20_init(void *start, uint32_t memory_size_mb, int instance);
 static void *
+smbios_type_22_init(void *start);
+static void *
 smbios_type_32_init(void *start);
 static void *
+smbios_type_39_init(void *start);
+static void *
+smbios_type_vendor_oem_init(void *start);
+static void *
 smbios_type_127_init(void *start);
 
 static void
@@ -85,6 +93,77 @@
         strncpy(buf, "unknown", len);
 }
 
+static struct hvm_smbios_table_header *
+get_smbios_info_by_type(struct hvm_smbios_info_table *pa_smbt, uint8_t type)
+{
+    struct hvm_smbios_table_header *header;
+    uint32_t count;
+    uint8_t *ptr;
+
+    header = (struct hvm_smbios_table_header*)
+        ((uint8_t*)pa_smbt + sizeof(struct hvm_smbios_info_table));
+
+    for ( count = 0; count < pa_smbt->count; count++ )
+    {
+        if ( (header->length > 0)&&(header->length < HVM_SMBIOS_INFO_MAX) )
+        {
+            ptr = ((uint8_t*)header + sizeof(struct hvm_smbios_table_header));
+            if ( ptr[0] == type )
+                return header;
+        }
+        else
+        {
+            printf("SMBIOS table invalid length: %d, aborting.",
+                   (int)header->length);
+            return NULL;
+        }
+
+        header = (struct hvm_smbios_table_header*)(ptr + header->length);
+    }
+
+    return NULL;
+}
+
+#define SPTARG(s, t) s, t, sizeof(struct smbios_type_##t)
+static uint32_t
+smbios_passthrough(void *start, uint8_t table, uint32_t stsize)
+{
+    struct hvm_smbios_info_table *pa_smbt;
+    struct hvm_smbios_table_header *header;
+
+    pa_smbt = get_hvm_smbios_info_table();
+    if ( pa_smbt == NULL )
+        return 0;
+
+    header = get_smbios_info_by_type(pa_smbt, table);
+    if ( header == NULL )
+        return 0;
+
+    if ( header->length < stsize )
+    {
+        printf("SMBIOS table length less than fixed minimum length, skipping.");
+        return 0;
+    }
+
+    memcpy(start,
+           ((uint8_t*)header + sizeof(struct hvm_smbios_table_header)),
+           header->length);
+
+    return header->length;
+}
+
+static uint32_t
+get_smbios_info_flags(void)
+{
+    struct hvm_smbios_info_table *pa_smbt;
+
+    pa_smbt = get_hvm_smbios_info_table();
+    if ( pa_smbt != NULL )
+        return pa_smbt->flags;
+
+    return 0;
+}
+
 static int
 write_smbios_tables(void *ep, void *start,
                     uint32_t vcpus, uint64_t memsize,
@@ -112,6 +191,7 @@
     do_struct(smbios_type_0_init(p, xen_version, xen_major_version,
                                  xen_minor_version));
     do_struct(smbios_type_1_init(p, xen_version, uuid));
+    do_struct(smbios_type_2_init(p));
     do_struct(smbios_type_3_init(p));
     for ( cpu_num = 1; cpu_num <= vcpus; cpu_num++ )
         do_struct(smbios_type_4_init(p, cpu_num, cpu_manufacturer));
@@ -130,7 +210,10 @@
         do_struct(smbios_type_20_init(p, dev_memsize, i));
     }
 
+    do_struct(smbios_type_22_init(p));
     do_struct(smbios_type_32_init(p));
+    do_struct(smbios_type_39_init(p));
+    do_struct(smbios_type_vendor_oem_init(p));
     do_struct(smbios_type_127_init(p));
 
 #undef do_struct
@@ -289,6 +372,15 @@
     struct smbios_type_0 *p = (struct smbios_type_0 *)start;
     static const char *smbios_release_date = __SMBIOS_DATE__;
     const char *s;
+    uint32_t length;
+
+    length = smbios_passthrough(SPTARG(start, 0));
+    if ( length > 0 )
+    {
+        /* Fix up, use consistent handles */
+        p->header.handle = 0;
+        return (start + length);
+    }
 
     memset(p, 0, sizeof(*p));
 
@@ -338,6 +430,15 @@
     char uuid_str[37];
     struct smbios_type_1 *p = (struct smbios_type_1 *)start;
     const char *s;
+    uint32_t length;
+
+    length = smbios_passthrough(SPTARG(start, 1));
+    if ( length > 0 )
+    {
+        /* Fix up, use consistent handles */
+        p->header.handle = 0x100;
+        return (start + length);
+    }
 
     memset(p, 0, sizeof(*p));
 
@@ -376,15 +477,88 @@
     start += strlen(s) + 1;
 
     *((uint8_t *)start) = 0;
-    
     return start+1; 
 }
 
+/* Type 2 -- System Board */
+static void *
+smbios_type_2_init(void *start)
+{
+    struct smbios_type_2 *p = (struct smbios_type_2 *)start;
+    uint8_t *bptr;
+    const char *s;
+    uint32_t length;
+
+    if ( (get_smbios_info_flags() & HVM_SMBIOS_INCLUDE_SYSTEM_BOARD) == 0 )
+        return start;
+
+    length = smbios_passthrough(SPTARG(start, 2));
+    if ( length > 0 )
+    {
+        /* Fix up, use consistent handles, set chassis handle */
+        p->header.handle = 0x200;
+
+        /* NOTE: if this code is enhanced to allow multiple instances of some tables like
+           this one, chassis info, etc. then work will have to be done to match these handles */
+        if ( p->header.length >= 13 )
+        {
+            bptr = ((uint8_t*)start) + 11;
+            if (*((uint16_t*)bptr) != 0)
+                *((uint16_t*)bptr) = 0x300; /* current chassis handle */
+        }
+
+        return (start + length);
+    }
+
+    memset(p, 0, sizeof(*p));
+
+    p->header.type = 2;
+    p->header.length = sizeof(struct smbios_type_2);
+    p->header.handle = 0x200;
+
+    p->manufacturer_str = 1;
+    p->product_name_str = 2;
+    p->version_str = 0;
+    p->serial_number_str = 0;
+
+    start += sizeof(struct smbios_type_2);
+
+    s = xenstore_read("bios-strings/board-manufacturer", "Xen");
+    strcpy((char *)start, s);
+    start += strlen(s) + 1;
+
+    s = xenstore_read("bios-strings/board-product-name", "HVM domU");
+    strcpy((char *)start, s);
+    start += strlen(s) + 1;
+
+    /* no internal defaults for this if the value is not set */
+    s = xenstore_read("bios-strings/board-serial-number", NULL);
+    if ( (s != NULL)&&(*s != '\0') )
+    {
+        strcpy((char *)start, s);
+        start += strlen(s) + 1;        
+        p->serial_number_str = 3;
+    }
+
+    *((uint8_t *)start) = 0;
+    return start+1;
+}
+
 /* Type 3 -- System Enclosure */
 static void *
 smbios_type_3_init(void *start)
 {
     struct smbios_type_3 *p = (struct smbios_type_3 *)start;
+    const char *s;
+    uint32_t length;
+
+    length = smbios_passthrough(SPTARG(start, 3));
+    if ( length > 0 )
+    {
+        /* Fix up, use consistent handles */
+        p->header.handle = 0x300;
+        return (start + length);
+    }
     
     memset(p, 0, sizeof(*p));
 
@@ -403,9 +577,20 @@
     p->security_status = 0x02; /* unknown */
 
     start += sizeof(struct smbios_type_3);
-    
-    strcpy((char *)start, "Xen");
-    start += strlen("Xen") + 1;
+
+    s = xenstore_read("bios-strings/enclosure-manufacturer", "Xen");
+    strcpy((char *)start, s);
+    start += strlen(s) + 1;
+
+    /* no internal defaults for this if the value is not set */
+    s = xenstore_read("bios-strings/enclosure-serial-number", NULL);
+    if ( (s != NULL)&&(*s != '\0') )
+    {
+        strcpy((char *)start, s);
+        start += strlen(s) + 1;        
+        p->serial_number_str = 2;
+    }
+
     *((uint8_t *)start) = 0;
     return start+1;
 }
@@ -468,6 +653,15 @@
     char path[20] = "bios-strings/oem-XX";
     const char *s;
     int i;
+    uint32_t length;
+
+    length = smbios_passthrough(SPTARG(start, 11));
+    if ( length > 0 )
+    {
+        /* Fix up, use consistent handles */
+        p->header.handle = 0xB00;
+        return (start + length);
+    }
 
     p->header.type = 11;
     p->header.length = sizeof(struct smbios_type_11);
@@ -609,6 +803,63 @@
     return start+2;
 }
 
+/* Type 22 -- Portable Battery */
+static void *
+smbios_type_22_init(void *start)
+{
+    struct smbios_type_22 *p = (struct smbios_type_22 *)start;
+    static const char *smbios_release_date = __SMBIOS_DATE__;
+    uint32_t length;
+
+    if ( (get_smbios_info_flags() & HVM_SMBIOS_INCLUDE_PORTABLE_BATTERY) == 0 )
+        return start;
+
+    length = smbios_passthrough(SPTARG(start, 22));
+    if ( length > 0 )
+    {
+        /* Fix up, use consistent handles */
+        p->header.handle = 0x1600;
+
+        return (start + length);
+    }
+
+    memset(p, 0, sizeof(*p));
+
+    p->header.type = 22;
+    p->header.length = sizeof(struct smbios_type_22);
+    p->header.handle = 0x1600;
+
+    p->location_str = 1;
+    p->manufacturer_str = 2;
+    p->manufacturer_date_str = 3;
+    p->serial_number_str = 0;
+    p->device_name_str = 4;
+    p->device_chemistry = 0x2; /* Unknown */
+    p->device_capacity = 0; /* Unknown */
+    p->device_voltage = 0; /* Unknown */
+    p->sbds_version_number = 0;
+    p->max_error = 0xff; /* Unknown */
+    p->sbds_serial_number = 0;
+    p->sbds_manufacturer_date = 0;
+    p->sbds_device_chemistry = 0;
+    p->design_capacity_multiplier = 0;
+    p->oem_specific = 0;
+
+    start += sizeof(struct smbios_type_22);
+
+    strcpy((char *)start, "Primary");
+    start += strlen("Primary") + 1;
+    strcpy((char *)start, "Xen");
+    start += strlen("Xen") + 1;
+    strcpy((char *)start, smbios_release_date);
+    start += strlen(smbios_release_date) + 1;
+    strcpy((char *)start, "XEN-VBAT");
+    start += strlen("XEN-VBAT") + 1;
+
+    *((uint8_t *)start) = 0;
+    return start+1; 
+}
+
 /* Type 32 -- System Boot Information */
 static void *
 smbios_type_32_init(void *start)
@@ -628,6 +879,75 @@
     return start+2;
 }
 
+/* Type 39 -- Power Supply */
+static void *
+smbios_type_39_init(void *start)
+{
+    struct smbios_type_39 *p = (struct smbios_type_39 *)start;
+    uint32_t length;
+
+    if ( (get_smbios_info_flags() & HVM_SMBIOS_INCLUDE_POWER_SUPPLY) == 0 )
+        return start;
+
+    /* No default values - only present if the table is passed in */
+    length = smbios_passthrough(SPTARG(start, 39));
+    if ( length == 0 )
+        return start;
+
+    /* Fix up, use consistent handles */
+    p->header.handle = 0x2700;
+
+    /* These devices are not present */
+    p->input_voltage_probe_handle = 0xFFFF;
+    p->cooling_device_handle = 0xFFFF;
+    p->input_current_probe_handle = 0xFFFF;
+
+    return (start + length);
+}
+
+static void *
+smbios_type_vendor_oem_init(void *start)
+{
+    struct hvm_smbios_info_table *pa_smbt;
+    struct hvm_smbios_table_header *header;
+    uint32_t count;
+    uint8_t *ptr;    
+
+    pa_smbt = get_hvm_smbios_info_table();
+    if ( pa_smbt == NULL )
+        return start;
+    
+    if ( (pa_smbt->flags & HVM_SMBIOS_INCLUDE_VENDOR_OEM) == 0 )
+        return start;
+
+    header = (struct hvm_smbios_table_header*)
+        ((uint8_t*)pa_smbt + sizeof(struct hvm_smbios_info_table));
+
+    for ( count = 0; count < pa_smbt->count; count++ )
+    {
+        if ( header->length != 0 )
+        {
+            ptr = ((uint8_t*)header + sizeof(struct hvm_smbios_table_header));
+            if ( ptr[0] >= SMBIOS_VENDOR_OEM_TABLE_MIN )
+            {
+                /* Vendor/OEM table, copy it in. Note the handle values cannot
+                   be changed since it is unknown what is in each of these tables
+                   but they could contain handle references to other tables. This
+                   means a slight risk of collision with the tables above but that
+                   would have to be dealt with on a case by case basis. */
+                memcpy(start, ptr, header->length);
+                start += header->length;
+            }
+        }
+        else
+            printf("Empty SMBIOS OEM table passed to HVM loader, skipping.");
+
+        header = (struct hvm_smbios_table_header*)(ptr + header->length);
+    }
+
+    return start;
+}
+
 /* Type 127 -- End of Table */
 static void *
 smbios_type_127_init(void *start)
diff -r 0900b1c905f1 tools/firmware/hvmloader/smbios_types.h
--- a/tools/firmware/hvmloader/smbios_types.h	Mon Feb 20 18:58:07 2012 +0000
+++ b/tools/firmware/hvmloader/smbios_types.h	Mon Feb 20 20:56:58 2012 -0500
@@ -28,6 +28,9 @@
 
 #include <stdint.h>
 
+#define SMBIOS_VENDOR_OEM_TABLE_MIN 128
+#define SMBIOS_VENDOR_OEM_TABLE_MAX 255
+
 /* SMBIOS entry point -- must be written to a 16-bit aligned address
    between 0xf0000 and 0xfffff. 
  */
@@ -84,6 +87,15 @@
     uint8_t family_str;
 } __attribute__ ((packed));
 
+/* SMBIOS type 2 - Base Board Information */
+struct smbios_type_2 {
+    struct smbios_structure_header header;
+    uint8_t manufacturer_str;
+    uint8_t product_name_str;
+    uint8_t version_str;
+    uint8_t serial_number_str;
+} __attribute__ ((packed));
+
 /* SMBIOS type 3 - System Enclosure */
 struct smbios_type_3 {
     struct smbios_structure_header header;
@@ -173,6 +185,26 @@
     uint8_t interleaved_data_depth;
 } __attribute__ ((packed));
 
+/* SMBIOS type 22 - Portable battery */
+struct smbios_type_22 {
+    struct smbios_structure_header header;
+    uint8_t location_str;
+    uint8_t manufacturer_str;
+    uint8_t manufacturer_date_str;
+    uint8_t serial_number_str;
+    uint8_t device_name_str;
+    uint8_t device_chemistry;
+    uint16_t device_capacity;
+    uint16_t device_voltage;
+    uint8_t sbds_version_number;
+    uint8_t max_error;
+    uint16_t sbds_serial_number;
+    uint16_t sbds_manufacturer_date;
+    uint8_t sbds_device_chemistry;
+    uint8_t design_capacity_multiplier;
+    uint32_t oem_specific;
+} __attribute__ ((packed));
+
 /* SMBIOS type 32 - System Boot Information */
 struct smbios_type_32 {
     struct smbios_structure_header header;
@@ -180,6 +212,24 @@
     uint8_t boot_status;
 } __attribute__ ((packed));
 
+/* SMBIOS type 39 - Power Supply */
+struct smbios_type_39 {
+    struct smbios_structure_header header;
+    uint8_t power_unit_group;
+    uint8_t location_str;
+    uint8_t device_name_str;
+    uint8_t manufacturer_str;
+    uint8_t serial_number_str;
+    uint8_t asset_tag_number_str;
+    uint8_t model_part_number_str;
+    uint8_t revision_level_str;
+    uint16_t max_capacity;
+    uint16_t characteristics;
+    uint16_t input_voltage_probe_handle;
+    uint16_t cooling_device_handle;
+    uint16_t input_current_probe_handle;
+} __attribute__ ((packed));
+
 /* SMBIOS type 127 -- End-of-table */
 struct smbios_type_127 {
     struct smbios_structure_header header;

[-- Attachment #3: Type: text/plain, Size: 132 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xensource.com/xen-devel

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2012-02-21  2:56 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-02-21  2:56 [PATCH 3/3] SMBIOS table passthrough support Ross Philipson

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.