silicon_init.c
1 /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 3 #include <arch/null_breakpoint.h> 4 #include <arch/stack_canary_breakpoint.h> 5 #include <bootsplash.h> 6 #include <bootstate.h> 7 #include <cbfs.h> 8 #include <cbmem.h> 9 #include <commonlib/fsp.h> 10 #include <stdlib.h> 11 #include <console/console.h> 12 #include <fsp/api.h> 13 #include <fsp/util.h> 14 #include <mrc_cache.h> 15 #include <program_loading.h> 16 #include <soc/intel/common/reset.h> 17 #include <soc/intel/common/vbt.h> 18 #include <stage_cache.h> 19 #include <string.h> 20 #include <timestamp.h> 21 #include <types.h> 22 #include <mode_switch.h> 23 24 struct fsp_header fsps_hdr; 25 26 /* Callbacks for SoC/Mainboard specific overrides */ 27 void __weak platform_fsp_silicon_multi_phase_init_cb(uint32_t phase_index) 28 { 29 /* Leave for the SoC/Mainboard to implement if necessary. */ 30 } 31 32 /* FSP Specification < 2.2 has only 1 stage like FspSiliconInit. FSP specification >= 2.2 33 * has multiple stages as below. 34 */ 35 enum fsp_silicon_init_phases { 36 FSP_SILICON_INIT_API, 37 FSP_MULTI_PHASE_SI_INIT_GET_NUMBER_OF_PHASES_API, 38 FSP_MULTI_PHASE_SI_INIT_EXECUTE_PHASE_API 39 }; 40 41 static void fsps_return_value_handler(enum fsp_silicon_init_phases phases, 42 efi_return_status_t status) 43 { 44 uint8_t postcode; 45 46 /* Handle any reset request returned by FSP-S APIs */ 47 fsp_handle_reset(status); 48 49 if (status == FSP_SUCCESS) 50 return; 51 /* Handle all other errors returned by FSP-S APIs */ 52 /* Assume video failure if attempted to initialize graphics */ 53 if (CONFIG(RUN_FSP_GOP) && vbt_get()) 54 postcode = POSTCODE_VIDEO_FAILURE; 55 else 56 postcode = POSTCODE_HW_INIT_FAILURE; /* else generic */ 57 58 switch (phases) { 59 case FSP_SILICON_INIT_API: 60 fsp_die_with_post_code(status, postcode, "FspSiliconInit error"); 61 break; 62 case FSP_MULTI_PHASE_SI_INIT_GET_NUMBER_OF_PHASES_API: 63 fsp_printk(status, BIOS_SPEW, "FspMultiPhaseSiInit NumberOfPhases"); 64 break; 65 case FSP_MULTI_PHASE_SI_INIT_EXECUTE_PHASE_API: 66 fsp_printk(status, BIOS_SPEW, "FspMultiPhaseSiInit ExecutePhase"); 67 break; 68 default: 69 break; 70 } 71 } 72 73 bool fsp_is_multi_phase_init_enabled(void) 74 { 75 return CONFIG(FSPS_USE_MULTI_PHASE_INIT) && 76 (fsps_hdr.fsp_multi_phase_si_init_entry_offset != 0); 77 } 78 79 static void fsp_fill_common_arch_params(FSPS_UPD *supd) 80 { 81 #if (CONFIG(FSPS_HAS_ARCH_UPD) && !CONFIG(PLATFORM_USES_FSP2_4)) 82 FSPS_ARCHx_UPD *s_arch_cfg = &supd->FspsArchUpd; 83 s_arch_cfg->EnableMultiPhaseSiliconInit = fsp_is_multi_phase_init_enabled(); 84 #endif 85 } 86 87 static void do_silicon_init(struct fsp_header *hdr) 88 { 89 FSPS_UPD *upd, *supd; 90 fsp_silicon_init_fn silicon_init; 91 efi_return_status_t status; 92 fsp_multi_phase_init_fn multi_phase_si_init; 93 struct fsp_multi_phase_params multi_phase_params; 94 struct fsp_multi_phase_get_number_of_phases_params multi_phase_get_number; 95 96 supd = (FSPS_UPD *)(uintptr_t)(hdr->cfg_region_offset + hdr->image_base); 97 98 fsp_verify_upd_header_signature(supd->FspUpdHeader.Signature, FSPS_UPD_SIGNATURE); 99 100 /* FSPS UPD and coreboot structure sizes should match. However, enforcing the exact 101 * match mandates simultaneous updates to coreboot and FSP repos. Allow coreboot 102 * to proceed if its UPD structure is smaller than FSP one to enable staggered UPD 103 * update process on both sides. The mismatch indicates a temporary build problem, 104 * don't leave it like this as FSP default settings can be bad choices for coreboot. 105 */ 106 if (!hdr->cfg_region_size || hdr->cfg_region_size < sizeof(FSPS_UPD)) 107 die_with_post_code(POSTCODE_INVALID_VENDOR_BINARY, 108 "Invalid FSPS UPD region\n"); 109 else if (hdr->cfg_region_size > sizeof(FSPS_UPD)) 110 printk(BIOS_ERR, "FSP and coreboot are out of sync! FSPS UPD size > coreboot\n"); 111 112 upd = xmalloc(hdr->cfg_region_size); 113 114 memcpy(upd, supd, hdr->cfg_region_size); 115 116 /* Fill common settings on behalf of chipset. */ 117 if (CONFIG(FSPS_HAS_ARCH_UPD)) 118 fsp_fill_common_arch_params(upd); 119 /* Give SoC/mainboard a chance to populate entries */ 120 platform_fsp_silicon_init_params_cb(upd); 121 122 /* Populate logo related entries */ 123 if (CONFIG(BMP_LOGO)) 124 soc_load_logo(upd); 125 126 /* Call SiliconInit */ 127 silicon_init = (void *)(uintptr_t)(hdr->image_base + 128 hdr->fsp_silicon_init_entry_offset); 129 fsp_debug_before_silicon_init(silicon_init, supd, upd); 130 131 timestamp_add_now(TS_FSP_SILICON_INIT_START); 132 post_code(POSTCODE_FSP_SILICON_INIT); 133 134 /* FSP disables the interrupt handler so remove debug exceptions temporarily */ 135 null_breakpoint_remove(); 136 stack_canary_breakpoint_remove(); 137 if (ENV_X86_64 && CONFIG(PLATFORM_USES_FSP2_X86_32)) 138 status = protected_mode_call_1arg(silicon_init, (uintptr_t)upd); 139 else 140 status = silicon_init(upd); 141 null_breakpoint_init(); 142 stack_canary_breakpoint_init(); 143 144 fsp_printk(status, BIOS_INFO, "FSPS"); 145 146 timestamp_add_now(TS_FSP_SILICON_INIT_END); 147 post_code(POSTCODE_FSP_SILICON_EXIT); 148 149 fsp_debug_after_silicon_init(status); 150 fsps_return_value_handler(FSP_SILICON_INIT_API, status); 151 152 /* Reinitialize CPUs if FSP-S has done MP Init */ 153 if (CONFIG(USE_INTEL_FSP_MP_INIT) && !fsp_is_multi_phase_init_enabled()) 154 do_mpinit_after_fsp(); 155 156 if (!CONFIG(PLATFORM_USES_FSP2_2)) 157 return; 158 159 /* Check if SoC user would like to call Multi Phase Init */ 160 if (!fsp_is_multi_phase_init_enabled()) 161 return; 162 163 /* Call MultiPhaseSiInit */ 164 multi_phase_si_init = (void *)(uintptr_t)(hdr->image_base + 165 hdr->fsp_multi_phase_si_init_entry_offset); 166 167 /* Implementing multi_phase_si_init() is optional as per FSP 2.2 spec */ 168 if (multi_phase_si_init == NULL) 169 return; 170 171 post_code(POSTCODE_FSP_MULTI_PHASE_SI_INIT_ENTRY); 172 timestamp_add_now(TS_FSP_MULTI_PHASE_SI_INIT_START); 173 /* Get NumberOfPhases Value */ 174 multi_phase_params.multi_phase_action = GET_NUMBER_OF_PHASES; 175 multi_phase_params.phase_index = 0; 176 multi_phase_params.multi_phase_param_ptr = &multi_phase_get_number; 177 status = multi_phase_si_init(&multi_phase_params); 178 fsps_return_value_handler(FSP_MULTI_PHASE_SI_INIT_GET_NUMBER_OF_PHASES_API, status); 179 180 /* Execute Multi Phase Execution */ 181 for (uint32_t i = 1; i <= multi_phase_get_number.number_of_phases; i++) { 182 printk(BIOS_SPEW, "Executing Phase %u of FspMultiPhaseSiInit\n", i); 183 /* 184 * Give SoC/mainboard a chance to perform any operation before 185 * Multi Phase Execution 186 */ 187 platform_fsp_silicon_multi_phase_init_cb(i); 188 189 multi_phase_params.multi_phase_action = EXECUTE_PHASE; 190 multi_phase_params.phase_index = i; 191 multi_phase_params.multi_phase_param_ptr = NULL; 192 status = multi_phase_si_init(&multi_phase_params); 193 if (CONFIG(FSP_MULTIPHASE_SI_INIT_RETURN_BROKEN)) 194 status = fsp_get_pch_reset_status(); 195 fsps_return_value_handler(FSP_MULTI_PHASE_SI_INIT_EXECUTE_PHASE_API, status); 196 } 197 timestamp_add_now(TS_FSP_MULTI_PHASE_SI_INIT_END); 198 post_code(POSTCODE_FSP_MULTI_PHASE_SI_INIT_EXIT); 199 200 /* Reinitialize CPUs if FSP-S has done MP Init */ 201 if (CONFIG(USE_INTEL_FSP_MP_INIT)) 202 do_mpinit_after_fsp(); 203 } 204 205 static void *fsps_allocator(void *arg_unused, size_t size, const union cbfs_mdata *mdata_unused) 206 { 207 return cbmem_add(CBMEM_ID_REFCODE, size); 208 } 209 210 void fsps_load(void) 211 { 212 const char *fsps_cbfs = soc_select_fsp_s_cbfs(); 213 struct fsp_load_descriptor fspld = { 214 .fsp_prog = PROG_INIT(PROG_REFCODE, fsps_cbfs), 215 .alloc = fsps_allocator, 216 }; 217 struct prog *fsps = &fspld.fsp_prog; 218 static int load_done; 219 220 if (load_done) 221 return; 222 223 timestamp_add_now(TS_FSP_SILICON_INIT_LOAD); 224 225 if (resume_from_stage_cache()) { 226 printk(BIOS_DEBUG, "Loading FSPS from stage_cache\n"); 227 stage_cache_load_stage(STAGE_REFCODE, fsps); 228 if (fsp_validate_component(&fsps_hdr, prog_start(fsps), prog_size(fsps))) 229 die("On resume fsps header is invalid\n"); 230 load_done = 1; 231 return; 232 } 233 234 if (fsp_load_component(&fspld, &fsps_hdr) != CB_SUCCESS) 235 die("FSP-S failed to load\n"); 236 237 stage_cache_add(STAGE_REFCODE, fsps); 238 239 load_done = 1; 240 } 241 242 void preload_fsps(void) 243 { 244 if (!CONFIG(CBFS_PRELOAD)) 245 return; 246 247 const char *fsps_cbfs = soc_select_fsp_s_cbfs(); 248 printk(BIOS_DEBUG, "Preloading %s\n", fsps_cbfs); 249 cbfs_preload(fsps_cbfs); 250 } 251 252 void fsp_silicon_init(void) 253 { 254 fsps_load(); 255 do_silicon_init(&fsps_hdr); 256 257 if (CONFIG(CACHE_MRC_SETTINGS) && CONFIG(FSP_NVS_DATA_POST_SILICON_INIT)) 258 save_memory_training_data(); 259 260 if (CONFIG(DISPLAY_FSP_TIMESTAMPS)) 261 fsp_display_timestamp(); 262 } 263 264 __weak void soc_load_logo(FSPS_UPD *supd) { } 265 266 static void release_logo(void *arg_unused) 267 { 268 if (CONFIG(BMP_LOGO)) 269 bmp_release_logo(); 270 } 271 272 BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_LOAD, BS_ON_EXIT, release_logo, NULL);