blob: 18e86480c71c205d68327d3dc2a500e279ffbbbe [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>
Lee Leahy3dad4892015-05-05 11:14:02 -070024#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 */
28FSP_INFO_HEADER *find_fsp(void)
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;
39 u32 *image_id;
Lee Leahy3dad4892015-05-05 11:14:02 -070040
Lee Leahyb5ad8272015-04-20 15:29:16 -070041 for (;;) {
42 /* Get the FSP binary base address in CBFS */
43 fsp_ptr.u8 = (u8 *)CONFIG_FSP_LOC;
Lee Leahy3dad4892015-05-05 11:14:02 -070044
Lee Leahyb5ad8272015-04-20 15:29:16 -070045 /* Check the FV signature, _FVH */
46 if (fsp_ptr.fvh->Signature != 0x4856465F) {
47 fsp_ptr.u8 = (u8 *)ERROR_NO_FV_SIG;
48 break;
Lee Leahy3dad4892015-05-05 11:14:02 -070049 }
50
Lee Leahyb5ad8272015-04-20 15:29:16 -070051 /* Locate the file header which follows the FV header. */
52 fsp_ptr.u8 += fsp_ptr.fvh->ExtHeaderOffset;
53 fsp_ptr.u8 += fsp_ptr.fveh->ExtHeaderSize;
Alexandru Gagniuc3f2a9452015-08-29 18:25:10 -070054 fsp_ptr.u8 = (u8 *)ALIGN_UP(fsp_ptr.u32, 8);
Lee Leahyb5ad8272015-04-20 15:29:16 -070055
56 /* Check the FFS GUID */
57 if ((((u32 *)&fsp_ptr.ffh->Name)[0] != 0x912740BE)
58 || (((u32 *)&fsp_ptr.ffh->Name)[1] != 0x47342284)
59 || (((u32 *)&fsp_ptr.ffh->Name)[2] != 0xB08471B9)
60 || (((u32 *)&fsp_ptr.ffh->Name)[3] != 0x0C3F3527)) {
61 fsp_ptr.u8 = (u8 *)ERROR_NO_FFS_GUID;
62 break;
63 }
64
65 /* Locate the Raw Section Header */
66 fsp_ptr.u8 += sizeof(EFI_FFS_FILE_HEADER);
67
68 if (fsp_ptr.rs->Type != EFI_SECTION_RAW) {
69 fsp_ptr.u8 = (u8 *)ERROR_NO_INFO_HEADER;
70 break;
71 }
72
73 /* Locate the FSP INFO Header which follows the Raw Header. */
74 fsp_ptr.u8 += sizeof(EFI_RAW_SECTION);
75
76 /* Verify that the FSP base address.*/
77 if (fsp_ptr.fih->ImageBase != CONFIG_FSP_LOC) {
78 fsp_ptr.u8 = (u8 *)ERROR_IMAGEBASE_MISMATCH;
79 break;
80 }
81
82 /* Verify the FSP Signature */
83 if (fsp_ptr.fih->Signature != FSP_SIG) {
84 fsp_ptr.u8 = (u8 *)ERROR_INFO_HEAD_SIG_MISMATCH;
85 break;
86 }
87
88 /* Verify the FSP ID */
89 image_id = (u32 *)&fsp_ptr.fih->ImageId[0];
90 if ((image_id[0] != CONFIG_FSP_IMAGE_ID_DWORD0)
91 || (image_id[1] != CONFIG_FSP_IMAGE_ID_DWORD1))
92 fsp_ptr.u8 = (u8 *)ERROR_FSP_SIG_MISMATCH;
93 break;
Lee Leahy3dad4892015-05-05 11:14:02 -070094 }
95
Lee Leahyb5ad8272015-04-20 15:29:16 -070096 return fsp_ptr.fih;
Lee Leahy3dad4892015-05-05 11:14:02 -070097}
98
Lee Leahyb5ad8272015-04-20 15:29:16 -070099void print_fsp_info(FSP_INFO_HEADER *fsp_header)
Lee Leahy3dad4892015-05-05 11:14:02 -0700100{
Lee Leahyb5ad8272015-04-20 15:29:16 -0700101 u8 *fsp_base;
Lee Leahy3dad4892015-05-05 11:14:02 -0700102
Lee Leahyb5ad8272015-04-20 15:29:16 -0700103 fsp_base = (u8 *)fsp_header->ImageBase;
104 printk(BIOS_SPEW, "FSP_INFO_HEADER: %p\n", fsp_header);
105 printk(BIOS_INFO, "FSP Signature: %c%c%c%c%c%c%c%c\n",
106 fsp_header->ImageId[0], fsp_header->ImageId[1],
107 fsp_header->ImageId[2], fsp_header->ImageId[3],
108 fsp_header->ImageId[4], fsp_header->ImageId[5],
109 fsp_header->ImageId[6], fsp_header->ImageId[7]);
110 printk(BIOS_INFO, "FSP Header Version: %d\n",
111 fsp_header->HeaderRevision);
112 printk(BIOS_INFO, "FSP Revision: %d.%d\n",
113 (u8)((fsp_header->ImageRevision >> 8) & 0xff),
114 (u8)(fsp_header->ImageRevision & 0xff));
115#if IS_ENABLED(CONFIG_DISPLAY_FSP_ENTRY_POINTS)
116 printk(BIOS_SPEW, "FSP Entry Points:\n");
117 printk(BIOS_SPEW, " 0x%p: Image Base\n", fsp_base);
118 printk(BIOS_SPEW, " 0x%p: TempRamInit\n",
119 &fsp_base[fsp_header->TempRamInitEntryOffset]);
120 printk(BIOS_SPEW, " 0x%p: FspInit\n",
121 &fsp_base[fsp_header->FspInitEntryOffset]);
122 if (fsp_header->HeaderRevision >= FSP_HEADER_REVISION_2) {
123 printk(BIOS_SPEW, " 0x%p: MemoryInit\n",
124 &fsp_base[fsp_header->FspMemoryInitEntryOffset]);
125 printk(BIOS_SPEW, " 0x%p: TempRamExit\n",
126 &fsp_base[fsp_header->TempRamExitEntryOffset]);
127 printk(BIOS_SPEW, " 0x%p: SiliconInit\n",
128 &fsp_base[fsp_header->FspSiliconInitEntryOffset]);
129 }
130 printk(BIOS_SPEW, " 0x%p: NotifyPhase\n",
131 &fsp_base[fsp_header->NotifyPhaseEntryOffset]);
132 printk(BIOS_SPEW, " 0x%p: Image End\n",
133 &fsp_base[fsp_header->ImageSize]);
134#endif
135}
136
137#if ENV_RAMSTAGE
138
139void fsp_notify(u32 phase)
140{
141 FSP_NOTIFY_PHASE notify_phase_proc;
142 NOTIFY_PHASE_PARAMS notify_phase_params;
143 EFI_STATUS status;
144 FSP_INFO_HEADER *fsp_header_ptr;
145
146 fsp_header_ptr = fsp_get_fih();
147 if (fsp_header_ptr == NULL) {
148 fsp_header_ptr = (void *)find_fsp();
149 if ((u32)fsp_header_ptr < 0xff) {
150 /* output something in case there is no serial */
151 post_code(0x4F);
152 die("Can't find the FSP!\n");
153 }
Lee Leahy3dad4892015-05-05 11:14:02 -0700154 }
155
Lee Leahyb5ad8272015-04-20 15:29:16 -0700156 /* call FSP PEI to Notify PostPciEnumeration */
157 notify_phase_proc = (FSP_NOTIFY_PHASE)(fsp_header_ptr->ImageBase +
158 fsp_header_ptr->NotifyPhaseEntryOffset);
159 notify_phase_params.Phase = phase;
Lee Leahy3dad4892015-05-05 11:14:02 -0700160
Lee Leahyb5ad8272015-04-20 15:29:16 -0700161 timestamp_add_now(phase == EnumInitPhaseReadyToBoot ?
162 TS_FSP_BEFORE_FINALIZE : TS_FSP_BEFORE_ENUMERATE);
Lee Leahy3dad4892015-05-05 11:14:02 -0700163
Lee Leahyb5ad8272015-04-20 15:29:16 -0700164 status = notify_phase_proc(&notify_phase_params);
Lee Leahy3dad4892015-05-05 11:14:02 -0700165
Lee Leahyb5ad8272015-04-20 15:29:16 -0700166 timestamp_add_now(phase == EnumInitPhaseReadyToBoot ?
167 TS_FSP_AFTER_FINALIZE : TS_FSP_AFTER_ENUMERATE);
Lee Leahy3dad4892015-05-05 11:14:02 -0700168
Lee Leahyb5ad8272015-04-20 15:29:16 -0700169 if (status != 0)
170 printk(BIOS_ERR, "FSP API NotifyPhase failed for phase 0x%x with status: 0x%x\n",
171 phase, status);
Lee Leahy3dad4892015-05-05 11:14:02 -0700172}
Lee Leahy3dad4892015-05-05 11:14:02 -0700173
Lee Leahyb5ad8272015-04-20 15:29:16 -0700174static void fsp_notify_boot_state_callback(void *arg)
Lee Leahy3dad4892015-05-05 11:14:02 -0700175{
Lee Leahyb5ad8272015-04-20 15:29:16 -0700176 u32 phase = (u32)arg;
Lee Leahy3dad4892015-05-05 11:14:02 -0700177
Lee Leahyb5ad8272015-04-20 15:29:16 -0700178 printk(BIOS_SPEW, "Calling FspNotify(0x%08x)\n", phase);
179 fsp_notify(phase);
Lee Leahy3dad4892015-05-05 11:14:02 -0700180}
181
Lee Leahyb5ad8272015-04-20 15:29:16 -0700182BOOT_STATE_INIT_ENTRY(BS_DEV_RESOURCES, BS_ON_EXIT,
183 fsp_notify_boot_state_callback,
184 (void *)EnumInitPhaseAfterPciEnumeration);
185BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_LOAD, BS_ON_EXIT,
186 fsp_notify_boot_state_callback,
187 (void *)EnumInitPhaseReadyToBoot);
188BOOT_STATE_INIT_ENTRY(BS_OS_RESUME, BS_ON_ENTRY,
189 fsp_notify_boot_state_callback,
190 (void *)EnumInitPhaseReadyToBoot);
191
192#endif /* ENV_RAMSTAGE */
193
194struct fsp_runtime {
195 uint32_t fih;
196 uint32_t hob_list;
197} __attribute__((packed));
198
199
200void fsp_set_runtime(FSP_INFO_HEADER *fih, void *hob_list)
Lee Leahy3dad4892015-05-05 11:14:02 -0700201{
Lee Leahyb5ad8272015-04-20 15:29:16 -0700202 struct fsp_runtime *fspr;
203
204 fspr = cbmem_add(CBMEM_ID_FSP_RUNTIME, sizeof(*fspr));
205
206 if (fspr == NULL)
207 die("Can't save FSP runtime information.\n");
208
209 fspr->fih = (uintptr_t)fih;
210 fspr->hob_list = (uintptr_t)hob_list;
Lee Leahy3dad4892015-05-05 11:14:02 -0700211}
212
Lee Leahyb5ad8272015-04-20 15:29:16 -0700213FSP_INFO_HEADER *fsp_get_fih(void)
Lee Leahy3dad4892015-05-05 11:14:02 -0700214{
Lee Leahyb5ad8272015-04-20 15:29:16 -0700215 struct fsp_runtime *fspr;
216
217 fspr = cbmem_find(CBMEM_ID_FSP_RUNTIME);
218
219 if (fspr == NULL)
220 return NULL;
221
222 return (void *)(uintptr_t)fspr->fih;
Lee Leahy3dad4892015-05-05 11:14:02 -0700223}
224
Lee Leahyb5ad8272015-04-20 15:29:16 -0700225void *fsp_get_hob_list(void)
226{
227 struct fsp_runtime *fspr;
Lee Leahy3dad4892015-05-05 11:14:02 -0700228
Lee Leahyb5ad8272015-04-20 15:29:16 -0700229 fspr = cbmem_find(CBMEM_ID_FSP_RUNTIME);
230
231 if (fspr == NULL)
232 return NULL;
233
234 return (void *)(uintptr_t)fspr->hob_list;
235}
236
237void fsp_update_fih(FSP_INFO_HEADER *fih)
238{
239 struct fsp_runtime *fspr;
240
241 fspr = cbmem_find(CBMEM_ID_FSP_RUNTIME);
242
243 if (fspr == NULL)
244 die("Can't update FSP runtime information.\n");
245
246 fspr->fih = (uintptr_t)fih;
247}