blob: ff79fc77159dad3e2b845a9822ce9807f49c35a4 [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
29static bool looks_like_fsp_header(const uint8_t *raw_hdr)
30{
Nikolai Vyssotski3c3d2cf2021-07-09 18:36:27 -050031 uint32_t fsp_header_length = read32(raw_hdr + 4);
32
Andrey Petrov97389702016-02-25 14:15:37 -080033 if (memcmp(raw_hdr, FSP_HDR_SIGNATURE, 4)) {
34 printk(BIOS_ALERT, "Did not find a valid FSP signature\n");
35 return false;
36 }
37
Nikolai Vyssotski3c3d2cf2021-07-09 18:36:27 -050038 /* It is possible to build FSP with any version of EDK2 which could have introduced new
39 fields in FSP_INFO_HEADER. The new fields will be ignored based on the reported FSP
40 version. This check ensures that the reported header length is at least what the
41 reported FSP version requires so that we do not access any out-of-bound bytes. */
42 if (fsp_header_length < fsp_hdr_get_expected_min_length()) {
43 printk(BIOS_ALERT, "FSP header has invalid length: %d\n", fsp_header_length);
Andrey Petrov97389702016-02-25 14:15:37 -080044 return false;
45 }
46
47 return true;
48}
49
50enum cb_err fsp_identify(struct fsp_header *hdr, const void *fsp_blob)
51{
52 const uint8_t *raw_hdr = fsp_blob;
53
54 if (!looks_like_fsp_header(raw_hdr))
55 return CB_ERR;
56
Andrey Petrovd5a6eb42016-05-04 17:30:16 -070057 hdr->spec_version = read8(raw_hdr + 10);
Andrey Petrov97389702016-02-25 14:15:37 -080058 hdr->revision = read8(raw_hdr + 11);
59 hdr->fsp_revision = read32(raw_hdr + 12);
60 memcpy(hdr->image_id, raw_hdr + 16, ARRAY_SIZE(hdr->image_id));
61 hdr->image_id[ARRAY_SIZE(hdr->image_id) - 1] = '\0';
62 hdr->image_size = read32(raw_hdr + 24);
63 hdr->image_base = read32(raw_hdr + 28);
Andrey Petrovd5a6eb42016-05-04 17:30:16 -070064 hdr->image_attribute = read16(raw_hdr + 32);
65 hdr->component_attribute = read16(raw_hdr + 34);
Andrey Petrov97389702016-02-25 14:15:37 -080066 hdr->cfg_region_offset = read32(raw_hdr + 36);
67 hdr->cfg_region_size = read32(raw_hdr + 40);
Brenton Dong0a5971c2016-10-18 11:35:15 -070068 hdr->temp_ram_init_entry = read32(raw_hdr + 48);
69 hdr->temp_ram_exit_entry = read32(raw_hdr + 64);
Andrey Petrov97389702016-02-25 14:15:37 -080070 hdr->notify_phase_entry_offset = read32(raw_hdr + 56);
71 hdr->memory_init_entry_offset = read32(raw_hdr + 60);
72 hdr->silicon_init_entry_offset = read32(raw_hdr + 68);
Subrata Banik33d9c4a2020-05-26 18:26:54 +053073 if (CONFIG(PLATFORM_USES_FSP2_2))
74 hdr->multi_phase_si_init_entry_offset = read32(raw_hdr + 72);
Anil Kumar57309d32021-11-11 18:56:21 -080075 if (CONFIG(PLATFORM_USES_FSP2_3))
76 hdr->extended_fsp_revision = read16(raw_hdr + 76);
Andrey Petrov97389702016-02-25 14:15:37 -080077
78 return CB_SUCCESS;
79}
80
Julius Werner43c9d702021-04-12 17:00:16 -070081enum cb_err fsp_validate_component(struct fsp_header *hdr, void *fsp_file, size_t file_size)
Aaron Durbina413e5e2016-07-17 23:06:03 -050082{
Julius Werner43c9d702021-04-12 17:00:16 -070083 void *raw_hdr = fsp_file + FSP_HDR_OFFSET;
Aaron Durbina413e5e2016-07-17 23:06:03 -050084
Nikolai Vyssotski3c3d2cf2021-07-09 18:36:27 -050085 if (file_size < FSP_HDR_OFFSET + fsp_hdr_get_expected_min_length()) {
Julius Werner43c9d702021-04-12 17:00:16 -070086 printk(BIOS_CRIT, "FSP blob too small.\n");
Aaron Durbina413e5e2016-07-17 23:06:03 -050087 return CB_ERR;
88 }
89
Julius Werner43c9d702021-04-12 17:00:16 -070090 if (fsp_identify(hdr, raw_hdr) != CB_SUCCESS) {
Lee Leahyb20d4ba2016-07-31 16:49:28 -070091 printk(BIOS_CRIT, "No valid FSP header\n");
Aaron Durbina413e5e2016-07-17 23:06:03 -050092 return CB_ERR;
93 }
94
Julius Wernercd49cce2019-03-05 16:53:33 -080095 if (CONFIG(DISPLAY_FSP_HEADER))
Lee Leahy37b5ef22016-07-31 14:15:49 -070096 fsp_print_header_info(hdr);
Aaron Durbina413e5e2016-07-17 23:06:03 -050097
98 /* Check if size specified in the header matches the cbfs file size */
Julius Werner43c9d702021-04-12 17:00:16 -070099 if (file_size < hdr->image_size) {
Lee Leahyb20d4ba2016-07-31 16:49:28 -0700100 printk(BIOS_CRIT, "Component size bigger than cbfs file.\n");
Aaron Durbina413e5e2016-07-17 23:06:03 -0500101 return CB_ERR;
102 }
103
Johnny Lin5b47d772020-11-13 17:21:25 +0800104 if (ENV_ROMSTAGE)
Felix Held42df9af2021-08-24 19:26:56 +0200105 soc_validate_fspm_header(hdr);
Johnny Lin5b47d772020-11-13 17:21:25 +0800106
Aaron Durbina413e5e2016-07-17 23:06:03 -0500107 return CB_SUCCESS;
108}
109
Brandon Breitensteinc31ba0e2016-07-27 17:34:45 -0700110static bool fsp_reset_requested(uint32_t status)
Andrey Petrov3a94a3b2016-07-18 00:15:41 -0700111{
112 return (status >= FSP_STATUS_RESET_REQUIRED_COLD &&
113 status <= FSP_STATUS_RESET_REQUIRED_8);
114}
115
Brandon Breitensteinc31ba0e2016-07-27 17:34:45 -0700116void fsp_handle_reset(uint32_t status)
Andrey Petrov901e43c2016-06-22 19:22:30 -0700117{
Andrey Petrov3a94a3b2016-07-18 00:15:41 -0700118 if (!fsp_reset_requested(status))
119 return;
120
Lee Leahyb20d4ba2016-07-31 16:49:28 -0700121 printk(BIOS_SPEW, "FSP: handling reset type %x\n", status);
Andrey Petrov3a94a3b2016-07-18 00:15:41 -0700122
Lee Leahyb2b97a52017-03-10 08:40:18 -0800123 switch (status) {
Andrey Petrov901e43c2016-06-22 19:22:30 -0700124 case FSP_STATUS_RESET_REQUIRED_COLD:
Patrick Rudolphf677d172018-10-01 19:17:11 +0200125 full_reset();
Andrey Petrov901e43c2016-06-22 19:22:30 -0700126 break;
127 case FSP_STATUS_RESET_REQUIRED_WARM:
Patrick Rudolphf677d172018-10-01 19:17:11 +0200128 system_reset();
Andrey Petrov901e43c2016-06-22 19:22:30 -0700129 break;
Andrey Petrov3a94a3b2016-07-18 00:15:41 -0700130 case FSP_STATUS_RESET_REQUIRED_3:
131 case FSP_STATUS_RESET_REQUIRED_4:
132 case FSP_STATUS_RESET_REQUIRED_5:
133 case FSP_STATUS_RESET_REQUIRED_6:
134 case FSP_STATUS_RESET_REQUIRED_7:
135 case FSP_STATUS_RESET_REQUIRED_8:
136 chipset_handle_reset(status);
Andrey Petrov901e43c2016-06-22 19:22:30 -0700137 break;
138 default:
139 break;
140 }
141}
Aaron Durbina85febc2020-05-15 15:09:10 -0600142
Aaron Durbinecbfa992020-05-15 17:01:58 -0600143static inline bool fspm_env(void)
144{
145 if (ENV_ROMSTAGE)
146 return true;
147 return false;
148}
149
150static inline bool fspm_xip(void)
151{
152 /* FSP-M is assumed to be loaded in romstage. */
153 if (fspm_env() && CONFIG(FSP_M_XIP))
154 return true;
155 return false;
156}
157
Aaron Durbina85febc2020-05-15 15:09:10 -0600158/* Load the FSP component described by fsp_load_descriptor from cbfs. The FSP
159 * header object will be validated and filled in on successful load. */
160enum cb_err fsp_load_component(struct fsp_load_descriptor *fspld, struct fsp_header *hdr)
161{
Aaron Durbina85febc2020-05-15 15:09:10 -0600162 size_t output_size;
163 void *dest;
Aaron Durbina85febc2020-05-15 15:09:10 -0600164 struct prog *fsp_prog = &fspld->fsp_prog;
165
Julius Werner8205ce62021-03-10 17:25:01 -0800166 dest = cbfs_alloc(prog_name(fsp_prog), fspld->alloc, fspld, &output_size);
167 if (!dest)
Aaron Durbina85febc2020-05-15 15:09:10 -0600168 return CB_ERR;
169
Raul E Rangel4911dc72021-11-05 10:29:24 -0600170 /* Don't allow FSP-M relocation when XIP. */
171 if (!fspm_xip() && fsp_component_relocate((uintptr_t)dest, dest, output_size) < 0) {
Julius Werner8205ce62021-03-10 17:25:01 -0800172 printk(BIOS_ERR, "Unable to relocate FSP component!\n");
Aaron Durbina85febc2020-05-15 15:09:10 -0600173 return CB_ERR;
Julius Werner8205ce62021-03-10 17:25:01 -0800174 }
Aaron Durbina85febc2020-05-15 15:09:10 -0600175
176 prog_set_area(fsp_prog, dest, output_size);
177
Julius Werner43c9d702021-04-12 17:00:16 -0700178 if (fsp_validate_component(hdr, dest, output_size) != CB_SUCCESS) {
Aaron Durbina85febc2020-05-15 15:09:10 -0600179 printk(BIOS_ERR, "Invalid FSP header after load!\n");
180 return CB_ERR;
181 }
182
183 /* Signal that FSP component has been loaded. */
184 prog_segment_loaded(hdr->image_base, hdr->image_size, SEG_FINAL);
185
186 return CB_SUCCESS;
187}
Johnny Linb8899ef2020-05-28 14:04:58 +0800188
189/* Only call this function when FSP header has been read and validated */
190void fsp_get_version(char *buf)
191{
192 struct fsp_header *hdr = &fsps_hdr;
Johnny Lin5b47d772020-11-13 17:21:25 +0800193 union fsp_revision revision;
Johnny Linb8899ef2020-05-28 14:04:58 +0800194
195 revision.val = hdr->fsp_revision;
196 snprintf(buf, FSP_VER_LEN, "%u.%u-%u.%u.%u.%u", (hdr->spec_version >> 4),
197 hdr->spec_version & 0xf, revision.rev.major,
198 revision.rev.minor, revision.rev.revision, revision.rev.bld_num);
199}
200
Felix Held88995982021-01-28 22:43:52 +0100201/* Check if the signature in the UPD header matches the expected one. If it doesn't match, the
202 FSP binaries in CBFS are for a different platform than the platform code trying to use it
203 in which case the function calls die(). */
204void fsp_verify_upd_header_signature(uint64_t upd_signature, uint64_t expected_signature)
205{
206 if (upd_signature != expected_signature) {
207 /* The UPD signatures are non-zero-terminated ASCII stored as a little endian
208 uint64_t, so this needs some casts. */
209 die_with_post_code(POST_INVALID_VENDOR_BINARY,
210 "Invalid UPD signature! FSP provided \"%8s\", expected was \"%8s\".\n",
211 (char *)&upd_signature,
212 (char *)&expected_signature);
213 }
214}
215
Johnny Linb8899ef2020-05-28 14:04:58 +0800216/* Add FSP version to coreboot table LB_TAG_PLATFORM_BLOB_VERSION */
217void lb_string_platform_blob_version(struct lb_header *header)
218{
219 struct lb_string *rec;
220 size_t len;
221 char fsp_version[FSP_VER_LEN] = {0};
222
223 fsp_get_version(fsp_version);
224 rec = (struct lb_string *)lb_new_record(header);
225 rec->tag = LB_TAG_PLATFORM_BLOB_VERSION;
226 len = strlen(fsp_version);
227 rec->size = ALIGN_UP(sizeof(*rec) + len + 1, 8);
228 memcpy(rec->string, fsp_version, len+1);
229}
Johnny Lin5b47d772020-11-13 17:21:25 +0800230
Felix Held42df9af2021-08-24 19:26:56 +0200231__weak void soc_validate_fspm_header(const struct fsp_header *hdr)
Johnny Lin5b47d772020-11-13 17:21:25 +0800232{
Johnny Lin5b47d772020-11-13 17:21:25 +0800233}