avionic design with actual uboot and tooling

submodule of avionic design uboot bootloader and with included tools to
get you started , read readme.md and readme-tk1-loader.md
This commit is contained in:
2026-03-03 21:46:32 +02:00
parent fe3ba02c96
commit 68d74d3181
11967 changed files with 2221897 additions and 0 deletions

View File

@@ -0,0 +1,11 @@
#
# Copyright (C) 2015 Google, Inc
#
# SPDX-License-Identifier: GPL-2.0+
#
obj-y += cmd_fsp.o
obj-y += fsp_car.o
obj-y += fsp_common.o
obj-y += fsp_dram.o
obj-y += fsp_support.o

View File

@@ -0,0 +1,132 @@
/*
* Copyright (C) 2014-2015, Bin Meng <bmeng.cn@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <command.h>
#include <asm/fsp/fsp_support.h>
DECLARE_GLOBAL_DATA_PTR;
static char *hob_type[] = {
"reserved",
"Hand-off",
"Mem Alloc",
"Res Desc",
"GUID Ext",
"FV",
"CPU",
"Mem Pool",
"reserved",
"FV2",
"Load PEIM",
"Capsule",
};
static int do_hdr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
struct fsp_header *hdr = find_fsp_header();
u32 img_addr = hdr->img_base;
char *sign = (char *)&hdr->sign;
int i;
printf("FSP : binary 0x%08x, header 0x%08x\n",
CONFIG_FSP_ADDR, (int)hdr);
printf("Header : sign ");
for (i = 0; i < sizeof(hdr->sign); i++)
printf("%c", *sign++);
printf(", size %d, rev %d\n", hdr->hdr_len, hdr->hdr_rev);
printf("Image : rev %d.%d, id ",
(hdr->img_rev >> 8) & 0xff, hdr->img_rev & 0xff);
for (i = 0; i < ARRAY_SIZE(hdr->img_id); i++)
printf("%c", hdr->img_id[i]);
printf(", addr 0x%08x, size %d\n", img_addr, hdr->img_size);
printf("VPD : addr 0x%08x, size %d\n",
hdr->cfg_region_off + img_addr, hdr->cfg_region_size);
printf("\nNumber of APIs Supported : %d\n", hdr->api_num);
printf("\tTempRamInit : 0x%08x\n", hdr->fsp_tempram_init + img_addr);
printf("\tFspInit : 0x%08x\n", hdr->fsp_init + img_addr);
printf("\tFspNotify : 0x%08x\n", hdr->fsp_notify + img_addr);
return 0;
}
static int do_hob(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
const struct hob_header *hdr;
uint type;
char *desc;
int i = 0;
hdr = gd->arch.hob_list;
printf("HOB list address: 0x%08x\n\n", (unsigned int)hdr);
printf("# | Address | Type | Len | ");
printf("%42s\n", "GUID");
printf("---|----------|-----------|------|-");
printf("------------------------------------------\n");
while (!end_of_hob(hdr)) {
printf("%02x | %08x | ", i, (unsigned int)hdr);
type = hdr->type;
if (type == HOB_TYPE_UNUSED)
desc = "*Unused*";
else if (type == HOB_TYPE_EOH)
desc = "*EOH*";
else if (type >= 0 && type <= ARRAY_SIZE(hob_type))
desc = hob_type[type];
else
desc = "*Invalid*";
printf("%-9s | %04x | ", desc, hdr->len);
if (type == HOB_TYPE_MEM_ALLOC || type == HOB_TYPE_RES_DESC ||
type == HOB_TYPE_GUID_EXT) {
struct efi_guid *guid = (struct efi_guid *)(hdr + 1);
int j;
printf("%08x-%04x-%04x", guid->data1,
guid->data2, guid->data3);
for (j = 0; j < ARRAY_SIZE(guid->data4); j++)
printf("-%02x", guid->data4[j]);
} else {
printf("%42s", "Not Available");
}
printf("\n");
hdr = get_next_hob(hdr);
i++;
}
return 0;
}
static cmd_tbl_t fsp_commands[] = {
U_BOOT_CMD_MKENT(hdr, 0, 1, do_hdr, "", ""),
U_BOOT_CMD_MKENT(hob, 0, 1, do_hob, "", ""),
};
static int do_fsp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
cmd_tbl_t *fsp_cmd;
int ret;
if (argc < 2)
return CMD_RET_USAGE;
fsp_cmd = find_cmd_tbl(argv[1], fsp_commands, ARRAY_SIZE(fsp_commands));
argc -= 2;
argv += 2;
if (!fsp_cmd || argc > fsp_cmd->maxargs)
return CMD_RET_USAGE;
ret = fsp_cmd->cmd(fsp_cmd, flag, argc, argv);
return cmd_process_error(fsp_cmd, ret);
}
U_BOOT_CMD(
fsp, 2, 1, do_fsp,
"Show Intel Firmware Support Package (FSP) related information",
"hdr - Print FSP header information\n"
"fsp hob - Print FSP Hand-Off Block (HOB) information"
);

View File

@@ -0,0 +1,110 @@
/*
* Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <config.h>
#include <asm/post.h>
.globl car_init
car_init:
/*
* Note: ebp holds the BIST value (built-in self test) so far, but ebp
* will be destroyed through the FSP call, thus we have to test the
* BIST value here before we call into FSP.
*/
test %ebp, %ebp
jz car_init_start
post_code(POST_BIST_FAILURE)
jmp die
car_init_start:
post_code(POST_CAR_START)
lea find_fsp_header_romstack, %esp
jmp find_fsp_header
find_fsp_header_ret:
/* EAX points to FSP_INFO_HEADER */
mov %eax, %ebp
/* sanity test */
cmp $CONFIG_FSP_ADDR, %eax
jb die
/* calculate TempRamInitEntry address */
mov 0x30(%ebp), %eax
add 0x1c(%ebp), %eax
/* call FSP TempRamInitEntry to setup temporary stack */
lea temp_ram_init_romstack, %esp
jmp *%eax
temp_ram_init_ret:
addl $4, %esp
cmp $0, %eax
jnz car_init_fail
post_code(POST_CAR_CPU_CACHE)
/*
* The FSP TempRamInit initializes the ecx and edx registers to
* point to a temporary but writable memory range (Cache-As-RAM).
* ecx: the start of this temporary memory range,
* edx: the end of this range.
*/
/* stack grows down from top of CAR */
movl %edx, %esp
subl $4, %esp
xor %esi, %esi
jmp car_init_done
.global fsp_init_done
fsp_init_done:
/*
* We come here from fsp_continue() with eax pointing to the HOB list.
* Save eax to esi temporarily.
*/
movl %eax, %esi
car_init_done:
/*
* Re-initialize the ebp (BIST) to zero, as we already reach here
* which means we passed BIST testing before.
*/
xorl %ebp, %ebp
jmp car_init_ret
car_init_fail:
post_code(POST_CAR_FAILURE)
die:
hlt
jmp die
hlt
/*
* The function call before CAR initialization is tricky. It cannot
* be called using the 'call' instruction but only the 'jmp' with
* the help of a handcrafted stack in the ROM. The stack needs to
* contain the function return address as well as the parameters.
*/
.balign 4
find_fsp_header_romstack:
.long find_fsp_header_ret
.balign 4
temp_ram_init_romstack:
.long temp_ram_init_ret
.long temp_ram_init_params
temp_ram_init_params:
_dt_ucode_base_size:
/* These next two fields are filled in by ifdtool */
.globl ucode_base
ucode_base: /* Declared in micrcode.h */
.long 0 /* microcode base */
.long 0 /* microcode size */
.long CONFIG_SYS_MONITOR_BASE /* code region base */
.long CONFIG_SYS_MONITOR_LEN /* code region size */

