diff --git a/arch.mk b/arch.mk index d001f7c2..4436093b 100644 --- a/arch.mk +++ b/arch.mk @@ -331,6 +331,7 @@ ifeq ($(TARGET),nxp_p1021) # Use the SP math all assembly accelerations CFLAGS+=-DWOLFSSL_SP_PPC endif + SPI_TARGET=nxp endif ifeq ($(TARGET),ti_hercules) diff --git a/config/examples/nxp-p1021.config b/config/examples/nxp-p1021.config old mode 100644 new mode 100755 index ee20155e..621ef383 --- a/config/examples/nxp-p1021.config +++ b/config/examples/nxp-p1021.config @@ -20,12 +20,13 @@ SPMATH?=0 SPMATHALL?=1 RAM_CODE?=0 DUALBANK_SWAP?=0 -WOLFTPM?=0 +WOLFTPM?=1 # Flash Sector (Block) Size (16KB) WOLFBOOT_SECTOR_SIZE=0x4000 -# Maximum size of wolfBoot stage 1 loader +# Maximum size of wolfBoot stage 1 loader (can be increased for debugging) +# Needs to be 4KB 0x1000 to fit into boot ROM loaded region WOLFBOOT_STAGE1_SIZE=0x1000 # wolfBoot partition size (128KB) @@ -39,7 +40,7 @@ WOLFBOOT_PARTITION_SIZE?=0x1000000 # Location in Flash for stage 1 loader (XIP from boot ROM) WOLFBOOT_STAGE1_FLASH_ADDR=0x0 # Location in Flash for wolfBoot -WOLFBOOT_ORIGIN=0x4000 +WOLFBOOT_ORIGIN=0x8000 # Location in Flash for Application Partition WOLFBOOT_PARTITION_BOOT_ADDRESS?= 0x200000 # Location in Flash for Update Partition @@ -49,7 +50,7 @@ WOLFBOOT_PARTITION_SWAP_ADDRESS?= 0x2200000 ## Loader Destinations (DDR) ## -# Address in RAM to load stage 1 loader +# Address in RAM to load stage 1 loader (can't be 0x0) WOLFBOOT_STAGE1_BASE_ADDR=0x4000 # Address in RAM to load wolfBoot diff --git a/docs/Targets.md b/docs/Targets.md index 8939b9dc..a5d0a453 100644 --- a/docs/Targets.md +++ b/docs/Targets.md @@ -1162,6 +1162,22 @@ make clean && make | swap block | 0x02200000 | +### Debugging NXP P1021 PPC + +Use `V=1` to show verbose output for build steps. +Use `DEBUG=1` to enable debug symbols. + +The first stage loader must fit into 4KB. To build this in release and assemble a debug version of wolfBoot use the following steps: + +``` +make clean +make stage1 +make DEBUG=1 wolfboot.bin +make DEBUG=1 test-app/image_v1_signed.bin +make factory_wstage1.bin +``` + + ## NXP QorIQ T2080 PPC The NXP QorIQ T2080 is a PPC e6500 based processor (four cores). Support has been tested with the NAII 68PPC2. diff --git a/hal/nxp_p1021.c b/hal/nxp_p1021.c old mode 100755 new mode 100644 index cd743f25..d14a5785 --- a/hal/nxp_p1021.c +++ b/hal/nxp_p1021.c @@ -34,6 +34,10 @@ #define ENABLE_CONF_IO #endif +#ifdef WOLFBOOT_TPM + #define ENABLE_ESPI +#endif + /* TODO */ /* Ethernet */ /* QUICC */ @@ -51,7 +55,8 @@ static int test_flash(void); /* P1021 Platform */ -#define SYS_CLK (533000000) /* 533MHz */ +//#define SYS_CLK (533000000) /* 533MHz */ + #define SYS_CLK (400000000) /* 400MHz */ #define RESET_BPTR ((volatile uint32_t*)(CCSRBAR + 0x42)) /* Boot page translation register */ @@ -380,6 +385,113 @@ enum elbc_amask_sizes { #define ECM_BASE (CCSRBAR + 0x1000) #define ECM_EEBACR ((volatile uint32_t*)(ECM_BASE + 0x0)) /* ECM CCB address configuration register */ +/* eSPI */ +#define ESPI_MAX_CS_NUM 4 +#define ESPI_MAX_RX_LEN (1 << 16) + +#define ESPI_BASE (CCSRBAR + 0x7000) +#define ESPI_SPMODE ((volatile uint32_t*)(ESPI_BASE + 0x00)) /* controls eSPI general operation mode */ +#define ESPI_SPIE ((volatile uint32_t*)(ESPI_BASE + 0x04)) /* controls interrupts and report events */ +#define ESPI_SPIM ((volatile uint32_t*)(ESPI_BASE + 0x08)) /* enables/masks interrupts */ +#define ESPI_SPCOM ((volatile uint32_t*)(ESPI_BASE + 0x0C)) /* command frame information */ +#define ESPI_SPITF ((volatile uint32_t*)(ESPI_BASE + 0x10)) /* transmit FIFO access register */ +#define ESPI_SPIRF ((volatile uint32_t*)(ESPI_BASE + 0x14)) /* 32-bit read-only receive data register */ +#define ESPI_SPCSMODE(x) ((volatile uint32_t*)(ESPI_BASE + 0x20 + ((cs) * 4))) /* controls master operation with chip select 0-3 */ + +#define ESPI_SPMODE_EN (0x80000000) /* Enable eSPI */ +#define ESPI_SPMODE_TXTHR(x) ((x) << 8) /* Tx FIFO threshold (1-32) */ +#define ESPI_SPMODE_RXTHR(x) ((x) << 0) /* Rx FIFO threshold (0-31) */ + +#define ESPI_SPCOM_CS(x) ((x) << 30) /* Chip select-chip select for which transaction is destined */ +#define ESPI_SPCOM_RXSKIP(x) ((x) << 16) /* Number of characters skipped for reception from frame start */ +#define ESPI_SPCOM_TRANLEN(x) (((x) - 1) << 0) /* Transaction length */ + +#define ESPI_SPIE_RNE (1 << 9) /* recevie not empty */ +#define ESPI_SPIE_TNF (1 << 8) /* transmit not full */ + +#define ESPI_CSMODE_CI 0x80000000 /* Inactive high */ +#define ESPI_CSMODE_CP 0x40000000 /* Begin edge clock */ +#define ESPI_CSMODE_REV 0x20000000 /* MSB first */ +#define ESPI_CSMODE_DIV16 0x10000000 /* divide system clock by 16 */ +#define ESPI_CSMODE_PM(x) (((x) & 0xF) << 24) /* presale modulus select */ +#define ESPI_CSMODE_POL 0x00100000 /* asserted low */ +#define ESPI_CSMODE_LEN(x) ((((x) - 1) & 0xF) << 16) /* Character length in bits per character */ +#define ESPI_CSMODE_CSBEF(x) (((x) & 0xF) << 12) /* CS assertion time in bits before frame start */ +#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 */ + +#ifdef ENABLE_ESPI +void hal_espi_init(uint32_t cs, uint32_t clock_hz, uint32_t mode) +{ + uint32_t spibrg = SYS_CLK / 2, pm, csmode; + + /* Enable eSPI with TX threadshold 4 and TX threshold 3 */ + set32(ESPI_SPMODE, (ESPI_SPMODE_EN | ESPI_SPMODE_TXTHR(4) | + ESPI_SPMODE_RXTHR(3))); + + set32(ESPI_SPIE, 0xffffffff); /* Clear all eSPI events */ + set32(ESPI_SPIM, 0x00000000); /* Mask all eSPI interrupts */ + + csmode = (ESPI_CSMODE_REV | ESPI_CSMODE_POL | ESPI_CSMODE_LEN(8) | + ESPI_CSMODE_CSBEF(0) | ESPI_CSMODE_CSAFT(0) | ESPI_CSMODE_CSCG(1)); + + /* calculate clock divisor */ + if (spibrg / clock_hz > 16) { + csmode |= ESPI_CSMODE_DIV16; + pm = (spibrg / (clock_hz * 16)); + } + else { + pm = (spibrg / (clock_hz)); + } + if (pm > 0) + pm--; + csmode |= ESPI_CSMODE_PM(pm); + + if (mode & 1) + csmode |= ESPI_CSMODE_CP; + if (mode & 2) + csmode |= ESPI_CSMODE_CI; + + /* configure CS */ + set32(ESPI_SPCSMODE(cs), csmode); +} +int hal_espi_xfer(int cs, const uint8_t* tx, uint8_t* rx, uint32_t sz) +{ + uint32_t reg, blks; + + /* assert CS */ + set32(ESPI_SPCOM, ESPI_SPCOM_CS(cs) | ESPI_SPCOM_TRANLEN(sz)); + + set32(ESPI_SPIE, 0xffffffff); /* Clear all eSPI events */ + + /* calculate the number of 4 byte blocks rounded up */ + blks = (sz + 3) / 4; + while (blks--) { + /* wait till TX fifo has room */ + while ((get32(ESPI_SPIE) & ESPI_SPIE_TNF) == 0); + reg = *((uint32_t*)tx); + set32(ESPI_SPITF, reg); + tx += 4; + + /* wait till RX has data */ + while ((get32(ESPI_SPIE) & ESPI_SPIE_RNE) == 0); + reg = get32(ESPI_SPIRF); + *((uint32_t*)rx) = reg; + rx += 4; + } + + /* toggle ESPI_SPMODE_EN - to deassert CS */ + reg = get32(ESPI_SPMODE); + set32(ESPI_SPMODE, reg & ~ESPI_SPMODE_EN); + set32(ESPI_SPMODE, reg); + + return 0; +} +void hal_espi_deinit(void) +{ + /* do nothing */ +} +#endif /* ENABLE_ESPI */ static void set_law(uint8_t idx, uint32_t addr, uint32_t trgt_id, @@ -932,10 +1044,7 @@ void hal_init(void) #ifdef DEBUG_UART uart_init(); - - #ifdef DEBUG - uart_write("wolfBoot Init\r\n", 15); - #endif + uart_write("wolfBoot HAL Init\r\n", 19); #endif #ifdef GET_PSVR diff --git a/hal/nxp_p1021.ld b/hal/nxp_p1021.ld index 4675f0fc..13465119 100644 --- a/hal/nxp_p1021.ld +++ b/hal/nxp_p1021.ld @@ -79,3 +79,4 @@ SECTIONS PROVIDE(_start_heap = _end); PROVIDE(_end_stack = _end + HEAP_SIZE + STACK_SIZE ); + diff --git a/hal/renesas-ra.c b/hal/renesas-ra.c old mode 100755 new mode 100644 diff --git a/hal/spi/spi_drv_nrf52.c b/hal/spi/spi_drv_nrf52.c index 1f7df73f..fd45e22b 100644 --- a/hal/spi/spi_drv_nrf52.c +++ b/hal/spi/spi_drv_nrf52.c @@ -28,6 +28,8 @@ #include "spi_drv.h" #include "spi_drv_nrf52.h" +#if defined(SPI_FLASH) || defined(WOLFBOOT_TPM) + #define SPI0 (0x40003000) #define SPI1 (0x40004000) #define SPI2 (0x40023000) @@ -122,3 +124,19 @@ void spi_release(void) { } + +#ifdef WOLFBOOT_TPM +int spi_xfer(int cs, const uint8_t* tx, uint8_t* rx, uint32_t sz) +{ + uint32_t i; + spi_cs_on(SPI_CS_TPM_PIO_BASE, cs); + for (i = 0; i < sz; i++) { + spi_write((const char)tx[i]); + rx[i] = spi_read(); + } + spi_cs_off(SPI_CS_TPM_PIO_BASE, cs); + return 0; +} +#endif /* WOLFBOOT_TPM */ + +#endif /* SPI_FLASH || WOLFBOOT_TPM */ diff --git a/hal/spi/spi_drv_nxp.c b/hal/spi/spi_drv_nxp.c new file mode 100644 index 00000000..74d001be --- /dev/null +++ b/hal/spi/spi_drv_nxp.c @@ -0,0 +1,62 @@ +/* spi_drv_nxp.c + * + * Driver for the SPI back-end of the SPI_FLASH module. + * + * Pinout: see spi_drv_nxp.h + * + * 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 + */ +#include +#include +#include "spi_drv.h" +#include "spi_drv_nxp.h" + +#ifdef WOLFBOOT_TPM + +#if defined(PLATFORM_nxp_p1021) +/* functions from nxp_p1021.c hal */ +extern void hal_espi_init(uint32_t cs, uint32_t clock_hz, uint32_t mode); +extern int hal_espi_xfer(int cs, const uint8_t* tx, uint8_t* rx, uint32_t sz); +extern void hal_espi_deinit(void); +#endif + +#include + +void spi_init(int polarity, int phase) +{ + static int initialized = 0; + if (!initialized) { + initialized++; + + hal_espi_init(SPI_CS_TPM, TPM2_SPI_MAX_HZ, (polarity | (phase << 1))); + } + (void)polarity; + (void)phase; +} + +void spi_release(void) +{ + hal_espi_deinit(); +} + +int spi_xfer(int cs, const uint8_t* tx, uint8_t* rx, uint32_t sz) +{ + return hal_espi_xfer(cs, tx, rx, sz); +} +#endif /* WOLFBOOT_TPM */ diff --git a/hal/spi/spi_drv_nxp.h b/hal/spi/spi_drv_nxp.h new file mode 100644 index 00000000..be742394 --- /dev/null +++ b/hal/spi/spi_drv_nxp.h @@ -0,0 +1,32 @@ +/* spi_drv_nxp.h + * + * 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 SPI_DRV_NXP_H_INCLUDED +#define SPI_DRV_NXP_H_INCLUDED + +#include + +#if defined(PLATFORM_nxp_p1021) + +/* Chip select for TPM */ +#ifndef SPI_CS_TPM +#define SPI_CS_TPM 2 +#endif + +#endif + +#endif /* !SPI_DRV_NXP_H_INCLUDED */ diff --git a/hal/spi/spi_drv_stm32.c b/hal/spi/spi_drv_stm32.c index 9516deb0..750ed1ea 100644 --- a/hal/spi/spi_drv_stm32.c +++ b/hal/spi/spi_drv_stm32.c @@ -499,4 +499,18 @@ void RAMFUNCTION spi_release(void) } } +#ifdef WOLFBOOT_TPM +int spi_xfer(int cs, const uint8_t* tx, uint8_t* rx, uint32_t sz) +{ + uint32_t i; + spi_cs_on(SPI_CS_TPM_PIO_BASE, cs); + for (i = 0; i < sz; i++) { + spi_write((const char)tx[i]); + rx[i] = spi_read(); + } + spi_cs_off(SPI_CS_TPM_PIO_BASE, cs); + return 0; +} +#endif /* WOLFBOOT_TPM */ + #endif /* SPI_FLASH || WOLFBOOT_TPM || QSPI_FLASH || OCTOSPI_FLASH */ diff --git a/hal/spi/spi_drv_zynq.c b/hal/spi/spi_drv_zynq.c index 442c05ca..1fc41a93 100644 --- a/hal/spi/spi_drv_zynq.c +++ b/hal/spi/spi_drv_zynq.c @@ -29,7 +29,7 @@ #include "spi_drv.h" #include "spi_drv_zynq.h" -#ifdef SPI_FLASH +#if defined(SPI_FLASH) || defined(WOLFBOOT_TPM) void spi_cs_off(uint32_t base, int pin) { @@ -70,4 +70,18 @@ void spi_release(void) } -#endif +#ifdef WOLFBOOT_TPM +int spi_xfer(int cs, const uint8_t* tx, uint8_t* rx, uint32_t sz) +{ + uint32_t i; + spi_cs_on(SPI_CS_TPM_PIO_BASE, cs); + for (i = 0; i < sz; i++) { + spi_write((const char)tx[i]); + rx[i] = spi_read(); + } + spi_cs_off(SPI_CS_TPM_PIO_BASE, cs); + return 0; +} +#endif /* WOLFBOOT_TPM */ + +#endif /* SPI_FLASH | WOLFBOOT_TPM */ diff --git a/include/spi_drv.h b/include/spi_drv.h index e42d65e9..4bd8326b 100644 --- a/include/spi_drv.h +++ b/include/spi_drv.h @@ -49,15 +49,23 @@ #include "hal/spi/spi_drv_nrf52.h" #endif +#if defined(PLATFORM_nxp_p1021) +#include "hal/spi/spi_drv_nxp.h" +#endif + void spi_init(int polarity, int phase); void spi_release(void); -#if defined(SPI_FLASH) || defined(WOLFBOOT_TPM) +#ifdef SPI_FLASH void spi_cs_on(uint32_t base, int pin); void spi_cs_off(uint32_t base, int pin); void spi_write(const char byte); uint8_t spi_read(void); -#endif /* SPI_FLASH || WOLFBOOT_TPM */ +#endif + +#ifdef WOLFBOOT_TPM +int spi_xfer(int cs, const uint8_t* tx, uint8_t* rx, uint32_t sz); +#endif #if defined(QSPI_FLASH) || defined(OCTOSPI_FLASH) diff --git a/options.mk b/options.mk index 36ff8727..d0a70136 100644 --- a/options.mk +++ b/options.mk @@ -448,8 +448,7 @@ ifeq ($(WOLFTPM),1) -D"MAX_COMMAND_SIZE=1024" -D"MAX_RESPONSE_SIZE=1024" -D"WOLFTPM2_MAX_BUFFER=1500" \ -D"MAX_SESSION_NUM=2" -D"MAX_DIGEST_BUFFER=973" \ -D"WOLFTPM_SMALL_STACK" - # Chip Type: WOLFTPM_SLB9670, WOLFTPM_ST33, WOLFTPM_MCHP - CFLAGS+=-D"WOLFTPM_SLB9670" + CFLAGS+=-D"WOLFTPM_AUTODETECT" # Use TPM for hashing (slow) #CFLAGS+=-D"WOLFBOOT_HASH_TPM" ifneq ($(SPI_FLASH),1) diff --git a/src/image.c b/src/image.c index 35b79f39..dd636f4c 100644 --- a/src/image.c +++ b/src/image.c @@ -717,17 +717,11 @@ static void key_sha3_384(uint8_t key_slot, uint8_t *hash) static int TPM2_IoCb(TPM2_CTX* ctx, const byte* txBuf, byte* rxBuf, word16 xferSz, void* userCtx) { - (void)userCtx; - (void)ctx; - word16 i; - spi_cs_on(SPI_CS_TPM_PIO_BASE, SPI_CS_TPM); + int ret; + memset(rxBuf, 0, xferSz); - for (i = 0; i < xferSz; i++) - { - spi_write(txBuf[i]); - rxBuf[i] = spi_read(); - } - spi_cs_off(SPI_CS_TPM_PIO_BASE, SPI_CS_TPM); + ret = spi_xfer(SPI_CS_TPM, txBuf, rxBuf, xferSz); + /* printf("\r\nSPI TX: "); printbin(txBuf, xferSz); @@ -735,7 +729,11 @@ static int TPM2_IoCb(TPM2_CTX* ctx, const byte* txBuf, byte* rxBuf, printbin(rxBuf, xferSz); printf("\r\n"); */ - return 0; + + (void)userCtx; + (void)ctx; + + return ret; } #endif /* !ARCH_SIM */ @@ -791,17 +789,18 @@ int wolfBoot_tpm2_init(void) #else rc = wolfTPM2_Init(&wolftpm_dev, TPM2_IoCb, NULL); #endif - if (rc != 0) { - return rc; + if (rc == 0) { + /* Get device capabilities + options */ + rc = wolfTPM2_GetCapabilities(&wolftpm_dev, &caps); + } + if (rc == 0) { + wolfBoot_printf("Mfg %s (%d), Vendor %s, Fw %u.%u (0x%x), " + "FIPS 140-2 %d, CC-EAL4 %d\n", + caps.mfgStr, caps.mfg, caps.vendorStr, caps.fwVerMajor, + caps.fwVerMinor, caps.fwVerVendor, caps.fips140_2, caps.cc_eal4); } - /* Get device capabilities + options */ - rc = wolfTPM2_GetCapabilities(&wolftpm_dev, &caps); - if (rc != 0) { - return rc; - } - - return 0; + return rc; } /* Currently only supports ecc256 */ diff --git a/stage1/Makefile b/stage1/Makefile index 395bf63a..ba27802e 100644 --- a/stage1/Makefile +++ b/stage1/Makefile @@ -29,6 +29,9 @@ OBJS:= \ WOLFCRYPT_OBJS:= PUBLIC_KEY_OBJS:= +# Forcefully disable TPM support in first stage loader +WOLFTPM=0 + ## Architecture/CPU configuration include ../arch.mk diff --git a/stage1/loader_stage1.c b/stage1/loader_stage1.c index d7e577f7..0495139d 100644 --- a/stage1/loader_stage1.c +++ b/stage1/loader_stage1.c @@ -40,12 +40,6 @@ #define WOLFBOOT_STAGE1_SIZE (4*1024) #endif -#ifndef WOLFBOOT_STAGE1_START_ADDR - /* default is end of 4KB region (0x0FFC) */ - #define WOLFBOOT_STAGE1_START_ADDR \ - (WOLFBOOT_STAGE1_LOAD_ADDR + WOLFBOOT_STAGE1_SIZE - 0x4) -#endif - #ifdef BUILD_LOADER_STAGE1 #if defined(WOLFBOOT_ARCH) && WOLFBOOT_ARCH == PPC @@ -87,7 +81,13 @@ int main(void) BOOTLOADER_PARTITION_SIZE /* boot-loader partition (entire) */ ); if (ret >= 0) { - wolfboot_start = (void*)WOLFBOOT_STAGE1_START_ADDR; + wolfboot_start = (void*)WOLFBOOT_STAGE1_LOAD_ADDR; + #ifdef PRINTF_ENABLED + wolfBoot_printf("Jumping to %p\r\n", wolfboot_start); + #elif defined(DEBUG_UART) + uart_write("Jump to relocated wolfboot_start\r\n", 34); + #endif + wolfboot_start(); /* never returns */ }