blob: bb3e96c05109f65204c4484d7246b431caed2d69 [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>
Aaron Durbin932e09d2016-07-13 23:09:52 -050018#include <arch/acpi.h>
Lee Leahy0946ec32015-04-20 15:24:54 -070019#include <arch/io.h>
20#include <arch/cbfs.h>
Lee Leahy0946ec32015-04-20 15:24:54 -070021#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>
Kyösti Mälkki65e8f642016-06-27 11:27:56 +030032#include <program_loading.h>
Lee Leahy0946ec32015-04-20 15:24:54 -070033#include <romstage_handoff.h>
Lee Leahy0be6d932015-06-26 11:15:42 -070034#include <smbios.h>
Lee Leahy0946ec32015-04-20 15:24:54 -070035#include <soc/intel/common/mrc_cache.h>
Lee Leahy0946ec32015-04-20 15:24:54 -070036#include <stage_cache.h>
Aaron Durbinafe8aee2016-11-29 21:37:42 -060037#include <string.h>
Lee Leahy0946ec32015-04-20 15:24:54 -070038#include <timestamp.h>
39#include <tpm.h>
40#include <vendorcode/google/chromeos/chromeos.h>
41
Aaron Durbine6af4be2015-09-24 12:26:31 -050042asmlinkage void *romstage_main(FSP_INFO_HEADER *fih)
Lee Leahy0946ec32015-04-20 15:24:54 -070043{
44 void *top_of_stack;
45 struct pei_data pei_data;
46 struct romstage_params params = {
Lee Leahy0946ec32015-04-20 15:24:54 -070047 .pei_data = &pei_data,
Aaron Durbine6af4be2015-09-24 12:26:31 -050048 .chipset_context = fih,
Lee Leahy0946ec32015-04-20 15:24:54 -070049 };
50
51 post_code(0x30);
52
Lee Leahy0946ec32015-04-20 15:24:54 -070053 timestamp_add_now(TS_START_ROMSTAGE);
54
Elyes HAOUAS77537312016-07-30 15:37:26 +020055 /* Load microcode before RAM init */
robbie zhang13a2e942016-02-10 11:40:11 -080056 if (IS_ENABLED(CONFIG_SUPPORT_CPU_UCODE_IN_CBFS))
57 intel_update_microcode_from_cbfs();
58
Lee Leahy0946ec32015-04-20 15:24:54 -070059 memset(&pei_data, 0, sizeof(pei_data));
60
Lee Leahy0946ec32015-04-20 15:24:54 -070061 /* Display parameters */
Lee Leahy0946ec32015-04-20 15:24:54 -070062 printk(BIOS_SPEW, "CONFIG_MMCONF_BASE_ADDRESS: 0x%08x\n",
63 CONFIG_MMCONF_BASE_ADDRESS);
Aaron Durbin929b6022015-12-09 16:00:18 -060064 printk(BIOS_INFO, "Using FSP 1.1\n");
Lee Leahy0946ec32015-04-20 15:24:54 -070065
66 /* Display FSP banner */
Aaron Durbine6af4be2015-09-24 12:26:31 -050067 print_fsp_info(fih);
Lee Leahy0946ec32015-04-20 15:24:54 -070068
Aaron Durbin929b6022015-12-09 16:00:18 -060069 /* Stash FSP version. */
70 params.fsp_version = fsp_version(fih);
71
Lee Leahy0946ec32015-04-20 15:24:54 -070072 /* Get power state */
73 params.power_state = fill_power_state();
74
Duncan Laurie91da91f2015-09-04 13:47:34 -070075 /*
76 * Read and print board version. Done after SOC romstage
77 * in case PCH needs to be configured to talk to the EC.
78 */
79 if (IS_ENABLED(CONFIG_BOARD_ID_AUTO))
80 printk(BIOS_INFO, "MLB: board version %d\n", board_id());
81
Lee Leahy0946ec32015-04-20 15:24:54 -070082 /* Call into mainboard. */
83 mainboard_romstage_entry(&params);
84 soc_after_ram_init(&params);
85 post_code(0x38);
86
87 top_of_stack = setup_stack_and_mtrrs();
88
Lee Leahy3e5bc1f2015-06-24 11:17:54 -070089 printk(BIOS_DEBUG, "Calling FspTempRamExit API\n");
90 timestamp_add_now(TS_FSP_TEMP_RAM_EXIT_START);
Lee Leahy0946ec32015-04-20 15:24:54 -070091 return top_of_stack;
92}
93
Aaron Durbine6af4be2015-09-24 12:26:31 -050094void *cache_as_ram_stage_main(FSP_INFO_HEADER *fih)
95{
96 return romstage_main(fih);
97}
98
Lee Leahy0946ec32015-04-20 15:24:54 -070099/* Entry from the mainboard. */
100void romstage_common(struct romstage_params *params)
101{
102 const struct mrc_saved_data *cache;
Lee Leahy0946ec32015-04-20 15:24:54 -0700103 struct pei_data *pei_data;
104
105 post_code(0x32);
106
107 timestamp_add_now(TS_BEFORE_INITRAM);
108
109 pei_data = params->pei_data;
110 pei_data->boot_mode = params->power_state->prev_sleep_state;
111
112#if IS_ENABLED(CONFIG_ELOG_BOOT_COUNT)
Aaron Durbin932e09d2016-07-13 23:09:52 -0500113 if (params->power_state->prev_sleep_state != ACPI_S3)
Lee Leahy0946ec32015-04-20 15:24:54 -0700114 boot_count_increment();
115#endif
116
117 /* Perform remaining SOC initialization */
118 soc_pre_ram_init(params);
119 post_code(0x33);
120
121 /* Check recovery and MRC cache */
122 params->pei_data->saved_data_size = 0;
123 params->pei_data->saved_data = NULL;
124 if (!params->pei_data->disable_saved_data) {
Furquan Shaikh0325dc62016-07-25 13:02:36 -0700125 if (vboot_recovery_mode_enabled()) {
Lee Leahy0946ec32015-04-20 15:24:54 -0700126 /* Recovery mode does not use MRC cache */
127 printk(BIOS_DEBUG,
128 "Recovery mode: not using MRC cache.\n");
Lee Leahya6089692016-01-05 16:34:58 -0800129 } else if (IS_ENABLED(CONFIG_CACHE_MRC_SETTINGS)
130 && (!mrc_cache_get_current_with_version(&cache,
131 params->fsp_version))) {
Lee Leahy0946ec32015-04-20 15:24:54 -0700132 /* MRC cache found */
133 params->pei_data->saved_data_size = cache->size;
134 params->pei_data->saved_data = &cache->data[0];
Aaron Durbin932e09d2016-07-13 23:09:52 -0500135 } else if (params->pei_data->boot_mode == ACPI_S3) {
Lee Leahy0946ec32015-04-20 15:24:54 -0700136 /* Waking from S3 and no cache. */
137 printk(BIOS_DEBUG,
138 "No MRC cache found in S3 resume path.\n");
139 post_code(POST_RESUME_FAILURE);
140 hard_reset();
141 } else {
142 printk(BIOS_DEBUG, "No MRC cache found.\n");
143 mainboard_check_ec_image(params);
144 }
145 }
146
147 /* Initialize RAM */
148 raminit(params);
149 timestamp_add_now(TS_AFTER_INITRAM);
150
151 /* Save MRC output */
Lee Leahya6089692016-01-05 16:34:58 -0800152 if (IS_ENABLED(CONFIG_CACHE_MRC_SETTINGS)) {
153 printk(BIOS_DEBUG, "MRC data at %p %d bytes\n",
154 pei_data->data_to_save, pei_data->data_to_save_size);
Aaron Durbin932e09d2016-07-13 23:09:52 -0500155 if ((params->pei_data->boot_mode != ACPI_S3)
Lee Leahya6089692016-01-05 16:34:58 -0800156 && (params->pei_data->data_to_save_size != 0)
157 && (params->pei_data->data_to_save != NULL))
158 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 /* Save DIMM information */
165 mainboard_save_dimm_info(params);
166
167 /* Create romstage handof information */
Aaron Durbin77e13992016-11-29 17:43:04 -0600168 if (romstage_handoff_init(
169 params->power_state->prev_sleep_state == ACPI_S3) < 0)
Lee Leahy0946ec32015-04-20 15:24:54 -0700170 hard_reset();
Lee Leahy0946ec32015-04-20 15:24:54 -0700171
Duncan Lauriefe4983e2016-03-14 09:29:09 -0700172 /*
173 * Initialize the TPM, unless the TPM was already initialized
174 * in verstage and used to verify romstage.
175 */
176 if (IS_ENABLED(CONFIG_LPC_TPM) &&
177 !IS_ENABLED(CONFIG_RESUME_PATH_SAME_AS_BOOT) &&
178 !IS_ENABLED(CONFIG_VBOOT_STARTS_IN_BOOTBLOCK))
179 init_tpm(params->power_state->prev_sleep_state ==
Aaron Durbin932e09d2016-07-13 23:09:52 -0500180 ACPI_S3);
Lee Leahy0946ec32015-04-20 15:24:54 -0700181}
182
Aaron Durbine6af4be2015-09-24 12:26:31 -0500183void after_cache_as_ram_stage(void)
Lee Leahy0946ec32015-04-20 15:24:54 -0700184{
Lee Leahy0946ec32015-04-20 15:24:54 -0700185 /* Load the ramstage. */
Kyösti Mälkki65e8f642016-06-27 11:27:56 +0300186 run_ramstage();
Lee Leahy0946ec32015-04-20 15:24:54 -0700187 die("ERROR - Failed to load ramstage!");
188}
189
190/* Initialize the power state */
191__attribute__((weak)) struct chipset_power_state *fill_power_state(void)
192{
Lee Leahy0946ec32015-04-20 15:24:54 -0700193 return NULL;
194}
195
196__attribute__((weak)) void mainboard_check_ec_image(
197 struct romstage_params *params)
198{
Lee Leahy0946ec32015-04-20 15:24:54 -0700199#if IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC)
200 struct pei_data *pei_data;
201
202 pei_data = params->pei_data;
Aaron Durbin932e09d2016-07-13 23:09:52 -0500203 if (params->pei_data->boot_mode == ACPI_S0) {
Lee Leahy0946ec32015-04-20 15:24:54 -0700204 /* Ensure EC is running RO firmware. */
205 google_chromeec_check_ec_image(EC_IMAGE_RO);
206 }
207#endif
208}
209
Lee Leahy0946ec32015-04-20 15:24:54 -0700210/* Board initialization before and after RAM is enabled */
211__attribute__((weak)) void mainboard_romstage_entry(
212 struct romstage_params *params)
213{
Lee Leahy0946ec32015-04-20 15:24:54 -0700214 post_code(0x31);
215
216 /* Initliaze memory */
217 romstage_common(params);
218}
219
220/* Save the DIMM information for SMBIOS table 17 */
Lee Leahy0946ec32015-04-20 15:24:54 -0700221__attribute__((weak)) void mainboard_save_dimm_info(
222 struct romstage_params *params)
223{
224 int channel;
225 CHANNEL_INFO *channel_info;
226 int dimm;
227 DIMM_INFO *dimm_info;
228 int dimm_max;
229 void *hob_list_ptr;
230 EFI_HOB_GUID_TYPE *hob_ptr;
231 int index;
232 struct memory_info *mem_info;
233 FSP_SMBIOS_MEMORY_INFO *memory_info_hob;
234 const EFI_GUID memory_info_hob_guid = FSP_SMBIOS_MEMORY_INFO_GUID;
235
236 /* Locate the memory info HOB, presence validated by raminit */
237 hob_list_ptr = fsp_get_hob_list();
238 hob_ptr = get_next_guid_hob(&memory_info_hob_guid, hob_list_ptr);
239 memory_info_hob = (FSP_SMBIOS_MEMORY_INFO *)(hob_ptr + 1);
240
241 /* Display the data in the FSP_SMBIOS_MEMORY_INFO HOB */
242 if (IS_ENABLED(CONFIG_DISPLAY_HOBS)) {
243 printk(BIOS_DEBUG, "FSP_SMBIOS_MEMORY_INFO HOB\n");
244 printk(BIOS_DEBUG, " 0x%02x: Revision\n",
245 memory_info_hob->Revision);
246 printk(BIOS_DEBUG, " 0x%02x: MemoryType\n",
247 memory_info_hob->MemoryType);
Lee Leahy0be6d932015-06-26 11:15:42 -0700248 printk(BIOS_DEBUG, " %d: MemoryFrequencyInMHz\n",
Lee Leahy0946ec32015-04-20 15:24:54 -0700249 memory_info_hob->MemoryFrequencyInMHz);
Lee Leahy0be6d932015-06-26 11:15:42 -0700250 printk(BIOS_DEBUG, " %d: DataWidth in bits\n",
251 memory_info_hob->DataWidth);
Lee Leahy0946ec32015-04-20 15:24:54 -0700252 printk(BIOS_DEBUG, " 0x%02x: ErrorCorrectionType\n",
253 memory_info_hob->ErrorCorrectionType);
254 printk(BIOS_DEBUG, " 0x%02x: ChannelCount\n",
255 memory_info_hob->ChannelCount);
256 for (channel = 0; channel < memory_info_hob->ChannelCount;
257 channel++) {
258 channel_info = &memory_info_hob->ChannelInfo[channel];
259 printk(BIOS_DEBUG, " Channel %d\n", channel);
260 printk(BIOS_DEBUG, " 0x%02x: ChannelId\n",
261 channel_info->ChannelId);
262 printk(BIOS_DEBUG, " 0x%02x: DimmCount\n",
263 channel_info->DimmCount);
264 for (dimm = 0; dimm < channel_info->DimmCount;
265 dimm++) {
266 dimm_info = &channel_info->DimmInfo[dimm];
267 printk(BIOS_DEBUG, " DIMM %d\n", dimm);
268 printk(BIOS_DEBUG, " 0x%02x: DimmId\n",
269 dimm_info->DimmId);
Lee Leahy0be6d932015-06-26 11:15:42 -0700270 printk(BIOS_DEBUG, " %d: SizeInMb\n",
Lee Leahy0946ec32015-04-20 15:24:54 -0700271 dimm_info->SizeInMb);
272 }
273 }
274 }
275
276 /*
277 * Allocate CBMEM area for DIMM information used to populate SMBIOS
278 * table 17
279 */
280 mem_info = cbmem_add(CBMEM_ID_MEMINFO, sizeof(*mem_info));
281 printk(BIOS_DEBUG, "CBMEM entry for DIMM info: 0x%p\n", mem_info);
282 if (mem_info == NULL)
283 return;
284 memset(mem_info, 0, sizeof(*mem_info));
285
286 /* Describe the first N DIMMs in the system */
287 index = 0;
288 dimm_max = ARRAY_SIZE(mem_info->dimm);
289 for (channel = 0; channel < memory_info_hob->ChannelCount; channel++) {
290 if (index >= dimm_max)
291 break;
292 channel_info = &memory_info_hob->ChannelInfo[channel];
293 for (dimm = 0; dimm < channel_info->DimmCount; dimm++) {
294 if (index >= dimm_max)
295 break;
296 dimm_info = &channel_info->DimmInfo[dimm];
297
298 /* Populate the DIMM information */
299 if (dimm_info->SizeInMb) {
300 mem_info->dimm[index].dimm_size =
301 dimm_info->SizeInMb;
302 mem_info->dimm[index].ddr_type =
303 memory_info_hob->MemoryType;
304 mem_info->dimm[index].ddr_frequency =
305 memory_info_hob->MemoryFrequencyInMHz;
306 mem_info->dimm[index].channel_num =
307 channel_info->ChannelId;
308 mem_info->dimm[index].dimm_num =
309 dimm_info->DimmId;
Lee Leahy0be6d932015-06-26 11:15:42 -0700310 switch (memory_info_hob->DataWidth) {
311 default:
312 case 8:
313 mem_info->dimm[index].bus_width =
314 MEMORY_BUS_WIDTH_8;
315 break;
316
317 case 16:
318 mem_info->dimm[index].bus_width =
319 MEMORY_BUS_WIDTH_16;
320 break;
321
322 case 32:
323 mem_info->dimm[index].bus_width =
324 MEMORY_BUS_WIDTH_32;
325 break;
326
327 case 64:
328 mem_info->dimm[index].bus_width =
329 MEMORY_BUS_WIDTH_64;
330 break;
331
332 case 128:
333 mem_info->dimm[index].bus_width =
334 MEMORY_BUS_WIDTH_128;
335 break;
336 }
Duncan Laurie46a2c772015-07-20 16:48:55 -0700337
338 /* Add any mainboard specific information */
339 mainboard_add_dimm_info(params, mem_info,
340 channel, dimm, index);
Lee Leahy0946ec32015-04-20 15:24:54 -0700341 index++;
342 }
343 }
344 }
345 mem_info->dimm_cnt = index;
346 printk(BIOS_DEBUG, "%d DIMMs found\n", mem_info->dimm_cnt);
347}
Lee Leahy0946ec32015-04-20 15:24:54 -0700348
Duncan Laurie46a2c772015-07-20 16:48:55 -0700349/* Add any mainboard specific information */
350__attribute__((weak)) void mainboard_add_dimm_info(
351 struct romstage_params *params,
352 struct memory_info *mem_info,
353 int channel, int dimm, int index)
354{
Duncan Laurie46a2c772015-07-20 16:48:55 -0700355}
356
Lee Leahy0946ec32015-04-20 15:24:54 -0700357/* Get the memory configuration data */
Lee Leahyd52f2582016-05-31 18:12:53 -0700358__attribute__((weak)) int mrc_cache_get_current_with_version(
359 const struct mrc_saved_data **cache, uint32_t version)
Lee Leahy0946ec32015-04-20 15:24:54 -0700360{
Lee Leahy0946ec32015-04-20 15:24:54 -0700361 return -1;
362}
363
364/* Save the memory configuration data */
Lee Leahyd52f2582016-05-31 18:12:53 -0700365__attribute__((weak)) int mrc_cache_stash_data_with_version(const void *data,
366 size_t size, uint32_t version)
Lee Leahy0946ec32015-04-20 15:24:54 -0700367{
Lee Leahy0946ec32015-04-20 15:24:54 -0700368 return -1;
369}
370
371/* Transition RAM from off or self-refresh to active */
372__attribute__((weak)) void raminit(struct romstage_params *params)
373{
Lee Leahy0946ec32015-04-20 15:24:54 -0700374 post_code(0x34);
375 die("ERROR - No RAM initialization specified!\n");
376}
377
Lee Leahy0946ec32015-04-20 15:24:54 -0700378/* Display the memory configuration */
379__attribute__((weak)) void report_memory_config(void)
380{
Lee Leahy0946ec32015-04-20 15:24:54 -0700381}
382
Lee Leahy0946ec32015-04-20 15:24:54 -0700383/* Choose top of stack and setup MTRRs */
384__attribute__((weak)) void *setup_stack_and_mtrrs(void)
385{
Lee Leahy0946ec32015-04-20 15:24:54 -0700386 die("ERROR - Must specify top of stack!\n");
387 return NULL;
388}
389
Lee Leahy0946ec32015-04-20 15:24:54 -0700390/* SOC initialization after RAM is enabled */
391__attribute__((weak)) void soc_after_ram_init(struct romstage_params *params)
392{
Lee Leahy0946ec32015-04-20 15:24:54 -0700393}
394
Lee Leahy0946ec32015-04-20 15:24:54 -0700395/* SOC initialization before RAM is enabled */
396__attribute__((weak)) void soc_pre_ram_init(struct romstage_params *params)
397{
Lee Leahy0946ec32015-04-20 15:24:54 -0700398}