payloads/libpayload: Add support for RISC-V 64-bit architecture

This patch adds config ARCH_RISCV_RV64 to support build of riscv64
payloads. New files under arch/riscv contain:
- Basic ldscript and payload entry point.
- Functions for riscv64 io and cache operations.
- Default timer code based on mtime delegation.
- Default cb_header_ptr passing with device tree to payload.

Change-Id: Ieb3d456d5edda87a3a4886ccfc17a7824c630427
Signed-off-by: Ziang Wang <wangziang.ok@bytedance.com>
Signed-off-by: Dong Wei <weidong.wd@bytedance.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/89646
Reviewed-by: Maximilian Brune <maximilian.brune@9elements.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
Ziang Wang 2025-10-20 20:07:50 +08:00 committed by Matt DeVillier
commit 82f9c593ab
23 changed files with 693 additions and 6 deletions

View file

@ -127,6 +127,15 @@ config ARCH_ARM64
help
Support the ARM64 architecture
config ARCH_RISCV_RV64
bool "RISCV64"
depends on GPL
depends on EXPERIMENTAL
help
Support the RISC-V 64-bit architecture
Please note that support for riscv64 payload is experimental at this time, may have
fundamental change in the future.
config ARCH_MOCK
bool "Mock architecture (for unit tests)"
help
@ -523,3 +532,4 @@ source "arch/arm/Kconfig"
source "arch/arm64/Kconfig"
source "arch/x86/Kconfig"
source "arch/mock/Kconfig"
source "arch/riscv/Kconfig"

View file

@ -111,6 +111,7 @@ ARCHDIR-$(CONFIG_LP_ARCH_ARM) := arm
ARCHDIR-$(CONFIG_LP_ARCH_ARM64) := arm64
ARCHDIR-$(CONFIG_LP_ARCH_X86) := x86
ARCHDIR-$(CONFIG_LP_ARCH_MOCK) := mock
ARCHDIR-$(CONFIG_LP_ARCH_RISCV_RV64) := riscv
ARCH-y := $(ARCHDIR-y)
@ -121,6 +122,7 @@ ARCH-$(CONFIG_LP_ARCH_ARM64) := arm64
ARCH-$(CONFIG_LP_ARCH_X86_32) := x86_32
ARCH-$(CONFIG_LP_ARCH_X86_64) := x86_64
ARCH-$(CONFIG_LP_ARCH_MOCK) := mock
ARCH-$(CONFIG_LP_ARCH_RISCV_RV64) := riscv
# Five cases where we don't need fully populated $(obj) lists:
# 1. when no .config exists

View file

@ -41,6 +41,7 @@ ARCHDIR-$(CONFIG_LP_ARCH_ARM) := arm
ARCHDIR-$(CONFIG_LP_ARCH_ARM64) := arm64
ARCHDIR-$(CONFIG_LP_ARCH_X86) := x86
ARCHDIR-$(CONFIG_LP_ARCH_MOCK) := mock
ARCHDIR-$(CONFIG_LP_ARCH_RISCV_RV64) := riscv
DESTDIR ?= install
real-target: lib

View file

@ -0,0 +1,4 @@
## SPDX-License-Identifier: GPL-2.0-only
config ARCH_RISCV_RV64
select LITTLE_ENDIAN

View file

@ -0,0 +1,7 @@
## SPDX-License-Identifier: GPL-2.0-only
libc-y += head.S
libc-y += main.c sysinfo.c
libc-y += timer.c coreboot.c cache.c util.S virtual.c
CFLAGS += -mcmodel=medany

View file

@ -0,0 +1,13 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <arch/cache.h>
void tlb_invalidate_all(void)
{
asm volatile ("sfence.vma" : : : "memory");
}
void dcache_clean_invalidate_all(void)
{
}

View file

