blob: ab9f28f93f147d35684484bfd032226637168c55 [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>
Elyes HAOUAS2195f7a2019-06-21 07:20:12 +020019#include <commonlib/helpers.h>
Lee Leahyb5ad8272015-04-20 15:29:16 -070020#include <console/console.h>
Lee Leahyc52a4f72016-08-09 09:02:13 -070021#include <console/streams.h>
Aaron Durbin789f2b62015-09-09 17:05:06 -050022#include <fsp/util.h>
Lee Leahy3dad4892015-05-05 11:14:02 -070023#include <timestamp.h>
24
Lee Leahyb5ad8272015-04-20 15:29:16 -070025/* Locate the FSP binary in the coreboot filesystem */
Lee Leahya8874922015-08-26 14:58:29 -070026FSP_INFO_HEADER *find_fsp(uintptr_t fsp_base_address)
Lee Leahy3dad4892015-05-05 11:14:02 -070027{
Lee Leahyb5ad8272015-04-20 15:29:16 -070028 union {
29 EFI_FFS_FILE_HEADER *ffh;
30 FSP_INFO_HEADER *fih;
31 EFI_FIRMWARE_VOLUME_EXT_HEADER *fveh;
32 EFI_FIRMWARE_VOLUME_HEADER *fvh;
33 EFI_RAW_SECTION *rs;
Lee Leahyb5ad8272015-04-20 15:29:16 -070034 u32 u32;
35 } fsp_ptr;
Alexandru Gagniuc5c261222015-08-29 18:53:43 -070036
Nico Hubere7947df2017-05-09 16:03:24 +020037 u64 *image_id;
Lee Leahy3dad4892015-05-05 11:14:02 -070038
Lee Leahy00c35c12016-05-17 08:57:42 -070039 /* Get the FSP binary base address in CBFS */
40 fsp_ptr.u32 = fsp_base_address;
Lee Leahy3dad4892015-05-05 11:14:02 -070041
Lee Leahy00c35c12016-05-17 08:57:42 -070042 /* Check the FV signature, _FVH */
Lee Leahy216712a2017-03-17 11:23:32 -070043 if (fsp_ptr.fvh->Signature != 0x4856465F)
Lee Leahy00c35c12016-05-17 08:57:42 -070044 return (FSP_INFO_HEADER *)ERROR_NO_FV_SIG;
Lee Leahy3dad4892015-05-05 11:14:02 -070045
Lee Leahy00c35c12016-05-17 08:57:42 -070046 /* Locate the file header which follows the FV header. */
Lee Leahyd3989a22016-05-17 09:29:09 -070047 fsp_ptr.u32 += fsp_ptr.fvh->ExtHeaderOffset;
48 fsp_ptr.u32 += fsp_ptr.fveh->ExtHeaderSize;
49 fsp_ptr.u32 = ALIGN_UP(fsp_ptr.u32, 8);
Lee Leahy00c35c12016-05-17 08:57:42 -070050
51 /* Check the FFS GUID */
52 if ((((u32 *)&fsp_ptr.ffh->Name)[0] != 0x912740BE)
53 || (((u32 *)&fsp_ptr.ffh->Name)[1] != 0x47342284)
54 || (((u32 *)&fsp_ptr.ffh->Name)[2] != 0xB08471B9)
55 || (((u32 *)&fsp_ptr.ffh->Name)[3] != 0x0C3F3527)) {
56 return (FSP_INFO_HEADER *)ERROR_NO_FFS_GUID;
57 }
58
59 /* Locate the Raw Section Header */
Lee Leahyd3989a22016-05-17 09:29:09 -070060 fsp_ptr.u32 += sizeof(EFI_FFS_FILE_HEADER);
Lee Leahy00c35c12016-05-17 08:57:42 -070061
Lee Leahy216712a2017-03-17 11:23:32 -070062 if (fsp_ptr.rs->Type != EFI_SECTION_RAW)
Lee Leahy00c35c12016-05-17 08:57:42 -070063 return (FSP_INFO_HEADER *)ERROR_NO_INFO_HEADER;
Lee Leahy00c35c12016-05-17 08:57:42 -070064
65 /* Locate the FSP INFO Header which follows the Raw Header. */
Lee Leahyd3989a22016-05-17 09:29:09 -070066 fsp_ptr.u32 += sizeof(EFI_RAW_SECTION);
Lee Leahy00c35c12016-05-17 08:57:42 -070067
68 /* Verify that the FSP base address.*/
Lee Leahy216712a2017-03-17 11:23:32 -070069 if (fsp_ptr.fih->ImageBase != fsp_base_address)
Lee Leahy00c35c12016-05-17 08:57:42 -070070 return (FSP_INFO_HEADER *)ERROR_IMAGEBASE_MISMATCH;
Lee Leahy00c35c12016-05-17 08:57:42 -070071
72 /* Verify the FSP Signature */
Lee Leahy216712a2017-03-17 11:23:32 -070073 if (fsp_ptr.fih->Signature != FSP_SIG)
Lee Leahy00c35c12016-05-17 08:57:42 -070074 return (FSP_INFO_HEADER *)ERROR_INFO_HEAD_SIG_MISMATCH;
Lee Leahy00c35c12016-05-17 08:57:42 -070075
76 /* Verify the FSP ID */
Nico Hubere7947df2017-05-09 16:03:24 +020077 image_id = (u64 *)&fsp_ptr.fih->ImageId[0];
78 if (*image_id != FSP_IMAGE_ID)
Lee Leahy00c35c12016-05-17 08:57:42 -070079 return (FSP_INFO_HEADER *)ERROR_FSP_SIG_MISMATCH;
80
Nico Hubere7947df2017-05-09 16:03:24 +020081 /* Verify the FSP Revision */
Matt DeVillier77c01e12017-09-07 11:28:53 -050082 if (fsp_ptr.fih->ImageRevision > FSP_IMAGE_REV)
Nico Hubere7947df2017-05-09 16:03:24 +020083 return (FSP_INFO_HEADER *)ERROR_FSP_REV_MISMATCH;
84
Lee Leahyb5ad8272015-04-20 15:29:16 -070085 return fsp_ptr.fih;
Lee Leahy3dad4892015-05-05 11:14:02 -070086}
87
Lee Leahyb5ad8272015-04-20 15:29:16 -070088void print_fsp_info(FSP_INFO_HEADER *fsp_header)
Lee Leahy3dad4892015-05-05 11:14:02 -070089{
Lee Leahyb5ad8272015-04-20 15:29:16 -070090 u8 *fsp_base;
Lee Leahy3dad4892015-05-05 11:14:02 -070091
Lee Leahyb5ad8272015-04-20 15:29:16 -070092 fsp_base = (u8 *)fsp_header->ImageBase;
93 printk(BIOS_SPEW, "FSP_INFO_HEADER: %p\n", fsp_header);
94 printk(BIOS_INFO, "FSP Signature: %c%c%c%c%c%c%c%c\n",
95 fsp_header->ImageId[0], fsp_header->ImageId[1],
96 fsp_header->ImageId[2], fsp_header->ImageId[3],
97 fsp_header->ImageId[4], fsp_header->ImageId[5],
98 fsp_header->ImageId[6], fsp_header->ImageId[7]);
99 printk(BIOS_INFO, "FSP Header Version: %d\n",
100 fsp_header->HeaderRevision);
Dhaval Sharma590ac642015-11-02 17:12:10 +0530101 printk(BIOS_INFO, "FSP Revision: %d.%d.%d.%d\n",
102 (u8)((fsp_header->ImageRevision >> 24) & 0xff),
103 (u8)((fsp_header->ImageRevision >> 16) & 0xff),
Lee Leahyb5ad8272015-04-20 15:29:16 -0700104 (u8)((fsp_header->ImageRevision >> 8) & 0xff),
105 (u8)(fsp_header->ImageRevision & 0xff));
Julius Wernercd49cce2019-03-05 16:53:33 -0800106#if CONFIG(DISPLAY_FSP_ENTRY_POINTS)
Lee Leahyb5ad8272015-04-20 15:29:16 -0700107 printk(BIOS_SPEW, "FSP Entry Points:\n");
108 printk(BIOS_SPEW, " 0x%p: Image Base\n", fsp_base);
109 printk(BIOS_SPEW, " 0x%p: TempRamInit\n",
110 &fsp_base[fsp_header->TempRamInitEntryOffset]);
111 printk(BIOS_SPEW, " 0x%p: FspInit\n",
112 &fsp_base[fsp_header->FspInitEntryOffset]);
113 if (fsp_header->HeaderRevision >= FSP_HEADER_REVISION_2) {
114 printk(BIOS_SPEW, " 0x%p: MemoryInit\n",
115 &fsp_base[fsp_header->FspMemoryInitEntryOffset]);
116 printk(BIOS_SPEW, " 0x%p: TempRamExit\n",
117 &fsp_base[fsp_header->TempRamExitEntryOffset]);
118 printk(BIOS_SPEW, " 0x%p: SiliconInit\n",
119 &fsp_base[fsp_header->FspSiliconInitEntryOffset]);
120 }
121 printk(BIOS_SPEW, " 0x%p: NotifyPhase\n",
122 &fsp_base[fsp_header->NotifyPhaseEntryOffset]);
123 printk(BIOS_SPEW, " 0x%p: Image End\n",
124 &fsp_base[fsp_header->ImageSize]);
125#endif
126}
127
Lee Leahyb5ad8272015-04-20 15:29:16 -0700128void fsp_notify(u32 phase)
129{
130 FSP_NOTIFY_PHASE notify_phase_proc;
131 NOTIFY_PHASE_PARAMS notify_phase_params;
132 EFI_STATUS status;
133 FSP_INFO_HEADER *fsp_header_ptr;
134
135 fsp_header_ptr = fsp_get_fih();
136 if (fsp_header_ptr == NULL) {
Lee Leahya8874922015-08-26 14:58:29 -0700137 fsp_header_ptr = (void *)find_fsp(CONFIG_FSP_LOC);
Lee Leahyb5ad8272015-04-20 15:29:16 -0700138 if ((u32)fsp_header_ptr < 0xff) {
139 /* output something in case there is no serial */
140 post_code(0x4F);
141 die("Can't find the FSP!\n");
142 }
Lee Leahy3dad4892015-05-05 11:14:02 -0700143 }
144
Lee Leahyb5ad8272015-04-20 15:29:16 -0700145 /* call FSP PEI to Notify PostPciEnumeration */
146 notify_phase_proc = (FSP_NOTIFY_PHASE)(fsp_header_ptr->ImageBase +
147 fsp_header_ptr->NotifyPhaseEntryOffset);
148 notify_phase_params.Phase = phase;
Lee Leahy3dad4892015-05-05 11:14:02 -0700149
Duncan Lauriefb509832015-11-22 14:53:57 -0800150 if (phase == EnumInitPhaseReadyToBoot) {
Duncan Lauriefb509832015-11-22 14:53:57 -0800151 timestamp_add_now(TS_FSP_BEFORE_FINALIZE);
152 post_code(POST_FSP_NOTIFY_BEFORE_FINALIZE);
Lee Leahya5244c32015-12-17 11:13:01 -0800153 } else {
154 timestamp_add_now(TS_FSP_BEFORE_ENUMERATE);
155 post_code(POST_FSP_NOTIFY_BEFORE_ENUMERATE);
Duncan Lauriefb509832015-11-22 14:53:57 -0800156 }
Lee Leahy3dad4892015-05-05 11:14:02 -0700157
Lee Leahyb5ad8272015-04-20 15:29:16 -0700158 status = notify_phase_proc(&notify_phase_params);
Lee Leahy3dad4892015-05-05 11:14:02 -0700159
Lee Leahyb5ad8272015-04-20 15:29:16 -0700160 timestamp_add_now(phase == EnumInitPhaseReadyToBoot ?
161 TS_FSP_AFTER_FINALIZE : TS_FSP_AFTER_ENUMERATE);
Lee Leahy3dad4892015-05-05 11:14:02 -0700162
Lee Leahyb5ad8272015-04-20 15:29:16 -0700163 if (status != 0)
164 printk(BIOS_ERR, "FSP API NotifyPhase failed for phase 0x%x with status: 0x%x\n",
165 phase, status);
Lee Leahy3dad4892015-05-05 11:14:02 -0700166}
Lee Leahy3dad4892015-05-05 11:14:02 -0700167
Lee Leahyb5ad8272015-04-20 15:29:16 -0700168static void fsp_notify_boot_state_callback(void *arg)
Lee Leahy3dad4892015-05-05 11:14:02 -0700169{
Lee Leahyb5ad8272015-04-20 15:29:16 -0700170 u32 phase = (u32)arg;
Lee Leahy3dad4892015-05-05 11:14:02 -0700171
Lee Leahyb5ad8272015-04-20 15:29:16 -0700172 printk(BIOS_SPEW, "Calling FspNotify(0x%08x)\n", phase);
173 fsp_notify(phase);
Lee Leahy3dad4892015-05-05 11:14:02 -0700174}
175
Lee Leahyb5ad8272015-04-20 15:29:16 -0700176BOOT_STATE_INIT_ENTRY(BS_DEV_RESOURCES, BS_ON_EXIT,
177 fsp_notify_boot_state_callback,
178 (void *)EnumInitPhaseAfterPciEnumeration);
179BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_LOAD, BS_ON_EXIT,
180 fsp_notify_boot_state_callback,
181 (void *)EnumInitPhaseReadyToBoot);
182BOOT_STATE_INIT_ENTRY(BS_OS_RESUME, BS_ON_ENTRY,
183 fsp_notify_boot_state_callback,
184 (void *)EnumInitPhaseReadyToBoot);
185
Lee Leahyb5ad8272015-04-20 15:29:16 -0700186struct fsp_runtime {
187 uint32_t fih;
188 uint32_t hob_list;
Stefan Reinauer6a001132017-07-13 02:20:27 +0200189} __packed;
Lee Leahyb5ad8272015-04-20 15:29:16 -0700190
191
192void fsp_set_runtime(FSP_INFO_HEADER *fih, void *hob_list)
Lee Leahy3dad4892015-05-05 11:14:02 -0700193{
Lee Leahyb5ad8272015-04-20 15:29:16 -0700194 struct fsp_runtime *fspr;
195
196 fspr = cbmem_add(CBMEM_ID_FSP_RUNTIME, sizeof(*fspr));
197
198 if (fspr == NULL)
199 die("Can't save FSP runtime information.\n");
200
201 fspr->fih = (uintptr_t)fih;
202 fspr->hob_list = (uintptr_t)hob_list;
Lee Leahy3dad4892015-05-05 11:14:02 -0700203}
204
Lee Leahyb5ad8272015-04-20 15:29:16 -0700205FSP_INFO_HEADER *fsp_get_fih(void)
Lee Leahy3dad4892015-05-05 11:14:02 -0700206{
Lee Leahyb5ad8272015-04-20 15:29:16 -0700207 struct fsp_runtime *fspr;
208
209 fspr = cbmem_find(CBMEM_ID_FSP_RUNTIME);
210
211 if (fspr == NULL)
212 return NULL;
213
214 return (void *)(uintptr_t)fspr->fih;
Lee Leahy3dad4892015-05-05 11:14:02 -0700215}
216
Lee Leahyb5ad8272015-04-20 15:29:16 -0700217void *fsp_get_hob_list(void)
218{
219 struct fsp_runtime *fspr;
Lee Leahy3dad4892015-05-05 11:14:02 -0700220
Lee Leahyb5ad8272015-04-20 15:29:16 -0700221 fspr = cbmem_find(CBMEM_ID_FSP_RUNTIME);
222
223 if (fspr == NULL)
224 return NULL;
225
226 return (void *)(uintptr_t)fspr->hob_list;
227}
228
229void fsp_update_fih(FSP_INFO_HEADER *fih)
230{
231 struct fsp_runtime *fspr;
232
233 fspr = cbmem_find(CBMEM_ID_FSP_RUNTIME);
234
235 if (fspr == NULL)
236 die("Can't update FSP runtime information.\n");
237
238 fspr->fih = (uintptr_t)fih;
239}
Lee Leahy94b856e2015-10-15 12:07:03 -0700240
Lee Leahy66208bd2015-10-15 16:17:58 -0700241void fsp_display_upd_value(const char *name, uint32_t size, uint64_t old,
Lee Leahy94b856e2015-10-15 12:07:03 -0700242 uint64_t new)
243{
244 if (old == new) {
245 switch (size) {
246 case 1:
247 printk(BIOS_SPEW, " 0x%02llx: %s\n", new, name);
248 break;
249
250 case 2:
251 printk(BIOS_SPEW, " 0x%04llx: %s\n", new, name);
252 break;
253
254 case 4:
255 printk(BIOS_SPEW, " 0x%08llx: %s\n", new, name);
256 break;
257
258 case 8:
259 printk(BIOS_SPEW, " 0x%016llx: %s\n", new, name);
260 break;
261 }
262 } else {
263 switch (size) {
264 case 1:
265 printk(BIOS_SPEW, " 0x%02llx --> 0x%02llx: %s\n", old,
266 new, name);
267 break;
268
269 case 2:
270 printk(BIOS_SPEW, " 0x%04llx --> 0x%04llx: %s\n", old,
271 new, name);
272 break;
273
274 case 4:
275 printk(BIOS_SPEW, " 0x%08llx --> 0x%08llx: %s\n", old,
276 new, name);
277 break;
278
279 case 8:
280 printk(BIOS_SPEW, " 0x%016llx --> 0x%016llx: %s\n",
281 old, new, name);
282 break;
283 }
284 }
285}
Lee Leahyc52a4f72016-08-09 09:02:13 -0700286
Lee Leahy216712a2017-03-17 11:23:32 -0700287__attribute__((cdecl)) size_t fsp_write_line(uint8_t *buffer,
288 size_t number_of_bytes)
Lee Leahyc52a4f72016-08-09 09:02:13 -0700289{
290 console_write_line(buffer, number_of_bytes);
291 return number_of_bytes;
292}