coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
fsp_util.c
Go to the documentation of this file.
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 */
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 
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 #endif
112 }
113 
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) {
139  } else {
142  }
143 
144  status = notify_phase_proc(&notify_phase_params);
145 
146  timestamp_add_now(phase == EnumInitPhaseReadyToBoot ?
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 
155 {
156  u32 phase = (u32)arg;
157 
158  printk(BIOS_SPEW, "Calling FspNotify(0x%08x)\n", phase);
159  fsp_notify(phase);
160 }
161 
164  (void *)EnumInitPhaseAfterPciEnumeration);
167  (void *)EnumInitPhaseReadyToBoot);
170  (void *)EnumInitPhaseReadyToBoot);
171 
172 struct fsp_runtime {
176 
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 
190 FSP_INFO_HEADER *fsp_get_fih(void)
191 {
192  struct fsp_runtime *fspr;
193 
195 
196  if (fspr == NULL)
197  return NULL;
198 
199  return (void *)(uintptr_t)fspr->fih;
200 }
201 
202 void *fsp_get_hob_list(void)
203 {
204  struct fsp_runtime *fspr;
205 
207 
208  if (fspr == NULL)
209  return NULL;
210 
211  return (void *)(uintptr_t)fspr->hob_list;
212 }
213 
214 void fsp_update_fih(FSP_INFO_HEADER *fih)
215 {
216  struct fsp_runtime *fspr;
217 
219 
220  if (fspr == NULL)
221  die("Can't update FSP runtime information.\n");
222 
223  fspr->fih = (uintptr_t)fih;
224 }
225 
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 }
const char * name
Definition: mmu.c:92
@ BS_PAYLOAD_LOAD
Definition: bootstate.h:88
@ BS_OS_RESUME
Definition: bootstate.h:86
@ BS_DEV_RESOURCES
Definition: bootstate.h:81
@ BS_ON_ENTRY
Definition: bootstate.h:95
@ BS_ON_EXIT
Definition: bootstate.h:96
#define ALIGN_UP(x, a)
Definition: helpers.h:17
void * cbmem_add(u32 id, u64 size)
Definition: imd_cbmem.c:144
void * cbmem_find(u32 id)
Definition: imd_cbmem.c:166
#define CBMEM_ID_FSP_RUNTIME
Definition: cbmem_id.h:26
#define printk(level,...)
Definition: stdlib.h:16
void __noreturn die(const char *fmt,...)
Definition: die.c:17
#define ERROR_IMAGEBASE_MISMATCH
Definition: util.h:70
#define ERROR_FSP_REV_MISMATCH
Definition: util.h:73
#define ERROR_NO_INFO_HEADER
Definition: util.h:69
#define ERROR_NO_FV_SIG
Definition: util.h:67
#define ERROR_INFO_HEAD_SIG_MISMATCH
Definition: util.h:71
#define ERROR_FSP_SIG_MISMATCH
Definition: util.h:72
#define ERROR_NO_FFS_GUID
Definition: util.h:68
void fsp_set_runtime(FSP_INFO_HEADER *fih, void *hob_list)
Definition: fsp_util.c:177
void print_fsp_info(FSP_INFO_HEADER *fsp_header)
Definition: fsp_util.c:74
static void fsp_notify_boot_state_callback(void *arg)
Definition: fsp_util.c:154
BOOT_STATE_INIT_ENTRY(BS_DEV_RESOURCES, BS_ON_EXIT, fsp_notify_boot_state_callback,(void *) EnumInitPhaseAfterPciEnumeration)
void fsp_notify(u32 phase)
Definition: fsp_util.c:114
void fsp_display_upd_value(const char *name, uint32_t size, uint64_t old, uint64_t new)
Definition: fsp_util.c:226
FSP_INFO_HEADER * find_fsp(uintptr_t fsp_base_address)
Definition: fsp_util.c:12
FSP_INFO_HEADER * fsp_get_fih(void)
Definition: fsp_util.c:190
struct fsp_runtime __packed
void fsp_update_fih(FSP_INFO_HEADER *fih)
Definition: fsp_util.c:214
void * fsp_get_hob_list(void)
Definition: fsp_util.c:202
struct bootblock_arg arg
Definition: decompressor.c:22
void timestamp_add_now(enum timestamp_id id)
Definition: timestamp.c:141
#define BIOS_INFO
BIOS_INFO - Expected events.
Definition: loglevel.h:113
#define BIOS_ERR
BIOS_ERR - System in incomplete state.
Definition: loglevel.h:72
#define BIOS_SPEW
BIOS_SPEW - Excessively verbose output.
Definition: loglevel.h:142
#define post_code(value)
Definition: post_code.h:12
#define POST_FSP_NOTIFY_BEFORE_FINALIZE
Before calling FSP Notify (ready to boot)
Definition: post_codes.h:260
#define POST_FSP_NOTIFY_BEFORE_ENUMERATE
Before calling FSP Notify (after PCI enumeration)
Definition: post_codes.h:253
#define NULL
Definition: stddef.h:19
uint64_t u64
Definition: stdint.h:54
unsigned int uint32_t
Definition: stdint.h:14
uint32_t u32
Definition: stdint.h:51
unsigned long uintptr_t
Definition: stdint.h:21
unsigned long long uint64_t
Definition: stdint.h:17
uint8_t u8
Definition: stdint.h:45
uint32_t hob_list
Definition: fsp_util.c:174
uint32_t fih
Definition: fsp_util.c:173
@ TS_FSP_FINALIZE_END
@ TS_FSP_FINALIZE_START
@ TS_FSP_ENUMERATE_END
@ TS_FSP_ENUMERATE_START