1 // SPDX-License-Identifier: Intel
3 * Copyright 2019 Google LLC
4 * Written by Simon Glass <sjg@chromium.org>
10 #include <spi_flash.h>
11 #include <asm/fsp/fsp_support.h>
12 #include <asm/fsp2/fsp_internal.h>
14 /* The amount of the FSP header to probe to obtain what we need */
15 #define PROBE_BUF_SIZE 0x180
17 int fsp_get_header(ulong offset, ulong size, bool use_spi_flash,
18 struct fsp_header **fspp)
20 static efi_guid_t guid = FSP_HEADER_GUID;
21 struct fv_ext_header *exhdr;
22 struct fsp_header *fsp;
23 struct ffs_file_header *file_hdr;
25 struct raw_section *raw;
27 u8 buf[PROBE_BUF_SIZE];
32 * There are quite a very steps to work through all the headers in this
33 * file and the structs have similar names. Turn on debugging if needed
34 * to understand what is going wrong.
36 * You are in a maze of twisty little headers all alike.
38 debug("offset=%x buf=%x\n", (uint)offset, (uint)buf);
40 ret = uclass_first_device_err(UCLASS_SPI_FLASH, &dev);
42 return log_msg_ret("Cannot find flash device", ret);
43 ret = spi_flash_read_dm(dev, offset, PROBE_BUF_SIZE, buf);
45 return log_msg_ret("Cannot read flash", ret);
47 memcpy(buf, (void *)offset, PROBE_BUF_SIZE);
50 /* Initalise the FSP base */
54 /* Check the FV signature, _FVH */
55 debug("offset=%x sign=%x\n", (uint)offset, (uint)fv->sign);
56 if (fv->sign != EFI_FVH_SIGNATURE)
57 return log_msg_ret("Base FV signature", -EINVAL);
59 /* Go to the end of the FV header and align the address */
60 debug("fv->ext_hdr_off = %x\n", fv->ext_hdr_off);
61 ptr += fv->ext_hdr_off;
63 ptr += ALIGN(exhdr->ext_hdr_size, 8);
64 debug("ptr=%x\n", ptr - (void *)buf);
66 /* Check the FFS GUID */
68 if (memcmp(&file_hdr->name, &guid, sizeof(guid)))
69 return log_msg_ret("Base FFS GUID", -ENXIO);
70 /* Add the FFS header size to find the raw section header */
74 debug("raw->type = %x\n", raw->type);
75 if (raw->type != EFI_SECTION_RAW)
76 return log_msg_ret("Section type not RAW", -ENOEXEC);
78 /* Add the raw section header size to find the FSP header */
82 /* Check the FSPH header */
83 debug("fsp %x\n", (uint)fsp);
84 if (fsp->sign != EFI_FSPH_SIGNATURE)
85 return log_msg_ret("Base FSPH signature", -EACCES);
87 base = (void *)fsp->img_base;
88 debug("Image base %x\n", (uint)base);
89 debug("Image addr %x\n", (uint)fsp->fsp_mem_init);
91 ret = spi_flash_read_dm(dev, offset, size, base);
93 return log_msg_ret("Could not read FPS-M", ret);
95 memcpy(base, (void *)offset, size);
97 ptr = base + (ptr - (void *)buf);
103 u32 fsp_notify(struct fsp_header *fsp_hdr, u32 phase)
106 struct fsp_notify_params params;
107 struct fsp_notify_params *params_ptr;
111 fsp_hdr = gd->arch.fsp_s_hdr;
114 return log_msg_ret("no FSP", -ENOENT);
116 notify = (fsp_notify_f)(fsp_hdr->img_base + fsp_hdr->fsp_notify);
117 params.phase = phase;
118 params_ptr = ¶ms;
121 * Use ASM code to ensure correct parameter is on the stack for
122 * FspNotify as U-Boot is using different ABI from FSP
125 "pushl %1;" /* push notify phase */
126 "call *%%eax;" /* call FspNotify */
127 "addl $4, %%esp;" /* clean up the stack */
128 : "=a"(status) : "m"(params_ptr), "a"(notify), "m"(*params_ptr)