@ -0,0 +1,34 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <libpayload-config.h>
#include <libpayload.h>
#include <coreboot_tables.h>
/*
* This pointer is no longer set in head.S by default like in other arch, payloads should have
* their own ways to init it from any source before using it.
* e.g. If run after OpenSBI, this could be retrieved from fdt node.
* If run directly after Ramstage, could be from arg0.
*/
void *cb_header_ptr;
/* == Architecture specific == */
int cb_parse_arch_specific(struct cb_record *rec, struct sysinfo_t *info)
{
switch (rec->tag) {
default:
return 0;
}
return 1;
}
int get_coreboot_info(struct sysinfo_t *info)
{
return cb_parse_header(cb_header_ptr, 1, info);
}
void *get_cb_header_ptr(void)
{
return cb_header_ptr;
}

View file

@ -0,0 +1,24 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <arch/asm.h>
/*
* Our entry point
*/
ENTRY(_entry)
/* Setup new stack */
lla t0, 1f
ld sp, 0(t0)
//mov sp, x1
/* Let's rock. */
j start_main
ret
ENDPROC(_entry)
.section .entry, "ax", %progbits
.align 4
1:
.quad _stack

View file

@ -0,0 +1,65 @@
/* SPDX-License-Identifier: GPL-2.0-only */
OUTPUT_ARCH(riscv)
ENTRY(_entry)
SECTIONS
{
. = CONFIG_LP_BASE_ADDRESS;
. = ALIGN(16);
_start = .;
.text : {
_text = .;
*(.text._entry)
*(.text)
*(.text.*)
_etext = .;
}
.rodata : {
_rodata = .;
*(.rodata)
*(.rodata.*)
_erodata = .;
}
.data : {
_data = .;
*(.data)
*(.data.*)
_edata = .;
}
.bss : {
_bss = .;
*(.sbss)
*(.sbss.*)
*(.bss)
*(.bss.*)
*(COMMON)
_ebss = .;
/* Stack and heap */
. = ALIGN(16);
_heap = .;
. += CONFIG_LP_HEAP_SIZE;
. = ALIGN(16);
_eheap = .;
_estack = .;
. += CONFIG_LP_STACK_SIZE;
. = ALIGN(16);
_stack = .;
}
_end = .;
/DISCARD/ : {
*(.comment)
*(.note*)
}
}

View file

@ -0,0 +1,53 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <libpayload.h>
#include <endian.h>
#include <commonlib/device_tree.h>
uint64_t boot_hartid;
/**
* This is our C entry function - set up the system and jump into the payload entry point.
* Unlike other archs, we do not save a0~a2 from previous stage as global variables in head.S,
* but pass them to start_main directly as arg0, arg1, arg2 instead.
*
* arg0 is the preferred boot hart id.
* arg1 is a pointer to the DTB.
* This interface is static no matter whether previous stage is OpenSBI or coreboot Ramstage.
*
* arg2 is reserved for possible future usage.
*/
void start_main(uint64_t arg0, uint64_t arg1, uint64_t arg2);
void start_main(uint64_t arg0, uint64_t arg1, uint64_t arg2)
{
extern int main(int argc, char **argv);
extern void *cb_header_ptr;
/* cbtable pointer is stored in the dtb passed by previous stage */
boot_hartid = arg0;
const void *dtb = (const void *)arg1;
if (dtb && fdt_is_valid(dtb)) {
/* Look for the "coreboot-table" node in the DTB */
u32 node_offset = fdt_find_node_by_path(dtb, "/chosen", NULL, NULL);
if (node_offset) {
struct fdt_property prop;
if (fdt_read_prop(dtb, node_offset, "coreboot-table", &prop)) {
/* Extract the coreboot table pointer from the property */
cb_header_ptr = (void *)be64dec(prop.data);
}
}
}
/* Gather system information. */
lib_get_sysinfo();
#if !CONFIG(LP_SKIP_CONSOLE_INIT)
console_init();
#endif
/*
* Go to the entry point.
* In the future we may care about the return value.
*/
main(0, NULL);
printf("Unexpected return from payload\n");
}

