blob: a5728b594d2bf23c388a970b467433b3bd4e1a5f [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
Aaron Durbin39bdb0b2015-08-04 23:59:43 -050021#include <arch/acpi.h>
Lee Leahy0946ec32015-04-20 15:24:54 -070022#include <cbmem.h>
23#include <cbfs.h>
24#include <console/console.h>
25#include <fsp_util.h>
26#include <lib.h>
Lee Leahy0946ec32015-04-20 15:24:54 -070027#include <soc/intel/common/memmap.h>
28#include <soc/intel/common/ramstage.h>
29#include <stage_cache.h>
Aaron Durbin39bdb0b2015-08-04 23:59:43 -050030#include <string.h>
Lee Leahy0946ec32015-04-20 15:24:54 -070031#include <timestamp.h>
32
33/* SOC initialization after FSP silicon init */
34__attribute__((weak)) void soc_after_silicon_init(void)
35{
36 printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
37}
38
39/*
40 * SMM Memory Map:
41 *
42 * +--------------------------+ smm_region_size() ----.
Aaron Durbinabf87a22015-08-05 12:26:56 -050043 * | FSP Cache | |
Lee Leahy0946ec32015-04-20 15:24:54 -070044 * +--------------------------+ |
Aaron Durbinabf87a22015-08-05 12:26:56 -050045 * | SMM Stage Cache | + CONFIG_SMM_RESERVED_SIZE
Lee Leahy0946ec32015-04-20 15:24:54 -070046 * +--------------------------+ ---------------------'
47 * | SMM Code |
48 * +--------------------------+ smm_base
49 *
50 */
51
52void stage_cache_external_region(void **base, size_t *size)
53{
54 size_t cache_size;
55 u8 *cache_base;
56
57 /* Determine the location of the ramstage cache */
58 smm_region((void **)&cache_base, &cache_size);
Aaron Durbinabf87a22015-08-05 12:26:56 -050059 *size = CONFIG_SMM_RESERVED_SIZE;
Lee Leahy0946ec32015-04-20 15:24:54 -070060 *base = &cache_base[cache_size - CONFIG_SMM_RESERVED_SIZE];
61}
62
Lee Leahy0946ec32015-04-20 15:24:54 -070063/* Display SMM memory map */
64static void smm_memory_map(void)
65{
66 u8 *smm_base;
67 size_t smm_bytes;
68 size_t smm_code_bytes;
Aaron Durbinabf87a22015-08-05 12:26:56 -050069 u8 *ext_cache;
70 size_t ext_cache_bytes;
Lee Leahy0946ec32015-04-20 15:24:54 -070071 u8 *smm_reserved;
72 size_t smm_reserved_bytes;
73
74 /* Locate the SMM regions */
75 smm_region((void **)&smm_base, &smm_bytes);
Aaron Durbinabf87a22015-08-05 12:26:56 -050076 stage_cache_external_region((void **)&ext_cache, &ext_cache_bytes);
77 smm_code_bytes = ext_cache - smm_base;
78 smm_reserved_bytes = smm_bytes - ext_cache_bytes - smm_code_bytes;
79 smm_reserved = smm_base + smm_bytes - smm_reserved_bytes;
Lee Leahy0946ec32015-04-20 15:24:54 -070080
81 /* Display the SMM regions */
82 printk(BIOS_SPEW, "\nLocation SMM Memory Map Offset\n");
83 if (smm_reserved_bytes) {
84 printk(BIOS_SPEW, "0x%p +--------------------------+ 0x%08x\n",
85 &smm_reserved[smm_reserved_bytes], (u32)smm_bytes);
86 printk(BIOS_SPEW, " | Other reserved region |\n");
87 }
88 printk(BIOS_SPEW, "0x%p +--------------------------+ 0x%08x\n",
89 smm_reserved, (u32)(smm_reserved - smm_base));
Aaron Durbinabf87a22015-08-05 12:26:56 -050090 printk(BIOS_SPEW, " | external cache |\n");
Lee Leahy0946ec32015-04-20 15:24:54 -070091 printk(BIOS_SPEW, "0x%p +--------------------------+ 0x%08x\n",
Aaron Durbinabf87a22015-08-05 12:26:56 -050092 ext_cache, (u32)(ext_cache - smm_base));
Lee Leahy0946ec32015-04-20 15:24:54 -070093 printk(BIOS_SPEW, " | SMM code |\n");
94 printk(BIOS_SPEW, "0x%p +--------------------------+ 0x%08x\n",
95 smm_base, 0);
Lee Leahy0946ec32015-04-20 15:24:54 -070096}
97
Aaron Durbin39bdb0b2015-08-04 23:59:43 -050098static void fsp_run_silicon_init(int is_s3_wakeup)
Lee Leahy0946ec32015-04-20 15:24:54 -070099{
100 FSP_INFO_HEADER *fsp_info_header;
101 FSP_SILICON_INIT fsp_silicon_init;
102 SILICON_INIT_UPD *original_params;
103 SILICON_INIT_UPD silicon_init_params;
104 EFI_STATUS status;
105 UPD_DATA_REGION *upd_ptr;
106 VPD_DATA_REGION *vpd_ptr;
107
108 /* Find the FSP image */
109 fsp_info_header = fsp_get_fih();
110 if (fsp_info_header == NULL) {
111 printk(BIOS_ERR, "FSP_INFO_HEADER not set!\n");
112 return;
113 }
114 print_fsp_info(fsp_info_header);
115
116 /* Initialize the UPD values */
117 vpd_ptr = (VPD_DATA_REGION *)(fsp_info_header->CfgRegionOffset +
118 fsp_info_header->ImageBase);
119 printk(BIOS_DEBUG, "0x%p: VPD Data\n", vpd_ptr);
120 upd_ptr = (UPD_DATA_REGION *)(vpd_ptr->PcdUpdRegionOffset +
121 fsp_info_header->ImageBase);
122 printk(BIOS_DEBUG, "0x%p: UPD Data\n", upd_ptr);
123 original_params = (void *)((u8 *)upd_ptr +
124 upd_ptr->SiliconInitUpdOffset);
125 memcpy(&silicon_init_params, original_params,
126 sizeof(silicon_init_params));
127 soc_silicon_init_params(&silicon_init_params);
128
129 /* Locate VBT and pass to FSP GOP */
130 if (IS_ENABLED(CONFIG_GOP_SUPPORT))
Aaron Durbin39bdb0b2015-08-04 23:59:43 -0500131 load_vbt(is_s3_wakeup, &silicon_init_params);
Lee Leahy0946ec32015-04-20 15:24:54 -0700132 mainboard_silicon_init_params(&silicon_init_params);
133
134 /* Display the UPD data */
135 if (IS_ENABLED(CONFIG_DISPLAY_UPD_DATA))
136 soc_display_silicon_init_params(original_params,
137 &silicon_init_params);
138
139 /* Perform silicon initialization after RAM is configured */
140 printk(BIOS_DEBUG, "Calling FspSiliconInit\n");
141 fsp_silicon_init = (FSP_SILICON_INIT)(fsp_info_header->ImageBase
142 + fsp_info_header->FspSiliconInitEntryOffset);
143 timestamp_add_now(TS_FSP_SILICON_INIT_START);
144 printk(BIOS_DEBUG, "Calling FspSiliconInit(0x%p) at 0x%p\n",
145 &silicon_init_params, fsp_silicon_init);
146 status = fsp_silicon_init(&silicon_init_params);
147 timestamp_add_now(TS_FSP_SILICON_INIT_END);
148 printk(BIOS_DEBUG, "FspSiliconInit returned 0x%08x\n", status);
149
150#if IS_ENABLED(CONFIG_DISPLAY_HOBS)
151 /* Verify the HOBs */
152 const EFI_GUID graphics_info_guid = EFI_PEI_GRAPHICS_INFO_HOB_GUID;
153 void *hob_list_ptr = get_hob_list();
154 int missing_hob = 0;
155
156 if (hob_list_ptr == NULL)
157 die("ERROR - HOB pointer is NULL!\n");
158 print_hob_type_structure(0, hob_list_ptr);
159
160 /*
161 * Verify that FSP is generating the required HOBs:
162 * 7.1: FSP_BOOTLOADER_TEMP_MEMORY_HOB only produced for FSP 1.0
163 * 7.2: FSP_RESERVED_MEMORY_RESOURCE_HOB verified by raminit
164 * 7.3: FSP_NON_VOLATILE_STORAGE_HOB verified by raminit
165 * 7.4: FSP_BOOTLOADER_TOLUM_HOB verified by raminit
166 * 7.5: EFI_PEI_GRAPHICS_INFO_HOB verified below,
167 * if the ImageAttribute bit is set
168 * FSP_SMBIOS_MEMORY_INFO HOB verified by raminit
169 */
170 if ((fsp_info_header->ImageAttribute & GRAPHICS_SUPPORT_BIT) &&
171 !get_next_guid_hob(&graphics_info_guid, hob_list_ptr)) {
172 printk(BIOS_ERR, "7.5: EFI_PEI_GRAPHICS_INFO_HOB missing!\n");
173 missing_hob = 1;
174 }
175 if (missing_hob)
176 die("ERROR - Missing one or more required FSP HOBs!\n");
177#endif
178
179 soc_after_silicon_init();
180}
181
Aaron Durbinabf87a22015-08-05 12:26:56 -0500182static void fsp_cache_save(struct prog *fsp)
Lee Leahy0946ec32015-04-20 15:24:54 -0700183{
Aaron Durbinabf87a22015-08-05 12:26:56 -0500184 if (IS_ENABLED(CONFIG_DISPLAY_SMM_MEMORY_MAP))
185 smm_memory_map();
Lee Leahy0946ec32015-04-20 15:24:54 -0700186
Aaron Durbinabf87a22015-08-05 12:26:56 -0500187 if (prog_entry(fsp) == NULL) {
188 printk(BIOS_ERR, "ERROR: No FSP to save in cache.\n");
Lee Leahy0946ec32015-04-20 15:24:54 -0700189 return;
190 }
191
Aaron Durbinabf87a22015-08-05 12:26:56 -0500192 stage_cache_add(STAGE_REFCODE, fsp);
Lee Leahy0946ec32015-04-20 15:24:54 -0700193}
194
Aaron Durbinabf87a22015-08-05 12:26:56 -0500195static int fsp_find_and_relocate(struct prog *fsp)
Lee Leahy0946ec32015-04-20 15:24:54 -0700196{
Aaron Durbin22ea0072015-08-05 10:17:33 -0500197 struct region_device fsp_rdev;
198 uint32_t type = CBFS_TYPE_FSP;
Lee Leahy0946ec32015-04-20 15:24:54 -0700199
Aaron Durbinabf87a22015-08-05 12:26:56 -0500200 if (cbfs_boot_locate(&fsp_rdev, prog_name(fsp), &type)) {
Aaron Durbin22ea0072015-08-05 10:17:33 -0500201 printk(BIOS_ERR, "ERROR: Couldn't find fsp.bin in CBFS.\n");
Lee Leahy0946ec32015-04-20 15:24:54 -0700202 return -1;
203 }
204
Aaron Durbinabf87a22015-08-05 12:26:56 -0500205 if (fsp_relocate(fsp, &fsp_rdev)) {
Aaron Durbin22ea0072015-08-05 10:17:33 -0500206 printk(BIOS_ERR, "ERROR: FSP relocation failed.\n");
207 return -1;
208 }
Lee Leahy0946ec32015-04-20 15:24:54 -0700209
Lee Leahy0946ec32015-04-20 15:24:54 -0700210 return 0;
211}
212
213void intel_silicon_init(void)
214{
Aaron Durbinabf87a22015-08-05 12:26:56 -0500215 struct prog fsp = PROG_INIT(ASSET_REFCODE, "fsp.bin");
Aaron Durbin39bdb0b2015-08-04 23:59:43 -0500216 int is_s3_wakeup = acpi_is_wakeup_s3();
Lee Leahy0946ec32015-04-20 15:24:54 -0700217
Aaron Durbin39bdb0b2015-08-04 23:59:43 -0500218 if (is_s3_wakeup) {
Lee Leahy0946ec32015-04-20 15:24:54 -0700219 printk(BIOS_DEBUG, "FSP: Loading binary from cache\n");
Aaron Durbinabf87a22015-08-05 12:26:56 -0500220 stage_cache_load_stage(STAGE_REFCODE, &fsp);
Lee Leahy0946ec32015-04-20 15:24:54 -0700221 } else {
Aaron Durbinabf87a22015-08-05 12:26:56 -0500222 fsp_find_and_relocate(&fsp);
Lee Leahy0946ec32015-04-20 15:24:54 -0700223 printk(BIOS_DEBUG, "FSP: Saving binary in cache\n");
Aaron Durbinabf87a22015-08-05 12:26:56 -0500224 fsp_cache_save(&fsp);
Lee Leahy0946ec32015-04-20 15:24:54 -0700225 }
226
Aaron Durbinabf87a22015-08-05 12:26:56 -0500227 /* FSP_INFO_HEADER is set as the program entry. */
228 fsp_update_fih(prog_entry(&fsp));
229
Aaron Durbin39bdb0b2015-08-04 23:59:43 -0500230 fsp_run_silicon_init(is_s3_wakeup);
Lee Leahy0946ec32015-04-20 15:24:54 -0700231}
232
233/* Initialize the UPD parameters for SiliconInit */
234__attribute__((weak)) void mainboard_silicon_init_params(
235 SILICON_INIT_UPD *params)
236{
237 printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
238};
239
240/* Display the UPD parameters for SiliconInit */
241__attribute__((weak)) void soc_display_silicon_init_params(
242 const SILICON_INIT_UPD *old, SILICON_INIT_UPD *new)
243{
244 printk(BIOS_SPEW, "UPD values for SiliconInit:\n");
245 hexdump32(BIOS_SPEW, new, sizeof(*new));
246}
247
248/* Initialize the UPD parameters for SiliconInit */
249__attribute__((weak)) void soc_silicon_init_params(SILICON_INIT_UPD *params)
250{
251 printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
252}