[coreboot-gerrit] New patch to review for coreboot: intel: Add MMA feature in coreboot

Patrick Georgi (pgeorgi@google.com) gerrit at coreboot.org
Thu Nov 19 17:12:45 CET 2015


Patrick Georgi (pgeorgi at google.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/12481

-gerrit

commit b95f4e8722bac61cc3aaa866c0b157549f9a3752
Author: Pratik Prajapati <pratikkumar.v.prajapati at intel.com>
Date:   Fri Sep 11 13:51:38 2015 -0700

    intel: Add MMA feature in coreboot
    
    This patch implements Memory Margin Analysis feature in coreboot.
    
    Few things to note
    (1) the feature is enabled by setting CONFIG_MMA=y in the config file
    (2) coreboot reads mma_test_metadata.bin from cbfs during romstage and
    gets the name of MMA test name and test config name. Then coreboot finds
    these files in CBFS.
    If found, coreboot passes location and size of these files to FSP via
    UPD params.  Sets MrcFastBoot to 0 so that MRC happens and then MMA test
    would be executed during memory init.
    (3) FSP passes MMA results data in HOB and coreboot saves it in cbmem
    (4) when system boots to OS after test is executed cbmem tool is used
    to grab the MMA results data.
    
    BRANCH=none
    BUG=chrome-os-partner:43731
    TEST=Build and Boot kunimitsu (FAB3) and executed MMA tests
    Not tested on Glados
    
    CQ-DEPEND=CL:299476,CL:299475,CL:299474,CL:299473,CL:299509,CL:299508,CL:299507,CL:*230478,CL:*230479
    
    Change-Id: I0b4524abcf57db4d2440a06a79b5a0f4b60fa0ea
    Signed-off-by: Patrick Georgi <pgeorgi at chromium.org>
    Original-Commit-Id: 4aba9b728c263b9d5da5746ede3807927c9cc2a7
    Original-Change-Id: Ie2728154b49eac8695f707127334b12e345398dc
    Original-Signed-off-by: Pratik Prajapati <pratikkumar.v.prajapati at intel.com>
    Original-Reviewed-on: https://chromium-review.googlesource.com/299476
    Original-Commit-Ready: Pratikkumar V Prajapati <pratikkumar.v.prajapati at intel.com>
    Original-Tested-by: Pratikkumar V Prajapati <pratikkumar.v.prajapati at intel.com>
    Original-Reviewed-by: Aaron Durbin <adurbin at chromium.org>
    Original-Reviewed-by: Pratikkumar V Prajapati <pratikkumar.v.prajapati at intel.com>
---
 src/commonlib/include/commonlib/cbfs_serialized.h |   2 +
 src/commonlib/include/commonlib/cbmem_id.h        |   2 +
 src/drivers/intel/fsp1_1/raminit.c                |   5 +
 src/soc/intel/common/Kconfig                      |  11 +
 src/soc/intel/common/Makefile.inc                 |  45 ++++
 src/soc/intel/common/mma.c                        | 244 ++++++++++++++++++++++
 src/soc/intel/common/mma.h                        |  27 +++
 7 files changed, 336 insertions(+)

diff --git a/src/commonlib/include/commonlib/cbfs_serialized.h b/src/commonlib/include/commonlib/cbfs_serialized.h
index 2efb532..edef551 100644
--- a/src/commonlib/include/commonlib/cbfs_serialized.h
+++ b/src/commonlib/include/commonlib/cbfs_serialized.h
@@ -72,6 +72,8 @@
 #define CBFS_TYPE_MICROCODE  0x53
 #define CBFS_TYPE_FSP        0x60
 #define CBFS_TYPE_MRC        0x61
+#define CBFS_TYPE_MMA        0x62
+#define CBFS_TYPE_EFI        0x63
 #define CBFS_COMPONENT_CMOS_DEFAULT 0xaa
 #define CBFS_TYPE_SPD          0xab
 #define CBFS_TYPE_MRC_CACHE    0xac
diff --git a/src/commonlib/include/commonlib/cbmem_id.h b/src/commonlib/include/commonlib/cbmem_id.h
index 44ab31e..729d38e 100644
--- a/src/commonlib/include/commonlib/cbmem_id.h
+++ b/src/commonlib/include/commonlib/cbmem_id.h
@@ -37,6 +37,7 @@
 #define CBMEM_ID_IMD_ROOT	0xff4017ff
 #define CBMEM_ID_IMD_SMALL	0x53a11439
 #define CBMEM_ID_MEMINFO	0x494D454D
+#define CBMEM_ID_MMA_DATA	0x4D4D4144
 #define CBMEM_ID_MPTABLE	0x534d5054
 #define CBMEM_ID_MRCDATA	0x4d524344
 #define CBMEM_ID_MTC		0xcb31d31c
@@ -84,6 +85,7 @@
 	{ CBMEM_ID_IMD_ROOT,		"IMD ROOT   " }, \
 	{ CBMEM_ID_IMD_SMALL,		"IMD SMALL  " }, \
 	{ CBMEM_ID_MEMINFO,		"MEM INFO   " }, \
+	{ CBMEM_ID_MMA_DATA,		"MMA DATA   " }, \
 	{ CBMEM_ID_MPTABLE,		"SMP TABLE  " }, \
 	{ CBMEM_ID_MRCDATA,		"MRC DATA   " }, \
 	{ CBMEM_ID_MTC,			"MTC        " }, \
diff --git a/src/drivers/intel/fsp1_1/raminit.c b/src/drivers/intel/fsp1_1/raminit.c
index c4b5b21..50704a8 100644
--- a/src/drivers/intel/fsp1_1/raminit.c
+++ b/src/drivers/intel/fsp1_1/raminit.c
@@ -19,6 +19,7 @@
 #include <fsp/util.h>
 #include <lib.h> /* hexdump */
 #include <reset.h>
+#include <soc/intel/common/mma.h>
 #include <soc/pei_data.h>
 #include <soc/romstage.h>
 #include <string.h>
@@ -98,6 +99,10 @@ void raminit(struct romstage_params *params)
 	/* Update the UPD data */
 	soc_memory_init_params(params, &memory_init_params);
 	mainboard_memory_init_params(params, &memory_init_params);
+
+	if (IS_ENABLED(CONFIG_MMA))
+		setup_mma(&memory_init_params);
+
 	post_code(0x36);
 
 	/* Display the UPD data */
diff --git a/src/soc/intel/common/Kconfig b/src/soc/intel/common/Kconfig
index 17c2809..547492b 100644
--- a/src/soc/intel/common/Kconfig
+++ b/src/soc/intel/common/Kconfig
@@ -48,4 +48,15 @@ config SOC_INTEL_COMMON_ACPI_WAKE_SOURCE
 	bool
 	default n
 
+config MMA
+        bool "enable MMA (Memory Margin Analysis) support"
+        default n
+        help
+         Set this option to y to enable MMA (Memory Margin Analysis) support
+
+config MMA_BLOBS_PATH
+        string "Path to MMA blobs"
+        depends on MMA
+        default "3rdparty/blobs/mainboard/$(MAINBOARDDIR)/mma"
+
 endif # SOC_INTEL_COMMON
diff --git a/src/soc/intel/common/Makefile.inc b/src/soc/intel/common/Makefile.inc
index 53d3b71..a7218b7 100644
--- a/src/soc/intel/common/Makefile.inc
+++ b/src/soc/intel/common/Makefile.inc
@@ -5,12 +5,14 @@ verstage-$(CONFIG_SOC_INTEL_COMMON_RESET) += reset.c
 romstage-$(CONFIG_CACHE_MRC_SETTINGS) += mrc_cache.c
 romstage-$(CONFIG_SOC_INTEL_COMMON_RESET) += reset.c
 romstage-y += util.c
+romstage-$(CONFIG_MMA) += mma.c
 
 ramstage-y += hda_verb.c
 ramstage-$(CONFIG_CACHE_MRC_SETTINGS) += mrc_cache.c
 ramstage-$(CONFIG_CACHE_MRC_SETTINGS) += nvm.c
 ramstage-$(CONFIG_SOC_INTEL_COMMON_RESET) += reset.c
 ramstage-y += util.c
+ramstage-$(CONFIG_MMA) += mma.c
 ramstage-$(CONFIG_SOC_INTEL_COMMON_ACPI_WAKE_SOURCE) += acpi_wake_source.c
 
 # Create and add the MRC cache to the cbfs image
@@ -26,4 +28,47 @@ mrc.cache-position := $(CONFIG_MRC_SETTINGS_CACHE_BASE)
 mrc.cache-type := mrc_cache
 endif
 
+ifeq ($(CONFIG_MMA),y)
+MMA_BLOBS_PATH = $(call strip_quotes,$(CONFIG_MMA_BLOBS_PATH))
+MMA_TEST_NAMES = $(notdir $(wildcard $(MMA_BLOBS_PATH)/tests/*))
+MMA_TEST_CONFIG_NAMES = $(notdir $(wildcard $(MMA_BLOBS_PATH)/configs/*))
+
+#
+# MMA_CBFS_template is the template to be expanded by eval
+# where $(1) is file name
+#	$(2) is file path
+#	$(3) is file type, efi for test names (all .EFI files under $(MMA_BLOBS_PATH)/tests )
+#			 , mma for test param (all .BIN files under $(MMA_BLOBS_PATH)/configs/<test name>)
+#
+# $(MMA_BLOBS_PATH)/tests/<testX>.efi has coresponding test params
+#  at $(MMA_BLOBS_PATH)/configs/<testX>/<XYZ>.bin
+#
+
+
+define MMA_CBFS_template =
+        cbfs-files-y += $(1)
+        $(1)-file := $(MMA_BLOBS_PATH)/$(2)/$(1)
+        $(1)-type := $(3)
+endef
+
+#
+# following loop calls MMA_CBFS_template for each .EFI file under $(MMA_BLOBS_PATH)/tests with type = efi
+#
+$(foreach mma_test,$(MMA_TEST_NAMES),$(eval $(call MMA_CBFS_template,$(mma_test),tests,efi)))
+
+
+#
+# following nested loops calls MMA_CBFS_template for each .BIN file under each MMA_TEST_CONFIG_NAMES
+#
+#  foreach <testX> do following
+#        foreach <XYZ>.bin in <testX> do following
+#                call MMA_CBFS_template for each <XYZ>.bin under current <testX> with type = mma
+#
+
+$(foreach mma_test, $(MMA_TEST_CONFIG_NAMES),\
+	$(eval $(foreach mma_config,$(notdir $(wildcard $(MMA_BLOBS_PATH)/configs/$(mma_test)/*)),\
+		$(eval $(call MMA_CBFS_template,$(mma_config),configs/$(mma_test),mma)))))
+
+endif
+
 endif
diff --git a/src/soc/intel/common/mma.c b/src/soc/intel/common/mma.c
new file mode 100644
index 0000000..3ac47e8
--- /dev/null
+++ b/src/soc/intel/common/mma.c
@@ -0,0 +1,244 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2015 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.
+ */
+
+#include <boot/coreboot_tables.h>
+#include <bootstate.h>
+#include <cbfs.h>
+#include <cbmem.h>
+#include <console/console.h>
+#include <lib.h>
+#include "mma.h"
+#include <soc/romstage.h>
+#include <string.h>
+
+#define MMA_TEST_METADATA_FILENAME      "mma_test_metadata.bin"
+#define MMA_TEST_NAME_TAG               "MMA_TEST_NAME"
+#define MMA_TEST_PARAM_TAG              "MMA_TEST_PARAM"
+#define TEST_NAME_MAX_SIZE              30
+#define TEST_PARAM_MAX_SIZE             100
+#define FSP_MMA_RESULTS_GUID            { 0x8f4e928, 0xf5f, 0x46d4, \
+                { 0x84, 0x10, 0x47, 0x9f, 0xda, 0x27, 0x9d, 0xb6 } }
+#define MMA_DATA_SIGNATURE      (('M'<<0)|('M'<<8)|('A'<<16)|('D'<<24))
+
+struct mma_data_container {
+        u32     mma_signature;  // "MMAD"
+        u8      mma_data[0];    // Variable size, platform/run time dependent.
+} __attribute__ ((packed));
+
+/*
+Format of the MMA test metadata file, stored under CBFS
+MMA_TEST_NAME=xxxxxx.efi;MMA_TEST_PARAM=xxxxxx.bin;
+*/
+
+/* Returns index in haystack after 'LABEL=' string is found, < 0 on error. */
+static int find_label(const char *haystack, size_t haystack_sz,
+		const char *label)
+{
+	size_t label_sz;
+	size_t i;
+	size_t search_sz;
+
+	label_sz = strlen(label);
+
+	if (label_sz + 1 >= haystack_sz)
+		return -1;
+
+	/* Handle '=' follow label. i.e. LABEL= */
+	search_sz = haystack_sz - label_sz - 1;
+	for (i = 0; i < search_sz; i++) {
+		if (!strncmp(&haystack[i], label, label_sz))
+			break;
+	}
+
+	if (i == search_sz)
+		return -1;
+
+	if (haystack[i + label_sz] != '=')
+		return -1;
+
+	return i + label_sz + 1;
+}
+/*
+ * Fill in value in dest field located by LABEL=.
+ *	Returns 0 on success, < 0 on  error.
+ */
+static int label_value(const char *haystack, size_t haystack_sz,
+			const char *label, char *dest, size_t dest_sz)
+{
+	size_t val_begin;
+	size_t val_end;
+	size_t val_sz;
+	int val_index;
+
+	memset(dest, 0, dest_sz);
+
+	/* Allow for NULL termination. */
+	dest_sz--;
+	val_index = find_label(haystack, haystack_sz, label);
+	if (val_index < 0)
+		return -1;
+
+	val_begin = val_index;
+	val_end = val_begin;
+	val_sz = 0;
+
+	for (val_end = val_begin; val_end < haystack_sz; val_end++) {
+		if (haystack[val_end] == ';') {
+			val_sz = val_end - val_begin;
+			break;
+		}
+	}
+
+	if (val_end == haystack_sz)
+		return -1;
+
+	if (dest_sz < val_sz)
+		return -1;
+
+	memcpy(dest, &haystack[val_begin], val_sz);
+
+	return 0;
+}
+
+void setup_mma(MEMORY_INIT_UPD *memory_params)
+{
+	void *mma_test_metadata, *mma_test_content, *mma_test_param;
+	size_t mma_test_metadata_file_len, mma_test_content_file_len,
+	       mma_test_param_file_len;
+	char test_filename[TEST_NAME_MAX_SIZE],
+	     test_param_filename[TEST_PARAM_MAX_SIZE];
+
+	printk(BIOS_DEBUG, "Entry setup_mma\n");
+
+	memory_params->MmaTestContentPtr = 0;
+	memory_params->MmaTestContentSize = 0;
+	memory_params->MmaTestConfigPtr = 0;
+	memory_params->MmaTestConfigSize = 0;
+
+	mma_test_metadata = cbfs_boot_map_with_leak(MMA_TEST_METADATA_FILENAME,
+			CBFS_TYPE_MMA , &mma_test_metadata_file_len);
+
+	if (!mma_test_metadata) {
+		printk(BIOS_DEBUG, "MMA setup failed: Failed to read %s\n",
+				MMA_TEST_METADATA_FILENAME);
+		return;
+	}
+
+	if (label_value(mma_test_metadata, mma_test_metadata_file_len,
+			MMA_TEST_NAME_TAG, test_filename, TEST_NAME_MAX_SIZE)) {
+			printk(BIOS_DEBUG, "MMA setup failed : Failed to get %s",
+					MMA_TEST_NAME_TAG);
+			return;
+	}
+
+	if (label_value(mma_test_metadata, mma_test_metadata_file_len,
+			MMA_TEST_PARAM_TAG, test_param_filename,
+			TEST_PARAM_MAX_SIZE)) {
+		printk(BIOS_DEBUG, "MMA setup failed : Failed to get %s",
+			MMA_TEST_PARAM_TAG);
+		return;
+	}
+
+	printk(BIOS_DEBUG, "Got MMA_TEST_NAME=%s MMA_TEST_PARAM=%s\n",
+			test_filename, test_param_filename);
+
+	mma_test_content = cbfs_boot_map_with_leak(test_filename,
+				CBFS_TYPE_EFI , &mma_test_content_file_len);
+	if (!mma_test_content) {
+		printk(BIOS_DEBUG, "MMA setup failed: Failed to read %s.\n",
+		test_filename);
+		return;
+	}
+
+	mma_test_param = cbfs_boot_map_with_leak(test_param_filename,
+				CBFS_TYPE_MMA , &mma_test_param_file_len);
+	if (!mma_test_param) {
+		printk(BIOS_DEBUG, "MMA setup failed: Failed to read %s.\n",
+				test_param_filename);
+		return;
+	}
+
+	memory_params->MmaTestContentPtr = (uintptr_t) mma_test_content;
+	memory_params->MmaTestContentSize = mma_test_content_file_len;
+	memory_params->MmaTestConfigPtr = (uintptr_t) mma_test_param;
+	memory_params->MmaTestConfigSize = mma_test_param_file_len;
+	memory_params->MrcFastBoot = 0x00;
+
+	printk(BIOS_DEBUG, "MMA Test name %s\n", test_filename);
+	printk(BIOS_DEBUG, "MMA Test Config name %s\n", test_param_filename);
+	printk(BIOS_DEBUG, "MMA passing following memory_params\n");
+	printk(BIOS_DEBUG, "memory_params->MmaTestContentPtr = %0x\n",
+			memory_params->MmaTestContentPtr);
+	printk(BIOS_DEBUG, "memory_params->MmaTestContentSize = %d\n",
+			memory_params->MmaTestContentSize);
+	printk(BIOS_DEBUG, "memory_params->MmaTestConfigPtr = %0x\n",
+			memory_params->MmaTestConfigPtr);
+	printk(BIOS_DEBUG, "memory_params->MmaTestConfigSize = %d\n",
+			memory_params->MmaTestConfigSize);
+	printk(BIOS_DEBUG, "memory_params->MrcFastBoot = %d\n",
+			memory_params->MrcFastBoot);
+	printk(BIOS_DEBUG, "MMA setup successfully\n");
+}
+
+static void save_mma_results_data(void *unused)
+{
+	void *mma_results_hob;
+	u32 mma_hob_size;
+	u32 *mma_hob_data;
+	struct mma_data_container *mma_data;
+	int cbmem_size;
+
+	const EFI_GUID mma_results_guid = FSP_MMA_RESULTS_GUID;
+
+	printk(BIOS_DEBUG, "Entry save_mma_results_data MMA save data.\n");
+
+	mma_results_hob = get_first_guid_hob(&mma_results_guid);
+	if (mma_results_hob == NULL) {
+		printk(BIOS_DEBUG,
+				"MMA results data Hob not present\n");
+		return;
+	}
+
+	mma_hob_data = GET_GUID_HOB_DATA(mma_results_hob);
+	mma_hob_size = GET_HOB_LENGTH(mma_results_hob);
+	cbmem_size = ALIGN(mma_hob_size, 16) +
+			sizeof(struct mma_data_container);
+	mma_data = cbmem_add(CBMEM_ID_MMA_DATA, cbmem_size);
+
+	if (mma_data == NULL) {
+		printk(BIOS_DEBUG,
+			"CBMEM was not available to save the MMA data.\n");
+		return;
+	}
+
+	/*clear the mma_data before coping the actual data */
+	memset(mma_data, 0, cbmem_size);
+
+	printk(BIOS_DEBUG,
+		"Copy MMA DATA to HOB(src addr %p, dest addr %p, %u bytes)\n",
+			mma_hob_data, mma_data, mma_hob_size);
+
+	mma_data->mma_signature = MMA_DATA_SIGNATURE;
+	memcpy(mma_data->mma_data, mma_hob_data, mma_hob_size);
+
+	printk(BIOS_DEBUG, "write MMA results data to cbmem success\n");
+}
+
+BOOT_STATE_INIT_ENTRY(BS_WRITE_TABLES, BS_ON_ENTRY,
+			save_mma_results_data, NULL);
diff --git a/src/soc/intel/common/mma.h b/src/soc/intel/common/mma.h
new file mode 100644
index 0000000..ab25ada
--- /dev/null
+++ b/src/soc/intel/common/mma.h
@@ -0,0 +1,27 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2015 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.
+ */
+
+#ifndef _SOC_MMA_H_
+#define _SOC_MMA_H_
+
+#include <fsp/soc_binding.h>
+
+void setup_mma(MEMORY_INIT_UPD *memory_params);
+
+#endif



More information about the coreboot-gerrit mailing list