View file

@ -0,0 +1,70 @@
/*
*
* Copyright (C) 2008 Advanced Micro Devices, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <libpayload-config.h>
#include <libpayload.h>
#include <coreboot_tables.h>
/**
* This is a global structure that is used through the library - we set it
* up initially with some dummy values - hopefully they will be overridden.
*/
struct sysinfo_t lib_sysinfo = {
.cpu_khz = 200,
};
int lib_get_sysinfo(void)
{
int ret;
/* Get the CPU speed (for delays). */
lib_sysinfo.cpu_khz = get_cpu_speed();
/* Get information from the coreboot tables,
* if they exist */
ret = get_coreboot_info(&lib_sysinfo);
if (!lib_sysinfo.n_memranges) {
/* If we can't get a good memory range, use the default. */
lib_sysinfo.n_memranges = 1;
lib_sysinfo.memrange[0].base = 0;
lib_sysinfo.memrange[0].size = 1024 * 1024;
lib_sysinfo.memrange[0].type = CB_MEM_RAM;
}
return ret;
}
void lib_sysinfo_get_memranges(struct memrange **ranges,
uint64_t *nranges)
{
*ranges = &lib_sysinfo.memrange[0];
*nranges = lib_sysinfo.n_memranges;
}

View file

@ -0,0 +1,53 @@
/*
*
* Copyright (C) 2008 Advanced Micro Devices, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/**
* @file riscv64/timer.c
* RISCV64 specific timer routines
*/
#include <libpayload.h>
/**
* @ingroup arch
* Global variable containing the speed of the processor in KHz.
*/
u32 cpu_khz;
/**
* Calculate the speed of the processor for use in delays.
*
* @return The CPU speed in kHz.
*/
unsigned int get_cpu_speed(void)
{
/* FIXME */
cpu_khz = 1000000U;
return cpu_khz;
}

View file

@ -0,0 +1,34 @@
/*
*
* Copyright (C) 2012 Google, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <arch/asm.h>
/* This function puts the system into a halt. */
ENTRY(halt)
j halt
ENDPROC(halt)

View file

@ -0,0 +1,36 @@
/*
*
* Copyright (C) 2008 coresystems GmbH
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <unistd.h>
unsigned long virtual_offset = 0;
int getpagesize(void)
{
return 4096;
}

View file

@ -64,6 +64,7 @@ libc-y += timer/generic.c
endif
libc-$(CONFIG_LP_TIMER_RDTSC) += timer/rdtsc.c
libc-$(CONFIG_LP_TIMER_ARM64_ARCH) += timer/arm64_arch_timer.c
libc-$(CONFIG_LP_TIMER_RISCV64_ARCH) += timer/riscv64_arch_timer.c
# Video console drivers
libc-$(CONFIG_LP_VIDEO_CONSOLE) += video/video.c

View file

@ -36,6 +36,12 @@ config TIMER_ARM64_ARCH
help
The cntfrq register needs to have been pre-initialized.
config TIMER_RISCV64_ARCH
bool "Architecture Timer for RISCV64 platforms"
depends on ARCH_RISCV_RV64
help
Payloads usually run in S-Mode, which has a time CSR for timer implementation.
config TIMER_RK3288
bool "Timer for Rockchip RK3288"

View file

@ -0,0 +1,16 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <libpayload.h>
uint64_t timer_hz(void)
{
/* FIXME */
return 1000000;
}
uint64_t timer_raw_value(void)
{
uint64_t value;
asm volatile ("csrr %0, time" : "=r" (value));
return value;
}

View file

@ -0,0 +1,23 @@
/*
*
* Copyright 2013 Google Inc.
*
*/
#ifndef __RISCV64_ASM_H
#define __RISCV64_ASM_H
#define ENDPROC(name) \
.type name, %function; \
END(name)
#define ENTRY(name) \
.section .text.name, "ax", %progbits; \
.global name; \
.align 2; \
name:
#define END(name) \
.size name, .-name
#endif /* __RISCV64_ASM_H */

