blob: f912d9acab85a9638a3943ad6ddf776a5c6c4b43 [file] [log] [blame]
Patrick Georgiac959032020-05-05 22:49:26 +02001/* SPDX-License-Identifier: GPL-2.0-or-later */
Andrey Petrov97389702016-02-25 14:15:37 -08002
Johnny Linb8899ef2020-05-28 14:04:58 +08003#include <boot/coreboot_tables.h>
Kyösti Mälkki13f66502019-03-03 08:01:05 +02004#include <device/mmio.h>
Aaron Durbina85febc2020-05-15 15:09:10 -06005#include <cbfs.h>
Patrick Rudolphf677d172018-10-01 19:17:11 +02006#include <cf9_reset.h>
Aaron Durbina85febc2020-05-15 15:09:10 -06007#include <commonlib/bsd/compression.h>
8#include <commonlib/fsp.h>
Andrey Petrov97389702016-02-25 14:15:37 -08009#include <console/console.h>
10#include <fsp/util.h>
Andrey Petrov97389702016-02-25 14:15:37 -080011#include <string.h>
Elyes HAOUASbd1683d2019-05-15 21:05:37 +020012#include <types.h>
Nikolai Vyssotski3c3d2cf2021-07-09 18:36:27 -050013#include <assert.h>
14
15static uint32_t fsp_hdr_get_expected_min_length(void)
16{
Anil Kumar57309d32021-11-11 18:56:21 -080017 if (CONFIG(PLATFORM_USES_FSP2_3))
18 return 80;
19 else if (CONFIG(PLATFORM_USES_FSP2_2))
Nikolai Vyssotski3c3d2cf2021-07-09 18:36:27 -050020 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);
27}
Andrey Petrov97389702016-02-25 14:15:37 -080028
Julian Schroeder8a576f62021-11-02 16:32:28 -050029static bool looks_like_fsp_header(struct fsp_header *hdr)
Andrey Petrov97389702016-02-25 14:15:37 -080030{
Julian Schroeder8a576f62021-11-02 16:32:28 -050031 if (memcmp(&hdr->signature, FSP_HDR_SIGNATURE, 4)) {
Andrey Petrov97389702016-02-25 14:15:37 -080032 printk(BIOS_ALERT, "Did not find a valid FSP signature\n");
33 return false;
34 }
35
Sean Rhodes38c99b52022-07-13 10:11:44 +010036 /* It is possible to build FSP with any version of edk2 which could have introduced new
Nikolai Vyssotski3c3d2cf2021-07-09 18:36:27 -050037 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. */
Julian Schroeder8a576f62021-11-02 16:32:28 -050040 if (hdr->header_length < fsp_hdr_get_expected_min_length()) {
41 printk(BIOS_ALERT, "FSP header has invalid length: %d\n", hdr->header_length);
Andrey Petrov97389702016-02-25 14:15:37 -080042 return false;
43 }
44
45 return true;
46}
47
48enum cb_err fsp_identify(struct fsp_header *hdr, const void *fsp_blob)
49{
Julian Schroeder8a576f62021-11-02 16:32:28 -050050 memcpy(hdr, fsp_blob, sizeof(struct fsp_header));
51 if (!looks_like_fsp_header(hdr))
Andrey Petrov97389702016-02-25 14:15:37 -080052 return CB_ERR;
53
Andrey Petrov97389702016-02-25 14:15:37 -080054 return CB_SUCCESS;
55}
56
Julius Werner43c9d702021-04-12 17:00:16 -070057enum cb_err fsp_validate_component(struct fsp_header *hdr, void *fsp_file, size_t file_size)
Aaron Durbina413e5e2016-07-17 23:06:03 -050058{
Julius Werner43c9d702021-04-12 17:00:16 -070059 void *raw_hdr = fsp_file + FSP_HDR_OFFSET;
Aaron Durbina413e5e2016-07-17 23:06:03 -050060
Nikolai Vyssotski3c3d2cf2021-07-09 18:36:27 -050061 if (file_size < FSP_HDR_OFFSET + fsp_hdr_get_expected_min_length()) {
Julius Werner43c9d702021-04-12 17:00:16 -070062 printk(BIOS_CRIT, "FSP blob too small.\n");
Aaron Durbina413e5e2016-07-17 23:06:03 -050063 return CB_ERR;
64 }
65
Julius Werner43c9d702021-04-12 17:00:16 -070066 if (fsp_identify(hdr, raw_hdr) != CB_SUCCESS) {
Lee Leahyb20d4ba2016-07-31 16:49:28 -070067 printk(BIOS_CRIT, "No valid FSP header\n");
Aaron Durbina413e5e2016-07-17 23:06:03 -050068 return CB_ERR;
69 }
70
Julius Wernercd49cce2019-03-05 16:53:33 -080071 if (CONFIG(DISPLAY_FSP_HEADER))
Lee Leahy37b5ef22016-07-31 14:15:49 -070072 fsp_print_header_info(hdr);
Aaron Durbina413e5e2016-07-17 23:06:03 -050073
74 /* Check if size specified in the header matches the cbfs file size */
Julius Werner43c9d702021-04-12 17:00:16 -070075 if (file_size < hdr->image_size) {
Lee Leahyb20d4ba2016-07-31 16:49:28 -070076 printk(BIOS_CRIT, "Component size bigger than cbfs file.\n");
Aaron Durbina413e5e2016-07-17 23:06:03 -050077 return CB_ERR;
78 }
79
Kyösti Mälkki11cac782022-04-07 07:16:48 +030080 if (ENV_RAMINIT)
Felix Held42df9af2021-08-24 19:26:56 +020081 soc_validate_fspm_header(hdr);
Johnny Lin5b47d772020-11-13 17:21:25 +080082
Aaron Durbina413e5e2016-07-17 23:06:03 -050083 return CB_SUCCESS;
84}
85
Brandon Breitensteinc31ba0e2016-07-27 17:34:45 -070086static bool fsp_reset_requested(uint32_t status)
Andrey Petrov3a94a3b2016-07-18 00:15:41 -070087{
88 return (status >= FSP_STATUS_RESET_REQUIRED_COLD &&
89 status <= FSP_STATUS_RESET_REQUIRED_8);
90}
91
Brandon Breitensteinc31ba0e2016-07-27 17:34:45 -070092void fsp_handle_reset(uint32_t status)
Andrey Petrov901e43c2016-06-22 19:22:30 -070093{
Andrey Petrov3a94a3b2016-07-18 00:15:41 -070094 if (!fsp_reset_requested(status))
95 return;
96
Lee Leahyb20d4ba2016-07-31 16:49:28 -070097 printk(BIOS_SPEW, "FSP: handling reset type %x\n", status);
Andrey Petrov3a94a3b2016-07-18 00:15:41 -070098
Lee Leahyb2b97a52017-03-10 08:40:18 -080099 switch (status) {
Andrey Petrov901e43c2016-06-22 19:22:30 -0700100 case FSP_STATUS_RESET_REQUIRED_COLD:
Patrick Rudolphf677d172018-10-01 19:17:11 +0200101 full_reset();
Andrey Petrov901e43c2016-06-22 19:22:30 -0700102 break;
103 case FSP_STATUS_RESET_REQUIRED_WARM:
Patrick Rudolphf677d172018-10-01 19:17:11 +0200104 system_reset();
Andrey Petrov901e43c2016-06-22 19:22:30 -0700105 break;
Andrey Petrov3a94a3b2016-07-18 00:15:41 -0700106 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);
Andrey Petrov901e43c2016-06-22 19:22:30 -0700113 break;
114 default:
115 break;
116 }
117}
Aaron Durbina85febc2020-05-15 15:09:10 -0600118
Aaron Durbinecbfa992020-05-15 17:01:58 -0600119static inline bool fspm_env(void)
120{
Kyösti Mälkki11cac782022-04-07 07:16:48 +0300121 if (ENV_RAMINIT)
Aaron Durbinecbfa992020-05-15 17:01:58 -0600122 return true;
123 return false;
124}
125
126static inline bool fspm_xip(void)
127{
128 /* FSP-M is assumed to be loaded in romstage. */
129 if (fspm_env() && CONFIG(FSP_M_XIP))
130 return true;
131 return false;
132}
133
Aaron Durbina85febc2020-05-15 15:09:10 -0600134/* 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. */
136enum cb_err fsp_load_component(struct fsp_load_descriptor *fspld, struct fsp_header *hdr)
137{
Aaron Durbina85febc2020-05-15 15:09:10 -0600138 size_t output_size;
139 void *dest;
Aaron Durbina85febc2020-05-15 15:09:10 -0600140 struct prog *fsp_prog = &fspld->fsp_prog;
141
Julius Werner8205ce62021-03-10 17:25:01 -0800142 dest = cbfs_alloc(prog_name(fsp_prog), fspld->alloc, fspld, &output_size);
143 if (!dest)
Aaron Durbina85febc2020-05-15 15:09:10 -0600144 return CB_ERR;
145
Raul E Rangel4911dc72021-11-05 10:29:24 -0600146 /* Don't allow FSP-M relocation when XIP. */
147 if (!fspm_xip() && fsp_component_relocate((uintptr_t)dest, dest, output_size) < 0) {
Julius Werner8205ce62021-03-10 17:25:01 -0800148 printk(BIOS_ERR, "Unable to relocate FSP component!\n");
Aaron Durbina85febc2020-05-15 15:09:10 -0600149 return CB_ERR;
Julius Werner8205ce62021-03-10 17:25:01 -0800150 }
Aaron Durbina85febc2020-05-15 15:09:10 -0600151
152 prog_set_area(fsp_prog, dest, output_size);
153
Julius Werner43c9d702021-04-12 17:00:16 -0700154 if (fsp_validate_component(hdr, dest, output_size) != CB_SUCCESS) {
Aaron Durbina85febc2020-05-15 15:09:10 -0600155 printk(BIOS_ERR, "Invalid FSP header after load!\n");
156 return CB_ERR;
157 }
158
159 /* Signal that FSP component has been loaded. */
160 prog_segment_loaded(hdr->image_base, hdr->image_size, SEG_FINAL);
161
162 return CB_SUCCESS;
163}
Johnny Linb8899ef2020-05-28 14:04:58 +0800164
165/* Only call this function when FSP header has been read and validated */
166void fsp_get_version(char *buf)
167{
168 struct fsp_header *hdr = &fsps_hdr;
Johnny Lin5b47d772020-11-13 17:21:25 +0800169 union fsp_revision revision;
Johnny Linb8899ef2020-05-28 14:04:58 +0800170
Julian Schroeder8a576f62021-11-02 16:32:28 -0500171 revision.val = hdr->image_revision;
Johnny Linb8899ef2020-05-28 14:04:58 +0800172 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);
175}
176
Felix Held88995982021-01-28 22:43:52 +0100177/* 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(). */
180void fsp_verify_upd_header_signature(uint64_t upd_signature, uint64_t expected_signature)
181{
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. */
lilacious40cb3fe2023-06-21 23:24:14 +0200185 die_with_post_code(POSTCODE_INVALID_VENDOR_BINARY,
Fred Reitbergerf9eeded2023-02-08 16:05:08 -0500186 "Invalid UPD signature! FSP provided \"%.8s\", expected was \"%.8s\".\n",
Felix Held88995982021-01-28 22:43:52 +0100187 (char *)&upd_signature,
188 (char *)&expected_signature);
189 }
190}
191
Johnny Linb8899ef2020-05-28 14:04:58 +0800192/* Add FSP version to coreboot table LB_TAG_PLATFORM_BLOB_VERSION */
193void lb_string_platform_blob_version(struct lb_header *header)
194{
195 struct lb_string *rec;
196 size_t len;
197 char fsp_version[FSP_VER_LEN] = {0};
198
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);
205}
Johnny Lin5b47d772020-11-13 17:21:25 +0800206
Felix Held42df9af2021-08-24 19:26:56 +0200207__weak void soc_validate_fspm_header(const struct fsp_header *hdr)
Johnny Lin5b47d772020-11-13 17:21:25 +0800208{
Johnny Lin5b47d772020-11-13 17:21:25 +0800209}