Fixes for NXP T1024 and booting Integrity OS:

* Fixed PPC spin table based on ePAPR 1.1.
* Added flattened device tree (FDT) support. Setting required FDT fields per ePAPR 1.1.
* Added Frame Manager microcode upload.
* Fixed CPLD and setting QE clock.
* Added support for setting logical device numbers and updated device tree.
* Fixed QUICC Engine base address (was incorrect, should be 0x140000).
* Fixed "cpu-release-addr" to use 64-bit value.
* Added secondary cached boot page.
* Added L2 cache support to multi-core.
* Added flattened device tree parser tool for testing (`make fdt-parser` and `tools/fdt-parser/fdt-parser`).
* Added checks for FDT header.
* Added automated test case for NXP T1024 FDT.
pull/400/head
David Garske 2024-01-05 14:13:31 -08:00 committed by Daniele Lacamera
parent a020852732
commit 83283c6cf7
25 changed files with 2251 additions and 379 deletions

View File

@ -0,0 +1,46 @@
name: Test parsing tools (elf and fdt)
on:
push:
branches: [ 'master', 'main', 'release/**' ]
pull_request:
branches: [ '*' ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
submodules: true
- name: Install cross compilers
run: |
sudo apt-get install -y gcc-arm-none-eabi gcc-powerpc-linux-gnu
- name: make distclean
run: |
make distclean
- name: Select config
run: |
cp config/examples/nxp-t1024.config .config
- name: Build wolfBoot
run: |
make
- name: Build tools
run: |
make elf-parser
make fdt-parser
- name: Run elf-parser test
run: |
./tools/elf-parser/elf-parser
- name: Run fdt-parser test (nxp_t1024.dtb)
run: |
./tools/fdt-parser/fdt-parser ./tools/fdt-parser/nxp_t1024.dtb -t

1
.gitignore vendored
View File

@ -100,6 +100,7 @@ tools/uart-flash-server/ufserver
tools/unit-tests/unit-parser
tools/bin-assemble/bin-assemble
tools/elf-parser/elf-parser
tools/fdt-parser/fdt-parser
tools/tpm/rot
tools/tpm/pcr_read
tools/tpm/pcr_reset

View File

@ -276,6 +276,7 @@ utilsclean: clean
$(Q)$(MAKE) -C tools/delta -s clean
$(Q)$(MAKE) -C tools/bin-assemble -s clean
$(Q)$(MAKE) -C tools/elf-parser -s clean
$(Q)$(MAKE) -C tools/fdt-parser -s clean
$(Q)$(MAKE) -C tools/check_config -s clean
$(Q)$(MAKE) -C tools/test-expect-version -s clean
$(Q)$(MAKE) -C tools/test-update-server -s clean
@ -313,6 +314,10 @@ elf-parser:
@$(MAKE) -C tools/elf-parser -s clean
@$(MAKE) -C tools/elf-parser
fdt-parser:
@$(MAKE) -C tools/fdt-parser -s clean
@$(MAKE) -C tools/fdt-parser
config: FORCE
$(MAKE) -C config

View File

@ -424,6 +424,7 @@ ifeq ($(TARGET),nxp_t1024)
LDFLAGS+=-Wl,--hash-style=both # generate both sysv and gnu symbol hash table
LDFLAGS+=-Wl,--as-needed # remove weak functions not used
OBJS+=src/boot_ppc_mp.o # support for spin table
OBJS+=src/fdt.o
UPDATE_OBJS:=src/update_ram.o
ifeq ($(SPMATH),1)
MATH_OBJS += ./lib/wolfssl/wolfcrypt/src/sp_c32.o
@ -445,6 +446,7 @@ ifeq ($(TARGET),nxp_t2080)
LDFLAGS+=-Wl,--hash-style=both # generate both sysv and gnu symbol hash table
LDFLAGS+=-Wl,--as-needed # remove weak functions not used
UPDATE_OBJS:=src/update_ram.o
OBJS+=src/fdt.o
ifeq ($(SPMATH),1)
MATH_OBJS += ./lib/wolfssl/wolfcrypt/src/sp_c32.o
else
@ -750,6 +752,7 @@ BOOT_IMG?=test-app/image.bin
## Update mechanism
ifeq ($(ARCH),AARCH64)
CFLAGS+=-DMMU -DWOLFBOOT_DUALBOOT
OBJS+=src/fdt.o
UPDATE_OBJS:=src/update_ram.o
endif
ifeq ($(DUALBANK_SWAP),1)

View File

@ -22,7 +22,7 @@
#include "target.h"
#include "image.h"
#include "printf.h"
#include <string.h>
#include "string.h"
#include "nxp_ppc.h"
@ -30,14 +30,16 @@
/* #define DEBUG_EXT_FLASH */
/* #define DEBUG_ESPI 1 */
/* Tests */
/* #define TEST_DDR */
/* #define TEST_FLASH */
/* #define TEST_TPM */
#define ENABLE_ELBC /* Flash Controller */
#define ENABLE_BUS_CLK_CALC
#ifndef BUILD_LOADER_STAGE1
/* Tests */
#if 0
#define TEST_DDR
#define TEST_FLASH
#define TEST_TPM
#endif
#define ENABLE_PCIE
#define ENABLE_CPLD /* Board Configuration and Status Registers (BCSR) */
#define ENABLE_CONF_IO
@ -50,6 +52,7 @@
/* #define ENABLE_QE_CRC32 */ /* CRC32 check on QE disabled by default */
#endif
/* Foward declarations */
#if defined(ENABLE_DDR) && defined(TEST_DDR)
static int test_ddr(void);
#endif
@ -421,8 +424,8 @@ enum elbc_amask_sizes {
#define DDR_SDRAM_CLK_CNTL ((volatile uint32_t*)(DDR_BASE + 0x130)) /* DDR SDRAM clock control */
#define DDR_SDRAM_CFG_MEM_EN 0x80000000 /* SDRAM interface logic is enabled */
#define DDR_SDRAM_CFG_32_BE 0x00080000
#define DDR_SDRAM_CFG_ECC_EN 0x20000000
#define DDR_SDRAM_CFG_32_BE 0x00080000
#define DDR_SDRAM_CFG_2_D_INIT 0x00000010 /* data initialization in progress */
#define DDR_SDRAM_CFG_BI 0x00000001 /* Bypass initialization */
@ -894,7 +897,7 @@ static void hal_ddr_init(void)
/* Map LAW for DDR */
set_law(6, 0, DDR_ADDRESS, LAW_TRGT_DDR, LAW_SIZE_512MB, 0);
/* If DDR is not already enabled */
/* If DDR is already enabled then just return */
if ((get32(DDR_SDRAM_CFG) & DDR_SDRAM_CFG_MEM_EN)) {
return;
}
@ -1379,7 +1382,7 @@ static int hal_qe_init(void)
set32(QE_SDMA_SDAQMR, 0);
/* Allocate 2KB temporary buffer for sdma */
sdma_base = 0;
sdma_base = 0; /* offset in QE_MURAM */
set32(QE_SDMA_SDEBCR, sdma_base & QE_SDEBCR_BA_MASK);
/* Clear sdma status */
@ -1401,28 +1404,25 @@ static int hal_qe_init(void)
#ifdef ENABLE_MP
/* from boot_ppc_core.S */
extern uint32_t _mp_page_start;
extern uint32_t _secondary_start_page;
extern uint32_t _second_half_boot_page;
extern uint32_t _spin_table;
extern uint32_t _spin_table_addr;
extern uint32_t _bootpg_addr;
/* Startup additional cores with spin table and synchronize the timebase */
static void hal_mp_up(uint32_t bootpg)
{
uint32_t up, cpu_up_mask, whoami, bpcr, devdisr;
uint8_t *spin_table_addr;
int timeout = 50, i;
/* Get current running core number */
whoami = get32(PIC_WHOAMI);
/* Calculate location of spin table in BPTR */
spin_table_addr = (uint8_t*)(BOOT_ROM_ADDR +
((uint32_t)&_spin_table - (uint32_t)&_mp_page_start));
wolfBoot_printf("MP: Starting core 2 (boot page %p, spin table %p)\n",
bootpg, (uint32_t)&_spin_table);
wolfBoot_printf("MP: Starting core 2 (spin table %p)\n",
spin_table_addr);
/* Set the boot page translation reigster */
/* Set the boot page translation register */
set32(RESET_BPTR, RESET_BPTR_EN | RESET_BPTR_BOOTPG(bootpg));
/* Disable time base on inactive core */
@ -1444,8 +1444,8 @@ static void hal_mp_up(uint32_t bootpg)
cpu_up_mask = (1 << whoami);
while (timeout) {
for (i = 0; i < CPU_NUMCORES; i++) {
uint32_t* entry = (uint32_t*)(spin_table_addr +
(i * ENTRY_SIZE) + ENTRY_ADDR_LOWER);
uint32_t* entry = (uint32_t*)(
(uint8_t*)&_spin_table + (i * ENTRY_SIZE) + ENTRY_ADDR_LOWER);
if (*entry) {
cpu_up_mask |= (1 << i);
}
@ -1480,23 +1480,29 @@ static void hal_mp_up(uint32_t bootpg)
static void hal_mp_init(void)
{
uint32_t *fixup = (uint32_t*)&_mp_page_start;
uint32_t *fixup = (uint32_t*)&_secondary_start_page;
uint32_t bootpg;
int i_tlb = 0; /* always 0 */
size_t i;
const uint32_t *s;
uint32_t *d;
const volatile uint32_t *s;
volatile uint32_t *d;
/* Assign virtual boot page at end of DDR */
bootpg = DDR_ADDRESS + DDR_SIZE - BOOT_ROM_SIZE;
/* Store the boot page address for use by additional CPU cores */
_bootpg_addr = bootpg;
_bootpg_addr = (uint32_t)&_second_half_boot_page;
/* map reset page to bootpg so we can copy code there */
/* Store location of spin table for other cores */
_spin_table_addr = (uint32_t)&_spin_table;
/* Flush bootpg before copying to invalidate any stale cache lines */
flush_cache(bootpg, BOOT_ROM_SIZE);
/* Map reset page to bootpg so we can copy code there */
disable_tlb1(i_tlb);
set_tlb(1, i_tlb, BOOT_ROM_ADDR, bootpg, 0, /* tlb, epn, rpn */
MAS3_SX | MAS3_SW | MAS3_SR, MAS2_I, /* perms, wimge */
set_tlb(1, i_tlb, BOOT_ROM_ADDR, bootpg, 0, /* tlb, epn, rpn, urpn */
(MAS3_SX | MAS3_SW | MAS3_SR), (MAS2_I | MAS2_G), /* perms, wimge */
0, BOOKE_PAGESZ_4K, 1); /* ts, esel, tsize, iprot */
/* copy startup code to virtually mapped boot address */

View File

@ -39,6 +39,8 @@ SECTIONS
{
_start_vector = .;
KEEP(*(.isr_vector))
. = ALIGN(256);
KEEP(*(.bootmp))
*(.text*)
*(.rodata*)
*(.sdata*)

View File

@ -32,7 +32,9 @@
#define CCSRBAR_SIZE BOOKE_PAGESZ_1M
#define ENABLE_DDR
#ifndef DDR_SIZE
#define DDR_SIZE (512UL * 1024UL * 1024UL)
#endif
/* Memory used for transferring blocks to/from NAND.
* Maps to eLBC FCM internal 8KB region (by hardware) */
@ -62,8 +64,9 @@
#elif defined(PLATFORM_nxp_t1024)
/* NXP T1024 */
#define CPU_NUMCORES 2
#define CORE_E5500
#define CPU_NUMCORES 2
#define CORES_PER_CLUSTER 1
#define LAW_MAX_ENTRIES 16
#define CCSRBAR_DEF (0xFE000000) /* T1024RM 4.4.1 default base */
@ -86,7 +89,9 @@
#endif
#define ENABLE_DDR
#ifndef DDR_SIZE
#define DDR_SIZE (2048ULL * 1024ULL * 1024ULL)
#endif
#define FLASH_BASE_ADDR 0xEC000000UL
#define FLASH_BASE_PHYS_HIGH 0xFULL
@ -97,9 +102,11 @@
#elif defined(PLATFORM_nxp_t2080)
/* NXP T0280 */
#define CPU_NUMCORES 4
#define CORE_E6500
#define CPU_NUMCORES 4
#define CORES_PER_CLUSTER 4
#define LAW_MAX_ENTRIES 32
#define ENABLE_PPC64
#define CCSRBAR_DEF (0xFE000000UL) /* T2080RM 4.3.1 default base */
#define CCSRBAR_SIZE BOOKE_PAGESZ_16M
@ -122,7 +129,9 @@
#define ENABLE_INTERRUPTS
#define ENABLE_DDR
#ifndef DDR_SIZE
#define DDR_SIZE (8192UL * 1024UL * 1024UL)
#endif
#define FLASH_BASE_ADDR 0xE8000000UL
#define FLASH_BASE_PHYS_HIGH 0x0ULL
@ -424,11 +433,32 @@
/* L2 Cache */
#if defined(CORE_E6500)
/* L2 Cache Control - E6500CORERM 2.2.3 Memory-mapped registers (MMRs) */
#define L2_CLUSTER_BASE(n) (CCSRBAR + 0xC20000 + (n * 0x40000))
#define L2PID(n) (0x200 + (n * 0x10)) /* L2 Cache Partitioning ID */
#define L2PIR(n) (0x208 + (n * 0x10)) /* L2 Cache Partitioning Allocation */
#define L2PWR(n) (0x20C + (n * 0x10)) /* L2 Cache Partitioning Way */
/* MMRs */
#define L2CSR0 0x000 /* L2 Cache Control and Status 0 */
#define L2CSR1 0x004 /* L2 Cache Control and Status 1 */
#define L2CFG0 0x008 /* L2 Cache Configuration */
#else
#ifdef CORE_E5500
/* L2 Cache Control - E5500RM 2.15 L2 Cache Registers */
#define L2_BASE (CCSRBAR + 0x20000)
#else
/* E500 */
#define L2_BASE (CCSRBAR + 0x20000)
#define L2CTL 0x000 /* 0xFFE20000 - L2 control register */
#define L2SRBAR0 0x100 /* 0xFFE20100 - L2 SRAM base address register */
#define L2CTL_EN (1 << 31) /* L2 enable */
#define L2CTL_INV (1 << 30) /* L2 invalidate */
#define L2CTL_SIZ(n) (((n) & 0x3) << 28) /* 2=256KB (always) */
#define L2CTL_L2SRAM(n) (((n) & 0x7) << 16) /* 1=all 256KB, 2=128KB */
#endif
/* SPR */
#define L2CFG0 0x207 /* L2 Cache Configuration Register 0 */
#define L2CSR0 0x3F9 /* L2 Data Cache Control and Status Register 0 */
@ -441,8 +471,6 @@
#define L2CSR0_L2PE 0x40000000 /* L2 Cache Parity/ECC Enable */
#define L2CSR0_L2E 0x80000000 /* L2 Cache Enable */
#define L2CSR0_L2E 0x80000000 /* L2 Cache Enable */
#define L2CSR0_L2PE 0x40000000 /* L2 Cache Parity/ECC Enable */
#define L2CSR0_L2WP 0x1c000000 /* L2 I/D Way Partioning */
#define L2CSR0_L2CM 0x03000000 /* L2 Cache Coherency Mode */
#define L2CSR0_L2FI 0x00200000 /* L2 Cache Flash Invalidate */
@ -702,17 +730,24 @@ extern void dcache_disable(void);
#define r31 31
#endif
/* ePAPR 1.1 spin table */
/* For multiple core spin table communication */
#define EPAPR_MAGIC (0x45504150)
/* The spin table must be WING 0b001x (memory-coherence required) */
/* For older PPC compat use dcbf to flush spin table entry */
/* Note: spin-table must be cache-line aligned in memory */
#define EPAPR_MAGIC (0x45504150) /* Book III-E CPUs */
#define ENTRY_ADDR_UPPER 0
#define ENTRY_ADDR_LOWER 4
#define ENTRY_R3_UPPER 8
#define ENTRY_R3_LOWER 12
#define ENTRY_RESV 16
#define ENTRY_PIR 20
/* not used for ePAPR 1.1 */
#define ENTRY_R6_UPPER 24
#define ENTRY_R6_LOWER 28
#define ENTRY_SIZE 32
#define ENTRY_SIZE 64
#endif /* !_NXP_PPC_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -6,7 +6,7 @@ MEMORY
{
/* DDR4 - 2GB (offset by destination address and 4KB boot region) */
DRAM (rwx) : ORIGIN = @WOLFBOOT_STAGE1_LOAD_ADDR@,
LENGTH = 0x7FFFFFFF - @WOLFBOOT_STAGE1_LOAD_ADDR@
LENGTH = 0x7FFFFFFF - 4K - @WOLFBOOT_STAGE1_LOAD_ADDR@
/* L1 SRAM - 16KB */
L1RAM (rwx) : ORIGIN = 0xF8F80000, LENGTH = 0x4000
@ -37,6 +37,7 @@ SECTIONS
KEEP(*(.isr_vector))
. = ALIGN(256);
_start_text = .;
KEEP(*(.bootmp))
*(.text*)
*(.rodata*)
*(.sdata*)

View File

@ -459,14 +459,14 @@ static void hal_cpld_init(void)
{
#ifdef ENABLE_CPLD
/* CPLD IFC Timing Parameters */
IFC_FTIM0(3) = (IFC_FTIM0_GPCM_TACSE(16) |
IFC_FTIM0_GPCM_TEADC(16) |
IFC_FTIM0_GPCM_TEAHC(16));
IFC_FTIM1(3) = (IFC_FTIM1_GPCM_TACO(16) |
IFC_FTIM1_GPCM_TRAD(31));
IFC_FTIM2(3) = (IFC_FTIM2_GPCM_TCS(16) |
IFC_FTIM2_GPCM_TCH(8) |
IFC_FTIM2_GPCM_TWP(31));
IFC_FTIM0(3) = (IFC_FTIM0_GPCM_TACSE(16UL) |
IFC_FTIM0_GPCM_TEADC(16UL) |
IFC_FTIM0_GPCM_TEAHC(16UL));
IFC_FTIM1(3) = (IFC_FTIM1_GPCM_TACO(16UL) |
IFC_FTIM1_GPCM_TRAD(31UL));
IFC_FTIM2(3) = (IFC_FTIM2_GPCM_TCS(16UL) |
IFC_FTIM2_GPCM_TCH(8UL) |
IFC_FTIM2_GPCM_TWP(31UL));
IFC_FTIM3(3) = 0;
/* CPLD IFC Definitions (CS3) */

View File

@ -41,6 +41,7 @@ SECTIONS
_start_vector = .;
KEEP(*(.isr_vector))
. = ALIGN(256);
KEEP(*(.bootmp))
*(.text*)
*(.rodata*)
*(.sdata*)

152
include/fdt.h 100644
View File

@ -0,0 +1,152 @@
/* fdt.h
*
* Functions to help with flattened device tree (DTB) parsing
*
*
* Copyright (C) 2023 wolfSSL Inc.
*
* This file is part of wolfBoot.
*
* wolfBoot is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfBoot is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#ifndef FDT_H
#define FDT_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#define FDT_MAGIC 0xD00DFEEDUL
#define FDT_SW_MAGIC (uint32_t)(~FDT_MAGIC) /* marker for run-time creation/edit of FDT */
struct fdt_header {
uint32_t magic;
uint32_t totalsize;
uint32_t off_dt_struct;
uint32_t off_dt_strings;
uint32_t off_mem_rsvmap;
uint32_t version;
uint32_t last_comp_version;
uint32_t boot_cpuid_phys;
uint32_t size_dt_strings;
uint32_t size_dt_struct;
};
struct fdt_reserve_entry {
uint64_t address;
uint64_t size;
};
struct fdt_prop {
uint32_t len;
uint32_t nameoff;
};
struct fdt_node_header {
uint32_t tag;
char name[0];
};
struct fdt_property {
uint32_t tag;
uint32_t len;
uint32_t nameoff;
char data[0];
};
#define FDT_TAGSIZE sizeof(uint32_t)
#define FDT_ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
#define FDT_TAGALIGN(x) (FDT_ALIGN((x), FDT_TAGSIZE))
#define FDT_FIRST_SUPPORTED_VERSION 0x10
#define FDT_LAST_SUPPORTED_VERSION 0x11
#define FDT_BEGIN_NODE 0x00000001UL
#define FDT_END_NODE 0x00000002UL
#define FDT_PROP 0x00000003UL
#define FDT_NOP 0x00000004UL
#define FDT_END 0x00000009UL
#define FDT_ERR_BADMAGIC 1
#define FDT_ERR_BADVERSION 2
#define FDT_ERR_BADSTRUCTURE 3
#define FDT_ERR_BADOFFSET 4
#define FDT_ERR_BADSTATE 5
#define FDT_ERR_NOTFOUND 6
#define FDT_ERR_NOSPACE 7
#define FDT_ERR_TRUNCATED 8
#define FDT_ERR_INTERNAL 9
uint32_t cpu_to_fdt32(uint32_t x);
uint64_t cpu_to_fdt64(uint64_t x);
uint32_t fdt32_to_cpu(uint32_t x);
uint64_t fdt64_to_cpu(uint64_t x);
#define fdt_get_header(fdt, field) (fdt32_to_cpu(((const struct fdt_header *)(fdt))->field))
#define fdt_magic(fdt) (fdt_get_header(fdt, magic))
#define fdt_totalsize(fdt) (fdt_get_header(fdt, totalsize))
#define fdt_off_dt_struct(fdt) (fdt_get_header(fdt, off_dt_struct))
#define fdt_off_dt_strings(fdt) (fdt_get_header(fdt, off_dt_strings))
#define fdt_off_mem_rsvmap(fdt) (fdt_get_header(fdt, off_mem_rsvmap))
#define fdt_version(fdt) (fdt_get_header(fdt, version))
#define fdt_last_comp_version(fdt) (fdt_get_header(fdt, last_comp_version))
#define fdt_boot_cpuid_phys(fdt) (fdt_get_header(fdt, boot_cpuid_phys))
#define fdt_size_dt_strings(fdt) (fdt_get_header(fdt, size_dt_strings))
#define fdt_size_dt_struct(fdt) (fdt_get_header(fdt, size_dt_struct))
#define fdt_set_header(fdt, field, val) (((struct fdt_header *)fdt)->field = cpu_to_fdt32(val))
#define fdt_set_magic(fdt, val) (fdt_set_header(fdt, magic, (val)))
#define fdt_set_totalsize(fdt, val) (fdt_set_header(fdt, totalsize, (val)))
#define fdt_set_off_dt_struct(fdt, val) (fdt_set_header(fdt, off_dt_struct, (val)))
#define fdt_set_off_dt_strings(fdt, val) (fdt_set_header(fdt, off_dt_strings, (val)))
#define fdt_set_off_mem_rsvmap(fdt, val) (fdt_set_header(fdt, off_mem_rsvmap, (val)))
#define fdt_set_version(fdt, val) (fdt_set_header(fdt, version, (val)))
#define fdt_set_last_comp_version(fdt, val) (fdt_set_header(fdt, last_comp_version, (val)))
#define fdt_set_boot_cpuid_phys(fdt, val) (fdt_set_header(fdt, boot_cpuid_phys, (val)))
#define fdt_set_size_dt_strings(fdt, val) (fdt_set_header(fdt, size_dt_strings, (val)))
#define fdt_set_size_dt_struct(fdt, val) (fdt_set_header(fdt, size_dt_struct, (val)))
int fdt_check_header(const void *fdt);
int fdt_next_node(const void *fdt, int offset, int *depth);
int fdt_first_property_offset(const void *fdt, int nodeoffset);
int fdt_next_property_offset(const void *fdt, int offset);
const struct fdt_property *fdt_get_property_by_offset(const void *fdt, int offset, int *lenp);
const char* fdt_get_name(const void *fdt, int nodeoffset, int *len);
const char* fdt_get_string(const void *fdt, int stroffset, int *lenp);
const void *fdt_getprop(const void *fdt, int nodeoffset, const char *name, int *lenp);
int fdt_setprop(void *fdt, int nodeoffset, const char *name, const void *val, int len);
int fdt_find_devtype(void* fdt, int startoff, const char* node);
int fdt_node_check_compatible(const void *fdt, int nodeoffset, const char *compatible);
int fdt_node_offset_by_compatible(const void *fdt, int startoffset, const char *compatible);
/* helpers to fix/append a property to a node */
int fdt_fixup_str(void* fdt, int off, const char* node, const char* name, const char* str);
int fdt_fixup_val(void* fdt, int off, const char* node, const char* name, uint32_t val);
int fdt_fixup_val64(void* fdt, int off, const char* node, const char* name, uint64_t val);
int fdt_shrink(void* fdt);
#ifdef __cplusplus
}
#endif
#endif /* !FDT_H */

View File

@ -668,7 +668,8 @@ static inline int wb_flash_write_verify_word(struct wolfBoot_image *img,
#define UBOOT_IMG_HDR_SZ 64
/* --- Flattened Device Tree Blob */
#define UBOOT_FDT_MAGIC 0xEDFE0DD0UL
#include "fdt.h"
#ifndef EXT_ENCRYPTED
#define WOLFBOOT_MAX_SPACE (WOLFBOOT_PARTITION_SIZE - \

View File

@ -105,6 +105,12 @@ void __attribute((weak)) hal_early_init(void)
{
}
#ifdef MMU
int __attribute((weak)) hal_dts_fixup(void* dts_addr)
{
return 0;
}
#endif
void boot_entry_C(void)
{
@ -172,6 +178,10 @@ void do_boot(const uint32_t *app_offset)
uintptr_t r7, uintptr_t r8, uintptr_t r9);
boot_entry entry = (boot_entry)app_offset;
#ifdef MMU
hal_dts_fixup((uint32_t*)dts_offset);
#endif
#ifndef BUILD_LOADER_STAGE1
/* invalidate cache */
flush_cache((uint32_t)app_offset, L1_CACHE_SZ);

View File

@ -25,46 +25,54 @@
#include "hal/nxp_ppc.h"
#define TORESET(x) (x - _mp_page_start + BOOT_ROM_ADDR)
#ifndef INTVEC_ADDR
/* workaround to use isr_empty for all interrupts, for real IRQ's adjust the
* offset and define additional interrupts at those offsets */
#define INTVEC_ADDR(n) isr_empty@l
#endif
#define TORESET(x) (x - _secondary_start_page + BOOT_ROM_ADDR)
/* Additional cores (mp) assembly code for core minimum startup and spin table.
* All code must fit in 4KB, which gets virtually mapped via the TLB1 (MMU) and
* loaded by core 0. Spin table entry TLB1(0) mapped for work is 64MB. */
.globl _mp_page_start
.align 12
_mp_page_start:
* loaded by core 0. Spin table entry TLB1(0) mapped for work is 64MB.
*/
.section .bootmp, "ax"
.globl _secondary_start_page
_secondary_start_page:
/* Time base, MAS7 and machine check pin enable */
lis r0, (HID0_EMCP | HID0_TBEN | HID0_ENMAS7)@h
ori r0, r0, (HID0_EMCP | HID0_TBEN | HID0_ENMAS7)@l
mtspr SPRN_HID0, r0
#ifdef CORE_E500
/* Set addr streaming & broadcast
* and optimized sync instruction (if rev 5.0 or greater) */
li r0, (HID1_ASTME | HID1_ABE)@l
mfspr r3, SPRN_PVR
andi. r3, r3, 0xFF
cmpwi r3, 0x50@l /* if rev 5.0 or greater set MBDD */
blt 1f
ori r0, r0, HID1_MBDD@l
1: mtspr SPRN_HID1, r0
#endif
branch_prediction:
/* enable branch prediction */
lis r0, (BUCSR_ENABLE)@h
ori r0, r0, (BUCSR_ENABLE)@l
mtspr SPRN_BUCSR, r0
/* Ensure TB is 0 */
/* Ensure Timebase is reset to 0 */
li r3, 0
mttbl r3
mttbu r3
/* Enable/invalidate the I-Cache */
lis r2, (L1CSR_CFI|L1CSR_CLFC)@h
ori r2, r2, (L1CSR_CFI|L1CSR_CLFC)@l
lis r2, (L1CSR_CFI | L1CSR_CLFC)@h
ori r2, r2, (L1CSR_CFI | L1CSR_CLFC)@l
mtspr L1CSR1, r2
1:
mfspr r3, L1CSR1
and. r1, r3, r2
bne 1b
lis r3, (L1CSR_CPE|L1CSR_CE)@h
ori r3, r3, (L1CSR_CPE|L1CSR_CE)@l
lis r3, (L1CSR_CPE | L1CSR_CE)@h
ori r3, r3, (L1CSR_CPE | L1CSR_CE)@l
mtspr L1CSR1,r3
isync
2:
@ -73,16 +81,16 @@ _mp_page_start:
beq 2b
/* Enable/invalidate the D-Cache */
lis r2, (L1CSR_CFI|L1CSR_CLFC)@h
ori r2, r2, (L1CSR_CFI|L1CSR_CLFC)@l
lis r2, (L1CSR_CFI | L1CSR_CLFC)@h
ori r2, r2, (L1CSR_CFI | L1CSR_CLFC)@l
mtspr L1CSR0, r2
1:
mfspr r3, L1CSR0
and. r1, r3, r2
bne 1b
lis r3, (L1CSR_CPE|L1CSR_CE)@h
ori r3, r3, (L1CSR_CPE|L1CSR_CE)@l
lis r3, (L1CSR_CPE | L1CSR_CE)@h
ori r3, r3, (L1CSR_CPE | L1CSR_CE)@l
mtspr L1CSR0, r3
isync
2:
@ -91,99 +99,184 @@ _mp_page_start:
beq 2b
/* Get our PIR to figure out our table entry */
lis r3, TORESET(_spin_table)@h
ori r3, r3, TORESET(_spin_table)@l
lis r3, TORESET(_spin_table_addr)@h
ori r3, r3, TORESET(_spin_table_addr)@l
lwz r3, 0(r3)
/* Determine base address for the core (use r10) */
/* Use PIR to determine cluster/core for spin table base at r10 */
mfspr r0, SPRN_PIR
#if defined(CORE_E5500) || defined(CORE_E6500)
rlwinm r8, r0, 29, 0x03 /* r8 = core within cluster */
srwi r10, r0, 5 /* r10 = cluster */
mulli r5, r10, CORES_PER_CLUSTER
add r5, r5, r8
mulli r4, r5, CORES_PER_CLUSTER
#elif defined(CORE_E500MC) /* BOOKE e500mc family */
rlwinm r4, r0, 27, 27, 31
mr r5, r4
#else /* BOOKE e500 family (like P1021) */
mr r4, r0
slwi r8, r4, 5 /* core number * ENTRY_SIZE */
mr r5, r4
#endif
slwi r8, r5, 6 /* spin table is padded to 64 bytes */
/* use r10 for the spin table base address */
add r10, r3, r8
/* Setup the spin table entry */
li r3, 0
li r8, 1
stw r0, ENTRY_PIR(r10)
stw r3, ENTRY_ADDR_UPPER(r10)
stw r8, ENTRY_ADDR_LOWER(r10)
stw r3, ENTRY_R3_UPPER(r10)
stw r4, ENTRY_R3_LOWER(r10)
stw r3, ENTRY_R6_UPPER(r10)
stw r3, ENTRY_R6_LOWER(r10)
mtspr SPRN_PIR, r4 /* Set processor information cluster/core (PIT) */
/* Load r13 with the address of the boot page */
lis r13, TORESET(_bootpg_addr)@h
ori r13, r13, TORESET(_bootpg_addr)@l
#if defined(CORE_E5500) || defined(CORE_E6500)
/* set L1 stash id = 32: (coreID * 2) + 32 + L1 CT (0) */
slwi r8, r4, 1
addi r8, r8, 32
mtspr L1CSR2, r8
#if defined(CORE_E6500) /* --- L2 E6500 --- */
l2_setup_cache:
/* E6500CORERM: 11.7 L2 cache state */
/* R5 = L2 cluster 1 base */
lis r5, L2_CLUSTER_BASE(0)@h
ori r5, r5, L2_CLUSTER_BASE(0)@l
/* Invalidate and clear locks */
lis r1, (L2CSR0_L2FI | L2CSR0_L2LFC)@h
ori r1, r1, (L2CSR0_L2FI | L2CSR0_L2LFC)@l
sync
stw r1, L2CSR0(r5)
/* poll till invalidate and lock bits are cleared */
l2_poll_invclear:
lwz r4, L2CSR0(r5)
and. r4, r1, r4
bne l2_poll_invclear
isync
/* set stash id to (coreID * 2) + 32 + L2 (1) */
addi r3, r8,1
stw r3, L2CSR1(r5)
/* enable L2 with parity */
sync
isync
lis r4, (L2CSR0_L2E | L2CSR0_L2PE)@h
stw r4, L2CSR0(r5)
isync
#elif defined(CORE_E5500) /* --- L2 E5500 --- */
l2_setup_cache:
/* Invalidate and clear locks */
msync
lis r2, (L2CSR0_L2FI | L2CSR0_L2LFC)@h
ori r2, r2, (L2CSR0_L2FI | L2CSR0_L2LFC)@l
mtspr L2CSR0, r2
/* poll till invalidate and lock bits are cleared */
l2_poll_invclear:
mfspr r3, L2CSR0
and. r1, r3, r2
bne l2_poll_invclear
/* set stash id to (coreID * 2) + 32 + L2 (1) */
addi r3, r8, 1
mtspr L2CSR1, r3
/* enable L2 with no parity */
lis r3, (L2CSR0_L2E)@h
mtspr L2CSR0, r3
isync
2:
mfspr r3, L2CSR0
andis. r1, r3, (L2CSR0_L2E)@h
beq 2b
#endif
#endif /* CORE_E5500 || CORE_E6500 */
3:
/* setup mapping for the spin table, WIMGE=0b00100 */
lis r13, TORESET(_spin_table_addr)@h
ori r13, r13, TORESET(_spin_table_addr)@l
lwz r13, 0(r13)
/* mask by 4K */
rlwinm r13, r13, 0, 0, 19
/* Write TLB1 entry 1 4KB for boot page */
lis r11, (MAS0_TLBSEL(1) | MAS0_ESEL(1))@h
mtspr MAS0, r11
lis r11, (MAS1_VALID | MAS1_IPROT)@h
ori r11, r11, (MAS1_TS | MAS1_TSIZE(BOOKE_PAGESZ_4K))@l
mtspr MAS1, r11
oris r11, r13, (MAS2_I)@h
ori r11, r13, (MAS2_I)@l
oris r11, r13, (MAS2_M | MAS2_G)@h
ori r11, r13, (MAS2_M | MAS2_G)@l
mtspr MAS2, r11
oris r11, r13, (MAS3_SX | MAS3_SW | MAS3_SR)@h
ori r11, r13, (MAS3_SX | MAS3_SW | MAS3_SR)@l
mtspr MAS3, r11
li r11, 0
mtspr MAS7, r11
tlbwe
bl 1f
1: mflr r11
/* Create a boot page mask to fixup the spin table */
ori r13, r13, 0xfff
and r11, r11, r13
and r10, r10, r13
addi r11, r11, (2f-1b)
/* _bootpg_addr has the address of _second_half_boot_page
* jump there in AS=1 space with cache enabled
*/
lis r13, TORESET(_bootpg_addr)@h
ori r13, r13, TORESET(_bootpg_addr)@l
lwz r11, 0(r13)
mtspr SRR0, r11
mfmsr r13
ori r12, r13, (MSR_IS | MSR_DS)@l
mtspr SRR0, r11
mtspr SRR1, r12
rfi
2: /* spin waiting for addr */
/* Reserve memory to store physical boot page address */
.align CACHE_LINE_SHIFT
.globl _bootpg_addr
_bootpg_addr:
.long 0
.global _spin_table_addr
_spin_table_addr:
.long 0
/* Fill in the empty space. The actual reset vector is
* the last word of the page */
_secondary_start_code_end:
.space (BOOT_ROM_SIZE - 4) - (_secondary_start_code_end - _secondary_start_page)
_secondary_reset_vector:
b _secondary_start_page
/* this is a separated page for the spin table and cacheable boot code */
.align CACHE_LINE_SHIFT
.global _second_half_boot_page
_second_half_boot_page:
lis r3, (spin_table_compat - _second_half_boot_page)@h
ori r3, r3, (spin_table_compat - _second_half_boot_page)@l
add r3, r3, r11 /* r11 has the address of _second_half_boot_page */
lwz r14, 0(r3)
/* Setup the spin table entry */
li r3, 0
li r8, 1
mfspr r4, SPRN_PIR
stw r3, ENTRY_ADDR_UPPER(r10)
stw r3, ENTRY_R3_UPPER(r10)
stw r4, ENTRY_R3_LOWER(r10)
stw r3, ENTRY_RESV(r10)
stw r4, ENTRY_PIR(r10)
msync
stw r8, ENTRY_ADDR_LOWER(r10)
/* spin waiting for addr */
3:
cmpwi r14, 0
beq 4f
dcbf 0, r10
sync
4:
lwz r4, ENTRY_ADDR_LOWER(r10)
andi. r11, r4, 1
bne 2b
bne 3b
isync
/* setup interrupts */
li r3, INTVEC_ADDR(0)
mtspr IVOR(0), r3 /* 0: Critical input */
li r3, INTVEC_ADDR(1)
mtspr IVOR(1), r3 /* 1: Machine check */
li r3, INTVEC_ADDR(2)
mtspr IVOR(2), r3 /* 2: Data storage */
li r3, INTVEC_ADDR(3)
mtspr IVOR(3), r3 /* 3: Instruction storage */
li r3, INTVEC_ADDR(4)
mtspr IVOR(4), r3 /* 4: External interrupt */
li r3, INTVEC_ADDR(5)
mtspr IVOR(5), r3 /* 5: Alignment */
li r3, INTVEC_ADDR(6)
mtspr IVOR(6), r3 /* 6: Program check */
li r3, INTVEC_ADDR(7)
mtspr IVOR(7), r3 /* 7: floating point unavailable */
li r3, INTVEC_ADDR(8)
mtspr IVOR(8), r3 /* 8: System call */
/* 9: Auxiliary processor unavailable(unsupported) */
li r3, INTVEC_ADDR(10)
mtspr IVOR(10), r3 /* 10: Decrementer */
li r3, INTVEC_ADDR(11)
mtspr IVOR(11), r3 /* 11: Interval timer */
li r3, INTVEC_ADDR(12)
mtspr IVOR(12), r3 /* 12: Watchdog timer */
li r3, INTVEC_ADDR(13)
mtspr IVOR(13), r3 /* 13: Data TLB error */
li r3, INTVEC_ADDR(14)
mtspr IVOR(14), r3 /* 14: Instruction TLB error */
li r3, INTVEC_ADDR(15)
mtspr IVOR(15), r3 /* 15: Debug */
/* get the upper bits of the addr */
lwz r11, ENTRY_ADDR_UPPER(r10)
@ -198,10 +291,14 @@ _mp_page_start:
rlwinm r12, r4, 0, 0, 5
/* setup registers before jump */
#ifdef ENABLE_PPC64
ld r3, ENTRY_R3_UPPER(r10)
#else
lwz r3, ENTRY_R3_LOWER(r10)
#endif
li r4, 0
li r5, 0
lwz r6, ENTRY_R6_LOWER(r10)
li r6, 0
lis r7, (64 * 1024 * 1024)@h
li r8, 0
li r9, 0
@ -230,20 +327,18 @@ _mp_page_start:
mtspr SRR1, r13
rfi
/* Reserve memory to store physical boot page address */
.globl _bootpg_addr
_bootpg_addr:
.long 0
.align CACHE_LINE_SHIFT
/* Reserve space for spin table entries */
.align 6 /* 64-bytes */
.globl _spin_table
_spin_table:
.space CPU_NUMCORES * ENTRY_SIZE
/* enable spin table compatibility for older ePAPR 1.1 */
.align CACHE_LINE_SHIFT
.global spin_table_compat
spin_table_compat:
.long 1
/* Fill remainder of page */
_mp_page_end:
.space 4092 - (_mp_page_end - _mp_page_start)
_mp_reset:
b _mp_page_start
_spin_table_end:
.space BOOT_ROM_SIZE - (_spin_table_end - _spin_table)

View File

@ -343,7 +343,9 @@ infinite_debug_loop:
#ifdef USE_CORENET_INTERFACE
ccsr_temp_law:
/* CCSR - LAW0 (Temp CoreNet 4K) */
#define CCSR_TEMP_LAW (LAWAR_ENABLE | LAWAR_TRGT_ID(LAW_TRGT_CORENET) | LAW_SIZE_4KB)
#define CCSR_TEMP_LAW (LAWAR_ENABLE | \
LAWAR_TRGT_ID(LAW_TRGT_CORENET) | \
LAW_SIZE_4KB)
lis r0, CCSRBAR_PHYS_HIGH@h
ori r0, r0, CCSRBAR_PHYS_HIGH@l
lis r1, CCSRBAR_DEF@h
@ -354,7 +356,8 @@ ccsr_temp_law:
stw r1, LAWBAR_BASE(0)+4(r9) /* LAWBARL */
sync
stw r2, LAWBAR_BASE(0)+8(r9) /* LAWAR */
lwz r2, LAWBAR_BASE(0)+8(r9) /* read back LAWAR (per 2.3.2 Configuring Local Access Windows) */
/* read back LAWAR (per 2.3.2 Configuring Local Access Windows) */
lwz r2, LAWBAR_BASE(0)+8(r9)
isync
read_old_ccsr:
@ -398,7 +401,8 @@ write_new_ccsrbar:
invalidate_temp_tlb:
/* invalidate TLB 0 */
li r3, 0x04 /* L2TLB0_FI: TLB0 flash invalidate (write 1 to invalidate) */
/* L2TLB0_FI: TLB0 flash invalidate (write 1 to invalidate) */
li r3, 0x04
mtspr MMUCSR0, r3
#endif /* CCSRBAR_DEF != CCSRBAR_PHYS */
@ -424,7 +428,9 @@ ccsr_tlb:
#if defined(CORE_E5500) || defined(CORE_E6500)
ccsr_law:
/* CCSR - LAW0 (CoreNet 16MB) */
#define CCSR_LAW (LAWAR_ENABLE | LAWAR_TRGT_ID(LAW_TRGT_CORENET) | LAW_SIZE_16MB)
#define CCSR_LAW (LAWAR_ENABLE | \
LAWAR_TRGT_ID(LAW_TRGT_CORENET) | \
LAW_SIZE_16MB)
lis r9, CCSRBAR + LAWBAR_BASE(0)@h
ori r9, r9, CCSRBAR + LAWBAR_BASE(0)@l
lis r0, CCSRBAR_PHYS_HIGH@h
@ -437,7 +443,8 @@ ccsr_law:
stw r1, 4(r9) /* LAWBARL */
sync
stw r2, 8(r9) /* LAWAR */
lwz r2, 8(r9) /* read back LAWAR (per 2.3.2 Configuring Local Access Windows) */
/* read back LAWAR (per 2.3.2 Configuring Local Access Windows) */
lwz r2, 8(r9)
isync
#endif /* CORE_E5500 || CORE_E6500 */
@ -446,7 +453,9 @@ ccsr_law:
/* Memory Mapped NOR Flash (64/128MB) at 0xEC000000/0xE8000000 */
flash_law:
/* FLASH - LAW1 (IFC 64/128MB) */
#define FLASH_LAW (LAWAR_ENABLE | LAWAR_TRGT_ID(LAW_TRGT_IFC) | FLASH_LAW_SIZE)
#define FLASH_LAW (LAWAR_ENABLE | \
LAWAR_TRGT_ID(LAW_TRGT_IFC) | \
FLASH_LAW_SIZE)
lis r9, CCSRBAR + LAWBAR_BASE(1)@h
ori r9, r9, CCSRBAR + LAWBAR_BASE(1)@l
lis r0, FLASH_BASE_PHYS_HIGH@h
@ -459,10 +468,11 @@ flash_law:
stw r1, 4(r9) /* LAWBARL */
sync
stw r2, 8(r9) /* LAWAR */
lwz r2, 8(r9) /* read back LAWAR (per 2.3.2 Configuring Local Access Windows) */
/* read back LAWAR (per 2.3.2 Configuring Local Access Windows) */
lwz r2, 8(r9)
isync
flash_tlb:
/* Flash: TLB 1, Entry 7, Super X/R/W, W/I/G, TS=0, 64/128M, IPROT */
/* Flash: TLB 1, Entry 2, Super X/R/W, W/I/G, TS=0, 64/128M, IPROT */
/* Write is required for Write/Erase using CFI commands to base */
#ifdef BUILD_LOADER_STAGE1
/* Using XIP from this flash, so cannot use cache inhibit */
@ -471,7 +481,7 @@ flash_tlb:
/* IFC polling requires cache inhibit */
#define FLASH_TLB_WING (MAS2_I | MAS2_G)
#endif
set_tlb(1, 7,
set_tlb(1, 2,
FLASH_BASE_ADDR, FLASH_BASE_ADDR, FLASH_BASE_PHYS_HIGH,
MAS3_SX | MAS3_SW | MAS3_SR, FLASH_TLB_WING, 0,
FLASH_TLB_PAGESZ, 1, r3);
@ -529,7 +539,8 @@ init_sram_law:
stw r1, 4(r9) /* LAWBARL */
sync
stw r2, 8(r9) /* LAWAR */
lwz r2, 8(r9) /* read back LAWAR (per 2.3.2 Configuring Local Access Windows) */
/* read back LAWAR (per 2.3.2 Configuring Local Access Windows) */
lwz r2, 8(r9)
isync
init_sram_tlb:
@ -577,12 +588,6 @@ l2_setup_sram:
#if defined(CORE_E6500) /* --- L2 E6500 --- */
l2_setup_cache:
/* L2 Cache Control - E6500CORERM 2.2.3 Memory-mapped registers (MMRs) */
#define L2_CLUSTER_BASE(n) (CCSRBAR + 0xC20000 + (n * 0x40000))
#define L2PID(n) (0x200 + (n * 0x10)) /* L2 Cache Partitioning ID */
#define L2PIR(n) (0x208 + (n * 0x10)) /* L2 Cache Partitioning Allocation */
#define L2PWR(n) (0x20C + (n * 0x10)) /* L2 Cache Partitioning Way */
/* E6500CORERM: 11.7 L2 cache state */
/* R5 = L2 cluster 1 base */
lis r5, L2_CLUSTER_BASE(0)@h
@ -600,7 +605,7 @@ l2_poll_invclear:
bne l2_poll_invclear
isync
/* set stash id to (coreID) * 2 + 32 + L2 (1) */
/* set stash id to (coreID * 2) + 32 + L2 (1) - only core 0 here */
li r4, (32 + 1)
stw r4, L2CSR1(r5)
@ -613,9 +618,6 @@ l2_poll_invclear:
#elif defined(CORE_E5500) /* --- L2 E5500 --- */
l2_setup_cache:
/* L2 Cache Control - E5500RM 2.15 L2 Cache Registers */
#define L2_BASE (CCSRBAR + 0x20000)
/* Invalidate and clear locks */
lis r1, (L2CSR0_L2FI | L2CSR0_L2LFC)@h
ori r1, r1, (L2CSR0_L2FI | L2CSR0_L2LFC)@l
@ -630,13 +632,9 @@ l2_poll_invclear:
and. r4, r1, r4
bne l2_poll_invclear
/* set stash id to (coreID) * 2 + 32 + L2 (1) */
/* set stash id to (coreID * 2) + 32 + L2 (1) - only core 0 here */
li r4, (32 + 1)
sync
isync
mtspr L2CSR1, r4
isync
sync
/* enable L2 with no parity */
lis r4, (L2CSR0_L2E)@h
@ -650,15 +648,6 @@ l2_poll_invclear:
#if defined(CORE_E500) /* --- L2 E500 --- */
/* e500 - L2 Cache */
l2_setup_cache:
#define L2_BASE (CCSRBAR + 0x20000)
#define L2CTL 0x000 /* 0xFFE20000 - L2 control register */
#define L2SRBAR0 0x100 /* 0xFFE20100 - L2 SRAM base address register */
#define L2CTL_EN (1 << 31) /* L2 enable */
#define L2CTL_INV (1 << 30) /* L2 invalidate */
#define L2CTL_SIZ(n) (((n) & 0x3) << 28) /* 2=256KB (always) */
#define L2CTL_L2SRAM(n) (((n) & 0x7) << 16) /* 1=all 256KB, 2=128KB */
#ifdef L2SRAM_ADDR /* as SRAM (1=256KB) */
#define L2CTL_VAL (L2CTL_EN | L2CTL_INV | L2CTL_SIZ(2) | L2CTL_L2SRAM(1))
#else

616
src/fdt.c 100644
View File

@ -0,0 +1,616 @@
/* fdt.c
*
* Functions to help with flattened device tree (DTB) parsing
*
*
* Copyright (C) 2023 wolfSSL Inc.
*
* This file is part of wolfBoot.
*
* wolfBoot is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfBoot is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#if defined(MMU) && !defined(BUILD_LOADER_STAGE1)
#include "fdt.h"
#include "hal.h"
#include "printf.h"
#include "string.h"
#include <stdint.h>
uint32_t cpu_to_fdt32(uint32_t x)
{
#ifdef BIG_ENDIAN_ORDER
return x;
#else
return (uint32_t)__builtin_bswap32(x);
#endif
}
uint64_t cpu_to_fdt64(uint64_t x)
{
#ifdef BIG_ENDIAN_ORDER
return x;
#else
return (uint64_t)__builtin_bswap64(x);
#endif
}
uint32_t fdt32_to_cpu(uint32_t x)
{
#ifdef BIG_ENDIAN_ORDER
return x;
#else
return (uint32_t)__builtin_bswap32(x);
#endif
}
uint64_t fdt64_to_cpu(uint64_t x)
{
#ifdef BIG_ENDIAN_ORDER
return x;
#else
return (uint64_t)__builtin_bswap64(x);
#endif
}
/* Internal Functions */
static inline const void *fdt_offset_ptr_(const void *fdt, int offset)
{
return (const char*)fdt + fdt_off_dt_struct(fdt) + offset;
}
static inline int fdt_data_size_(void *fdt)
{
/* the last portion of a FDT is the DT string, so use its offset and size to
* determine total size */
return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
}
static const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
{
unsigned int uoffset = offset;
unsigned int absoffset = offset + fdt_off_dt_struct(fdt);
if (offset < 0) {
return NULL;
}
if ((absoffset < uoffset)
|| ((absoffset + len) < absoffset)
|| (absoffset + len) > fdt_totalsize(fdt)) {
return NULL;
}
if (fdt_version(fdt) >= 0x11) {
if (((uoffset + len) < uoffset)
|| ((offset + len) > fdt_size_dt_struct(fdt))) {
return NULL;
}
}
return fdt_offset_ptr_(fdt, offset);
}
static uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
{
const uint32_t *tagp, *lenp;
uint32_t tag;
int offset = startoffset;
const char *p;
*nextoffset = -FDT_ERR_TRUNCATED;
tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE);
if (tagp == NULL) {
return FDT_END; /* premature end */
}
tag = fdt32_to_cpu(*tagp);
offset += FDT_TAGSIZE;
*nextoffset = -FDT_ERR_BADSTRUCTURE;
switch (tag) {
case FDT_BEGIN_NODE:
/* skip name */
do {
p = fdt_offset_ptr(fdt, offset++, 1);
} while (p && (*p != '\0'));
if (p == NULL)
return FDT_END; /* premature end */
break;
case FDT_PROP:
lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp));
if (!lenp) {
return FDT_END; /* premature end */
}
/* skip-name offset, length and value */
offset += sizeof(struct fdt_property) - FDT_TAGSIZE
+ fdt32_to_cpu(*lenp);
if (fdt_version(fdt) < 0x10 && fdt32_to_cpu(*lenp) >= 8 &&
((offset - fdt32_to_cpu(*lenp)) % 8) != 0) {
offset += 4;
}
break;
case FDT_END:
case FDT_END_NODE:
case FDT_NOP:
break;
default:
return FDT_END;
}
if (!fdt_offset_ptr(fdt, startoffset, offset - startoffset)) {
return FDT_END; /* premature end */
}
*nextoffset = FDT_TAGALIGN(offset);
return tag;
}
static int fdt_check_node_offset_(const void *fdt, int offset)
{
if ((offset < 0) || (offset % FDT_TAGSIZE)
|| (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE)) {
return -FDT_ERR_BADOFFSET;
}
return offset;
}
static int fdt_check_prop_offset_(const void *fdt, int offset)
{
if ((offset < 0) || (offset % FDT_TAGSIZE)
|| (fdt_next_tag(fdt, offset, &offset) != FDT_PROP)) {
return -FDT_ERR_BADOFFSET;
}
return offset;
}
static int fdt_next_property_(const void *fdt, int offset)
{
uint32_t tag;
int nextoffset;
do {
tag = fdt_next_tag(fdt, offset, &nextoffset);
switch (tag) {
case FDT_END:
if (nextoffset >= 0)
return -FDT_ERR_BADSTRUCTURE;
else
return nextoffset;
case FDT_PROP:
return offset;
}
offset = nextoffset;
} while (tag == FDT_NOP);
return -FDT_ERR_NOTFOUND;
}
static const struct fdt_property *fdt_get_property(const void *fdt, int offset,
const char *name, int *lenp, int *poffset)
{
int namelen = (int)strlen(name);
for (offset = fdt_first_property_offset(fdt, offset);
offset >= 0;
offset = fdt_next_property_offset(fdt, offset))
{
int slen, stroffset;
const char *p;
const struct fdt_property *prop =
fdt_get_property_by_offset(fdt, offset, lenp);
if (prop == NULL) {
offset = -FDT_ERR_INTERNAL;
break;
}
stroffset = fdt32_to_cpu(prop->nameoff);
p = fdt_get_string(fdt, stroffset, &slen);
if (p && (slen == namelen) && (memcmp(p, name, namelen) == 0)) {
if (poffset)
*poffset = offset;
return prop;
}
}
if (lenp) {
*lenp = offset;
}
return NULL;
}
static void fdt_del_last_string_(void *fdt, const char *s)
{
int newlen = strlen(s) + 1;
fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) - newlen);
}
static int fdt_splice_(void *fdt, void *splicepoint, int oldlen, int newlen)
{
char *p, *end;
p = splicepoint;
end = (char*)fdt + fdt_data_size_(fdt);
if (((p + oldlen) < p) || ((p + oldlen) > end)) {
return -FDT_ERR_BADOFFSET;
}
if ((p < (char*)fdt) || ((end - oldlen + newlen) < (char*)fdt)) {
return -FDT_ERR_BADOFFSET;
}
if ((end - oldlen + newlen) > ((char*)fdt + fdt_totalsize(fdt))) {
return -FDT_ERR_NOSPACE;
}
memmove(p + newlen, p + oldlen, end - p - oldlen);
return 0;
}
static int fdt_splice_struct_(void *fdt, void *p, int oldlen, int newlen)
{
int err, delta;
delta = newlen - oldlen;
err = fdt_splice_(fdt, p, oldlen, newlen);
if (err == 0) {
fdt_set_size_dt_struct(fdt, fdt_size_dt_struct(fdt) + delta);
fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta);
}
return err;
}
static int fdt_resize_property_(void *fdt, int nodeoffset, const char *name,
int len, struct fdt_property **prop)
{
int err, oldlen;
*prop = (struct fdt_property*)(uintptr_t)
fdt_get_property(fdt, nodeoffset, name, &oldlen, NULL);
if (*prop != NULL) {
err = fdt_splice_struct_(fdt, (*prop)->data, FDT_TAGALIGN(oldlen),
FDT_TAGALIGN(len));
if (err == 0) {
(*prop)->len = cpu_to_fdt32(len);
}
}
else {
err = oldlen;
}
return err;
}
static int fdt_splice_string_(void *fdt, int newlen)
{
int err;
void *p = (char*)fdt + fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
if ((err = fdt_splice_(fdt, p, 0, newlen))) {
return err;
}
fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) + newlen);
return 0;
}
static const char* fdt_find_string_(const char *strtab, int tabsize, const char *s)
{
int len = strlen(s) + 1;
const char *last = strtab + tabsize - len;
const char *p;
for (p = strtab; p <= last; p++) {
if (memcmp(p, s, len) == 0) {
return p;
}
}
return NULL;
}
static int fdt_find_add_string_(void *fdt, const char *s, int *allocated)
{
int err, len;
char *strtab, *new;
const char *p;
strtab = (char*)fdt + fdt_off_dt_strings(fdt);
len = strlen(s) + 1;
*allocated = 0;
p = fdt_find_string_(strtab, fdt_size_dt_strings(fdt), s);
if (p) { /* found it */
return (p - strtab);
}
new = strtab + fdt_size_dt_strings(fdt);
err = fdt_splice_string_(fdt, len);
if (err) {
return err;
}
*allocated = 1;
memcpy(new, s, len);
return (new - strtab);
}
static int fdt_add_property_(void *fdt, int nodeoffset, const char *name,
int len, struct fdt_property **prop)
{
int err, proplen, nextoffset, namestroff, allocated;
if ((nextoffset = fdt_check_node_offset_(fdt, nodeoffset)) < 0) {
return nextoffset;
}
namestroff = fdt_find_add_string_(fdt, name, &allocated);
if (namestroff < 0) {
return namestroff;
}
*prop = (void*)(uintptr_t)fdt_offset_ptr_(fdt, nextoffset);
proplen = sizeof(**prop) + FDT_TAGALIGN(len);
err = fdt_splice_struct_(fdt, *prop, 0, proplen);
if (err) {
/* Delete the string if we failed to add it */
if (allocated)
fdt_del_last_string_(fdt, name);
return err;
}
(*prop)->tag = cpu_to_fdt32(FDT_PROP);
(*prop)->nameoff = cpu_to_fdt32(namestroff);
(*prop)->len = cpu_to_fdt32(len);
return 0;
}
/* Public Functions */
int fdt_check_header(const void *fdt)
{
if (fdt_magic(fdt) == FDT_MAGIC) {
if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
return -FDT_ERR_BADVERSION;
if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION)
return -FDT_ERR_BADVERSION;
}
else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
if (fdt_size_dt_struct(fdt) == 0)
return -FDT_ERR_BADSTATE;
}
else {
return -FDT_ERR_BADMAGIC;
}
return 0;
}
int fdt_next_node(const void *fdt, int offset, int *depth)
{
int nextoffset = 0;
uint32_t tag;
if (offset >= 0) {
if ((nextoffset = fdt_check_node_offset_(fdt, offset)) < 0)
return nextoffset;
}
do {
offset = nextoffset;
tag = fdt_next_tag(fdt, offset, &nextoffset);
switch (tag) {
case FDT_PROP:
case FDT_NOP:
break;
case FDT_BEGIN_NODE:
if (depth)
(*depth)++;
break;
case FDT_END_NODE:
if (depth && ((--(*depth)) < 0))
return nextoffset;
break;
case FDT_END:
if ((nextoffset >= 0)
|| ((nextoffset == -FDT_ERR_TRUNCATED) && !depth))
return -FDT_ERR_NOTFOUND;
else
return nextoffset;
}
} while (tag != FDT_BEGIN_NODE);
return offset;
}
int fdt_first_property_offset(const void *fdt, int nodeoffset)
{
int offset;
if ((offset = fdt_check_node_offset_(fdt, nodeoffset)) < 0) {
return offset;
}
return fdt_next_property_(fdt, offset);
}
int fdt_next_property_offset(const void *fdt, int offset)
{
if ((offset = fdt_check_prop_offset_(fdt, offset)) < 0) {
return offset;
}
return fdt_next_property_(fdt, offset);
}
const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
int offset, int *lenp)
{
int err;
const struct fdt_property *prop;
if ((err = fdt_check_prop_offset_(fdt, offset)) < 0) {
if (lenp) {
*lenp = err;
}
return NULL;
}
prop = fdt_offset_ptr_(fdt, offset);
if (lenp) {
*lenp = fdt32_to_cpu(prop->len);
}
return prop;
}
const char* fdt_get_name(const void *fdt, int nodeoffset, int *len)
{
int err;
const struct fdt_node_header *nh = fdt_offset_ptr_(fdt, nodeoffset);
int namelen = 0;
const char* name = NULL;
err = fdt_check_header(fdt);
if (err == 0) {
err = fdt_check_node_offset_(fdt, nodeoffset);
if (err >= 0) {
name = nh->name;
namelen = strlen(nh->name);
}
}
if (err < 0)
namelen = err;
if (len)
*len = namelen;
return name;
}
const char* fdt_get_string(const void *fdt, int stroffset, int *lenp)
{
const char *s = (const char*)fdt + fdt_off_dt_strings(fdt) + stroffset;
if (lenp) {
*lenp = strlen(s);
}
return s;
}
int fdt_setprop(void *fdt, int nodeoffset, const char *name, const void *val,
int len)
{
int err = 0;
void *prop_data;
struct fdt_property *prop;
err = fdt_totalsize(fdt); /* confirm size in header */
if (err > 0) {
err = fdt_resize_property_(fdt, nodeoffset, name, len, &prop);
if (err == -FDT_ERR_NOTFOUND) {
err = fdt_add_property_(fdt, nodeoffset, name, len, &prop);
}
}
else {
err = FDT_ERR_BADSTRUCTURE;
}
if (err == 0) {
prop_data = prop->data;
if (len > 0) {
memcpy(prop_data, val, len);
}
}
return err;
}
const void *fdt_getprop(const void *fdt, int nodeoffset, const char *name,
int *lenp)
{
int poffset;
const struct fdt_property *prop = fdt_get_property(
fdt, nodeoffset, name, lenp, &poffset);
if (prop != NULL) {
/* Handle alignment */
if (fdt_version(fdt) < 0x10 &&
(poffset + sizeof(*prop)) % 8 && fdt32_to_cpu(prop->len) >= 8) {
return prop->data + 4;
}
return prop->data;
}
return NULL;
}
int fdt_find_devtype(void* fdt, int startoff, const char* node)
{
int len, off;
const void* val;
const char* propname = "device_type";
int nodelen = strlen(node)+1;
for (off = fdt_next_node(fdt, startoff, NULL);
off >= 0;
off = fdt_next_node(fdt, off, NULL))
{
val = fdt_getprop(fdt, off, propname, &len);
if (val && (len == nodelen) && (memcmp(val, node, len) == 0)) {
return off;
}
}
return off; /* return error from fdt_next_node() */
}
int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
const char *compatible)
{
int offset;
int complen = (int)strlen(compatible);
for (offset = fdt_next_node(fdt, startoffset, NULL);
offset >= 0;
offset = fdt_next_node(fdt, offset, NULL))
{
int len;
const char *prop = (const char*)fdt_getprop(fdt, offset, "compatible",
&len);
/* property list may contain multiple null terminated strings */
while (prop != NULL && len >= complen) {
const char* nextprop;
if (memcmp(compatible, prop, complen+1) == 0) {
return offset;
}
nextprop = memchr(prop, '\0', len);
if (nextprop != NULL) {
len -= (nextprop - prop) + 1;
prop = nextprop + 1;
}
}
}
return offset;
}
/* adjust the actual total size in the FDT header */
int fdt_shrink(void* fdt)
{
uint32_t total_size = fdt_data_size_(fdt);
return fdt_set_totalsize(fdt, total_size);
}
/* FTD Fixup API's */
int fdt_fixup_str(void* fdt, int off, const char* node, const char* name,
const char* str)
{
wolfBoot_printf("FDT: Set %s (%d), %s=%s\n", node, off, name, str);
return fdt_setprop(fdt, off, name, str, strlen(str)+1);
}
int fdt_fixup_val(void* fdt, int off, const char* node, const char* name,
uint32_t val)
{
wolfBoot_printf("FDT: Set %s (%d), %s=%u\n", node, off, name, val);
val = cpu_to_fdt32(val);
return fdt_setprop(fdt, off, name, &val, sizeof(val));
}
int fdt_fixup_val64(void* fdt, int off, const char* node, const char* name,
uint64_t val)
{
wolfBoot_printf("FDT: Set %s (%d), %s=%llu\n",
node, off, name, (unsigned long long)val);
val = cpu_to_fdt64(val);
return fdt_setprop(fdt, off, name, &val, sizeof(val));
}
#endif /* MMU && !BUILD_LOADER_STAGE1 */

