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