blob: 16db4dfd91f8cd6da7966b7f23d17c98edcfb1d9 [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.
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.
Lee Leahy0946ec32015-04-20 15:24:54 -070015 */
16
17#include <stddef.h>
18#include <stdint.h>
19#include <arch/cpu.h>
20#include <arch/io.h>
21#include <arch/cbfs.h>
22#include <arch/stages.h>
23#include <arch/early_variables.h>
Duncan Laurie91da91f2015-09-04 13:47:34 -070024#include <boardid.h>
Lee Leahy0946ec32015-04-20 15:24:54 -070025#include <console/console.h>
26#include <cbmem.h>
27#include <cpu/x86/mtrr.h>
28#include <ec/google/chromeec/ec.h>
29#include <ec/google/chromeec/ec_commands.h>
30#include <elog.h>
Aaron Durbine1ecfc92015-09-16 15:18:04 -050031#include <fsp/util.h>
Lee Leahy0946ec32015-04-20 15:24:54 -070032#include <memory_info.h>
33#include <reset.h>
34#include <romstage_handoff.h>
Lee Leahy0be6d932015-06-26 11:15:42 -070035#include <smbios.h>
Lee Leahy0946ec32015-04-20 15:24:54 -070036#include <soc/intel/common/mrc_cache.h>
37#include <soc/intel/common/util.h>
38#include <soc/pei_wrapper.h>
39#include <soc/pm.h>
40#include <soc/romstage.h>
41#include <soc/spi.h>
42#include <stage_cache.h>
43#include <timestamp.h>
44#include <tpm.h>
45#include <vendorcode/google/chromeos/chromeos.h>
46
Aaron Durbine6af4be2015-09-24 12:26:31 -050047asmlinkage void *romstage_main(FSP_INFO_HEADER *fih)
Lee Leahy0946ec32015-04-20 15:24:54 -070048{
49 void *top_of_stack;
50 struct pei_data pei_data;
51 struct romstage_params params = {
Lee Leahy0946ec32015-04-20 15:24:54 -070052 .pei_data = &pei_data,
Aaron Durbine6af4be2015-09-24 12:26:31 -050053 .chipset_context = fih,
Lee Leahy0946ec32015-04-20 15:24:54 -070054 };
55
56 post_code(0x30);
57
Lee Leahy0946ec32015-04-20 15:24:54 -070058 timestamp_add_now(TS_START_ROMSTAGE);
59
60 memset(&pei_data, 0, sizeof(pei_data));
61
Lee Leahy0946ec32015-04-20 15:24:54 -070062 /* Display parameters */
Lee Leahy0946ec32015-04-20 15:24:54 -070063 printk(BIOS_SPEW, "CONFIG_MMCONF_BASE_ADDRESS: 0x%08x\n",
64 CONFIG_MMCONF_BASE_ADDRESS);
Aaron Durbin929b6022015-12-09 16:00:18 -060065 printk(BIOS_INFO, "Using FSP 1.1\n");
Lee Leahy0946ec32015-04-20 15:24:54 -070066
67 /* Display FSP banner */
Aaron Durbine6af4be2015-09-24 12:26:31 -050068 print_fsp_info(fih);
Lee Leahy0946ec32015-04-20 15:24:54 -070069
Aaron Durbin929b6022015-12-09 16:00:18 -060070 /* Stash FSP version. */
71 params.fsp_version = fsp_version(fih);
72
Lee Leahy0946ec32015-04-20 15:24:54 -070073 /* Get power state */
74 params.power_state = fill_power_state();
75
Duncan Laurie91da91f2015-09-04 13:47:34 -070076 /*
77 * Read and print board version. Done after SOC romstage
78 * in case PCH needs to be configured to talk to the EC.
79 */
80 if (IS_ENABLED(CONFIG_BOARD_ID_AUTO))
81 printk(BIOS_INFO, "MLB: board version %d\n", board_id());
82
Lee Leahy0946ec32015-04-20 15:24:54 -070083 /* Call into mainboard. */
84 mainboard_romstage_entry(&params);
85 soc_after_ram_init(&params);
86 post_code(0x38);
87
88 top_of_stack = setup_stack_and_mtrrs();
89
Lee Leahy3e5bc1f2015-06-24 11:17:54 -070090 printk(BIOS_DEBUG, "Calling FspTempRamExit API\n");
91 timestamp_add_now(TS_FSP_TEMP_RAM_EXIT_START);
Lee Leahy0946ec32015-04-20 15:24:54 -070092 return top_of_stack;
93}
94
Aaron Durbine6af4be2015-09-24 12:26:31 -050095void *cache_as_ram_stage_main(FSP_INFO_HEADER *fih)
96{
97 return romstage_main(fih);
98}
99
Lee Leahy0946ec32015-04-20 15:24:54 -0700100/* Entry from the mainboard. */
101void romstage_common(struct romstage_params *params)
102{
103 const struct mrc_saved_data *cache;
104 struct romstage_handoff *handoff;
105 struct pei_data *pei_data;
106
107 post_code(0x32);
108
109 timestamp_add_now(TS_BEFORE_INITRAM);
110
111 pei_data = params->pei_data;
112 pei_data->boot_mode = params->power_state->prev_sleep_state;
113
114#if IS_ENABLED(CONFIG_ELOG_BOOT_COUNT)
115 if (params->power_state->prev_sleep_state != SLEEP_STATE_S3)
116 boot_count_increment();
117#endif
118
119 /* Perform remaining SOC initialization */
120 soc_pre_ram_init(params);
121 post_code(0x33);
122
123 /* Check recovery and MRC cache */
124 params->pei_data->saved_data_size = 0;
125 params->pei_data->saved_data = NULL;
126 if (!params->pei_data->disable_saved_data) {
127 if (recovery_mode_enabled()) {
128 /* Recovery mode does not use MRC cache */
129 printk(BIOS_DEBUG,
130 "Recovery mode: not using MRC cache.\n");
Aaron Durbin929b6022015-12-09 16:00:18 -0600131 } else if (!mrc_cache_get_current_with_version(&cache,
132 params->fsp_version)) {
Lee Leahy0946ec32015-04-20 15:24:54 -0700133 /* MRC cache found */
134 params->pei_data->saved_data_size = cache->size;
135 params->pei_data->saved_data = &cache->data[0];
136 } else if (params->pei_data->boot_mode == SLEEP_STATE_S3) {
137 /* Waking from S3 and no cache. */
138 printk(BIOS_DEBUG,
139 "No MRC cache found in S3 resume path.\n");
140 post_code(POST_RESUME_FAILURE);
141 hard_reset();
142 } else {
143 printk(BIOS_DEBUG, "No MRC cache found.\n");
144 mainboard_check_ec_image(params);
145 }
146 }
147
148 /* Initialize RAM */
149 raminit(params);
150 timestamp_add_now(TS_AFTER_INITRAM);
151
152 /* Save MRC output */
153 printk(BIOS_DEBUG, "MRC data at %p %d bytes\n", pei_data->data_to_save,
154 pei_data->data_to_save_size);
155 if (params->pei_data->boot_mode != SLEEP_STATE_S3) {
156 if (params->pei_data->data_to_save_size != 0 &&
157 params->pei_data->data_to_save != NULL) {
Aaron Durbin929b6022015-12-09 16:00:18 -0600158 mrc_cache_stash_data_with_version(
159 params->pei_data->data_to_save,
160 params->pei_data->data_to_save_size,
161 params->fsp_version);
Lee Leahy0946ec32015-04-20 15:24:54 -0700162 }
163 }
164
165 /* Save DIMM information */
166 mainboard_save_dimm_info(params);
167
168 /* Create romstage handof information */
169 handoff = romstage_handoff_find_or_add();
170 if (handoff != NULL)
171 handoff->s3_resume = (params->power_state->prev_sleep_state ==
172 SLEEP_STATE_S3);
173 else {
174 printk(BIOS_DEBUG, "Romstage handoff structure not added!\n");
175 hard_reset();
176 }
177
178 if (IS_ENABLED(CONFIG_LPC_TPM))
179 init_tpm(params->power_state->prev_sleep_state == SLEEP_STATE_S3);
180}
181
Aaron Durbine6af4be2015-09-24 12:26:31 -0500182void after_cache_as_ram_stage(void)
Lee Leahy0946ec32015-04-20 15:24:54 -0700183{
Lee Leahy0946ec32015-04-20 15:24:54 -0700184 /* Load the ramstage. */
185 copy_and_run();
186 die("ERROR - Failed to load ramstage!");
187}
188
189/* Initialize the power state */
190__attribute__((weak)) struct chipset_power_state *fill_power_state(void)
191{
192 printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
193 return NULL;
194}
195
196__attribute__((weak)) void mainboard_check_ec_image(
197 struct romstage_params *params)
198{
199 printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
200#if IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC)
201 struct pei_data *pei_data;
202
203 pei_data = params->pei_data;
204 if (params->pei_data->boot_mode == SLEEP_STATE_S0) {
205 /* Ensure EC is running RO firmware. */
206 google_chromeec_check_ec_image(EC_IMAGE_RO);
207 }
208#endif
209}
210
Lee Leahy0946ec32015-04-20 15:24:54 -0700211/* Board initialization before and after RAM is enabled */
212__attribute__((weak)) void mainboard_romstage_entry(
213 struct romstage_params *params)
214{
215 printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
216
217 post_code(0x31);
218
219 /* Initliaze memory */
220 romstage_common(params);
221}
222
223/* Save the DIMM information for SMBIOS table 17 */
Lee Leahy0946ec32015-04-20 15:24:54 -0700224__attribute__((weak)) void mainboard_save_dimm_info(
225 struct romstage_params *params)
226{
227 int channel;
228 CHANNEL_INFO *channel_info;
229 int dimm;
230 DIMM_INFO *dimm_info;
231 int dimm_max;
232 void *hob_list_ptr;
233 EFI_HOB_GUID_TYPE *hob_ptr;
234 int index;
235 struct memory_info *mem_info;
236 FSP_SMBIOS_MEMORY_INFO *memory_info_hob;
237 const EFI_GUID memory_info_hob_guid = FSP_SMBIOS_MEMORY_INFO_GUID;
238
239 /* Locate the memory info HOB, presence validated by raminit */
240 hob_list_ptr = fsp_get_hob_list();
241 hob_ptr = get_next_guid_hob(&memory_info_hob_guid, hob_list_ptr);
242 memory_info_hob = (FSP_SMBIOS_MEMORY_INFO *)(hob_ptr + 1);
243
244 /* Display the data in the FSP_SMBIOS_MEMORY_INFO HOB */
245 if (IS_ENABLED(CONFIG_DISPLAY_HOBS)) {
246 printk(BIOS_DEBUG, "FSP_SMBIOS_MEMORY_INFO HOB\n");
247 printk(BIOS_DEBUG, " 0x%02x: Revision\n",
248 memory_info_hob->Revision);
249 printk(BIOS_DEBUG, " 0x%02x: MemoryType\n",
250 memory_info_hob->MemoryType);
Lee Leahy0be6d932015-06-26 11:15:42 -0700251 printk(BIOS_DEBUG, " %d: MemoryFrequencyInMHz\n",
Lee Leahy0946ec32015-04-20 15:24:54 -0700252 memory_info_hob->MemoryFrequencyInMHz);
Lee Leahy0be6d932015-06-26 11:15:42 -0700253 printk(BIOS_DEBUG, " %d: DataWidth in bits\n",
254 memory_info_hob->DataWidth);
Lee Leahy0946ec32015-04-20 15:24:54 -0700255 printk(BIOS_DEBUG, " 0x%02x: ErrorCorrectionType\n",
256 memory_info_hob->ErrorCorrectionType);
257 printk(BIOS_DEBUG, " 0x%02x: ChannelCount\n",
258 memory_info_hob->ChannelCount);
259 for (channel = 0; channel < memory_info_hob->ChannelCount;
260 channel++) {
261 channel_info = &memory_info_hob->ChannelInfo[channel];
262 printk(BIOS_DEBUG, " Channel %d\n", channel);
263 printk(BIOS_DEBUG, " 0x%02x: ChannelId\n",
264 channel_info->ChannelId);
265 printk(BIOS_DEBUG, " 0x%02x: DimmCount\n",
266 channel_info->DimmCount);
267 for (dimm = 0; dimm < channel_info->DimmCount;
268 dimm++) {
269 dimm_info = &channel_info->DimmInfo[dimm];
270 printk(BIOS_DEBUG, " DIMM %d\n", dimm);
271 printk(BIOS_DEBUG, " 0x%02x: DimmId\n",
272 dimm_info->DimmId);
Lee Leahy0be6d932015-06-26 11:15:42 -0700273 printk(BIOS_DEBUG, " %d: SizeInMb\n",
Lee Leahy0946ec32015-04-20 15:24:54 -0700274 dimm_info->SizeInMb);
275 }
276 }
277 }
278
279 /*
280 * Allocate CBMEM area for DIMM information used to populate SMBIOS
281 * table 17
282 */
283 mem_info = cbmem_add(CBMEM_ID_MEMINFO, sizeof(*mem_info));
284 printk(BIOS_DEBUG, "CBMEM entry for DIMM info: 0x%p\n", mem_info);
285 if (mem_info == NULL)
286 return;
287 memset(mem_info, 0, sizeof(*mem_info));
288
289 /* Describe the first N DIMMs in the system */
290 index = 0;
291 dimm_max = ARRAY_SIZE(mem_info->dimm);
292 for (channel = 0; channel < memory_info_hob->ChannelCount; channel++) {
293 if (index >= dimm_max)
294 break;
295 channel_info = &memory_info_hob->ChannelInfo[channel];
296 for (dimm = 0; dimm < channel_info->DimmCount; dimm++) {
297 if (index >= dimm_max)
298 break;
299 dimm_info = &channel_info->DimmInfo[dimm];
300
301 /* Populate the DIMM information */
302 if (dimm_info->SizeInMb) {
303 mem_info->dimm[index].dimm_size =
304 dimm_info->SizeInMb;
305 mem_info->dimm[index].ddr_type =
306 memory_info_hob->MemoryType;
307 mem_info->dimm[index].ddr_frequency =
308 memory_info_hob->MemoryFrequencyInMHz;
309 mem_info->dimm[index].channel_num =
310 channel_info->ChannelId;
311 mem_info->dimm[index].dimm_num =
312 dimm_info->DimmId;
Lee Leahy0be6d932015-06-26 11:15:42 -0700313 switch (memory_info_hob->DataWidth) {
314 default:
315 case 8:
316 mem_info->dimm[index].bus_width =
317 MEMORY_BUS_WIDTH_8;
318 break;
319
320 case 16:
321 mem_info->dimm[index].bus_width =
322 MEMORY_BUS_WIDTH_16;
323 break;
324
325 case 32:
326 mem_info->dimm[index].bus_width =
327 MEMORY_BUS_WIDTH_32;
328 break;
329
330 case 64:
331 mem_info->dimm[index].bus_width =
332 MEMORY_BUS_WIDTH_64;
333 break;
334
335 case 128:
336 mem_info->dimm[index].bus_width =
337 MEMORY_BUS_WIDTH_128;
338 break;
339 }
Duncan Laurie46a2c772015-07-20 16:48:55 -0700340
341 /* Add any mainboard specific information */
342 mainboard_add_dimm_info(params, mem_info,
343 channel, dimm, index);
Lee Leahy0946ec32015-04-20 15:24:54 -0700344 index++;
345 }
346 }
347 }
348 mem_info->dimm_cnt = index;
349 printk(BIOS_DEBUG, "%d DIMMs found\n", mem_info->dimm_cnt);
350}
Lee Leahy0946ec32015-04-20 15:24:54 -0700351
Duncan Laurie46a2c772015-07-20 16:48:55 -0700352/* Add any mainboard specific information */
353__attribute__((weak)) void mainboard_add_dimm_info(
354 struct romstage_params *params,
355 struct memory_info *mem_info,
356 int channel, int dimm, int index)
357{
358 printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
359}
360
Lee Leahy0946ec32015-04-20 15:24:54 -0700361/* Get the memory configuration data */
362__attribute__((weak)) int mrc_cache_get_current(
363 const struct mrc_saved_data **cache)
364{
365 printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
366 return -1;
367}
368
369/* Save the memory configuration data */
370__attribute__((weak)) int mrc_cache_stash_data(void *data, size_t size)
371{
372 printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
373 return -1;
374}
375
376/* Transition RAM from off or self-refresh to active */
377__attribute__((weak)) void raminit(struct romstage_params *params)
378{
379 printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
380 post_code(0x34);
381 die("ERROR - No RAM initialization specified!\n");
382}
383
384void ramstage_cache_invalid(void)
385{
386 if (IS_ENABLED(CONFIG_RESET_ON_INVALID_RAMSTAGE_CACHE))
387 /* Perform cold reset on invalid ramstage cache. */
388 hard_reset();
389}
390
391/* Display the memory configuration */
392__attribute__((weak)) void report_memory_config(void)
393{
394 printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
395}
396
Lee Leahy0946ec32015-04-20 15:24:54 -0700397/* Choose top of stack and setup MTRRs */
398__attribute__((weak)) void *setup_stack_and_mtrrs(void)
399{
400 printk(BIOS_ERR, "WEAK: %s/%s called\n", __FILE__, __func__);
401 die("ERROR - Must specify top of stack!\n");
402 return NULL;
403}
404
Lee Leahy0946ec32015-04-20 15:24:54 -0700405/* SOC initialization after RAM is enabled */
406__attribute__((weak)) void soc_after_ram_init(struct romstage_params *params)
407{
408 printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
409}
410
Lee Leahy0946ec32015-04-20 15:24:54 -0700411/* SOC initialization before RAM is enabled */
412__attribute__((weak)) void soc_pre_ram_init(struct romstage_params *params)
413{
414 printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
415}