View File

@@ -0,0 +1,100 @@
/*
* Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <errno.h>
#include <asm/io.h>
#include <asm/mrccache.h>
#include <asm/post.h>
#include <asm/processor.h>
#include <asm/fsp/fsp_support.h>
DECLARE_GLOBAL_DATA_PTR;
int print_cpuinfo(void)
{
post_code(POST_CPU_INFO);
return default_print_cpuinfo();
}
int fsp_init_phase_pci(void)
{
u32 status;
/* call into FspNotify */
debug("Calling into FSP (notify phase INIT_PHASE_PCI): ");
status = fsp_notify(NULL, INIT_PHASE_PCI);
if (status)
debug("fail, error code %x\n", status);
else
debug("OK\n");
return status ? -EPERM : 0;
}
void board_final_cleanup(void)
{
u32 status;
/* call into FspNotify */
debug("Calling into FSP (notify phase INIT_PHASE_BOOT): ");
status = fsp_notify(NULL, INIT_PHASE_BOOT);
if (status)
debug("fail, error code %x\n", status);
else
debug("OK\n");
return;
}
static __maybe_unused void *fsp_prepare_mrc_cache(void)
{
struct mrc_data_container *cache;
struct mrc_region entry;
int ret;
ret = mrccache_get_region(NULL, &entry);
if (ret)
return NULL;
cache = mrccache_find_current(&entry);
if (!cache)
return NULL;
debug("%s: mrc cache at %p, size %x checksum %04x\n", __func__,
cache->data, cache->data_size, cache->checksum);
return cache->data;
}
int x86_fsp_init(void)
{
void *nvs;
if (!gd->arch.hob_list) {
#ifdef CONFIG_ENABLE_MRC_CACHE
nvs = fsp_prepare_mrc_cache();
#else
nvs = NULL;
#endif
/*
* The first time we enter here, call fsp_init().
* Note the execution does not return to this function,
* instead it jumps to fsp_continue().
*/
fsp_init(CONFIG_FSP_TEMP_RAM_ADDR, BOOT_FULL_CONFIG, nvs);
} else {
/*
* The second time we enter here, adjust the size of malloc()
* pool before relocation. Given gd->malloc_base was adjusted
* after the call to board_init_f_init_reserve() in arch/x86/
* cpu/start.S, we should fix up gd->malloc_limit here.
*/
gd->malloc_limit += CONFIG_FSP_SYS_MALLOC_F_LEN;
}
return 0;
}

