mirror of https://github.com/wolfSSL/wolfBoot.git
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
parent
a020852732
commit
83283c6cf7
|
@ -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
|
|
@ -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
|
||||
|
|
5
Makefile
5
Makefile
|
@ -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
|
||||
|
||||
|
|
3
arch.mk
3
arch.mk
|
@ -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)
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -39,6 +39,8 @@ SECTIONS
|
|||
{
|
||||
_start_vector = .;
|
||||
KEEP(*(.isr_vector))
|
||||
. = ALIGN(256);
|
||||
KEEP(*(.bootmp))
|
||||
*(.text*)
|
||||
*(.rodata*)
|
||||
*(.sdata*)
|
||||
|
|
|
@ -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_ */
|
||||
|
|
821
hal/nxp_t1024.c
821
hal/nxp_t1024.c
File diff suppressed because it is too large
Load Diff
|
@ -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*)
|
||||
|
|
|
@ -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) */
|
||||
|
|
|
@ -41,6 +41,7 @@ SECTIONS
|
|||
_start_vector = .;
|
||||
KEEP(*(.isr_vector))
|
||||
. = ALIGN(256);
|
||||
KEEP(*(.bootmp))
|
||||
*(.text*)
|
||||
*(.rodata*)
|
||||
*(.sdata*)
|
||||
|
|
|
@ -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 */
|
|
@ -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 - \
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
28
src/image.c
28
src/image.c
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
13
src/string.c
13
src/string.c
|
@ -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) */
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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=
|
||||
|
|
|
@ -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)
|
|
@ -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.
Loading…
Reference in New Issue