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 <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 = &params;
 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