[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] HVM firmware passthrough SMBIOS processing


  • To: xen-changelog@xxxxxxxxxxxxxxxxxxx
  • From: Xen patchbot-unstable <patchbot@xxxxxxx>
  • Date: Fri, 11 Jan 2013 03:33:09 +0000
  • Delivery-date: Fri, 11 Jan 2013 03:33:23 +0000
  • List-id: "Change log for Mercurial \(receive only\)" <xen-changelog.lists.xen.org>

# HG changeset patch
# User Ross Philipson <ross.philipson@xxxxxxxxxx>
# Date 1357838290 0
# Node ID a7ce196f40444fafbe8f13b2d80e4885d4321806
# Parent  cabf395a6c849cc65e56f1640b18db0c3e0faf5d
HVM firmware passthrough SMBIOS processing

Passthrough support for the SMBIOS structures including three new DMTF
defined types and support for OEM defined tables. Passed in SMBIOS
types override the default internal values. Default values can be
enabled for the new type 22 portable battery using a xenstore
flag. All other new DMTF defined and OEM structures will only be added
to the SMBIOS table if passthrough values are present.

Signed-off-by: Ross Philipson <ross.philipson@xxxxxxxxxx>
Committed-by: Keir Fraser <keir@xxxxxxx>
---


diff -r cabf395a6c84 -r a7ce196f4044 tools/firmware/hvmloader/smbios.c
--- a/tools/firmware/hvmloader/smbios.c Thu Jan 10 17:17:21 2013 +0000
+++ b/tools/firmware/hvmloader/smbios.c Thu Jan 10 17:18:10 2013 +0000
@@ -26,16 +26,38 @@
 #include "smbios_types.h"
 #include "util.h"
 #include "hypercall.h"
+#include <xen/hvm/hvm_xs_strings.h>
 
+/* SBMIOS handle base values */
+#define SMBIOS_HANDLE_TYPE0   0x0000
+#define SMBIOS_HANDLE_TYPE1   0x0100
+#define SMBIOS_HANDLE_TYPE2   0x0200
+#define SMBIOS_HANDLE_TYPE3   0x0300
+#define SMBIOS_HANDLE_TYPE4   0x0400
+#define SMBIOS_HANDLE_TYPE11  0x0B00
+#define SMBIOS_HANDLE_TYPE16  0x1000
+#define SMBIOS_HANDLE_TYPE17  0x1100
+#define SMBIOS_HANDLE_TYPE19  0x1300
+#define SMBIOS_HANDLE_TYPE20  0x1400
+#define SMBIOS_HANDLE_TYPE22  0x1600
+#define SMBIOS_HANDLE_TYPE32  0x2000
+#define SMBIOS_HANDLE_TYPE39  0x2700
+#define SMBIOS_HANDLE_TYPE127 0x7f00
+
+static void
+smbios_pt_init(void);
+static void*
+get_smbios_pt_struct(uint8_t type, uint32_t *length_out);
+static void
+get_cpu_manufacturer(char *buf, int len);
 static int
 write_smbios_tables(void *ep, void *start,
                     uint32_t vcpus, uint64_t memsize,
                     uint8_t uuid[16], char *xen_version,
                     uint32_t xen_major_version, uint32_t xen_minor_version,
                     unsigned *nr_structs, unsigned *max_struct_size);
