Change license from GPLv3 to LGPLv3.
[seabios.git] / src / smbios.c
index fe78e12a20823570334aca9ca9402409a911c023..e2f21901420581b528b4e473e15b5f64e1c05c71 100644 (file)
@@ -3,42 +3,53 @@
 // Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
 // Copyright (C) 2006 Fabrice Bellard
 //
-// This file may be distributed under the terms of the GNU GPLv3 license.
+// This file may be distributed under the terms of the GNU LGPLv3 license.
 
 #include "util.h" // dprintf
 #include "memmap.h" // bios_table_cur_addr
+#include "biosvar.h" // GET_EBDA
 
 
 /****************************************************************
  * UUID probe
  ****************************************************************/
 
+#define QEMU_CFG_SIGNATURE  0x00
+#define QEMU_CFG_ID         0x01
+#define QEMU_CFG_UUID       0x02
+
+static void
+qemu_cfg_read(u8 *buf, u16 f, int len)
+{
+    outw(f, PORT_QEMU_CFG_CTL);
+    while (len--)
+        *(buf++) = inb(PORT_QEMU_CFG_DATA);
+}
+
+static int
+qemu_cfg_port_probe()
+{
+    u8 sig[4] = "QEMU";
+    u8 buf[4];
+    qemu_cfg_read(buf, QEMU_CFG_SIGNATURE, 4);
+    return *(u32*)buf == *(u32*)sig;
+}
+
 static void
 uuid_probe(u8 *bios_uuid)
 {
     // Default to UUID not set
     memset(bios_uuid, 0, 16);
 
-    if (! CONFIG_QEMU)
+    if (! CONFIG_UUID_BACKDOOR)
         return;
-
-    // check if backdoor port exists
-    u32 eax, ebx, ecx, edx;
-    asm volatile ("outl %%eax, %%dx"
-                  : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)
-                  : "a" (0x564d5868), "c" (0xa), "d" (0x5658));
-    if (ebx != 0x564d5868)
+    if (CONFIG_COREBOOT)
+        return;
+    if (! qemu_cfg_port_probe())
+        // Feature not available
         return;
 
-    u32 *uuid_ptr = (u32 *)bios_uuid;
-    // get uuid
-    asm volatile ("outl %%eax, %%dx"
-                  : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)
-                  : "a" (0x564d5868), "c" (0x13), "d" (0x5658));
-    uuid_ptr[0] = eax;
-    uuid_ptr[1] = ebx;
-    uuid_ptr[2] = ecx;
-    uuid_ptr[3] = edx;
+    qemu_cfg_read(bios_uuid, QEMU_CFG_UUID, 16);
 }
 
 
