xref: /aosp_15_r20/external/coreboot/src/soc/intel/common/mma.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <bootstate.h>
4 #include <cbfs.h>
5 #include <cbmem.h>
6 #include <console/console.h>
7 #include <soc/intel/common/mma.h>
8 #include <string.h>
9 
10 #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))
17 
18 struct mma_data_container {
19 	uint32_t mma_signature; /* "MMAD" */
20 	uint8_t mma_data[]; /* Variable size, platform/run time dependent. */
21 } __packed;
22 
23 /*
24  * Format of the MMA test metadata file, stored under CBFS
25  * MMA_TEST_NAME=xxxxxx.efi;MMA_TEST_PARAM=xxxxxx.bin;
26  */
27 
28 /* Returns index in haystack after 'LABEL='
29  * string is found, < 0 on error.
30  */
find_label(const char * haystack,size_t haystack_sz,const char * label)31 static int find_label(const char *haystack, size_t haystack_sz,
32 		const char *label)
33 {
34 	size_t label_sz;
35 	size_t i;
36 	size_t search_sz;
37 
38 	label_sz = strlen(label);
39 
40 	if (label_sz + 1 >= haystack_sz)
41 		return -1;
42 
43 	/* Handle '=' follow label. i.e. LABEL= */
44 	search_sz = haystack_sz - label_sz - 1;
45 	for (i = 0; i < search_sz; i++) {
46 		if (!strncmp(&haystack[i], label, label_sz))
47 			break;
48 	}
49 
50 	if (i == search_sz)
51 		return -1;
52 
53 	if (haystack[i + label_sz] != '=')
54 		return -1;
55 
56 	return i + label_sz + 1;
57 }
58 
59 /*
60  * Fill in value in dest field located by LABEL=.
61  * Returns 0 on success, < 0 on  error.
62  */
label_value(const char * haystack,size_t haystack_sz,const char * label,char * dest,size_t dest_sz)63 static int label_value(const char *haystack, size_t haystack_sz,
64 		const char *label, char *dest, size_t dest_sz)
65 {
66 	size_t val_begin;
67 	size_t val_end;
68 	size_t val_sz;
69 	int val_index;
70 
71 	memset(dest, 0, dest_sz);
72 
73 	/* Allow for NULL termination. */
74 	dest_sz--;
75 	val_index = find_label(haystack, haystack_sz, label);
76 	if (val_index < 0)
77 		return -1;
78 
79 	val_begin = val_index;
80 	val_end = val_begin;
81 	val_sz = 0;
82 
83 	for (val_end = val_begin; val_end < haystack_sz; val_end++) {
84 		if (haystack[val_end] == ';') {
85 			val_sz = val_end - val_begin;
86 			break;
87 		}
88 	}
89 
90 	if (val_end == haystack_sz)
91 		return -1;
92 
93 	if (dest_sz < val_sz)
94 		return -1;
95 
96 	memcpy(dest, &haystack[val_begin], val_sz);
97 
98 	return 0;
99 }
100 
mma_map_param(struct mma_config_param * mma_cfg)101 int mma_map_param(struct mma_config_param *mma_cfg)
102 {
103 	void *mma_test_metadata;
104 	size_t mma_test_metadata_file_len;
105 	char test_filename[TEST_NAME_MAX_SIZE],
106 		test_param_filename[TEST_PARAM_MAX_SIZE];
107 	bool metadata_parse_flag = true;
108 
109 	printk(BIOS_DEBUG, "MMA: Entry %s\n", __func__);
110 
111 	mma_test_metadata = cbfs_ro_map(MMA_TEST_METADATA_FILENAME,
112 					&mma_test_metadata_file_len);
113 	if (!mma_test_metadata) {
114 		printk(BIOS_DEBUG, "MMA: Failed to map %s\n",
115 				MMA_TEST_METADATA_FILENAME);
116 		return -1;
117 	}
118 
119 	if (label_value(mma_test_metadata, mma_test_metadata_file_len,
120 			MMA_TEST_NAME_TAG, test_filename,
121 				TEST_NAME_MAX_SIZE)) {
122 		printk(BIOS_DEBUG, "MMA: Failed to get %s\n",
123 				MMA_TEST_NAME_TAG);
124 		metadata_parse_flag = false;
125 	}
126 
127 	if (metadata_parse_flag &&
128 		label_value(mma_test_metadata, mma_test_metadata_file_len,
129 			MMA_TEST_PARAM_TAG, test_param_filename,
130 				TEST_PARAM_MAX_SIZE)) {
131 		printk(BIOS_DEBUG, "MMA: Failed to get %s\n",
132 			MMA_TEST_PARAM_TAG);
133 		metadata_parse_flag = false;
134 	}
135 
136 	cbfs_unmap(mma_test_metadata);
137 
138 	if (!metadata_parse_flag)
139 		return -1;
140 
141 	printk(BIOS_DEBUG, "MMA: Got MMA_TEST_NAME=%s MMA_TEST_PARAM=%s\n",
142 			test_filename, test_param_filename);
143 
144 	mma_cfg->test_content = cbfs_ro_map(test_filename, &mma_cfg->test_content_size);
145 	if (!mma_cfg->test_content) {
146 		printk(BIOS_DEBUG, "MMA: Failed to map %s\n", test_filename);
147 		return -1;
148 	}
149 
150 	mma_cfg->test_param = cbfs_ro_map(test_param_filename, &mma_cfg->test_param_size);
151 	if (!mma_cfg->test_param) {
152 		printk(BIOS_DEBUG, "MMA: Failed to map %s\n", test_param);
153 		return -1;
154 	}
155 
156 	printk(BIOS_DEBUG, "MMA: %s exit success\n", __func__);
157 
158 	return 0;
159 }
160 
save_mma_results_data(void * unused)161 static void save_mma_results_data(void *unused)
162 {
163 	const void *mma_hob;
164 	size_t mma_hob_size;
165 	struct mma_data_container *mma_data;
166 	size_t mma_data_size;
167 
168 	printk(BIOS_DEBUG, "MMA: Entry %s\n", __func__);
169 
170 	if (fsp_locate_mma_results(&mma_hob, &mma_hob_size)) {
171 		printk(BIOS_DEBUG,
172 				"MMA: results data Hob not present\n");
173 		return;
174 	}
175 
176 	mma_data_size = ALIGN_UP(mma_hob_size, 16) +
177 			sizeof(struct mma_data_container);
178 
179 	mma_data = cbmem_add(CBMEM_ID_MMA_DATA, mma_data_size);
180 
181 	if (mma_data == NULL) {
182 		printk(BIOS_DEBUG,
183 			"MMA: CBMEM was not available to save the MMA data.\n");
184 		return;
185 	}
186 
187 	/*clear the mma_data before coping the actual data */
188 	memset(mma_data, 0, mma_data_size);
189 
190 	printk(BIOS_DEBUG,
191 		"MMA: copy MMA data to CBMEM(src %p, dest %p, %u bytes)\n",
192 			mma_hob, mma_data, mma_hob_size);
193 
194 	mma_data->mma_signature = MMA_DATA_SIGNATURE;
195 	memcpy(mma_data->mma_data, mma_hob, mma_hob_size);
196 
197 	printk(BIOS_DEBUG, "MMA: %s exit successfully\n", __func__);
198 }
199 
200 BOOT_STATE_INIT_ENTRY(BS_WRITE_TABLES, BS_ON_ENTRY,
201 			save_mma_results_data, NULL);
202