blob: a2ccaf5c167976662d871e6fd575f0990840cecb [file] [log] [blame]
Angel Pons0612b272020-04-05 15:46:56 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Pratik Prajapatib90b94d2015-09-11 13:51:38 -07002
Pratik Prajapatib90b94d2015-09-11 13:51:38 -07003#include <bootstate.h>
4#include <cbfs.h>
5#include <cbmem.h>
6#include <console/console.h>
Pratik Prajapatiffc934d2016-11-18 14:36:34 -08007#include <soc/intel/common/mma.h>
Elyes HAOUASa1e22b82019-03-18 22:49:36 +01008#include <string.h>
Pratik Prajapatib90b94d2015-09-11 13:51:38 -07009
Pratik Prajapatiffc934d2016-11-18 14:36:34 -080010#define MMA_TEST_METADATA_FILENAME "mma_test_metadata.bin"
11#define MMA_TEST_NAME_TAG "MMA_TEST_NAME"
12#define MMA_TEST_PARAM_TAG "MMA_TEST_PARAM"
13#define TEST_NAME_MAX_SIZE 30
14#define TEST_PARAM_MAX_SIZE 100
15#define MMA_DATA_SIGNATURE (('M' << 0) | ('M' << 8) | \
16 ('A' << 16) | ('D' << 24))
Pratik Prajapatide62e0f2016-02-22 16:50:31 -080017#define MMA_CBFS_REGION "COREBOOT"
Pratik Prajapatib90b94d2015-09-11 13:51:38 -070018
19struct mma_data_container {
Pratik Prajapatiffc934d2016-11-18 14:36:34 -080020 uint32_t mma_signature; /* "MMAD" */
21 uint8_t mma_data[0]; /* Variable size, platform/run time dependent. */
Stefan Reinauer6a001132017-07-13 02:20:27 +020022} __packed;
Pratik Prajapatib90b94d2015-09-11 13:51:38 -070023
24/*
Pratik Prajapatiffc934d2016-11-18 14:36:34 -080025 * Format of the MMA test metadata file, stored under CBFS
26 * MMA_TEST_NAME=xxxxxx.efi;MMA_TEST_PARAM=xxxxxx.bin;
27 */
Pratik Prajapatib90b94d2015-09-11 13:51:38 -070028
Pratik Prajapatiffc934d2016-11-18 14:36:34 -080029/* Returns index in haystack after 'LABEL='
30 * string is found, < 0 on error.
31 */
Pratik Prajapatib90b94d2015-09-11 13:51:38 -070032static int find_label(const char *haystack, size_t haystack_sz,
33 const char *label)
34{
35 size_t label_sz;
36 size_t i;
37 size_t search_sz;
38
39 label_sz = strlen(label);
40
41 if (label_sz + 1 >= haystack_sz)
42 return -1;
43
44 /* Handle '=' follow label. i.e. LABEL= */
45 search_sz = haystack_sz - label_sz - 1;
46 for (i = 0; i < search_sz; i++) {
47 if (!strncmp(&haystack[i], label, label_sz))
48 break;
49 }
50
51 if (i == search_sz)
52 return -1;
53
54 if (haystack[i + label_sz] != '=')
55 return -1;
56
57 return i + label_sz + 1;
58}
Pratik Prajapatiffc934d2016-11-18 14:36:34 -080059
Pratik Prajapatib90b94d2015-09-11 13:51:38 -070060/*
61 * Fill in value in dest field located by LABEL=.
Pratik Prajapatiffc934d2016-11-18 14:36:34 -080062 * Returns 0 on success, < 0 on error.
Pratik Prajapatib90b94d2015-09-11 13:51:38 -070063 */
64static int label_value(const char *haystack, size_t haystack_sz,
Pratik Prajapatiffc934d2016-11-18 14:36:34 -080065 const char *label, char *dest, size_t dest_sz)
Pratik Prajapatib90b94d2015-09-11 13:51:38 -070066{
67 size_t val_begin;
68 size_t val_end;
69 size_t val_sz;
70 int val_index;
71
72 memset(dest, 0, dest_sz);
73
74 /* Allow for NULL termination. */
75 dest_sz--;
76 val_index = find_label(haystack, haystack_sz, label);
77 if (val_index < 0)
78 return -1;
79
80 val_begin = val_index;
81 val_end = val_begin;
82 val_sz = 0;
83
84 for (val_end = val_begin; val_end < haystack_sz; val_end++) {
85 if (haystack[val_end] == ';') {
86 val_sz = val_end - val_begin;
87 break;
88 }
89 }
90
91 if (val_end == haystack_sz)
92 return -1;
93
94 if (dest_sz < val_sz)
95 return -1;
96
97 memcpy(dest, &haystack[val_begin], val_sz);
98
99 return 0;
100}
101
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800102int mma_locate_param(struct mma_config_param *mma_cfg)
Pratik Prajapatide62e0f2016-02-22 16:50:31 -0800103{
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800104 void *mma_test_metadata;
105 size_t mma_test_metadata_file_len;
Pratik Prajapatib90b94d2015-09-11 13:51:38 -0700106 char test_filename[TEST_NAME_MAX_SIZE],
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800107 test_param_filename[TEST_PARAM_MAX_SIZE];
108 struct cbfsf metadata_fh, test_content_fh, test_param_fh;
109 uint32_t mma_type = CBFS_TYPE_MMA;
110 uint32_t efi_type = CBFS_TYPE_EFI;
111 bool metadata_parse_flag = true;
Pratik Prajapatib90b94d2015-09-11 13:51:38 -0700112
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800113 printk(BIOS_DEBUG, "MMA: Entry %s\n", __func__);
Pratik Prajapatib90b94d2015-09-11 13:51:38 -0700114
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800115 if (cbfs_locate_file_in_region(&metadata_fh, MMA_CBFS_REGION,
116 MMA_TEST_METADATA_FILENAME, &mma_type)) {
117 printk(BIOS_DEBUG, "MMA: Failed to locate %s\n",
Pratik Prajapatib90b94d2015-09-11 13:51:38 -0700118 MMA_TEST_METADATA_FILENAME);
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800119 return -1;
120 }
121
122 mma_test_metadata = rdev_mmap_full(&metadata_fh.data);
123 mma_test_metadata_file_len = region_device_sz(&metadata_fh.data);
124
125 if (!mma_test_metadata || !mma_test_metadata_file_len) {
126 printk(BIOS_DEBUG, "MMA: Failed to read %s\n",
127 MMA_TEST_METADATA_FILENAME);
128 return -1;
Pratik Prajapatib90b94d2015-09-11 13:51:38 -0700129 }
130
131 if (label_value(mma_test_metadata, mma_test_metadata_file_len,
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800132 MMA_TEST_NAME_TAG, test_filename,
133 TEST_NAME_MAX_SIZE)) {
134 printk(BIOS_DEBUG, "MMA: Failed to get %s\n",
135 MMA_TEST_NAME_TAG);
136 metadata_parse_flag = false;
Pratik Prajapatib90b94d2015-09-11 13:51:38 -0700137 }
138
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800139 if (metadata_parse_flag &&
140 label_value(mma_test_metadata, mma_test_metadata_file_len,
Pratik Prajapatib90b94d2015-09-11 13:51:38 -0700141 MMA_TEST_PARAM_TAG, test_param_filename,
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800142 TEST_PARAM_MAX_SIZE)) {
143 printk(BIOS_DEBUG, "MMA: Failed to get %s\n",
Pratik Prajapatib90b94d2015-09-11 13:51:38 -0700144 MMA_TEST_PARAM_TAG);
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800145 metadata_parse_flag = false;
Pratik Prajapatib90b94d2015-09-11 13:51:38 -0700146 }
147
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800148 rdev_munmap(&metadata_fh.data, mma_test_metadata);
149
150 if (!metadata_parse_flag)
151 return -1;
152
153 printk(BIOS_DEBUG, "MMA: Got MMA_TEST_NAME=%s MMA_TEST_PARAM=%s\n",
Pratik Prajapatib90b94d2015-09-11 13:51:38 -0700154 test_filename, test_param_filename);
155
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800156 if (cbfs_locate_file_in_region(&test_content_fh, MMA_CBFS_REGION,
157 test_filename, &efi_type)) {
158 printk(BIOS_DEBUG, "MMA: Failed to locate %s\n",
159 test_filename);
160 return -1;
Pratik Prajapatib90b94d2015-09-11 13:51:38 -0700161 }
162
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800163 cbfs_file_data(&mma_cfg->test_content, &test_content_fh);
164
165 if (cbfs_locate_file_in_region(&test_param_fh, MMA_CBFS_REGION,
166 test_param_filename, &mma_type)) {
167 printk(BIOS_DEBUG, "MMA: Failed to locate %s\n",
Pratik Prajapatib90b94d2015-09-11 13:51:38 -0700168 test_param_filename);
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800169 return -1;
Pratik Prajapatib90b94d2015-09-11 13:51:38 -0700170 }
171
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800172 cbfs_file_data(&mma_cfg->test_param, &test_param_fh);
Pratik Prajapatib90b94d2015-09-11 13:51:38 -0700173
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800174 printk(BIOS_DEBUG, "MMA: %s exit success\n", __func__);
Pratik Prajapatiad8c35c2016-04-11 16:44:15 -0700175
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800176 return 0;
Pratik Prajapatib90b94d2015-09-11 13:51:38 -0700177}
178
179static void save_mma_results_data(void *unused)
180{
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800181 const void *mma_hob;
182 size_t mma_hob_size;
Pratik Prajapatib90b94d2015-09-11 13:51:38 -0700183 struct mma_data_container *mma_data;
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800184 size_t mma_data_size;
Pratik Prajapatib90b94d2015-09-11 13:51:38 -0700185
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800186 printk(BIOS_DEBUG, "MMA: Entry %s\n", __func__);
Pratik Prajapatib90b94d2015-09-11 13:51:38 -0700187
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800188 if (fsp_locate_mma_results(&mma_hob, &mma_hob_size)) {
Pratik Prajapatib90b94d2015-09-11 13:51:38 -0700189 printk(BIOS_DEBUG,
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800190 "MMA: results data Hob not present\n");
Pratik Prajapatib90b94d2015-09-11 13:51:38 -0700191 return;
192 }
193
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800194 mma_data_size = ALIGN(mma_hob_size, 16) +
Pratik Prajapatib90b94d2015-09-11 13:51:38 -0700195 sizeof(struct mma_data_container);
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800196
197 mma_data = cbmem_add(CBMEM_ID_MMA_DATA, mma_data_size);
Pratik Prajapatib90b94d2015-09-11 13:51:38 -0700198
199 if (mma_data == NULL) {
200 printk(BIOS_DEBUG,
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800201 "MMA: CBMEM was not available to save the MMA data.\n");
Pratik Prajapatib90b94d2015-09-11 13:51:38 -0700202 return;
203 }
204
205 /*clear the mma_data before coping the actual data */
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800206 memset(mma_data, 0, mma_data_size);
Pratik Prajapatib90b94d2015-09-11 13:51:38 -0700207
208 printk(BIOS_DEBUG,
Julius Werner540a9802019-12-09 13:03:29 -0800209 "MMA: copy MMA data to CBMEM(src %p, dest %p, %u bytes)\n",
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800210 mma_hob, mma_data, mma_hob_size);
Pratik Prajapatib90b94d2015-09-11 13:51:38 -0700211
212 mma_data->mma_signature = MMA_DATA_SIGNATURE;
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800213 memcpy(mma_data->mma_data, mma_hob, mma_hob_size);
Pratik Prajapatib90b94d2015-09-11 13:51:38 -0700214
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800215 printk(BIOS_DEBUG, "MMA: %s exit successfully\n", __func__);
Pratik Prajapatib90b94d2015-09-11 13:51:38 -0700216}
217
218BOOT_STATE_INIT_ENTRY(BS_WRITE_TABLES, BS_ON_ENTRY,
219 save_mma_results_data, NULL);