blob: 6584c55b31283fe535bd536ce703d890db5794e9 [file] [log] [blame]
Lee Leahy0946ec32015-04-20 15:24:54 -07001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2014 Google Inc.
Lee Leahya6089692016-01-05 16:34:58 -08005 * Copyright (C) 2015-2016 Intel Corporation.
Lee Leahy0946ec32015-04-20 15:24:54 -07006 *
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.
Lee Leahy0946ec32015-04-20 15:24:54 -070015 */
16
17#include <stddef.h>
Lee Leahy0946ec32015-04-20 15:24:54 -070018#include <arch/io.h>
19#include <arch/cbfs.h>
20#include <arch/stages.h>
21#include <arch/early_variables.h>
Duncan Laurie91da91f2015-09-04 13:47:34 -070022#include <boardid.h>
Lee Leahy0946ec32015-04-20 15:24:54 -070023#include <console/console.h>
24#include <cbmem.h>
robbie zhang13a2e942016-02-10 11:40:11 -080025#include <cpu/intel/microcode.h>
Lee Leahy0946ec32015-04-20 15:24:54 -070026#include <cpu/x86/mtrr.h>
27#include <ec/google/chromeec/ec.h>
28#include <ec/google/chromeec/ec_commands.h>
29#include <elog.h>
Lee Leahyb092c9e2016-01-01 18:09:50 -080030#include <fsp/romstage.h>
Lee Leahy0946ec32015-04-20 15:24:54 -070031#include <reset.h>
32#include <romstage_handoff.h>
Lee Leahy0be6d932015-06-26 11:15:42 -070033#include <smbios.h>
Lee Leahy0946ec32015-04-20 15:24:54 -070034#include <soc/intel/common/mrc_cache.h>
Lee Leahy0946ec32015-04-20 15:24:54 -070035#include <stage_cache.h>
36#include <timestamp.h>
37#include <tpm.h>
38#include <vendorcode/google/chromeos/chromeos.h>
39
Aaron Durbine6af4be2015-09-24 12:26:31 -050040asmlinkage void *romstage_main(FSP_INFO_HEADER *fih)
Lee Leahy0946ec32015-04-20 15:24:54 -070041{
42 void *top_of_stack;
43 struct pei_data pei_data;
44 struct romstage_params params = {
Lee Leahy0946ec32015-04-20 15:24:54 -070045 .pei_data = &pei_data,
Aaron Durbine6af4be2015-09-24 12:26:31 -050046 .chipset_context = fih,
Lee Leahy0946ec32015-04-20 15:24:54 -070047 };
48
49 post_code(0x30);
50
Lee Leahy0946ec32015-04-20 15:24:54 -070051 timestamp_add_now(TS_START_ROMSTAGE);
52
robbie zhang13a2e942016-02-10 11:40:11 -080053 /* Load microcode before ram init */
54 if (IS_ENABLED(CONFIG_SUPPORT_CPU_UCODE_IN_CBFS))
55 intel_update_microcode_from_cbfs();
56
Lee Leahy0946ec32015-04-20 15:24:54 -070057 memset(&pei_data, 0, sizeof(pei_data));
58
Lee Leahy0946ec32015-04-20 15:24:54 -070059 /* Display parameters */
Lee Leahy0946ec32015-04-20 15:24:54 -070060 printk(BIOS_SPEW, "CONFIG_MMCONF_BASE_ADDRESS: 0x%08x\n",
61 CONFIG_MMCONF_BASE_ADDRESS);
Aaron Durbin929b6022015-12-09 16:00:18 -060062 printk(BIOS_INFO, "Using FSP 1.1\n");
Lee Leahy0946ec32015-04-20 15:24:54 -070063
64 /* Display FSP banner */
Aaron Durbine6af4be2015-09-24 12:26:31 -050065 print_fsp_info(fih);
Lee Leahy0946ec32015-04-20 15:24:54 -070066
Aaron Durbin929b6022015-12-09 16:00:18 -060067 /* Stash FSP version. */
68 params.fsp_version = fsp_version(fih);
69
Lee Leahy0946ec32015-04-20 15:24:54 -070070 /* Get power state */
71 params.power_state = fill_power_state();
72
Duncan Laurie91da91f2015-09-04 13:47:34 -070073 /*
74 * Read and print board version. Done after SOC romstage
75 * in case PCH needs to be configured to talk to the EC.
76 */
77 if (IS_ENABLED(CONFIG_BOARD_ID_AUTO))
78 printk(BIOS_INFO, "MLB: board version %d\n", board_id());
79
Lee Leahy0946ec32015-04-20 15:24:54 -070080 /* Call into mainboard. */
81 mainboard_romstage_entry(&params);
82 soc_after_ram_init(&params);
83 post_code(0x38);
84
85 top_of_stack = setup_stack_and_mtrrs();
86
Lee Leahy3e5bc1f2015-06-24 11:17:54 -070087 printk(BIOS_DEBUG, "Calling FspTempRamExit API\n");
88 timestamp_add_now(TS_FSP_TEMP_RAM_EXIT_START);
Lee Leahy0946ec32015-04-20 15:24:54 -070089 return top_of_stack;
90}
91
Aaron Durbine6af4be2015-09-24 12:26:31 -050092void *cache_as_ram_stage_main(FSP_INFO_HEADER *fih)
93{
94 return romstage_main(fih);
95}
96
Lee Leahy0946ec32015-04-20 15:24:54 -070097/* Entry from the mainboard. */
98void romstage_common(struct romstage_params *params)
99{
100 const struct mrc_saved_data *cache;
101 struct romstage_handoff *handoff;
102 struct pei_data *pei_data;
103
104 post_code(0x32);
105
106 timestamp_add_now(TS_BEFORE_INITRAM);
107
108 pei_data = params->pei_data;
109 pei_data->boot_mode = params->power_state->prev_sleep_state;
110
111#if IS_ENABLED(CONFIG_ELOG_BOOT_COUNT)
112 if (params->power_state->prev_sleep_state != SLEEP_STATE_S3)
113 boot_count_increment();
114#endif
115
116 /* Perform remaining SOC initialization */
117 soc_pre_ram_init(params);
118 post_code(0x33);
119
120 /* Check recovery and MRC cache */
121 params->pei_data->saved_data_size = 0;
122 params->pei_data->saved_data = NULL;
123 if (!params->pei_data->disable_saved_data) {
124 if (recovery_mode_enabled()) {
125 /* Recovery mode does not use MRC cache */
126 printk(BIOS_DEBUG,
127 "Recovery mode: not using MRC cache.\n");
Lee Leahya6089692016-01-05 16:34:58 -0800128 } else if (IS_ENABLED(CONFIG_CACHE_MRC_SETTINGS)
129 && (!mrc_cache_get_current_with_version(&cache,
130 params->fsp_version))) {
Lee Leahy0946ec32015-04-20 15:24:54 -0700131 /* MRC cache found */
132 params->pei_data->saved_data_size = cache->size;
133 params->pei_data->saved_data = &cache->data[0];
134 } else if (params->pei_data->boot_mode == SLEEP_STATE_S3) {
135 /* Waking from S3 and no cache. */
136 printk(BIOS_DEBUG,
137 "No MRC cache found in S3 resume path.\n");
138 post_code(POST_RESUME_FAILURE);
139 hard_reset();
140 } else {
141 printk(BIOS_DEBUG, "No MRC cache found.\n");
142 mainboard_check_ec_image(params);
143 }
144 }
145
146 /* Initialize RAM */
147 raminit(params);
148 timestamp_add_now(TS_AFTER_INITRAM);
149
150 /* Save MRC output */
Lee Leahya6089692016-01-05 16:34:58 -0800151 if (IS_ENABLED(CONFIG_CACHE_MRC_SETTINGS)) {
152 printk(BIOS_DEBUG, "MRC data at %p %d bytes\n",
153 pei_data->data_to_save, pei_data->data_to_save_size);
154 if ((params->pei_data->boot_mode != SLEEP_STATE_S3)
155 && (params->pei_data->data_to_save_size != 0)
156 && (params->pei_data->data_to_save != NULL))
157 mrc_cache_stash_data_with_version(
158 params->pei_data->data_to_save,
159 params->pei_data->data_to_save_size,
160 params->fsp_version);
Lee Leahy0946ec32015-04-20 15:24:54 -0700161 }
162
163 /* Save DIMM information */
164 mainboard_save_dimm_info(params);
165
166 /* Create romstage handof information */
167 handoff = romstage_handoff_find_or_add();
168 if (handoff != NULL)
169 handoff->s3_resume = (params->power_state->prev_sleep_state ==
170 SLEEP_STATE_S3);
171 else {
172 printk(BIOS_DEBUG, "Romstage handoff structure not added!\n");
173 hard_reset();
174 }
175
Duncan Lauriefe4983e2016-03-14 09:29:09 -0700176 /*
177 * Initialize the TPM, unless the TPM was already initialized
178 * in verstage and used to verify romstage.
179 */
180 if (IS_ENABLED(CONFIG_LPC_TPM) &&
181 !IS_ENABLED(CONFIG_RESUME_PATH_SAME_AS_BOOT) &&
182 !IS_ENABLED(CONFIG_VBOOT_STARTS_IN_BOOTBLOCK))
183 init_tpm(params->power_state->prev_sleep_state ==
184 SLEEP_STATE_S3);
Lee Leahy0946ec32015-04-20 15:24:54 -0700185}
186
Aaron Durbine6af4be2015-09-24 12:26:31 -0500187void after_cache_as_ram_stage(void)
Lee Leahy0946ec32015-04-20 15:24:54 -0700188{
Lee Leahy0946ec32015-04-20 15:24:54 -0700189 /* Load the ramstage. */
190 copy_and_run();
191 die("ERROR - Failed to load ramstage!");
192}
193
194/* Initialize the power state */
195__attribute__((weak)) struct chipset_power_state *fill_power_state(void)
196{
197 printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
198 return NULL;
199}
200
201__attribute__((weak)) void mainboard_check_ec_image(
202 struct romstage_params *params)
203{
204 printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
205#if IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC)
206 struct pei_data *pei_data;
207
208 pei_data = params->pei_data;
209 if (params->pei_data->boot_mode == SLEEP_STATE_S0) {
210 /* Ensure EC is running RO firmware. */
211 google_chromeec_check_ec_image(EC_IMAGE_RO);
212 }
213#endif
214}
215
Lee Leahy0946ec32015-04-20 15:24:54 -0700216/* Board initialization before and after RAM is enabled */
217__attribute__((weak)) void mainboard_romstage_entry(
218 struct romstage_params *params)
219{
220 printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
221
222 post_code(0x31);
223
224 /* Initliaze memory */
225 romstage_common(params);
226}
227
228/* Save the DIMM information for SMBIOS table 17 */
Lee Leahy0946ec32015-04-20 15:24:54 -0700229__attribute__((weak)) void mainboard_save_dimm_info(
230 struct romstage_params *params)
231{
232 int channel;
233 CHANNEL_INFO *channel_info;
234 int dimm;
235 DIMM_INFO *dimm_info;
236 int dimm_max;
237 void *hob_list_ptr;
238 EFI_HOB_GUID_TYPE *hob_ptr;
239 int index;
240 struct memory_info *mem_info;
241 FSP_SMBIOS_MEMORY_INFO *memory_info_hob;
242 const EFI_GUID memory_info_hob_guid = FSP_SMBIOS_MEMORY_INFO_GUID;
243
244 /* Locate the memory info HOB, presence validated by raminit */
245 hob_list_ptr = fsp_get_hob_list();
246 hob_ptr = get_next_guid_hob(&memory_info_hob_guid, hob_list_ptr);
247 memory_info_hob = (FSP_SMBIOS_MEMORY_INFO *)(hob_ptr + 1);
248
249 /* Display the data in the FSP_SMBIOS_MEMORY_INFO HOB */
250 if (IS_ENABLED(CONFIG_DISPLAY_HOBS)) {
251 printk(BIOS_DEBUG, "FSP_SMBIOS_MEMORY_INFO HOB\n");
252 printk(BIOS_DEBUG, " 0x%02x: Revision\n",
253 memory_info_hob->Revision);
254 printk(BIOS_DEBUG, " 0x%02x: MemoryType\n",
255 memory_info_hob->MemoryType);
Lee Leahy0be6d932015-06-26 11:15:42 -0700256 printk(BIOS_DEBUG, " %d: MemoryFrequencyInMHz\n",
Lee Leahy0946ec32015-04-20 15:24:54 -0700257 memory_info_hob->MemoryFrequencyInMHz);
Lee Leahy0be6d932015-06-26 11:15:42 -0700258 printk(BIOS_DEBUG, " %d: DataWidth in bits\n",
259 memory_info_hob->DataWidth);
Lee Leahy0946ec32015-04-20 15:24:54 -0700260 printk(BIOS_DEBUG, " 0x%02x: ErrorCorrectionType\n",
261 memory_info_hob->ErrorCorrectionType);
262 printk(BIOS_DEBUG, " 0x%02x: ChannelCount\n",
263 memory_info_hob->ChannelCount);
264 for (channel = 0; channel < memory_info_hob->ChannelCount;
265 channel++) {
266 channel_info = &memory_info_hob->ChannelInfo[channel];
267 printk(BIOS_DEBUG, " Channel %d\n", channel);
268 printk(BIOS_DEBUG, " 0x%02x: ChannelId\n",
269 channel_info->ChannelId);
270 printk(BIOS_DEBUG, " 0x%02x: DimmCount\n",
271 channel_info->DimmCount);
272 for (dimm = 0; dimm < channel_info->DimmCount;
273 dimm++) {
274 dimm_info = &channel_info->DimmInfo[dimm];
275 printk(BIOS_DEBUG, " DIMM %d\n", dimm);
276 printk(BIOS_DEBUG, " 0x%02x: DimmId\n",
277 dimm_info->DimmId);
Lee Leahy0be6d932015-06-26 11:15:42 -0700278 printk(BIOS_DEBUG, " %d: SizeInMb\n",
Lee Leahy0946ec32015-04-20 15:24:54 -0700279 dimm_info->SizeInMb);
280 }
281 }
282 }
283
284 /*
285 * Allocate CBMEM area for DIMM information used to populate SMBIOS
286 * table 17
287 */
288 mem_info = cbmem_add(CBMEM_ID_MEMINFO, sizeof(*mem_info));
289 printk(BIOS_DEBUG, "CBMEM entry for DIMM info: 0x%p\n", mem_info);
290 if (mem_info == NULL)
291 return;
292 memset(mem_info, 0, sizeof(*mem_info));
293
294 /* Describe the first N DIMMs in the system */
295 index = 0;
296 dimm_max = ARRAY_SIZE(mem_info->dimm);
297 for (channel = 0; channel < memory_info_hob->ChannelCount; channel++) {
298 if (index >= dimm_max)
299 break;
300 channel_info = &memory_info_hob->ChannelInfo[channel];
301 for (dimm = 0; dimm < channel_info->DimmCount; dimm++) {
302 if (index >= dimm_max)
303 break;
304 dimm_info = &channel_info->DimmInfo[dimm];
305
306 /* Populate the DIMM information */
307 if (dimm_info->SizeInMb) {
308 mem_info->dimm[index].dimm_size =
309 dimm_info->SizeInMb;
310 mem_info->dimm[index].ddr_type =
311 memory_info_hob->MemoryType;
312 mem_info->dimm[index].ddr_frequency =
313 memory_info_hob->MemoryFrequencyInMHz;
314 mem_info->dimm[index].channel_num =
315 channel_info->ChannelId;
316 mem_info->dimm[index].dimm_num =
317 dimm_info->DimmId;
Lee Leahy0be6d932015-06-26 11:15:42 -0700318 switch (memory_info_hob->DataWidth) {
319 default:
320 case 8:
321 mem_info->dimm[index].bus_width =
322 MEMORY_BUS_WIDTH_8;
323 break;
324
325 case 16:
326 mem_info->dimm[index].bus_width =
327 MEMORY_BUS_WIDTH_16;
328 break;
329
330 case 32:
331 mem_info->dimm[index].bus_width =
332 MEMORY_BUS_WIDTH_32;
333 break;
334
335 case 64:
336 mem_info->dimm[index].bus_width =
337 MEMORY_BUS_WIDTH_64;
338 break;
339
340 case 128:
341 mem_info->dimm[index].bus_width =
342 MEMORY_BUS_WIDTH_128;
343 break;
344 }
Duncan Laurie46a2c772015-07-20 16:48:55 -0700345
346 /* Add any mainboard specific information */
347 mainboard_add_dimm_info(params, mem_info,
348 channel, dimm, index);
Lee Leahy0946ec32015-04-20 15:24:54 -0700349 index++;
350 }
351 }
352 }
353 mem_info->dimm_cnt = index;
354 printk(BIOS_DEBUG, "%d DIMMs found\n", mem_info->dimm_cnt);
355}
Lee Leahy0946ec32015-04-20 15:24:54 -0700356
Duncan Laurie46a2c772015-07-20 16:48:55 -0700357/* Add any mainboard specific information */
358__attribute__((weak)) void mainboard_add_dimm_info(
359 struct romstage_params *params,
360 struct memory_info *mem_info,
361 int channel, int dimm, int index)
362{
363 printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
364}
365
Lee Leahy0946ec32015-04-20 15:24:54 -0700366/* Get the memory configuration data */
Lee Leahyd52f2582016-05-31 18:12:53 -0700367__attribute__((weak)) int mrc_cache_get_current_with_version(
368 const struct mrc_saved_data **cache, uint32_t version)
Lee Leahy0946ec32015-04-20 15:24:54 -0700369{
370 printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
371 return -1;
372}
373
374/* Save the memory configuration data */
Lee Leahyd52f2582016-05-31 18:12:53 -0700375__attribute__((weak)) int mrc_cache_stash_data_with_version(const void *data,
376 size_t size, uint32_t version)
Lee Leahy0946ec32015-04-20 15:24:54 -0700377{
378 printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
379 return -1;
380}
381
382/* Transition RAM from off or self-refresh to active */
383__attribute__((weak)) void raminit(struct romstage_params *params)
384{
385 printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
386 post_code(0x34);
387 die("ERROR - No RAM initialization specified!\n");
388}
389
390void ramstage_cache_invalid(void)
391{
392 if (IS_ENABLED(CONFIG_RESET_ON_INVALID_RAMSTAGE_CACHE))
393 /* Perform cold reset on invalid ramstage cache. */
394 hard_reset();
395}
396
397/* Display the memory configuration */
398__attribute__((weak)) void report_memory_config(void)
399{
400 printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
401}
402
Lee Leahy0946ec32015-04-20 15:24:54 -0700403/* Choose top of stack and setup MTRRs */
404__attribute__((weak)) void *setup_stack_and_mtrrs(void)
405{
406 printk(BIOS_ERR, "WEAK: %s/%s called\n", __FILE__, __func__);
407 die("ERROR - Must specify top of stack!\n");
408 return NULL;
409}
410
Lee Leahy0946ec32015-04-20 15:24:54 -0700411/* SOC initialization after RAM is enabled */
412__attribute__((weak)) void soc_after_ram_init(struct romstage_params *params)
413{
414 printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
415}
416
Lee Leahy0946ec32015-04-20 15:24:54 -0700417/* SOC initialization before RAM is enabled */
418__attribute__((weak)) void soc_pre_ram_init(struct romstage_params *params)
419{
420 printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
421}