1 /* SPDX-License-Identifier: GPL-2.0-or-later */
3 #include <device/mmio.h>
5 #include <commonlib/helpers.h>
6 #include <console/console.h>
12 #define HOB_HEADER_LEN 8
14 /* GUIDs in little-endian, so they can be used with memcmp() */
15 const uint8_t fsp_bootloader_tolum_guid
[16] = {
16 0x56, 0x4f, 0xff, 0x73, 0x8e, 0xaa, 0x51, 0x44,
17 0xb3, 0x16, 0x36, 0x35, 0x36, 0x67, 0xad, 0x44,
20 const uint8_t fsp_reserved_memory_guid
[16] = {
21 0x59, 0x97, 0xa7, 0x69, 0x73, 0x13, 0x67, 0x43,
22 0xa6, 0xc4, 0xc7, 0xf5, 0x9e, 0xfd, 0x98, 0x6e,
25 const uint8_t fsp_nv_storage_guid_2
[16] = {
26 0x8f, 0x78, 0x66, 0x48, 0xa8, 0x6b, 0xd8, 0x47,
27 0x83, 0x6, 0xac, 0xf7, 0x7f, 0x55, 0x10, 0x46
30 const uint8_t fsp_nv_storage_guid
[16] = {
31 0x02, 0xcf, 0x1a, 0x72, 0x77, 0x4d, 0x2a, 0x4c,
32 0xb3, 0xdc, 0x27, 0x0b, 0x7b, 0xa9, 0xe4, 0xb0
35 const uint8_t fsp_error_info_guid
[16] = {
36 0x88, 0x6a, 0x1e, 0x61, 0xb7, 0xad, 0x01, 0x43,
37 0x93, 0xff, 0xe4, 0x73, 0x04, 0xb4, 0x3d, 0xa6
40 static const uint8_t uuid_fv_info
[16] = {
41 0x2e, 0x72, 0x8e, 0x79, 0xb2, 0x15, 0x13, 0x4e,
42 0x8a, 0xe9, 0x6b, 0xa3, 0x0f, 0xf7, 0xf1, 0x67
46 * Utilities for walking HOBs
49 bool fsp_guid_compare(const uint8_t guid1
[16], const uint8_t guid2
[16])
51 return !memcmp(guid1
, guid2
, 16);
54 const struct hob_header
*fsp_next_hob(const struct hob_header
*parent
)
57 const struct hob_header
*hob
;
61 hob_walker
.hob
= parent
;
62 hob_walker
.addr
+= parent
->length
;
63 return hob_walker
.hob
;
66 static const void *hob_header_to_struct(const struct hob_header
*hob
)
69 const struct hob_header
*hob_hdr
;
70 const void *hob_descr
;
74 hob_walker
.hob_hdr
= hob
;
75 hob_walker
.addr
+= HOB_HEADER_LEN
;
76 return hob_walker
.hob_descr
;
79 static const void *hob_header_to_extension_hob(const struct hob_header
*hob
)
82 const struct hob_header
*hob_hdr
;
83 const void *hob_descr
;
87 hob_walker
.hob_hdr
= hob
;
88 hob_walker
.addr
+= HOB_HEADER_LEN
+ 16; /* header and 16-byte GUID */
89 return hob_walker
.hob_descr
;
93 struct hob_resource
*fsp_hob_header_to_resource(const struct hob_header
*hob
)
95 return hob_header_to_struct(hob
);
99 * Utilities for locating and identifying HOBs
102 static void *fsp_hob_list_ptr
;
104 static void save_hob_list(int is_recovery
)
107 const void *hob_list
;
108 cbmem_loc
= cbmem_add(CBMEM_ID_FSP_RUNTIME
, sizeof(*cbmem_loc
));
109 if (cbmem_loc
== NULL
)
110 die("Error: Could not add cbmem area for HOB list.\n");
111 hob_list
= fsp_get_hob_list();
113 die("Error: Could not locate HOB list pointer.\n");
114 *cbmem_loc
= (uintptr_t)hob_list
;
117 CBMEM_CREATION_HOOK(save_hob_list
);
119 const void *fsp_get_hob_list(void)
124 return fsp_hob_list_ptr
;
125 list_loc
= cbmem_find(CBMEM_ID_FSP_RUNTIME
);
126 return (list_loc
) ? (void *)(uintptr_t)(*list_loc
) : NULL
;
129 void *fsp_get_hob_list_ptr(void)
131 return &fsp_hob_list_ptr
;
134 enum cb_err
fsp_hob_iterator_init(const struct hob_header
**hob_iterator
)
136 *hob_iterator
= fsp_get_hob_list();
137 return *hob_iterator
? CB_SUCCESS
: CB_ERR
;
140 static enum cb_err
fsp_hob_iterator_get_next(const struct hob_header
**hob_iterator
,
142 const struct hob_header
**hob
)
144 const struct hob_header
*current_hob
;
145 while ((*hob_iterator
)->type
!= HOB_TYPE_END_OF_HOB_LIST
) {
146 current_hob
= *hob_iterator
;
147 *hob_iterator
= fsp_next_hob(*hob_iterator
);
148 if (current_hob
->type
== hob_type
) {
156 enum cb_err
fsp_hob_iterator_get_next_resource(const struct hob_header
**hob_iterator
,
157 const struct hob_resource
**res
)
159 const struct hob_header
*hob
;
160 while (fsp_hob_iterator_get_next(hob_iterator
, HOB_TYPE_RESOURCE_DESCRIPTOR
, &hob
) == CB_SUCCESS
) {
161 *res
= fsp_hob_header_to_resource(hob
);
167 enum cb_err
fsp_hob_iterator_get_next_guid_resource(const struct hob_header
**hob_iterator
,
168 const uint8_t guid
[16],
169 const struct hob_resource
**res
)
171 const struct hob_resource
*res_hob
;
172 while (fsp_hob_iterator_get_next_resource(hob_iterator
, &res_hob
) == CB_SUCCESS
) {
173 if (fsp_guid_compare(res_hob
->owner_guid
, guid
)) {
181 enum cb_err
fsp_hob_iterator_get_next_guid_extension(const struct hob_header
**hob_iterator
,
182 const uint8_t guid
[16],
183 const void **data
, size_t *size
)
185 const struct hob_header
*hob
;
186 const uint8_t *guid_hob
;
187 while (fsp_hob_iterator_get_next(hob_iterator
, HOB_TYPE_GUID_EXTENSION
, &hob
) == CB_SUCCESS
) {
188 guid_hob
= hob_header_to_struct(hob
);
189 if (fsp_guid_compare(guid_hob
, guid
)) {
190 *size
= hob
->length
- (HOB_HEADER_LEN
+ 16);
191 *data
= hob_header_to_extension_hob(hob
);
198 void fsp_print_guid(int level
, const void *base
)
203 const uint8_t *id
= base
;
204 big
= read32(id
+ 0);
205 mid
[0] = read16(id
+ 4);
206 mid
[1] = read16(id
+ 6);
208 printk(level
, "%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x\n",
210 id
[8], id
[9], id
[10], id
[11], id
[12], id
[13], id
[14], id
[15]);
213 enum cb_err
fsp_find_range_hob(struct range_entry
*re
, const uint8_t guid
[16])
215 const struct hob_header
*hob_iterator
;
216 const struct hob_resource
*fsp_mem
;
218 if (fsp_hob_iterator_init(&hob_iterator
) != CB_SUCCESS
)
221 range_entry_init(re
, 0, 0, 0);
223 if (fsp_hob_iterator_get_next_guid_resource(&hob_iterator
, guid
, &fsp_mem
) != CB_SUCCESS
) {
224 fsp_print_guid(BIOS_SPEW
, guid
);
225 printk(BIOS_SPEW
, " not found!\n");
229 range_entry_init(re
, fsp_mem
->addr
, fsp_mem
->addr
+ fsp_mem
->length
, 0);
233 void fsp_find_reserved_memory(struct range_entry
*re
)
235 if (fsp_find_range_hob(re
, fsp_reserved_memory_guid
) != CB_SUCCESS
)
236 die("9.1: FSP_RESERVED_MEMORY_RESOURCE_HOB missing!\n");
239 const void *fsp_find_extension_hob_by_guid(const uint8_t *guid
, size_t *size
)
241 const struct hob_header
*hob_iterator
;
242 const void *hob_guid
;
244 if (fsp_hob_iterator_init(&hob_iterator
) != CB_SUCCESS
)
247 if (fsp_hob_iterator_get_next_guid_extension(&hob_iterator
, guid
, &hob_guid
, size
) == CB_SUCCESS
)
253 const void *fsp_find_resource_hob_by_guid(const uint8_t *guid
)
255 const struct hob_header
*hob_iterator
;
256 const struct hob_resource
*res_hob
;
258 if (fsp_hob_iterator_init(&hob_iterator
) != CB_SUCCESS
)
261 if (fsp_hob_iterator_get_next_guid_resource(&hob_iterator
, guid
, &res_hob
) == CB_SUCCESS
)
267 static void display_fsp_version_info_hob(const void *hob
)
269 #if CONFIG(DISPLAY_FSP_VERSION_INFO) || CONFIG(DISPLAY_FSP_VERSION_INFO_2)
271 int index
, cnt
, tcount
;
274 #if CONFIG(DISPLAY_FSP_VERSION_INFO)
275 const FIRMWARE_VERSION_INFO
*fvi
;
276 const FIRMWARE_VERSION_INFO_HOB
*fvih
= (FIRMWARE_VERSION_INFO_HOB
*)hob
;
278 fvi
= (void *)&fvih
[1];
279 str_ptr
= (char *)((uintptr_t)fvi
+ (fvih
->Count
* sizeof(FIRMWARE_VERSION_INFO
)));
280 tcount
= fvih
->Count
;
281 #elif CONFIG(DISPLAY_FSP_VERSION_INFO_2)
283 uint8_t *hobstart
= (uint8_t *)hob
;
284 hobstart
+= sizeof(EFI_HOB_GUID_TYPE
);
286 const SMBIOS_TABLE_TYPE_OEM_INTEL_FVI
*stfvi
=
287 (SMBIOS_TABLE_TYPE_OEM_INTEL_FVI
*)hobstart
;
288 const INTEL_FIRMWARE_VERSION_INFO
*fvi
;
290 str_ptr
= ((char *)&(stfvi
->Fvi
[0])) +
291 (stfvi
->Count
* sizeof(INTEL_FIRMWARE_VERSION_INFO
));
292 tcount
= stfvi
->Count
;
293 fvi
= &stfvi
->Fvi
[0];
296 for (index
= 0; index
< tcount
; index
++) {
297 cnt
= strlen(str_ptr
);
299 #if CONFIG(DISPLAY_FSP_VERSION_INFO)
300 vs
= fvi
[index
].VersionStringIndex
;
301 #elif CONFIG(DISPLAY_FSP_VERSION_INFO_2)
302 vs
= fvi
[index
].VersionString
;
304 /* Don't show ingredient name and version if its all 0xFF */
305 if (fvi
[index
].Version
.MajorVersion
== 0xFF &&
306 fvi
[index
].Version
.MinorVersion
== 0xFF &&
307 fvi
[index
].Version
.Revision
== 0xFF &&
308 fvi
[index
].Version
.BuildNumber
== 0xFF &&
310 str_ptr
= (char *)((uintptr_t)str_ptr
+ cnt
+ sizeof(uint8_t));
314 * Firmware Version String consist of 2 pieces of information
315 * 1. Component Name: string type data holds FW type name.
316 * 2. Version Information : Either a string type data or
317 * numeric field holds FW version information.
319 printk(BIOS_DEBUG
, "%s = ", str_ptr
);
322 printk(BIOS_DEBUG
, "%x.%x.%x.%x\n",
323 fvi
[index
].Version
.MajorVersion
,
324 fvi
[index
].Version
.MinorVersion
,
325 fvi
[index
].Version
.Revision
,
326 fvi
[index
].Version
.BuildNumber
);
328 str_ptr
= (char *)((uintptr_t)str_ptr
+ cnt
+ sizeof(uint8_t));
329 cnt
= strlen(str_ptr
);
330 printk(BIOS_DEBUG
, "%s\n", str_ptr
);
332 str_ptr
= (char *)((uintptr_t)str_ptr
+ cnt
+ sizeof(uint8_t));
337 void fsp_display_fvi_version_hob(void)
339 const uint8_t *hob_uuid
;
340 const struct hob_header
*hob
= fsp_get_hob_list();
345 printk(BIOS_DEBUG
, "Display FSP Version Info HOB\n");
346 for (; hob
->type
!= HOB_TYPE_END_OF_HOB_LIST
; hob
= fsp_next_hob(hob
)) {
347 if (hob
->type
!= HOB_TYPE_GUID_EXTENSION
)
350 hob_uuid
= hob_header_to_struct(hob
);
352 if (fsp_guid_compare(hob_uuid
, uuid_fv_info
)) {
353 display_fsp_version_info_hob(hob
);
358 const void *fsp_find_nv_storage_data(size_t *size
)
360 if (CONFIG(PLATFORM_USES_FSP2_3
)) {
361 const struct fsp_nvs_hob2_data_region_header
*hob
;
363 hob
= (const struct fsp_nvs_hob2_data_region_header
*)
364 fsp_find_extension_hob_by_guid(fsp_nv_storage_guid_2
, size
);
366 *size
= hob
->nvs_data_length
;
367 return (void *)(uintptr_t)hob
->nvs_data_ptr
;
370 return fsp_find_extension_hob_by_guid(fsp_nv_storage_guid
, size
);
373 void fsp_find_bootloader_tolum(struct range_entry
*re
)
375 if (fsp_find_range_hob(re
, fsp_bootloader_tolum_guid
) != CB_SUCCESS
)
376 die("9.3: FSP_BOOTLOADER_TOLUM_HOB missing!\n");
379 bool fsp_display_error_info(void)
381 if (!CONFIG(ENABLE_FSP_ERROR_INFO
))
384 const struct hob_header
*hob
;
387 hob
= (const struct hob_header
*)fsp_find_extension_hob_by_guid(
388 fsp_error_info_guid
, &size
);
390 display_fsp_error_info_hob(hob
);