uboot/arch/x86/lib/fsp1/fsp_support.c
<<
>>
Prefs
   1// SPDX-License-Identifier: Intel
   2/*
   3 * Copyright (C) 2013, Intel Corporation
   4 * Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com>
   5 */
   6
   7#include <common.h>
   8#include <log.h>
   9#include <asm/fsp1/fsp_support.h>
  10#include <asm/post.h>
  11
  12struct fsp_header *__attribute__((optimize("O0"))) fsp_find_header(void)
  13{
  14        /*
  15         * This function may be called before the a stack is established,
  16         * so special care must be taken. First, it cannot declare any local
  17         * variable using stack. Only register variable can be used here.
  18         * Secondly, some compiler version will add prolog or epilog code
  19         * for the C function. If so the function call may not work before
  20         * stack is ready.
  21         *
  22         * GCC 4.8.1 has been verified to be working for the following codes.
  23         */
  24        volatile register u8 *fsp asm("eax");
  25
  26        /* Initalize the FSP base */
  27        fsp = (u8 *)CONFIG_FSP_ADDR;
  28
  29        /* Check the FV signature, _FVH */
  30        if (((struct fv_header *)fsp)->sign == EFI_FVH_SIGNATURE) {
  31                /* Go to the end of the FV header and align the address */
  32                fsp += ((struct fv_header *)fsp)->ext_hdr_off;
  33                fsp += ((struct fv_ext_header *)fsp)->ext_hdr_size;
  34                fsp  = (u8 *)(((u32)fsp + 7) & 0xFFFFFFF8);
  35        } else {
  36                fsp  = 0;
  37        }
  38
  39        /* Check the FFS GUID */
  40        if (fsp &&
  41            ((struct ffs_file_header *)fsp)->name.b[0] == FSP_GUID_BYTE0 &&
  42            ((struct ffs_file_header *)fsp)->name.b[1] == FSP_GUID_BYTE1 &&
  43            ((struct ffs_file_header *)fsp)->name.b[2] == FSP_GUID_BYTE2 &&
  44            ((struct ffs_file_header *)fsp)->name.b[3] == FSP_GUID_BYTE3 &&
  45            ((struct ffs_file_header *)fsp)->name.b[4] == FSP_GUID_BYTE4 &&
  46            ((struct ffs_file_header *)fsp)->name.b[5] == FSP_GUID_BYTE5 &&
  47            ((struct ffs_file_header *)fsp)->name.b[6] == FSP_GUID_BYTE6 &&
  48            ((struct ffs_file_header *)fsp)->name.b[7] == FSP_GUID_BYTE7 &&
  49            ((struct ffs_file_header *)fsp)->name.b[8] == FSP_GUID_BYTE8 &&
  50            ((struct ffs_file_header *)fsp)->name.b[9] == FSP_GUID_BYTE9 &&
  51            ((struct ffs_file_header *)fsp)->name.b[10] == FSP_GUID_BYTE10 &&
  52            ((struct ffs_file_header *)fsp)->name.b[11] == FSP_GUID_BYTE11 &&
  53            ((struct ffs_file_header *)fsp)->name.b[12] == FSP_GUID_BYTE12 &&
  54            ((struct ffs_file_header *)fsp)->name.b[13] == FSP_GUID_BYTE13 &&
  55            ((struct ffs_file_header *)fsp)->name.b[14] == FSP_GUID_BYTE14 &&
  56            ((struct ffs_file_header *)fsp)->name.b[15] == FSP_GUID_BYTE15) {
  57                /* Add the FFS header size to find the raw section header */
  58                fsp += sizeof(struct ffs_file_header);
  59        } else {
  60                fsp = 0;
  61        }
  62
  63        if (fsp &&
  64            ((struct raw_section *)fsp)->type == EFI_SECTION_RAW) {
  65                /* Add the raw section header size to find the FSP header */
  66                fsp += sizeof(struct raw_section);
  67        } else {
  68                fsp = 0;
  69        }
  70
  71        return (struct fsp_header *)fsp;
  72}
  73
  74void fsp_continue(u32 status, void *hob_list)
  75{
  76        post_code(POST_MRC);
  77
  78        assert(status == 0);
  79
  80        /* The boot loader main function entry */
  81        fsp_init_done(hob_list);
  82}
  83
  84void fsp_init(u32 stack_top, u32 boot_mode, void *nvs_buf)
  85{
  86        struct fsp_config_data config_data;
  87        fsp_init_f init;
  88        struct fsp_init_params params;
  89        struct fspinit_rtbuf rt_buf;
  90        struct fsp_header *fsp_hdr;
  91        struct fsp_init_params *params_ptr;
  92#ifdef CONFIG_FSP_USE_UPD
  93        struct vpd_region *fsp_vpd;
  94        struct upd_region *fsp_upd;
  95#endif
  96
  97        fsp_hdr = fsp_find_header();
  98        if (fsp_hdr == NULL) {
  99                /* No valid FSP info header was found */
 100                panic("Invalid FSP header");
 101        }
 102
 103        config_data.common.fsp_hdr = fsp_hdr;
 104        config_data.common.stack_top = stack_top;
 105        config_data.common.boot_mode = boot_mode;
 106
 107#ifdef CONFIG_FSP_USE_UPD
 108        /* Get VPD region start */
 109        fsp_vpd = (struct vpd_region *)(fsp_hdr->img_base +
 110                        fsp_hdr->cfg_region_off);
 111
 112        /* Verify the VPD data region is valid */
 113        assert(fsp_vpd->sign == VPD_IMAGE_ID);
 114
 115        fsp_upd = &config_data.fsp_upd;
 116
 117        /* Copy default data from Flash */
 118        memcpy(fsp_upd, (void *)(fsp_hdr->img_base + fsp_vpd->upd_offset),
 119               sizeof(struct upd_region));
 120
 121        /* Verify the UPD data region is valid */
 122        assert(fsp_upd->terminator == UPD_TERMINATOR);
 123#endif
 124
 125        memset(&rt_buf, 0, sizeof(struct fspinit_rtbuf));
 126
 127        /* Override any configuration if required */
 128        fsp_update_configs(&config_data, &rt_buf);
 129
 130        memset(&params, 0, sizeof(struct fsp_init_params));
 131        params.nvs_buf = nvs_buf;
 132        params.rt_buf = (struct fspinit_rtbuf *)&rt_buf;
 133        params.continuation = (fsp_continuation_f)fsp_asm_continuation;
 134
 135        init = (fsp_init_f)(fsp_hdr->img_base + fsp_hdr->fsp_init);
 136        params_ptr = &params;
 137
 138        post_code(POST_PRE_MRC);
 139
 140        /* Load GDT for FSP */
 141        setup_fsp_gdt();
 142
 143        /*
 144         * Use ASM code to ensure the register value in EAX & EDX
 145         * will be passed into fsp_continue
 146         */
 147        asm volatile (
 148                "pushl  %0;"
 149                "call   *%%eax;"
 150                ".global fsp_asm_continuation;"
 151                "fsp_asm_continuation:;"
 152                "movl   4(%%esp), %%eax;"       /* status */
 153                "movl   8(%%esp), %%edx;"       /* hob_list */
 154                "jmp    fsp_continue;"
 155                : : "m"(params_ptr), "a"(init)
 156        );
 157
 158        /*
 159         * Should never get here.
 160         * Control will continue from fsp_continue.
 161         * This line below is to prevent the compiler from optimizing
 162         * structure intialization.
 163         *
 164         * DO NOT REMOVE!
 165         */
 166        init(&params);
 167}
 168
 169u32 fsp_notify(struct fsp_header *fsp_hdr, u32 phase)
 170{
 171        fsp_notify_f notify;
 172        struct fsp_notify_params params;
 173        struct fsp_notify_params *params_ptr;
 174        u32 status;
 175
 176        if (!fsp_hdr)
 177                fsp_hdr = (struct fsp_header *)fsp_find_header();
 178
 179        if (fsp_hdr == NULL) {
 180                /* No valid FSP info header */
 181                panic("Invalid FSP header");
 182        }
 183
 184        notify = (fsp_notify_f)(fsp_hdr->img_base + fsp_hdr->fsp_notify);
 185        params.phase = phase;
 186        params_ptr = &params;
 187
 188        /*
 189         * Use ASM code to ensure correct parameter is on the stack for
 190         * FspNotify as U-Boot is using different ABI from FSP
 191         */
 192        asm volatile (
 193                "pushl  %1;"            /* push notify phase */
 194                "call   *%%eax;"        /* call FspNotify */
 195                "addl   $4, %%esp;"     /* clean up the stack */
 196                : "=a"(status) : "m"(params_ptr), "a"(notify), "m"(*params_ptr)
 197        );
 198
 199        return status;
 200}
 201