blob: a4b623d2f44423f5d361712ad9bb3be61b7f68f9 [file] [log] [blame]
Lee Leahy3dad4892015-05-05 11:14:02 -07001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2013-2014 Sage Electronic Engineering, LLC.
Lee Leahyb5ad8272015-04-20 15:29:16 -07005 * Copyright (C) 2015 Intel Corp.
Lee Leahy3dad4892015-05-05 11:14:02 -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 Leahy3dad4892015-05-05 11:14:02 -070015 */
16
Lee Leahy3dad4892015-05-05 11:14:02 -070017#include <bootstate.h>
18#include <cbmem.h>
Lee Leahyb5ad8272015-04-20 15:29:16 -070019#include <console/console.h>
Aaron Durbin789f2b62015-09-09 17:05:06 -050020#include <fsp/util.h>
Lee Leahy3dad4892015-05-05 11:14:02 -070021#include <timestamp.h>
22
Lee Leahyb5ad8272015-04-20 15:29:16 -070023/* Locate the FSP binary in the coreboot filesystem */
Lee Leahya8874922015-08-26 14:58:29 -070024FSP_INFO_HEADER *find_fsp(uintptr_t fsp_base_address)
Lee Leahy3dad4892015-05-05 11:14:02 -070025{
Lee Leahyb5ad8272015-04-20 15:29:16 -070026 union {
27 EFI_FFS_FILE_HEADER *ffh;
28 FSP_INFO_HEADER *fih;
29 EFI_FIRMWARE_VOLUME_EXT_HEADER *fveh;
30 EFI_FIRMWARE_VOLUME_HEADER *fvh;
31 EFI_RAW_SECTION *rs;
32 u8 *u8;
33 u32 u32;
34 } fsp_ptr;
Alexandru Gagniuc5c261222015-08-29 18:53:43 -070035 static const union {
36 char str_id[8];
37 u32 int_id[2];
38 } fsp_id = {
39 .str_id = CONFIG_FSP_IMAGE_ID_STRING
40 };
41
Lee Leahyb5ad8272015-04-20 15:29:16 -070042 u32 *image_id;
Lee Leahy3dad4892015-05-05 11:14:02 -070043
Lee Leahyb5ad8272015-04-20 15:29:16 -070044 for (;;) {
45 /* Get the FSP binary base address in CBFS */
Lee Leahya8874922015-08-26 14:58:29 -070046 fsp_ptr.u32 = fsp_base_address;
Lee Leahy3dad4892015-05-05 11:14:02 -070047
Lee Leahyb5ad8272015-04-20 15:29:16 -070048 /* Check the FV signature, _FVH */
49 if (fsp_ptr.fvh->Signature != 0x4856465F) {
50 fsp_ptr.u8 = (u8 *)ERROR_NO_FV_SIG;
51 break;
Lee Leahy3dad4892015-05-05 11:14:02 -070052 }
53
Lee Leahyb5ad8272015-04-20 15:29:16 -070054 /* Locate the file header which follows the FV header. */
55 fsp_ptr.u8 += fsp_ptr.fvh->ExtHeaderOffset;
56 fsp_ptr.u8 += fsp_ptr.fveh->ExtHeaderSize;
Alexandru Gagniuc3f2a9452015-08-29 18:25:10 -070057 fsp_ptr.u8 = (u8 *)ALIGN_UP(fsp_ptr.u32, 8);
Lee Leahyb5ad8272015-04-20 15:29:16 -070058
59 /* Check the FFS GUID */
60 if ((((u32 *)&fsp_ptr.ffh->Name)[0] != 0x912740BE)
61 || (((u32 *)&fsp_ptr.ffh->Name)[1] != 0x47342284)
62 || (((u32 *)&fsp_ptr.ffh->Name)[2] != 0xB08471B9)
63 || (((u32 *)&fsp_ptr.ffh->Name)[3] != 0x0C3F3527)) {
64 fsp_ptr.u8 = (u8 *)ERROR_NO_FFS_GUID;
65 break;
66 }
67
68 /* Locate the Raw Section Header */
69 fsp_ptr.u8 += sizeof(EFI_FFS_FILE_HEADER);
70
71 if (fsp_ptr.rs->Type != EFI_SECTION_RAW) {
72 fsp_ptr.u8 = (u8 *)ERROR_NO_INFO_HEADER;
73 break;
74 }
75
76 /* Locate the FSP INFO Header which follows the Raw Header. */
77 fsp_ptr.u8 += sizeof(EFI_RAW_SECTION);
78
79 /* Verify that the FSP base address.*/
Lee Leahya8874922015-08-26 14:58:29 -070080 if (fsp_ptr.fih->ImageBase != fsp_base_address) {
Lee Leahyb5ad8272015-04-20 15:29:16 -070081 fsp_ptr.u8 = (u8 *)ERROR_IMAGEBASE_MISMATCH;
82 break;
83 }
84
85 /* Verify the FSP Signature */
86 if (fsp_ptr.fih->Signature != FSP_SIG) {
87 fsp_ptr.u8 = (u8 *)ERROR_INFO_HEAD_SIG_MISMATCH;
88 break;
89 }
90
91 /* Verify the FSP ID */
92 image_id = (u32 *)&fsp_ptr.fih->ImageId[0];
Alexandru Gagniuc5c261222015-08-29 18:53:43 -070093 if ((image_id[0] != fsp_id.int_id[0])
94 || (image_id[1] != fsp_id.int_id[1]))
Lee Leahyb5ad8272015-04-20 15:29:16 -070095 fsp_ptr.u8 = (u8 *)ERROR_FSP_SIG_MISMATCH;
96 break;
Lee Leahy3dad4892015-05-05 11:14:02 -070097 }
98
Lee Leahyb5ad8272015-04-20 15:29:16 -070099 return fsp_ptr.fih;
Lee Leahy3dad4892015-05-05 11:14:02 -0700100}
101
Lee Leahyb5ad8272015-04-20 15:29:16 -0700102void print_fsp_info(FSP_INFO_HEADER *fsp_header)
Lee Leahy3dad4892015-05-05 11:14:02 -0700103{
Lee Leahyb5ad8272015-04-20 15:29:16 -0700104 u8 *fsp_base;
Lee Leahy3dad4892015-05-05 11:14:02 -0700105
Lee Leahyb5ad8272015-04-20 15:29:16 -0700106 fsp_base = (u8 *)fsp_header->ImageBase;
107 printk(BIOS_SPEW, "FSP_INFO_HEADER: %p\n", fsp_header);
108 printk(BIOS_INFO, "FSP Signature: %c%c%c%c%c%c%c%c\n",
109 fsp_header->ImageId[0], fsp_header->ImageId[1],
110 fsp_header->ImageId[2], fsp_header->ImageId[3],
111 fsp_header->ImageId[4], fsp_header->ImageId[5],
112 fsp_header->ImageId[6], fsp_header->ImageId[7]);
113 printk(BIOS_INFO, "FSP Header Version: %d\n",
114 fsp_header->HeaderRevision);
115 printk(BIOS_INFO, "FSP Revision: %d.%d\n",
116 (u8)((fsp_header->ImageRevision >> 8) & 0xff),
117 (u8)(fsp_header->ImageRevision & 0xff));
118#if IS_ENABLED(CONFIG_DISPLAY_FSP_ENTRY_POINTS)
119 printk(BIOS_SPEW, "FSP Entry Points:\n");
120 printk(BIOS_SPEW, " 0x%p: Image Base\n", fsp_base);
121 printk(BIOS_SPEW, " 0x%p: TempRamInit\n",
122 &fsp_base[fsp_header->TempRamInitEntryOffset]);
123 printk(BIOS_SPEW, " 0x%p: FspInit\n",
124 &fsp_base[fsp_header->FspInitEntryOffset]);
125 if (fsp_header->HeaderRevision >= FSP_HEADER_REVISION_2) {
126 printk(BIOS_SPEW, " 0x%p: MemoryInit\n",
127 &fsp_base[fsp_header->FspMemoryInitEntryOffset]);
128 printk(BIOS_SPEW, " 0x%p: TempRamExit\n",
129 &fsp_base[fsp_header->TempRamExitEntryOffset]);
130 printk(BIOS_SPEW, " 0x%p: SiliconInit\n",
131 &fsp_base[fsp_header->FspSiliconInitEntryOffset]);
132 }
133 printk(BIOS_SPEW, " 0x%p: NotifyPhase\n",
134 &fsp_base[fsp_header->NotifyPhaseEntryOffset]);
135 printk(BIOS_SPEW, " 0x%p: Image End\n",
136 &fsp_base[fsp_header->ImageSize]);
137#endif
138}
139
Lee Leahyb5ad8272015-04-20 15:29:16 -0700140void fsp_notify(u32 phase)
141{
142 FSP_NOTIFY_PHASE notify_phase_proc;
143 NOTIFY_PHASE_PARAMS notify_phase_params;
144 EFI_STATUS status;
145 FSP_INFO_HEADER *fsp_header_ptr;
146
147 fsp_header_ptr = fsp_get_fih();
148 if (fsp_header_ptr == NULL) {
Lee Leahya8874922015-08-26 14:58:29 -0700149 fsp_header_ptr = (void *)find_fsp(CONFIG_FSP_LOC);
Lee Leahyb5ad8272015-04-20 15:29:16 -0700150 if ((u32)fsp_header_ptr < 0xff) {
151 /* output something in case there is no serial */
152 post_code(0x4F);
153 die("Can't find the FSP!\n");
154 }
Lee Leahy3dad4892015-05-05 11:14:02 -0700155 }
156
Lee Leahyb5ad8272015-04-20 15:29:16 -0700157 /* call FSP PEI to Notify PostPciEnumeration */
158 notify_phase_proc = (FSP_NOTIFY_PHASE)(fsp_header_ptr->ImageBase +
159 fsp_header_ptr->NotifyPhaseEntryOffset);
160 notify_phase_params.Phase = phase;
Lee Leahy3dad4892015-05-05 11:14:02 -0700161
Lee Leahyb5ad8272015-04-20 15:29:16 -0700162 timestamp_add_now(phase == EnumInitPhaseReadyToBoot ?
163 TS_FSP_BEFORE_FINALIZE : TS_FSP_BEFORE_ENUMERATE);
Lee Leahy3dad4892015-05-05 11:14:02 -0700164
Lee Leahyb5ad8272015-04-20 15:29:16 -0700165 status = notify_phase_proc(&notify_phase_params);
Lee Leahy3dad4892015-05-05 11:14:02 -0700166
Lee Leahyb5ad8272015-04-20 15:29:16 -0700167 timestamp_add_now(phase == EnumInitPhaseReadyToBoot ?
168 TS_FSP_AFTER_FINALIZE : TS_FSP_AFTER_ENUMERATE);
Lee Leahy3dad4892015-05-05 11:14:02 -0700169
Lee Leahyb5ad8272015-04-20 15:29:16 -0700170 if (status != 0)
171 printk(BIOS_ERR, "FSP API NotifyPhase failed for phase 0x%x with status: 0x%x\n",
172 phase, status);
Lee Leahy3dad4892015-05-05 11:14:02 -0700173}
Lee Leahy3dad4892015-05-05 11:14:02 -0700174
Lee Leahyb5ad8272015-04-20 15:29:16 -0700175static void fsp_notify_boot_state_callback(void *arg)
Lee Leahy3dad4892015-05-05 11:14:02 -0700176{
Lee Leahyb5ad8272015-04-20 15:29:16 -0700177 u32 phase = (u32)arg;
Lee Leahy3dad4892015-05-05 11:14:02 -0700178
Lee Leahyb5ad8272015-04-20 15:29:16 -0700179 printk(BIOS_SPEW, "Calling FspNotify(0x%08x)\n", phase);
180 fsp_notify(phase);
Lee Leahy3dad4892015-05-05 11:14:02 -0700181}
182
Lee Leahyb5ad8272015-04-20 15:29:16 -0700183BOOT_STATE_INIT_ENTRY(BS_DEV_RESOURCES, BS_ON_EXIT,
184 fsp_notify_boot_state_callback,
185 (void *)EnumInitPhaseAfterPciEnumeration);
186BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_LOAD, BS_ON_EXIT,
187 fsp_notify_boot_state_callback,
188 (void *)EnumInitPhaseReadyToBoot);
189BOOT_STATE_INIT_ENTRY(BS_OS_RESUME, BS_ON_ENTRY,
190 fsp_notify_boot_state_callback,
191 (void *)EnumInitPhaseReadyToBoot);
192
Lee Leahyb5ad8272015-04-20 15:29:16 -0700193struct fsp_runtime {
194 uint32_t fih;
195 uint32_t hob_list;
196} __attribute__((packed));
197
198
199void fsp_set_runtime(FSP_INFO_HEADER *fih, void *hob_list)
Lee Leahy3dad4892015-05-05 11:14:02 -0700200{
Lee Leahyb5ad8272015-04-20 15:29:16 -0700201 struct fsp_runtime *fspr;
202
203 fspr = cbmem_add(CBMEM_ID_FSP_RUNTIME, sizeof(*fspr));
204
205 if (fspr == NULL)
206 die("Can't save FSP runtime information.\n");
207
208 fspr->fih = (uintptr_t)fih;
209 fspr->hob_list = (uintptr_t)hob_list;
Lee Leahy3dad4892015-05-05 11:14:02 -0700210}
211
Lee Leahyb5ad8272015-04-20 15:29:16 -0700212FSP_INFO_HEADER *fsp_get_fih(void)
Lee Leahy3dad4892015-05-05 11:14:02 -0700213{
Lee Leahyb5ad8272015-04-20 15:29:16 -0700214 struct fsp_runtime *fspr;
215
216 fspr = cbmem_find(CBMEM_ID_FSP_RUNTIME);
217
218 if (fspr == NULL)
219 return NULL;
220
221 return (void *)(uintptr_t)fspr->fih;
Lee Leahy3dad4892015-05-05 11:14:02 -0700222}
223
Lee Leahyb5ad8272015-04-20 15:29:16 -0700224void *fsp_get_hob_list(void)
225{
226 struct fsp_runtime *fspr;
Lee Leahy3dad4892015-05-05 11:14:02 -0700227
Lee Leahyb5ad8272015-04-20 15:29:16 -0700228 fspr = cbmem_find(CBMEM_ID_FSP_RUNTIME);
229
230 if (fspr == NULL)
231 return NULL;
232
233 return (void *)(uintptr_t)fspr->hob_list;
234}
235
236void fsp_update_fih(FSP_INFO_HEADER *fih)
237{
238 struct fsp_runtime *fspr;
239
240 fspr = cbmem_find(CBMEM_ID_FSP_RUNTIME);
241
242 if (fspr == NULL)
243 die("Can't update FSP runtime information.\n");
244
245 fspr->fih = (uintptr_t)fih;
246}
Lee Leahy94b856e2015-10-15 12:07:03 -0700247
Lee Leahy66208bd2015-10-15 16:17:58 -0700248void fsp_display_upd_value(const char *name, uint32_t size, uint64_t old,
Lee Leahy94b856e2015-10-15 12:07:03 -0700249 uint64_t new)
250{
251 if (old == new) {
252 switch (size) {
253 case 1:
254 printk(BIOS_SPEW, " 0x%02llx: %s\n", new, name);
255 break;
256
257 case 2:
258 printk(BIOS_SPEW, " 0x%04llx: %s\n", new, name);
259 break;
260
261 case 4:
262 printk(BIOS_SPEW, " 0x%08llx: %s\n", new, name);
263 break;
264
265 case 8:
266 printk(BIOS_SPEW, " 0x%016llx: %s\n", new, name);
267 break;
268 }
269 } else {
270 switch (size) {
271 case 1:
272 printk(BIOS_SPEW, " 0x%02llx --> 0x%02llx: %s\n", old,
273 new, name);
274 break;
275
276 case 2:
277 printk(BIOS_SPEW, " 0x%04llx --> 0x%04llx: %s\n", old,
278 new, name);
279 break;
280
281 case 4:
282 printk(BIOS_SPEW, " 0x%08llx --> 0x%08llx: %s\n", old,
283 new, name);
284 break;
285
286 case 8:
287 printk(BIOS_SPEW, " 0x%016llx --> 0x%016llx: %s\n",
288 old, new, name);
289 break;
290 }
291 }
292}