View File

@ -884,14 +884,6 @@ int wolfBoot_open_image_address(struct wolfBoot_image *img, uint8_t *image)
}
#ifdef MMU
#ifndef WOLFBOOT_TPM /* tpm2_types.h has ByteReverseWord32 */
#define WOLFSSL_MISC_INCLUDED /* allow misc.c code to be inlined */
#include <wolfcrypt/src/misc.c> /* for ByteReverseWord32 */
#endif /* !WOLFBOOT_TPM */
static uint32_t wb_reverse_word32(uint32_t x)
{
return ByteReverseWord32(x);
}
/**
* @brief Get the size of the Device Tree Blob (DTB).
@ -904,20 +896,14 @@ static uint32_t wb_reverse_word32(uint32_t x)
*/
int wolfBoot_get_dts_size(void *dts_addr)
{
uint32_t hdr[2], magic, size;
memcpy(hdr, dts_addr, sizeof(hdr));
#ifdef BIG_ENDIAN_ORDER
magic = wb_reverse_word32(hdr[0]);
size = hdr[1];
#else
magic = hdr[0];
size = wb_reverse_word32(hdr[1]);
#endif
return (magic == UBOOT_FDT_MAGIC) ? (int)size : -1;
int ret = fdt_check_header(dts_addr);
if (ret == 0) {
ret = fdt_totalsize(dts_addr);
}
return ret;
}
#endif
#endif /* MMU */
#ifdef WOLFBOOT_FIXED_PARTITIONS

