soc/intel/alderlake: Add ADL-P 4+4 with 28W TDP
[coreboot.git] / src / drivers / intel / fsp2_0 / util.c
blob7fa2af4722fd254f1691f7b2a4815f2cabb392da
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
3 #include <boot/coreboot_tables.h>
4 #include <device/mmio.h>
5 #include <cbfs.h>
6 #include <cf9_reset.h>
7 #include <commonlib/bsd/compression.h>
8 #include <commonlib/fsp.h>
9 #include <console/console.h>
10 #include <fsp/util.h>
11 #include <string.h>
12 #include <types.h>
13 #include <assert.h>
15 static uint32_t fsp_hdr_get_expected_min_length(void)
17 if (CONFIG(PLATFORM_USES_FSP2_3))
18 return 80;
19 else if (CONFIG(PLATFORM_USES_FSP2_2))
20 return 76;
21 else if (CONFIG(PLATFORM_USES_FSP2_1))
22 return 72;
23 else if (CONFIG(PLATFORM_USES_FSP2_0))
24 return 72;
25 else
26 return dead_code_t(uint32_t);
29 static bool looks_like_fsp_header(struct fsp_header *hdr)
31 if (memcmp(&hdr->signature, FSP_HDR_SIGNATURE, 4)) {
32 printk(BIOS_ALERT, "Did not find a valid FSP signature\n");
33 return false;
36 /* It is possible to build FSP with any version of edk2 which could have introduced new
37 fields in FSP_INFO_HEADER. The new fields will be ignored based on the reported FSP
38 version. This check ensures that the reported header length is at least what the
39 reported FSP version requires so that we do not access any out-of-bound bytes. */
40 if (hdr->header_length < fsp_hdr_get_expected_min_length()) {
41 printk(BIOS_ALERT, "FSP header has invalid length: %d\n", hdr->header_length);
42 return false;
45 return true;
48 enum cb_err fsp_identify(struct fsp_header *hdr, const void *fsp_blob)
50 memcpy(hdr, fsp_blob, sizeof(struct fsp_header));
51 if (!looks_like_fsp_header(hdr))
52 return CB_ERR;
54 return CB_SUCCESS;
57 enum cb_err fsp_validate_component(struct fsp_header *hdr, void *fsp_file, size_t file_size)
59 void *raw_hdr = fsp_file + FSP_HDR_OFFSET;
61 if (file_size < FSP_HDR_OFFSET + fsp_hdr_get_expected_min_length()) {
62 printk(BIOS_CRIT, "FSP blob too small.\n");
63 return CB_ERR;
66 if (fsp_identify(hdr, raw_hdr) != CB_SUCCESS) {
67 printk(BIOS_CRIT, "No valid FSP header\n");
68 return CB_ERR;
71 if (CONFIG(DISPLAY_FSP_HEADER))
72 fsp_print_header_info(hdr);
74 /* Check if size specified in the header matches the cbfs file size */
75 if (file_size < hdr->image_size) {
76 printk(BIOS_CRIT, "Component size bigger than cbfs file.\n");
77 return CB_ERR;
80 if (ENV_RAMINIT)
81 soc_validate_fspm_header(hdr);
83 return CB_SUCCESS;
86 static bool fsp_reset_requested(uint32_t status)
88 return (status >= FSP_STATUS_RESET_REQUIRED_COLD &&
89 status <= FSP_STATUS_RESET_REQUIRED_8);
92 void fsp_handle_reset(uint32_t status)
94 if (!fsp_reset_requested(status))
95 return;
97 printk(BIOS_SPEW, "FSP: handling reset type %x\n", status);
99 switch (status) {
100 case FSP_STATUS_RESET_REQUIRED_COLD:
101 full_reset();
102 break;
103 case FSP_STATUS_RESET_REQUIRED_WARM:
104 system_reset();
105 break;
106 case FSP_STATUS_RESET_REQUIRED_3:
107 case FSP_STATUS_RESET_REQUIRED_4:
108 case FSP_STATUS_RESET_REQUIRED_5:
109 case FSP_STATUS_RESET_REQUIRED_6:
110 case FSP_STATUS_RESET_REQUIRED_7:
111 case FSP_STATUS_RESET_REQUIRED_8:
112 chipset_handle_reset(status);
113 break;
114 default:
115 break;
119 static inline bool fspm_env(void)
121 if (ENV_RAMINIT)
122 return true;
123 return false;
126 static inline bool fspm_xip(void)
128 /* FSP-M is assumed to be loaded in romstage. */
129 if (fspm_env() && CONFIG(FSP_M_XIP))
130 return true;
131 return false;
134 /* Load the FSP component described by fsp_load_descriptor from cbfs. The FSP
135 * header object will be validated and filled in on successful load. */
136 enum cb_err fsp_load_component(struct fsp_load_descriptor *fspld, struct fsp_header *hdr)
138 size_t output_size;
139 void *dest;
140 struct prog *fsp_prog = &fspld->fsp_prog;
142 dest = cbfs_alloc(prog_name(fsp_prog), fspld->alloc, fspld, &output_size);
143 if (!dest)
144 return CB_ERR;
146 /* Don't allow FSP-M relocation when XIP. */
147 if (!fspm_xip() && fsp_component_relocate((uintptr_t)dest, dest, output_size) < 0) {
148 printk(BIOS_ERR, "Unable to relocate FSP component!\n");
149 return CB_ERR;
152 prog_set_area(fsp_prog, dest, output_size);
154 if (fsp_validate_component(hdr, dest, output_size) != CB_SUCCESS) {
155 printk(BIOS_ERR, "Invalid FSP header after load!\n");
156 return CB_ERR;
159 /* Signal that FSP component has been loaded. */
160 prog_segment_loaded(hdr->image_base, hdr->image_size, SEG_FINAL);
162 return CB_SUCCESS;
165 /* Only call this function when FSP header has been read and validated */
166 void fsp_get_version(char *buf)
168 struct fsp_header *hdr = &fsps_hdr;
169 union fsp_revision revision;
171 revision.val = hdr->image_revision;
172 snprintf(buf, FSP_VER_LEN, "%u.%u-%u.%u.%u.%u", (hdr->spec_version >> 4),
173 hdr->spec_version & 0xf, revision.rev.major,
174 revision.rev.minor, revision.rev.revision, revision.rev.bld_num);
177 /* Check if the signature in the UPD header matches the expected one. If it doesn't match, the
178 FSP binaries in CBFS are for a different platform than the platform code trying to use it
179 in which case the function calls die(). */
180 void fsp_verify_upd_header_signature(uint64_t upd_signature, uint64_t expected_signature)
182 if (upd_signature != expected_signature) {
183 /* The UPD signatures are non-zero-terminated ASCII stored as a little endian
184 uint64_t, so this needs some casts. */
185 die_with_post_code(POST_INVALID_VENDOR_BINARY,
186 "Invalid UPD signature! FSP provided \"%.8s\", expected was \"%.8s\".\n",
187 (char *)&upd_signature,
188 (char *)&expected_signature);
192 /* Add FSP version to coreboot table LB_TAG_PLATFORM_BLOB_VERSION */
193 void lb_string_platform_blob_version(struct lb_header *header)
195 struct lb_string *rec;
196 size_t len;
197 char fsp_version[FSP_VER_LEN] = {0};
199 fsp_get_version(fsp_version);
200 rec = (struct lb_string *)lb_new_record(header);
201 rec->tag = LB_TAG_PLATFORM_BLOB_VERSION;
202 len = strlen(fsp_version);
203 rec->size = ALIGN_UP(sizeof(*rec) + len + 1, 8);
204 memcpy(rec->string, fsp_version, len+1);
207 __weak void soc_validate_fspm_header(const struct fsp_header *hdr)