diff --git a/.github/workflows/test-parse-tools.yml b/.github/workflows/test-parse-tools.yml new file mode 100644 index 000000000..f8a2f1468 --- /dev/null +++ b/.github/workflows/test-parse-tools.yml @@ -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 diff --git a/.gitignore b/.gitignore index 7c6b8a0ec..30a4563e9 100644 --- a/.gitignore +++ b/.gitignore @@ -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 diff --git a/Makefile b/Makefile index 3b87fbaa9..f0255b7fc 100644 --- a/Makefile +++ b/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 diff --git a/arch.mk b/arch.mk index 320aa6694..66151e004 100644 --- a/arch.mk +++ b/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) diff --git a/hal/nxp_p1021.c b/hal/nxp_p1021.c index b4df54ea6..63e04b503 100644 --- a/hal/nxp_p1021.c +++ b/hal/nxp_p1021.c @@ -22,7 +22,7 @@ #include "target.h" #include "image.h" #include "printf.h" -#include +#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 (spin table %p)\n", - spin_table_addr); + wolfBoot_printf("MP: Starting core 2 (boot page %p, spin table %p)\n", + bootpg, (uint32_t)&_spin_table); - /* 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; + + /* 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 */ + /* 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 */ diff --git a/hal/nxp_p1021.ld b/hal/nxp_p1021.ld index e10f50764..3058dcc99 100644 --- a/hal/nxp_p1021.ld +++ b/hal/nxp_p1021.ld @@ -39,6 +39,8 @@ SECTIONS { _start_vector = .; KEEP(*(.isr_vector)) + . = ALIGN(256); + KEEP(*(.bootmp)) *(.text*) *(.rodata*) *(.sdata*) diff --git a/hal/nxp_ppc.h b/hal/nxp_ppc.h index 240751179..85da21064 100644 --- a/hal/nxp_ppc.h +++ b/hal/nxp_ppc.h @@ -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_ */ diff --git a/hal/nxp_t1024.c b/hal/nxp_t1024.c index 99ae14bce..6a0323750 100644 --- a/hal/nxp_t1024.c +++ b/hal/nxp_t1024.c @@ -24,18 +24,19 @@ #include "string.h" #include "hal.h" #include "nxp_ppc.h" +#include "fdt.h" /* Tested on T1024E Rev 1.0, e5500 core 2.1, PVR 8024_1021 and SVR 8548_0010 */ -/* IFC: CS0 NOR, CS1 MRAM, CS2 CPLD, CS3, MPU CPLD */ +/* IFC: CS0 NOR, CS1 MRAM, CS2 APU CPLD, CS3, MPU CPLD */ /* DDR: DDR4 w/ECC (5 chips MT40A256M16GE-083EIT) - SPD on I2C1 at Addr 0x51 */ /* Debugging */ /* #define DEBUG_FLASH */ /* #define DEBUG_ESPI 1 */ -#define ENABLE_DDR -#define ENABLE_BUS_CLK_CALC #define ENABLE_IFC +#define ENABLE_BUS_CLK_CALC + #ifndef BUILD_LOADER_STAGE1 /* Tests */ #if 0 @@ -44,13 +45,15 @@ #define TEST_TPM #endif - //#define ENABLE_CPLD + #define ENABLE_PCIE + #define ENABLE_CPLD #define ENABLE_QE /* QUICC Engine */ - //#define ENABLE_FMAN - //#define ENABLE_MP /* multi-core support */ + #define ENABLE_FMAN + #if defined(WOLFBOOT_TPM) || defined(TEST_TPM) #define ENABLE_ESPI /* SPI for TPM */ #endif + #define ENABLE_MP /* multi-core support */ #endif #define USE_ERRATA_DDRA008378 @@ -76,6 +79,7 @@ static void hal_flash_unlock_sector(uint32_t sector); #endif /* T1024 */ +/* System input clock */ #define SYS_CLK (100000000) /* 100MHz */ /* Boot page translation register - T1024RM 4.5.9 */ @@ -87,6 +91,9 @@ static void hal_flash_unlock_sector(uint32_t sector); #define LCC_BSTAR_LAWSZ(n) ((n) & 0x3F) /* DCFG (Device Configuration/Pin Control) T1024RM 7.3 */ +#define DCSRBAR_BASE_HIGH 0xF +#define DCSRBAR_BASE 0xF0000000 + #define DCFG_BASE (CCSRBAR + 0xE0000) #define DCFG_PVR ((volatile uint32_t*)(DCFG_BASE + 0xA0UL)) #define DCFG_SVR ((volatile uint32_t*)(DCFG_BASE + 0xA4UL)) @@ -99,6 +106,50 @@ static void hal_flash_unlock_sector(uint32_t sector); #define DCFG_BRR ((volatile uint32_t*)(DCFG_BASE + 0xE4UL)) /* Boot Release Register (DCFG_CCSR_BRR) */ #define DCFG_DCSR ((volatile uint32_t*)(DCFG_BASE + 0x704UL)) /* Debug configuration and status */ +/* Logical I/O Device Number */ +#define DCFG_USB1LIODNR ((volatile uint32_t*)(DCFG_BASE + 0x520)) +#define DCFG_USB2LIODNR ((volatile uint32_t*)(DCFG_BASE + 0x524)) +#define DCFG_SDMMCLIODNR ((volatile uint32_t*)(DCFG_BASE + 0x530)) +#define DCFG_SATALIODNR ((volatile uint32_t*)(DCFG_BASE + 0x550)) +#define DCFG_DIULIODNR ((volatile uint32_t*)(DCFG_BASE + 0x570)) +#define DCFG_TDMDMALIODNR ((volatile uint32_t*)(DCFG_BASE + 0x574)) +#define DCFG_QELIODNR ((volatile uint32_t*)(DCFG_BASE + 0x578)) /* QUICC Engine Logical I/O Device Number register */ +#define DCFG_DMA1LIODNR ((volatile uint32_t*)(DCFG_BASE + 0x580)) +#define DCFG_DMA2LIODNR ((volatile uint32_t*)(DCFG_BASE + 0x584)) + +/* PCI Express LIODN base register */ +#define PCI_BASE(n) (0x240000 + ((n) * 0x10000)) +#define PCIE_LIODN(n) ((volatile uint32_t*)(PCI_BASE(n) + 0x40)) /* PEXx_PEX_LBR */ + +/* Buffer Manager */ +#define BMAN_LIODNR ((volatile uint32_t*)(BMAN_CCSR_BASE + 0xD08)) +#define BCSP_ISDR(n) ((volatile uint32_t*)(BMAN_BASE_PHYS + 0x1000E08 + ((n) * 0x1000))) + +/* Frame Queue Descriptor (FQD) */ +#define FQD_BAR ((volatile uint32_t*)(QMAN_CCSR_BASE + 0xC04)) +#define FQD_AR ((volatile uint32_t*)(QMAN_CCSR_BASE + 0xC10)) +/* Packed Frame Desc riptor Record (PFDR) */ +#define PFDR_BARE ((volatile uint32_t*)(QMAN_CCSR_BASE + 0xC20)) +#define PFDR_BAR ((volatile uint32_t*)(QMAN_CCSR_BASE + 0xC24)) +#define PFDR_AR ((volatile uint32_t*)(QMAN_CCSR_BASE + 0xC30)) + +/* QMan */ +#define QCSP_BARE ((volatile uint32_t*)(QMAN_CCSR_BASE + 0xC80)) /* Base Address (upper) */ +#define QCSP_BAR ((volatile uint32_t*)(QMAN_CCSR_BASE + 0xC84)) /* Base Address */ +/* QMan Software Portals */ +#define QMAN_LIODNR ((volatile uint32_t*)(QMAN_CCSR_BASE + 0xD08)) +#define QCSP_LIO_CFG(n) ((volatile uint32_t*)(QMAN_CCSR_BASE + 0x1000 + ((n) * 0x10))) +#define QCSP_IO_CFG(n) ((volatile uint32_t*)(QMAN_CCSR_BASE + 0x1004 + ((n) * 0x10))) + +#define QCSP_ISDR(n) ((volatile uint32_t*)(QMAN_BASE_PHYS + 0x1000E08 + ((n) * 0x1000))) + +/* SCGG (Supplemental Configuration Unit) T1024RM 6.1 */ +#define SCFG_BASE (CCSRBAR + 0xFC000) +#define SCFG_QEIOCLKCR ((volatile uint32_t*)(DCFG_BASE + 0x400UL)) + +#define SCFG_QEIOCLKCR_CLK11 0x04000000 /* IO_CLK[11] = GPIO_4[16] */ + + /* T1024RM: 4.6.5 */ #define CLOCKING_BASE (CCSRBAR + 0xE1000) #define CLOCKING_PLLPGSR ((volatile uint32_t*)(CLOCKING_BASE + 0xC00UL)) /* Platform PLL general status register */ @@ -118,39 +169,46 @@ static void hal_flash_unlock_sector(uint32_t sector); /* QUICC Engine */ #define QE_MAX_RISC 1 +#define QE_MURAM_SIZE (24 * 1024) /* QE microcode/firmware address */ #ifndef QE_FW_ADDR #define QE_FW_ADDR 0xEFE00000 /* location in NOR flash */ #endif -#define QE_BASE (CCSRBAR + 0xF000) -#define QE_CEPIER ((volatile uint32_t*)(QE_BASE + 0x00CUL)) -#define QE_CEPIMR ((volatile uint32_t*)(QE_BASE + 0x010UL)) -#define QE_CEPICR ((volatile uint32_t*)(QE_BASE + 0x014UL)) -#define QE_ENGINE_BASE (CCSRBAR + 0x80000) -#define QE_IRAM (QE_ENGINE_BASE + 0x000UL) /* Instruction RAM registers */ -#define QE_IRAM_IADD ((volatile uint32_t*)(QE_IRAM + 0x000UL)) -#define QE_IRAM_IDATA ((volatile uint32_t*)(QE_IRAM + 0x004UL)) -#define QE_IRAM_IREADY ((volatile uint32_t*)(QE_IRAM + 0x00CUL)) +#define QE_BASE (CCSRBAR + 0x140000) +#define QE_IRAM_IADD ((volatile uint32_t*)(QE_BASE + 0x000UL)) +#define QE_IRAM_IDATA ((volatile uint32_t*)(QE_BASE + 0x004UL)) +#define QE_IRAM_IREADY ((volatile uint32_t*)(QE_BASE + 0x00CUL)) + +/* QUICC Engine Interrupt Controller */ +#define QEIC_CIMR ((volatile uint32_t*)(QE_BASE + 0x0A0UL)) -#define QE_CP (QE_ENGINE_BASE + 0x100UL) /* Configuration register */ +/* T1024 -> Two UCCs — UCC1, UCC3 supported - CMX UCC1/3 Clock Route Register */ +#define QE_CMXUCR1 ((volatile uint32_t*)(QE_BASE + 0xC0000 + 0x410UL)) + +/* Baud-Rate Generator Configuration Registers */ +#define BRG_BRGC(n) ((volatile uint32_t*)(QE_BASE + 0xC0000 + 0x640UL + ((n-1) * 0x4))) + +#define QE_CP (QE_BASE + 0x100UL) /* Configuration register */ #define QE_CP_CECR ((volatile uint32_t*)(QE_CP + 0x00)) /* command register */ #define QE_CP_CECDR ((volatile uint32_t*)(QE_CP + 0x08)) /* data register */ #define QE_CP_CERCR ((volatile uint16_t*)(QE_CP + 0x38)) /* RAM control register */ -#define QE_SDMA (QE_ENGINE_BASE + 0x4000UL) /* Serial DMA */ +#define QE_SDMA (QE_BASE + 0x4000UL) /* Serial DMA */ #define QE_SDMA_SDSR ((volatile uint32_t*)(QE_SDMA + 0x00)) #define QE_SDMA_SDMR ((volatile uint32_t*)(QE_SDMA + 0x04)) #define QE_SDMA_SDAQR ((volatile uint32_t*)(QE_SDMA + 0x38)) #define QE_SDMA_SDAQMR ((volatile uint32_t*)(QE_SDMA + 0x3C)) #define QE_SDMA_SDEBCR ((volatile uint32_t*)(QE_SDMA + 0x44)) -#define QE_RSP (QE_ENGINE_BASE + 0x4100UL) /* Special Registers */ +#define QE_RSP (QE_BASE + 0x4100UL) /* Special Registers */ #define QE_RSP_TIBCR(n, i) ((volatile uint32_t*)(QE_RSP + ((n) * 0x100) + (i))) #define QE_RSP_ECCR(n) ((volatile uint32_t*)(QE_RSP + ((n) * 0x100) + 0xF0)) +#define QE_MURAM (QE_BASE + 0x110000UL) /* 24KB */ + #define QE_IRAM_IADD_AIE 0x80000000 /* Auto Increment Enable */ #define QE_IRAM_IADD_BADDR 0x00080000 /* Base Address */ #define QE_IRAM_READY 0x80000000 @@ -174,11 +232,19 @@ static void hal_flash_unlock_sector(uint32_t sector); * - 2-Kbyte SFDRs * - 256 congestion groups */ +#define QMAN_CCSR_BASE (CCSRBAR + 0x318000) +#define QMAN_BASE_PHYS_HIGH 0xF +#define QMAN_BASE_PHYS 0xF6000000 +#define QMAN_NUM_PORTALS 10 /* T1024RM 10.5.2: Buffer Manager (BMan): * - BMan block base address: 31_A000h * - 64 buffer pools */ +#define BMAN_CCSR_BASE (CCSRBAR + 0x31A000) +#define BMAN_BASE_PHYS_HIGH 0xF +#define BMAN_BASE_PHYS 0xF4000000 +#define BMAN_NUM_POOLS 64 /* T1024RM 10.5.4: Security and Encryption Engine (SEC) * - SEC block base address: 30_0000h @@ -229,8 +295,25 @@ static void hal_flash_unlock_sector(uint32_t sector); #endif #define FMAN_BASE (CCSRBAR + 0x400000) -//#define QE_CEPIER ((volatile uint32_t*)(FMAN_BASE + 0x00CUL)) +#define FMAN_MURAM (FMAN_BASE) +#define FMAN_MURAM_SIZE (512 * 1024) + +/* Hardware Ports (0-63) 4KB each (256KB total) */ +#define FMAN_BMI(n) ((FMAN_BASE + 0x80000) + ((n) * 0x1000)) + +#define FMAN_QMI(n) ((FMAN_BASE + 0x80000) + ((n) * 0x1000) + 0x400) + +#define FMAN_DMA (FMAN_BASE + 0xC2000UL) /* FMan DMA */ + +#define FMAN_FPM (FMAN_BASE + 0xC3000UL) /* Frame processing manager (FPM) */ + +#define FMAN_IRAM (FMAN_BASE + 0xC4000UL) /* FMan Controller Configuration Data */ +#define FMAN_IRAM_IADD ((volatile uint32_t*)(FMAN_IRAM + 0x000UL)) /* Address Register (FMCDADDR) */ +#define FMAN_IRAM_IDATA ((volatile uint32_t*)(FMAN_IRAM + 0x004UL)) /* Register (FMCDDATA) */ +#define FMAN_IRAM_IREADY ((volatile uint32_t*)(FMAN_IRAM + 0x00CUL)) /* Ready Register (FMCDREADY) */ +#define FMAN_IRAM_IADD_AIE 0x80000000 /* Auto Increment Enable */ +#define FMAN_IRAM_READY 0x80000000 /* T1024 PC16552D Dual UART */ @@ -407,41 +490,6 @@ enum ifc_amask_sizes { #endif -/* CPLD */ -#define CPLD_BASE 0xFFDF0000 -#define CPLD_BASE_PHYS_HIGH 0xFULL - -#define CPLD_VER 0x00 /* CPLD Major Revision Register */ -#define CPLD_VER_SUB 0x01 /* CPLD Minor Revision Register */ -#define HW_VER 0x02 /* Hardware Revision Register */ -#define SW_VER 0x03 /* Software Revision register */ -#define RESET_CTL1 0x10 /* Reset control Register1 */ -#define RESET_CTL2 0x11 /* Reset control Register2 */ -#define INT_STATUS 0x12 /* Interrupt status Register */ -#define FLASH_CSR 0x13 /* Flash control and status register */ -#define FAN_CTL_STATUS 0x14 /* Fan control and status register */ -#define LED_CTL_STATUS 0x15 /* LED control and status register */ -#define SFP_CTL_STATUS 0x16 /* SFP control and status register */ -#define MISC_CTL_STATUS 0x17 /* Miscellanies ctrl & status register*/ -#define BOOT_OVERRIDE 0x18 /* Boot override register */ -#define BOOT_CONFIG1 0x19 /* Boot config override register*/ -#define BOOT_CONFIG2 0x1A /* Boot config override register*/ - -#define CPLD_LBMAP_MASK 0x3F -#define CPLD_BANK_SEL_MASK 0x07 -#define CPLD_BANK_OVERRIDE 0x40 -#define CPLD_LBMAP_ALTBANK 0x44 /* BANK OR | BANK 4 */ -#define CPLD_LBMAP_DFLTBANK 0x40 /* BANK OR | BANK 0 */ -#define CPLD_LBMAP_RESET 0xFF -#define CPLD_LBMAP_SHIFT 0x03 -#define CPLD_BOOT_SEL 0x80 - -#define CPLD_PCIE_SGMII_MUX 0x80 -#define CPLD_OVERRIDE_BOOT_EN 0x01 -#define CPLD_OVERRIDE_MUX_EN 0x02 /* PCIE/2.5G-SGMII mux override enable */ - -#define CPLD_DATA(n) ((volatile uint8_t*)(CPLD_BASE + n)) - /* DDR4 - 2GB */ /* 1600 MT/s (64-bit, CL=12, ECC on) */ @@ -567,6 +615,43 @@ enum ifc_amask_sizes { #define DDR_SDRAM_INTERVAL_BSTOPRE 0x3FFF +/* CPLD (APU) */ +#define CPLD_BASE 0xFFDF0000 +#define CPLD_BASE_PHYS_HIGH 0xFULL +/* CPLD (MPU) */ +#define CPLD_MPU_BASE 0xFFCF0000 +#define CPLD_MPU_BASE_PHYS_HIGH 0xFULL + +#define BOARD_ID_L_ADDR 0x0002 +#define BOARD_ID_H_ADDR 0x0004 +#define PLD_VER_ADDR 0x0006 +#define POWER_STATUS_ADDRR 0x0400 +#define MPU_INT_STATUS_ADDR 0x0402 +#define MPU_INT_ENABLE_ADDR 0x0404 +#define MPU_CONTROL_ADDR 0x042E +#define MPU_RESET_ADDR 0x0430 +#define PCI_STATUS_ADDR 0x0432 +#define HS_CSR_ADDR 0x103C +#define CPCI_GA_ADDRS 0x103E +#define CPCI_INTX_ADDR 0x1040 +#define PLD_CURRENT_VERSION 0x1042 + +#define CPLD_LBMAP_MASK 0x3F +#define CPLD_BANK_SEL_MASK 0x07 +#define CPLD_BANK_OVERRIDE 0x40 +#define CPLD_LBMAP_ALTBANK 0x44 /* BANK OR | BANK 4 */ +#define CPLD_LBMAP_DFLTBANK 0x40 /* BANK OR | BANK 0 */ +#define CPLD_LBMAP_RESET 0xFF +#define CPLD_LBMAP_SHIFT 0x03 +#define CPLD_BOOT_SEL 0x80 + +#define CPLD_PCIE_SGMII_MUX 0x80 +#define CPLD_OVERRIDE_BOOT_EN 0x01 +#define CPLD_OVERRIDE_MUX_EN 0x02 /* PCIE/2.5G-SGMII mux override enable */ + +#define CPLD_DATA(n) ((volatile uint16_t*)(CPLD_BASE + n)) + + /* eSPI */ #define ESPI_MAX_CS_NUM 4 #define ESPI_MAX_RX_LEN (1 << 16) @@ -609,28 +694,36 @@ enum ifc_amask_sizes { #define ESPI_CSMODE_CSAFT(x) (((x) & 0xF) << 8) /* CS assertion time in bits after frame end */ #define ESPI_CSMODE_CSCG(x) (((x) & 0xF) << 3) /* Clock gaps between transmitted frames according to this size */ - /* generic share NXP QorIQ driver code */ #include "nxp_ppc.c" #ifdef ENABLE_BUS_CLK_CALC -static uint32_t hal_get_bus_clk(void) +static uint32_t hal_get_plat_clk(void) { - /* compute bus clock (system input * ratio) */ - uint32_t plat_clk, bus_clk; + /* compute platform clock (system input * ratio) */ + uint32_t plat_clk; uint32_t plat_ratio = get32(CLOCKING_PLLPGSR); /* see SYS_PLL_RAT in RCW */ /* mask and shift by 1 to get platform ratio */ plat_ratio = ((plat_ratio & 0x3E) >> 1); /* default is 4 (4:1) */ plat_clk = SYS_CLK * plat_ratio; - bus_clk = plat_clk / 2; + return plat_clk; +} + +static uint32_t hal_get_bus_clk(void) +{ + /* compute bus clock (platform clock / 2) */ + uint32_t bus_clk = hal_get_plat_clk() / 2; return bus_clk; } #else -#define hal_get_bus_clk() (uint32_t)((SYS_CLK * 4) / 2) +#define hal_get_plat_clk() (uint32_t)(SYS_CLK * 4) +#define hal_get_bus_clk() (uint32_t)(hal_get_plat_clk() / 2) #endif -#define DELAY_US ((hal_get_bus_clk() / 16) / 1000000) +#define TIMEBASE_CLK_DIV 16 +#define TIMEBASE_HZ (hal_get_plat_clk() / TIMEBASE_CLK_DIV) +#define DELAY_US (TIMEBASE_HZ / 1000000) static void udelay(uint32_t delay_us) { wait_ticks(delay_us * DELAY_US); @@ -638,8 +731,31 @@ static void udelay(uint32_t delay_us) static void law_init(void) { - /* Buffer Manager (BMan) (control) - probably not required */ - set_law(3, 0xF, 0xF4000000, LAW_TRGT_BMAN, LAW_SIZE_32MB, 1); +#ifndef BUILD_LOADER_STAGE1 + /* Buffer Manager (BMan) (control) - 32MB */ + set_law(3, BMAN_BASE_PHYS_HIGH, BMAN_BASE_PHYS, LAW_TRGT_BMAN, LAW_SIZE_32MB, 1); + set_tlb(1, 5, BMAN_BASE_PHYS, + BMAN_BASE_PHYS, BMAN_BASE_PHYS_HIGH, + (MAS3_SX | MAS3_SW | MAS3_SR), 0, 0, BOOKE_PAGESZ_16M, 1); + set_tlb(1, 6, BMAN_BASE_PHYS + 0x01000000, + BMAN_BASE_PHYS + 0x01000000, BMAN_BASE_PHYS_HIGH, + (MAS3_SX | MAS3_SW | MAS3_SR), (MAS2_I | MAS2_G), 0, BOOKE_PAGESZ_16M, 1); + + /* QMAN - 32MB */ + set_law(4, QMAN_BASE_PHYS_HIGH, QMAN_BASE_PHYS, LAW_TRGT_QMAN, LAW_SIZE_32MB, 1); + set_tlb(1, 7, QMAN_BASE_PHYS, + QMAN_BASE_PHYS, QMAN_BASE_PHYS_HIGH, + (MAS3_SX | MAS3_SW | MAS3_SR), 0, 0, BOOKE_PAGESZ_16M, 1); + set_tlb(1, 8, QMAN_BASE_PHYS + 0x01000000, + QMAN_BASE_PHYS + 0x01000000, QMAN_BASE_PHYS_HIGH, + (MAS3_SX | MAS3_SW | MAS3_SR), (MAS2_I | MAS2_G), 0, BOOKE_PAGESZ_16M, 1); + + /* DCSR - 4MB */ + set_law(5, DCSRBAR_BASE_HIGH, DCSRBAR_BASE, LAW_TRGT_DCSR, LAW_SIZE_4MB, 1); + set_tlb(1, 9, DCSRBAR_BASE, + DCSRBAR_BASE, DCSRBAR_BASE_HIGH, + (MAS3_SX | MAS3_SW | MAS3_SR), (MAS2_I | MAS2_G), 0, BOOKE_PAGESZ_4M, 1); +#endif } @@ -760,6 +876,7 @@ void hal_espi_deinit(void) } #endif /* ENABLE_ESPI */ +/* ---- DUART Driver ---- */ #ifdef DEBUG_UART void uart_init(void) { @@ -800,6 +917,7 @@ void uart_write(const char* buf, uint32_t sz) } #endif /* DEBUG_UART */ +/* ---- IFC Driver ---- */ #if defined(ENABLE_IFC) && !defined(BUILD_LOADER_STAGE1) static int hal_flash_getid(void) { @@ -1022,52 +1140,101 @@ void hal_early_init(void) hal_ddr_init(); } -static void hal_cpld_init(void) +#ifdef ENABLE_PCIE +#define CONFIG_SYS_PCIE1_MEM_PHYS_HIGH 0xC +#define CONFIG_SYS_PCIE1_MEM_PHYS 0x00000000 +#define CONFIG_SYS_PCIE1_MEM_VIRT 0x80000000 +#define CONFIG_SYS_PCIE1_IO_PHYS_HIGH 0xF +#define CONFIG_SYS_PCIE1_IO_PHYS 0xF8000000 +#define CONFIG_SYS_PCIE1_IO_VIRT CONFIG_SYS_PCIE1_IO_PHYS + +#define CONFIG_SYS_PCIE2_MEM_PHYS_HIGH 0xC +#define CONFIG_SYS_PCIE2_MEM_PHYS 0x10000000 +#define CONFIG_SYS_PCIE2_MEM_VIRT 0x90000000 +#define CONFIG_SYS_PCIE2_IO_PHYS_HIGHT 0xF +#define CONFIG_SYS_PCIE2_IO_PHYS 0xF8010000 +#define CONFIG_SYS_PCIE2_IO_VIRT CONFIG_SYS_PCIE2_IO_PHYS + +#define CONFIG_SYS_PCIE3_MEM_PHYS_HIGH 0xC +#define CONFIG_SYS_PCIE3_MEM_PHYS 0x20000000 +#define CONFIG_SYS_PCIE3_MEM_VIRT 0xA0000000 +#define CONFIG_SYS_PCIE3_IO_PHYS_HIGH 0xF +#define CONFIG_SYS_PCIE3_IO_PHYS 0xF8020000 +#define CONFIG_SYS_PCIE3_IO_VIRT CONFIG_SYS_PCIE3_IO_PHYS +static int hal_pcie_init(void) { + /* Map TLB for PCIe */ + set_tlb(1, 3, CONFIG_SYS_PCIE1_MEM_VIRT, + CONFIG_SYS_PCIE1_MEM_PHYS, CONFIG_SYS_PCIE1_MEM_PHYS_HIGH, + (MAS3_SX | MAS3_SW | MAS3_SR), (MAS2_I | MAS2_G), 0, BOOKE_PAGESZ_1G, 1); + set_tlb(1, 4, CONFIG_SYS_PCIE1_MEM_VIRT, + CONFIG_SYS_PCIE1_MEM_PHYS, CONFIG_SYS_PCIE1_MEM_PHYS_HIGH, + (MAS3_SX | MAS3_SW | MAS3_SR), (MAS2_I | MAS2_G), 0, BOOKE_PAGESZ_256K, 1); + + return 0; +} +#endif + #ifdef ENABLE_CPLD - #ifdef DEBUG - uint32_t fw; - #endif +static void hal_cpld_ifc_init(uint32_t base, uint32_t base_high, uint8_t ifc) +{ /* CPLD IFC Timing Parameters */ - set32(IFC_FTIM0(2), (IFC_FTIM0_GPCM_TACSE(14) | - IFC_FTIM0_GPCM_TEADC(14) | - IFC_FTIM0_GPCM_TEAHC(14))); - set32(IFC_FTIM1(2), (IFC_FTIM1_GPCM_TACO(14) | - IFC_FTIM1_GPCM_TRAD(31))); - set32(IFC_FTIM2(2), (IFC_FTIM2_GPCM_TCS(14) | - IFC_FTIM2_GPCM_TCH(8) | - IFC_FTIM2_GPCM_TWP(31))); - set32(IFC_FTIM3(2), 0); + set32(IFC_FTIM0(ifc), (IFC_FTIM0_GPCM_TACSE(14UL) | + IFC_FTIM0_GPCM_TEADC(14UL) | + IFC_FTIM0_GPCM_TEAHC(14UL))); + set32(IFC_FTIM1(ifc), (IFC_FTIM1_GPCM_TACO(14UL) | + IFC_FTIM1_GPCM_TRAD(31UL))); + set32(IFC_FTIM2(ifc), (IFC_FTIM2_GPCM_TCS(14UL) | + IFC_FTIM2_GPCM_TCH(8UL) | + IFC_FTIM2_GPCM_TWP(31UL))); + set32(IFC_FTIM3(ifc), 0); /* CPLD IFC Definitions (CS2) */ - set32(IFC_CSPR_EXT(2), CPLD_BASE_PHYS_HIGH); - set32(IFC_CSPR(2), (IFC_CSPR_PHYS_ADDR(CPLD_BASE) | + set32(IFC_CSPR_EXT(ifc), base_high); + set32(IFC_CSPR(ifc), (IFC_CSPR_PHYS_ADDR(base) | IFC_CSPR_PORT_SIZE_8 | IFC_CSPR_MSEL_GPCM | IFC_CSPR_V)); - set32(IFC_AMASK(2), IFC_AMASK_64KB); - set32(IFC_CSOR(2), 0); - - /* IFC - CPLD */ - set_law(2, CPLD_BASE_PHYS_HIGH, CPLD_BASE, - LAW_TRGT_IFC, LAW_SIZE_4KB, 1); + set32(IFC_AMASK(ifc), IFC_AMASK_64KB); + set32(IFC_CSOR(ifc), 0); +} +#endif +static void hal_cpld_init(void) +{ +#ifdef ENABLE_CPLD + #ifdef DEBUG + uint32_t fw; + #endif - /* CPLD - TBL=1, Entry 11 */ - set_tlb(1, 11, CPLD_BASE, CPLD_BASE, CPLD_BASE_PHYS_HIGH, - MAS3_SX | MAS3_SW | MAS3_SR, MAS2_I | MAS2_G, - 0, BOOKE_PAGESZ_4K, 1); + /* CPLD (APU) IFC 2 - LAW 2, TLB 1.11 */ + hal_cpld_ifc_init(CPLD_BASE, CPLD_BASE_PHYS_HIGH, 2); + set_law(2, CPLD_BASE_PHYS_HIGH, CPLD_BASE, LAW_TRGT_IFC, LAW_SIZE_64KB, 1); + set_tlb(1, 11, CPLD_BASE, + CPLD_BASE, CPLD_BASE_PHYS_HIGH, + (MAS3_SX | MAS3_SW | MAS3_SR), + (MAS2_I | MAS2_G), 0, BOOKE_PAGESZ_256K, 1); + + /* CPLD (MPU) IFC 3 - LAW 6, TLB 1.10 */ + hal_cpld_ifc_init(CPLD_MPU_BASE, CPLD_MPU_BASE_PHYS_HIGH, 3); + set_law(6, CPLD_MPU_BASE_PHYS_HIGH, CPLD_MPU_BASE, LAW_TRGT_IFC, + LAW_SIZE_64KB, 1); + set_tlb(1, 10, CPLD_MPU_BASE, + CPLD_MPU_BASE, CPLD_MPU_BASE_PHYS_HIGH, + (MAS3_SX | MAS3_SW | MAS3_SR), + (MAS2_I | MAS2_G), 0, BOOKE_PAGESZ_256K, 1); #ifdef DEBUG - fw = get8(CPLD_DATA(HW_VER)); - wolfBoot_printf("CPLD HW Rev: 0x%x\n", fw); - fw = get8(CPLD_DATA(SW_VER)); - wolfBoot_printf("CPLD SW Rev: 0x%x\n", fw); + fw = get16(CPLD_DATA(BOARD_ID_L_ADDR)) << 16; + fw |= get16(CPLD_DATA(BOARD_ID_H_ADDR)); + wolfBoot_printf("CPLD BOARD_ID: 0x%x\n", fw); + fw = get16(CPLD_DATA(PLD_VER_ADDR)); + wolfBoot_printf("CPLD PLD_VER: 0x%x\n", fw); #endif #endif /* ENABLE_CPLD */ } -/* QE Microcode */ +/* QE Microcode Loading */ #if defined(ENABLE_QE) || defined(ENABLE_FMAN) /* Structure packing */ @@ -1079,7 +1246,6 @@ static void hal_cpld_init(void) #endif /* QE based on work from Shlomi Gridish and Dave Liu at Freescale/NXP */ - struct qe_header { uint32_t length; /* Length of the entire structure, in bytes */ uint8_t magic[3]; /* Set to { 'Q', 'E', 'F' } */ @@ -1121,27 +1287,9 @@ struct qe_firmware { /* CRC32 should be located here, after the microcode binaries */ } QE_PACKED; -static void qe_upload_microcode(const struct qe_firmware *firmware, - const struct qe_microcode *ucode) -{ - const uint32_t *code = (uint32_t*)((uint8_t *)firmware + ucode->code_offset); - unsigned int i; - - wolfBoot_printf("QE: uploading '%s' version %u.%u.%u\n", - ucode->id, ucode->major, ucode->minor, ucode->revision); - - /* Use auto-increment */ - set32(QE_IRAM_IADD, ucode->iram_offset | - QE_IRAM_IADD_AIE | QE_IRAM_IADD_BADDR); - - /* Copy 32-bits at a time to iRAM */ - for (i = 0; i < ucode->count; i++) { - set32(QE_IRAM_IDATA, code[i]); - } -} -/* Upload a microcode to the I-RAM at a specific address */ -static int qe_upload_firmware(const struct qe_firmware *firmware) +/* Checks for valid QE firmware */ +static int qe_check_firmware(const struct qe_firmware *firmware, const char* t) { unsigned int i, j; uint32_t crc; @@ -1155,19 +1303,19 @@ static int qe_upload_firmware(const struct qe_firmware *firmware) /* Check the magic */ if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') || (hdr->magic[2] != 'F')) { - wolfBoot_printf("QE firmware header invalid!\n"); + wolfBoot_printf("%s: firmware header invalid!\n", t); return -1; } /* Check the version */ if (hdr->version != 1) { - wolfBoot_printf("QE version %d unsupported!\n", hdr->version); + wolfBoot_printf("%s: version %d unsupported!\n", t, hdr->version); return -1; } /* Validate some of the fields */ if ((firmware->count < 1) || (firmware->count > QE_MAX_RISC)) { - wolfBoot_printf("QE count %d invalid!\n", firmware->count); + wolfBoot_printf("%s: count %d invalid!\n", t, firmware->count); return -1; } @@ -1182,7 +1330,7 @@ static int qe_upload_firmware(const struct qe_firmware *firmware) /* Validate the length */ if (length != calc_size + sizeof(uint32_t)) { - wolfBoot_printf("QE length %d invalid!\n", length); + wolfBoot_printf("%s: length %d invalid!\n", t, length); return -1; } @@ -1190,18 +1338,112 @@ static int qe_upload_firmware(const struct qe_firmware *firmware) /* Validate the CRC */ crc = *(uint32_t *)((void *)firmware + calc_size); if (crc != (crc32(-1, (const void *) firmware, calc_size) ^ -1)) { - wolfBoot_printf("QE firmware CRC is invalid\n"); + wolfBoot_printf("%s: firmware CRC is invalid\n", t); return -1; } #endif + wolfBoot_printf("%s: Firmware: Length %d, Count %d\n", + t, length, firmware->count); + + return 0; +} +#endif /* ENABLE_QE || ENABLE_FMAN */ + + +struct liodn_id_table { + const char* compat; + uint32_t id; + void* reg_offset; +}; +#define SET_LIODN(fdtcomp, liodn, reg) \ + {.compat = fdtcomp, .id = liodn, .reg_offset = (void*)reg} + +static const struct liodn_id_table liodn_tbl[] = { + SET_LIODN("fsl-usb2-mph", 553, DCFG_USB1LIODNR), + SET_LIODN("fsl-usb2-dr", 554, DCFG_USB2LIODNR), + SET_LIODN("fsl,esdhc", 552, DCFG_SDMMCLIODNR), + SET_LIODN("fsl,pq-sata-v2", 555, DCFG_SATALIODNR), + SET_LIODN("fsl,tdm1.0", 560, DCFG_TDMDMALIODNR), + SET_LIODN("fsl,qe", 559, DCFG_QELIODNR), + SET_LIODN("fsl,elo3-dma", 147, DCFG_DMA1LIODNR), + SET_LIODN("fsl,elo3-dma", 227, DCFG_DMA2LIODNR), + + SET_LIODN("fsl,qman", 62, QMAN_LIODNR), + SET_LIODN("fsl,bman", 63, BMAN_LIODNR), + SET_LIODN("fsl,qoriq-pcie-v2.4", 148, PCIE_LIODN(1)), + SET_LIODN("fsl,qoriq-pcie-v2.4", 228, PCIE_LIODN(2)), + SET_LIODN("fsl,qoriq-pcie-v2.4", 308, PCIE_LIODN(3)), +}; + + +/* Logical I/O Device Number */ +void hal_liodn_init(void) +{ + int i; + for (i=0; i<(int)(sizeof(liodn_tbl)/sizeof(struct liodn_id_table)); i++) { + wolfBoot_printf("LIODN %s: %p=%d\n", + liodn_tbl[i].compat, liodn_tbl[i].reg_offset, liodn_tbl[i].id); + set32(liodn_tbl[i].reg_offset, liodn_tbl[i].id); + } +} + +/* ---- QUICC Engine Driver ---- */ +#ifdef ENABLE_QE + +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 } + +static 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) +}; + +static void qe_upload_microcode(const struct qe_firmware *firmware, + const struct qe_microcode *ucode) +{ + const uint32_t *code = (uint32_t*)((uint8_t *)firmware + ucode->code_offset); + unsigned int i; + + wolfBoot_printf("QE: uploading '%s' version %u.%u.%u\n", + ucode->id, ucode->major, ucode->minor, ucode->revision); + + /* Use auto-increment */ + set32(QE_IRAM_IADD, ucode->iram_offset | + QE_IRAM_IADD_AIE | QE_IRAM_IADD_BADDR); + + /* Copy 32-bits at a time to iRAM */ + for (i = 0; i < ucode->count; i++) { + set32(QE_IRAM_IDATA, code[i]); + } +} + +/* Upload a microcode to the I-RAM at a specific address */ +static int qe_upload_firmware(const struct qe_firmware *firmware) +{ + unsigned int i, j; + /* Use common instruction RAM if not split (default is split) */ if (!firmware->split) { set16(QE_CP_CERCR, get16(QE_CP_CERCR) | QE_CP_CERCR_CIR); } - wolfBoot_printf("QE: Length %d, Count %d\n", length, firmware->count); - /* Loop through each microcode. */ for (i = 0; i < firmware->count; i++) { const struct qe_microcode *ucode = &firmware->microcode[i]; @@ -1229,11 +1471,6 @@ static int qe_upload_firmware(const struct qe_firmware *firmware) return 0; } -#endif - -/* ---- QUICC Engine Driver ---- */ -#ifdef ENABLE_QE - static void qe_issue_cmd(uint32_t cmd, uint32_t sbc, uint8_t mcn, uint32_t cmd_data) { @@ -1251,11 +1488,18 @@ static void qe_issue_cmd(uint32_t cmd, uint32_t sbc, uint8_t mcn, static int hal_qe_init(void) { - int ret; + int ret, i; uint32_t sdma_base; + const struct qe_firmware* fw = (const struct qe_firmware*)QE_FW_ADDR; - /* Upload microcode to IRAM */ - ret = qe_upload_firmware((const struct qe_firmware *)QE_FW_ADDR); + /* setup QE clk */ + set32(SCFG_QEIOCLKCR, get32(SCFG_QEIOCLKCR) | SCFG_QEIOCLKCR_CLK11); + + ret = qe_check_firmware(fw, "QE"); + if (ret == 0) { + /* Upload microcode to IRAM */ + ret = qe_upload_firmware(fw); + } if (ret == 0) { /* enable the microcode in IRAM */ set32(QE_IRAM_IREADY, QE_IRAM_READY); @@ -1266,7 +1510,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 */ @@ -1279,17 +1523,102 @@ static int hal_qe_init(void) qe_issue_cmd(QE_RESET, 0, 0, 0); } + /* Configure QMan software portal base address (QCSP) */ + set32(QCSP_BARE, QMAN_BASE_PHYS_HIGH); + set32(QCSP_BAR, QMAN_BASE_PHYS); + + /* Configure Frame Queue Descriptor (FQD) */ + set32(FQD_BAR, 0); + set32(FQD_AR, 0); + + /* Packed Frame Descriptor Record (PFDR) */ + set32(PFDR_BARE, 0); + set32(PFDR_BAR, 0); + set32(PFDR_AR, 0); + + /* Inhibit BMan/QMan portals by default */ + for (i=0; icode_offset); + unsigned int i; + + wolfBoot_printf("FMAN: uploading '%s' version %u.%u.%u\n", + ucode->id, ucode->major, ucode->minor, ucode->revision); + + /* Use auto-increment */ + set32(FMAN_IRAM_IADD, FMAN_IRAM_IADD_AIE); + + /* Copy 32-bits at a time to iRAM */ + for (i = 0; i < ucode->count; i++) { + set32(FMAN_IRAM_IDATA, code[i]); + } + + /* Verify write is done */ + set32(FMAN_IRAM_IADD, 0); + while (get32(FMAN_IRAM_IDATA) != code[0]); + + /* Enable microcode */ + set32(FMAN_IRAM_IREADY, FMAN_IRAM_READY); + +} + +/* Upload a microcode to the I-RAM at a specific address */ +static int fman_upload_firmware(const struct qe_firmware *firmware) +{ + unsigned int i; + + /* Loop through each microcode. */ + for (i = 0; i < firmware->count; i++) { + const struct qe_microcode *ucode = &firmware->microcode[i]; + uint32_t trapCount = 0; + + /* Upload a microcode if it's present */ + if (ucode->code_offset) { + fman_upload_microcode(firmware, ucode); + } + } + + return 0; +} + static int hal_fman_init(void) { int ret; + const struct qe_firmware* fw = (const struct qe_firmware*)FMAN_FW_ADDR; /* Upload microcode to IRAM */ - ret = qe_upload_firmware((const struct qe_firmware *)FMAN_FW_ADDR); + ret = qe_check_firmware(fw, "FMAN"); + if (ret == 0) { + ret = fman_upload_firmware(fw); + } if (ret == 0) { } @@ -1302,32 +1631,30 @@ static int hal_fman_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 all_cores, active_cores, whoami, bpcr; - uint8_t *spin_table_addr; int timeout = 50, i; whoami = get32(PIC_WHOAMI); /* Get current running core number */ all_cores = ((1 << CPU_NUMCORES) - 1); /* mask of all cores */ active_cores = (1 << whoami); /* current running cores */ - /* 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 (spin table %p)\n", - spin_table_addr); + wolfBoot_printf("MP: Starting core 2 (boot page %p, spin table %p)\n", + bootpg, (uint32_t)&_spin_table); - /* Set the boot page translation reigster */ + /* Set the boot page translation register */ + set32(LCC_BSTRH, 0); set32(LCC_BSTRL, bootpg); set32(LCC_BSTAR, (LCC_BSTAR_EN | - LCC_BSTAR_LAWTRGT(LAW_TRGT_IFC) | + LCC_BSTAR_LAWTRGT(LAW_TRGT_DDR_1) | LAW_SIZE_4KB)); (void)get32(LCC_BSTAR); /* read back to sync */ @@ -1338,11 +1665,11 @@ static void hal_mp_up(uint32_t bootpg) set32(DCFG_BRR, all_cores); __asm__ __volatile__("sync; isync; msync"); - /* wait for other core to start */ + /* wait for other core(s) to start */ 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) { active_cores |= (1 << i); } @@ -1372,23 +1699,29 @@ static void hal_mp_up(uint32_t bootpg) static void hal_mp_init(void) { - uint32_t *fixup = (uint32_t*)&_mp_page_start; - size_t bootpg; + 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 */ + /* Assign virtual boot page at end of DDR (should be 0x7FFFF000) */ 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; + + /* 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 */ + /* 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, urpn */ - MAS3_SX | MAS3_SW | MAS3_SR, MAS2_I | MAS2_G, /* perms, wimge */ + (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 */ @@ -1415,8 +1748,12 @@ void hal_init(void) uart_write("wolfBoot HAL Init\n", 18); #endif + hal_liodn_init(); hal_flash_init(); hal_cpld_init(); +#ifdef ENABLE_PCIE + hal_pcie_init(); +#endif #ifdef ENABLE_QE if (hal_qe_init() != 0) { @@ -1603,7 +1940,133 @@ void* hal_get_dts_address(void) { return (void*)WOLFBOOT_DTS_BOOT_ADDRESS; } -#endif + +int hal_dts_fixup(void* dts_addr) +{ +#ifndef BUILD_LOADER_STAGE1 + struct fdt_header *fdt = (struct fdt_header *)dts_addr; + int off, i; + uint32_t *reg; + + /* verify the FTD is valid */ + off = fdt_check_header(dts_addr); + if (off != 0) { + wolfBoot_printf("FDT: Invalid header! %d\n", off); + return off; + } + + /* display FTD information */ + wolfBoot_printf("FDT: Version %d, Size %d\n", + fdt_version(fdt), fdt_totalsize(fdt)); + + /* expand total size */ + fdt->totalsize += 1024; /* expand by 1KB */ + wolfBoot_printf("FDT: Expanded (1KB) to %d bytes\n", fdt->totalsize); + + /* 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); + fdt_setprop(fdt, off, "reg", ranges, (int)(p - ranges)); + 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; + + 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 = (uint64_t)((uintptr_t)( + (uint8_t*)&_spin_table + (core * ENTRY_SIZE))); + + fdt_fixup_str(fdt, off, "cpu", "status", (core == 0) ? "okay" : "disabled"); + fdt_fixup_val64(fdt, off, "cpu", "cpu-release-addr", core_spin_table); + fdt_fixup_str(fdt, off, "cpu", "enable-method", "spin-table"); + fdt_fixup_val(fdt, off, "cpu", "timebase-frequency", TIMEBASE_HZ); + fdt_fixup_val(fdt, off, "cpu", "clock-frequency", hal_get_plat_clk()); + fdt_fixup_val(fdt, off, "cpu", "bus-frequency", hal_get_plat_clk()); + + off = fdt_find_devtype(fdt, off, "cpu"); + } + + /* fixup the soc clock */ + off = fdt_find_devtype(fdt, -1, "soc"); + if (off != -FDT_ERR_NOTFOUND) { + fdt_fixup_val(fdt, off, "soc", "bus-frequency", hal_get_plat_clk()); + } + + /* fixup the serial clocks */ + off = fdt_find_devtype(fdt, -1, "serial"); + while (off != -FDT_ERR_NOTFOUND) { + fdt_fixup_val(fdt, off, "serial", "clock-frequency", hal_get_bus_clk()); + 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) { + fdt_fixup_val(fdt, off, "qe", "clock-frequency", hal_get_bus_clk()); + fdt_fixup_val(fdt, off, "qe", "bus-frequency", hal_get_bus_clk()); + fdt_fixup_val(fdt, off, "qe", "brg-frequency", hal_get_bus_clk()/2); + } + + /* 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) { + fdt_fixup_val(fdt, off, liodn_tbl[i].compat, "fsl,liodn", + liodn_tbl[i].id); + } + } + + /* fixup the QMAN portals */ + off = fdt_node_offset_by_compatible(fdt, -1, "fsl,qman-portal"); + while (off != -FDT_ERR_NOTFOUND) { + uint32_t liodns[2]; + + reg = (uint32_t*)fdt_getprop(fdt, off, "cell-index", NULL); + if (reg == NULL) + break; + i = (int)fdt32_to_cpu(*reg); + if (i >= QMAN_NUM_PORTALS) { + break; /* invalid index */ + } + 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]); + fdt_setprop(fdt, off, "fsl,liodn", liodns, sizeof(liodns)); + + 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) { + fdt_fixup_val(fdt, off, "open-pic", "clock-frequency", hal_get_bus_clk()); + } +#endif /* !BUILD_LOADER_STAGE1 */ + return 0; +} +#endif /* MMU */ + #if defined(ENABLE_DDR) && defined(TEST_DDR) diff --git a/hal/nxp_t1024.ld b/hal/nxp_t1024.ld index 06baab811..d7cf8794a 100644 --- a/hal/nxp_t1024.ld +++ b/hal/nxp_t1024.ld @@ -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*) diff --git a/hal/nxp_t2080.c b/hal/nxp_t2080.c index adbdb302f..ea0f4eb65 100644 --- a/hal/nxp_t2080.c +++ b/hal/nxp_t2080.c @@ -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) */ diff --git a/hal/nxp_t2080.ld b/hal/nxp_t2080.ld index 3ee1be3f4..43e692cab 100644 --- a/hal/nxp_t2080.ld +++ b/hal/nxp_t2080.ld @@ -41,6 +41,7 @@ SECTIONS _start_vector = .; KEEP(*(.isr_vector)) . = ALIGN(256); + KEEP(*(.bootmp)) *(.text*) *(.rodata*) *(.sdata*) diff --git a/include/fdt.h b/include/fdt.h new file mode 100644 index 000000000..12a50774c --- /dev/null +++ b/include/fdt.h @@ -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 + +#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 */ diff --git a/include/image.h b/include/image.h index dfade4b95..9315e02e5 100644 --- a/include/image.h +++ b/include/image.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 - \ diff --git a/src/boot_ppc.c b/src/boot_ppc.c index 1df610556..e63b1ece6 100644 --- a/src/boot_ppc.c +++ b/src/boot_ppc.c @@ -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); diff --git a/src/boot_ppc_mp.S b/src/boot_ppc_mp.S index 2eb099785..25dea2c4c 100644 --- a/src/boot_ppc_mp.S +++ b/src/boot_ppc_mp.S @@ -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) */ + +#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 - /* Load r13 with the address of the boot page */ - lis r13, TORESET(_bootpg_addr)@h - ori r13, r13, TORESET(_bootpg_addr)@l + /* 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) diff --git a/src/boot_ppc_start.S b/src/boot_ppc_start.S index 918b9da95..3ce577cc9 100644 --- a/src/boot_ppc_start.S +++ b/src/boot_ppc_start.S @@ -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 diff --git a/src/fdt.c b/src/fdt.c new file mode 100644 index 000000000..ae5b7f5cc --- /dev/null +++ b/src/fdt.c @@ -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 + +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 */ diff --git a/src/image.c b/src/image.c index c272c74ce..9ec37b810 100644 --- a/src/image.c +++ b/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 /* 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 diff --git a/src/libwolfboot.c b/src/libwolfboot.c index 9d9c5490f..3dc961bfc 100644 --- a/src/libwolfboot.c +++ b/src/libwolfboot.c @@ -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; diff --git a/src/string.c b/src/string.c index 983db8eeb..3401ebc4e 100644 --- a/src/string.c +++ b/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) */ diff --git a/test-app/Makefile b/test-app/Makefile index e0bca642c..91398def6 100644 --- a/test-app/Makefile +++ b/test-app/Makefile @@ -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) diff --git a/tools/elf-parser/Makefile b/tools/elf-parser/Makefile index fd89e343c..585d8a973 100644 --- a/tools/elf-parser/Makefile +++ b/tools/elf-parser/Makefile @@ -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= diff --git a/tools/fdt-parser/Makefile b/tools/fdt-parser/Makefile new file mode 100644 index 000000000..744f47c1d --- /dev/null +++ b/tools/fdt-parser/Makefile @@ -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) diff --git a/tools/fdt-parser/fdt-parser.c b/tools/fdt-parser/fdt-parser.c new file mode 100644 index 000000000..723e01875 --- /dev/null +++ b/tools/fdt-parser/fdt-parser.c @@ -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 +#include +#include + +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; +} diff --git a/tools/fdt-parser/nxp_t1024.dtb b/tools/fdt-parser/nxp_t1024.dtb new file mode 100644 index 000000000..0daaf6a9e Binary files /dev/null and b/tools/fdt-parser/nxp_t1024.dtb differ