@@ -64,14 +75,14 @@ struct smbios_entry_point {
        u32 structure_table_address;
        u16 number_of_structures;
        u8 smbios_bcd_revision;
-} __attribute__((__packed__));
+} PACKED;
 
 /* This goes at the beginning of every SMBIOS structure. */
 struct smbios_structure_header {
        u8 type;
        u8 length;
        u16 handle;
-} __attribute__((__packed__));
+} PACKED;
 
 /* SMBIOS type 0 - BIOS Information */
 struct smbios_type_0 {
@@ -87,7 +98,7 @@ struct smbios_type_0 {
        u8 system_bios_minor_release;
        u8 embedded_controller_major_release;
        u8 embedded_controller_minor_release;
-} __attribute__((__packed__));
+} PACKED;
 
 /* SMBIOS type 1 - System Information */
 struct smbios_type_1 {
@@ -100,7 +111,7 @@ struct smbios_type_1 {
        u8 wake_up_type;
        u8 sku_number_str;
        u8 family_str;
-} __attribute__((__packed__));
+} PACKED;
 
 /* SMBIOS type 3 - System Enclosure (v2.3) */
 struct smbios_type_3 {
@@ -119,7 +130,7 @@ struct smbios_type_3 {
     u8 number_of_power_cords;
     u8 contained_element_count;
     // contained elements follow
-} __attribute__((__packed__));
+} PACKED;
 
 /* SMBIOS type 4 - Processor Information (v2.0) */
 struct smbios_type_4 {
@@ -136,7 +147,10 @@ struct smbios_type_4 {
        u16 current_speed;
        u8 status;
        u8 processor_upgrade;
-} __attribute__((__packed__));
+       u16 l1_cache_handle;
+       u16 l2_cache_handle;
+       u16 l3_cache_handle;
+} PACKED;
 
 /* SMBIOS type 16 - Physical Memory Array
  *   Associated with one type 17 (Memory Device).
@@ -149,7 +163,7 @@ struct smbios_type_16 {
        u32 maximum_capacity;
        u16 memory_error_information_handle;
        u16 number_of_memory_devices;
-} __attribute__((__packed__));
+} PACKED;
 
 /* SMBIOS type 17 - Memory Device
  *   Associated with one type 19
@@ -167,7 +181,7 @@ struct smbios_type_17 {
        u8 bank_locator_str;
        u8 memory_type;
        u16 type_detail;
-} __attribute__((__packed__));
+} PACKED;
 
 /* SMBIOS type 19 - Memory Array Mapped Address */
 struct smbios_type_19 {
@@ -176,7 +190,7 @@ struct smbios_type_19 {
        u32 ending_address;
        u16 memory_array_handle;
        u8 partition_width;
-} __attribute__((__packed__));
+} PACKED;
 
 /* SMBIOS type 20 - Memory Device Mapped Address */
 struct smbios_type_20 {
@@ -188,19 +202,19 @@ struct smbios_type_20 {
        u8 partition_row_position;
        u8 interleave_position;
        u8 interleaved_data_depth;
-} __attribute__((__packed__));
+} PACKED;
 
 /* SMBIOS type 32 - System Boot Information */
 struct smbios_type_32 {
        struct smbios_structure_header header;
        u8 reserved[6];
        u8 boot_status;
-} __attribute__((__packed__));
+} PACKED;
 
 /* SMBIOS type 127 -- End-of-table */
 struct smbios_type_127 {
        struct smbios_structure_header header;
-} __attribute__((__packed__));
+} PACKED;
 
 
 /****************************************************************
@@ -255,8 +269,8 @@ smbios_type_0_init(void *start)
     p->bios_release_date_str = 2;
     p->bios_rom_size = 0; /* FIXME */
 
-    memset(p->bios_characteristics, 0, 7);
-    p->bios_characteristics[7] = 0x08; /* BIOS characteristics not supported */
+    memset(p->bios_characteristics, 0, sizeof(p->bios_characteristics));
+    p->bios_characteristics[0] = 0x08; /* BIOS characteristics not supported */
     p->bios_characteristics_extension_bytes[0] = 0;
     p->bios_characteristics_extension_bytes[1] = 0;
 
@@ -361,6 +375,10 @@ smbios_type_4_init(void *start, unsigned int cpu_number)
     p->status = 0x41; /* socket populated, CPU enabled */
     p->processor_upgrade = 0x01; /* other */
 
+    p->l1_cache_handle = 0xffff; /* cache information structure not provided */
+    p->l2_cache_handle = 0xffff;
+    p->l3_cache_handle = 0xffff;
+
     start += sizeof(struct smbios_type_4);
 
     memcpy((char *)start, "CPU  " "\0" "" "\0" "", 7);
@@ -371,7 +389,7 @@ smbios_type_4_init(void *start, unsigned int cpu_number)
 
 /* Type 16 -- Physical Memory Array */
 static void *
