summaryrefslogtreecommitdiff
path: root/src/arch/x86/boot
diff options
context:
space:
mode:
authorKane Chen <kane.chen@intel.com>2014-07-27 12:54:44 -0700
committerPatrick Georgi <pgeorgi@google.com>2015-03-27 09:55:21 +0100
commit33faac643d8cbd521668f163df0a83865435e8c9 (patch)
tree23675b242eeaa063d608573515ef2cd071c6ae89 /src/arch/x86/boot
parentdc27ca9fcb64481b4557968ab3582e0db7831cf8 (diff)
smbios: add funtion for smbios type17
Add smbios type 17 which can optionally be implemented at the platform or mainboard level In order to create SMBIOS type17, you will need to fill memory_info data BUG=None BRANCH=None TEST=Compile successfully on rambi and samus Boot to chromeOS on samus and rambi Original-Change-Id: Ie4da89135c879d7a687305d423103fcfcbb96e3f Original-Signed-off-by: Kane Chen <kane.chen@intel.com> Original-Reviewed-on: https://chromium-review.googlesource.com/210005 Original-Reviewed-by: Aaron Durbin <adurbin@chromium.org> Original-Reviewed-by: Duncan Laurie <dlaurie@chromium.org> (cherry picked from commit 634b899ba41242caa800d7b570f3a339c738db77) Signed-off-by: Marc Jones <marc.jones@se-eng.com> Change-Id: I61d1e8b1d32d43f0011b0f93966d57646ea0eb63 Reviewed-on: http://review.coreboot.org/8955 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Georgi <pgeorgi@google.com>
Diffstat (limited to 'src/arch/x86/boot')
-rw-r--r--src/arch/x86/boot/smbios.c115
1 files changed, 115 insertions, 0 deletions
diff --git a/src/arch/x86/boot/smbios.c b/src/arch/x86/boot/smbios.c
index f2f998d7bc..16e25311a3 100644
--- a/src/arch/x86/boot/smbios.c
+++ b/src/arch/x86/boot/smbios.c
@@ -30,6 +30,9 @@
#include <cbfs_core.h>
#include <arch/byteorder.h>
#include <elog.h>
+#include <memory_info.h>
+#include <spd.h>
+#include <cbmem.h>
#if CONFIG_CHROMEOS
#include <vendorcode/google/chromeos/gnvs.h>
#endif
@@ -118,6 +121,97 @@ static int smbios_processor_name(char *start)
return smbios_add_string(start, tmp);
}
+/* this function will fill the corresponding manufacturer */
+static void fill_dimm_manufacturer(uint16_t mod_id, struct smbios_type17 *t)
+{
+ switch (mod_id) {
+ case 0xad80:
+ t->manufacturer = smbios_add_string(t->eos,
+ "Hynix/Hyundai");
+ break;
+ case 0xce80:
+ t->manufacturer = smbios_add_string(t->eos,
+ "Samsung");
+ break;
+ case 0xfe02:
+ t->manufacturer = smbios_add_string(t->eos,
+ "Elpida");
+ break;
+ default:
+ t->manufacturer = smbios_add_string(t->eos,
+ "Unknown");
+ break;
+ }
+}
+
+static int create_smbios_type17_for_dimm(struct dimm_info *dimm,
+ unsigned long *current, int *handle)
+{
+ struct smbios_type17 *t = (struct smbios_type17 *)*current;
+ uint8_t length;
+ char locator[40];
+
+ memset(t, 0, sizeof(struct smbios_type17));
+ t->memory_type = dimm->ddr_type;
+ t->clock_speed = dimm->ddr_frequency;
+ t->speed = dimm->ddr_frequency;
+ t->type = SMBIOS_MEMORY_DEVICE;
+ t->size = dimm->dimm_size;
+ t->data_width = 8 * (1 << (dimm->bus_width & 0x7));
+ t->total_width = t->data_width + 8 * ((dimm->bus_width & 0x18) >> 3);
+
+ switch (dimm->mod_type) {
+ case SPD_RDIMM:
+ case SPD_MINI_RDIMM:
+ t->form_factor = MEMORY_FORMFACTOR_RIMM;
+ break;
+ case SPD_UDIMM:
+ case SPD_MICRO_DIMM:
+ case SPD_MINI_UDIMM:
+ t->form_factor = MEMORY_FORMFACTOR_DIMM;
+ break;
+ case SPD_SODIMM:
+ t->form_factor = MEMORY_FORMFACTOR_SODIMM;
+ break;
+ default:
+ t->form_factor = MEMORY_FORMFACTOR_UNKNOWN;
+ break;
+ }
+
+ fill_dimm_manufacturer(dimm->mod_id, t);
+ /* put '\0' in the end of data */
+ length = sizeof(dimm->serial);
+ dimm->serial[length - 1] = '\0';
+ if (dimm->serial[0] == 0)
+ t->serial_number = smbios_add_string(t->eos, "None");
+ else
+ t->serial_number = smbios_add_string(t->eos,
+ (const char *)dimm->serial);
+
+ snprintf(locator, sizeof(locator), "Channel-%d-DIMM-%d",
+ dimm->channel_num, dimm->dimm_num);
+ t->device_locator = smbios_add_string(t->eos, locator);
+
+ snprintf(locator, sizeof(locator), "BANK %d", dimm->bank_locator);
+ t->bank_locator = smbios_add_string(t->eos, locator);
+
+ /* put '\0' in the end of data */
+ length = sizeof(dimm->module_part_number);
+ dimm->module_part_number[length - 1] = '\0';
+ t->part_number = smbios_add_string(t->eos,
+ (const char *)dimm->module_part_number);
+
+ /* Synchronous = 1 */
+ t->type_detail = 0x0080;
+ /* no handle for error information */
+ t->memory_error_information_handle = 0xFFFE;
+ t->attributes = dimm->rank_per_dimm;
+ t->handle = *handle;
+ *handle += 1;
+ t->length = sizeof(struct smbios_type17) - 2;
+ return t->length + smbios_string_table_len(t->eos);
+}
+
const char *__attribute__((weak)) smbios_mainboard_bios_version(void)
{
if (strlen(CONFIG_LOCALVERSION))
@@ -327,6 +421,26 @@ static int smbios_write_type11(unsigned long *current, int *handle)
return len;
}
+static int smbios_write_type17(unsigned long *current, int *handle)
+{
+ int len = sizeof(struct smbios_type17);
+ int i;
+
+ struct memory_info *meminfo;
+ meminfo = cbmem_find(CBMEM_ID_MEMINFO);
+ if (meminfo == NULL)
+ return 0; /* can't find mem info in cbmem */
+
+ printk(BIOS_INFO, "Create SMBIOS type 17\n");
+ for (i = 0; i < meminfo->dimm_cnt && i < ARRAY_SIZE(meminfo->dimm); i++) {
+ struct dimm_info *dimm;
+ dimm = &meminfo->dimm[i];
+ len = create_smbios_type17_for_dimm(dimm, current, handle);
+ *current += len;
+ }
+ return meminfo->dimm_cnt * len;
+}
+
static int smbios_write_type32(unsigned long *current, int handle)
{
struct smbios_type32 *t = (struct smbios_type32 *)*current;
@@ -416,6 +530,7 @@ unsigned long smbios_write_tables(unsigned long current)
#if CONFIG_ELOG
len += elog_smbios_write_type15(&current, handle++);
#endif
+ len += smbios_write_type17(&current, &handle);
len += smbios_write_type32(&current, handle++);
len += smbios_walk_device_tree(all_devices, &handle, &current);