blob: 503f97d5f3346ff164a95b69137fc838cb18f5b4 [file] [log] [blame]
Simon Glass466c7852019-12-06 21:42:18 -07001// SPDX-License-Identifier: Intel
2/*
3 * Copyright 2019 Google LLC
4 * Written by Simon Glass <sjg@chromium.org>
5 */
6
7#include <common.h>
8#include <dm.h>
Simon Glass0f2af882020-05-10 11:40:05 -06009#include <log.h>
Simon Glass466c7852019-12-06 21:42:18 -070010#include <spi_flash.h>
11#include <asm/fsp/fsp_support.h>
12#include <asm/fsp2/fsp_internal.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060013#include <asm/global_data.h>
Simon Glass466c7852019-12-06 21:42:18 -070014
15/* The amount of the FSP header to probe to obtain what we need */
16#define PROBE_BUF_SIZE 0x180
17
18int fsp_get_header(ulong offset, ulong size, bool use_spi_flash,
19 struct fsp_header **fspp)
20{
21 static efi_guid_t guid = FSP_HEADER_GUID;
22 struct fv_ext_header *exhdr;
23 struct fsp_header *fsp;
24 struct ffs_file_header *file_hdr;
25 struct fv_header *fv;
26 struct raw_section *raw;
27 void *ptr, *base;
28 u8 buf[PROBE_BUF_SIZE];
29 struct udevice *dev;
30 int ret;
31
32 /*
33 * There are quite a very steps to work through all the headers in this
34 * file and the structs have similar names. Turn on debugging if needed
35 * to understand what is going wrong.
36 *
37 * You are in a maze of twisty little headers all alike.
38 */
Simon Glass549995d2020-09-22 12:45:38 -060039 log_debug("offset=%x buf=%x, use_spi_flash=%d\n", (uint)offset,
40 (uint)buf, use_spi_flash);
Simon Glass466c7852019-12-06 21:42:18 -070041 if (use_spi_flash) {
42 ret = uclass_first_device_err(UCLASS_SPI_FLASH, &dev);
43 if (ret)
44 return log_msg_ret("Cannot find flash device", ret);
45 ret = spi_flash_read_dm(dev, offset, PROBE_BUF_SIZE, buf);
46 if (ret)
47 return log_msg_ret("Cannot read flash", ret);
48 } else {
49 memcpy(buf, (void *)offset, PROBE_BUF_SIZE);
50 }
51
52 /* Initalise the FSP base */
53 ptr = buf;
54 fv = ptr;
55
56 /* Check the FV signature, _FVH */
Simon Glass549995d2020-09-22 12:45:38 -060057 log_debug("offset=%x sign=%x\n", (uint)offset, (uint)fv->sign);
Simon Glass466c7852019-12-06 21:42:18 -070058 if (fv->sign != EFI_FVH_SIGNATURE)
59 return log_msg_ret("Base FV signature", -EINVAL);
60
61 /* Go to the end of the FV header and align the address */
Simon Glass549995d2020-09-22 12:45:38 -060062 log_debug("fv->ext_hdr_off = %x\n", fv->ext_hdr_off);
Simon Glass466c7852019-12-06 21:42:18 -070063 ptr += fv->ext_hdr_off;
64 exhdr = ptr;
65 ptr += ALIGN(exhdr->ext_hdr_size, 8);
Simon Glass549995d2020-09-22 12:45:38 -060066 log_debug("ptr=%x\n", ptr - (void *)buf);
Simon Glass466c7852019-12-06 21:42:18 -070067
68 /* Check the FFS GUID */
69 file_hdr = ptr;
70 if (memcmp(&file_hdr->name, &guid, sizeof(guid)))
71 return log_msg_ret("Base FFS GUID", -ENXIO);
72 /* Add the FFS header size to find the raw section header */
73 ptr = file_hdr + 1;
74
75 raw = ptr;
Simon Glass549995d2020-09-22 12:45:38 -060076 log_debug("raw->type = %x\n", raw->type);
Simon Glass466c7852019-12-06 21:42:18 -070077 if (raw->type != EFI_SECTION_RAW)
78 return log_msg_ret("Section type not RAW", -ENOEXEC);
79
80 /* Add the raw section header size to find the FSP header */
81 ptr = raw + 1;
82 fsp = ptr;
83
84 /* Check the FSPH header */
Simon Glass549995d2020-09-22 12:45:38 -060085 log_debug("fsp %x, fsp-buf=%x, si=%x\n", (uint)fsp, ptr - (void *)buf,
86 (void *)&fsp->fsp_silicon_init - (void *)buf);
Simon Glass466c7852019-12-06 21:42:18 -070087 if (fsp->sign != EFI_FSPH_SIGNATURE)
88 return log_msg_ret("Base FSPH signature", -EACCES);
89
90 base = (void *)fsp->img_base;
Simon Glass549995d2020-09-22 12:45:38 -060091 log_debug("image base %x\n", (uint)base);
92 if (fsp->fsp_mem_init)
93 log_debug("mem_init offset %x\n", (uint)fsp->fsp_mem_init);
94 else if (fsp->fsp_silicon_init)
95 log_debug("silicon_init offset %x\n",
96 (uint)fsp->fsp_silicon_init);
Simon Glass466c7852019-12-06 21:42:18 -070097 if (use_spi_flash) {
98 ret = spi_flash_read_dm(dev, offset, size, base);
99 if (ret)
100 return log_msg_ret("Could not read FPS-M", ret);
101 } else {
102 memcpy(base, (void *)offset, size);
103 }
104 ptr = base + (ptr - (void *)buf);
105 *fspp = ptr;
106
107 return 0;
108}
109
110u32 fsp_notify(struct fsp_header *fsp_hdr, u32 phase)
111{
112 fsp_notify_f notify;
113 struct fsp_notify_params params;
114 struct fsp_notify_params *params_ptr;
115 u32 status;
116
117 if (!fsp_hdr)
118 fsp_hdr = gd->arch.fsp_s_hdr;
119
120 if (!fsp_hdr)
121 return log_msg_ret("no FSP", -ENOENT);
122
123 notify = (fsp_notify_f)(fsp_hdr->img_base + fsp_hdr->fsp_notify);
124 params.phase = phase;
125 params_ptr = &params;
126
127 /*
128 * Use ASM code to ensure correct parameter is on the stack for
129 * FspNotify as U-Boot is using different ABI from FSP
130 */
131 asm volatile (
132 "pushl %1;" /* push notify phase */
133 "call *%%eax;" /* call FspNotify */
134 "addl $4, %%esp;" /* clean up the stack */
135 : "=a"(status) : "m"(params_ptr), "a"(notify), "m"(*params_ptr)
136 );
137
138 return status;
139}