blob: a58fe221f80034d55f88aca22d4dbbc92c2e47e8 [file] [log] [blame]
Pratik Prajapatib90b94d2015-09-11 13:51:38 -07001/*
2 * This file is part of the coreboot project.
3 *
Pratik Prajapatiffc934d2016-11-18 14:36:34 -08004 * Copyright (C) 2016 Intel Corporation.
Pratik Prajapatib90b94d2015-09-11 13:51:38 -07005 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
Pratik Prajapatib90b94d2015-09-11 13:51:38 -070014 */
15
Pratik Prajapatib90b94d2015-09-11 13:51:38 -070016#include <bootstate.h>
17#include <cbfs.h>
18#include <cbmem.h>
19#include <console/console.h>
Pratik Prajapatiffc934d2016-11-18 14:36:34 -080020#include <soc/intel/common/mma.h>
Pratik Prajapatib90b94d2015-09-11 13:51:38 -070021
Pratik Prajapatiffc934d2016-11-18 14:36:34 -080022#define MMA_TEST_METADATA_FILENAME "mma_test_metadata.bin"
23#define MMA_TEST_NAME_TAG "MMA_TEST_NAME"
24#define MMA_TEST_PARAM_TAG "MMA_TEST_PARAM"
25#define TEST_NAME_MAX_SIZE 30
26#define TEST_PARAM_MAX_SIZE 100
27#define MMA_DATA_SIGNATURE (('M' << 0) | ('M' << 8) | \
28 ('A' << 16) | ('D' << 24))
Pratik Prajapatide62e0f2016-02-22 16:50:31 -080029#define MMA_CBFS_REGION "COREBOOT"
Pratik Prajapatib90b94d2015-09-11 13:51:38 -070030
31struct mma_data_container {
Pratik Prajapatiffc934d2016-11-18 14:36:34 -080032 uint32_t mma_signature; /* "MMAD" */
33 uint8_t mma_data[0]; /* Variable size, platform/run time dependent. */
Pratik Prajapatib90b94d2015-09-11 13:51:38 -070034} __attribute__ ((packed));
35
36/*
Pratik Prajapatiffc934d2016-11-18 14:36:34 -080037 * Format of the MMA test metadata file, stored under CBFS
38 * MMA_TEST_NAME=xxxxxx.efi;MMA_TEST_PARAM=xxxxxx.bin;
39 */
Pratik Prajapatib90b94d2015-09-11 13:51:38 -070040
Pratik Prajapatiffc934d2016-11-18 14:36:34 -080041/* Returns index in haystack after 'LABEL='
42 * string is found, < 0 on error.
43 */
Pratik Prajapatib90b94d2015-09-11 13:51:38 -070044static int find_label(const char *haystack, size_t haystack_sz,
45 const char *label)
46{
47 size_t label_sz;
48 size_t i;
49 size_t search_sz;
50
51 label_sz = strlen(label);
52
53 if (label_sz + 1 >= haystack_sz)
54 return -1;
55
56 /* Handle '=' follow label. i.e. LABEL= */
57 search_sz = haystack_sz - label_sz - 1;
58 for (i = 0; i < search_sz; i++) {
59 if (!strncmp(&haystack[i], label, label_sz))
60 break;
61 }
62
63 if (i == search_sz)
64 return -1;
65
66 if (haystack[i + label_sz] != '=')
67 return -1;
68
69 return i + label_sz + 1;
70}
Pratik Prajapatiffc934d2016-11-18 14:36:34 -080071
Pratik Prajapatib90b94d2015-09-11 13:51:38 -070072/*
73 * Fill in value in dest field located by LABEL=.
Pratik Prajapatiffc934d2016-11-18 14:36:34 -080074 * Returns 0 on success, < 0 on error.
Pratik Prajapatib90b94d2015-09-11 13:51:38 -070075 */
76static int label_value(const char *haystack, size_t haystack_sz,
Pratik Prajapatiffc934d2016-11-18 14:36:34 -080077 const char *label, char *dest, size_t dest_sz)
Pratik Prajapatib90b94d2015-09-11 13:51:38 -070078{
79 size_t val_begin;
80 size_t val_end;
81 size_t val_sz;
82 int val_index;
83
84 memset(dest, 0, dest_sz);
85
86 /* Allow for NULL termination. */
87 dest_sz--;
88 val_index = find_label(haystack, haystack_sz, label);
89 if (val_index < 0)
90 return -1;
91
92 val_begin = val_index;
93 val_end = val_begin;
94 val_sz = 0;
95
96 for (val_end = val_begin; val_end < haystack_sz; val_end++) {
97 if (haystack[val_end] == ';') {
98 val_sz = val_end - val_begin;
99 break;
100 }
101 }
102
103 if (val_end == haystack_sz)
104 return -1;
105
106 if (dest_sz < val_sz)
107 return -1;
108
109 memcpy(dest, &haystack[val_begin], val_sz);
110
111 return 0;
112}
113
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800114int mma_locate_param(struct mma_config_param *mma_cfg)
Pratik Prajapatide62e0f2016-02-22 16:50:31 -0800115{
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800116 void *mma_test_metadata;
117 size_t mma_test_metadata_file_len;
Pratik Prajapatib90b94d2015-09-11 13:51:38 -0700118 char test_filename[TEST_NAME_MAX_SIZE],
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800119 test_param_filename[TEST_PARAM_MAX_SIZE];
120 struct cbfsf metadata_fh, test_content_fh, test_param_fh;
121 uint32_t mma_type = CBFS_TYPE_MMA;
122 uint32_t efi_type = CBFS_TYPE_EFI;
123 bool metadata_parse_flag = true;
Pratik Prajapatib90b94d2015-09-11 13:51:38 -0700124
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800125 printk(BIOS_DEBUG, "MMA: Entry %s\n", __func__);
Pratik Prajapatib90b94d2015-09-11 13:51:38 -0700126
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800127 if (cbfs_locate_file_in_region(&metadata_fh, MMA_CBFS_REGION,
128 MMA_TEST_METADATA_FILENAME, &mma_type)) {
129 printk(BIOS_DEBUG, "MMA: Failed to locate %s\n",
Pratik Prajapatib90b94d2015-09-11 13:51:38 -0700130 MMA_TEST_METADATA_FILENAME);
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800131 return -1;
132 }
133
134 mma_test_metadata = rdev_mmap_full(&metadata_fh.data);
135 mma_test_metadata_file_len = region_device_sz(&metadata_fh.data);
136
137 if (!mma_test_metadata || !mma_test_metadata_file_len) {
138 printk(BIOS_DEBUG, "MMA: Failed to read %s\n",
139 MMA_TEST_METADATA_FILENAME);
140 return -1;
Pratik Prajapatib90b94d2015-09-11 13:51:38 -0700141 }
142
143 if (label_value(mma_test_metadata, mma_test_metadata_file_len,
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800144 MMA_TEST_NAME_TAG, test_filename,
145 TEST_NAME_MAX_SIZE)) {
146 printk(BIOS_DEBUG, "MMA: Failed to get %s\n",
147 MMA_TEST_NAME_TAG);
148 metadata_parse_flag = false;
Pratik Prajapatib90b94d2015-09-11 13:51:38 -0700149 }
150
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800151 if (metadata_parse_flag &&
152 label_value(mma_test_metadata, mma_test_metadata_file_len,
Pratik Prajapatib90b94d2015-09-11 13:51:38 -0700153 MMA_TEST_PARAM_TAG, test_param_filename,
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800154 TEST_PARAM_MAX_SIZE)) {
155 printk(BIOS_DEBUG, "MMA: Failed to get %s\n",
Pratik Prajapatib90b94d2015-09-11 13:51:38 -0700156 MMA_TEST_PARAM_TAG);
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800157 metadata_parse_flag = false;
Pratik Prajapatib90b94d2015-09-11 13:51:38 -0700158 }
159
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800160 rdev_munmap(&metadata_fh.data, mma_test_metadata);
161
162 if (!metadata_parse_flag)
163 return -1;
164
165 printk(BIOS_DEBUG, "MMA: Got MMA_TEST_NAME=%s MMA_TEST_PARAM=%s\n",
Pratik Prajapatib90b94d2015-09-11 13:51:38 -0700166 test_filename, test_param_filename);
167
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800168 if (cbfs_locate_file_in_region(&test_content_fh, MMA_CBFS_REGION,
169 test_filename, &efi_type)) {
170 printk(BIOS_DEBUG, "MMA: Failed to locate %s\n",
171 test_filename);
172 return -1;
Pratik Prajapatib90b94d2015-09-11 13:51:38 -0700173 }
174
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800175 cbfs_file_data(&mma_cfg->test_content, &test_content_fh);
176
177 if (cbfs_locate_file_in_region(&test_param_fh, MMA_CBFS_REGION,
178 test_param_filename, &mma_type)) {
179 printk(BIOS_DEBUG, "MMA: Failed to locate %s\n",
Pratik Prajapatib90b94d2015-09-11 13:51:38 -0700180 test_param_filename);
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800181 return -1;
Pratik Prajapatib90b94d2015-09-11 13:51:38 -0700182 }
183
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800184 cbfs_file_data(&mma_cfg->test_param, &test_param_fh);
Pratik Prajapatib90b94d2015-09-11 13:51:38 -0700185
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800186 printk(BIOS_DEBUG, "MMA: %s exit success\n", __func__);
Pratik Prajapatiad8c35c2016-04-11 16:44:15 -0700187
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800188 return 0;
Pratik Prajapatib90b94d2015-09-11 13:51:38 -0700189}
190
191static void save_mma_results_data(void *unused)
192{
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800193 const void *mma_hob;
194 size_t mma_hob_size;
Pratik Prajapatib90b94d2015-09-11 13:51:38 -0700195 struct mma_data_container *mma_data;
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800196 size_t mma_data_size;
Pratik Prajapatib90b94d2015-09-11 13:51:38 -0700197
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800198 printk(BIOS_DEBUG, "MMA: Entry %s\n", __func__);
Pratik Prajapatib90b94d2015-09-11 13:51:38 -0700199
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800200 if (fsp_locate_mma_results(&mma_hob, &mma_hob_size)) {
Pratik Prajapatib90b94d2015-09-11 13:51:38 -0700201 printk(BIOS_DEBUG,
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800202 "MMA: results data Hob not present\n");
Pratik Prajapatib90b94d2015-09-11 13:51:38 -0700203 return;
204 }
205
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800206 mma_data_size = ALIGN(mma_hob_size, 16) +
Pratik Prajapatib90b94d2015-09-11 13:51:38 -0700207 sizeof(struct mma_data_container);
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800208
209 mma_data = cbmem_add(CBMEM_ID_MMA_DATA, mma_data_size);
Pratik Prajapatib90b94d2015-09-11 13:51:38 -0700210
211 if (mma_data == NULL) {
212 printk(BIOS_DEBUG,
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800213 "MMA: CBMEM was not available to save the MMA data.\n");
Pratik Prajapatib90b94d2015-09-11 13:51:38 -0700214 return;
215 }
216
217 /*clear the mma_data before coping the actual data */
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800218 memset(mma_data, 0, mma_data_size);
Pratik Prajapatib90b94d2015-09-11 13:51:38 -0700219
220 printk(BIOS_DEBUG,
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800221 "MMA: copy MMA data to CBMEM(src 0x%p, dest 0x%p, %u bytes)\n",
222 mma_hob, mma_data, mma_hob_size);
Pratik Prajapatib90b94d2015-09-11 13:51:38 -0700223
224 mma_data->mma_signature = MMA_DATA_SIGNATURE;
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800225 memcpy(mma_data->mma_data, mma_hob, mma_hob_size);
Pratik Prajapatib90b94d2015-09-11 13:51:38 -0700226
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800227 printk(BIOS_DEBUG, "MMA: %s exit successfully\n", __func__);
Pratik Prajapatib90b94d2015-09-11 13:51:38 -0700228}
229
230BOOT_STATE_INIT_ENTRY(BS_WRITE_TABLES, BS_ON_ENTRY,
231 save_mma_results_data, NULL);