1// SPDX-License-Identifier: Intel 2/* 3 * Copyright (C) 2013, Intel Corporation 4 * Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com> 5 */ 6 7#include <common.h> 8#include <log.h> 9#include <asm/fsp1/fsp_support.h> 10#include <asm/post.h> 11 12struct fsp_header *__attribute__((optimize("O0"))) fsp_find_header(void) 13{ 14 /* 15 * This function may be called before the a stack is established, 16 * so special care must be taken. First, it cannot declare any local 17 * variable using stack. Only register variable can be used here. 18 * Secondly, some compiler version will add prolog or epilog code 19 * for the C function. If so the function call may not work before 20 * stack is ready. 21 * 22 * GCC 4.8.1 has been verified to be working for the following codes. 23 */ 24 volatile register u8 *fsp asm("eax"); 25 26 /* Initalize the FSP base */ 27 fsp = (u8 *)CONFIG_FSP_ADDR; 28 29 /* Check the FV signature, _FVH */ 30 if (((struct fv_header *)fsp)->sign == EFI_FVH_SIGNATURE) { 31 /* Go to the end of the FV header and align the address */ 32 fsp += ((struct fv_header *)fsp)->ext_hdr_off; 33 fsp += ((struct fv_ext_header *)fsp)->ext_hdr_size; 34 fsp = (u8 *)(((u32)fsp + 7) & 0xFFFFFFF8); 35 } else { 36 fsp = 0; 37 } 38 39 /* Check the FFS GUID */ 40 if (fsp && 41 ((struct ffs_file_header *)fsp)->name.b[0] == FSP_GUID_BYTE0 && 42 ((struct ffs_file_header *)fsp)->name.b[1] == FSP_GUID_BYTE1 && 43 ((struct ffs_file_header *)fsp)->name.b[2] == FSP_GUID_BYTE2 && 44 ((struct ffs_file_header *)fsp)->name.b[3] == FSP_GUID_BYTE3 && 45 ((struct ffs_file_header *)fsp)->name.b[4] == FSP_GUID_BYTE4 && 46 ((struct ffs_file_header *)fsp)->name.b[5] == FSP_GUID_BYTE5 && 47 ((struct ffs_file_header *)fsp)->name.b[6] == FSP_GUID_BYTE6 && 48 ((struct ffs_file_header *)fsp)->name.b[7] == FSP_GUID_BYTE7 && 49 ((struct ffs_file_header *)fsp)->name.b[8] == FSP_GUID_BYTE8 && 50 ((struct ffs_file_header *)fsp)->name.b[9] == FSP_GUID_BYTE9 && 51 ((struct ffs_file_header *)fsp)->name.b[10] == FSP_GUID_BYTE10 && 52 ((struct ffs_file_header *)fsp)->name.b[11] == FSP_GUID_BYTE11 && 53 ((struct ffs_file_header *)fsp)->name.b[12] == FSP_GUID_BYTE12 && 54 ((struct ffs_file_header *)fsp)->name.b[13] == FSP_GUID_BYTE13 && 55 ((struct ffs_file_header *)fsp)->name.b[14] == FSP_GUID_BYTE14 && 56 ((struct ffs_file_header *)fsp)->name.b[15] == FSP_GUID_BYTE15) { 57 /* Add the FFS header size to find the raw section header */ 58 fsp += sizeof(struct ffs_file_header); 59 } else { 60 fsp = 0; 61 } 62 63 if (fsp && 64 ((struct raw_section *)fsp)->type == EFI_SECTION_RAW) { 65 /* Add the raw section header size to find the FSP header */ 66 fsp += sizeof(struct raw_section); 67 } else { 68 fsp = 0; 69 } 70 71 return (struct fsp_header *)fsp; 72} 73 74void fsp_continue(u32 status, void *hob_list) 75{ 76 post_code(POST_MRC); 77 78 assert(status == 0); 79 80 /* The boot loader main function entry */ 81 fsp_init_done(hob_list); 82} 83 84void fsp_init(u32 stack_top, u32 boot_mode, void *nvs_buf) 85{ 86 struct fsp_config_data config_data; 87 fsp_init_f init; 88 struct fsp_init_params params; 89 struct fspinit_rtbuf rt_buf; 90 struct fsp_header *fsp_hdr; 91 struct fsp_init_params *params_ptr; 92#ifdef CONFIG_FSP_USE_UPD 93 struct vpd_region *fsp_vpd; 94 struct upd_region *fsp_upd; 95#endif 96 97 fsp_hdr = fsp_find_header(); 98 if (fsp_hdr == NULL) { 99 /* No valid FSP info header was found */ 100 panic("Invalid FSP header"); 101 } 102 103 config_data.common.fsp_hdr = fsp_hdr; 104 config_data.common.stack_top = stack_top; 105 config_data.common.boot_mode = boot_mode; 106 107#ifdef CONFIG_FSP_USE_UPD 108 /* Get VPD region start */ 109 fsp_vpd = (struct vpd_region *)(fsp_hdr->img_base + 110 fsp_hdr->cfg_region_off); 111 112 /* Verify the VPD data region is valid */ 113 assert(fsp_vpd->sign == VPD_IMAGE_ID); 114 115 fsp_upd = &config_data.fsp_upd; 116 117 /* Copy default data from Flash */ 118 memcpy(fsp_upd, (void *)(fsp_hdr->img_base + fsp_vpd->upd_offset), 119 sizeof(struct upd_region)); 120 121 /* Verify the UPD data region is valid */ 122 assert(fsp_upd->terminator == UPD_TERMINATOR); 123#endif 124 125 memset(&rt_buf, 0, sizeof(struct fspinit_rtbuf)); 126 127 /* Override any configuration if required */ 128 fsp_update_configs(&config_data, &rt_buf); 129 130 memset(¶ms, 0, sizeof(struct fsp_init_params)); 131 params.nvs_buf = nvs_buf; 132 params.rt_buf = (struct fspinit_rtbuf *)&rt_buf; 133 params.continuation = (fsp_continuation_f)fsp_asm_continuation; 134 135 init = (fsp_init_f)(fsp_hdr->img_base + fsp_hdr->fsp_init); 136 params_ptr = ¶ms; 137 138 post_code(POST_PRE_MRC); 139 140 /* Load GDT for FSP */ 141 setup_fsp_gdt(); 142 143 /* 144 * Use ASM code to ensure the register value in EAX & EDX 145 * will be passed into fsp_continue 146 */ 147 asm volatile ( 148 "pushl %0;" 149 "call *%%eax;" 150 ".global fsp_asm_continuation;" 151 "fsp_asm_continuation:;" 152 "movl 4(%%esp), %%eax;" /* status */ 153 "movl 8(%%esp), %%edx;" /* hob_list */ 154 "jmp fsp_continue;" 155 : : "m"(params_ptr), "a"(init) 156 ); 157 158 /* 159 * Should never get here. 160 * Control will continue from fsp_continue. 161 * This line below is to prevent the compiler from optimizing 162 * structure intialization. 163 * 164 * DO NOT REMOVE! 165 */ 166 init(¶ms); 167} 168 169u32 fsp_notify(struct fsp_header *fsp_hdr, u32 phase) 170{ 171 fsp_notify_f notify; 172 struct fsp_notify_params params; 173 struct fsp_notify_params *params_ptr; 174 u32 status; 175 176 if (!fsp_hdr) 177 fsp_hdr = (struct fsp_header *)fsp_find_header(); 178 179 if (fsp_hdr == NULL) { 180 /* No valid FSP info header */ 181 panic("Invalid FSP header"); 182 } 183 184 notify = (fsp_notify_f)(fsp_hdr->img_base + fsp_hdr->fsp_notify); 185 params.phase = phase; 186 params_ptr = ¶ms; 187 188 /* 189 * Use ASM code to ensure correct parameter is on the stack for 190 * FspNotify as U-Boot is using different ABI from FSP 191 */ 192 asm volatile ( 193 "pushl %1;" /* push notify phase */ 194 "call *%%eax;" /* call FspNotify */ 195 "addl $4, %%esp;" /* clean up the stack */ 196 : "=a"(status) : "m"(params_ptr), "a"(notify), "m"(*params_ptr) 197 ); 198 199 return status; 200} 201