View file

@ -0,0 +1,21 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef RISCV64_CACHE_H
#define RISCV64_CACHE_H
#include <stddef.h>
#include <stdint.h>
/* tlb invalidate all */
void tlb_invalidate_all(void);
void dcache_clean_invalidate_all(void);
/* Invalidate all of the instruction cache for PE to PoU. */
static inline void icache_invalidate_all(void)
{
__asm__ __volatile__("fence.i\n\t");
}
#endif /* RISCV64_CACHE_H */

View file

@ -0,0 +1,106 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef _ARCH_IO_H
#define _ARCH_IO_H
#include <stdint.h>
#include <arch/cache.h>
#define fence_i_r() __asm__ __volatile__("fence i,r" : : : "memory")
#define fence_ow_ow() __asm__ __volatile__("fence ow,ow" : : : "memory")
/*
* readb/w/l writeb/w/l are deprecated. use read8/16/32 and write8/16/32
* instead for future development.
*/
static inline uint8_t readb(volatile const void *_a)
{
return *(volatile const uint8_t *)_a;
fence_i_r();
}
static inline uint16_t readw(volatile const void *_a)
{
return *(volatile const uint16_t *)_a;
fence_i_r();
}
static inline uint32_t readl(volatile const void *_a)
{
return *(volatile const uint32_t *)_a;
fence_i_r();
}
static inline void writeb(uint8_t _v, volatile void *_a)
{
fence_ow_ow();
*(volatile uint8_t *)_a = _v;
}
static inline void writew(uint16_t _v, volatile void *_a)
{
fence_ow_ow();
*(volatile uint16_t *)_a = _v;
}
static inline void writel(uint32_t _v, volatile void *_a)
{
fence_ow_ow();
*(volatile uint32_t *)_a = _v;
}
/*
* TODO: make the existing code use read8/16/32 and write8/16/32 then remove
* readb/w/l and writeb/w/l.
*/
static inline uint8_t read8(volatile const void *addr)
{
return *(volatile uint8_t *)addr;
fence_i_r();
}
static inline uint16_t read16(volatile const void *addr)
{
return *(volatile uint16_t *)addr;
fence_i_r();
}
static inline uint32_t read32(volatile const void *addr)
{
return *(volatile uint32_t *)addr;
fence_i_r();
}
static inline uint64_t read64(volatile const void *addr)
{
return *(volatile uint64_t *)addr;
fence_i_r();
}
static inline void write8(volatile void *addr, uint8_t val)
{
fence_ow_ow();
*(volatile uint8_t *)addr = val;
}
static inline void write16(volatile void *addr, uint16_t val)
{
fence_ow_ow();
*(volatile uint16_t *)addr = val;
}
static inline void write32(volatile void *addr, uint32_t val)
{
fence_ow_ow();
*(volatile uint32_t *)addr = val;
}
static inline void write64(volatile void *addr, uint64_t val)
{
fence_ow_ow();
*(volatile uint64_t *)addr = val;
}
#endif

View file

@ -0,0 +1,33 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef _ARCH_TYPES_H
#define _ARCH_TYPES_H
typedef unsigned char uint8_t;
typedef unsigned char u8;
typedef signed char int8_t;
typedef signed char s8;
typedef unsigned short uint16_t;
typedef unsigned short u16;
typedef signed short int16_t;
typedef signed short s16;
typedef unsigned int uint32_t;
typedef unsigned int u32;
typedef signed int int32_t;
typedef signed int s32;
typedef unsigned long long uint64_t;
typedef unsigned long long u64;
typedef signed long long int64_t;
typedef signed long long s64;
typedef long time_t;
typedef long suseconds_t;
#ifndef NULL
#define NULL ((void *)0)
#endif
#endif

View file

