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