coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
util.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
3 #include <boot/coreboot_tables.h>
4 #include <device/mmio.h>
5 #include <cbfs.h>
6 #include <cf9_reset.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>
14 
16 {
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);
27 }
28 
29 static bool looks_like_fsp_header(struct fsp_header *hdr)
30 {
31  if (memcmp(&hdr->signature, FSP_HDR_SIGNATURE, 4)) {
32  printk(BIOS_ALERT, "Did not find a valid FSP signature\n");
33  return false;
34  }
35 
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;
43  }
44 
45  return true;
46 }
47 
48 enum cb_err fsp_identify(struct fsp_header *hdr, const void *fsp_blob)
49 {
50  memcpy(hdr, fsp_blob, sizeof(struct fsp_header));
51  if (!looks_like_fsp_header(hdr))
52  return CB_ERR;
53 
54  return CB_SUCCESS;
55 }
56 
57 enum cb_err fsp_validate_component(struct fsp_header *hdr, void *fsp_file, size_t file_size)
58 {
59  void *raw_hdr = fsp_file + FSP_HDR_OFFSET;
60 
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;
64  }
65 
66  if (fsp_identify(hdr, raw_hdr) != CB_SUCCESS) {
67  printk(BIOS_CRIT, "No valid FSP header\n");
68  return CB_ERR;
69  }
70 
71  if (CONFIG(DISPLAY_FSP_HEADER))
73 
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;
78  }
79 
80  if (ENV_ROMSTAGE)
82 
83  return CB_SUCCESS;
84 }
85 
86 static bool fsp_reset_requested(uint32_t status)
87 {
88  return (status >= FSP_STATUS_RESET_REQUIRED_COLD &&
89  status <= FSP_STATUS_RESET_REQUIRED_8);
90 }
91 
93 {
94  if (!fsp_reset_requested(status))
95  return;
96 
97  printk(BIOS_SPEW, "FSP: handling reset type %x\n", status);
98 
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;
116  }
117 }
118 
119 static inline bool fspm_env(void)
120 {
121  if (ENV_ROMSTAGE)
122  return true;
123  return false;
124 }
125 
126 static 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 
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)
137 {
138  size_t output_size;
139  void *dest;
140  struct prog *fsp_prog = &fspld->fsp_prog;
141 
142  dest = cbfs_alloc(prog_name(fsp_prog), fspld->alloc, fspld, &output_size);
143  if (!dest)
144  return CB_ERR;
145 
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;
150  }
151 
152  prog_set_area(fsp_prog, dest, output_size);
153 
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;
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 }
164 
165 /* Only call this function when FSP header has been read and validated */
166 void fsp_get_version(char *buf)
167 {
168  struct fsp_header *hdr = &fsps_hdr;
169  union fsp_revision revision;
170 
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);
175 }
176 
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)
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. */
186  "Invalid UPD signature! FSP provided \"%8s\", expected was \"%8s\".\n",
187  (char *)&upd_signature,
188  (char *)&expected_signature);
189  }
190 }
191 
192 /* Add FSP version to coreboot table LB_TAG_PLATFORM_BLOB_VERSION */
194 {
195  struct lb_string *rec;
196  size_t len;
197  char fsp_version[FSP_VER_LEN] = {0};
198 
200  rec = (struct lb_string *)lb_new_record(header);
202  len = strlen(fsp_version);
203  rec->size = ALIGN_UP(sizeof(*rec) + len + 1, 8);
204  memcpy(rec->string, fsp_version, len+1);
205 }
206 
207 __weak void soc_validate_fspm_header(const struct fsp_header *hdr)
208 {
209 }
struct arm64_kernel_header header
Definition: fit_payload.c:30
void * memcpy(void *dest, const void *src, size_t n)
Definition: memcpy.c:7
#define dead_code_t(type)
Definition: assert.h:92
#define ALIGN_UP(x, a)
Definition: helpers.h:17
cb_err
coreboot error codes
Definition: cb_err.h:15
@ CB_ERR
Generic error code.
Definition: cb_err.h:17
@ CB_SUCCESS
Call completed successfully.
Definition: cb_err.h:16
static void * cbfs_alloc(const char *name, cbfs_allocator_t allocator, void *arg, size_t *size_out)
Definition: cbfs.h:215
void full_reset(void)
Definition: cf9_reset.c:45
void system_reset(void)
Definition: cf9_reset.c:37
ssize_t fsp_component_relocate(uintptr_t new_addr, void *fsp, size_t size)
Definition: fsp_relocate.c:507
@ LB_TAG_PLATFORM_BLOB_VERSION
#define printk(level,...)
Definition: stdlib.h:16
#define die_with_post_code(value, fmt,...)
Definition: console.h:21
#define FSP_VER_LEN
Definition: util.h:17
void chipset_handle_reset(uint32_t status)
Definition: fsp_reset.c:9
static bool fspm_xip(void)
Definition: util.c:126
void lb_string_platform_blob_version(struct lb_header *header)
Definition: util.c:193
static uint32_t fsp_hdr_get_expected_min_length(void)
Definition: util.c:15
void fsp_verify_upd_header_signature(uint64_t upd_signature, uint64_t expected_signature)
Definition: util.c:180
static bool looks_like_fsp_header(struct fsp_header *hdr)
Definition: util.c:29
enum cb_err fsp_identify(struct fsp_header *hdr, const void *fsp_blob)
Definition: util.c:48
static bool fsp_reset_requested(uint32_t status)
Definition: util.c:86
static bool fspm_env(void)
Definition: util.c:119
void fsp_handle_reset(uint32_t status)
Definition: util.c:92
void fsp_get_version(char *buf)
Definition: util.c:166
enum cb_err fsp_validate_component(struct fsp_header *hdr, void *fsp_file, size_t file_size)
Definition: util.c:57
enum cb_err fsp_load_component(struct fsp_load_descriptor *fspld, struct fsp_header *hdr)
Definition: util.c:136
__weak void soc_validate_fspm_header(const struct fsp_header *hdr)
Definition: util.c:207
@ CONFIG
Definition: dsi_common.h:201
void fsp_print_header_info(const struct fsp_header *hdr)
Definition: header_display.c:6
struct lb_record * lb_new_record(struct lb_header *header)
#define FSP_HDR_OFFSET
Definition: info_header.h:8
#define FSP_HDR_SIGNATURE
Definition: info_header.h:9
struct fsp_header fsps_hdr
Definition: silicon_init.c:19
#define BIOS_CRIT
BIOS_CRIT - Recovery unlikely.
Definition: loglevel.h:56
#define BIOS_ALERT
BIOS_ALERT - Dying / Unrecoverable.
Definition: loglevel.h:41
#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
static uint8_t * buf
Definition: uart.c:7
#define POST_INVALID_VENDOR_BINARY
Vendor binary error.
Definition: post_codes.h:338
@ SEG_FINAL
void prog_segment_loaded(uintptr_t start, size_t size, int flags)
Definition: prog_ops.c:6
static const char * prog_name(const struct prog *prog)
static void prog_set_area(struct prog *prog, void *start, size_t size)
#define ENV_ROMSTAGE
Definition: rules.h:149
const struct smm_save_state_ops *legacy_ops __weak
Definition: save_state.c:8
static uint32_t fsp_version
Definition: romstage.c:38
unsigned int uint32_t
Definition: stdint.h:14
unsigned long uintptr_t
Definition: stdint.h:21
unsigned long long uint64_t
Definition: stdint.h:17
int memcmp(const void *s1, const void *s2, size_t n)
Definition: memcmp.c:3
size_t strlen(const char *src)
Definition: string.c:42
struct prog fsp_prog
Definition: util.h:136
cbfs_allocator_t alloc
Definition: util.h:138
uint8_t string[0]
uint32_t size
uint32_t tag
uint8_t revision
Definition: util.h:63
int snprintf(char *buf, size_t size, const char *fmt,...)
Note: This file is only for POSIX compatibility, and is meant to be chain-included via string....
Definition: vsprintf.c:35