@ -0,0 +1,14 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef _ARCH_VIRTUAL_H
#define _ARCH_VIRTUAL_H
extern unsigned long virtual_offset;
#define virt_to_phys(virt) ((unsigned long) (virt) + virtual_offset)
#define phys_to_virt(phys) ((void *) ((unsigned long) (phys) - virtual_offset))
#define virt_to_bus(addr) virt_to_phys(addr)
#define bus_to_virt(addr) phys_to_virt(addr)
#endif

View file

@ -8,12 +8,58 @@
#include <mcall.h>
#include <cbfs.h>
#include <console/console.h>
#include <commonlib/device_tree.h>
#include <cbmem.h>
struct arch_prog_run_args {
struct prog *prog;
struct prog *opensbi;
};
/*
* At the moment devicetree is the default handoff format to the payload instead of
* coreboot tables (on RISC-V only). That may change in the future, but for now we will put a
* reference to the coreboot tables inside the FDT (similar to what we do in ACPI).
*/
static void *add_coreboot_table_to_fdt(void *fdt)
{
if (!fdt || !fdt_is_valid(fdt)) {
printk(BIOS_ERR, "Invalid FDT provided\n");
return fdt;
}
void *coreboot_table = cbmem_find(CBMEM_ID_CBTABLE);
if (!coreboot_table) {
printk(BIOS_ERR, "coreboot table not found in CBMEM\n");
return fdt;
}
struct device_tree *tree = fdt_unflatten(fdt);
if (!tree) {
printk(BIOS_ERR, "Failed to unflatten FDT\n");
return fdt;
}
struct device_tree_node *chosen_node = dt_find_node_by_path(tree, "/chosen", NULL, NULL, 1);
if (!chosen_node) {
printk(BIOS_ERR, "Failed to find or create /chosen node\n");
return fdt;
}
printk(BIOS_INFO, "Adding cbtable@%p to fdt\n", coreboot_table);
dt_add_u64_prop(chosen_node, "coreboot-table", (uint64_t)(uintptr_t)coreboot_table);
size_t next_size = dt_flat_size(tree);
void *next_fdt = malloc(next_size);
if (!next_fdt) {
printk(BIOS_ERR, "Failed to allocate memory for next-stage FDT\n");
return fdt;
}
dt_flatten(tree, next_fdt);
return next_fdt;
}
/*
* A pointer to the Flattened Device Tree passed to coreboot by the boot ROM.
* Presumably this FDT is also in ROM.
@ -51,14 +97,29 @@ void arch_prog_run(struct prog *prog)
args.prog = prog;
/* In case of OpenSBI we have to load it before resuming all HARTs */
if (ENV_RAMSTAGE && CONFIG(RISCV_OPENSBI)) {
struct prog sbi = PROG_INIT(PROG_OPENSBI, CONFIG_CBFS_PREFIX"/opensbi");
if (ENV_RAMSTAGE) {
int hart_count = CONFIG_MAX_CPUS;
if (CONFIG(RISCV_GET_HART_COUNT_AT_RUNTIME))
hart_count = smp_get_hart_count();
if (!selfload_check(&sbi, BM_MEM_OPENSBI))
die("OpenSBI load failed");
/* Embed coreboot table pointer into fdt, so that payload can find it. */
void *fdt = HLS()->fdt;
void *next_fdt = add_coreboot_table_to_fdt(fdt);
args.opensbi = &sbi;
/* Update per hart's fdt with "coreboot-table" node embedded */
for (int i = 0; i < hart_count; i++) {
OTHER_HLS(i)->fdt = next_fdt;
}
/* In case of OpenSBI we have to load it before resuming all HARTs */
if (CONFIG(RISCV_OPENSBI)) {
struct prog sbi = PROG_INIT(PROG_OPENSBI, CONFIG_CBFS_PREFIX"/opensbi");
if (!selfload_check(&sbi, BM_MEM_OPENSBI))
die("OpenSBI load failed");
args.opensbi = &sbi;
}
}
smp_resume((void (*)(void *))do_arch_prog_run, &args);