blob: d44f0f015711c221934a5003e10e5c9a11df9542 [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.
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
Patrick Georgib890a122015-03-26 15:17:45 +010018 * Foundation, Inc.
Lee Leahy3dad4892015-05-05 11:14:02 -070019 */
20
Lee Leahy3dad4892015-05-05 11:14:02 -070021#include <bootstate.h>
22#include <cbmem.h>
Lee Leahyb5ad8272015-04-20 15:29:16 -070023#include <console/console.h>
Aaron Durbin789f2b62015-09-09 17:05:06 -050024#include <fsp/util.h>
Lee Leahy3dad4892015-05-05 11:14:02 -070025#include <timestamp.h>
26
Lee Leahyb5ad8272015-04-20 15:29:16 -070027/* Locate the FSP binary in the coreboot filesystem */
Lee Leahya8874922015-08-26 14:58:29 -070028FSP_INFO_HEADER *find_fsp(uintptr_t fsp_base_address)
Lee Leahy3dad4892015-05-05 11:14:02 -070029{
Lee Leahyb5ad8272015-04-20 15:29:16 -070030 union {
31 EFI_FFS_FILE_HEADER *ffh;
32 FSP_INFO_HEADER *fih;
33 EFI_FIRMWARE_VOLUME_EXT_HEADER *fveh;
34 EFI_FIRMWARE_VOLUME_HEADER *fvh;
35 EFI_RAW_SECTION *rs;
36 u8 *u8;
37 u32 u32;
38 } fsp_ptr;
Alexandru Gagniuc5c261222015-08-29 18:53:43 -070039 static const union {
40 char str_id[8];
41 u32 int_id[2];
42 } fsp_id = {
43 .str_id = CONFIG_FSP_IMAGE_ID_STRING
44 };
45
Lee Leahyb5ad8272015-04-20 15:29:16 -070046 u32 *image_id;
Lee Leahy3dad4892015-05-05 11:14:02 -070047
Lee Leahyb5ad8272015-04-20 15:29:16 -070048 for (;;) {
49 /* Get the FSP binary base address in CBFS */
Lee Leahya8874922015-08-26 14:58:29 -070050 fsp_ptr.u32 = fsp_base_address;
Lee Leahy3dad4892015-05-05 11:14:02 -070051
Lee Leahyb5ad8272015-04-20 15:29:16 -070052 /* Check the FV signature, _FVH */
53 if (fsp_ptr.fvh->Signature != 0x4856465F) {
54 fsp_ptr.u8 = (u8 *)ERROR_NO_FV_SIG;
55 break;
Lee Leahy3dad4892015-05-05 11:14:02 -070056 }
57
Lee Leahyb5ad8272015-04-20 15:29:16 -070058 /* Locate the file header which follows the FV header. */
59 fsp_ptr.u8 += fsp_ptr.fvh->ExtHeaderOffset;
60 fsp_ptr.u8 += fsp_ptr.fveh->ExtHeaderSize;
Alexandru Gagniuc3f2a9452015-08-29 18:25:10 -070061 fsp_ptr.u8 = (u8 *)ALIGN_UP(fsp_ptr.u32, 8);
Lee Leahyb5ad8272015-04-20 15:29:16 -070062
63 /* Check the FFS GUID */
64 if ((((u32 *)&fsp_ptr.ffh->Name)[0] != 0x912740BE)
65 || (((u32 *)&fsp_ptr.ffh->Name)[1] != 0x47342284)
66 || (((u32 *)&fsp_ptr.ffh->Name)[2] != 0xB08471B9)
67 || (((u32 *)&fsp_ptr.ffh->Name)[3] != 0x0C3F3527)) {
68 fsp_ptr.u8 = (u8 *)ERROR_NO_FFS_GUID;
69 break;
70 }
71
72 /* Locate the Raw Section Header */
73 fsp_ptr.u8 += sizeof(EFI_FFS_FILE_HEADER);
74
75 if (fsp_ptr.rs->Type != EFI_SECTION_RAW) {
76 fsp_ptr.u8 = (u8 *)ERROR_NO_INFO_HEADER;
77 break;
78 }
79
80 /* Locate the FSP INFO Header which follows the Raw Header. */
81 fsp_ptr.u8 += sizeof(EFI_RAW_SECTION);
82
83 /* Verify that the FSP base address.*/
Lee Leahya8874922015-08-26 14:58:29 -070084 if (fsp_ptr.fih->ImageBase != fsp_base_address) {
Lee Leahyb5ad8272015-04-20 15:29:16 -070085 fsp_ptr.u8 = (u8 *)ERROR_IMAGEBASE_MISMATCH;
86 break;
87 }
88
89 /* Verify the FSP Signature */
90 if (fsp_ptr.fih->Signature != FSP_SIG) {
91 fsp_ptr.u8 = (u8 *)ERROR_INFO_HEAD_SIG_MISMATCH;
92 break;
93 }
94
95 /* Verify the FSP ID */
96 image_id = (u32 *)&fsp_ptr.fih->ImageId[0];
Alexandru Gagniuc5c261222015-08-29 18:53:43 -070097 if ((image_id[0] != fsp_id.int_id[0])
98 || (image_id[1] != fsp_id.int_id[1]))
Lee Leahyb5ad8272015-04-20 15:29:16 -070099 fsp_ptr.u8 = (u8 *)ERROR_FSP_SIG_MISMATCH;
100 break;
Lee Leahy3dad4892015-05-05 11:14:02 -0700101 }
102
Lee Leahyb5ad8272015-04-20 15:29:16 -0700103 return fsp_ptr.fih;
Lee Leahy3dad4892015-05-05 11:14:02 -0700104}
105
Lee Leahyb5ad8272015-04-20 15:29:16 -0700106void print_fsp_info(FSP_INFO_HEADER *fsp_header)
Lee Leahy3dad4892015-05-05 11:14:02 -0700107{
Lee Leahyb5ad8272015-04-20 15:29:16 -0700108 u8 *fsp_base;
Lee Leahy3dad4892015-05-05 11:14:02 -0700109
Lee Leahyb5ad8272015-04-20 15:29:16 -0700110 fsp_base = (u8 *)fsp_header->ImageBase;
111 printk(BIOS_SPEW, "FSP_INFO_HEADER: %p\n", fsp_header);
112 printk(BIOS_INFO, "FSP Signature: %c%c%c%c%c%c%c%c\n",
113 fsp_header->ImageId[0], fsp_header->ImageId[1],
114 fsp_header->ImageId[2], fsp_header->ImageId[3],
115 fsp_header->ImageId[4], fsp_header->ImageId[5],
116 fsp_header->ImageId[6], fsp_header->ImageId[7]);
117 printk(BIOS_INFO, "FSP Header Version: %d\n",
118 fsp_header->HeaderRevision);
119 printk(BIOS_INFO, "FSP Revision: %d.%d\n",
120 (u8)((fsp_header->ImageRevision >> 8) & 0xff),
121 (u8)(fsp_header->ImageRevision & 0xff));
122#if IS_ENABLED(CONFIG_DISPLAY_FSP_ENTRY_POINTS)
123 printk(BIOS_SPEW, "FSP Entry Points:\n");
124 printk(BIOS_SPEW, " 0x%p: Image Base\n", fsp_base);
125 printk(BIOS_SPEW, " 0x%p: TempRamInit\n",
126 &fsp_base[fsp_header->TempRamInitEntryOffset]);
127 printk(BIOS_SPEW, " 0x%p: FspInit\n",
128 &fsp_base[fsp_header->FspInitEntryOffset]);
129 if (fsp_header->HeaderRevision >= FSP_HEADER_REVISION_2) {
130 printk(BIOS_SPEW, " 0x%p: MemoryInit\n",
131 &fsp_base[fsp_header->FspMemoryInitEntryOffset]);
132 printk(BIOS_SPEW, " 0x%p: TempRamExit\n",
133 &fsp_base[fsp_header->TempRamExitEntryOffset]);
134 printk(BIOS_SPEW, " 0x%p: SiliconInit\n",
135 &fsp_base[fsp_header->FspSiliconInitEntryOffset]);
136 }
137 printk(BIOS_SPEW, " 0x%p: NotifyPhase\n",
138 &fsp_base[fsp_header->NotifyPhaseEntryOffset]);
139 printk(BIOS_SPEW, " 0x%p: Image End\n",
140 &fsp_base[fsp_header->ImageSize]);
141#endif
142}
143
Lee Leahyb5ad8272015-04-20 15:29:16 -0700144void fsp_notify(u32 phase)
145{
146 FSP_NOTIFY_PHASE notify_phase_proc;
147 NOTIFY_PHASE_PARAMS notify_phase_params;
148 EFI_STATUS status;
149 FSP_INFO_HEADER *fsp_header_ptr;
150
151 fsp_header_ptr = fsp_get_fih();
152 if (fsp_header_ptr == NULL) {
Lee Leahya8874922015-08-26 14:58:29 -0700153 fsp_header_ptr = (void *)find_fsp(CONFIG_FSP_LOC);
Lee Leahyb5ad8272015-04-20 15:29:16 -0700154 if ((u32)fsp_header_ptr < 0xff) {
155 /* output something in case there is no serial */
156 post_code(0x4F);
157 die("Can't find the FSP!\n");
158 }
Lee Leahy3dad4892015-05-05 11:14:02 -0700159 }
160
Lee Leahyb5ad8272015-04-20 15:29:16 -0700161 /* call FSP PEI to Notify PostPciEnumeration */
162 notify_phase_proc = (FSP_NOTIFY_PHASE)(fsp_header_ptr->ImageBase +
163 fsp_header_ptr->NotifyPhaseEntryOffset);
164 notify_phase_params.Phase = phase;
Lee Leahy3dad4892015-05-05 11:14:02 -0700165
Lee Leahyb5ad8272015-04-20 15:29:16 -0700166 timestamp_add_now(phase == EnumInitPhaseReadyToBoot ?
167 TS_FSP_BEFORE_FINALIZE : TS_FSP_BEFORE_ENUMERATE);
Lee Leahy3dad4892015-05-05 11:14:02 -0700168
Lee Leahyb5ad8272015-04-20 15:29:16 -0700169 status = notify_phase_proc(&notify_phase_params);
Lee Leahy3dad4892015-05-05 11:14:02 -0700170
Lee Leahyb5ad8272015-04-20 15:29:16 -0700171 timestamp_add_now(phase == EnumInitPhaseReadyToBoot ?
172 TS_FSP_AFTER_FINALIZE : TS_FSP_AFTER_ENUMERATE);
Lee Leahy3dad4892015-05-05 11:14:02 -0700173
Lee Leahyb5ad8272015-04-20 15:29:16 -0700174 if (status != 0)
175 printk(BIOS_ERR, "FSP API NotifyPhase failed for phase 0x%x with status: 0x%x\n",
176 phase, status);
Lee Leahy3dad4892015-05-05 11:14:02 -0700177}
Lee Leahy3dad4892015-05-05 11:14:02 -0700178
Lee Leahyb5ad8272015-04-20 15:29:16 -0700179static void fsp_notify_boot_state_callback(void *arg)
Lee Leahy3dad4892015-05-05 11:14:02 -0700180{
Lee Leahyb5ad8272015-04-20 15:29:16 -0700181 u32 phase = (u32)arg;
Lee Leahy3dad4892015-05-05 11:14:02 -0700182
Lee Leahyb5ad8272015-04-20 15:29:16 -0700183 printk(BIOS_SPEW, "Calling FspNotify(0x%08x)\n", phase);
184 fsp_notify(phase);
Lee Leahy3dad4892015-05-05 11:14:02 -0700185}
186
Lee Leahyb5ad8272015-04-20 15:29:16 -0700187BOOT_STATE_INIT_ENTRY(BS_DEV_RESOURCES, BS_ON_EXIT,
188 fsp_notify_boot_state_callback,
189 (void *)EnumInitPhaseAfterPciEnumeration);
190BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_LOAD, BS_ON_EXIT,
191 fsp_notify_boot_state_callback,
192 (void *)EnumInitPhaseReadyToBoot);
193BOOT_STATE_INIT_ENTRY(BS_OS_RESUME, BS_ON_ENTRY,
194 fsp_notify_boot_state_callback,
195 (void *)EnumInitPhaseReadyToBoot);
196
Lee Leahyb5ad8272015-04-20 15:29:16 -0700197struct fsp_runtime {
198 uint32_t fih;
199 uint32_t hob_list;
200} __attribute__((packed));
201
202
203void fsp_set_runtime(FSP_INFO_HEADER *fih, void *hob_list)
Lee Leahy3dad4892015-05-05 11:14:02 -0700204{
Lee Leahyb5ad8272015-04-20 15:29:16 -0700205 struct fsp_runtime *fspr;
206
207 fspr = cbmem_add(CBMEM_ID_FSP_RUNTIME, sizeof(*fspr));
208
209 if (fspr == NULL)
210 die("Can't save FSP runtime information.\n");
211
212 fspr->fih = (uintptr_t)fih;
213 fspr->hob_list = (uintptr_t)hob_list;
Lee Leahy3dad4892015-05-05 11:14:02 -0700214}
215
Lee Leahyb5ad8272015-04-20 15:29:16 -0700216FSP_INFO_HEADER *fsp_get_fih(void)
Lee Leahy3dad4892015-05-05 11:14:02 -0700217{
Lee Leahyb5ad8272015-04-20 15:29:16 -0700218 struct fsp_runtime *fspr;
219
220 fspr = cbmem_find(CBMEM_ID_FSP_RUNTIME);
221
222 if (fspr == NULL)
223 return NULL;
224
225 return (void *)(uintptr_t)fspr->fih;
Lee Leahy3dad4892015-05-05 11:14:02 -0700226}
227
Lee Leahyb5ad8272015-04-20 15:29:16 -0700228void *fsp_get_hob_list(void)
229{
230 struct fsp_runtime *fspr;
Lee Leahy3dad4892015-05-05 11:14:02 -0700231
Lee Leahyb5ad8272015-04-20 15:29:16 -0700232 fspr = cbmem_find(CBMEM_ID_FSP_RUNTIME);
233
234 if (fspr == NULL)
235 return NULL;
236
237 return (void *)(uintptr_t)fspr->hob_list;
238}
239
240void fsp_update_fih(FSP_INFO_HEADER *fih)
241{
242 struct fsp_runtime *fspr;
243
244 fspr = cbmem_find(CBMEM_ID_FSP_RUNTIME);
245
246 if (fspr == NULL)
247 die("Can't update FSP runtime information.\n");
248
249 fspr->fih = (uintptr_t)fih;
250}