View File

@@ -0,0 +1,94 @@
/*
* Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <asm/fsp/fsp_support.h>
#include <asm/e820.h>
#include <asm/mrccache.h>
#include <asm/post.h>
DECLARE_GLOBAL_DATA_PTR;
int dram_init(void)
{
phys_size_t ram_size = 0;
const struct hob_header *hdr;
struct hob_res_desc *res_desc;
hdr = gd->arch.hob_list;
while (!end_of_hob(hdr)) {
if (hdr->type == HOB_TYPE_RES_DESC) {
res_desc = (struct hob_res_desc *)hdr;
if (res_desc->type == RES_SYS_MEM ||
res_desc->type == RES_MEM_RESERVED) {
ram_size += res_desc->len;
}
}
hdr = get_next_hob(hdr);
}
gd->ram_size = ram_size;
post_code(POST_DRAM);
#ifdef CONFIG_ENABLE_MRC_CACHE
gd->arch.mrc_output = fsp_get_nvs_data(gd->arch.hob_list,
&gd->arch.mrc_output_len);
#endif
return 0;
}
void dram_init_banksize(void)
{
gd->bd->bi_dram[0].start = 0;
gd->bd->bi_dram[0].size = gd->ram_size;
}
/*
* This function looks for the highest region of memory lower than 4GB which
* has enough space for U-Boot where U-Boot is aligned on a page boundary.
* It overrides the default implementation found elsewhere which simply
* picks the end of ram, wherever that may be. The location of the stack,
* the relocation address, and how far U-Boot is moved by relocation are
* set in the global data structure.
*/
ulong board_get_usable_ram_top(ulong total_size)
{
return fsp_get_usable_lowmem_top(gd->arch.hob_list);
}
unsigned install_e820_map(unsigned max_entries, struct e820entry *entries)
{
unsigned num_entries = 0;
const struct hob_header *hdr;
struct hob_res_desc *res_desc;
hdr = gd->arch.hob_list;
while (!end_of_hob(hdr)) {
if (hdr->type == HOB_TYPE_RES_DESC) {
res_desc = (struct hob_res_desc *)hdr;
entries[num_entries].addr = res_desc->phys_start;
entries[num_entries].size = res_desc->len;
if (res_desc->type == RES_SYS_MEM)
entries[num_entries].type = E820_RAM;
else if (res_desc->type == RES_MEM_RESERVED)
entries[num_entries].type = E820_RESERVED;
num_entries++;
}
hdr = get_next_hob(hdr);
}
/* Mark PCIe ECAM address range as reserved */
entries[num_entries].addr = CONFIG_PCIE_ECAM_BASE;
entries[num_entries].size = CONFIG_PCIE_ECAM_SIZE;
entries[num_entries].type = E820_RESERVED;
num_entries++;
return num_entries;
}

View File