-
-static void
-get_cpu_manufacturer(char *buf, int len);
+static uint64_t
+get_memsize(void);
 static void
 smbios_entry_point_init(void *start,
                         uint16_t max_structure_size,
@@ -49,6 +71,8 @@ static void *
 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,10 +88,73 @@ smbios_type_19_init(void *start, uint32_
 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 uint32_t *smbios_pt_addr = NULL;
+static uint32_t smbios_pt_length = 0;
+
+static void
+smbios_pt_init(void)
+{
+    const char *s;
+
+    s = xenstore_read(HVM_XS_SMBIOS_PT_ADDRESS, NULL);
+    if ( s == NULL )
+        goto reset;
+
+    smbios_pt_addr = (uint32_t*)(uint32_t)strtoll(s, NULL, 0);
+    if ( smbios_pt_addr == NULL )
+        goto reset;
+
+    s = xenstore_read(HVM_XS_SMBIOS_PT_LENGTH, NULL);
+    if ( s == NULL )
+        goto reset;
+
+    smbios_pt_length = (uint32_t)strtoll(s, NULL, 0);
+    if ( smbios_pt_length == 0 )
+        goto reset;
+
+    return;
+
+reset:
+    smbios_pt_addr = NULL;
+    smbios_pt_length = 0;
+}
+
+static void*
+get_smbios_pt_struct(uint8_t type, uint32_t *length_out)
+{
+    uint32_t *sep = smbios_pt_addr;
+    uint32_t total = 0;
+    uint8_t *ptr;
+
+    if ( sep == NULL )
+        return NULL;
+
+    while ( total < smbios_pt_length )
+    {
+        ptr = (uint8_t*)(sep + 1);
+        if ( ptr[0] == type )
+        {
+            *length_out = *sep;
+            return ptr;
+        }
+
+        total += (*sep + sizeof(uint32_t));
+        sep = (uint32_t*)(ptr + *sep);
+    }
+
+    return NULL;
+}
+
 static void
 get_cpu_manufacturer(char *buf, int len)
 {
@@ -97,6 +184,8 @@ write_smbios_tables(void *ep, void *star
     char cpu_manufacturer[15];
     int i, nr_mem_devs;
 
+    smbios_pt_init();
+
     get_cpu_manufacturer(cpu_manufacturer, 15);
 
     p = (char *)start;
@@ -112,6 +201,7 @@ write_smbios_tables(void *ep, void *star
     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 +220,10 @@ write_smbios_tables(void *ep, void *star
         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,12 +382,22 @@ smbios_type_0_init(void *start, const ch
     struct smbios_type_0 *p = (struct smbios_type_0 *)start;
     static const char *smbios_release_date = __SMBIOS_DATE__;
     const char *s;
+    void *pts;
+    uint32_t length;
+
+    pts = get_smbios_pt_struct(0, &length);
+    if ( (pts != NULL)&&(length > 0) )
+    {
+        memcpy(start, pts, length);
+        p->header.handle = SMBIOS_HANDLE_TYPE0;
+        return (start + length);
+    }
 
     memset(p, 0, sizeof(*p));
 
     p->header.type = 0;
     p->header.length = sizeof(struct smbios_type_0);
-    p->header.handle = 0;
+    p->header.handle = SMBIOS_HANDLE_TYPE0;
 
     p->vendor_str = 1;
     p->version_str = 2;
@@ -315,11 +418,11 @@ smbios_type_0_init(void *start, const ch
     p->embedded_controller_minor = 0xff;
 
     start += sizeof(struct smbios_type_0);
-    s = xenstore_read("bios-strings/bios-vendor", "Xen");
+    s = xenstore_read(HVM_XS_BIOS_VENDOR, "Xen");
     strcpy((char *)start, s);
     start += strlen(s) + 1;
 
-    s = xenstore_read("bios-strings/bios-version", xen_version);
+    s = xenstore_read(HVM_XS_BIOS_VERSION, xen_version);
     strcpy((char *)start, s);
     start += strlen(s) + 1;
 
@@ -338,12 +441,22 @@ smbios_type_1_init(void *start, const ch
     char uuid_str[37];
     struct smbios_type_1 *p = (struct smbios_type_1 *)start;
     const char *s;
+    void *pts;
+    uint32_t length;
+
+    pts = get_smbios_pt_struct(1, &length);
+    if ( (pts != NULL)&&(length > 0) )
+    {
+        memcpy(start, pts, length);
+        p->header.handle = SMBIOS_HANDLE_TYPE1;
+        return (start + length);
+    }
 
     memset(p, 0, sizeof(*p));
 
     p->header.type = 1;
     p->header.length = sizeof(struct smbios_type_1);
-    p->header.handle = 0x100;
+    p->header.handle = SMBIOS_HANDLE_TYPE1;
 
     p->manufacturer_str = 1;
     p->product_name_str = 2;
@@ -358,20 +471,20 @@ smbios_type_1_init(void *start, const ch
 
     start += sizeof(struct smbios_type_1);
     
-    s = xenstore_read("bios-strings/system-manufacturer", "Xen");
+    s = xenstore_read(HVM_XS_SYSTEM_MANUFACTURER, "Xen");
     strcpy((char *)start, s);
     start += strlen(s) + 1;
 
-    s = xenstore_read("bios-strings/system-product-name", "HVM domU");
+    s = xenstore_read(HVM_XS_SYSTEM_PRODUCT_NAME, "HVM domU");
     strcpy((char *)start, s);
     start += strlen(s) + 1;
 
-    s = xenstore_read("bios-strings/system-version", xen_version);
+    s = xenstore_read(HVM_XS_SYSTEM_VERSION, xen_version);
     strcpy((char *)start, s);
     start += strlen(s) + 1;
 
     uuid_to_string(uuid_str, uuid); 
-    s = xenstore_read("bios-strings/system-serial-number", uuid_str);
+    s = xenstore_read(HVM_XS_SYSTEM_SERIAL_NUMBER, uuid_str);
     strcpy((char *)start, s);
     start += strlen(s) + 1;
 
@@ -380,17 +493,58 @@ smbios_type_1_init(void *start, const ch
     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 *ptr;
+    void *pts;
+    uint32_t length;
+
+    pts = get_smbios_pt_struct(2, &length);
+    if ( (pts != NULL)&&(length > 0) )
+    {
+        memcpy(start, pts, length);
+        p->header.handle = SMBIOS_HANDLE_TYPE2;
+
+        /* Set current chassis handle if present */
+        if ( p->header.length > 13 )
+        {
+            ptr = ((uint8_t*)start) + 11;            
+            if ( *((uint16_t*)ptr) != 0 )
+                *((uint16_t*)ptr) = SMBIOS_HANDLE_TYPE3;
+        }
+
+        return (start + length);
+    }
+
+    /* Only present when passed in */
+    return start;
+}
+
 /* 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;
+    void *pts;
+    uint32_t length;
+
+    pts = get_smbios_pt_struct(3, &length);
+    if ( (pts != NULL)&&(length > 0) )
+    {
+        memcpy(start, pts, length);
+        p->header.handle = SMBIOS_HANDLE_TYPE3;
+        return (start + length);
+    }
     
     memset(p, 0, sizeof(*p));
 
     p->header.type = 3;
     p->header.length = sizeof(struct smbios_type_3);
-    p->header.handle = 0x300;
+    p->header.handle = SMBIOS_HANDLE_TYPE3;
 
     p->manufacturer_str = 1;
     p->type = 0x01; /* other */
@@ -404,8 +558,19 @@ smbios_type_3_init(void *start)
 
     start += sizeof(struct smbios_type_3);
     
-    strcpy((char *)start, "Xen");
-    start += strlen("Xen") + 1;
+    s = xenstore_read(HVM_XS_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(HVM_XS_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;
 }
@@ -423,7 +588,7 @@ smbios_type_4_init(
 
     p->header.type = 4;
     p->header.length = sizeof(struct smbios_type_4);
-    p->header.handle = 0x400 + cpu_number;
+    p->header.handle = SMBIOS_HANDLE_TYPE4 + cpu_number;
 
     p->socket_designation_str = 1;
     p->processor_type = 0x03; /* CPU */
@@ -465,13 +630,23 @@ static void *
 smbios_type_11_init(void *start) 
 {
     struct smbios_type_11 *p = (struct smbios_type_11 *)start;
-    char path[20] = "bios-strings/oem-XX";
+    char path[20];
     const char *s;
     int i;
+    void *pts;
+    uint32_t length;
+
+    pts = get_smbios_pt_struct(11, &length);
+    if ( (pts != NULL)&&(length > 0) )
+    {
+        memcpy(start, pts, length);
+        p->header.handle = SMBIOS_HANDLE_TYPE11;
+        return (start + length);
+    }
 
     p->header.type = 11;
     p->header.length = sizeof(struct smbios_type_11);
-    p->header.handle = 0xB00;
+    p->header.handle = SMBIOS_HANDLE_TYPE11;
 
     p->count = 0;
 
@@ -480,8 +655,7 @@ smbios_type_11_init(void *start)
     /* Pull out as many oem-* strings we find in xenstore */
     for ( i = 1; i < 100; i++ )
     {
-        path[(sizeof path) - 3] = '0' + ((i < 10) ? i : i / 10);
-        path[(sizeof path) - 2] = (i < 10) ? '\0' : '0' + (i % 10);
+        snprintf(path, sizeof(path), HVM_XS_OEM_STRINGS, i);
         if ( ((s = xenstore_read(path, NULL)) == NULL) || (*s == '\0') )
             break;
         strcpy((char *)start, s);
@@ -510,7 +684,7 @@ smbios_type_16_init(void *start, uint32_
     memset(p, 0, sizeof(*p));
 
     p->header.type = 16;
-    p->header.handle = 0x1000;
+    p->header.handle = SMBIOS_HANDLE_TYPE16;
     p->header.length = sizeof(struct smbios_type_16);
     
     p->location = 0x01; /* other */
@@ -536,7 +710,7 @@ smbios_type_17_init(void *start, uint32_
 
     p->header.type = 17;
     p->header.length = sizeof(struct smbios_type_17);
-    p->header.handle = 0x1100 + instance;
+    p->header.handle = SMBIOS_HANDLE_TYPE17 + instance;
 
     p->physical_memory_array_handle = 0x1000;
     p->total_width = 64;
@@ -571,7 +745,7 @@ smbios_type_19_init(void *start, uint32_
 
     p->header.type = 19;
     p->header.length = sizeof(struct smbios_type_19);
-    p->header.handle = 0x1300 + instance;
+    p->header.handle = SMBIOS_HANDLE_TYPE19 + instance;
 
     p->starting_address = instance << 24;
     p->ending_address = p->starting_address + (memory_size_mb << 10) - 1;
@@ -593,7 +767,7 @@ smbios_type_20_init(void *start, uint32_
 
     p->header.type = 20;
     p->header.length = sizeof(struct smbios_type_20);
-    p->header.handle = 0x1400 + instance;
+    p->header.handle = SMBIOS_HANDLE_TYPE20 + instance;
 
     p->starting_address = instance << 24;
     p->ending_address = p->starting_address + (memory_size_mb << 10) - 1;
@@ -609,6 +783,71 @@ smbios_type_20_init(void *start, uint32_
     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__;
+    const char *s;
+    void *pts;
+    uint32_t length;
+
+    pts = get_smbios_pt_struct(22, &length);
+    if ( (pts != NULL)&&(length > 0) )
+    {
+        memcpy(start, pts, length);
+        p->header.handle = SMBIOS_HANDLE_TYPE22;
+        return (start + length);
+    }
+
+    s = xenstore_read(HVM_XS_SMBIOS_DEFAULT_BATTERY, "0");
+    if ( strncmp(s, "1", 1) != 0 )
+        return start;
+
+    memset(p, 0, sizeof(*p));
+
+    p->header.type = 22;
+    p->header.length = sizeof(struct smbios_type_22);
+    p->header.handle = SMBIOS_HANDLE_TYPE22;
+
+    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;
+
+    s = xenstore_read(HVM_XS_BATTERY_MANUFACTURER, "Xen");
+    strcpy((char *)start, s);
+    start += strlen(s) + 1;
+
+    strcpy((char *)start, smbios_release_date);
+    start += strlen(smbios_release_date) + 1;
+
+    s = xenstore_read(HVM_XS_BATTERY_DEVICE_NAME, "XEN-VBAT");
+    strcpy((char *)start, s);
+    start += strlen(s) + 1;
+
+    *((uint8_t *)start) = 0;
+
+    return start+1; 
+}
+
 /* Type 32 -- System Boot Information */
 static void *
 smbios_type_32_init(void *start)
@@ -619,7 +858,7 @@ smbios_type_32_init(void *start)
 
     p->header.type = 32;
     p->header.length = sizeof(struct smbios_type_32);
-    p->header.handle = 0x2000;
+    p->header.handle = SMBIOS_HANDLE_TYPE32;
     memset(p->reserved, 0, 6);
     p->boot_status = 0; /* no errors detected */
     
@@ -628,6 +867,58 @@ smbios_type_32_init(void *start)
     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;
+    void *pts;
+    uint32_t length;
+
+    pts = get_smbios_pt_struct(39, &length);
+    if ( (pts != NULL)&&(length > 0) )
+    {
+        memcpy(start, pts, length);
+        p->header.handle = SMBIOS_HANDLE_TYPE39;
+        return (start + length);
+    }
+
+    /* Only present when passed in */
+    return start;
+}
+
+static void *
+smbios_type_vendor_oem_init(void *start)
+{
+    uint32_t *sep = smbios_pt_addr;
+    uint32_t total = 0;
+    uint8_t *ptr;
+
+    if ( sep == NULL )
+        return start;
+
+    while ( total < smbios_pt_length )
+    {
+        ptr = (uint8_t*)(sep + 1);
+        if ( ptr[0] >= 128 )
+        {
+            /* 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, *sep);
+            start += *sep;
+        }
+
+        total += (*sep + sizeof(uint32_t));
+        sep = (uint32_t*)(ptr + *sep);
+    }
+
+    return start;
+}
+
 /* Type 127 -- End of Table */
 static void *
 smbios_type_127_init(void *start)
@@ -638,7 +929,7 @@ smbios_type_127_init(void *start)
 
     p->header.type = 127;
     p->header.length = sizeof(struct smbios_type_127);
-    p->header.handle = 0x7f00;
+    p->header.handle = SMBIOS_HANDLE_TYPE127;
 
     start += sizeof(struct smbios_type_127);
     *((uint16_t *)start) = 0;
diff -r cabf395a6c84 -r a7ce196f4044 tools/firmware/hvmloader/smbios_types.h
--- a/tools/firmware/hvmloader/smbios_types.h   Thu Jan 10 17:17:21 2013 +0000
+++ b/tools/firmware/hvmloader/smbios_types.h   Thu Jan 10 17:18:10 2013 +0000
@@ -84,6 +84,15 @@ struct smbios_type_1 {
     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 +182,26 @@ struct smbios_type_20 {
     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 +209,24 @@ struct smbios_type_32 {
     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;

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.