• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <bootstate.h>
4 #include <cbmem.h>
5 #include <commonlib/helpers.h>
6 #include <console/console.h>
7 #include <console/streams.h>
8 #include <fsp/util.h>
9 #include <timestamp.h>
10 
11 /* Locate the FSP binary in the coreboot filesystem */
find_fsp(uintptr_t fsp_base_address)12 FSP_INFO_HEADER *find_fsp(uintptr_t fsp_base_address)
13 {
14 	union {
15 		EFI_FFS_FILE_HEADER *ffh;
16 		FSP_INFO_HEADER *fih;
17 		EFI_FIRMWARE_VOLUME_EXT_HEADER *fveh;
18 		EFI_FIRMWARE_VOLUME_HEADER *fvh;
19 		EFI_RAW_SECTION *rs;
20 		u32 u32;
21 	} fsp_ptr;
22 
23 	u64 *image_id;
24 
25 	/* Get the FSP binary base address in CBFS */
26 	fsp_ptr.u32 = fsp_base_address;
27 
28 	/* Check the FV signature, _FVH */
29 	if (fsp_ptr.fvh->Signature != 0x4856465F)
30 		return (FSP_INFO_HEADER *)ERROR_NO_FV_SIG;
31 
32 	/* Locate the file header which follows the FV header. */
33 	fsp_ptr.u32 += fsp_ptr.fvh->ExtHeaderOffset;
34 	fsp_ptr.u32 += fsp_ptr.fveh->ExtHeaderSize;
35 	fsp_ptr.u32 = ALIGN_UP(fsp_ptr.u32, 8);
36 
37 	/* Check the FFS GUID */
38 	if ((((u32 *)&fsp_ptr.ffh->Name)[0] != 0x912740BE)
39 		|| (((u32 *)&fsp_ptr.ffh->Name)[1] != 0x47342284)
40 		|| (((u32 *)&fsp_ptr.ffh->Name)[2] != 0xB08471B9)
41 		|| (((u32 *)&fsp_ptr.ffh->Name)[3] != 0x0C3F3527)) {
42 		return (FSP_INFO_HEADER *)ERROR_NO_FFS_GUID;
43 	}
44 
45 	/* Locate the Raw Section Header */
46 	fsp_ptr.u32 += sizeof(EFI_FFS_FILE_HEADER);
47 
48 	if (fsp_ptr.rs->Type != EFI_SECTION_RAW)
49 		return (FSP_INFO_HEADER *)ERROR_NO_INFO_HEADER;
50 
51 	/* Locate the FSP INFO Header which follows the Raw Header. */
52 	fsp_ptr.u32 += sizeof(EFI_RAW_SECTION);
53 
54 	/* Verify that the FSP base address.*/
55 	if (fsp_ptr.fih->ImageBase != fsp_base_address)
56 		return (FSP_INFO_HEADER *)ERROR_IMAGEBASE_MISMATCH;
57 
58 	/* Verify the FSP Signature */
59 	if (fsp_ptr.fih->Signature != FSP_SIG)
60 		return (FSP_INFO_HEADER *)ERROR_INFO_HEAD_SIG_MISMATCH;
61 
62 	/* Verify the FSP ID */
63 	image_id = (u64 *)&fsp_ptr.fih->ImageId[0];
64 	if (*image_id != FSP_IMAGE_ID)
65 		return (FSP_INFO_HEADER *)ERROR_FSP_SIG_MISMATCH;
66 
67 	/* Verify the FSP Revision */
68 	if (fsp_ptr.fih->ImageRevision > FSP_IMAGE_REV)
69 		return (FSP_INFO_HEADER *)ERROR_FSP_REV_MISMATCH;
70 
71 	return fsp_ptr.fih;
72 }
73 
print_fsp_info(FSP_INFO_HEADER * fsp_header)74 void print_fsp_info(FSP_INFO_HEADER *fsp_header)
75 {
76 	u8 *fsp_base;
77 
78 	fsp_base = (u8 *)fsp_header->ImageBase;
79 	printk(BIOS_SPEW, "FSP_INFO_HEADER: %p\n", fsp_header);
80 	printk(BIOS_INFO, "FSP Signature: %c%c%c%c%c%c%c%c\n",
81 			fsp_header->ImageId[0], fsp_header->ImageId[1],
82 			fsp_header->ImageId[2], fsp_header->ImageId[3],
83 			fsp_header->ImageId[4], fsp_header->ImageId[5],
84 			fsp_header->ImageId[6], fsp_header->ImageId[7]);
85 	printk(BIOS_INFO, "FSP Header Version: %d\n",
86 			fsp_header->HeaderRevision);
87 	printk(BIOS_INFO, "FSP Revision: %d.%d.%d.%d\n",
88 			(u8)((fsp_header->ImageRevision >> 24) & 0xff),
89 			(u8)((fsp_header->ImageRevision >> 16) & 0xff),
90 			(u8)((fsp_header->ImageRevision >> 8) & 0xff),
91 			(u8)(fsp_header->ImageRevision  & 0xff));
92 	if (CONFIG(DISPLAY_FSP_ENTRY_POINTS)) {
93 		printk(BIOS_SPEW, "FSP Entry Points:\n");
94 		printk(BIOS_SPEW, "    %p: Image Base\n", fsp_base);
95 		printk(BIOS_SPEW, "    %p: TempRamInit\n",
96 		       &fsp_base[fsp_header->TempRamInitEntryOffset]);
97 		printk(BIOS_SPEW, "    %p: FspInit\n",
98 		       &fsp_base[fsp_header->FspInitEntryOffset]);
99 		if (fsp_header->HeaderRevision >= FSP_HEADER_REVISION_2) {
100 			printk(BIOS_SPEW, "    %p: MemoryInit\n",
101 			       &fsp_base[fsp_header->FspMemoryInitEntryOffset]);
102 			printk(BIOS_SPEW, "    %p: TempRamExit\n",
103 			       &fsp_base[fsp_header->TempRamExitEntryOffset]);
104 			printk(BIOS_SPEW, "    %p: SiliconInit\n",
105 			       &fsp_base[fsp_header->FspSiliconInitEntryOffset]);
106 		}
107 		printk(BIOS_SPEW, "    %p: NotifyPhase\n",
108 		       &fsp_base[fsp_header->NotifyPhaseEntryOffset]);
109 		printk(BIOS_SPEW, "    %p: Image End\n",
110 		       &fsp_base[fsp_header->ImageSize]);
111 	}
112 }
113 
fsp_notify(u32 phase)114 void fsp_notify(u32 phase)
115 {
116 	FSP_NOTIFY_PHASE notify_phase_proc;
117 	NOTIFY_PHASE_PARAMS notify_phase_params;
118 	EFI_STATUS status;
119 	FSP_INFO_HEADER *fsp_header_ptr;
120 
121 	fsp_header_ptr = fsp_get_fih();
122 	if (fsp_header_ptr == NULL) {
123 		fsp_header_ptr = (void *)find_fsp(CONFIG_FSP_LOC);
124 		if ((u32)fsp_header_ptr < 0xff) {
125 			/* output something in case there is no serial */
126 			post_code(0x4F);
127 			die("Can't find the FSP!\n");
128 		}
129 	}
130 
131 	/* call FSP PEI to Notify PostPciEnumeration */
132 	notify_phase_proc = (FSP_NOTIFY_PHASE)(fsp_header_ptr->ImageBase +
133 		fsp_header_ptr->NotifyPhaseEntryOffset);
134 	notify_phase_params.Phase = phase;
135 
136 	if (phase == EnumInitPhaseReadyToBoot) {
137 		timestamp_add_now(TS_FSP_FINALIZE_START);
138 		post_code(POSTCODE_FSP_NOTIFY_BEFORE_FINALIZE);
139 	} else {
140 		timestamp_add_now(TS_FSP_ENUMERATE_START);
141 		post_code(POSTCODE_FSP_NOTIFY_BEFORE_ENUMERATE);
142 	}
143 
144 	status = notify_phase_proc(&notify_phase_params);
145 
146 	timestamp_add_now(phase == EnumInitPhaseReadyToBoot ?
147 		TS_FSP_FINALIZE_END : TS_FSP_ENUMERATE_END);
148 
149 	if (status != 0)
150 		printk(BIOS_ERR, "FSP API NotifyPhase failed for phase 0x%x with status: 0x%x\n",
151 			phase, status);
152 }
153 
fsp_notify_boot_state_callback(void * arg)154 static void fsp_notify_boot_state_callback(void *arg)
155 {
156 	u32 phase = (u32)arg;
157 
158 	printk(BIOS_SPEW, "Calling FspNotify(0x%08x)\n", phase);
159 	fsp_notify(phase);
160 }
161 
162 BOOT_STATE_INIT_ENTRY(BS_DEV_RESOURCES, BS_ON_EXIT,
163 	fsp_notify_boot_state_callback,
164 	(void *)EnumInitPhaseAfterPciEnumeration);
165 BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_LOAD, BS_ON_EXIT,
166 	fsp_notify_boot_state_callback,
167 	(void *)EnumInitPhaseReadyToBoot);
168 BOOT_STATE_INIT_ENTRY(BS_OS_RESUME, BS_ON_ENTRY,
169 	fsp_notify_boot_state_callback,
170 	(void *)EnumInitPhaseReadyToBoot);
171 
172 struct fsp_runtime {
173 	uint32_t fih;
174 	uint32_t hob_list;
175 } __packed;
176 
fsp_set_runtime(FSP_INFO_HEADER * fih,void * hob_list)177 void fsp_set_runtime(FSP_INFO_HEADER *fih, void *hob_list)
178 {
179 	struct fsp_runtime *fspr;
180 
181 	fspr = cbmem_add(CBMEM_ID_FSP_RUNTIME, sizeof(*fspr));
182 
183 	if (fspr == NULL)
184 		die("Can't save FSP runtime information.\n");
185 
186 	fspr->fih = (uintptr_t)fih;
187 	fspr->hob_list = (uintptr_t)hob_list;
188 }
189 
fsp_get_fih(void)190 FSP_INFO_HEADER *fsp_get_fih(void)
191 {
192 	struct fsp_runtime *fspr;
193 
194 	fspr = cbmem_find(CBMEM_ID_FSP_RUNTIME);
195 
196 	if (fspr == NULL)
197 		return NULL;
198 
199 	return (void *)(uintptr_t)fspr->fih;
200 }
201 
fsp_get_hob_list(void)202 void *fsp_get_hob_list(void)
203 {
204 	struct fsp_runtime *fspr;
205 
206 	fspr = cbmem_find(CBMEM_ID_FSP_RUNTIME);
207 
208 	if (fspr == NULL)
209 		return NULL;
210 
211 	return (void *)(uintptr_t)fspr->hob_list;
212 }
213 
fsp_update_fih(FSP_INFO_HEADER * fih)214 void fsp_update_fih(FSP_INFO_HEADER *fih)
215 {
216 	struct fsp_runtime *fspr;
217 
218 	fspr = cbmem_find(CBMEM_ID_FSP_RUNTIME);
219 
220 	if (fspr == NULL)
221 		die("Can't update FSP runtime information.\n");
222 
223 	fspr->fih = (uintptr_t)fih;
224 }
225 
fsp_display_upd_value(const char * name,uint32_t size,uint64_t old,uint64_t new)226 void fsp_display_upd_value(const char *name, uint32_t size, uint64_t old,
227 	uint64_t new)
228 {
229 	if (old == new) {
230 		switch (size) {
231 		case 1:
232 			printk(BIOS_SPEW, "  0x%02llx: %s\n", new, name);
233 			break;
234 
235 		case 2:
236 			printk(BIOS_SPEW, "  0x%04llx: %s\n", new, name);
237 			break;
238 
239 		case 4:
240 			printk(BIOS_SPEW, "  0x%08llx: %s\n", new, name);
241 			break;
242 
243 		case 8:
244 			printk(BIOS_SPEW, "  0x%016llx: %s\n", new, name);
245 			break;
246 		}
247 	} else {
248 		switch (size) {
249 		case 1:
250 			printk(BIOS_SPEW, "  0x%02llx --> 0x%02llx: %s\n", old,
251 				new, name);
252 			break;
253 
254 		case 2:
255 			printk(BIOS_SPEW, "  0x%04llx --> 0x%04llx: %s\n", old,
256 				new, name);
257 			break;
258 
259 		case 4:
260 			printk(BIOS_SPEW, "  0x%08llx --> 0x%08llx: %s\n", old,
261 				new, name);
262 			break;
263 
264 		case 8:
265 			printk(BIOS_SPEW, "  0x%016llx --> 0x%016llx: %s\n",
266 				old, new, name);
267 			break;
268 		}
269 	}
270 }
271