View File

@ -529,11 +529,11 @@ static uint8_t* RAMFUNCTION get_trailer_at(uint8_t part, uint32_t at)
sel_sec = nvm_select_fresh_sector(part);
#endif
if (part == PART_BOOT) {
ret = (void *)(PART_BOOT_ENDFLAGS -
ret = (void *)(PART_BOOT_ENDFLAGS -
(WOLFBOOT_SECTOR_SIZE * sel_sec + (sizeof(uint32_t) + at)));
}
else if (part == PART_UPDATE) {
ret = (void *)(PART_UPDATE_ENDFLAGS -
ret = (void *)(PART_UPDATE_ENDFLAGS -
(WOLFBOOT_SECTOR_SIZE * sel_sec + (sizeof(uint32_t) + at)));
}
return ret;

View File

@ -227,6 +227,19 @@ int memcmp(const void *_s1, const void *_s2, size_t n)
return diff;
}
void* memchr(void const *s, int c_in, size_t n)
{
unsigned char c = (unsigned char)c_in;
unsigned char *char_ptr = (unsigned char*)s;
for (; n > 0; --n, ++char_ptr) {
if (*char_ptr == c) {
return (void*)char_ptr;
}
}
return NULL;
}
#endif /* __CCRX__ Renesas CCRX */
#endif /* !BUILD_LOADER_STAGE1 || (PRINTF_ENABLED && DEBUG_UART) */

View File

@ -166,8 +166,13 @@ endif
ifeq ($(TARGET),sim)
APP_OBJS=app_$(TARGET).o ../test-app/libwolfboot.o ../hal/$(TARGET).o
# Override linker flags
LDFLAGS=-Wl,-Map=image.map
# LD on MacOS does not support "-Map="
LDMAPSUPPORTED=$(shell $(CC) -Wl,-Map=image.map 2>&1 | grep 'unknown option')
LDFLAGS=
ifeq ($(LDMAPSUPPORTED),)
# Override linker flags
LDFLAGS+=-Wl,-Map=image.map
endif
endif
ifeq ($(EXT_FLASH),1)

View File

@ -4,7 +4,7 @@
CC=gcc
CFLAGS=-Wall -g -ggdb
CFLAGS+=-I../../include -DWOLFBOOT_ELF -DELF_PARSER -DPRINTF_ENABLED
CFLAGS+=-I../../include -DWOLFBOOT_ELF -DELF_PARSER -DDEBUG_ELF -DPRINTF_ENABLED
EXE=elf-parser
LIBS=

View File

@ -0,0 +1,18 @@
-include ../../.config
-include ../../tools/config.mk
-include ../../options.mk
CC=gcc
CFLAGS=-Wall -g -ggdb
CFLAGS+=-I../../include -DMMU -DPRINTF_ENABLED
EXE=fdt-parser
LIBS=
all: $(EXE)
$(EXE):
$(CC) -o $@ $(CFLAGS) $(LIBS) fdt-parser.c ../../src/fdt.c
clean:
rm -f *.o $(EXE)

View File

@ -0,0 +1,424 @@
/* fdt-parser.c
*
* Copyright (C) 2023 wolfSSL Inc.
*
* This file is part of wolfBoot.
*
* wolfBoot is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfBoot is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*
* flattened device tree parser tool
*/
#include "wolfboot/wolfboot.h"
#include "printf.h"
#include "string.h"
#include "fdt.h"
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
static int gEnableUnitTest = 0;
#define UNIT_TEST_GROW_SIZE 1024
/* Test case for "nxp_t1024.dtb" */
static int fdt_test(void* fdt)
{
int ret = 0, off, i;
uint32_t *reg, oldsize;
#define DDR_ADDRESS 0
#define DDR_SIZE (2048ULL * 1024ULL * 1024ULL)
#define CPU_NUMCORES 2
#define SPIN_TABLE_ADDR 0x7FF01900UL
#define ENTRY_SIZE 64
#define SYS_CLK (100000000) /* 100MHz */
#define PLAT_CLK (SYS_CLK * 4)
#define BUS_CLK (PLAT_CLK / 2)
#define TIMEBASE_HZ (PLAT_CLK / 16)
struct qportal_info {
uint16_t dliodn; /* DQRR LIODN */
uint16_t fliodn; /* frame data LIODN */
uint16_t liodn_offset;
uint8_t sdest;
};
#define SET_QP_INFO(dqrr, fdata, off, dest) \
{ .dliodn = dqrr, .fliodn = fdata, .liodn_offset = off, .sdest = dest }
#define QMAN_NUM_PORTALS 10
const struct qportal_info qp_info[QMAN_NUM_PORTALS] = {
/* dqrr liodn, frame data liodn, liodn off, sdest */
SET_QP_INFO(1, 27, 1, 0),
SET_QP_INFO(2, 28, 1, 0),
SET_QP_INFO(3, 29, 1, 1),
SET_QP_INFO(4, 30, 1, 1),
SET_QP_INFO(5, 31, 1, 2),
SET_QP_INFO(6, 32, 1, 2),
SET_QP_INFO(7, 33, 1, 3),
SET_QP_INFO(8, 34, 1, 3),
SET_QP_INFO(9, 35, 1, 0),
SET_QP_INFO(10, 36, 1, 0)
};
struct liodn_id_table {
const char* compat;
uint32_t id;
};
#define SET_LIODN(fdtcomp, liodn) \
{.compat = fdtcomp, .id = liodn}
const struct liodn_id_table liodn_tbl[] = {
SET_LIODN("fsl-usb2-mph", 553),
SET_LIODN("fsl-usb2-dr", 554),
SET_LIODN("fsl,esdhc", 552),
SET_LIODN("fsl,pq-sata-v2", 555),
SET_LIODN("fsl,tdm1.0", 560),
SET_LIODN("fsl,qe", 559),
SET_LIODN("fsl,elo3-dma", 147),
SET_LIODN("fsl,elo3-dma", 227),
SET_LIODN("fsl,qman", 62),
SET_LIODN("fsl,bman", 63),
SET_LIODN("fsl,qoriq-pcie-v2.4", 148),
SET_LIODN("fsl,qoriq-pcie-v2.4", 228),
SET_LIODN("fsl,qoriq-pcie-v2.4", 308),
};
/* expand total size to allow growth */
oldsize = fdt_totalsize(fdt);
fdt_set_totalsize(fdt, oldsize + UNIT_TEST_GROW_SIZE);
/* fixup the memory region - single bank */
off = fdt_find_devtype(fdt, -1, "memory");
if (off != -FDT_ERR_NOTFOUND) {
/* build addr/size as 64-bit */
uint8_t ranges[sizeof(uint64_t) * 2], *p = ranges;
*(uint64_t*)p = cpu_to_fdt64(DDR_ADDRESS);
p += sizeof(uint64_t);
*(uint64_t*)p = cpu_to_fdt64(DDR_SIZE);
p += sizeof(uint64_t);
ret = fdt_setprop(fdt, off, "reg", ranges, (int)(p - ranges));
if (ret != 0) goto exit;
wolfBoot_printf("FDT: Set memory, start=0x%x, size=0x%x\n",
DDR_ADDRESS, (uint32_t)DDR_SIZE);
}
/* fixup CPU status and, release address and enable method */
off = fdt_find_devtype(fdt, -1, "cpu");
while (off != -FDT_ERR_NOTFOUND) {
int core;
uint64_t core_spin_table_addr;
reg = (uint32_t*)fdt_getprop(fdt, off, "reg", NULL);
if (reg == NULL)
break;
core = (int)fdt32_to_cpu(*reg);
if (core >= CPU_NUMCORES) {
break; /* invalid core index */
}
/* calculate location of spin table for core */
core_spin_table_addr = (uint64_t)((uintptr_t)(
SPIN_TABLE_ADDR + (core * ENTRY_SIZE)));
ret = fdt_fixup_str(fdt, off, "cpu", "status", (core == 0) ? "okay" : "disabled");
if (ret == 0)
ret = fdt_fixup_val64(fdt, off, "cpu", "cpu-release-addr", core_spin_table_addr);
if (ret == 0)
ret = fdt_fixup_str(fdt, off, "cpu", "enable-method", "spin-table");
if (ret == 0)
ret = fdt_fixup_val(fdt, off, "cpu", "timebase-frequency", TIMEBASE_HZ);
if (ret == 0)
ret = fdt_fixup_val(fdt, off, "cpu", "clock-frequency", PLAT_CLK);
if (ret == 0)
ret = fdt_fixup_val(fdt, off, "cpu", "bus-frequency", PLAT_CLK);
if (ret != 0) goto exit;
off = fdt_find_devtype(fdt, off, "cpu");
}
/* fixup the soc clock */
off = fdt_find_devtype(fdt, -1, "soc");
if (off != -FDT_ERR_NOTFOUND) {
ret = fdt_fixup_val(fdt, off, "soc", "bus-frequency", PLAT_CLK);
if (ret != 0) goto exit;
}
/* fixup the serial clocks */
off = fdt_find_devtype(fdt, -1, "serial");
while (off != -FDT_ERR_NOTFOUND) {
ret = fdt_fixup_val(fdt, off, "serial", "clock-frequency", BUS_CLK);
if (ret != 0) goto exit;
off = fdt_find_devtype(fdt, off, "serial");
}
/* fixup the QE bridge and bus blocks */
off = fdt_find_devtype(fdt, -1, "qe");
if (off != -FDT_ERR_NOTFOUND) {
ret = fdt_fixup_val(fdt, off, "qe", "clock-frequency", BUS_CLK);
if (ret == 0)
ret = fdt_fixup_val(fdt, off, "qe", "bus-frequency", BUS_CLK);
if (ret == 0)
ret = fdt_fixup_val(fdt, off, "qe", "brg-frequency", BUS_CLK/2);
if (ret != 0) goto exit;
}
/* fixup the LIODN */
for (i=0; i<(int)(sizeof(liodn_tbl)/sizeof(struct liodn_id_table)); i++) {
off = fdt_node_offset_by_compatible(fdt, -1, liodn_tbl[i].compat);
if (off >= 0) {
ret = fdt_fixup_val(fdt, off, liodn_tbl[i].compat, "fsl,liodn",
liodn_tbl[i].id);
if (ret != 0) goto exit;
}
}
/* fixup the QMAN portals */
off = fdt_node_offset_by_compatible(fdt, -1, "fsl,qman-portal");
while (off != -FDT_ERR_NOTFOUND) {
const int *ci = fdt_getprop(fdt, off, "cell-index", NULL);
uint32_t liodns[2];
if (!ci)
break;
i = fdt32_to_cpu(*ci);
liodns[0] = qp_info[i].dliodn;
liodns[1] = qp_info[i].fliodn;
wolfBoot_printf("FDT: Set %s@%d (%d), %s=%d,%d\n",
"qman-portal", i, off, "fsl,liodn", liodns[0], liodns[1]);
ret = fdt_setprop(fdt, off, "fsl,liodn", liodns, sizeof(liodns));
if (ret != 0) goto exit;
off = fdt_node_offset_by_compatible(fdt, off, "fsl,qman-portal");
}
/* mpic clock */
off = fdt_find_devtype(fdt, -1, "open-pic");
if (off != -FDT_ERR_NOTFOUND) {
ret = fdt_fixup_val(fdt, off, "open-pic", "clock-frequency", BUS_CLK);
if (ret != 0) goto exit;
}
/* resize the device tree */
fdt_shrink(fdt);
/* display information */
printf("FDT Updated: Size %d -> %d\n", oldsize, fdt_totalsize(fdt));
exit:
printf("FDT Test Result: %d\n", ret);
return ret;
}
static void print_bin(const uint8_t* buffer, uint32_t length)
{
uint32_t i, notprintable = 0;
if (!buffer || length == 0) {
printf("NULL");
return;
}
for (i = 0; i < length; i++) {
if (buffer[i] > 31 && buffer[i] < 127) {
printf("%c", buffer[i]);
} else if (i == length-1 && buffer[i] == '\0') {
printf(" "); /* null term */
} else {
printf(".");
notprintable++;
}
}
if (notprintable > 0) {
printf("| ");
for (i = 0; i < length; i++) {
printf("%02x ", buffer[i]);
}
}
}
static int write_bin(const char* filename, const uint8_t *buf, uint32_t bufSz)
{
int rc = -1;
FILE* fp = NULL;
size_t fileSz = 0;
if (filename == NULL || buf == NULL)
return -1;
fp = fopen(filename, "wb");
if (fp != NULL) {
fileSz = fwrite(buf, 1, bufSz, fp);
/* sanity check */
if (fileSz == (uint32_t)bufSz) {
rc = 0;
}
printf("Wrote %d bytes to %s\n", (int)fileSz, filename);
fclose(fp);
}
return rc;
}
static int load_file(const char* filename, uint8_t** buf, size_t* bufLen)
{
int ret = 0;
ssize_t fileSz, readLen;
FILE* fp;
if (filename == NULL || buf == NULL || bufLen == NULL)
return -1;
/* open file (read-only binary) */
fp = fopen(filename, "rb");
if (fp == NULL) {
fprintf(stderr, "Error loading %s\n", filename);
return -1;
}
fseek(fp, 0, SEEK_END);
fileSz = ftell(fp);
rewind(fp);
if (fileSz > 0) {
if (*buf == NULL) {
if (gEnableUnitTest)
*buf = (uint8_t*)malloc(fileSz + UNIT_TEST_GROW_SIZE);
else
*buf = (uint8_t*)malloc(fileSz);
if (*buf == NULL)
ret = -1;
}
else if (*buf != NULL && fileSz > (ssize_t)*bufLen) {
ret = -1;
}
*bufLen = (size_t)fileSz;
if (ret == 0) {
readLen = fread(*buf, 1, *bufLen, fp);
ret = (readLen == (ssize_t)*bufLen) ? 0 : -1;
}
}
else {
ret = -1;
}
fclose(fp);
return ret;
}
int dts_parse(void* dts_addr)
{
int ret = 0;
struct fdt_header *fdt = (struct fdt_header *)dts_addr;
const struct fdt_property* prop;
int nlen, plen, slen;
int noff, poff, soff;
const char* nstr = NULL, *pstr = NULL;
int depth = 0;
#define MAX_DEPTH 24
char tabs[MAX_DEPTH+1] = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
/* check header */
ret = fdt_check_header(fdt);
if (ret != 0) {
printf("FDT check failed %d!\n", ret);
return ret;
}
/* display information */
printf("FDT Version %d, Size %d\n",
fdt_version(fdt), fdt_totalsize(fdt));
/* walk tree */
for (noff = fdt_next_node(fdt, -1, &depth);
noff >= 0;
noff = fdt_next_node(fdt, noff, &depth))
{
nstr = fdt_get_name(fdt, noff, &nlen);
if (depth > MAX_DEPTH)
depth = MAX_DEPTH;
if (nlen == 0 && depth == 1)
nstr = "root";
printf("%s%s (node offset %d, depth %d, len %d):\n",
&tabs[MAX_DEPTH-depth+1], nstr, noff, depth, nlen);
for (poff = fdt_first_property_offset(fdt, noff);
poff >= 0;
poff = fdt_next_property_offset(fdt, poff))
{
prop = fdt_get_property_by_offset(fdt, poff, &plen);
if (prop != NULL) {
soff = fdt32_to_cpu(prop->nameoff);
pstr = fdt_get_string(fdt, soff, &slen);
printf("%s%s (prop offset %d, len %d): ",
&tabs[MAX_DEPTH-depth], pstr, poff, plen);
if (plen > 32)
printf("\n%s", &tabs[MAX_DEPTH-depth-1]);
print_bin((const uint8_t*)prop->data, plen);
printf("\n");
}
}
}
return ret;
}
int main(int argc, char *argv[])
{
int ret = 0;
uint8_t *image = NULL;
size_t imageSz = 0;
const char* filename = NULL;
if (argc >= 2) {
filename = argv[1];
}
while (argc > 2) {
if (strcmp(argv[argc-1], "-t") == 0) {
gEnableUnitTest = 1;
}
argc--;
}
printf("FDT Parser (%s):\n", filename);
if (filename == NULL) {
printf("Usage: fdt-parser [filename.dtb]\n");
return 0;
}
ret = load_file(filename, &image, &imageSz);
if (ret == 0 && gEnableUnitTest) {
ret = fdt_test(image);
if (ret == 0) {
char outfilename[PATH_MAX];
strncpy(outfilename, filename, sizeof(outfilename)-1);
strncat(outfilename, ".out", sizeof(outfilename)-1);
/* save updated binary file */
write_bin(outfilename, image, imageSz + UNIT_TEST_GROW_SIZE);
}
}
if (ret == 0) {
ret = dts_parse(image);
}
free(image);
printf("Return %d\n", ret);
return ret;
}

Binary file not shown.