blob: b85591d7e1b1f2ad7a461d6e12160e5be4779b3a [file] [log] [blame]
Lee Leahy0946ec32015-04-20 15:24:54 -07001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright 2015 Google Inc.
5 * Copyright (C) 2015 Intel Corporation.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.
19 */
20
21#include <cbmem.h>
22#include <cbfs.h>
23#include <console/console.h>
24#include <fsp_util.h>
25#include <lib.h>
26#include <romstage_handoff.h>
27#include <soc/intel/common/memmap.h>
28#include <soc/intel/common/ramstage.h>
29#include <stage_cache.h>
30#include <timestamp.h>
31
32/* SOC initialization after FSP silicon init */
33__attribute__((weak)) void soc_after_silicon_init(void)
34{
35 printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
36}
37
38/*
39 * SMM Memory Map:
40 *
41 * +--------------------------+ smm_region_size() ----.
42 * | FSP Cache | CONFIG_FSP_CACHE_SIZE |
43 * +--------------------------+ |
44 * | SMM Ramstage Cache | + CONFIG_SMM_RESERVED_SIZE
45 * +--------------------------+ ---------------------'
46 * | SMM Code |
47 * +--------------------------+ smm_base
48 *
49 */
50
51void stage_cache_external_region(void **base, size_t *size)
52{
53 size_t cache_size;
54 u8 *cache_base;
55
56 /* Determine the location of the ramstage cache */
57 smm_region((void **)&cache_base, &cache_size);
58 *size = CONFIG_SMM_RESERVED_SIZE - CONFIG_FSP_CACHE_SIZE;
59 *base = &cache_base[cache_size - CONFIG_SMM_RESERVED_SIZE];
60}
61
62static void *smm_fsp_cache_base(size_t *size)
63{
64 size_t cache_size;
65 u8 *cache_base;
66
67 /* Determine the location of the FSP cache */
68 stage_cache_external_region((void **)&cache_base, &cache_size);
69 *size = CONFIG_FSP_CACHE_SIZE;
70 return &cache_base[cache_size];
71}
72
73/* Display SMM memory map */
74static void smm_memory_map(void)
75{
76 u8 *smm_base;
77 size_t smm_bytes;
78 size_t smm_code_bytes;
79 u8 *fsp_cache;
80 size_t fsp_cache_bytes;
81 u8 *ramstage_cache;
82 size_t ramstage_cache_bytes;
83 u8 *smm_reserved;
84 size_t smm_reserved_bytes;
85
86 /* Locate the SMM regions */
87 smm_region((void **)&smm_base, &smm_bytes);
88 fsp_cache = smm_fsp_cache_base(&fsp_cache_bytes);
89 stage_cache_external_region((void **)&ramstage_cache, &ramstage_cache_bytes);
90 smm_code_bytes = ramstage_cache - smm_base;
91 smm_reserved = fsp_cache + fsp_cache_bytes;
92 smm_reserved_bytes = smm_bytes - fsp_cache_bytes - ramstage_cache_bytes
93 - smm_code_bytes;
94
95 /* Display the SMM regions */
96 printk(BIOS_SPEW, "\nLocation SMM Memory Map Offset\n");
97 if (smm_reserved_bytes) {
98 printk(BIOS_SPEW, "0x%p +--------------------------+ 0x%08x\n",
99 &smm_reserved[smm_reserved_bytes], (u32)smm_bytes);
100 printk(BIOS_SPEW, " | Other reserved region |\n");
101 }
102 printk(BIOS_SPEW, "0x%p +--------------------------+ 0x%08x\n",
103 smm_reserved, (u32)(smm_reserved - smm_base));
104 printk(BIOS_SPEW, " | FSP binary cache |\n");
105 printk(BIOS_SPEW, "0x%p +--------------------------+ 0x%08x\n",
106 fsp_cache, (u32)(fsp_cache - smm_base));
107 printk(BIOS_SPEW, " | ramstage cache |\n");
108 printk(BIOS_SPEW, "0x%p +--------------------------+ 0x%08x\n",
109 ramstage_cache, (u32)(ramstage_cache - smm_base));
110 printk(BIOS_SPEW, " | SMM code |\n");
111 printk(BIOS_SPEW, "0x%p +--------------------------+ 0x%08x\n",
112 smm_base, 0);
113 printk(BIOS_ERR, "\nCONFIG_FSP_CACHE_SIZE: 0x%08x bytes\n\n",
114 CONFIG_FSP_CACHE_SIZE);
115}
116
117struct smm_fsp_cache_header {
118 void *start;
119 size_t size;
120 FSP_INFO_HEADER *fih;
121};
122
123/* SoC implementation for caching support code. */
124static void soc_save_support_code(void *start, size_t size,
125 FSP_INFO_HEADER *fih)
126{
127 u8 *fsp_cache;
128 size_t fsp_cache_length;
129 struct smm_fsp_cache_header *header;
130 size_t smm_fsp_cache_length;
131
132 if (IS_ENABLED(CONFIG_DISPLAY_SMM_MEMORY_MAP))
133 smm_memory_map();
134
135 /* Locate the FSP cache in SMM */
136 fsp_cache = smm_fsp_cache_base(&smm_fsp_cache_length);
137
138 /* Initialize the FSP cache header */
139 header = (struct smm_fsp_cache_header *)fsp_cache;
140 fsp_cache += sizeof(*header);
141 header->start = start;
142 header->size = size;
143 header->fih = fih;
144
145 /* Validate the CONFIG_FSP_CACHE_SIZE value */
146 fsp_cache_length = sizeof(*header) + size;
147 if (smm_fsp_cache_length < fsp_cache_length) {
148 printk(BIOS_ERR, "CONFIG_FSP_CACHE_SIZE < 0x%08x bytes\n",
149 (u32)fsp_cache_length);
150 die("ERROR: Insufficent space to cache FSP binary!\n");
151 }
152
153 /* Copy the FSP binary into the SMM region for safe keeping */
154 memcpy(fsp_cache, start, size);
155}
156
157/* SoC implementation for restoring support code after S3 resume. Returns
158 * previously passed fih pointer from soc_save_support_code(). */
159static FSP_INFO_HEADER *soc_restore_support_code(void)
160{
161 u8 *fsp_cache;
162 struct smm_fsp_cache_header *header;
163 size_t smm_fsp_cache_length;
164
165 /* Locate the FSP cache in SMM */
166 fsp_cache = smm_fsp_cache_base(&smm_fsp_cache_length);
167
168 /* Get the FSP cache header */
169 header = (struct smm_fsp_cache_header *)fsp_cache;
170 fsp_cache += sizeof(*header);
171
172 /* Copy the FSP binary from the SMM region back into RAM */
173 memcpy(header->start, fsp_cache, header->size);
174
175 /* Return the FSP_INFO_HEADER address */
176 return header->fih;
177}
178
179static void fsp_run_silicon_init(struct romstage_handoff *handoff)
180{
181 FSP_INFO_HEADER *fsp_info_header;
182 FSP_SILICON_INIT fsp_silicon_init;
183 SILICON_INIT_UPD *original_params;
184 SILICON_INIT_UPD silicon_init_params;
185 EFI_STATUS status;
186 UPD_DATA_REGION *upd_ptr;
187 VPD_DATA_REGION *vpd_ptr;
188
189 /* Find the FSP image */
190 fsp_info_header = fsp_get_fih();
191 if (fsp_info_header == NULL) {
192 printk(BIOS_ERR, "FSP_INFO_HEADER not set!\n");
193 return;
194 }
195 print_fsp_info(fsp_info_header);
196
197 /* Initialize the UPD values */
198 vpd_ptr = (VPD_DATA_REGION *)(fsp_info_header->CfgRegionOffset +
199 fsp_info_header->ImageBase);
200 printk(BIOS_DEBUG, "0x%p: VPD Data\n", vpd_ptr);
201 upd_ptr = (UPD_DATA_REGION *)(vpd_ptr->PcdUpdRegionOffset +
202 fsp_info_header->ImageBase);
203 printk(BIOS_DEBUG, "0x%p: UPD Data\n", upd_ptr);
204 original_params = (void *)((u8 *)upd_ptr +
205 upd_ptr->SiliconInitUpdOffset);
206 memcpy(&silicon_init_params, original_params,
207 sizeof(silicon_init_params));
208 soc_silicon_init_params(&silicon_init_params);
209
210 /* Locate VBT and pass to FSP GOP */
211 if (IS_ENABLED(CONFIG_GOP_SUPPORT))
212 load_vbt(handoff->s3_resume, &silicon_init_params);
213 mainboard_silicon_init_params(&silicon_init_params);
214
215 /* Display the UPD data */
216 if (IS_ENABLED(CONFIG_DISPLAY_UPD_DATA))
217 soc_display_silicon_init_params(original_params,
218 &silicon_init_params);
219
220 /* Perform silicon initialization after RAM is configured */
221 printk(BIOS_DEBUG, "Calling FspSiliconInit\n");
222 fsp_silicon_init = (FSP_SILICON_INIT)(fsp_info_header->ImageBase
223 + fsp_info_header->FspSiliconInitEntryOffset);
224 timestamp_add_now(TS_FSP_SILICON_INIT_START);
225 printk(BIOS_DEBUG, "Calling FspSiliconInit(0x%p) at 0x%p\n",
226 &silicon_init_params, fsp_silicon_init);
227 status = fsp_silicon_init(&silicon_init_params);
228 timestamp_add_now(TS_FSP_SILICON_INIT_END);
229 printk(BIOS_DEBUG, "FspSiliconInit returned 0x%08x\n", status);
230
231#if IS_ENABLED(CONFIG_DISPLAY_HOBS)
232 /* Verify the HOBs */
233 const EFI_GUID graphics_info_guid = EFI_PEI_GRAPHICS_INFO_HOB_GUID;
234 void *hob_list_ptr = get_hob_list();
235 int missing_hob = 0;
236
237 if (hob_list_ptr == NULL)
238 die("ERROR - HOB pointer is NULL!\n");
239 print_hob_type_structure(0, hob_list_ptr);
240
241 /*
242 * Verify that FSP is generating the required HOBs:
243 * 7.1: FSP_BOOTLOADER_TEMP_MEMORY_HOB only produced for FSP 1.0
244 * 7.2: FSP_RESERVED_MEMORY_RESOURCE_HOB verified by raminit
245 * 7.3: FSP_NON_VOLATILE_STORAGE_HOB verified by raminit
246 * 7.4: FSP_BOOTLOADER_TOLUM_HOB verified by raminit
247 * 7.5: EFI_PEI_GRAPHICS_INFO_HOB verified below,
248 * if the ImageAttribute bit is set
249 * FSP_SMBIOS_MEMORY_INFO HOB verified by raminit
250 */
251 if ((fsp_info_header->ImageAttribute & GRAPHICS_SUPPORT_BIT) &&
252 !get_next_guid_hob(&graphics_info_guid, hob_list_ptr)) {
253 printk(BIOS_ERR, "7.5: EFI_PEI_GRAPHICS_INFO_HOB missing!\n");
254 missing_hob = 1;
255 }
256 if (missing_hob)
257 die("ERROR - Missing one or more required FSP HOBs!\n");
258#endif
259
260 soc_after_silicon_init();
261}
262
263static void fsp_cache_save(void)
264{
265 const struct cbmem_entry *fsp_entry;
266 FSP_INFO_HEADER *fih;
267
268 fsp_entry = cbmem_entry_find(CBMEM_ID_REFCODE);
269
270 if (fsp_entry == NULL) {
271 printk(BIOS_ERR, "ERROR: FSP not found in CBMEM.\n");
272 return;
273 }
274
275 fih = fsp_get_fih();
276
277 if (fih == NULL) {
278 printk(BIOS_ERR, "ERROR: No FIH found.\n");
279 return;
280 }
281
282 soc_save_support_code(cbmem_entry_start(fsp_entry),
283 cbmem_entry_size(fsp_entry), fih);
284}
285
286static int fsp_find_and_relocate(void)
287{
288 void *fih;
289 void *data;
290 size_t length;
291
292 data = cbfs_boot_map_with_leak("fsp.bin", CBFS_TYPE_FSP, &length);
293
294 if (data == NULL) {
295 printk(BIOS_ERR, "Couldn't find fsp.bin in CBFS.\n");
296 return -1;
297 }
298
299 fih = fsp_relocate(data, length);
300
301 fsp_update_fih(fih);
302
303 return 0;
304}
305
306void intel_silicon_init(void)
307{
308 struct romstage_handoff *handoff;
309
310 handoff = cbmem_find(CBMEM_ID_ROMSTAGE_INFO);
311
312 if (handoff != NULL && handoff->s3_resume) {
313 printk(BIOS_DEBUG, "FSP: Loading binary from cache\n");
314 fsp_update_fih(soc_restore_support_code());
315 } else {
316 fsp_find_and_relocate();
317 printk(BIOS_DEBUG, "FSP: Saving binary in cache\n");
318 fsp_cache_save();
319 }
320
321 fsp_run_silicon_init(handoff);
322}
323
324/* Initialize the UPD parameters for SiliconInit */
325__attribute__((weak)) void mainboard_silicon_init_params(
326 SILICON_INIT_UPD *params)
327{
328 printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
329};
330
331/* Display the UPD parameters for SiliconInit */
332__attribute__((weak)) void soc_display_silicon_init_params(
333 const SILICON_INIT_UPD *old, SILICON_INIT_UPD *new)
334{
335 printk(BIOS_SPEW, "UPD values for SiliconInit:\n");
336 hexdump32(BIOS_SPEW, new, sizeof(*new));
337}
338
339/* Initialize the UPD parameters for SiliconInit */
340__attribute__((weak)) void soc_silicon_init_params(SILICON_INIT_UPD *params)
341{
342 printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
343}