-smbios_type_16_init(void *start, u32 memsize)
+smbios_type_16_init(void *start)
 {
     struct smbios_type_16 *p = (struct smbios_type_16*)start;
 
@@ -382,7 +400,8 @@ smbios_type_16_init(void *start, u32 memsize)
     p->location = 0x01; /* other */
     p->use = 0x03; /* system memory */
     p->error_correction = 0x01; /* other */
-    p->maximum_capacity = memsize * 1024;
+    u64 memsize = RamSize + RamSizeOver4G;
+    p->maximum_capacity = memsize / 1024;
     p->memory_error_information_handle = 0xfffe; /* none provided */
     p->number_of_memory_devices = 1;
 
@@ -394,7 +413,7 @@ smbios_type_16_init(void *start, u32 memsize)
 
 /* Type 17 -- Memory Device */
 static void *
-smbios_type_17_init(void *start, u32 memory_size_mb)
+smbios_type_17_init(void *start)
 {
     struct smbios_type_17 *p = (struct smbios_type_17 *)start;
 
@@ -407,7 +426,8 @@ smbios_type_17_init(void *start, u32 memory_size_mb)
     p->data_width = 64;
     /* truncate memory_size_mb to 16 bits and clear most significant
        bit [indicates size in MB] */
-    p->size = (u16) memory_size_mb & 0x7fff;
+    u64 memsize = RamSize + RamSizeOver4G;
+    p->size = (u16) (memsize / (1024*1024)) & 0x7fff;
     p->form_factor = 0x09; /* DIMM */
     p->device_set = 0;
     p->device_locator_str = 1;
@@ -425,7 +445,7 @@ smbios_type_17_init(void *start, u32 memory_size_mb)
 
 /* Type 19 -- Memory Array Mapped Address */
 static void *
-smbios_type_19_init(void *start, u32 memory_size_mb)
+smbios_type_19_init(void *start)
 {
     struct smbios_type_19 *p = (struct smbios_type_19 *)start;
 
@@ -434,7 +454,12 @@ smbios_type_19_init(void *start, u32 memory_size_mb)
     p->header.handle = 0x1300;
 
     p->starting_address = 0;
-    p->ending_address = (memory_size_mb-1) * 1024;
+    u64 memsize = RamSizeOver4G;
+    if (memsize)
+        memsize += 0x100000000ull;
+    else
+        memsize = RamSize;
+    p->ending_address = memsize / 1024 - 1;
     p->memory_array_handle = 0x1000;
     p->partition_width = 1;
 
@@ -446,7 +471,7 @@ smbios_type_19_init(void *start, u32 memory_size_mb)
 
 /* Type 20 -- Memory Device Mapped Address */
 static void *
-smbios_type_20_init(void *start, u32 memory_size_mb)
+smbios_type_20_init(void *start)
 {
     struct smbios_type_20 *p = (struct smbios_type_20 *)start;
 
@@ -455,7 +480,12 @@ smbios_type_20_init(void *start, u32 memory_size_mb)
     p->header.handle = 0x1400;
 
     p->starting_address = 0;
-    p->ending_address = (memory_size_mb-1)*1024;
+    u64 memsize = RamSizeOver4G;
+    if (memsize)
+        memsize += 0x100000000ull;
+    else
+        memsize = RamSize;
+    p->ending_address = memsize / 1024 - 1;
     p->memory_device_handle = 0x1100;
     p->memory_array_mapped_address_handle = 0x1300;
     p->partition_row_position = 1;
@@ -505,9 +535,13 @@ smbios_type_127_init(void *start)
 void
 smbios_init(void)
 {
+    if (! CONFIG_SMBIOS)
+        return;
+
+    dprintf(3, "init SMBIOS tables\n");
+
     unsigned cpu_num, nr_structs = 0, max_struct_size = 0;
     char *start, *p, *q;
-    int memsize = GET_EBDA(ram_size) / (1024 * 1024);
 
     bios_table_cur_addr = ALIGN(bios_table_cur_addr, 16);
     start = (void *)(bios_table_cur_addr);
@@ -528,10 +562,10 @@ smbios_init(void)
     int smp_cpus = smp_probe();
     for (cpu_num = 1; cpu_num <= smp_cpus; cpu_num++)
         add_struct(smbios_type_4_init(p, cpu_num));
-    add_struct(smbios_type_16_init(p, memsize));
-    add_struct(smbios_type_17_init(p, memsize));
-    add_struct(smbios_type_19_init(p, memsize));
-    add_struct(smbios_type_20_init(p, memsize));
+    add_struct(smbios_type_16_init(p));
+    add_struct(smbios_type_17_init(p));
+    add_struct(smbios_type_19_init(p));
+    add_struct(smbios_type_20_init(p));
     add_struct(smbios_type_32_init(p));
     add_struct(smbios_type_127_init(p));