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