@@ -0,0 +1,431 @@
/*
* Copyright (C) 2013, Intel Corporation
* Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com>
*
* SPDX-License-Identifier: Intel
*/
#include <common.h>
#include <asm/fsp/fsp_support.h>
#include <asm/post.h>
/**
* Compares two GUIDs
*
* If the GUIDs are identical then true is returned.
* If there are any bit differences in the two GUIDs, then false is returned.
*
* @guid1: A pointer to a 128 bit GUID.
* @guid2: A pointer to a 128 bit GUID.
*
* @retval true: guid1 and guid2 are identical.
* @retval false: guid1 and guid2 are not identical.
*/
static bool compare_guid(const struct efi_guid *guid1,
const struct efi_guid *guid2)
{
if (memcmp(guid1, guid2, sizeof(struct efi_guid)) == 0)
return true;
else
return false;
}
struct fsp_header *__attribute__((optimize("O0"))) find_fsp_header(void)
{
/*
* This function may be called before the a stack is established,
* so special care must be taken. First, it cannot declare any local
* variable using stack. Only register variable can be used here.
* Secondly, some compiler version will add prolog or epilog code
* for the C function. If so the function call may not work before
* stack is ready.
*
* GCC 4.8.1 has been verified to be working for the following codes.
*/
volatile register u8 *fsp asm("eax");
/* Initalize the FSP base */
fsp = (u8 *)CONFIG_FSP_ADDR;
/* Check the FV signature, _FVH */
if (((struct fv_header *)fsp)->sign == EFI_FVH_SIGNATURE) {
/* Go to the end of the FV header and align the address */
fsp += ((struct fv_header *)fsp)->ext_hdr_off;
fsp += ((struct fv_ext_header *)fsp)->ext_hdr_size;
fsp = (u8 *)(((u32)fsp + 7) & 0xFFFFFFF8);
} else {
fsp = 0;
}
/* Check the FFS GUID */
if (fsp &&
((struct ffs_file_header *)fsp)->name.data1 == FSP_GUID_DATA1 &&
((struct ffs_file_header *)fsp)->name.data2 == FSP_GUID_DATA2 &&
((struct ffs_file_header *)fsp)->name.data3 == FSP_GUID_DATA3 &&
((struct ffs_file_header *)fsp)->name.data4[0] == FSP_GUID_DATA4_0 &&
((struct ffs_file_header *)fsp)->name.data4[1] == FSP_GUID_DATA4_1 &&
((struct ffs_file_header *)fsp)->name.data4[2] == FSP_GUID_DATA4_2 &&
((struct ffs_file_header *)fsp)->name.data4[3] == FSP_GUID_DATA4_3 &&
((struct ffs_file_header *)fsp)->name.data4[4] == FSP_GUID_DATA4_4 &&
((struct ffs_file_header *)fsp)->name.data4[5] == FSP_GUID_DATA4_5 &&
((struct ffs_file_header *)fsp)->name.data4[6] == FSP_GUID_DATA4_6 &&
((struct ffs_file_header *)fsp)->name.data4[7] == FSP_GUID_DATA4_7) {
/* Add the FFS header size to find the raw section header */
fsp += sizeof(struct ffs_file_header);
} else {
fsp = 0;
}
if (fsp &&
((struct raw_section *)fsp)->type == EFI_SECTION_RAW) {
/* Add the raw section header size to find the FSP header */
fsp += sizeof(struct raw_section);
} else {
fsp = 0;
}
return (struct fsp_header *)fsp;
}
void fsp_continue(u32 status, void *hob_list)
{
post_code(POST_MRC);
assert(status == 0);
/* The boot loader main function entry */
fsp_init_done(hob_list);
}
void fsp_init(u32 stack_top, u32 boot_mode, void *nvs_buf)
{
struct fsp_config_data config_data;
fsp_init_f init;
struct fsp_init_params params;
struct fspinit_rtbuf rt_buf;
struct fsp_header *fsp_hdr;
struct fsp_init_params *params_ptr;
#ifdef CONFIG_FSP_USE_UPD
struct vpd_region *fsp_vpd;
struct upd_region *fsp_upd;
#endif
#ifdef CONFIG_DEBUG_UART
setup_internal_uart(1);
#endif
fsp_hdr = find_fsp_header();
if (fsp_hdr == NULL) {
/* No valid FSP info header was found */
panic("Invalid FSP header");
}
config_data.common.fsp_hdr = fsp_hdr;
config_data.common.stack_top = stack_top;
config_data.common.boot_mode = boot_mode;
#ifdef CONFIG_FSP_USE_UPD
/* Get VPD region start */
fsp_vpd = (struct vpd_region *)(fsp_hdr->img_base +
fsp_hdr->cfg_region_off);
/* Verify the VPD data region is valid */
assert(fsp_vpd->sign == VPD_IMAGE_ID);
fsp_upd = &config_data.fsp_upd;
/* Copy default data from Flash */
memcpy(fsp_upd, (void *)(fsp_hdr->img_base + fsp_vpd->upd_offset),
sizeof(struct upd_region));
/* Verify the UPD data region is valid */
assert(fsp_upd->terminator == UPD_TERMINATOR);
#endif
memset(&rt_buf, 0, sizeof(struct fspinit_rtbuf));
/* Override any configuration if required */
update_fsp_configs(&config_data, &rt_buf);
memset(&params, 0, sizeof(struct fsp_init_params));
params.nvs_buf = nvs_buf;
params.rt_buf = (struct fspinit_rtbuf *)&rt_buf;
params.continuation = (fsp_continuation_f)asm_continuation;
init = (fsp_init_f)(fsp_hdr->img_base + fsp_hdr->fsp_init);
params_ptr = &params;
post_code(POST_PRE_MRC);
/* Load GDT for FSP */
setup_fsp_gdt();
/*
* Use ASM code to ensure the register value in EAX & EDX
* will be passed into fsp_continue
*/
asm volatile (
"pushl %0;"
"call *%%eax;"
".global asm_continuation;"
"asm_continuation:;"
"movl 4(%%esp), %%eax;" /* status */
"movl 8(%%esp), %%edx;" /* hob_list */
"jmp fsp_continue;"
: : "m"(params_ptr), "a"(init)
);
/*
* Should never get here.
* Control will continue from fsp_continue.
* This line below is to prevent the compiler from optimizing
* structure intialization.
*
* DO NOT REMOVE!
*/
init(&params);
}
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 (!fsp_hdr)
fsp_hdr = (struct fsp_header *)find_fsp_header();
if (fsp_hdr == NULL) {
/* No valid FSP info header */
panic("Invalid FSP header");
}
notify = (fsp_notify_f)(fsp_hdr->img_base + fsp_hdr->fsp_notify);
params.phase = phase;
params_ptr = &params;
/*
* 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;
}
u32 fsp_get_usable_lowmem_top(const void *hob_list)
{
const struct hob_header *hdr;
struct hob_res_desc *res_desc;
phys_addr_t phys_start;
u32 top;
#ifdef CONFIG_FSP_BROKEN_HOB
struct hob_mem_alloc *res_mem;
phys_addr_t mem_base = 0;
#endif
/* Get the HOB list for processing */
hdr = hob_list;
/* * Collect memory ranges */
top = FSP_LOWMEM_BASE;
while (!end_of_hob(hdr)) {
if (hdr->type == HOB_TYPE_RES_DESC) {
res_desc = (struct hob_res_desc *)hdr;
if (res_desc->type == RES_SYS_MEM) {
phys_start = res_desc->phys_start;
/* Need memory above 1MB to be collected here */
if (phys_start >= FSP_LOWMEM_BASE &&
phys_start < (phys_addr_t)FSP_HIGHMEM_BASE)
top += (u32)(res_desc->len);
}
}
#ifdef CONFIG_FSP_BROKEN_HOB
/*
* Find out the lowest memory base address allocated by FSP
* for the boot service data
*/
if (hdr->type == HOB_TYPE_MEM_ALLOC) {
res_mem = (struct hob_mem_alloc *)hdr;
if (!mem_base)
mem_base = res_mem->mem_base;
if (res_mem->mem_base < mem_base)
mem_base = res_mem->mem_base;
}
#endif
hdr = get_next_hob(hdr);
}
#ifdef CONFIG_FSP_BROKEN_HOB
/*
* Check whether the memory top address is below the FSP HOB list.
* If not, use the lowest memory base address allocated by FSP as
* the memory top address. This is to prevent U-Boot relocation
* overwrites the important boot service data which is used by FSP,
* otherwise the subsequent call to fsp_notify() will fail.
*/
if (top > (u32)hob_list) {
debug("Adjust memory top address due to a buggy FSP\n");
top = (u32)mem_base;
}
#endif
return top;
}
u64 fsp_get_usable_highmem_top(const void *hob_list)
{
const struct hob_header *hdr;
struct hob_res_desc *res_desc;
phys_addr_t phys_start;
u64 top;
/* Get the HOB list for processing */
hdr = hob_list;
/* Collect memory ranges */
top = FSP_HIGHMEM_BASE;
while (!end_of_hob(hdr)) {
if (hdr->type == HOB_TYPE_RES_DESC) {
res_desc = (struct hob_res_desc *)hdr;
if (res_desc->type == RES_SYS_MEM) {
phys_start = res_desc->phys_start;
/* Need memory above 4GB to be collected here */
if (phys_start >= (phys_addr_t)FSP_HIGHMEM_BASE)
top += (u32)(res_desc->len);
}
}
hdr = get_next_hob(hdr);
}
return top;
}
u64 fsp_get_reserved_mem_from_guid(const void *hob_list, u64 *len,
struct efi_guid *guid)
{
const struct hob_header *hdr;
struct hob_res_desc *res_desc;
/* Get the HOB list for processing */
hdr = hob_list;
/* Collect memory ranges */
while (!end_of_hob(hdr)) {
if (hdr->type == HOB_TYPE_RES_DESC) {
res_desc = (struct hob_res_desc *)hdr;
if (res_desc->type == RES_MEM_RESERVED) {
if (compare_guid(&res_desc->owner, guid)) {
if (len)
*len = (u32)(res_desc->len);
return (u64)(res_desc->phys_start);
}
}
}
hdr = get_next_hob(hdr);
}
return 0;
}
u32 fsp_get_fsp_reserved_mem(const void *hob_list, u32 *len)
{
const struct efi_guid guid = FSP_HOB_RESOURCE_OWNER_FSP_GUID;
u64 length;
u32 base;
base = (u32)fsp_get_reserved_mem_from_guid(hob_list,
&length, (struct efi_guid *)&guid);
if ((len != 0) && (base != 0))
*len = (u32)length;
return base;
}
u32 fsp_get_tseg_reserved_mem(const void *hob_list, u32 *len)
{
const struct efi_guid guid = FSP_HOB_RESOURCE_OWNER_TSEG_GUID;
u64 length;
u32 base;
base = (u32)fsp_get_reserved_mem_from_guid(hob_list,
&length, (struct efi_guid *)&guid);
if ((len != 0) && (base != 0))
*len = (u32)length;
return base;
}
const struct hob_header *fsp_get_next_hob(uint type, const void *hob_list)
{
const struct hob_header *hdr;
hdr = hob_list;
/* Parse the HOB list until end of list or matching type is found */
while (!end_of_hob(hdr)) {
if (hdr->type == type)
return hdr;
hdr = get_next_hob(hdr);
}
return NULL;
}
const struct hob_header *fsp_get_next_guid_hob(const struct efi_guid *guid,
const void *hob_list)
{
const struct hob_header *hdr;
struct hob_guid *guid_hob;
hdr = hob_list;
while ((hdr = fsp_get_next_hob(HOB_TYPE_GUID_EXT,
hdr)) != NULL) {
guid_hob = (struct hob_guid *)hdr;
if (compare_guid(guid, &(guid_hob->name)))
break;
hdr = get_next_hob(hdr);
}
return hdr;
}
void *fsp_get_guid_hob_data(const void *hob_list, u32 *len,
struct efi_guid *guid)
{
const struct hob_header *guid_hob;
guid_hob = fsp_get_next_guid_hob(guid, hob_list);
if (guid_hob == NULL) {
return NULL;
} else {
if (len)
*len = get_guid_hob_data_size(guid_hob);
return get_guid_hob_data(guid_hob);
}
}
void *fsp_get_nvs_data(const void *hob_list, u32 *len)
{
const struct efi_guid guid = FSP_NON_VOLATILE_STORAGE_HOB_GUID;
return fsp_get_guid_hob_data(hob_list, len, (struct efi_guid *)&guid);
}
void *fsp_get_bootloader_tmp_mem(const void *hob_list, u32 *len)
{
const struct efi_guid guid = FSP_BOOTLOADER_TEMP_MEM_HOB_GUID;
return fsp_get_guid_hob_data(hob_list, len, (struct efi_guid *)&guid);
}