From a0e344237461808a953fef448399461aadfecca6 Mon Sep 17 00:00:00 2001 From: David Garske Date: Mon, 8 Dec 2025 15:55:20 -0800 Subject: [PATCH 01/13] Support for Microchip PolarFire SoC (MPFS250) --- .github/workflows/test-build-riscv.yml | 29 +- .github/workflows/test-configs.yml | 12 + Makefile | 2 +- arch.mk | 50 +- config/examples/polarfire_mpfs250.config | 54 ++ config/examples/raspi3-encrypted.config | 1 - docs/Targets.md | 105 +++ hal/hifive1.c | 12 +- hal/mpfs.dtb | Bin 0 -> 19897 bytes hal/mpfs.dts | 924 +++++++++++++++++++++++ hal/mpfs.yaml | 21 + hal/mpfs250.c | 266 +++++++ hal/mpfs250.h | 153 ++++ hal/mpfs250.ld | 60 ++ hal/x86_fsp_qemu_loader.c | 7 - include/{x86/gpt.h => disk.h} | 13 +- include/gpt.h | 154 ++++ include/loader.h | 4 + include/user_settings.h | 3 + include/x86/common.h | 6 +- src/boot_arm32.c | 2 +- src/boot_ppc.c | 5 +- src/boot_riscv64.c | 95 +++ src/boot_riscv64_start.S | 138 ++++ src/elf.c | 2 +- src/fdt.c | 4 +- src/gpt.c | 210 ++++++ src/update_disk.c | 202 +++-- src/update_flash.c | 5 + src/update_ram.c | 2 +- src/vector_riscv64.S | 179 +++++ src/x86/{gpt.c => disk.c} | 247 +++--- test-app/Makefile | 5 + test-app/RISCV64-mpfs250.ld | 106 +++ test-app/app_mpfs250.c | 159 ++++ tools/elf-parser/Makefile | 2 +- tools/fdt-parser/Makefile | 2 +- tools/scripts/x86_fsp/qemu/qemu.sh | 1 + 38 files changed, 2993 insertions(+), 249 deletions(-) create mode 100644 config/examples/polarfire_mpfs250.config create mode 100644 hal/mpfs.dtb create mode 100644 hal/mpfs.dts create mode 100644 hal/mpfs.yaml create mode 100644 hal/mpfs250.c create mode 100644 hal/mpfs250.h create mode 100644 hal/mpfs250.ld rename include/{x86/gpt.h => disk.h} (90%) create mode 100644 include/gpt.h create mode 100644 src/boot_riscv64.c create mode 100644 src/boot_riscv64_start.S create mode 100644 src/gpt.c create mode 100644 src/vector_riscv64.S rename src/x86/{gpt.c => disk.c} (58%) create mode 100644 test-app/RISCV64-mpfs250.ld create mode 100644 test-app/app_mpfs250.c diff --git a/.github/workflows/test-build-riscv.yml b/.github/workflows/test-build-riscv.yml index 95893d7f91..eae92fbf0e 100644 --- a/.github/workflows/test-build-riscv.yml +++ b/.github/workflows/test-build-riscv.yml @@ -26,6 +26,7 @@ jobs: submodules: true - uses: actions/checkout@v4 + if: ${{ inputs.arch == 'riscv' }} with: repository: sifive/freedom-e-sdk path: freedom-e-sdk @@ -79,12 +80,21 @@ jobs: - name: Update repository run: sudo apt-get update -o Acquire::Retries=3 - - name: Download and install SiFive RISC-V toolchain + - name: Download and install RISC-V toolchain + if: ${{ inputs.arch == 'riscv' }} run: | - # Download SiFive prebuilt toolchain with newlib - wget -q https://static.dev.sifive.com/dev-tools/freedom-tools/v2020.12/riscv64-unknown-elf-toolchain-10.2.0-2020.12.8-x86_64-linux-ubuntu14.tar.gz - tar xzf riscv64-unknown-elf-toolchain-10.2.0-2020.12.8-x86_64-linux-ubuntu14.tar.gz - echo "$GITHUB_WORKSPACE/riscv64-unknown-elf-toolchain-10.2.0-2020.12.8-x86_64-linux-ubuntu14/bin" >> $GITHUB_PATH + # Download latest prebuilt RISC-V toolchains + wget -q https://github.com/RISCV-Tools/riscv-gnu-toolchain/releases/latest/download/riscv32-elf-ubuntu-24.04-gcc.tar.xz + tar -xf riscv32-elf-ubuntu-24.04-gcc.tar.xz + echo "$GITHUB_WORKSPACE/riscv/bin" >> $GITHUB_PATH + + - name: Download and install RISC-V toolchain + if: ${{ inputs.arch == 'riscv64' }} + run: | + # Download latest prebuilt RISC-V toolchains + wget -q https://github.com/RISCV-Tools/riscv-gnu-toolchain/releases/latest/download/riscv64-elf-ubuntu-24.04-gcc.tar.xz + tar -xf riscv64-elf-ubuntu-24.04-gcc.tar.xz + echo "$GITHUB_WORKSPACE/riscv/bin" >> $GITHUB_PATH - name: make clean run: | @@ -98,7 +108,12 @@ jobs: run: | make -C tools/keytools && make -C tools/bin-assemble - - name: Build wolfboot + - name: Build wolfboot (riscv32) + if: ${{ inputs.arch == 'riscv' }} run: | - make FREEDOM_E_SDK=$GITHUB_WORKSPACE/freedom-e-sdk CROSS_COMPILE=riscv64-unknown-elf- ${{inputs.make-args}} + make CROSS_COMPILE=riscv32-unknown-elf- FREEDOM_E_SDK=$GITHUB_WORKSPACE/freedom-e-sdk ${{inputs.make-args}} + - name: Build wolfboot (riscv64)) + if: ${{ inputs.arch == 'riscv64' }} + run: | + make CROSS_COMPILE=riscv64-unknown-elf- ${{inputs.make-args}} diff --git a/.github/workflows/test-configs.yml b/.github/workflows/test-configs.yml index b552544d83..308f8a3cc3 100644 --- a/.github/workflows/test-configs.yml +++ b/.github/workflows/test-configs.yml @@ -19,6 +19,9 @@ jobs: with: arch: riscv config-file: ./config/examples/hifive1.config + # Only building wolfBoot - not test app for now (cross compiler cannot find suitable multilib set for '-march=rv32imafdc_zicsr_zmmul_zaamo_zalrsc_zca_zcd_zcf'/'-mabi=ilp32d') + # Consider building cached RISCV64 toolchain for this target + test-args: wolfboot.bin sama5d3_test: uses: ./.github/workflows/test-build.yml @@ -207,6 +210,15 @@ jobs: arch: arm config-file: ./config/examples/mcxw-tz.config + microchip_mpfs250_test: + uses: ./.github/workflows/test-build-riscv.yml + with: + arch: riscv64 + config-file: ./config/examples/polarfire_mpfs250.config + # Only building wolfBoot - not test app for now (cross compiler cannot find suitable multilib set for '-march=rv64imafd_zicsr_zmmul_zaamo_zalrsc'/'-mabi=lp64d') + # Consider building cached RISCV64 toolchain for this target + test-args: wolfboot.bin + raspi3_test: uses: ./.github/workflows/test-build.yml with: diff --git a/Makefile b/Makefile index 1bb259a2d0..08d6ed0cfa 100644 --- a/Makefile +++ b/Makefile @@ -528,7 +528,7 @@ line-count-nrf52: cloc --force-lang-def cloc_lang_def.txt src/boot_arm.c src/image.c src/libwolfboot.c src/loader.c src/update_flash.c hal/nrf52.c line-count-x86: - cloc --force-lang-def cloc_lang_def.txt src/boot_x86_fsp.c src/boot_x86_fsp_payload.c src/boot_x86_fsp_start.S src/image.c src/keystore.c src/libwolfboot.c src/loader.c src/string.c src/update_disk.c src/x86/ahci.c src/x86/ata.c src/x86/common.c src/x86/gpt.c src/x86/hob.c src/pci.c src/x86/tgl_fsp.c hal/x86_fsp_tgl.c hal/x86_uart.c + cloc --force-lang-def cloc_lang_def.txt src/boot_x86_fsp.c src/boot_x86_fsp_payload.c src/boot_x86_fsp_start.S src/image.c src/keystore.c src/libwolfboot.c src/loader.c src/string.c src/update_disk.c src/gpt.c src/x86/ahci.c src/x86/ata.c src/x86/common.c src/x86/disk.c src/x86/hob.c src/pci.c src/x86/tgl_fsp.c hal/x86_fsp_tgl.c hal/x86_uart.c stack-usage: wolfboot.bin $(Q)echo $(STACK_USAGE) > .stack_usage diff --git a/arch.mk b/arch.mk index 460f57d21d..6250482125 100644 --- a/arch.mk +++ b/arch.mk @@ -545,8 +545,10 @@ endif ## RISCV ifeq ($(ARCH),RISCV) CROSS_COMPILE?=riscv32-unknown-elf- - CFLAGS+=-fno-builtin-printf -DUSE_M_TIME -g -march=rv32imac -mabi=ilp32 -mcmodel=medany -nostartfiles -DARCH_RISCV - LDFLAGS+=-march=rv32imac -mabi=ilp32 -mcmodel=medany + ARCH_FLAGS=-march=rv32imac -mabi=ilp32 -mcmodel=medany + CFLAGS+=-fno-builtin-printf -DUSE_M_TIME -g -nostartfiles -DARCH_RISCV + CFLAGS+=$(ARCH_FLAGS) + LDFLAGS+=$(ARCH_FLAGS) MATH_OBJS += $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/sp_c32.o # Prune unused functions and data @@ -557,6 +559,39 @@ ifeq ($(ARCH),RISCV) ARCH_FLASH_OFFSET=0x20010000 endif +## RISCV64 +ifeq ($(ARCH),RISCV64) + CROSS_COMPILE?=riscv64-unknown-elf- + CFLAGS+=-DMMU -DWOLFBOOT_DUALBOOT + CFLAGS+=-DWOLFBOOT_UPDATE_DISK + UPDATE_OBJS:=src/update_disk.o + OBJS += src/gpt.o + ARCH_FLAGS=-march=rv64imafd -mabi=lp64d -mcmodel=medany + CFLAGS+=-fno-builtin-printf -DUSE_M_TIME -g -nostartfiles -DARCH_RISCV64 + CFLAGS+=$(ARCH_FLAGS) + LDFLAGS+=$(ARCH_FLAGS) + + # Prune unused functions and data + CFLAGS +=-ffunction-sections -fdata-sections + LDFLAGS+=-Wl,--gc-sections + + OBJS+=src/boot_riscv64_start.o src/boot_riscv64.o src/vector_riscv64.o + + CFLAGS+=-DWOLFBOOT_FDT + OBJS+=src/fdt.o + + ifeq ($(SPMATH),1) + MATH_OBJS += $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/sp_c64.o + endif + + ifneq ($(NO_ASM),1) + MATH_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/riscv/riscv-64-sha256.o \ + $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/riscv/riscv-64-sha512.o \ + $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/riscv/riscv-64-sha3.o \ + $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/riscv/riscv-64-aes.o + endif +endif + # powerpc ifeq ($(ARCH),PPC) CROSS_COMPILE?=powerpc-linux-gnu- @@ -815,7 +850,7 @@ ifeq ($(TARGET),nxp_t1024) ARCH_FLAGS=-mhard-float -mcpu=e5500 CFLAGS+=$(ARCH_FLAGS) BIG_ENDIAN=1 - CFLAGS+=-DMMU -DWOLFBOOT_DUALBOOT + CFLAGS+=-DMMU -DWOLFBOOT_FDT -DWOLFBOOT_DUALBOOT CFLAGS+=-pipe # use pipes instead of temp files CFLAGS+=-feliminate-unused-debug-types LDFLAGS+=$(ARCH_FLAGS) @@ -836,7 +871,7 @@ ifeq ($(TARGET),nxp_t2080) ARCH_FLAGS=-mhard-float -mcpu=e6500 CFLAGS+=$(ARCH_FLAGS) BIG_ENDIAN=1 - CFLAGS+=-DMMU -DWOLFBOOT_DUALBOOT + CFLAGS+=-DMMU -DWOLFBOOT_FDT -DWOLFBOOT_DUALBOOT CFLAGS+=-pipe # use pipes instead of temp files CFLAGS+=-feliminate-unused-debug-types LDFLAGS+=$(ARCH_FLAGS) @@ -1012,6 +1047,8 @@ ifeq ("${FSP}", "1") LD_START_GROUP = LD_END_GROUP = LD := ld + # load to address in RAM after wolfBoot (aligned to 16 bytes) + CFLAGS+=-DWOLFBOOT_NO_LOAD_ADDRESS ifeq ($(filter-out $(STAGE1),1),) # building stage1 ifeq ($(FSP_TGL), 1) @@ -1079,7 +1116,8 @@ ifeq ("${FSP}", "1") CFLAGS+=-DWOLFBOOT_USE_PCI OBJS += src/x86/ahci.o OBJS += src/x86/ata.o - OBJS += src/x86/gpt.o + OBJS += src/gpt.o + OBJS += src/x86/disk.o OBJS += src/x86/mptable.o OBJS += src/stage2_params.o OBJS += src/x86/exceptions.o @@ -1339,7 +1377,7 @@ BOOT_IMG?=test-app/image.bin ## Update mechanism ifeq ($(ARCH),AARCH64) - CFLAGS+=-DMMU -DWOLFBOOT_DUALBOOT + CFLAGS+=-DMMU -DWOLFBOOT_FDT -DWOLFBOOT_DUALBOOT OBJS+=src/fdt.o UPDATE_OBJS:=src/update_ram.o else diff --git a/config/examples/polarfire_mpfs250.config b/config/examples/polarfire_mpfs250.config new file mode 100644 index 0000000000..3b224c1865 --- /dev/null +++ b/config/examples/polarfire_mpfs250.config @@ -0,0 +1,54 @@ +ARCH?=RISCV64 +TARGET?=mpfs250 +SIGN?=ECC384 +HASH?=SHA384 +IMAGE_HEADER_SIZE=512 +WOLFBOOT_VERSION?=1 +ARMORED?=0 +DEBUG?=0 +DEBUG_SYMBOLS?=1 +DEBUG_UART?=1 +VTOR?=1 +EXT_FLASH?=1 +SPI_FLASH?=0 +NO_XIP?=1 +NVM_FLASH_WRITEONCE?=0 +UART_FLASH?=0 +V?=0 +NO_MPU?=1 +RAM_CODE?=0 +SPMATH?=1 +DUALBANK_SWAP?=0 +PKA?=0 +ENCRYPT=0 +WOLFTPM?=0 + +# Optionally allow downgrade to older valid version in update partition +ALLOW_DOWNGRADE?=0 + +# Use assembly version of ECDSA and SHA +NO_ASM?=0 +NO_ARM_ASM?=0 + +# Optional: Use smaller SHA512 +#CFLAGS_EXTRA+=-DUSE_SLOW_SHA512 + +# Flash sector size (4KB typical) +WOLFBOOT_SECTOR_SIZE?=0x1000 + +# Load Partition to RAM Address +WOLFBOOT_LOAD_ADDRESS?=0xA0000000 + +# Partition layout for PolarFire SoC MPFS250T +# TODO: Update with actual flash layout based on your system design +WOLFBOOT_PARTITION_SIZE?=0x10000 +WOLFBOOT_PARTITION_BOOT_ADDRESS?=0x08080000 +WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x08090000 +WOLFBOOT_PARTITION_SWAP_ADDRESS?=0x080FF000 + +# DTS (Device Tree) +WOLFBOOT_LOAD_DTS_ADDRESS?=0x80000000 +WOLFBOOT_DTS_BOOT_ADDRESS?=0x20F00000 +WOLFBOOT_DTS_UPDATE_ADDRESS?=0x20F00000 + +#CFLAGS_EXTRA+=-DDEBUG_EXT_FLASH diff --git a/config/examples/raspi3-encrypted.config b/config/examples/raspi3-encrypted.config index 117e7894f3..74ee2d87a7 100644 --- a/config/examples/raspi3-encrypted.config +++ b/config/examples/raspi3-encrypted.config @@ -16,7 +16,6 @@ WOLFBOOT_PARTITION_SWAP_ADDRESS=0xFFFFFFFF WOLFBOOT_PARTITION_SIZE=0x1000000 WOLFBOOT_SECTOR_SIZE=0x400 EXT_FLASH=0 -MMU=1 ENCRYPT=1 NO_XIP=1 ENCRYPT_WITH_AES256=1 diff --git a/docs/Targets.md b/docs/Targets.md index 42558d1f50..81f6b4426d 100644 --- a/docs/Targets.md +++ b/docs/Targets.md @@ -12,6 +12,7 @@ This README describes configuration of supported targets. * [Kontron VX3060-S2](#kontron-vx3060-s2) * [Microchip PIC32CK](#microchip-pic32ck) * [Microchip PIC32CZ](#microchip-pic32cz) +* [Microchip PolarFire SoC](#microchip-polarfire-soc) * [Microchip SAMA5D3](#microchip-sama5d3) * [Microchip SAME51](#microchip-same51) * [Nordic nRF52840](#nordic-nrf52840) @@ -778,6 +779,110 @@ add-symbol-file test-app/image.elf 0x20020100 ``` +## Microchip PolarFire SoC + +The PolarFire SoC is a 64-bit RISC-V SoC featuring a five-core CPU cluster (1× E51 monitor core and 4× U54 application cores) and FPGA fabric. Tested with MPFS250. + +### Features +* RISC-V 64-bit architecture (rv64imac) +* Five-core CPU: 1× E51 monitor + 4× U54 application cores +* Integrated DDR3/4, LPDDR3/4 controller and PHY +* PCIe Gen2, USB 2.0, and Gigabit Ethernet interfaces +* Secure boot capabilities +* Low power consumption +* External flash support + +### Building PolarFire SoC + +All build settings come from .config file. For this platform use `TARGET=mpfs250` and `ARCH=RISCV64`. + +See example configuration at `config/examples/polarfire_mpfs250.config`. + +```sh +cp config/examples/polarfire_mpfs250.config .config +make wolfboot.elf +``` + +To assemble this as a flashable image you need the 0x100 byte HART header added: + +```sh +git clone https://github.com/polarfire-soc/hart-software-services.git +cd hart-software-services +cd tools/hss-payload-generator +make +# install tool +sudo cp hss-payload-generator /usr/local/bin/ +``` + +Use this command to assemble a bootable wolfboot image: + +```sh +hss-payload-generator -vvv -c ./hal/mpfs.yaml wolfboot.bin +``` + +Any customizations to the Device Tree can be made in mpfs.dts and it can be recompiled using: `dtc -I dts -O dtb mpfs.dts -o mpfs.dtb` + + +Example one-shot command: + +```sh +cp ./config/examples/polarfire_mpfs250.config .config && make clean && make wolfboot.elf && size wolfboot.elf && hss-payload-generator -vvv -c ./hal/mpfs.yaml wolfboot.bin && file wolfboot.bin && ls -la wolfboot.bin +``` + +### Flashing PolarFire SoC + + +The HSS MMC boot source looks for GPT with GUID "21686148-6449-6E6F-744E-656564454649" or sector "0" if no GPT found. That GUID is the default "BIOS" boot partition. + +The resulting image from `hss-payload-generator` can be directly placed into GPT BIOS partition. The HSS tinyCLI supports the `USBDMSC` command to mount the eMMC or SD card as a USB device. You can then use "dd" to copy the boot image to the BOOT partition 2. Example: + +``` +sudo dd if=wolfboot.bin of=/dev/sde2 bs=1024 +``` + +Flashing to eNVM: + +The boot rom expects a 0x100 byte secure boot header added. It also requires the .ld is offset by 0x100 to leave room for this. The mpfsBootmodeProgrammer adds 0x100 of meta information for secure boot. + +```sh +$SC_INSTALL_DIR/eclipse/jre/bin/java -jar \ + $SC_INSTALL_DIR/extras/mpfs/mpfsBootmodeProgrammer.jar \ + --bootmode 1 --die MPFS250T --package FCVG484 --workdir $PWD wolfboot.elf +``` +Note: wolfBoot does not support running from eNVM in machine mode yet. + +### Debugging PolarFire Soc + +Start GDB server: + +```sh +$SC_INSTALL_DIR/openocd/bin/openocd --command "set DEVICE MPFS" --file board/microsemi-riscv.cfg +``` + +Start GDB Client: `riscv64-unknown-elf-gdb` + +``` +file wolfboot.elf +tar rem:3333 +add-symbol-file ../hart-software-services/build/hss-l2scratch.elf +set pagination off +foc c + +set $target_riscv=1 +set mem inaccessible-by-default off +set architecture riscv:rv64 +#load wolfboot.elf +#thread apply 2 set $pc=_reset +#thread apply all set $pc=_start +``` + +### PolarFire TODO + +1) Add support for full HSS replacement using wolfboot. +2) Add support for eMMC and QSPI NOR flash + + + ## STM32F7 The STM32-F76x and F77x offer dual-bank hardware-assisted swapping. diff --git a/hal/hifive1.c b/hal/hifive1.c index c73c7ccf31..a7b10666f6 100644 --- a/hal/hifive1.c +++ b/hal/hifive1.c @@ -269,7 +269,7 @@ void fespi_init(uint32_t cpu_clock, uint32_t flash_freq) static RAMFUNCTION void fespi_swmode(void) { asm volatile("fence"); - asm volatile("fence.i"); + if (FESPI_REG_FCTRL & FESPI_FCTRL_MODE_SEL) FESPI_REG_FCTRL &= ~FESPI_FCTRL_MODE_SEL; } @@ -280,9 +280,9 @@ static RAMFUNCTION void fespi_hwmode(void) if ((FESPI_REG_FCTRL & FESPI_FCTRL_MODE_SEL) == 0) FESPI_REG_FCTRL |= FESPI_FCTRL_MODE_SEL; asm volatile("fence"); - asm volatile("fence.i"); + /* Wait two milliseconds for the eSPI device - * to reboot into hw-mapped mode and link to the + * to reboot into hw-mapped mode and link to the * instruction cache */ for(x = 0; x < CPU_FREQ / 500; x++) { @@ -457,7 +457,7 @@ void hifive1_init(uint32_t cpu_clock, uint32_t uart_baud) /* Reconfigure the SPI to maximum frequency */ fespi_init(cpu_clock, MAX_FLASH_FREQ); - + /* Reconfigure the UART */ uart_init(cpu_clock, uart_baud); } @@ -480,7 +480,7 @@ void hal_prepare_boot(void) int RAMFUNCTION hal_flash_write(uint32_t address, const uint8_t *data, int len) { uint32_t i, j = 0; - uint32_t off, page; + uint32_t off, page; const uint8_t *src; uint8_t data_copy[FLASH_PAGE_SIZE]; int swmode = 0; @@ -575,7 +575,7 @@ int RAMFUNCTION hal_flash_erase(uint32_t address, int len) address -= FLASH_BASE; end = address + len - 1; - + FESPI_REG_TXMARK = 1; fespi_wait_txwm(); fespi_swmode(); diff --git a/hal/mpfs.dtb b/hal/mpfs.dtb new file mode 100644 index 0000000000000000000000000000000000000000..dc4e8bd5c86f0622e466a198310621c4e19e1432 GIT binary patch literal 19897 zcmeHPTZ|;vS+1U$UB~z~Hk)AQM$gWAvv#ID-E-NUae}vP?gwt8 z_RUq@bFqjRi722Tkw_>Kk@Db&@M4f4C{j$s!^ZJL!cz=FiV#9*qacwe59BQp0>1A* z=Tx1luAZKqu^%jQq`%MQ|IdH^+c|YkUHS*N{m;)F=gGfw9B0FEKK@bU=KyyC<^f12 zKZo`?RnGjDbZr*7!Ox&<>UW@Q>ZehD-;<#q_5F4@C_mlrc+tngC~%+YKU#k7@k^JV zDnAhpL4?Hq7Xb@hL%-A=v|@KVYzBSzD#&t(IM^;|CM&1p4@R++Qn{oZKen7~Gxa6s zjz?;!vu~|}0upg$z(O3h!tG!wSg$&|2$ik|!-^AyvA+$HgwI9vx9d-!QnT=%MS0(< zUsdR&|1NM$9Q$U#??>C`*TSynvk{5yCjnoOcDAUtGswRZI$g(eeCOrR?+qhnF@IY@ z&ksTr+Jmm4e-{d`0&IVByl*ta*lToxCJB)^9{v29E|ejVCedN4ASp(f(SS! zLwgNn@@1Xzupm}if@NIv_R*qn%-_^yGsZ2bGkyr-iz*68m9X zDjJY}88gZTw8J|oX1Mmf-7#}J#>m7B7jL9r#*A9$-)S*(6MXk}$Bfwzn`@KX^#+WY zlHVD{*h%TFChGktu=bt2#`-$8RA1n&y^z84`kLUa>z=`LElu#&8fWmFHwoT~XM?AW zh_|8CjpHb2`JJmkAkpu<1~0V2-Jt3E9c+$GJNay}f+#BBnE2FpQ zdCKsP`@W51nPXBm*hu!xrp|R3dzkK^6Sxh1vLPK(=`ZlZGWLh1zd}y_lJ<2@W=N-W z?!2Mua)@C2uju+0bAk~*#Bwgb#`8|!Heun&(|3$KL&PC#xbN+I#!#Z=;c^zY&IqO`bSZB^U%hZoL zy%!)l6`lKP^b`_knAnf!n*tpNoiI79vFuhKs61fzOZ24BOcVgg$f9a#{TdpKFNibe zNSskJHn~;XhHN?aZ_{Vowi{84qc}$Sl8oAw0%3Ri)|PiVw+~yvm<}ivI_ez z5OTLK2Iyma&T^qG*jc50W?Gg^T$Z8lb>O(3aV@9+IE5)Y<>T66;sGX|VVR~idU35Y zb~HYJAKFAOwH8YtGnmmV{aDEBgQe0P_6IJyM8TG$dO|^2w7RXP>6`eu?3CGt#HK`^ zGbr2g5NFrv7rV|FC4<82cx_#-Xw>!nfV|9GgRt+0(MxW3BufhEXggM(1z2{<*c_-N z-bix|U}X9_iu4ELi!nucDc_v{E~&h~z%`oJyY~Qo4RAMre&AfA?J4UA0KDe?I-m?# z0GtLa0%)Uq0bEZ$1ULt{4{$%=!+<4#3wQvq45$FOb>Q}ZTL2n`Yq5?2iDk+~pXdF~ zSVptZQii+@mA~ECZy2AGTG3N)F>F~xU^AOC<5E`{Q+5rRS+rqaKqxC^%#ZK;K3Wye z8gdzLgWixN<2f4~!K!cO@S9n@wu|grNXa_q(?R#f=&y--tZ_jA0n&}>!RV5t^b z_01f9GmAfp9*nt3ddT(sNO~yo!CLE47A2DUW)8oZ#UDiv&YMYkh&zs?M-5yhX+8FJ zRqM4`%hj{^qv%lvN6{k=qR{J@O@&BLevHe7UR*uDzFzTAW@0-9)N_wbOcE?wh8eC0 zY%ukQQ06$go>}ieCu`bgQvA$gPU&@2g`QFODu8o^W%8IdUlu@<)hmrI)Bj+-lncP- z*n0hrmKlsD>P3Ah*Fooo)4=C-vag%deKlVO3#Mc1^t)i9eK}Dl?hmHvvvaCcbh-i-Ovl!V$0y2b&mnuiX3w*OVvqX) z(P_sU`t4?aOI8ZbDIkzIM$z?ir#VdU)|z1^m*jc*I1byOd}f`14zf-(feSSaVr=HQ z?shbAhEceMM%_Mbec;|EuTNDr1j6D5^_f4GJ^_Y&QOi9^pM!kEJ=(Y~W@mMyzL~Em z3#5A~J9eh|riIQ|r|2@xH|GlVSwCW|%|Cq{eHc=mW9oBXp*|Oms?Xp!`f%QKkEzf7 zMxSoimt|lhQAOrW8TkA@I&QADeaCP1;w4qoGH~MPeZ)SBOl&Hg|6C8Q1NXef+i`g^ z?K9K5<)^QsDm;qj4Nx;&mGl}j^LdoPTk6F9sa5`}Resef|GicIzE%FARsOM6{<&4= zy%asRoQ-&X6X9?=Ub0HJQNo_p8&o-o~Ha-s`_O)%y zGbh__1{`!&;rTG5&t^70-a>u8jG>sO>T>}^d3|_(K8!v*>!$jsePjh~Ozh8da6aB& zqJz?VGQ9iFCN~;(+-)9|k=U2MVw&nZZfI4Ss_SooF0U)^1sq0K>LR*^E1cWaikI~r zeVf-6q&Zd5qBN!1Wn2oa=K1_9Y(uj3kcLS%fQ>Ty0M@Ug$Af^po{W2K*V51_ec=^d zFIop^`_}-xhmp~_@s{iSHyDEH*gF3PnB;XP(;}Ux&C?3{iQc}~6JPUoE83XIuV|iv zG{JLR?bB=0Xz52B*Gu}8_okTN3ovrNi8A&&NuB=O&~>aivs`P)gMHa&nl4q)WOQjB zS(hJx6%&V-v29&=kL@tJZ0f$YF6?_4UAR1mF2S%JM7@Bw`m3_+0D(jvypNKfhj@#t zp)RpfB55MO@)NBosmx#P3u!p)+`C)Py&8Hw40r_aDBu#{GJrgBEuKAv+$6TyHsrkH zc+`$!lj}LhUWvE5p}IU89cMoRA`?qy-mjvqWNhpX z+Iuy6O^rhu+Kh3>aZMlkFykBP$H-0T*pJsuyC279zf528t2x0d`Xl2UD38GgTVse zG++^M25>LnEP&_SbAbB*_XD_Z=6;0xGwxe>9j^eY0Is2&-;4$7$o*{59`J6oAJ(RZ zmTSU6`(KWgwP|*a-+)caV8wJKo9=6y*1+Ilz$1W10ha)m0gR!dx&BGCKMD90;3>e< zfZqgs8t@F@SpfH#jJw|kJP&vQ!27qn*U5W>yqCs%Pjvw8Ysc|Dx{cYiI4*12qV<9E z=rsWSD)x?svS(c}HxPAS&ei;U2Ps;WY&7mJE9JXt%#g4Dab?zpJ^cdT@9c~{2qb-??*(#|L>GvRW=x(HWX!G?b{hTNnhc7Awva1YuCMuVHMvmb z#-f>+?6ESorLC`n;0l0!X^)qXvjgiz_A~O5xyZ|V0wODd0Bua{%k?fV>sx;2ypX&E zGgZf)mW%RpE-*%?>Bv1&%$aLjGC? zv7f1E?5`O)5Bh@Dez%t9LosjwBE2aQjhStt4Yl#(q1j6JxIGV3htA#-P-@dwS7 zkAkMiX6iZYbeoyDGIlU=W$IW<#V$?_12NU)*Kx`^zmm&M`@idUlk0Y!CEaNkri#jv z+_W2Cy#_qb|CFobbwV!=Vs;@OYuD^6%XsN;*&JxHhYQjm_GVudnu3SDnh$CIHcKNX zPa~V*^X)uMy2TNB$mjJuP42o(nt#aCms_rng$_lxMv zq^}e<--~Fr`T9CoNj_EHH%NtaQe`&Z8k%gr)rvifr}NIgcWLu}IL~`covh4-X`0;T zolmnm+PohzyrTf#-NtLask00nNJKYN=h{zQSw~W9R~s*iHAbyg5Y?)c)s}jLP!W)h zK3|C2UW5_&THT=E?+|NnjEDJ)*Vu$qlV8n$_TNxr*~G@9D2uIo{hli?k~ZB=e@725 zT@${O#$;%4?<|av<;Q}&vp*)@_?!bG*>YS$JugQ)+-lo`kp3Xu6FEqPl$V1|KiBO> zri1)>8MGpk_Qi&tkZ7K26N(`7@{dW4Wa*6Bm>+muvd8j|GS>Gv5Ym*fxJR_dY93{* zAIeBm$GTgOCF6|{t*~W9cTM~mUfp@QyEKwu2A*i*FgNDrbRW0bjPTO4^dt`PJ4YKc zv7Y$e(w#IP0FJgbeR$qx*_Nk@IuqN;b76u!z-8s>DS-@c_T_$n^@HT0{Y{@Dd3f$; znkEnSr+InY9ludAeT|K%>ol3@r$U+P^?0w_=y&2ekHJE7E5==4<_E<5N%y@AXn)XZ zUoLtdnoN*57WrIC>BS9fC!fcy_QUXbCZ!ki89vWj?T6vhNa{Dcsw_hSv zXLE@f92K+MOD{Kbb_U_E-sD>hxbid*FU}?iX1aYeXd<_?#%^X~y@% zCvMKujPHj}+?l7b_QTW<>)(lcgr@jKEJO3bJdO2olc8B0r%60&XwHq(BroC^8h4x~ zdAWr&cR}VAp&5T+#Nf{ho;N!ae{%gV3x52ew(0+g z3_g7TZ17JBe*8hH!9Sb9rw<>Ar_WvxeCBLsjuE2cS? za9{zgq5sSzdi&5}(Z4u}-aa^hp8HI~&5Is(>j4h2e$eT}&SD(CjL#mW-0e4mj^p>c z18*4OKUADy*bN%E3*@%&cF_p`!m{TygYD1{>chQ3;DqW>>NfbntV>2oQydKAv_cHO zs#5-j$#hYvBcnK~JnG?Jeegdwss01p zb-AaW1|y+Xs^*Z>n-FNlm zP_gGKUGU4Pvk!%Wz&)mtKqXwzef7Ib==4mS~r^;I&1} zB^;v47c(ZuUpGk|%1OSe^EFJ6W`8tvF=^XQuP-0ydmX4`LI>xB(e4tx+YDOXs58`) zSkyxh;u(nB8+9A_A0)NTyYMn*AU=re`ATy{bcJDEsUxEBn(bgzm7k=#!s<#=U1fDO zsjjiQrmFhG`|Jq`pWpF7V@ITCfatFe^^vhI zqd>trEmBvDg1Y!S>U!>|OMRW+(_iIFTpb59qb^HBvyQujQpKdpH)#q^vpk8k;nK-< gp`P!WZ4y!?0&f~&XkSZ&Y8BO; + #size-cells = <0x02>; + model = "Microchip PolarFire-SoC VIDEO Kit"; + compatible = "microchip,mpfs-video-kit\0microchip,mpfs-sev-kit\0microchip,mpfs"; + + cpus { + #address-cells = <0x01>; + #size-cells = <0x00>; + timebase-frequency = <0xf4240>; + + cpu@0 { + compatible = "sifive,e51\0sifive,rocket0\0riscv"; + device_type = "cpu"; + i-cache-block-size = <0x40>; + i-cache-sets = <0x80>; + i-cache-size = <0x4000>; + reg = <0x00>; + riscv,isa = "rv64imac"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i\0m\0a\0c\0zicntr\0zicsr\0zifencei\0zihpm"; + clocks = <0x01 0x00>; + status = "disabled"; + phandle = <0x03>; + + interrupt-controller { + #interrupt-cells = <0x01>; + compatible = "riscv,cpu-intc"; + interrupt-controller; + phandle = <0x0b>; + }; + }; + + cpu@1 { + compatible = "sifive,u54-mc\0sifive,rocket0\0riscv"; + d-cache-block-size = <0x40>; + d-cache-sets = <0x40>; + d-cache-size = <0x8000>; + d-tlb-sets = <0x01>; + d-tlb-size = <0x20>; + device_type = "cpu"; + i-cache-block-size = <0x40>; + i-cache-sets = <0x40>; + i-cache-size = <0x8000>; + i-tlb-sets = <0x01>; + i-tlb-size = <0x20>; + mmu-type = "riscv,sv39"; + reg = <0x01>; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i\0m\0a\0f\0d\0c\0zicntr\0zicsr\0zifencei\0zihpm"; + clocks = <0x01 0x00>; + tlb-split; + next-level-cache = <0x02>; + status = "okay"; + phandle = <0x04>; + + interrupt-controller { + #interrupt-cells = <0x01>; + compatible = "riscv,cpu-intc"; + interrupt-controller; + phandle = <0x0c>; + }; + }; + + cpu@2 { + compatible = "sifive,u54-mc\0sifive,rocket0\0riscv"; + d-cache-block-size = <0x40>; + d-cache-sets = <0x40>; + d-cache-size = <0x8000>; + d-tlb-sets = <0x01>; + d-tlb-size = <0x20>; + device_type = "cpu"; + i-cache-block-size = <0x40>; + i-cache-sets = <0x40>; + i-cache-size = <0x8000>; + i-tlb-sets = <0x01>; + i-tlb-size = <0x20>; + mmu-type = "riscv,sv39"; + reg = <0x02>; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i\0m\0a\0f\0d\0c\0zicntr\0zicsr\0zifencei\0zihpm"; + clocks = <0x01 0x00>; + tlb-split; + next-level-cache = <0x02>; + status = "okay"; + phandle = <0x05>; + + interrupt-controller { + #interrupt-cells = <0x01>; + compatible = "riscv,cpu-intc"; + interrupt-controller; + phandle = <0x0d>; + }; + }; + + cpu@3 { + compatible = "sifive,u54-mc\0sifive,rocket0\0riscv"; + d-cache-block-size = <0x40>; + d-cache-sets = <0x40>; + d-cache-size = <0x8000>; + d-tlb-sets = <0x01>; + d-tlb-size = <0x20>; + device_type = "cpu"; + i-cache-block-size = <0x40>; + i-cache-sets = <0x40>; + i-cache-size = <0x8000>; + i-tlb-sets = <0x01>; + i-tlb-size = <0x20>; + mmu-type = "riscv,sv39"; + reg = <0x03>; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i\0m\0a\0f\0d\0c\0zicntr\0zicsr\0zifencei\0zihpm"; + clocks = <0x01 0x00>; + tlb-split; + next-level-cache = <0x02>; + status = "okay"; + phandle = <0x06>; + + interrupt-controller { + #interrupt-cells = <0x01>; + compatible = "riscv,cpu-intc"; + interrupt-controller; + phandle = <0x0e>; + }; + }; + + cpu@4 { + compatible = "sifive,u54-mc\0sifive,rocket0\0riscv"; + d-cache-block-size = <0x40>; + d-cache-sets = <0x40>; + d-cache-size = <0x8000>; + d-tlb-sets = <0x01>; + d-tlb-size = <0x20>; + device_type = "cpu"; + i-cache-block-size = <0x40>; + i-cache-sets = <0x40>; + i-cache-size = <0x8000>; + i-tlb-sets = <0x01>; + i-tlb-size = <0x20>; + mmu-type = "riscv,sv39"; + reg = <0x04>; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i\0m\0a\0f\0d\0c\0zicntr\0zicsr\0zifencei\0zihpm"; + clocks = <0x01 0x00>; + tlb-split; + next-level-cache = <0x02>; + status = "okay"; + phandle = <0x07>; + + interrupt-controller { + #interrupt-cells = <0x01>; + compatible = "riscv,cpu-intc"; + interrupt-controller; + phandle = <0x0f>; + }; + }; + + cpu-map { + + cluster0 { + + core0 { + cpu = <0x03>; + }; + + core1 { + cpu = <0x04>; + }; + + core2 { + cpu = <0x05>; + }; + + core3 { + cpu = <0x06>; + }; + + core4 { + cpu = <0x07>; + }; + }; + }; + }; + + mssrefclk { + compatible = "fixed-clock"; + #clock-cells = <0x00>; + clock-frequency = <0x7735940>; + phandle = <0x15>; + }; + + syscontroller { + compatible = "microchip,mpfs-sys-controller"; + mboxes = <0x08 0x00>; + microchip,bitstream-flash = <0x09>; + status = "okay"; + phandle = <0x19>; + }; + + mssclkclk { + compatible = "fixed-clock"; + #clock-cells = <0x00>; + clock-frequency = <0x4c4b400>; + phandle = <0x14>; + }; + + soc { + #address-cells = <0x02>; + #size-cells = <0x02>; + compatible = "simple-bus"; + ranges; + dma-ranges = <0x14 0x00 0x00 0x80000000 0x00 0x4000000 0x14 0x4000000 0x00 0xc4000000 0x00 0x6000000 0x14 0xa000000 0x00 0x8a000000 0x00 0x8000000 0x14 0x12000000 0x14 0x12000000 0x00 0x10000000 0x14 0x22000000 0x10 0x22000000 0x00 0x5e000000>; + + cache-controller@2010000 { + compatible = "microchip,mpfs-ccache\0sifive,fu540-c000-ccache\0cache"; + reg = <0x00 0x2010000 0x00 0x1000>; + cache-block-size = <0x40>; + cache-level = <0x02>; + cache-sets = <0x400>; + cache-size = <0x200000>; + cache-unified; + interrupt-parent = <0x0a>; + interrupts = <0x01 0x03 0x04 0x02>; + phandle = <0x02>; + }; + + clint@2000000 { + compatible = "sifive,fu540-c000-clint\0sifive,clint0"; + reg = <0x00 0x2000000 0x00 0xc000>; + interrupts-extended = <0x0b 0xffffffff 0x0b 0xffffffff 0x0c 0x03 0x0c 0x07 0x0d 0x03 0x0d 0x07 0x0e 0x03 0x0e 0x07 0x0f 0x03 0x0f 0x07>; + phandle = <0x1a>; + }; + + interrupt-controller@c000000 { + compatible = "sifive,fu540-c000-plic\0sifive,plic-1.0.0"; + reg = <0x00 0xc000000 0x00 0x4000000>; + #address-cells = <0x00>; + #interrupt-cells = <0x01>; + interrupt-controller; + interrupts-extended = <0x0b 0xffffffff 0x0c 0xffffffff 0x0c 0x09 0x0d 0xffffffff 0x0d 0x09 0x0e 0xffffffff 0x0e 0x09 0x0f 0xffffffff 0x0f 0x09>; + riscv,ndev = <0xba>; + phandle = <0x0a>; + }; + + dma-controller@3000000 { + compatible = "microchip,mpfs-pdma\0sifive,pdma0"; + reg = <0x00 0x3000000 0x00 0x8000>; + interrupt-parent = <0x0a>; + interrupts = <0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c>; + dma-channels = <0x04>; + #dma-cells = <0x01>; + phandle = <0x1b>; + }; + + syscon@20002000 { + compatible = "microchip,mpfs-mss-top-sysreg\0syscon\0simple-mfd"; + reg = <0x00 0x20002000 0x00 0x1000>; + #reset-cells = <0x01>; + #address-cells = <0x01>; + #size-cells = <0x01>; + phandle = <0x10>; + + interrupt-controller@54 { + compatible = "microchip,mpfs-gpio-irq-mux"; + reg = <0x54 0x04>; + interrupt-parent = <0x0a>; + interrupt-controller; + #interrupt-cells = <0x01>; + interrupts = <0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e 0x1f 0x20 0x21 0x22 0x23 0x24 0x25 0x26 0x27 0x28 0x29 0x2a 0x2b 0x2c 0x2d 0x2e 0x2f 0x30 0x31 0x32 0x33 0x34 0x35>; + phandle = <0x13>; + }; + }; + + syscon@20003000 { + compatible = "microchip,mpfs-sysreg-scb\0syscon"; + reg = <0x00 0x20003000 0x00 0x1000>; + phandle = <0x1c>; + }; + + clock-controller@38010000 { + compatible = "microchip,mpfs-ccc"; + reg = <0x00 0x38010000 0x00 0x1000 0x00 0x38020000 0x00 0x1000 0x00 0x39010000 0x00 0x1000 0x00 0x39020000 0x00 0x1000>; + #clock-cells = <0x01>; + status = "disabled"; + phandle = <0x1d>; + }; + + clock-controller@38040000 { + compatible = "microchip,mpfs-ccc"; + reg = <0x00 0x38040000 0x00 0x1000 0x00 0x38080000 0x00 0x1000 0x00 0x39040000 0x00 0x1000 0x00 0x39080000 0x00 0x1000>; + #clock-cells = <0x01>; + status = "disabled"; + phandle = <0x1e>; + }; + + clock-controller@38100000 { + compatible = "microchip,mpfs-ccc"; + reg = <0x00 0x38100000 0x00 0x1000 0x00 0x38200000 0x00 0x1000 0x00 0x39100000 0x00 0x1000 0x00 0x39200000 0x00 0x1000>; + #clock-cells = <0x01>; + status = "disabled"; + phandle = <0x1f>; + }; + + clock-controller@38400000 { + compatible = "microchip,mpfs-ccc"; + reg = <0x00 0x38400000 0x00 0x1000 0x00 0x38800000 0x00 0x1000 0x00 0x39400000 0x00 0x1000 0x00 0x39800000 0x00 0x1000>; + #clock-cells = <0x01>; + status = "disabled"; + phandle = <0x20>; + }; + + serial@20000000 { + compatible = "ns16550a"; + reg = <0x00 0x20000000 0x00 0x400>; + reg-io-width = <0x04>; + reg-shift = <0x02>; + interrupt-parent = <0x0a>; + interrupts = <0x5a>; + current-speed = <0x1c200>; + clocks = <0x01 0x08>; + status = "disabled"; + phandle = <0x21>; + }; + + serial@20100000 { + compatible = "ns16550a"; + reg = <0x00 0x20100000 0x00 0x400>; + reg-io-width = <0x04>; + reg-shift = <0x02>; + interrupt-parent = <0x0a>; + interrupts = <0x5b>; + current-speed = <0x1c200>; + clocks = <0x01 0x09>; + status = "okay"; + phandle = <0x22>; + }; + + serial@20102000 { + compatible = "ns16550a"; + reg = <0x00 0x20102000 0x00 0x400>; + reg-io-width = <0x04>; + reg-shift = <0x02>; + interrupt-parent = <0x0a>; + interrupts = <0x5c>; + current-speed = <0x1c200>; + clocks = <0x01 0x0a>; + status = "okay"; + phandle = <0x23>; + }; + + serial@20104000 { + compatible = "ns16550a"; + reg = <0x00 0x20104000 0x00 0x400>; + reg-io-width = <0x04>; + reg-shift = <0x02>; + interrupt-parent = <0x0a>; + interrupts = <0x5d>; + current-speed = <0x1c200>; + clocks = <0x01 0x0b>; + status = "okay"; + phandle = <0x24>; + }; + + serial@20106000 { + compatible = "ns16550a"; + reg = <0x00 0x20106000 0x00 0x400>; + reg-io-width = <0x04>; + reg-shift = <0x02>; + interrupt-parent = <0x0a>; + interrupts = <0x5e>; + clocks = <0x01 0x0c>; + current-speed = <0x1c200>; + status = "okay"; + phandle = <0x25>; + }; + + watchdog@20001000 { + compatible = "microchip,mpfs-wdt"; + reg = <0x00 0x20001000 0x00 0x1000>; + clocks = <0x01 0x02>; + interrupt-parent = <0x0a>; + interrupts = <0x64 0x69>; + interrupt-names = "mvrp\0trig"; + status = "disabled"; + phandle = <0x26>; + }; + + watchdog@20101000 { + compatible = "microchip,mpfs-wdt"; + reg = <0x00 0x20101000 0x00 0x1000>; + clocks = <0x01 0x02>; + interrupt-parent = <0x0a>; + interrupts = <0x65 0x6a>; + interrupt-names = "mvrp\0trig"; + status = "okay"; + phandle = <0x27>; + }; + + watchdog@20103000 { + compatible = "microchip,mpfs-wdt"; + reg = <0x00 0x20103000 0x00 0x1000>; + clocks = <0x01 0x02>; + interrupt-parent = <0x0a>; + interrupts = <0x66 0x6b>; + interrupt-names = "mvrp\0trig"; + status = "disabled"; + phandle = <0x28>; + }; + + watchdog@20105000 { + compatible = "microchip,mpfs-wdt"; + reg = <0x00 0x20105000 0x00 0x1000>; + clocks = <0x01 0x02>; + interrupt-parent = <0x0a>; + interrupts = <0x67 0x6c>; + interrupt-names = "mvrp\0trig"; + status = "disabled"; + phandle = <0x29>; + }; + + watchdog@20107000 { + compatible = "microchip,mpfs-wdt"; + reg = <0x00 0x20107000 0x00 0x1000>; + clocks = <0x01 0x02>; + interrupt-parent = <0x0a>; + interrupts = <0x69 0x6d>; + interrupt-names = "mvrp\0trig"; + status = "disabled"; + phandle = <0x2a>; + }; + + mmc@20008000 { + compatible = "microchip,mpfs-sd4hc\0cdns,sd4hc"; + reg = <0x00 0x20008000 0x00 0x1000>; + interrupt-parent = <0x0a>; + interrupts = <0x58>; + clocks = <0x01 0x06>; + max-frequency = <0xbebc200>; + status = "okay"; + dma-noncoherent; + bus-width = <0x04>; + disable-wp; + cap-sd-highspeed; + cap-mmc-highspeed; + mmc-ddr-1_8v; + mmc-hs200-1_8v; + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr50; + sd-uhs-sdr104; + phandle = <0x2b>; + }; + + spi@20108000 { + compatible = "microchip,mpfs-spi"; + #address-cells = <0x01>; + #size-cells = <0x00>; + reg = <0x00 0x20108000 0x00 0x1000>; + interrupt-parent = <0x0a>; + interrupts = <0x36>; + clocks = <0x01 0x0d>; + status = "disabled"; + phandle = <0x2c>; + }; + + spi@20109000 { + compatible = "microchip,mpfs-spi"; + #address-cells = <0x01>; + #size-cells = <0x00>; + reg = <0x00 0x20109000 0x00 0x1000>; + interrupt-parent = <0x0a>; + interrupts = <0x37>; + clocks = <0x01 0x0e>; + status = "disabled"; + phandle = <0x2d>; + }; + + spi@21000000 { + compatible = "microchip,mpfs-qspi\0microchip,coreqspi-rtl-v2"; + #address-cells = <0x01>; + #size-cells = <0x00>; + reg = <0x00 0x21000000 0x00 0x1000>; + interrupt-parent = <0x0a>; + interrupts = <0x55>; + clocks = <0x01 0x16>; + status = "disabled"; + phandle = <0x2e>; + }; + + i2c@2010a000 { + compatible = "microchip,mpfs-i2c\0microchip,corei2c-rtl-v7"; + reg = <0x00 0x2010a000 0x00 0x1000>; + #address-cells = <0x01>; + #size-cells = <0x00>; + interrupt-parent = <0x0a>; + interrupts = <0x3a>; + clocks = <0x01 0x0f>; + clock-frequency = <0x186a0>; + status = "okay"; + phandle = <0x2f>; + }; + + i2c@2010b000 { + compatible = "microchip,mpfs-i2c\0microchip,corei2c-rtl-v7"; + reg = <0x00 0x2010b000 0x00 0x1000>; + #address-cells = <0x01>; + #size-cells = <0x00>; + interrupt-parent = <0x0a>; + interrupts = <0x3d>; + clocks = <0x01 0x10>; + clock-frequency = <0x186a0>; + status = "disabled"; + phandle = <0x30>; + }; + + can@2010c000 { + compatible = "microchip,mpfs-can"; + reg = <0x00 0x2010c000 0x00 0x1000>; + clocks = <0x01 0x11 0x01 0x25>; + interrupt-parent = <0x0a>; + interrupts = <0x38>; + resets = <0x10 0x11>; + status = "disabled"; + phandle = <0x31>; + }; + + can@2010d000 { + compatible = "microchip,mpfs-can"; + reg = <0x00 0x2010d000 0x00 0x1000>; + clocks = <0x01 0x12 0x01 0x25>; + interrupt-parent = <0x0a>; + interrupts = <0x39>; + resets = <0x10 0x12>; + status = "disabled"; + phandle = <0x32>; + }; + + ethernet@20110000 { + compatible = "microchip,mpfs-macb\0cdns,macb"; + reg = <0x00 0x20110000 0x00 0x2000>; + #address-cells = <0x01>; + #size-cells = <0x00>; + interrupt-parent = <0x0a>; + interrupts = <0x40 0x41 0x42 0x43 0x44 0x45>; + local-mac-address = [00 00 00 00 00 00]; + clocks = <0x01 0x04 0x01 0x02>; + clock-names = "pclk\0hclk"; + resets = <0x10 0x04>; + status = "okay"; + dma-noncoherent; + phy-mode = "sgmii"; + phy-handle = <0x11>; + phandle = <0x33>; + + ethernet-phy@9 { + reg = <0x09>; + phandle = <0x12>; + }; + + ethernet-phy@8 { + reg = <0x08>; + phandle = <0x11>; + }; + }; + + ethernet@20112000 { + compatible = "microchip,mpfs-macb\0cdns,macb"; + reg = <0x00 0x20112000 0x00 0x2000>; + #address-cells = <0x01>; + #size-cells = <0x00>; + interrupt-parent = <0x0a>; + interrupts = <0x46 0x47 0x48 0x49 0x4a 0x4b>; + local-mac-address = [00 00 00 00 00 00]; + clocks = <0x01 0x05 0x01 0x02>; + clock-names = "pclk\0hclk"; + resets = <0x10 0x05>; + status = "okay"; + dma-noncoherent; + phy-mode = "sgmii"; + phy-handle = <0x12>; + phandle = <0x34>; + }; + + gpio@20120000 { + compatible = "microchip,mpfs-gpio"; + reg = <0x00 0x20120000 0x00 0x1000>; + interrupt-parent = <0x13>; + interrupt-controller; + #interrupt-cells = <0x02>; + interrupts = <0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d>; + clocks = <0x01 0x17>; + gpio-controller; + #gpio-cells = <0x02>; + ngpios = <0x0e>; + status = "disabled"; + phandle = <0x35>; + }; + + gpio@20121000 { + compatible = "microchip,mpfs-gpio"; + reg = <0x00 0x20121000 0x00 0x1000>; + interrupt-parent = <0x13>; + interrupt-controller; + #interrupt-cells = <0x02>; + interrupts = <0x20 0x21 0x22 0x23 0x24 0x25 0x26 0x27 0x28 0x29 0x2a 0x2b 0x2c 0x2d 0x2e 0x2f 0x30 0x31 0x32 0x33 0x34 0x35 0x36 0x37>; + clocks = <0x01 0x18>; + gpio-controller; + #gpio-cells = <0x02>; + ngpios = <0x18>; + status = "disabled"; + phandle = <0x36>; + }; + + gpio@20122000 { + compatible = "microchip,mpfs-gpio"; + reg = <0x00 0x20122000 0x00 0x1000>; + interrupt-parent = <0x13>; + interrupt-controller; + #interrupt-cells = <0x02>; + interrupts = <0x40 0x41 0x42 0x43 0x44 0x45 0x46 0x47 0x48 0x49 0x4a 0x4b 0x4c 0x4d 0x4e 0x4f 0x50 0x51 0x52 0x53 0x54 0x55 0x56 0x57 0x58 0x59 0x5a 0x5b 0x5c 0x5d 0x5e 0x5f>; + clocks = <0x01 0x19>; + gpio-controller; + #gpio-cells = <0x02>; + ngpios = <0x20>; + status = "okay"; + phandle = <0x37>; + }; + + rtc@20124000 { + compatible = "microchip,mpfs-rtc"; + reg = <0x00 0x20124000 0x00 0x1000>; + interrupt-parent = <0x0a>; + interrupts = <0x50 0x51>; + clocks = <0x01 0x15 0x01 0x21>; + clock-names = "rtc\0rtcref"; + status = "okay"; + phandle = <0x38>; + }; + + usb@20201000 { + compatible = "microchip,mpfs-musb"; + reg = <0x00 0x20201000 0x00 0x1000>; + interrupt-parent = <0x0a>; + interrupts = <0x56 0x57>; + clocks = <0x01 0x13>; + interrupt-names = "dma\0mc"; + status = "okay"; + dma-noncoherent; + dr_mode = "otg"; + phandle = <0x39>; + }; + + syscon@37020000 { + compatible = "microchip,mpfs-control-scb\0syscon"; + reg = <0x00 0x37020000 0x00 0x100>; + phandle = <0x3a>; + }; + + mailbox@37020800 { + compatible = "microchip,mpfs-mailbox"; + reg = <0x00 0x37020800 0x00 0x100>; + interrupt-parent = <0x0a>; + interrupts = <0x60>; + #mbox-cells = <0x01>; + status = "okay"; + phandle = <0x08>; + }; + + spi@37020100 { + compatible = "microchip,mpfs-qspi\0microchip,coreqspi-rtl-v2"; + #address-cells = <0x01>; + #size-cells = <0x00>; + reg = <0x00 0x37020100 0x00 0x100>; + interrupt-parent = <0x0a>; + interrupts = <0x6e>; + clocks = <0x14>; + status = "okay"; + phandle = <0x3b>; + + flash@0 { + compatible = "jedec,spi-nor"; + #address-cells = <0x01>; + #size-cells = <0x01>; + spi-max-frequency = <0x1312d00>; + spi-rx-bus-width = <0x01>; + reg = <0x00>; + phandle = <0x09>; + }; + }; + + clkcfg@3e001000 { + compatible = "microchip,mpfs-clkcfg"; + reg = <0x00 0x3e001000 0x00 0x1000>; + clocks = <0x15>; + #clock-cells = <0x01>; + phandle = <0x01>; + }; + }; + + fabric-bus@22000000 { + compatible = "simple-bus"; + reg = <0x00 0x22000000 0x00 0x10000>; + #address-cells = <0x02>; + #size-cells = <0x02>; + ranges; + + crypto@22000000 { + compatible = "microchip,mpfs-crypto"; + reg = <0x00 0x22000000 0x00 0x10000>; + clocks = <0x01 0x1f 0x01 0x23>; + interrupt-parent = <0x0a>; + interrupts = <0x70>; + status = "okay"; + phandle = <0x3c>; + }; + }; + + fabric-bus@40000000 { + compatible = "simple-bus"; + #address-cells = <0x02>; + #size-cells = <0x02>; + ranges = <0x00 0x40000000 0x00 0x40000000 0x00 0x20000000 0x00 0x60000000 0x00 0x60000000 0x00 0x20000000 0x00 0xe0000000 0x00 0xe0000000 0x00 0x20000000 0x20 0x00 0x20 0x00 0x10 0x00 0x30 0x00 0x30 0x00 0x10 0x00>; + phandle = <0x3d>; + }; + + aliases { + ethernet0 = "/soc/ethernet@20112000"; + serial0 = "/soc/serial@20000000"; + serial1 = "/soc/serial@20100000"; + serial2 = "/soc/serial@20102000"; + serial3 = "/soc/serial@20104000"; + serial4 = "/soc/serial@20106000"; + }; + + chosen { + stdout-path = "serial1:115200n8"; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x00 0x80000000 0x00 0x4000000>; + phandle = <0x3e>; + }; + + memory@8a000000 { + device_type = "memory"; + reg = <0x00 0x8a000000 0x00 0x8000000>; + phandle = <0x3f>; + }; + + memory@c4000000 { + device_type = "memory"; + reg = <0x00 0xc4000000 0x00 0x6000000>; + phandle = <0x40>; + }; + + memory@1022000000 { + device_type = "memory"; + reg = <0x10 0x22000000 0x00 0x5e000000>; + phandle = <0x41>; + }; + + memory@1412000000 { + device_type = "memory"; + reg = <0x14 0x12000000 0x00 0x10000000>; + phandle = <0x42>; + }; + + reserved-memory { + #address-cells = <0x02>; + #size-cells = <0x02>; + ranges; + + hss-buffer@103fc00000 { + compatible = "shared-dma-pool"; + reg = <0x10 0x3fc00000 0x00 0x400000>; + no-map; + phandle = <0x43>; + }; + + non-cached-low-buffer { + compatible = "shared-dma-pool"; + size = <0x00 0x2000000>; + no-map; + alloc-ranges = <0x00 0xc4000000 0x00 0x2000000>; + phandle = <0x44>; + }; + + non-cached-high-buffer { + compatible = "shared-dma-pool"; + size = <0x00 0x10000000>; + no-map; + linux,dma-default; + alloc-ranges = <0x14 0x12000000 0x00 0x10000000>; + phandle = <0x45>; + }; + + buffer@88000000 { + compatible = "shared-dma-pool"; + reg = <0x00 0x88000000 0x00 0x2000000>; + no-map; + phandle = <0x16>; + }; + + buffer@c8000000 { + compatible = "shared-dma-pool"; + reg = <0x00 0xc8000000 0x00 0x2000000>; + no-map; + phandle = <0x17>; + }; + + buffer@d8000000 { + compatible = "shared-dma-pool"; + reg = <0x00 0xd8000000 0x00 0x2000000>; + no-map; + phandle = <0x18>; + }; + }; + + udmabuf0 { + compatible = "ikwzm,u-dma-buf"; + device-name = "udmabuf-ddr-c0"; + minor-number = <0x00>; + size = <0x00 0x2000000>; + memory-region = <0x16>; + sync-mode = <0x03>; + }; + + udmabuf1 { + compatible = "ikwzm,u-dma-buf"; + device-name = "udmabuf-ddr-nc0"; + minor-number = <0x01>; + size = <0x00 0x2000000>; + memory-region = <0x17>; + sync-mode = <0x03>; + }; + + udmabuf2 { + compatible = "ikwzm,u-dma-buf"; + device-name = "udmabuf-ddr-nc-wcb0"; + minor-number = <0x02>; + size = <0x00 0x2000000>; + memory-region = <0x18>; + sync-mode = <0x03>; + }; + + __symbols__ { + cpu0 = "/cpus/cpu@0"; + cpu0_intc = "/cpus/cpu@0/interrupt-controller"; + cpu1 = "/cpus/cpu@1"; + cpu1_intc = "/cpus/cpu@1/interrupt-controller"; + cpu2 = "/cpus/cpu@2"; + cpu2_intc = "/cpus/cpu@2/interrupt-controller"; + cpu3 = "/cpus/cpu@3"; + cpu3_intc = "/cpus/cpu@3/interrupt-controller"; + cpu4 = "/cpus/cpu@4"; + cpu4_intc = "/cpus/cpu@4/interrupt-controller"; + refclk = "/mssrefclk"; + syscontroller = "/syscontroller"; + scbclk = "/mssclkclk"; + cctrllr = "/soc/cache-controller@2010000"; + clint = "/soc/clint@2000000"; + plic = "/soc/interrupt-controller@c000000"; + pdma = "/soc/dma-controller@3000000"; + mss_top_sysreg = "/soc/syscon@20002000"; + irqmux = "/soc/syscon@20002000/interrupt-controller@54"; + sysreg_scb = "/soc/syscon@20003000"; + ccc_se = "/soc/clock-controller@38010000"; + ccc_ne = "/soc/clock-controller@38040000"; + ccc_nw = "/soc/clock-controller@38100000"; + ccc_sw = "/soc/clock-controller@38400000"; + mmuart0 = "/soc/serial@20000000"; + mmuart1 = "/soc/serial@20100000"; + mmuart2 = "/soc/serial@20102000"; + mmuart3 = "/soc/serial@20104000"; + mmuart4 = "/soc/serial@20106000"; + wdt0 = "/soc/watchdog@20001000"; + wdt1 = "/soc/watchdog@20101000"; + wdt2 = "/soc/watchdog@20103000"; + wdt3 = "/soc/watchdog@20105000"; + wdt4 = "/soc/watchdog@20107000"; + mmc = "/soc/mmc@20008000"; + spi0 = "/soc/spi@20108000"; + spi1 = "/soc/spi@20109000"; + qspi = "/soc/spi@21000000"; + i2c0 = "/soc/i2c@2010a000"; + i2c1 = "/soc/i2c@2010b000"; + can0 = "/soc/can@2010c000"; + can1 = "/soc/can@2010d000"; + mac0 = "/soc/ethernet@20110000"; + phy1 = "/soc/ethernet@20110000/ethernet-phy@9"; + phy0 = "/soc/ethernet@20110000/ethernet-phy@8"; + mac1 = "/soc/ethernet@20112000"; + gpio0 = "/soc/gpio@20120000"; + gpio1 = "/soc/gpio@20121000"; + gpio2 = "/soc/gpio@20122000"; + rtc = "/soc/rtc@20124000"; + usb = "/soc/usb@20201000"; + control_scb = "/soc/syscon@37020000"; + mbox = "/soc/mailbox@37020800"; + syscontroller_qspi = "/soc/spi@37020100"; + sys_ctrl_flash = "/soc/spi@37020100/flash@0"; + clkcfg = "/soc/clkcfg@3e001000"; + crypto = "/fabric-bus@22000000/crypto@22000000"; + fabric_bus = "/fabric-bus@40000000"; + kernel = "/memory@80000000"; + ddr_cached_low = "/memory@8a000000"; + ddr_non_cached_low = "/memory@c4000000"; + ddr_cached_high = "/memory@1022000000"; + ddr_non_cached_high = "/memory@1412000000"; + hss = "/reserved-memory/hss-buffer@103fc00000"; + dma_non_cached_low = "/reserved-memory/non-cached-low-buffer"; + dma_non_cached_high = "/reserved-memory/non-cached-high-buffer"; + fabricbuf0ddrc = "/reserved-memory/buffer@88000000"; + fabricbuf1ddrnc = "/reserved-memory/buffer@c8000000"; + fabricbuf2ddrncwcb = "/reserved-memory/buffer@d8000000"; + }; +}; diff --git a/hal/mpfs.yaml b/hal/mpfs.yaml new file mode 100644 index 0000000000..ab397c940d --- /dev/null +++ b/hal/mpfs.yaml @@ -0,0 +1,21 @@ +# +# HSS Payload Generator - configuration file for wolfBoot on PolarFire SoC +# + +set-name: 'PolarFire-SoC-HSS::wolfBoot' +hart-entry-points: { + u54_1: '0x80200000', + u54_2: '0x80200000', + u54_3: '0x80200000', + u54_4: '0x80200000' +} +payloads: + wolfboot.elf: { + exec-addr: '0x80200000', + owner-hart: u54_1, + secondary-hart: u54_2, + secondary-hart: u54_3, + secondary-hart: u54_4, + priv-mode: prv_s, + ancilliary-data: hal/mpfs.dtb + } diff --git a/hal/mpfs250.c b/hal/mpfs250.c new file mode 100644 index 0000000000..cbedc31e94 --- /dev/null +++ b/hal/mpfs250.c @@ -0,0 +1,266 @@ +/* mpfs250.c + * + * Copyright (C) 2025 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 3 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 + */ + +/* Microchip PolarFire SoC MPFS250T HAL for wolfBoot */ +/* Supports: + * RISC-V 64-bit architecture + * External flash operations + * UART communication + * System initialization + */ + +#include +#include +#include + +#include + +#include "mpfs250.h" +#include "image.h" +#ifndef ARCH_RISCV64 +# error "wolfBoot mpfs250 HAL: wrong architecture selected. Please compile with ARCH=RISCV64." +#endif + +#include "printf.h" +#include "loader.h" +#include "disk.h" + +/* Placeholder functions - to be implemented */ +void hal_init(void) +{ + +} + +void hal_prepare_boot(void) +{ + +} + +void RAMFUNCTION hal_flash_unlock(void) +{ + +} + +void RAMFUNCTION hal_flash_lock(void) +{ + +} + +int RAMFUNCTION hal_flash_write(uint32_t address, const uint8_t *data, int len) +{ + (void)address; + (void)data; + (void)len; + return 0; +} + +int RAMFUNCTION hal_flash_erase(uint32_t address, int len) +{ + (void)address; + (void)len; + return 0; +} + +#ifdef EXT_FLASH +/* External flash support */ +void ext_flash_lock(void) +{ + /* TODO: Lock external flash */ +} + +void ext_flash_unlock(void) +{ + /* TODO: Unlock external flash */ +} + +int ext_flash_write(uintptr_t address, const uint8_t *data, int len) +{ + /* TODO: Write to external flash */ + (void)address; + (void)data; + (void)len; + return 0; +} + +int ext_flash_read(uintptr_t address, uint8_t *data, int len) +{ + /* TODO: Read from external flash */ + (void)address; + (void)data; + (void)len; + return 0; +} + +int ext_flash_erase(uintptr_t address, int len) +{ + /* TODO: Erase external flash sectors */ + (void)address; + (void)len; + return 0; +} +#endif /* EXT_FLASH */ + +#ifdef MMU +void* hal_get_dts_address(void) +{ + return (void*)WOLFBOOT_DTS_BOOT_ADDRESS; +} +#endif + +/* TODO: Add support for reading uSD card with GPT (Global Partition Table) */ +/* The partition ID's are determined using BOOT_PART_A and BOOT_PART_B. */ +int disk_open(int drv) +{ + (void)drv; + return 0; +} +int disk_read(int drv, int part, uint64_t off, uint64_t sz, uint8_t *buf) +{ + (void)drv; + (void)part; + (void)off; + (void)sz; + (void)buf; + return 0; +} +int disk_write(int drv, int part, uint64_t off, uint64_t sz, const uint8_t *buf) +{ + (void)drv; + (void)part; + (void)off; + (void)sz; + (void)buf; + return 0; +} +int disk_find_partition_by_label(int drv, const char *label) +{ + (void)drv; + (void)label; + return 0; +} + +#ifdef DEBUG_UART + +#ifndef DEBUG_UART_BASE +#define DEBUG_UART_BASE MSS_UART1_LO_BASE +#endif + +/* Configure baud divisors with fractional baud rate support. + * + * UART baud rate divisor formula: divisor = PCLK / (baudrate * 16) + * + * To support fractional divisors (6-bit, 0-63), we scale up the calculation: + * divisor_x128 = (PCLK * 8) / baudrate (128x scaled for rounding precision) + * divisor_x64 = divisor_x128 / 2 (64x scaled for 6-bit fractional) + * integer_div = divisor_x64 / 64 (integer portion of divisor) + * frac_div = divisor_x64 % 64 (fractional portion, 0-63) + * + * The fractional part is then adjusted using the x128 value for rounding. + */ +static void uart_config_clk(uint32_t baudrate) +{ + const uint64_t pclk = MSS_APB_AHB_CLK; + + /* Scale up for precision: (PCLK * 128) / (baudrate * 16) */ + uint32_t div_x128 = (uint32_t)((8UL * pclk) / baudrate); + uint32_t div_x64 = div_x128 / 2u; + + /* Extract integer and fractional parts */ + uint32_t div_int = div_x64 / 64u; + uint32_t div_frac = div_x64 - (div_int * 64u); + + /* Apply rounding correction from x128 calculation */ + div_frac += (div_x128 - (div_int * 128u)) - (div_frac * 2u); + + if (div_int > (uint32_t)UINT16_MAX) + return; + + /* Write 16-bit divisor: set DLAB, write high/low bytes, clear DLAB */ + MMUART_LCR(DEBUG_UART_BASE) |= DLAB_MASK; + MMUART_DMR(DEBUG_UART_BASE) = (uint8_t)(div_int >> 8); + MMUART_DLR(DEBUG_UART_BASE) = (uint8_t)div_int; + MMUART_LCR(DEBUG_UART_BASE) &= ~DLAB_MASK; + + /* Enable fractional divisor if integer divisor > 1 */ + if (div_int > 1u) { + MMUART_MM0(DEBUG_UART_BASE) |= EFBR_MASK; + MMUART_DFR(DEBUG_UART_BASE) = (uint8_t)div_frac; + } + else { + MMUART_MM0(DEBUG_UART_BASE) &= ~EFBR_MASK; + } +} + +void uart_init(void) +{ + /* Disable special modes: LIN, IrDA, SmartCard */ + MMUART_MM0(DEBUG_UART_BASE) &= ~ELIN_MASK; + MMUART_MM1(DEBUG_UART_BASE) &= ~EIRD_MASK; + MMUART_MM2(DEBUG_UART_BASE) &= ~EERR_MASK; + + /* Disable interrupts */ + MMUART_IER(DEBUG_UART_BASE) = 0u; + + /* Reset and configure FIFOs, enable RXRDYN/TXRDYN pins */ + MMUART_FCR(DEBUG_UART_BASE) = 0u; + MMUART_FCR(DEBUG_UART_BASE) |= CLEAR_RX_FIFO_MASK | CLEAR_TX_FIFO_MASK; + MMUART_FCR(DEBUG_UART_BASE) |= RXRDY_TXRDYN_EN_MASK; + + /* Disable loopback (local and remote) */ + MMUART_MCR(DEBUG_UART_BASE) &= ~(LOOP_MASK | RLOOP_MASK); + + /* Set LSB-first for TX/RX */ + MMUART_MM1(DEBUG_UART_BASE) &= ~(E_MSB_TX_MASK | E_MSB_RX_MASK); + + /* Disable AFM, single wire mode */ + MMUART_MM2(DEBUG_UART_BASE) &= ~(EAFM_MASK | ESWM_MASK); + + /* Disable TX time guard, RX timeout, fractional baud */ + MMUART_MM0(DEBUG_UART_BASE) &= ~(ETTG_MASK | ERTO_MASK | EFBR_MASK); + + /* Clear timing registers */ + MMUART_GFR(DEBUG_UART_BASE) = 0u; + MMUART_TTG(DEBUG_UART_BASE) = 0u; + MMUART_RTO(DEBUG_UART_BASE) = 0u; + + /* Configure baud rate (115200) */ + uart_config_clk(115200); + + /* Set line config: 8N1 */ + MMUART_LCR(DEBUG_UART_BASE) = MSS_UART_DATA_8_BITS | + MSS_UART_NO_PARITY | + MSS_UART_ONE_STOP_BIT; +} + +void uart_write(const char* buf, unsigned int sz) +{ + uint32_t pos = 0; + while (sz-- > 0) { + char c = buf[pos++]; + if (c == '\n') { /* handle CRLF */ + while ((MMUART_LSR(DEBUG_UART_BASE) & MSS_UART_THRE) == 0); + MMUART_THR(DEBUG_UART_BASE) = '\r'; + } + while ((MMUART_LSR(DEBUG_UART_BASE) & MSS_UART_THRE) == 0); + MMUART_THR(DEBUG_UART_BASE) = c; + } +} +#endif /* DEBUG_UART */ diff --git a/hal/mpfs250.h b/hal/mpfs250.h new file mode 100644 index 0000000000..63348cbe0f --- /dev/null +++ b/hal/mpfs250.h @@ -0,0 +1,153 @@ +/* mpfs250.h + * + * Copyright (C) 2025 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 MPFS250_DEF_INCLUDED +#define MPFS250_DEF_INCLUDED + +/* PolarFire SoC MPFS250T board specific configuration */ + +#define MSS_APB_AHB_CLK 150000000 + +/* Hardware Base Address */ +#define SYSREG_BASE 0x20002000 + +/* Write "0xDEAD" to cause a full MSS reset*/ +#define SYSREG_MSS_RESET_CR (*((volatile uint32_t*)(SYSREG_BASE + 0x18))) + +/* TODO: Add support for machine mode wolfBoot */ +#if 1 + #define WOLFBOOT_RISCV_SMODE /* supervisor mode */ +#else + #define WOLFBOOT_RISCV_MMODE /* machine mode */ +#endif + +/* size of each trap frame register */ +#define REGBYTES (1 << 3) + +/* Machine Information Registers */ +#define CSR_MVENDORID 0xf11 +#define CSR_MARCHID 0xf12 +#define CSR_MIMPID 0xf13 +#define CSR_MHARTID 0xf14 + +/* Initial stack pointer address (stack grows downward from here) */ +#ifdef WOLFBOOT_RISCV_SMODE +#define WOLFBOOT_STACK_TOP 0x80200000 +#else +#define WOLFBOOT_STACK_TOP 0x80000000 +#endif + +#ifdef WOLFBOOT_RISCV_SMODE +#define MODE_PREFIX(__suffix) s##__suffix +#else +#define MODE_PREFIX(__suffix) m##__suffix +#endif + +/* SIE (Interrupt Enable) and SIP (Interrupt Pending) flags */ +#define IRQ_U_SOFT 0 +#define IRQ_S_SOFT 1 +#define IRQ_M_SOFT 3 +#define IRQ_U_TIMER 4 +#define IRQ_S_TIMER 5 +#define IRQ_M_TIMER 7 +#define IRQ_U_EXT 8 +#define IRQ_S_EXT 9 +#define IRQ_M_EXT 11 +#define MIE_MSIE (1 << IRQ_M_SOFT) +#define SIE_SSIE (1 << IRQ_S_SOFT) +#define SIE_STIE (1 << IRQ_S_TIMER) +#define SIE_SEIE (1 << IRQ_S_EXT) + + + +/* UART */ +#define MSS_UART0_LO_BASE 0x20000000UL +#define MSS_UART1_LO_BASE 0x20100000UL +#define MSS_UART2_LO_BASE 0x20102000UL +#define MSS_UART3_LO_BASE 0x20104000UL +#define MSS_UART4_LO_BASE 0x20106000UL + +#define MSS_UART0_HI_BASE 0x28000000UL +#define MSS_UART1_HI_BASE 0x28100000UL +#define MSS_UART2_HI_BASE 0x28102000UL +#define MSS_UART3_HI_BASE 0x28104000UL +#define MSS_UART4_HI_BASE 0x28106000UL + +#define MMUART_RBR(base) *((volatile uint8_t*)((base)) + 0x00) /* Receiver buffer register */ +#define MMUART_IER(base) *((volatile uint8_t*)((base)) + 0x04) /* Interrupt enable register */ +#define MMUART_IIR(base) *((volatile uint8_t*)((base)) + 0x08) /* Interrupt ID register */ +#define MMUART_LCR(base) *((volatile uint8_t*)((base)) + 0x0C) /* Line control register */ +#define MMUART_MCR(base) *((volatile uint8_t*)((base)) + 0x10) /* Modem control register */ +#define MMUART_LSR(base) *((volatile uint8_t*)((base)) + 0x14) /* Line status register */ +#define MMUART_MSR(base) *((volatile uint8_t*)((base)) + 0x18) /* Modem status register */ +#define MMUART_SCR(base) *((volatile uint8_t*)((base)) + 0x1C) /* Scratch register */ +#define MMUART_IEM(base) *((volatile uint8_t*)((base)) + 0x24) /* Interrupt enable mask */ +#define MMUART_IIM(base) *((volatile uint8_t*)((base)) + 0x28) /* multi-mode Interrupt ID register */ +#define MMUART_MM0(base) *((volatile uint8_t*)((base)) + 0x30) /* Mode register 0 */ +#define MMUART_MM1(base) *((volatile uint8_t*)((base)) + 0x34) /* Mode register 1 */ +#define MMUART_MM2(base) *((volatile uint8_t*)((base)) + 0x38) /* Mode register 2 */ +#define MMUART_DFR(base) *((volatile uint8_t*)((base)) + 0x3C) /* Data frame register */ +#define MMUART_GFR(base) *((volatile uint8_t*)((base)) + 0x44) /* Global filter register */ +#define MMUART_TTG(base) *((volatile uint8_t*)((base)) + 0x48) /* TX time guard register */ +#define MMUART_RTO(base) *((volatile uint8_t*)((base)) + 0x4C) /* RX timeout register */ +#define MMUART_ADR(base) *((volatile uint8_t*)((base)) + 0x50) /* Address register */ +#define MMUART_DLR(base) *((volatile uint8_t*)((base)) + 0x80) /* Divisor latch register */ +#define MMUART_DMR(base) *((volatile uint8_t*)((base)) + 0x84) /* Divisor mode register */ +#define MMUART_THR(base) *((volatile uint8_t*)((base)) + 0x100) /* Transmitter holding register */ +#define MMUART_FCR(base) *((volatile uint8_t*)((base)) + 0x104) /* FIFO control register */ + + +/* LCR (Line Control Register) */ +#define MSS_UART_DATA_8_BITS ((uint8_t)0x03) +#define MSS_UART_NO_PARITY ((uint8_t)0x00) +#define MSS_UART_ONE_STOP_BIT ((uint8_t)0x00) + +/* LSR (Line Status Register) */ +#define MSS_UART_THRE ((uint8_t)0x20) /* Transmitter holding register empty */ +#define MSS_UART_TEMT ((uint8_t)0x40) /* Transmit empty */ + +#define ELIN_MASK (0x01u << 3u) /* Enable LIN header detection */ +#define EIRD_MASK (0x01u << 2u) /* Enable IrDA modem */ +#define EERR_MASK (0x01u << 0u) /* Enable ERR / NACK during stop time */ + +#define RXRDY_TXRDYN_EN_MASK (0x01u << 0u) /* Enable TXRDY and RXRDY signals */ +#define CLEAR_RX_FIFO_MASK (0x01u << 1u) /* Clear receiver FIFO */ +#define CLEAR_TX_FIFO_MASK (0x01u << 2u) /* Clear transmitter FIFO */ + +#define LOOP_MASK (0x01u << 4u) /* Local loopback */ +#define RLOOP_MASK (0x01u << 5u) /* Remote loopback & Automatic echo*/ + +#define E_MSB_RX_MASK (0x01u << 0u) /* MSB / LSB first for receiver */ +#define E_MSB_TX_MASK (0x01u << 1u) /* MSB / LSB first for transmitter */ + +#define EAFM_MASK (0x01u << 1u) /* Enable 9-bit address flag mode */ +#define ETTG_MASK (0x01u << 5u) /* Enable transmitter time guard */ +#define ERTO_MASK (0x01u << 6u) /* Enable receiver time-out */ +#define ESWM_MASK (0x01u << 3u) /* Enable single wire half-duplex mode */ +#define EFBR_MASK (0x01u << 7u) /* Enable fractional baud rate mode */ + +/* Line Control register bit masks */ +#define SB_MASK (0x01u << 6) /* Set break */ +#define DLAB_MASK (0x01u << 7) /* Divisor latch access bit */ + + +#endif /* MPFS250_DEF_INCLUDED */ + diff --git a/hal/mpfs250.ld b/hal/mpfs250.ld new file mode 100644 index 0000000000..1542d663c8 --- /dev/null +++ b/hal/mpfs250.ld @@ -0,0 +1,60 @@ +/* PolarFire SoC MPFS250 Linker Script for wolfBoot */ +/* This linker script assumes wolfBoot is loaded by the HSS (FSBL) into DDR */ + +OUTPUT_ARCH( "riscv" ) + +ENTRY( _reset ) + +MEMORY +{ + /* The first 0x100 bytes of eNVM are used for boot ROM secure boot meta information */ + FLASH_ENVM (rx) : ORIGIN = 0x20220100, LENGTH = 128k - 0x100 + DDR (rx) : ORIGIN = 0x80200000, LENGTH = 1028k + L2_SCRATCH (rwx) : ORIGIN = 0x0A000000, LENGTH = 256k +} + +PROVIDE(STACK_SIZE_PER_HART = 16k); + +SECTIONS +{ + .text : ALIGN(0x10) + { + _start_text = .; + KEEP(*(.init)) /* Only for _reset, relocates IV to 0x100 */ + . = ORIGIN(DDR) + 0x100; + _start_vector = .; + KEEP(*(.isr_vector)) + . = ALIGN(0x10); + *(.text*) + *(.rodata*) + *(.srodata*) + . = ALIGN(4); + _end_text = .; + } > DDR + + .data : ALIGN(0x10) + { + _start_data = .; + KEEP(*(.ramcode*)) + . = ALIGN(4); + *(.data*) + . = ALIGN(4); + _global_pointer = . + 0x800; + *(.sdata*) + . = ALIGN(4); + _end_data = .; + } > DDR + + .bss (NOLOAD) : ALIGN(0x10) + { + _start_bss = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + _end_bss = .; + _end = .; + } > DDR +} + +PROVIDE(_start_heap = _end); +PROVIDE(_end_stack = ORIGIN(RAM_L2_SCRATCH) + (LENGTH(RAM_L2_SCRATCH)) ); diff --git a/hal/x86_fsp_qemu_loader.c b/hal/x86_fsp_qemu_loader.c index d0a590efe6..5fbf324a42 100644 --- a/hal/x86_fsp_qemu_loader.c +++ b/hal/x86_fsp_qemu_loader.c @@ -27,9 +27,6 @@ #ifdef __WOLFBOOT #include - -static void panic(void); - void hal_init(void) { } @@ -88,7 +85,3 @@ void *hal_get_dts_update_address(void) return 0; } -static void panic(void) -{ - while(1) {} -} diff --git a/include/x86/gpt.h b/include/disk.h similarity index 90% rename from include/x86/gpt.h rename to include/disk.h index d911c4b5b7..75c09576cc 100644 --- a/include/x86/gpt.h +++ b/include/disk.h @@ -1,4 +1,4 @@ -/* gpt.h +/* disk.h * * Copyright (C) 2025 wolfSSL Inc. * @@ -19,10 +19,15 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ -#ifndef GPT_H -#define GPT_H +#ifndef _WOLFBOOT_DISK_H +#define _WOLFBOOT_DISK_H + +#include + int disk_open(int drv); int disk_read(int drv, int part, uint64_t off, uint64_t sz, uint8_t *buf); int disk_write(int drv, int part, uint64_t off, uint64_t sz, const uint8_t *buf); int disk_find_partition_by_label(int drv, const char *label); -#endif + +#endif /* _WOLFBOOT_DISK_H */ + diff --git a/include/gpt.h b/include/gpt.h new file mode 100644 index 0000000000..fb92ceebdb --- /dev/null +++ b/include/gpt.h @@ -0,0 +1,154 @@ +/* gpt.h + * + * Generic GPT (GUID Partition Table) parsing support. + * + * Copyright (C) 2025 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 3 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 GPT_H +#define GPT_H + +#include + +/* GPT Constants */ +#define GPT_SECTOR_SIZE 0x200 +#define GPT_SIGNATURE 0x5452415020494645ULL /* "EFI PART" */ +#define GPT_PTYPE_PROTECTIVE 0xEE +#define GPT_PART_NAME_SIZE 36 +#define GPT_MBR_ENTRY_START 0x01BE +#define GPT_MBR_BOOTSIG_OFFSET 0x01FE +#define GPT_MBR_BOOTSIG_VALUE 0xAA55 + +/** + * @brief MBR partition table entry structure. + * + * This packed structure defines the layout of an MBR partition table entry + * used to identify GPT partitions (protective MBR). + */ +struct __attribute__((packed)) gpt_mbr_part_entry { + uint8_t stat; + uint8_t chs_first[3]; + uint8_t ptype; + uint8_t chs_last[3]; + uint32_t lba_first; + uint32_t lba_size; +}; + +/** + * @brief GPT (GUID Partition Table) header structure. + */ +struct __attribute__((packed)) guid_ptable { + uint64_t signature; + uint32_t revision; + uint32_t hdr_size; + uint32_t hdr_crc32; + uint32_t res0; + uint64_t main_lba; + uint64_t backup_lba; + uint64_t first_usable; + uint64_t last_usable; + uint64_t disk_guid[2]; + uint64_t start_array; + uint32_t n_part; + uint32_t array_sz; + uint32_t part_crc; + uint8_t res1[GPT_SECTOR_SIZE - 0x5C]; +}; + +/** + * @brief GPT partition entry structure. + * + * This packed structure defines the layout of a GPT partition entry + * used to describe individual partitions on the disk. + */ +struct __attribute__((packed)) gpt_part_entry { + uint64_t type[2]; + uint64_t uuid[2]; + uint64_t first; + uint64_t last; + uint64_t flags; + uint16_t name[GPT_PART_NAME_SIZE]; +}; + +/** + * @brief Parsed partition information. + * + * This structure holds parsed information about a partition extracted + * from a GPT partition entry. + */ +struct gpt_part_info { + uint64_t start; /* Start offset in bytes */ + uint64_t end; /* End offset in bytes */ + uint16_t name[GPT_PART_NAME_SIZE]; +}; + +/** + * @brief Check MBR for protective GPT partition entry. + * + * Scans the MBR sector for a protective GPT partition entry (type 0xEE) + * and validates the boot signature. + * + * @param[in] mbr_sector Pointer to 512-byte MBR sector data. + * @param[out] gpt_lba If not NULL, receives the LBA of the GPT header. + * + * @return 0 on success (valid protective MBR found), -1 on error. + */ +int gpt_check_mbr_protective(const uint8_t *mbr_sector, uint32_t *gpt_lba); + +/** + * @brief Parse and validate a GPT header. + * + * Validates the GPT signature and copies header data to the output structure. + * + * @param[in] sector Pointer to 512-byte GPT header sector data. + * @param[out] hdr Pointer to structure to receive parsed header. + * + * @return 0 on success (valid GPT header), -1 on error. + */ +int gpt_parse_header(const uint8_t *sector, struct guid_ptable *hdr); + +/** + * @brief Parse a GPT partition entry. + * + * Parses a single partition entry and extracts partition information. + * Returns success only if the partition entry is valid (non-zero type GUID). + * + * @param[in] entry_data Pointer to partition entry data. + * @param[in] entry_size Size of the partition entry in bytes. + * @param[out] part Pointer to structure to receive parsed partition info. + * + * @return 0 on success (valid partition entry), -1 if entry is empty/invalid. + */ +int gpt_parse_partition(const uint8_t *entry_data, uint32_t entry_size, + struct gpt_part_info *part); + +/** + * @brief Compare UTF-16 partition name with ASCII string. + * + * Compares a GPT partition name (UTF-16LE) with an ASCII string label. + * + * @param[in] utf16_name UTF-16LE partition name from GPT entry. + * @param[in] ascii_label ASCII string to compare against. + * + * @return 1 if names match, 0 if they don't match. + */ +int gpt_part_name_eq(const uint16_t *utf16_name, const char *ascii_label); + +#endif /* GPT_H */ + diff --git a/include/loader.h b/include/loader.h index 44753c90ec..167d9b0e5b 100644 --- a/include/loader.h +++ b/include/loader.h @@ -85,6 +85,10 @@ static inline void wolfBoot_panic(void) static inline void wolfBoot_panic(void) { wolfBoot_printf("wolfBoot: PANIC!\n"); +#ifdef WOLFBOOT_FSP + extern void panic(void); + panic(); +#endif while(1) ; } diff --git a/include/user_settings.h b/include/user_settings.h index b21ff4c5c4..9dd8594589 100644 --- a/include/user_settings.h +++ b/include/user_settings.h @@ -319,6 +319,9 @@ extern int tolower(int c); # define HAVE___UINT128_T # define WOLFSSL_SP_ARM64_ASM # define SP_WORD_SIZE 64 +# elif defined(ARCH_RISCV64) +# define HAVE___UINT128_T +# define SP_WORD_SIZE 64 # elif defined(ARCH_x86_64) && !defined(FORCE_32BIT) # define SP_WORD_SIZE 64 # ifndef NO_ASM diff --git a/include/x86/common.h b/include/x86/common.h index b10c85b49a..b720f4392d 100644 --- a/include/x86/common.h +++ b/include/x86/common.h @@ -61,12 +61,12 @@ void io_write32(uint16_t port, uint32_t value); uint32_t io_read32(uint16_t port); void reset(uint8_t warm); void delay(int msec); -void panic(); +void panic(void); void cpuid(uint32_t eax_param, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx); -int cpuid_is_1gb_page_supported(); +int cpuid_is_1gb_page_supported(void); void switch_to_long_mode(uint64_t *entry, uint32_t page_table); void x86_log_memory_load(uint32_t start, uint32_t end, const char *name); -void hlt(); +void hlt(void); int x86_run_fsp_32bit(void* api, void* arg); #endif /* COMMON_H */ diff --git a/src/boot_arm32.c b/src/boot_arm32.c index f7b29f61dc..9a999dda8f 100644 --- a/src/boot_arm32.c +++ b/src/boot_arm32.c @@ -34,7 +34,7 @@ extern unsigned int *END_STACK; extern void main(void); -void boot_entry_C(void) +void boot_entry_C(void) { register unsigned int *dst; /* Initialize the BSS section to 0 */ diff --git a/src/boot_ppc.c b/src/boot_ppc.c index 47ca7edb74..fe86cad08a 100644 --- a/src/boot_ppc.c +++ b/src/boot_ppc.c @@ -209,4 +209,7 @@ void do_boot(const uint32_t *app_offset) ); } -void arch_reboot(void) {} +void arch_reboot(void) +{ + +} diff --git a/src/boot_riscv64.c b/src/boot_riscv64.c new file mode 100644 index 0000000000..9824564d7b --- /dev/null +++ b/src/boot_riscv64.c @@ -0,0 +1,95 @@ +/* boot_riscv64.c + * + * Copyright (C) 2025 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 3 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 + */ + +/* RISC-V 64-bit boot code */ + +#include + +#include "image.h" +#include "loader.h" + +#ifdef TARGET_mpfs250 +#include "hal/mpfs250.h" +#endif + +extern void trap_entry(void); +extern void trap_exit(void); + +extern uint64_t _start_vector; +extern uint64_t _stored_data; +extern uint64_t _start_data; +extern uint64_t _end_data; +extern uint64_t _start_bss; +extern uint64_t _end_bss; +extern uint64_t _end_stack; +extern uint64_t _start_heap; +extern uint64_t _global_pointer; +extern void (* const trap_vector_table[])(void); + +/* reloc_trap_vector is implemented in boot_riscv64_start.S */ +extern void reloc_trap_vector(const uint32_t *address); + +unsigned long handle_trap(unsigned long cause, unsigned long epc, unsigned long tval) +{ + /* TODO: Implement trap handling */ + return epc; +} + +#ifdef MMU +int WEAKFUNCTION hal_dts_fixup(void* dts_addr) +{ + (void)dts_addr; + return 0; +} +#endif + +#ifdef MMU +void do_boot(const uint32_t *app_offset, const uint32_t* dts_offset) +#else +void do_boot(const uint32_t *app_offset) +#endif +{ +#ifdef MMU + hal_dts_fixup((uint32_t*)dts_offset); +#endif + + /* Relocate trap vector table to application */ + reloc_trap_vector(app_offset); + + /* Jump to application entry point */ + asm volatile("jr %0":: "r"((uint8_t *)(app_offset))); +} + +void isr_empty(void) +{ + /* Empty interrupt handler */ +} + +void WEAKFUNCTION arch_reboot(void) +{ +#ifdef TARGET_mpfs250 + SYSREG_MSS_RESET_CR = 0xDEAD; +#endif + + while(1) + ; + wolfBoot_panic(); +} diff --git a/src/boot_riscv64_start.S b/src/boot_riscv64_start.S new file mode 100644 index 0000000000..82b7e1c446 --- /dev/null +++ b/src/boot_riscv64_start.S @@ -0,0 +1,138 @@ +/** + * RISC-V 64-bit bootup + * Copyright (C) 2025 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 3 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 + */ + +#ifdef TARGET_mpfs250 +#include "hal/mpfs250.h" +#endif + +/* + * ============================================================ + * RISC-V 64-bit Boot Entry Point + * ============================================================ + * Entry conditions (passed by prior boot stage / SBI): + * a0 = hart ID (hardware thread identifier) + * a1 = pointer to device tree blob (DTB) in memory + * ============================================================ + */ +.section .init +.globl _reset +_reset: +#ifdef WOLFBOOT_RISCV_MMODE + /* + * Machine Mode: Read hart ID from CSR since we're the first code + * running on this core. In Supervisor mode, the SBI passes it in a0. + */ + csrr a0, CSR_MHARTID +#endif + + /* + * Preserve boot parameters in callee-saved registers: + * tp (x4) = hart ID - Used for multi-hart coordination. The RISC-V ABI + * reserves tp as thread-local storage pointer, which C code + * won't clobber, making it safe for inter-hart communication. + * s1 (x9) = DTB pointer - Saved for later use (e.g., passing to kernel) + */ + mv tp, a0 + mv s1, a1 + + /* + * Initialize global pointer to zero as a safety measure. + * If an exception occurs before the C runtime is initialized, + * gp=0 ensures predictable behavior rather than random memory access. + */ + mv gp, zero + + /* + * Configure trap/exception handler: + * Load address of trap_vector_table into the trap-vector base-address + * register (mtvec in M-mode, stvec in S-mode). All synchronous exceptions + * and interrupts will vector through this table. + */ + la t0, trap_vector_table + csrw MODE_PREFIX(tvec), t0 + + /* + * Disable all interrupt sources initially by clearing the + * interrupt-enable register (mie/sie). This prevents spurious + * interrupts during early initialization. + */ + csrw MODE_PREFIX(ie), zero + + /* + * Selectively enable Software Interrupts (IPIs) only. + * IPIs are required for multi-hart boot coordination - secondary harts + * may need to be woken via software interrupt after initialization. + * - M-mode: Set MSIE (Machine Software Interrupt Enable) bit + * - S-mode: Set SSIE (Supervisor Software Interrupt Enable) bit + */ +#ifdef WOLFBOOT_RISCV_SMODE + li t0, SIE_SSIE +#else + li t0, MIE_MSIE +#endif + csrs MODE_PREFIX(ie), t0 + + /* + * Initialize stack pointer: + * WOLFBOOT_STACK_TOP = 0x80000000 (M-mode) or 0x80200000 (S-mode) + * + * The stack grows downward from this address. RISC-V calling convention + * requires 16-byte stack alignment, enforced by AND with -16 (0xFFFF...FFF0). + * + * s0 (frame pointer) is set to match sp for the initial stack frame. + */ + li t0, -16 + li t1, WOLFBOOT_STACK_TOP + and sp, t1, t0 + mv s0, sp + + /* + * Set global pointer (gp) to the stack base. + * Note: This is platform-specific. Typically gp points to a .sdata + * section for efficient global variable access, but here it's used + * as a known reference point for early boot. + */ + mv gp, s0 + + /* + * Jump to C entry point: + * a0 = hart ID (restored from tp for main's first argument) + * + * Using 'j' (jump) instead of 'call' since main() should never return. + * The DTB pointer in s1 can be retrieved later if needed. + */ + mv a0, tp + j main + +/* + * reloc_trap_vector - Relocate trap vector table + * + * Parameters: + * a0 = pointer to new trap vector table base (uint32_t*) + * + * Sets the trap-vector base-address register to (address + 4), + * accounting for the header offset in the application image. + */ +.globl reloc_trap_vector +reloc_trap_vector: + addi a0, a0, 4 /* address + 1 (uint32_t* = +4 bytes) */ + csrw MODE_PREFIX(tvec), a0 + ret diff --git a/src/elf.c b/src/elf.c index 8ea8bd19ef..eb33793dc8 100644 --- a/src/elf.c +++ b/src/elf.c @@ -50,7 +50,7 @@ static int check_scatter_format(const unsigned char* ehdr, int is_elf32); -#if defined(MMU) || defined (WOLFBOOT_FSP) || defined (ARCH_PPC) +#if defined(MMU) || defined(WOLFBOOT_FSP) || defined(WOLFBOOT_ELF) /* Loader for elf32 or elf64 format program headers * Returns the entry point function */ diff --git a/src/fdt.c b/src/fdt.c index 2dab83905b..85259591ca 100644 --- a/src/fdt.c +++ b/src/fdt.c @@ -22,7 +22,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ -#if defined(MMU) && !defined(BUILD_LOADER_STAGE1) +#if (defined(MMU) || defined(WOLFBOOT_FDT)) && !defined(BUILD_LOADER_STAGE1) #include "fdt.h" #include "hal.h" @@ -851,4 +851,4 @@ void* fit_load_image(void* fdt, const char* image, int* lenp) } -#endif /* MMU && !BUILD_LOADER_STAGE1 */ +#endif /* (MMU || WOLFBOOT_FDT) && !BUILD_LOADER_STAGE1 */ diff --git a/src/gpt.c b/src/gpt.c new file mode 100644 index 0000000000..5c290b40e0 --- /dev/null +++ b/src/gpt.c @@ -0,0 +1,210 @@ +/* gpt.c + * + * Generic GPT (GUID Partition Table) parsing implementation. + * + * Copyright (C) 2025 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 3 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 + */ + +/** + * @file gpt.c + * @brief Generic GPT (GUID Partition Table) parsing implementation. + * + * This file contains platform-independent GPT parsing functions that operate + * on memory buffers. Platform-specific disk I/O is handled separately. + */ + +#include +#include + +#include "gpt.h" + +/** + * @brief Check MBR for protective GPT partition entry. + * + * Scans the MBR sector for a protective GPT partition entry (type 0xEE) + * and validates the boot signature. + * + * @param[in] mbr_sector Pointer to 512-byte MBR sector data. + * @param[out] gpt_lba If not NULL, receives the LBA of the GPT header. + * + * @return 0 on success (valid protective MBR found), -1 on error. + */ +int gpt_check_mbr_protective(const uint8_t *mbr_sector, uint32_t *gpt_lba) +{ + const struct gpt_mbr_part_entry *pte; + const uint16_t *boot_sig; + uint32_t i; + int found = 0; + uint32_t lba = 0; + + if (mbr_sector == NULL) { + return -1; + } + + /* Check boot signature at offset 0x1FE */ + boot_sig = (const uint16_t *)(mbr_sector + GPT_MBR_BOOTSIG_OFFSET); + if (*boot_sig != GPT_MBR_BOOTSIG_VALUE) { + return -1; + } + + /* Scan all 4 MBR partition entries for protective GPT type (0xEE) */ + for (i = 0; i < 4; i++) { + pte = (const struct gpt_mbr_part_entry *)(mbr_sector + + GPT_MBR_ENTRY_START + (i * sizeof(struct gpt_mbr_part_entry))); + if (pte->ptype == GPT_PTYPE_PROTECTIVE) { + lba = pte->lba_first; + found = 1; + break; + } + } + + if (!found) { + return -1; + } + + if (gpt_lba != NULL) { + *gpt_lba = lba; + } + + return 0; +} + +/** + * @brief Parse and validate a GPT header. + * + * Validates the GPT signature and copies header data to the output structure. + * + * @param[in] sector Pointer to 512-byte GPT header sector data. + * @param[out] hdr Pointer to structure to receive parsed header. + * + * @return 0 on success (valid GPT header), -1 on error. + */ +int gpt_parse_header(const uint8_t *sector, struct guid_ptable *hdr) +{ + const struct guid_ptable *src; + + if (sector == NULL || hdr == NULL) { + return -1; + } + + src = (const struct guid_ptable *)sector; + + /* Validate GPT signature */ + if (src->signature != GPT_SIGNATURE) { + return -1; + } + + /* Copy header to output */ + memcpy(hdr, src, sizeof(struct guid_ptable)); + + return 0; +} + +/** + * @brief Parse a GPT partition entry. + * + * Parses a single partition entry and extracts partition information. + * Returns success only if the partition entry is valid (non-zero type GUID). + * + * @param[in] entry_data Pointer to partition entry data. + * @param[in] entry_size Size of the partition entry in bytes. + * @param[out] part Pointer to structure to receive parsed partition info. + * + * @return 0 on success (valid partition entry), -1 if entry is empty/invalid. + */ +int gpt_parse_partition(const uint8_t *entry_data, uint32_t entry_size, + struct gpt_part_info *part) +{ + const struct gpt_part_entry *pe; + + if (entry_data == NULL || part == NULL) { + return -1; + } + + if (entry_size < sizeof(struct gpt_part_entry)) { + return -1; + } + + pe = (const struct gpt_part_entry *)entry_data; + + /* Check if partition entry is empty (type GUID is all zeros) */ + if (pe->type[0] == 0 && pe->type[1] == 0) { + return -1; + } + + /* Validate geometry */ + if (pe->first > pe->last) { + return -1; + } + + /* Extract partition info (convert LBA to byte offsets) */ + part->start = pe->first * GPT_SECTOR_SIZE; + part->end = (pe->last * GPT_SECTOR_SIZE) - 1; + memcpy(part->name, pe->name, sizeof(part->name)); + + return 0; +} + +/** + * @brief Compare UTF-16 partition name with ASCII string. + * + * Compares a GPT partition name (UTF-16LE) with an ASCII string label. + * Handles optional BOM prefix in UTF-16 string. + * + * @param[in] utf16_name UTF-16LE partition name from GPT entry. + * @param[in] ascii_label ASCII string to compare against. + * + * @return 1 if names match, 0 if they don't match. + */ +int gpt_part_name_eq(const uint16_t *utf16_name, const char *ascii_label) +{ + unsigned int utf16_idx; + unsigned int i; + unsigned int ascii_len; + + if (utf16_name == NULL || ascii_label == NULL) { + return 0; + } + + ascii_len = strlen(ascii_label); + if (ascii_len > GPT_PART_NAME_SIZE) { + return 0; + } + + utf16_idx = 0; + /* Skip BOM if present */ + if (utf16_name[utf16_idx] == 0xfeff) { + utf16_idx = 1; + } + + /* Compare each character */ + for (i = 0; i < ascii_len; i++, utf16_idx++) { + /* Non-ASCII character or mismatch */ + if (utf16_name[utf16_idx] != (uint16_t)ascii_label[i]) { + return 0; + } + } + + /* Check that UTF-16 string is null-terminated after the match */ + if (utf16_idx < GPT_PART_NAME_SIZE && utf16_name[utf16_idx] != 0x0) { + return 0; + } + + return 1; +} diff --git a/src/update_disk.c b/src/update_disk.c index f3c8fc44b6..8b8db2b930 100644 --- a/src/update_disk.c +++ b/src/update_disk.c @@ -41,34 +41,54 @@ #include "hal.h" #include "spi_flash.h" #include "printf.h" -#include "stage2_params.h" #include "wolfboot/wolfboot.h" +#include "disk.h" +#ifdef WOLFBOOT_ELF +#include "elf.h" +#endif + #include #include -#include -#include -#include -#include -#include -#if defined(WOLFBOOT_FSP) -#include +#ifdef WOLFBOOT_FSP +#include "stage2_params.h" +#include "x86/common.h" +#include "x86/ahci.h" +#include "x86/ata.h" +#include "pci.h" +#include "x86/tgl_fsp.h" + +#ifdef TARGET_kontron_vx3060_s2 + #define BOOT_PART_A 5 + #define BOOT_PART_B 6 #endif +#endif /* WOLFBOOT_FSP */ -#ifdef TARGET_x86_fsp_qemu -#define BOOT_DISK 0 -#define BOOT_PART_A 0 -#define BOOT_PART_B 1 -#else +/* Default values for BOOT_DISK, BOOT_PART_A and BOOT_PART_B */ +#ifndef BOOT_DISK #define BOOT_DISK 0 -#define BOOT_PART_A 5 -#define BOOT_PART_B 6 +#endif +#ifndef BOOT_PART_A +#define BOOT_PART_A 1 +#endif +#ifndef BOOT_PART_B +#define BOOT_PART_B 2 #endif +#ifndef MAX_FAILURES #define MAX_FAILURES 4 +#endif + +#ifndef DISK_BLOCK_SIZE +#define DISK_BLOCK_SIZE 512 +#endif + +extern int wolfBoot_get_dts_size(void *dts_addr); +#if defined(WOLFBOOT_NO_LOAD_ADDRESS) || !defined(WOLFBOOT_LOAD_ADDRESS) /* from the linker, where wolfBoot ends */ extern uint8_t _end_wb[]; +#endif /** * @brief function for starting the boot process. @@ -80,33 +100,37 @@ extern uint8_t _end_wb[]; void RAMFUNCTION wolfBoot_start(void) { uint8_t p_hdr[IMAGE_HEADER_SIZE] XALIGNED_STACK(16); - struct stage2_parameter *stage2_params; struct wolfBoot_image os_image; int pA_ver = 0, pB_ver = 0; uint32_t cur_part = 0; int ret = -1; int selected; - uint32_t img_size = 0; uint32_t *load_address; int failures = 0; uint32_t load_off; - uint32_t sata_bar; +#ifdef MMU + uint8_t *dts_addr = NULL; + uint32_t dts_size = 0; +#endif + char part_name[4] = {'P', ':', 'X', '\0'}; -#if defined(WOLFBOOT_FSP) +#ifdef WOLFBOOT_FSP + struct stage2_parameter *stage2_params; + uint32_t sata_bar; ret = x86_fsp_tgl_init_sata(&sata_bar); if (ret != 0) - panic(); -#if defined(WOLFBOOT_ATA_DISK_LOCK) + wolfBoot_panic(); +#ifdef WOLFBOOT_ATA_DISK_LOCK ret = sata_unlock_disk(BOOT_DISK, 1); if (ret != 0) - panic(); -#endif /* WOLFBOOT_ATA_DISK_LOCK */ + wolfBoot_panic(); +#endif #endif /* WOLFBOOT_FSP */ - if (disk_open(BOOT_DISK) < 0) - panic(); - - memset(&os_image, 0, sizeof(struct wolfBoot_image)); + if (disk_open(BOOT_DISK) < 0) { + wolfBoot_printf("Error opening disk %d\r\n", BOOT_DISK); + wolfBoot_panic(); + } wolfBoot_printf("Checking primary OS image in %d,%d...\r\n", BOOT_DISK, BOOT_PART_A); @@ -123,20 +147,27 @@ void RAMFUNCTION wolfBoot_start(void) } if ((pB_ver == 0) && (pA_ver == 0)) { - wolfBoot_printf("No valid OS image found in either partitions.\r\n"); - panic(); + wolfBoot_printf("No valid OS image found in either partition %d or %d\r\n", + BOOT_PART_A, BOOT_PART_B); + wolfBoot_panic(); } wolfBoot_printf("Versions, A:%u B:%u\r\n", pA_ver, pB_ver); - if (pB_ver > pA_ver) - selected = 1; - else - selected = 0; + /* Choose partition with higher version */ + selected = (pB_ver > pA_ver) ? 1: 0; +#ifdef WOLFBOOT_FSP stage2_params = stage2_get_parameters(); +#endif + +#if !defined(WOLFBOOT_NO_LOAD_ADDRESS) && defined(WOLFBOOT_LOAD_ADDRESS) + load_address = (uint32_t*)WOLFBOOT_LOAD_ADDRESS; +#else /* load the image just after wolfboot, 16 bytes aligned */ load_address = (uint32_t *)((((uintptr_t)_end_wb) + 0xf) & ~0xf); +#endif + wolfBoot_printf("Load address 0x%x\r\n", load_address); do { failures++; @@ -145,9 +176,11 @@ void RAMFUNCTION wolfBoot_start(void) else cur_part = BOOT_PART_A; - wolfBoot_printf("Attempting boot from partition %c\r\n", 'A' + selected); + part_name[2] = 'A' + selected; - /* Fetch header again */ + wolfBoot_printf("Attempting boot from %s\r\n", part_name); + + /* Fetch header only */ if (disk_read(BOOT_DISK, cur_part, 0, IMAGE_HEADER_SIZE, p_hdr) != IMAGE_HEADER_SIZE) { wolfBoot_printf("Error reading image header from disk: p%d\r\n", @@ -156,28 +189,38 @@ void RAMFUNCTION wolfBoot_start(void) continue; } - /* Dereference img_size from header */ - img_size = *( ((uint32_t *)p_hdr) + 1); + memset(&os_image, 0, sizeof(os_image)); + ret = wolfBoot_open_image_address(&os_image, (void*)p_hdr); + if (ret < 0) { + wolfBoot_printf("Error parsing loaded image\r\n"); + selected ^= 1; + continue; + } - if (img_size > - ((uint32_t)(stage2_params->tolum) - (uint32_t)(uintptr_t)load_address)) { - wolfBoot_printf("Image size %d doesn't fit in low memory\r\n", img_size); - break; +#ifdef WOLFBOOT_FSP + /* Verify image size fits in low memory */ + if (os_image.fw_size > ((uint32_t)(stage2_params->tolum) - + (uint32_t)(uintptr_t)load_address)) { + wolfBoot_printf("Image size %d doesn't fit in low memory\r\n", + os_image.fw_size); + break; } + /* Log memory load */ + x86_log_memory_load((uint32_t)(uintptr_t)load_address, + (uint32_t)(uintptr_t)load_address + os_image.fw_size, + part_name); +#endif /* Read the image into RAM */ - x86_log_memory_load((uint32_t)(uintptr_t)load_address, - (uint32_t)(uintptr_t)load_address + img_size, - "ELF"); wolfBoot_printf("Loading image from disk..."); load_off = 0; do { - ret = disk_read(BOOT_DISK, cur_part, load_off, 512, - (uint8_t *)load_address + load_off); + ret = disk_read(BOOT_DISK, cur_part, load_off, + DISK_BLOCK_SIZE, (uint8_t*)load_address + load_off); if (ret < 0) break; load_off += ret; - } while (load_off < img_size + IMAGE_HEADER_SIZE); + } while (load_off < os_image.fw_size + IMAGE_HEADER_SIZE); if (ret < 0) { wolfBoot_printf("Error reading image from disk: p%d\r\n", @@ -186,7 +229,9 @@ void RAMFUNCTION wolfBoot_start(void) continue; } wolfBoot_printf("done.\r\n"); - ret = wolfBoot_open_image_address(&os_image, (void *)load_address); + + memset(&os_image, 0, sizeof(os_image)); + ret = wolfBoot_open_image_address(&os_image, (void*)load_address); if (ret < 0) { wolfBoot_printf("Error parsing loaded image\r\n"); selected ^= 1; @@ -195,16 +240,16 @@ void RAMFUNCTION wolfBoot_start(void) wolfBoot_printf("Checking image integrity..."); if (wolfBoot_verify_integrity(&os_image) != 0) { - wolfBoot_printf("Error validating integrity for partition %c\r\n", - 'A' + selected); + wolfBoot_printf("Error validating integrity for %s\r\n", part_name); selected ^= 1; continue; } wolfBoot_printf("done.\r\n"); + wolfBoot_printf("Verifying image signature..."); if (wolfBoot_verify_authenticity(&os_image) != 0) { - wolfBoot_printf("Error validating authenticity for partition %c\r\n", - 'A' + selected); + wolfBoot_printf("Error validating authenticity for %s\r\n", + part_name); selected ^= 1; continue; } else { @@ -215,18 +260,65 @@ void RAMFUNCTION wolfBoot_start(void) } while (failures < MAX_FAILURES); if (failures) { - panic(); + wolfBoot_printf("Unable to find a valid partition!\r\n"); + wolfBoot_panic(); } +#ifdef WOLFBOOT_FSP sata_disable(sata_bar); +#endif + wolfBoot_printf("Firmware Valid.\r\n"); - wolfBoot_printf("Booting at %08lx\r\n", os_image.fw_base); + + load_address = (uint32_t*)os_image.fw_base; + +#ifdef WOLFBOOT_FDT + /* Is this a Flattened uImage Tree (FIT) image (FDT format) */ + if (wolfBoot_get_dts_size(load_address) > 0) { + void* fit = (void*)load_address; + const char *kernel = NULL, *flat_dt = NULL; + + wolfBoot_printf("Flattened uImage Tree: Version %d, Size %d\n", + fdt_version(fit), fdt_totalsize(fit)); + + (void)fit_find_images(fit, &kernel, &flat_dt); + if (kernel != NULL) { + load_address = fit_load_image(fit, kernel, NULL); + } + if (flat_dt != NULL) { + uint8_t *dts_ptr = fit_load_image(fit, flat_dt, (int*)&dts_size); + if (dts_ptr != NULL && wolfBoot_get_dts_size(dts_ptr) >= 0) { + /* relocate to load DTS address */ + dts_addr = (uint8_t*)WOLFBOOT_LOAD_DTS_ADDRESS; + wolfBoot_printf("Loading DTS: %p -> %p (%d bytes)\n", + dts_ptr, dts_addr, dts_size); + memcpy(dts_addr, dts_ptr, dts_size); + } + } + } +#endif + +#if defined(WOLFBOOT_ELF) && !defined(WOLFBOOT_FSP) + /* Load elf sections and return the new entry point */ + /* Skip for FSP, since it expects ELF image directly */ + if (elf_load_image_mmu((uint8_t*)load_address, (uintptr_t*)&load_address, NULL) != 0){ + wolfBoot_printf("Invalid elf, falling back to raw binary\n"); + } +#endif + + wolfBoot_printf("Booting at %08lx\r\n", load_address); + #ifdef WOLFBOOT_ENABLE_WOLFHSM_CLIENT (void)hal_hsm_disconnect(); #elif defined(WOLFBOOT_ENABLE_WOLFHSM_SERVER) (void)hal_hsm_server_cleanup(); #endif hal_prepare_boot(); - do_boot((uint32_t*)os_image.fw_base); + + do_boot((uint32_t*)load_address + #ifdef MMU + ,(uint32_t*)dts_addr + #endif + ); } #endif /* WOLFBOOT_UPDATE_DISK */ diff --git a/src/update_flash.c b/src/update_flash.c index 2cb6915ca8..6f2c733174 100644 --- a/src/update_flash.c +++ b/src/update_flash.c @@ -42,6 +42,10 @@ int WP11_Library_Init(void); #include "encrypt.h" #endif /* EXT_ENCRYPTED */ +#ifdef MMU +#error "MMU is not yet supported for update_flash.c, please consider update_ram.c instead" +#endif + #ifdef RAM_CODE #ifndef TARGET_rp2350 extern unsigned int _start_text; @@ -1275,6 +1279,7 @@ void RAMFUNCTION wolfBoot_start(void) (void)hal_hsm_server_cleanup(); #endif hal_prepare_boot(); + do_boot((void *)boot.fw_base); } diff --git a/src/update_ram.c b/src/update_ram.c index 36e2491a81..ece070fd57 100644 --- a/src/update_ram.c +++ b/src/update_ram.c @@ -175,7 +175,7 @@ void RAMFUNCTION wolfBoot_start(void) } else { /* Success - integrity and signature valid */ - #ifdef WOLFBOOT_LOAD_ADDRESS + #if !defined(WOLFBOOT_NO_LOAD_ADDRESS) && defined(WOLFBOOT_LOAD_ADDRESS) load_address = (uint32_t*)WOLFBOOT_LOAD_ADDRESS; #elif !defined(NO_XIP) load_address = (uint32_t*)os_image.fw_base; diff --git a/src/vector_riscv64.S b/src/vector_riscv64.S new file mode 100644 index 0000000000..a960f841e6 --- /dev/null +++ b/src/vector_riscv64.S @@ -0,0 +1,179 @@ +/** + * RISC-V 64-bit vector table + * Copyright (C) 2025 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 3 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 "hal/mpfs250.h" + +/* RISC-V 64-bit trap/exception handling macros */ +.macro trap_entry + addi sp, sp, -32 * REGBYTES + sd x1, 1 * REGBYTES(sp) + sd x2, 2 * REGBYTES(sp) + sd x3, 3 * REGBYTES(sp) + sd x4, 4 * REGBYTES(sp) + sd x5, 5 * REGBYTES(sp) + sd x6, 6 * REGBYTES(sp) + sd x7, 7 * REGBYTES(sp) + sd x8, 8 * REGBYTES(sp) + sd x9, 9 * REGBYTES(sp) + sd x10, 10 * REGBYTES(sp) + sd x11, 11 * REGBYTES(sp) + sd x12, 12 * REGBYTES(sp) + sd x13, 13 * REGBYTES(sp) + sd x14, 14 * REGBYTES(sp) + sd x15, 15 * REGBYTES(sp) + sd x16, 16 * REGBYTES(sp) + sd x17, 17 * REGBYTES(sp) + sd x18, 18 * REGBYTES(sp) + sd x19, 19 * REGBYTES(sp) + sd x20, 20 * REGBYTES(sp) + sd x21, 21 * REGBYTES(sp) + sd x22, 22 * REGBYTES(sp) + sd x23, 23 * REGBYTES(sp) + sd x24, 24 * REGBYTES(sp) + sd x25, 25 * REGBYTES(sp) + sd x26, 26 * REGBYTES(sp) + sd x27, 27 * REGBYTES(sp) + sd x28, 28 * REGBYTES(sp) + sd x29, 29 * REGBYTES(sp) + sd x30, 30 * REGBYTES(sp) + sd x31, 31 * REGBYTES(sp) + csrr a0, MODE_PREFIX(cause) + csrr a1, MODE_PREFIX(epc) + csrr a2, MODE_PREFIX(tval) + mv a3, sp + jal handle_trap + csrw MODE_PREFIX(epc), a0 +.endm + +.macro trap_exit + ld x1, 1 * REGBYTES(sp) + ld x3, 3 * REGBYTES(sp) + ld x4, 4 * REGBYTES(sp) + ld x5, 5 * REGBYTES(sp) + ld x6, 6 * REGBYTES(sp) + ld x7, 7 * REGBYTES(sp) + ld x8, 8 * REGBYTES(sp) + ld x9, 9 * REGBYTES(sp) + ld x10, 10 * REGBYTES(sp) + ld x11, 11 * REGBYTES(sp) + ld x12, 12 * REGBYTES(sp) + ld x13, 13 * REGBYTES(sp) + ld x14, 14 * REGBYTES(sp) + ld x15, 15 * REGBYTES(sp) + ld x16, 16 * REGBYTES(sp) + ld x17, 17 * REGBYTES(sp) + ld x18, 18 * REGBYTES(sp) + ld x19, 19 * REGBYTES(sp) + ld x20, 20 * REGBYTES(sp) + ld x21, 21 * REGBYTES(sp) + ld x22, 22 * REGBYTES(sp) + ld x23, 23 * REGBYTES(sp) + ld x24, 24 * REGBYTES(sp) + ld x25, 25 * REGBYTES(sp) + ld x26, 26 * REGBYTES(sp) + ld x27, 27 * REGBYTES(sp) + ld x28, 28 * REGBYTES(sp) + ld x29, 29 * REGBYTES(sp) + ld x30, 30 * REGBYTES(sp) + ld x31, 31 * REGBYTES(sp) + ld x2, 2 * REGBYTES(sp) + addi sp, sp, 32 * REGBYTES + mret +.endm + +.section .isr_vector +.align 8 + +.global trap_vector_table +trap_vector_table: + j _synctrap + .align 3 + j trap_empty + .align 3 + j trap_empty + .align 3 + j trap_empty + .align 3 + j trap_empty + .align 3 + j trap_empty + .align 3 + j trap_empty + .align 3 + j trap_empty + .align 3 + j trap_empty + .align 3 + j trap_empty + .align 3 + j trap_empty + .align 3 + j trap_empty + .align 3 + j trap_empty + .align 3 + j trap_empty + .align 3 + j trap_empty + .align 3 + j trap_empty + .align 3 + j trap_empty + .align 3 + j trap_empty + .align 3 + j trap_empty + .align 3 + j trap_empty + .align 3 + j trap_empty + .align 3 + j trap_empty + .align 3 + j trap_empty + .align 3 + j trap_empty + .align 3 + j trap_empty + .align 3 + j trap_empty + .align 3 + j trap_empty + .align 3 + j trap_empty + .align 3 + j trap_empty + .align 3 + j trap_empty + .align 3 + j trap_empty + .align 3 + j trap_empty + .align 3 + j trap_empty + .align 3 + +_synctrap: + trap_entry + trap_exit + +trap_empty: + nop diff --git a/src/x86/gpt.c b/src/x86/disk.c similarity index 58% rename from src/x86/gpt.c rename to src/x86/disk.c index 5a8112d8df..5bdf26c4f3 100644 --- a/src/x86/gpt.c +++ b/src/x86/disk.c @@ -1,4 +1,4 @@ -/* gpt.c +/* disk.c * * Copyright (C) 2025 wolfSSL Inc. * @@ -20,82 +20,26 @@ * */ /** - * @file gpt.c - * @brief GPT (GUID Partition Table) driver implementation. + * @file x86/disk.c + * @brief x86 GPT disk driver implementation. * - * This file contains the implementation of the GPT driver used for interacting - * with GPT partitioned disks. It provides functions for disk initialization, - * partition reading, and writing. + * This file contains the x86-specific GPT disk driver that uses ATA for + * disk I/O operations. It uses the generic GPT parsing functions from + * src/gpt.c for partition table parsing. */ -#ifndef GPT_C -#define GPT_C +#ifndef X86_DISK_C +#define X86_DISK_C + #include +#include +#include #include #include #include #include -#include -#include #define MAX_PARTITIONS 16 #define MAX_DISKS 4 -#define SECTOR_SIZE 0x200 -#define GPT_OFFSET 0x200 -#define GPT_SIGNATURE 0x5452415020494645ULL /* "EFI PART" */ - -#define PTYPE_GPT 0xEE -#define P_ENTRY_START 0x01BE -#define P_BOOTSIG_OFFSET 0x01FE -#define GPT_PART_NAME_SIZE (36) - -/** - * @brief This packed structure defines the layout of an MBR partition table entry - * used to identify GPT partitions. - */ -struct __attribute__((packed)) mbr_ptable_entry { - uint8_t stat; - uint8_t chs_first[3]; - uint8_t ptype; - uint8_t chs_last[3]; - uint32_t lba_first; - uint32_t lba_size; -}; - -/** - * @brief Structure representing a GPT (GUID Partition Table) header. - */ -struct __attribute__((packed)) guid_ptable -{ - uint64_t signature; - uint32_t revision; - uint32_t hdr_size; - uint32_t hdr_crc32; - uint32_t res0; - uint64_t main_lba; - uint64_t backup_lba; - uint64_t first_usable; - uint64_t last_usable; - uint64_t disk_guid[2]; - uint64_t start_array; - uint32_t n_part; - uint32_t array_sz; - uint32_t part_crc; - uint8_t res1[SECTOR_SIZE - 0x5C]; -}; - -/** - * @brief This packed structure defines the layout of a GPT partition entry - * used to describe individual partitions on the disk. - */ -struct __attribute__((packed)) guid_part_array -{ - uint64_t type[2]; - uint64_t uuid[2]; - uint64_t first; - uint64_t last; - uint64_t flags; - uint16_t name[GPT_PART_NAME_SIZE]; -}; /** * @brief This structure holds information about a disk partition, including @@ -128,30 +72,6 @@ struct disk_drive { */ static struct disk_drive Drives[MAX_DISKS] = {0}; -static int disk_u16_ascii_eq(const uint16_t *utf16, const char *ascii) -{ - unsigned int utf16_idx; - unsigned int i; - - if (strlen(ascii) > GPT_PART_NAME_SIZE) - return 0; - - utf16_idx = 0; - /* skip BOM if present */ - if (utf16[utf16_idx] == 0xfeff) - utf16_idx = 1; - for (i = 0; i < strlen(ascii); i++, utf16_idx++) { - /* non-ascii character*/ - if (utf16[utf16_idx] != (uint16_t)ascii[i]) - return 0; - } - - if (utf16_idx < GPT_PART_NAME_SIZE && utf16[utf16_idx] != 0x0) - return 0; - - return 1; -} - /** * @brief Opens a disk drive and initializes its partitions. * @@ -169,11 +89,9 @@ int disk_open(int drv) int r; uint32_t i; uint32_t n_parts = 0; - uint64_t signature = GPT_SIGNATURE; + uint32_t gpt_lba = 0; struct guid_ptable ptable; - struct mbr_ptable_entry pte; - uint16_t boot_signature; - int gpt_found = 0; + uint8_t sector[GPT_SECTOR_SIZE]; if ((drv < 0) || (drv > MAX_DISKS)) { wolfBoot_printf("Attempting to access invalid drive %d\r\n", drv); @@ -181,85 +99,100 @@ int disk_open(int drv) } wolfBoot_printf("Reading MBR...\r\n"); - for (i = 0; i < 4; i++) { - r = ata_drive_read(drv, P_ENTRY_START + 0x10 * i, sizeof(struct mbr_ptable_entry), - (void *)&pte); - if ((r > 0) && (pte.ptype == PTYPE_GPT)) { - wolfBoot_printf("Found GPT PTE at sector %u\r\n", pte.lba_first); - gpt_found = 1; - break; - } - } - if (!gpt_found) { - wolfBoot_printf("Cannot find valid partition table entry for GPT\r\n"); + + /* Read MBR sector */ + r = ata_drive_read(drv, 0, GPT_SECTOR_SIZE, sector); + if (r <= 0) { + wolfBoot_printf("Failed to read MBR\r\n"); return -1; } - - r = ata_drive_read(drv, P_BOOTSIG_OFFSET, sizeof(uint16_t), (void *)&boot_signature); - if ((r > 0) && (boot_signature == 0xAA55)) { - wolfBoot_printf("Found valid boot signature in MBR\r\n"); - } else { - wolfBoot_printf("FATAL: Invalid boot signature in MBR!\r\n"); + /* Check for protective MBR and get GPT header location */ + if (gpt_check_mbr_protective(sector, &gpt_lba) != 0) { + wolfBoot_printf("Cannot find valid partition table entry for GPT\r\n"); return -1; } + wolfBoot_printf("Found GPT PTE at sector %u\r\n", gpt_lba); + wolfBoot_printf("Found valid boot signature in MBR\r\n"); Drives[drv].is_open = 1; Drives[drv].drv = drv; Drives[drv].n_parts = 0; - r = ata_drive_read(drv, SECTOR_SIZE * pte.lba_first, SECTOR_SIZE, - (void *)&ptable); - if (r > 0) { - if (ptable.signature == signature) { - wolfBoot_printf("Valid GPT partition table\r\n"); - wolfBoot_printf("Current LBA: 0x%llx \r\n", ptable.main_lba); - wolfBoot_printf("Backup LBA: 0x%llx \r\n", ptable.backup_lba); - wolfBoot_printf("Max number of partitions: %d\r\n", ptable.n_part); - n_parts = ptable.n_part; - if (ptable.n_part > MAX_PARTITIONS) { - n_parts = MAX_PARTITIONS; - wolfBoot_printf("Software limited: only allowing up to %d partitions per disk.\r\n", n_parts); - } - wolfBoot_printf("Disk size: %d\r\n", (1 + ptable.last_usable - ptable.first_usable) * SECTOR_SIZE); - } else { - wolfBoot_printf("Invalid partition table\r\n"); - return -1; - } - } else { + + /* Read GPT header */ + r = ata_drive_read(drv, GPT_SECTOR_SIZE * gpt_lba, GPT_SECTOR_SIZE, sector); + if (r <= 0) { wolfBoot_printf("ATA: Read failed\r\n"); return -1; } + + /* Parse and validate GPT header */ + if (gpt_parse_header(sector, &ptable) != 0) { + wolfBoot_printf("Invalid partition table\r\n"); + return -1; + } + + wolfBoot_printf("Valid GPT partition table\r\n"); + wolfBoot_printf("Current LBA: 0x%llx \r\n", ptable.main_lba); + wolfBoot_printf("Backup LBA: 0x%llx \r\n", ptable.backup_lba); + wolfBoot_printf("Max number of partitions: %d\r\n", ptable.n_part); + + n_parts = ptable.n_part; + if (ptable.n_part > MAX_PARTITIONS) { + n_parts = MAX_PARTITIONS; + wolfBoot_printf("Software limited: only allowing up to %d partitions " + "per disk.\r\n", n_parts); + } + wolfBoot_printf("Disk size: %d\r\n", + (1 + ptable.last_usable - ptable.first_usable) * GPT_SECTOR_SIZE); + + /* Read and parse partition entries */ for (i = 0; i < n_parts; i++) { - struct guid_part_array pa; - uint64_t address = ptable.start_array * SECTOR_SIZE + + struct gpt_part_info part_info; + uint64_t address = ptable.start_array * GPT_SECTOR_SIZE + i * ptable.array_sz; - r = ata_drive_read(drv, address, ptable.array_sz, (void *)&pa); - if (r < 0) + uint8_t entry_buf[256]; /* Max partition entry size */ + + if (ptable.array_sz > sizeof(entry_buf)) { + wolfBoot_printf("Partition entry size too large\r\n"); + break; + } + + r = ata_drive_read(drv, address, ptable.array_sz, entry_buf); + if (r < 0) { return -1; - if (pa.type[0] != 0 || pa.type[1] != 0) { + } + + /* Parse partition entry using generic function */ + if (gpt_parse_partition(entry_buf, ptable.array_sz, &part_info) == 0) { uint64_t size; uint32_t part_count; - if (pa.first > pa.last) { - wolfBoot_printf("Bad geometry for partition %d\r\n", i); - break; - } - size = (1 + pa.last - pa.first) * SECTOR_SIZE; + + size = part_info.end - part_info.start + 1; part_count = Drives[drv].n_parts; Drives[drv].n_parts++; Drives[drv].part[part_count].drv = drv; - Drives[drv].part[part_count].start = pa.first * SECTOR_SIZE; - Drives[drv].part[part_count].end = (pa.last * SECTOR_SIZE - 1); - memcpy(&Drives[drv].part[part_count].name, (uint8_t*)&pa.name, sizeof(pa.name)); + Drives[drv].part[part_count].start = part_info.start; + Drives[drv].part[part_count].end = part_info.end; + memcpy(&Drives[drv].part[part_count].name, part_info.name, + sizeof(part_info.name)); + wolfBoot_printf("disk%d.p%u ", drv, part_count); - wolfBoot_printf("(%x_%xh", (uint32_t)(size>>32), (uint32_t)size); - wolfBoot_printf("@ %x_%x)\r\n", (uint32_t)((pa.first * SECTOR_SIZE) >> 32), - (uint32_t)((pa.first * SECTOR_SIZE))); - } else + wolfBoot_printf("(%x_%xh", (uint32_t)(size >> 32), (uint32_t)size); + wolfBoot_printf("@ %x_%x)\r\n", + (uint32_t)(part_info.start >> 32), + (uint32_t)(part_info.start)); + } else { + /* Empty partition entry - end of used entries */ break; + } } - wolfBoot_printf("Total partitions on disk%u: %u\r\n", drv, Drives[drv].n_parts); + + wolfBoot_printf("Total partitions on disk%u: %u\r\n", drv, + Drives[drv].n_parts); return Drives[drv].n_parts; } + /** * @brief Opens a disk partition and returns a pointer to its structure. * @@ -358,6 +291,16 @@ int disk_write(int drv, int part, uint64_t off, uint64_t sz, const uint8_t *buf) return ret; } +/** + * @brief Find a partition by its label. + * + * Searches for a partition with the specified label on the given drive. + * + * @param[in] drv The drive number to search (0 to `MAX_DISKS - 1`). + * @param[in] label The ASCII label to search for. + * + * @return The partition number if found, or -1 if not found. + */ int disk_find_partition_by_label(int drv, const char *label) { struct disk_partition *p; @@ -371,9 +314,11 @@ int disk_find_partition_by_label(int drv, const char *label) for (i = 0; i < Drives[drv].n_parts; i++) { p = open_part(drv, i); - if (disk_u16_ascii_eq(p->name, label) == 1) + if (gpt_part_name_eq(p->name, label) == 1) return i; } return -1; } -#endif /* GPT_C */ + +#endif /* X86_DISK_C */ + diff --git a/test-app/Makefile b/test-app/Makefile index 65d6f7ce96..c2480d63e6 100644 --- a/test-app/Makefile +++ b/test-app/Makefile @@ -467,6 +467,11 @@ ifeq ($(TARGET),hifive1) APP_OBJS+=hifive1_write_page.o endif +ifeq ($(TARGET),mpfs250) + LSCRIPT_TEMPLATE:=RISCV64-mpfs250.ld + CFLAGS+=-DRAMFUNCTION='__attribute__((used,section(".ramcode")))' +endif + # $(CYPRESS_PDL)/devices/templates/COMPONENT_MTB/COMPONENT_CM0P/system_psoc6_cm0plus.o ifeq ($(TARGET),psoc6) diff --git a/test-app/RISCV64-mpfs250.ld b/test-app/RISCV64-mpfs250.ld new file mode 100644 index 0000000000..975a44e606 --- /dev/null +++ b/test-app/RISCV64-mpfs250.ld @@ -0,0 +1,106 @@ +/* PolarFire SoC MPFS250 Linker Script for test application */ + +/* Memory configuration for PolarFire SoC MPFS250 test app */ +/* TODO: Update with actual memory map for MPFS250 */ + +_Min_Heap_Size = 0x00002000; /* required amount of heap */ +_Min_Stack_Size = 0x00002000; /* required amount of stack */ + +/* Memory areas */ +MEMORY +{ + /* TODO: Configure actual memory regions based on PolarFire SoC memory map */ + /* Application typically runs from DDR or LSRAM */ + IRAM (rx) :ORIGIN = @WOLFBOOT_TEST_APP_ADDRESS@, LENGTH = @WOLFBOOT_TEST_APP_SIZE@ + DDR (rwx) :ORIGIN = 0x80000000, LENGTH = 1M + LSRAM (rwx) :ORIGIN = 0x08000000, LENGTH = 128K +} + +/* Define output sections */ +SECTIONS +{ + /* The startup code goes first into IRAM */ + .isr_vector : + { + . = ALIGN(8); + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(8); + } >IRAM + + /* The program code and other data goes into IRAM */ + .text : + { + . = ALIGN(8); + _start_text = .; + *(.text) /* .text sections (code) */ + *(.text*) /* .text* sections (code) */ + *(.rodata) /* .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(8); + _etext = .; /* define a global symbol at end of code */ + } >IRAM + + /* used by the startup to initialize data */ + _stored_data = LOADADDR(.data); + + /* Initialized data sections transported to RAM */ + .data : + { + . = ALIGN(8); + _start_data = .; /* create a global symbol at data start */ + *(.data) /* .data sections */ + *(.data*) /* .data* sections */ + *(.RamFunc) /* .RamFunc sections */ + *(.RamFunc*) /* .RamFunc* sections */ + + . = ALIGN(8); + _end_data = .; /* define a global symbol at data end */ + } >LSRAM AT> IRAM + + /* Uninitialized data section */ + . = ALIGN(8); + .bss : + { + /* This is used by the startup in order to initialize the .bss section */ + _start_bss = .; /* define a global symbol at bss start */ + __bss_start__ = _start_bss; + *(.bss) + *(.bss*) + /* *(COMMON) */ + + . = ALIGN(8); + _end_bss = .; /* define a global symbol at bss end */ + __bss_end__ = _end_bss; + } >LSRAM + + /* User_heap_stack section, used to check that there is enough RAM left */ + ._user_heap_stack : + { + . = ALIGN(8); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + PROVIDE ( _start_heap = . ); + . = . + _Min_Heap_Size; + . = . + _Min_Stack_Size; + . = ALIGN(8); + PROVIDE ( END_STACK = . ); + PROVIDE ( _end_stack = . ); + } >LSRAM + + /* Global pointer for RISC-V */ + . = ALIGN(8); + _global_pointer = .; + + /* Remove information from the standard libraries */ + /DISCARD/ : + { + libc.a ( * ) + libm.a ( * ) + libgcc.a ( * ) + } +} + diff --git a/test-app/app_mpfs250.c b/test-app/app_mpfs250.c new file mode 100644 index 0000000000..af05c96fba --- /dev/null +++ b/test-app/app_mpfs250.c @@ -0,0 +1,159 @@ +/* app_mpfs250.c + * + * Test bare-metal application for PolarFire SoC MPFS250. + * + * Copyright (C) 2025 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 3 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 +#include + +#include "hal.h" +#include "wolfboot/wolfboot.h" +#include "target.h" +#include "printf.h" +#include "keystore.h" + +#include "../hal/mpfs250.h" + +static uint8_t boot_part_state = IMG_STATE_NEW; +static uint8_t update_part_state = IMG_STATE_NEW; + +const char part_state_names[6][16] = { + "NEW", + "UPDATING", + "FFLAGS", + "TESTING", + "CONFIRMED", + "[Invalid state]" +}; + +static const char *part_state_name(uint8_t state) +{ + switch(state) { + case IMG_STATE_NEW: + return part_state_names[0]; + case IMG_STATE_UPDATING: + return part_state_names[1]; + case IMG_STATE_FINAL_FLAGS: + return part_state_names[2]; + case IMG_STATE_TESTING: + return part_state_names[3]; + case IMG_STATE_SUCCESS: + return part_state_names[4]; + default: + return part_state_names[5]; + } +} + +static int print_info(void) +{ + int i, j; + uint32_t cur_fw_version, update_fw_version; + uint32_t n_keys; + uint16_t hdrSz; + + cur_fw_version = wolfBoot_current_firmware_version(); + update_fw_version = wolfBoot_update_firmware_version(); + + wolfBoot_get_partition_state(PART_BOOT, &boot_part_state); + wolfBoot_get_partition_state(PART_UPDATE, &update_part_state); + + wolfBoot_printf("\r\n"); + wolfBoot_printf("System information\r\n"); + wolfBoot_printf("====================================\r\n"); + wolfBoot_printf("Firmware version : 0x%lx\r\n", wolfBoot_current_firmware_version()); + wolfBoot_printf("Current firmware state: %s\r\n", part_state_name(boot_part_state)); + if (update_fw_version != 0) { + if (update_part_state == IMG_STATE_UPDATING) + wolfBoot_printf("Candidate firmware version : 0x%lx\r\n", update_fw_version); + else + wolfBoot_printf("Backup firmware version : 0x%lx\r\n", update_fw_version); + wolfBoot_printf("Update state: %s\r\n", part_state_name(update_part_state)); + if (update_fw_version > cur_fw_version) { + wolfBoot_printf("'reboot' to initiate update.\r\n"); + } else { + wolfBoot_printf("Update image older than current.\r\n"); + } + } else { + wolfBoot_printf("No image in update partition.\r\n"); + } + + wolfBoot_printf("\r\n"); + wolfBoot_printf("Bootloader OTP keystore information\r\n"); + wolfBoot_printf("====================================\r\n"); + n_keys = keystore_num_pubkeys(); + wolfBoot_printf("Number of public keys: %lu\r\n", n_keys); + for (i = 0; i < n_keys; i++) { + uint32_t size = keystore_get_size(i); + uint32_t type = keystore_get_key_type(i); + uint32_t mask = keystore_get_mask(i); + uint8_t *keybuf = keystore_get_buffer(i); + + wolfBoot_printf("\r\n"); + wolfBoot_printf(" Public Key #%d: size %lu, type %lx, mask %08lx\r\n", i, + size, type, mask); + wolfBoot_printf(" ====================================\r\n "); + for (j = 0; j < size; j++) { + wolfBoot_printf("%02X ", keybuf[j]); + if (j % 16 == 15) { + wolfBoot_printf("\r\n "); + } + } + wolfBoot_printf("\r\n"); + } + return 0; +} + +void main(void) +{ + uint32_t app_version; + + hal_init(); + + app_version = wolfBoot_current_firmware_version(); + + wolfBoot_printf("========================\r\n"); + wolfBoot_printf("PolarFire SoC MPFS250 wolfBoot demo Application\r\n"); + wolfBoot_printf("Copyright 2025 wolfSSL Inc\r\n"); + wolfBoot_printf("GPL v3\r\n"); + wolfBoot_printf("Version : 0x%lx\r\n", app_version); + wolfBoot_printf("========================\r\n"); + + print_info(); + + if (app_version > 1) { + if (boot_part_state == IMG_STATE_TESTING) { + wolfBoot_printf("Booting new firmware, marking successful boot\n"); + + /* Mark successful boot, so update won't be rolled back */ + wolfBoot_success(); + } + } + + /* TODO: Add application-specific code here */ + + while(1) { + /* Main application loop */ + /* TODO: Add watchdog feed if needed */ + } +} + diff --git a/tools/elf-parser/Makefile b/tools/elf-parser/Makefile index dc67c3895e..50660afef1 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 -DMMU -DARCH_FLASH_OFFSET=0 +CFLAGS+=-I../../include -DWOLFBOOT_ELF -DELF_PARSER -DPRINTF_ENABLED -DARCH_FLASH_OFFSET=0 EXE=elf-parser LIBS= diff --git a/tools/fdt-parser/Makefile b/tools/fdt-parser/Makefile index 744f47c1d2..78ea9bf97d 100644 --- a/tools/fdt-parser/Makefile +++ b/tools/fdt-parser/Makefile @@ -4,7 +4,7 @@ CC=gcc CFLAGS=-Wall -g -ggdb -CFLAGS+=-I../../include -DMMU -DPRINTF_ENABLED +CFLAGS+=-I../../include -DWOLFBOOT_FDT -DPRINTF_ENABLED EXE=fdt-parser LIBS= diff --git a/tools/scripts/x86_fsp/qemu/qemu.sh b/tools/scripts/x86_fsp/qemu/qemu.sh index 77b6dedd7e..2ad6d19e20 100755 --- a/tools/scripts/x86_fsp/qemu/qemu.sh +++ b/tools/scripts/x86_fsp/qemu/qemu.sh @@ -110,6 +110,7 @@ if [ "$ENABLE_TPM" = true ]; then killall swtpm || true sleep 1 echo TPM Emulation ON + rm -rf /tmp/swtpm || true mkdir -p /tmp/swtpm swtpm socket --tpm2 --tpmstate dir=/tmp/swtpm \ --ctrl type=unixio,path=/tmp/swtpm/swtpm-sock --log level=20 & From 4b542f55215fadf9d66de8f6230cd4e69e7d5908 Mon Sep 17 00:00:00 2001 From: David Garske Date: Tue, 9 Dec 2025 16:51:41 -0800 Subject: [PATCH 02/13] Progress with eMMC/SD driver. --- .github/workflows/test-configs.yml | 4 +- docs/Targets.md | 1 + hal/mpfs250.c | 406 ++++++++++++++- hal/mpfs250.h | 770 ++++++++++++++++++++++++++++- 4 files changed, 1156 insertions(+), 25 deletions(-) diff --git a/.github/workflows/test-configs.yml b/.github/workflows/test-configs.yml index 308f8a3cc3..d8cc7704ac 100644 --- a/.github/workflows/test-configs.yml +++ b/.github/workflows/test-configs.yml @@ -21,7 +21,7 @@ jobs: config-file: ./config/examples/hifive1.config # Only building wolfBoot - not test app for now (cross compiler cannot find suitable multilib set for '-march=rv32imafdc_zicsr_zmmul_zaamo_zalrsc_zca_zcd_zcf'/'-mabi=ilp32d') # Consider building cached RISCV64 toolchain for this target - test-args: wolfboot.bin + make-args: wolfboot.bin sama5d3_test: uses: ./.github/workflows/test-build.yml @@ -217,7 +217,7 @@ jobs: config-file: ./config/examples/polarfire_mpfs250.config # Only building wolfBoot - not test app for now (cross compiler cannot find suitable multilib set for '-march=rv64imafd_zicsr_zmmul_zaamo_zalrsc'/'-mabi=lp64d') # Consider building cached RISCV64 toolchain for this target - test-args: wolfboot.bin + make-args: wolfboot.bin raspi3_test: uses: ./.github/workflows/test-build.yml diff --git a/docs/Targets.md b/docs/Targets.md index 81f6b4426d..3ebfe880da 100644 --- a/docs/Targets.md +++ b/docs/Targets.md @@ -2438,6 +2438,7 @@ Executing Initialization File: /opt/Freescale/CodeWarrior_PA_10.5.1/PA/PA_Suppor thread break: Stopped, 0x0, 0x0, cpuPowerPCBig, Connected (state, tid, pid, cpu, target) ``` + ## NXP MCXA153 NXP MCXA153 is a Cortex-M33 microcontroller running at 96MHz. diff --git a/hal/mpfs250.c b/hal/mpfs250.c index cbedc31e94..84ff5e506c 100644 --- a/hal/mpfs250.c +++ b/hal/mpfs250.c @@ -49,6 +49,13 @@ void hal_init(void) } +int hal_dts_fixup(void* dts_addr) +{ + /* TODO: Consider FDT fixups: + * ethernet0: local-mac-address {0x00, 0x04, 0xA3, SERIAL2, SERIAL1, SERIAL0} */ + (void)dts_addr; + return 0; +} void hal_prepare_boot(void) { @@ -125,12 +132,409 @@ void* hal_get_dts_address(void) } #endif +int mmc_set_timeout(uint32_t timeout_us) +{ + uint32_t reg, i, tcfclk, tcfclk_mhz, tcfclk_khz, timeout_val, dtcv; + + /* read capabilities to determine timeout clock frequency and unit (MHz or kHz) */ + reg = EMMC_SD_SRS16; + tcfclk_khz = (reg * EMMC_SD_SRS16_TCF_MASK); + + if (((reg & EMMC_SD_SRS16_TCU) == 0) && (timeout_us < 1000)) { + /* invalid timeout_us value */ + return -1; + } + if (tcfclk_khz == 0) { + /* reported timeout clock frequency is 0 */ + return -1; + } + + if ((reg & EMMC_SD_SRS16_TCU) != 0) { + tcfclk_khz *= 1000; /* MHz to kHz */ + } + tcfclk_mhz = tcfclk_khz / 1000; + if (tcfclk_mhz == 0) { + tcfclk = tcfclk_khz; + timeout_val = timeout_us / 1000; + } + else { + tcfclk = tcfclk_mhz; + timeout_val = timeout_us; + } + + /* calculate the data timeout counter value */ + dtcv = 8192; /* 2*13 */ + for (i=0; i<15; i++) { + if (timeout_val < (dtcv / tcfclk)) { + break; + } + dtcv *= 2; + } + + /* set the data timeout counter value */ + reg = EMMC_SD_SRS11; + reg &= ~EMMC_SD_SRS11_DTCV_MASK; + reg |= (timeout_val << EMMC_SD_SRS11_DTCV_SHIFT) & EMMC_SD_SRS11_DTCV_MASK; + EMMC_SD_SRS11 = reg; + + return 0; +} + +#define DEFAULT_DELAY 0x00FFFFFF +void mmc_delay(uint32_t delay) +{ + while (delay--) { + asm volatile("nop"); + } +} + +/* voltage values: + * 0 = off + * EMMC_SD_SRS10_BVS_1_8V + * EMMC_SD_SRS10_BVS_3_0V + * EMMC_SD_SRS10_BVS_3_3V + */ +int mmc_set_power(uint32_t voltage) +{ + uint32_t reg; + + /* disable bus power */ + reg = EMMC_SD_SRS10; + reg &= ~EMMC_SD_SRS10_BP; + EMMC_SD_SRS10 = reg; + + if (voltage != 0) { + /* read voltage capabilities */ + uint32_t cap2 = EMMC_SD_SRS16; + + /* select voltage (if capable) */ + reg &= ~EMMC_SD_SRS10_BVS_MASK; + if (voltage == EMMC_SD_SRS10_BVS_1_8V && (cap2 & EMMC_SD_SRS16_VS18)) { + reg |= EMMC_SD_SRS10_BP | EMMC_SD_SRS10_BVS_1_8V; + } + else if (voltage == EMMC_SD_SRS10_BVS_3_0V && (cap2 & EMMC_SD_SRS16_VS30)) { + reg |= EMMC_SD_SRS10_BVS_3_0V; + } + else if (voltage == EMMC_SD_SRS10_BVS_3_3V && (cap2 & EMMC_SD_SRS16_VS33)) { + reg |= EMMC_SD_SRS10_BVS_3_3V; + } + else { + /* voltage not supported */ + return -1; + } + EMMC_SD_SRS10 = reg; + mmc_delay(DEFAULT_DELAY); /* delay after bus power is applied */ + } + return 0; +} + +/* returns actual frequency in kHz */ +uint32_t mmc_set_clock(uint32_t clock_khz) +{ + uint32_t reg, base_clk_khz, i, mclk, freq_khz; + + /* disable clock */ + EMMC_SD_SRS11 &= ~EMMC_SD_SRS11_SDCE; + + /* get base clock */ + reg = EMMC_SD_SRS16; + base_clk_khz = (reg & EMMC_SD_SRS16_BCSDCLK_MASK) >> EMMC_SD_SRS16_BCSDCLK_SHIFT; + if (base_clk_khz == 0) { + /* error getting base clock */ + return 0; + } + + /* select clock frequency */ + reg = EMMC_SD_SRS11; + reg &= ~(EMMC_SD_SRS11_SDCFSL_MASK | EMMC_SD_SRS11_SDCFSH_MASK); + /* calculate divider */ + for (i=1; i<2046; i++) { + if (((base_clk_khz / i) < clock_khz) || + (((base_clk_khz / i) == clock_khz) && (base_clk_khz % i) == 0)) { + break; + } + } + mclk = ((i / 2) << EMMC_SD_SRS11_SDCFSL_SHIFT); + reg |= (mclk & EMMC_SD_SRS11_SDCFSL_MASK) | ((mclk & 0x30000) >> 10); + reg |= EMMC_SD_SRS11_ICE; /* clock enable */ + reg &= ~EMMC_SD_SRS11_CGS; /* select clock */ + EMMC_SD_SRS11 = reg; + freq_khz = base_clk_khz / i; + + /* wait for clock to stabilize */ + while ((EMMC_SD_SRS11 & EMMC_SD_SRS11_ICE) == 0); + + /* enable clock */ + EMMC_SD_SRS11 |= EMMC_SD_SRS11_SDCE; + + mmc_delay(DEFAULT_DELAY); /* delay after clock changed */ + + return freq_khz; +} + +/* eMMC/SD Response Type */ +typedef enum { + EMMC_SD_RESP_NONE, + EMMC_SD_RESP_R1, + EMMC_SD_RESP_R1B, + EMMC_SD_RESP_R2, + EMMC_SD_RESP_R3, + EMMC_SD_RESP_R4, + EMMC_SD_RESP_R5, + EMMC_SD_RESP_R5B, + EMMC_SD_RESP_R6, + EMMC_SD_RESP_R7, + EMMC_SD_RESP_R1A +} EMMC_SD_Resp_t; + +static uint32_t mmc_get_response_type(uint8_t resp_type) +{ + uint32_t cmd_reg; + switch (resp_type) { + case EMMC_SD_RESP_R2: + cmd_reg = (EMMC_SD_SRS03_RESP_136 | EMMC_SD_SRS03_CRCCE); + break; + case EMMC_SD_RESP_R3: + case EMMC_SD_RESP_R4: + cmd_reg = EMMC_SD_SRS03_RESP_48; + break; + case EMMC_SD_RESP_R1: + case EMMC_SD_RESP_R5: + case EMMC_SD_RESP_R6: + case EMMC_SD_RESP_R7: + cmd_reg = (EMMC_SD_SRS03_RESP_48 | EMMC_SD_SRS03_CRCCE | EMMC_SD_SRS03_CICE); + break; + case EMMC_SD_RESP_R1B: + case EMMC_SD_RESP_R5B: + cmd_reg = (EMMC_SD_SRS03_RESP_48B | EMMC_SD_SRS03_CRCCE | EMMC_SD_SRS03_CICE); + break; + case EMMC_SD_RESP_NONE: + default: + cmd_reg = EMMC_SD_SRS03_RESP_NONE; + break; + } + return cmd_reg; +} + +int mmc_send_cmd(uint32_t cmd_index, uint32_t cmd_arg, uint8_t resp_type) +{ + uint32_t cmd_reg; + uint32_t cmd_type = EMMC_SD_SRS03_CMD_NORMAL; /* TODO: Add support for suspend and resume */ + +#ifdef DEBUG_MMC + wolfBoot_printf("mmc_send_cmd: cmd_index: %d, cmd_arg: %08X, resp_type: %d\n", + cmd_index, cmd_arg, resp_type); +#endif + + /* wait for command line to be idle - TODO: Add timeout */ + while ((EMMC_SD_SRS09 & EMMC_SD_SRS09_CICMD) != 0); + + /* clear all status interrupts (except current limit, card interrupt/removal/insert) */ + EMMC_SD_SRS12 = ~(EMMC_SD_SRS12_ECL | + EMMC_SD_SRS12_CINT | + EMMC_SD_SRS12_CR | + EMMC_SD_SRS12_CIN); + + /* set command argument and command transfer registers */ + EMMC_SD_SRS02 = cmd_arg; + cmd_reg = + ((cmd_index & EMMC_SD_SRS03_CIDX_MASK) << EMMC_SD_SRS03_CIDX_SHIFT) | + ((cmd_type & EMMC_SD_SRS03_CT_MASK) << EMMC_SD_SRS03_CT_SHIFT) | + mmc_get_response_type(resp_type); + + EMMC_SD_SRS03 = cmd_reg; + + if (resp_type != EMMC_SD_RESP_NONE) { + /* wait for command complete or error - TODO: Add timeout */ + while ((EMMC_SD_SRS12 & (EMMC_SD_SRS12_CC | EMMC_SD_SRS12_ERR_STAT)) == 0); + } + + /* clear all status interrupts (except current limit, card interrupt/removal/insert) */ + EMMC_SD_SRS12 = ~(EMMC_SD_SRS12_ECL | + EMMC_SD_SRS12_CINT | + EMMC_SD_SRS12_CR | + EMMC_SD_SRS12_CIN); + + return 0; +} + +/* Set power and send initialization commands */ +/* voltage: 0=off or EMMC_SD_SRS10_BVS_ */ +int mmc_power_init_seq(uint32_t voltage) +{ + /* Set power to specified voltage */ + int status = mmc_set_power(voltage); + if (status == 0) { + /* send CMD0 (go idle) to reset card */ + status = mmc_send_cmd(MMC_CMD0_GO_IDLE, 0, EMMC_SD_RESP_NONE); + + if (status == 0) { + mmc_delay(DEFAULT_DELAY); + + /* send the operating conditions command */ + status = mmc_send_cmd(SD_CMD8_SEND_IF_COND, IF_COND_27V_33V, + EMMC_SD_RESP_R7); + } + } + return status; +} + +int mmc_card_init(uint32_t acmd41_arg, uint32_t *ocr_reg) +{ + int status = mmc_send_cmd(SD_CMD55_APP_CMD, 0, EMMC_SD_RESP_R1); + if (status == 0) { + status = mmc_send_cmd(SD_ACMD41_SD_SEND_OP, acmd41_arg, + EMMC_SD_RESP_R3); + } + if (status == 0) { + *ocr_reg = EMMC_SD_SRS04; + } + return status; +} + +int mmc_init(void) +{ + int status = 0; + uint32_t reg, cap; + uint32_t ctrl_volts = EMMC_SD_SRS10_BVS_3_3V; /* default to 3.3v */ + uint32_t card_volts; + int is_xpc, is_si8r; + + /* Reset the MMC controller */ + SYSREG_SOFT_RESET_CR &= ~SYSREG_SOFT_RESET_CR_MMC; + /* Reset the host controller */ + EMMC_SD_HRS00 |= EMMC_SD_HRS00_SWR; + /* Bit will clear when reset is done */ + while ((EMMC_SD_HRS00 & EMMC_SD_HRS00_SWR) != 0); + + /* Set debounce period to ~15ms (at 200MHz) */ + EMMC_SD_HRS01 = (EMMC_SD_DEBOUNCE_TIME & EMMC_SD_HRS01_DP_MASK); + + /* Select SDCard Mode */ + reg = EMMC_SD_HRS06; + reg &= ~EMMC_SD_HRS06_EMM_MASK; + reg |= EMMC_SD_HRS06_MODE_SD; + EMMC_SD_HRS06 = reg; + + /* Clear error/interrupt status */ + EMMC_SD_SRS12 = (EMMC_SD_SRS12_NORM_STAT | EMMC_SD_SRS12_ERR_STAT); + + /* Check and enable 64-bit DMA support */ + reg = EMMC_SD_SRS15; + cap = EMMC_SD_SRS16; + if (cap & EMMC_SD_SRS16_A64S) { + reg |= EMMC_SD_SRS15_A64; + reg |= EMMC_SD_SRS15_HV4E; + EMMC_SD_SRS15 = reg; + } + /* Set all status enables */ + EMMC_SD_SRS13 = 0xFFFFFFFF; + /* Clear all signal enables */ + EMMC_SD_SRS14 = 0; + /* Set initial timeout to 500ms */ + status = mmc_set_timeout(EMMC_SD_DATA_TIMEOUT_US); + if (status != 0) { + return status; + } + /* Turn off host controller power */ + (void)mmc_set_power(0); + + /* check if card inserted and stable */ + reg = EMMC_SD_SRS09; + if ((reg & EMMC_SD_SRS09_CSS) == 0) { + /* card not inserted or not stable */ + return -1; + } + /* NOTE: if using eMMC mode skip this check */ + if ((reg & EMMC_SD_SRS09_CI) == 0) { + /* card not inserted */ + return -1; + } + + /* Start in 1-bit bus mode */ + reg = EMMC_SD_SRS10; + reg &= ~EMMC_SD_SRS10_DTW; + reg &= ~EMMC_SD_SRS10_EDTW; + EMMC_SD_SRS10 = reg; + + /* Setup 400khz starting clock */ + mmc_set_clock(EMMC_SD_CLK_400KHZ); + + /* Set power to 3.3v and send init commands */ + status = mmc_power_init_seq(ctrl_volts); + if (status == 0) { + uint32_t max_ma_3_3v, max_ma_1_8v; + /* determine host controller capabilities */ + reg = EMMC_SD_SRS18; + max_ma_3_3v = (reg & EMMC_SD_SRS18_MC33_MASK) >> EMMC_SD_SRS18_MC33_SHIFT; + max_ma_1_8v = (reg & EMMC_SD_SRS18_MC18_MASK) >> EMMC_SD_SRS18_MC18_SHIFT; + /* does it support eXtended Power Control (XPC)? */ + is_xpc = (max_ma_1_8v >= 150) && (max_ma_3_3v >= 150) ? 1 : 0; + /* does it support UHS-I (Ultra High Speed Interface) v1.8 signaling? */ + is_si8r =((EMMC_SD_SRS16 & EMMC_SD_SRS16_VS18) && /* 1.8v supported */ + (EMMC_SD_SRS17 & (EMMC_SD_SRS17_DDR50 | /* DDR50, SDR104, SDR50 or supported */ + EMMC_SD_SRS17_SDR104 | + EMMC_SD_SRS17_SDR50))) ? 1: 0; + } + if (status == 0) { + reg = 0; + status = mmc_card_init(0, ®); + if (status == 0) { + /* pick host and card operating voltages */ + if (reg & SDCARD_REG_OCR_3_3_3_4) { /* 3.3v - 3.4v */ + card_volts = SDCARD_REG_OCR_3_3_3_4; + } + else if (reg & SDCARD_REG_OCR_3_2_3_3) { /* 3.2v - 3.3v */ + card_volts = SDCARD_REG_OCR_3_2_3_3; + } + else if (reg & SDCARD_REG_OCR_3_1_3_2) { /* 3.1v - 3.2v */ + card_volts = SDCARD_REG_OCR_3_1_3_2; + } + else if (reg & SDCARD_REG_OCR_3_0_3_1) { /* 3.0v - 3.1v */ + card_volts = SDCARD_REG_OCR_3_0_3_1; + ctrl_volts = EMMC_SD_SRS10_BVS_3_0V; + } + else if (reg & SDCARD_REG_OCR_2_9_3_0) { /* 2.9v - 3.0v */ + card_volts = SDCARD_REG_OCR_2_9_3_0; + ctrl_volts = EMMC_SD_SRS10_BVS_3_0V; + } + else { /* default to v3.3 */ + card_volts = SDCARD_REG_OCR_3_3_3_4; + } + /* if needed change operating volage and re-init */ + if (ctrl_volts != EMMC_SD_SRS10_BVS_3_3V) { + status = mmc_power_init_seq(ctrl_volts); + } + } + } + if (status == 0) { + /* configure operating conditions */ + uint32_t cmd_arg = SDCARD_ACMD41_HCS; + cmd_arg |= card_volts; + if (is_si8r) { + cmd_arg |= SDCARD_REG_OCR_S18RA; + } + if (is_xpc) { + cmd_arg |= SDCARD_REG_OCR_XPC; + } + + /* retry until OCR ready */ + do { + status = mmc_card_init(cmd_arg, ®); + } while (status == 0 && (reg & SDCARD_REG_OCR_READY) == 0); + + + } + return status; +} + /* TODO: Add support for reading uSD card with GPT (Global Partition Table) */ /* The partition ID's are determined using BOOT_PART_A and BOOT_PART_B. */ int disk_open(int drv) { + wolfBoot_printf("disk_open: drv = %d\r\n", drv); (void)drv; - return 0; + return mmc_init(); } int disk_read(int drv, int part, uint64_t off, uint64_t sz, uint8_t *buf) { diff --git a/hal/mpfs250.h b/hal/mpfs250.h index 63348cbe0f..e203e893ec 100644 --- a/hal/mpfs250.h +++ b/hal/mpfs250.h @@ -24,6 +24,7 @@ /* PolarFire SoC MPFS250T board specific configuration */ +/* APB/AHB Clock Frequency */ #define MSS_APB_AHB_CLK 150000000 /* Hardware Base Address */ @@ -32,6 +33,25 @@ /* Write "0xDEAD" to cause a full MSS reset*/ #define SYSREG_MSS_RESET_CR (*((volatile uint32_t*)(SYSREG_BASE + 0x18))) +/* Peripheral Soft Reset Control Register */ +#define SYSREG_SOFT_RESET_CR (*((volatile uint32_t*)(SYSREG_BASE + 0x88))) +#define SYSREG_SOFT_RESET_CR_ENVM (1U << 0) +#define SYSREG_SOFT_RESET_CR_MMC (1U << 3) +#define SYSREG_SOFT_RESET_CR_MMUART0 (1U << 5) +#define SYSREG_SOFT_RESET_CR_MMUART1 (1U << 6) +#define SYSREG_SOFT_RESET_CR_MMUART2 (1U << 7) +#define SYSREG_SOFT_RESET_CR_MMUART3 (1U << 8) +#define SYSREG_SOFT_RESET_CR_MMUART4 (1U << 9) +#define SYSREG_SOFT_RESET_CR_SPI0 (1U << 10) +#define SYSREG_SOFT_RESET_CR_SPI1 (1U << 11) +#define SYSREG_SOFT_RESET_CR_QSPI (1U << 19) +#define SYSREG_SOFT_RESET_CR_GPIO0 (1U << 20) +#define SYSREG_SOFT_RESET_CR_GPIO1 (1U << 21) +#define SYSREG_SOFT_RESET_CR_GPIO2 (1U << 22) +#define SYSREG_SOFT_RESET_CR_DDRC (1U << 23) +#define SYSREG_SOFT_RESET_CR_ATHENA (1U << 28) /* Crypto hardware accelerator */ + + /* TODO: Add support for machine mode wolfBoot */ #if 1 #define WOLFBOOT_RISCV_SMODE /* supervisor mode */ @@ -43,10 +63,10 @@ #define REGBYTES (1 << 3) /* Machine Information Registers */ -#define CSR_MVENDORID 0xf11 -#define CSR_MARCHID 0xf12 -#define CSR_MIMPID 0xf13 -#define CSR_MHARTID 0xf14 +#define CSR_MVENDORID 0xF11 +#define CSR_MARCHID 0xF12 +#define CSR_MIMPID 0xF13 +#define CSR_MHARTID 0xF14 /* Initial stack pointer address (stack grows downward from here) */ #ifdef WOLFBOOT_RISCV_SMODE @@ -77,7 +97,6 @@ #define SIE_SEIE (1 << IRQ_S_EXT) - /* UART */ #define MSS_UART0_LO_BASE 0x20000000UL #define MSS_UART1_LO_BASE 0x20100000UL @@ -124,29 +143,736 @@ #define MSS_UART_THRE ((uint8_t)0x20) /* Transmitter holding register empty */ #define MSS_UART_TEMT ((uint8_t)0x40) /* Transmit empty */ -#define ELIN_MASK (0x01u << 3u) /* Enable LIN header detection */ -#define EIRD_MASK (0x01u << 2u) /* Enable IrDA modem */ -#define EERR_MASK (0x01u << 0u) /* Enable ERR / NACK during stop time */ +#define ELIN_MASK (1U << 3) /* Enable LIN header detection */ +#define EIRD_MASK (1U << 2) /* Enable IrDA modem */ +#define EERR_MASK (1U << 0) /* Enable ERR / NACK during stop time */ -#define RXRDY_TXRDYN_EN_MASK (0x01u << 0u) /* Enable TXRDY and RXRDY signals */ -#define CLEAR_RX_FIFO_MASK (0x01u << 1u) /* Clear receiver FIFO */ -#define CLEAR_TX_FIFO_MASK (0x01u << 2u) /* Clear transmitter FIFO */ +#define RXRDY_TXRDYN_EN_MASK (1U << 0) /* Enable TXRDY and RXRDY signals */ +#define CLEAR_RX_FIFO_MASK (1U << 1) /* Clear receiver FIFO */ +#define CLEAR_TX_FIFO_MASK (1U << 2) /* Clear transmitter FIFO */ -#define LOOP_MASK (0x01u << 4u) /* Local loopback */ -#define RLOOP_MASK (0x01u << 5u) /* Remote loopback & Automatic echo*/ +#define LOOP_MASK (1U << 4) /* Local loopback */ +#define RLOOP_MASK (1U << 5) /* Remote loopback & Automatic echo*/ -#define E_MSB_RX_MASK (0x01u << 0u) /* MSB / LSB first for receiver */ -#define E_MSB_TX_MASK (0x01u << 1u) /* MSB / LSB first for transmitter */ +#define E_MSB_RX_MASK (1U << 0) /* MSB / LSB first for receiver */ +#define E_MSB_TX_MASK (1U << 1) /* MSB / LSB first for transmitter */ -#define EAFM_MASK (0x01u << 1u) /* Enable 9-bit address flag mode */ -#define ETTG_MASK (0x01u << 5u) /* Enable transmitter time guard */ -#define ERTO_MASK (0x01u << 6u) /* Enable receiver time-out */ -#define ESWM_MASK (0x01u << 3u) /* Enable single wire half-duplex mode */ -#define EFBR_MASK (0x01u << 7u) /* Enable fractional baud rate mode */ +#define EAFM_MASK (1U << 1) /* Enable 9-bit address flag mode */ +#define ETTG_MASK (1U << 5) /* Enable transmitter time guard */ +#define ERTO_MASK (1U << 6) /* Enable receiver time-out */ +#define ESWM_MASK (1U << 3) /* Enable single wire half-duplex mode */ +#define EFBR_MASK (1U << 7) /* Enable fractional baud rate mode */ /* Line Control register bit masks */ -#define SB_MASK (0x01u << 6) /* Set break */ -#define DLAB_MASK (0x01u << 7) /* Divisor latch access bit */ +#define SB_MASK (1U << 6) /* Set break */ +#define DLAB_MASK (1U << 7) /* Divisor latch access bit */ + +/* ============================================================================ + * EMMC/SD Card Controller (Cadence SD4HC) + * Base Address: 0x20008000 + * ============================================================================ */ +#define EMMC_SD_BASE 0x20008000UL + +/* ---------------------------------------------------------------------------- + * HRS - Host Register Set (Cadence-specific registers) + * ---------------------------------------------------------------------------- */ + +/* HRS00 - General Information Register */ +#define EMMC_SD_HRS00 *((volatile uint32_t*)(EMMC_SD_BASE + 0x000)) +#define EMMC_SD_HRS00_SAV_SHIFT 16 /* 23:16: RO - Number of slots */ +#define EMMC_SD_HRS00_SAV_MASK (0xFFU << 16) +#define EMMC_SD_HRS00_SWR (1U << 0) /* 0: RW - Software Reset (entire core) */ + +/* HRS01 - Debounce Setting Register */ +#define EMMC_SD_HRS01 *((volatile uint32_t*)(EMMC_SD_BASE + 0x004)) +#define EMMC_SD_HRS01_DP_SHIFT 0 /* 23:0: RW - Debounce Period */ +#define EMMC_SD_HRS01_DP_MASK (0xFFFFFFU << 0) + +/* HRS02 - Bus Setting Register */ +#define EMMC_SD_HRS02 *((volatile uint32_t*)(EMMC_SD_BASE + 0x008)) +#define EMMC_SD_HRS02_OTN_SHIFT 16 /* 17:16: RW - Outstanding Transactions Number */ +#define EMMC_SD_HRS02_OTN_MASK (0x3U << 16) +#define EMMC_SD_HRS02_PBL_SHIFT 0 /* 3:0: RW - Programmable Burst Length */ +#define EMMC_SD_HRS02_PBL_MASK (0xFU << 0) + +/* HRS03 - AXI ERROR Responses Register */ +#define EMMC_SD_HRS03 *((volatile uint32_t*)(EMMC_SD_BASE + 0x00C)) +#define EMMC_SD_HRS03_AER_IEBS (1U << 19) /* 19: Int Enable Bus Status */ +#define EMMC_SD_HRS03_AER_IEBD (1U << 18) /* 18: Int Enable Bus Data */ +#define EMMC_SD_HRS03_AER_IERS (1U << 17) /* 17: Int Enable Resp Status */ +#define EMMC_SD_HRS03_AER_IERD (1U << 16) /* 16: Int Enable Resp Data */ +#define EMMC_SD_HRS03_AER_SENBS (1U << 11) /* 11: Status Enable Bus Status */ +#define EMMC_SD_HRS03_AER_SENBD (1U << 10) /* 10: Status Enable Bus Data */ +#define EMMC_SD_HRS03_AER_SENRS (1U << 9) /* 9: Status Enable Resp Status */ +#define EMMC_SD_HRS03_AER_SENRD (1U << 8) /* 8: Status Enable Resp Data */ + +/* HRS04 - PHY Registers Interface (SD/eMMC PHY access) */ +#define EMMC_SD_HRS04 *((volatile uint32_t*)(EMMC_SD_BASE + 0x010)) +#define EMMC_SD_HRS04_UIS_ACK (1U << 26) /* 26: RO - PHY Acknowledge */ +#define EMMC_SD_HRS04_UIS_RD (1U << 25) /* 25: RW - PHY Read Request */ +#define EMMC_SD_HRS04_UIS_WR (1U << 24) /* 24: RW - PHY Write Request */ +#define EMMC_SD_HRS04_UIS_RDATA_SHIFT 16 /* 23:16: RO - PHY Read Data */ +#define EMMC_SD_HRS04_UIS_RDATA_MASK (0xFFU << 16) +#define EMMC_SD_HRS04_UIS_WDATA_SHIFT 8 /* 15:8: RW - PHY Write Data */ +#define EMMC_SD_HRS04_UIS_WDATA_MASK (0xFFU << 8) +#define EMMC_SD_HRS04_UIS_ADDR_SHIFT 0 /* 5:0: RW - PHY Register Address */ +#define EMMC_SD_HRS04_UIS_ADDR_MASK (0x3FU << 0) +/* PHY register addresses */ +#define EMMC_SD_PHY_ADDR_HIGH_SPEED 0x00U +#define EMMC_SD_PHY_ADDR_DEFAULT_SPEED 0x01U +#define EMMC_SD_PHY_ADDR_UHSI_SDR12 0x02U +#define EMMC_SD_PHY_ADDR_UHSI_SDR25 0x03U +#define EMMC_SD_PHY_ADDR_UHSI_SDR50 0x04U +#define EMMC_SD_PHY_ADDR_UHSI_DDR50 0x05U +#define EMMC_SD_PHY_ADDR_MMC_LEGACY 0x06U +#define EMMC_SD_PHY_ADDR_MMC_SDR 0x07U +#define EMMC_SD_PHY_ADDR_MMC_DDR 0x08U +#define EMMC_SD_PHY_ADDR_SDCLK 0x0BU +#define EMMC_SD_PHY_ADDR_HS_SDCLK 0x0CU +#define EMMC_SD_PHY_ADDR_DAT_STROBE 0x0DU + +/* HRS06 - eMMC Control Register */ +#define EMMC_SD_HRS06 *((volatile uint32_t*)(EMMC_SD_BASE + 0x018)) +#define EMMC_SD_HRS06_ETR (1U << 15) /* 15: RW - eMMC Tune Request */ +#define EMMC_SD_HRS06_ETV_SHIFT 8 /* eMMC Tune Value */ +#define EMMC_SD_HRS06_ETV_MASK 0x3FU +#define EMMC_SD_HRS06_EMM_SHIFT 0 /* 2:0: RW - eMMC Mode Select */ +#define EMMC_SD_HRS06_EMM_MASK (0x7U << 0) +/* eMMC Mode values */ +#define EMMC_SD_HRS06_MODE_SD (0x0U << 0) /* SD card mode */ +#define EMMC_SD_HRS06_MODE_MMC_SDR (0x2U << 0) /* eMMC SDR mode */ +#define EMMC_SD_HRS06_MODE_MMC_DDR (0x3U << 0) /* eMMC DDR mode */ +#define EMMC_SD_HRS06_MODE_MMC_HS200 (0x4U << 0) /* eMMC HS200 mode */ +#define EMMC_SD_HRS06_MODE_MMC_HS400 (0x5U << 0) /* eMMC HS400 mode */ +#define EMMC_SD_HRS06_MODE_MMC_HS400ES (0x6U << 0) /* eMMC HS400 Enhanced Strobe */ +#define EMMC_SD_HRS06_MODE_LEGACY (0x7U << 0) /* Legacy mode */ + +/* HRS07 - IO Delay Information Register */ +#define EMMC_SD_HRS07 *((volatile uint32_t*)(EMMC_SD_BASE + 0x01C)) +#define EMMC_SD_HRS07_ODELAY_VAL_SHIFT 16 /* 20:16: RW - Output Delay Value */ +#define EMMC_SD_HRS07_ODELAY_VAL_MASK (0x1FU << 16) +#define EMMC_SD_HRS07_IDELAY_VAL_SHIFT 0 /* 4:0: RW - Input Delay Value */ +#define EMMC_SD_HRS07_IDELAY_VAL_MASK (0x1FU << 0) + +#define EMMC_SD_HRS30 *((volatile uint32_t*)(EMMC_SD_BASE + 0x078)) /* Host Capability Register */ +#define EMMC_SD_HRS30_HS400ESSUP (1U << 1) /* 1: RO - HS400 Enhanced Strobe Support */ +#define EMMC_SD_HRS30_CQSUP (1U << 0) /* 0: RO - Command Queuing Support */ + +#define EMMC_SD_HRS31 *((volatile uint32_t*)(EMMC_SD_BASE + 0x07C)) /* Host Controller Version */ +#define EMMC_SD_HRS31_HOSTCTRLVER_SHIFT 16 /* 27:16: RO */ +#define EMMC_SD_HRS31_HOSTCTRLVER_MASK (0xFFFU << 16) +#define EMMC_SD_HRS31_HOSTFIXVER_SHIFT 0 /* 7:0: RO */ +#define EMMC_SD_HRS31_HOSTFIXVER_MASK (0xFFU << 0) + +#define EMMC_SD_HRS32 *((volatile uint32_t*)(EMMC_SD_BASE + 0x080)) /* FSM Monitor Register */ +#define EMMC_SD_HRS32_LOAD (1U << 31) /* 31: RW */ +#define EMMC_SD_HRS32_ADDR_SHIFT 16 /* 30:16: WO */ +#define EMMC_SD_HRS32_ADDR_MASK (0x7FFFU << 16) +#define EMMC_SD_HRS32_DATA_SHIFT 0 /* 15:0: RO */ +#define EMMC_SD_HRS32_DATA_MASK (0xFFFFU << 0) + +#define EMMC_SD_HRS33 *((volatile uint32_t*)(EMMC_SD_BASE + 0x084)) /* Tune Status 0 Register */ +#define EMMC_SD_HRS33_STAT0_SHIFT 0 /* 31:0: RO */ +#define EMMC_SD_HRS33_STAT0_MASK (0xFFFFFFFFU << 0) + +#define EMMC_SD_HRS34 *((volatile uint32_t*)(EMMC_SD_BASE + 0x088)) /* Tune Status 1 Register */ +#define EMMC_SD_HRS34_STAT1_SHIFT 0 /* 7:0: RO */ +#define EMMC_SD_HRS34_STAT1_MASK (0xFFU << 0) + +#define EMMC_SD_HRS35 *((volatile uint32_t*)(EMMC_SD_BASE + 0x08C)) /* Tune Debug Register */ +#define EMMC_SD_HRS35_TFR (1U << 31) /* 31: RW */ +#define EMMC_SD_HRS35_TFV_SHIFT 16 /* 21:16: RW */ +#define EMMC_SD_HRS35_TFV_MASK (0x3FU << 16) +#define EMMC_SD_HRS35_TVAL_SHIFT 0 /* 5:0: RO */ +#define EMMC_SD_HRS35_TVAL_MASK (0x3FU << 0) + +#define EMMC_SD_HRS36 *((volatile uint32_t*)(EMMC_SD_BASE + 0x090)) /* Boot Status Register */ +#define EMMC_SD_HRS36_BOOT_EDE (1U << 5) /* 5: RO - Boot Error Data End Bit */ +#define EMMC_SD_HRS36_BOOT_EDC (1U << 4) /* 4: RO - Boot Error Data CRC */ +#define EMMC_SD_HRS36_BOOT_EDT (1U << 3) /* 3: RO - Boot Error Data Timeout */ +#define EMMC_SD_HRS36_BOOT_EAI (1U << 2) /* 2: RO - Boot Error Ack Index */ +#define EMMC_SD_HRS36_BOOT_EAT (1U << 1) /* 1: RO - Boot Error Ack Timeout */ +#define EMMC_SD_HRS36_BOOT_ACT (1U << 0) /* 0: RO - Boot Active */ + +#define EMMC_SD_HRS37 *((volatile uint32_t*)(EMMC_SD_BASE + 0x094)) /* Read block gap coeff interface mode select */ +#define EMMC_SD_HRS37_RGB_COEFF_IFM_SHIFT 0 /* 5:0: RW */ +#define EMMC_SD_HRS37_RGB_COEFF_IFM_MASK (0x3FU << 0) + +#define EMMC_SD_HRS38 *((volatile uint32_t*)(EMMC_SD_BASE + 0x098)) /* Read block gap coefficient */ +#define EMMC_SD_HRS38_RGB_COEFF_SHIFT 0 /* 3:0: RW */ +#define EMMC_SD_HRS38_RGB_COEFF_MASK (0xFU << 0) + +/* CRS - Capability Register Set */ +#define EMMC_SD_CRS63 *((volatile uint32_t*)(EMMC_SD_BASE + 0x0FC)) /* Host Controller Version/Slot Interrupt Status */ +#define EMMC_SD_CRS63_SVN_SHIFT 16 /* 23:16: RO */ +#define EMMC_SD_CRS63_SVN_MASK (0xFFU << 16) +#define EMMC_SD_CRS63_ISES_SHIFT 0 /* 7:0: RO */ +#define EMMC_SD_CRS63_ISES_MASK (0xFFU << 0) + +/* ---------------------------------------------------------------------------- + * SRS - Slot Register Set (SD Host Controller Standard Registers) + * ---------------------------------------------------------------------------- */ + +/* SRS00 - SDMA System Address / Argument 2 (for Auto CMD23) */ +#define EMMC_SD_SRS00 *((volatile uint32_t*)(EMMC_SD_BASE + 0x200)) +#define EMMC_SD_SRS00_SAAR_SHIFT 0 /* 31:0: RW */ +#define EMMC_SD_SRS00_SAAR_MASK (0xFFFFFFFFU << 0) + +/* SRS01 - Block Size / Block Count Register */ +#define EMMC_SD_SRS01 *((volatile uint32_t*)(EMMC_SD_BASE + 0x204)) +#define EMMC_SD_SRS01_BCCT_SHIFT 16 /* 31:16: RW - Block Count for Current Transfer */ +#define EMMC_SD_SRS01_BCCT_MASK (0xFFFFU << 16) +#define EMMC_SD_SRS01_SDMABB_SHIFT 12 /* SDMA Buffer Boundary */ +#define EMMC_SD_SRS01_SDMABB_MASK 0x7U +#define EMMC_SD_SRS01_DMA_BUFF_4KB (0x0U << 12) /* DMA buffer 4KB boundary */ +#define EMMC_SD_SRS01_DMA_BUFF_8KB (0x1U << 12) /* DMA buffer 8KB boundary */ +#define EMMC_SD_SRS01_DMA_BUFF_16KB (0x2U << 12) /* DMA buffer 16KB boundary */ +#define EMMC_SD_SRS01_DMA_BUFF_32KB (0x3U << 12) /* DMA buffer 32KB boundary */ +#define EMMC_SD_SRS01_DMA_BUFF_64KB (0x4U << 12) /* DMA buffer 64KB boundary */ +#define EMMC_SD_SRS01_DMA_BUFF_128KB (0x5U << 12) /* DMA buffer 128KB boundary */ +#define EMMC_SD_SRS01_DMA_BUFF_256KB (0x6U << 12) /* DMA buffer 256KB boundary */ +#define EMMC_SD_SRS01_DMA_BUFF_512KB (0x7U << 12) /* DMA buffer 512KB boundary */ +#define EMMC_SD_SRS01_TBS_SHIFT 0 /* 11:0: RW - Transfer Block Size */ +#define EMMC_SD_SRS01_TBS_MASK (0xFFFU << 0) + +/* SRS02 - Argument 1 Register */ +#define EMMC_SD_SRS02 *((volatile uint32_t*)(EMMC_SD_BASE + 0x208)) +#define EMMC_SD_SRS02_ARG1_SHIFT 0 /* 31:0: RW */ +#define EMMC_SD_SRS02_ARG1_MASK (0xFFFFFFFFU << 0) + +/* SRS03 - Command/Transfer Mode Register */ +#define EMMC_SD_SRS03 *((volatile uint32_t*)(EMMC_SD_BASE + 0x20C)) +#define EMMC_SD_SRS03_CIDX_SHIFT 24 /* 29:24: RW - Command Index */ +#define EMMC_SD_SRS03_CIDX_MASK (0x3FU << 24) +#define EMMC_SD_SRS03_CT_SHIFT 22 /* 23:22: RW - Command Type */ +#define EMMC_SD_SRS03_CT_MASK (0x3U << 22) +#define EMMC_SD_SRS03_CMD_NORMAL (0x0U << 22) /* Normal command */ +#define EMMC_SD_SRS03_CMD_SUSPEND (0x1U << 22) /* Suspend command */ +#define EMMC_SD_SRS03_CMD_RESUME (0x2U << 22) /* Resume command */ +#define EMMC_SD_SRS03_CMD_ABORT (0x3U << 22) /* Abort command (CMD12, CMD52) */ +#define EMMC_SD_SRS03_DPS (1U << 21) /* 21: RW - Data Present Select */ +#define EMMC_SD_SRS03_CICE (1U << 20) /* 20: RW - Command Index Check Enable */ +#define EMMC_SD_SRS03_CRCCE (1U << 19) /* 19: RW - Command CRC Check Enable */ +#define EMMC_SD_SRS03_RTS_SHIFT 16 /* Response Type Select */ +#define EMMC_SD_SRS03_RTS_MASK 0x3U +#define EMMC_SD_SRS03_RESP_NONE (0x0U << 16) /* No response */ +#define EMMC_SD_SRS03_RESP_136 (0x1U << 16) /* Response length 136 bits */ +#define EMMC_SD_SRS03_RESP_48 (0x2U << 16) /* Response length 48 bits */ +#define EMMC_SD_SRS03_RESP_48B (0x3U << 16) /* Response length 48 bits + busy */ +#define EMMC_SD_SRS03_RID (1U << 8) /* 8: RW - Response Interrupt Disable */ +#define EMMC_SD_SRS03_RECE (1U << 7) /* 7: RW - Response Error Check Enable */ +#define EMMC_SD_SRS03_RECT (1U << 6) /* 6: RW - Response Check Type (R1/R5) */ +#define EMMC_SD_SRS03_MSBS (1U << 5) /* 5: RW - Multi/Single Block Select */ +#define EMMC_SD_SRS03_DTDS (1U << 4) /* 4: RW - Data Transfer Direction (1=read) */ +#define EMMC_SD_SRS03_ACE_SHIFT 2 /* 3:2: RW - Auto CMD Enable */ +#define EMMC_SD_SRS03_ACE_MASK (0x3U << 2) +#define EMMC_SD_SRS03_ACMD_DISABLE (0x0U << 2) /* Auto CMD disabled */ +#define EMMC_SD_SRS03_ACMD12 (0x1U << 2) /* Auto CMD12 enable */ +#define EMMC_SD_SRS03_ACMD23 (0x2U << 2) /* Auto CMD23 enable */ +#define EMMC_SD_SRS03_BCE (1U << 1) /* 1: RW - Block Count Enable */ +#define EMMC_SD_SRS03_DMAE (1U << 0) /* 0: RW - DMA Enable */ + +#define EMMC_SD_SRS04 *((volatile uint32_t*)(EMMC_SD_BASE + 0x210)) /* Response Register 1 */ +#define EMMC_SD_SRS04_RESP1_SHIFT 0 /* 31:0: RO */ +#define EMMC_SD_SRS04_RESP1_MASK (0xFFFFFFFFU << 0) + +#define EMMC_SD_SRS05 *((volatile uint32_t*)(EMMC_SD_BASE + 0x214)) /* Response Register 2 */ +#define EMMC_SD_SRS05_RESP2_SHIFT 0 /* 31:0: RO */ +#define EMMC_SD_SRS05_RESP2_MASK (0xFFFFFFFFU << 0) + +#define EMMC_SD_SRS06 *((volatile uint32_t*)(EMMC_SD_BASE + 0x218)) /* Response Register 3 */ +#define EMMC_SD_SRS06_RESP3_SHIFT 0 /* 31:0: RO */ +#define EMMC_SD_SRS06_RESP3_MASK (0xFFFFFFFFU << 0) + +#define EMMC_SD_SRS07 *((volatile uint32_t*)(EMMC_SD_BASE + 0x21C)) /* Response Register 4 */ +#define EMMC_SD_SRS07_RESP4_SHIFT 0 /* 31:0: RO */ +#define EMMC_SD_SRS07_RESP4_MASK (0xFFFFFFFFU << 0) + +#define EMMC_SD_SRS08 *((volatile uint32_t*)(EMMC_SD_BASE + 0x220)) /* Data Buffer */ +#define EMMC_SD_SRS08_BDP_SHIFT 0 /* 31:0: RW */ +#define EMMC_SD_SRS08_BDP_MASK (0xFFFFFFFFU << 0) + +/* SRS09 - Present State Register */ +#define EMMC_SD_SRS09 *((volatile uint32_t*)(EMMC_SD_BASE + 0x224)) +#define EMMC_SD_SRS09_CMDSL (1U << 24) /* 24: RO - CMD Line Signal Level */ +#define EMMC_SD_SRS09_DATSL1_SHIFT 20 /* 23:20: RO - DAT[3:0] Line Signal Level */ +#define EMMC_SD_SRS09_DATSL1_MASK (0xFU << 20) +#define EMMC_SD_SRS09_DAT3_LVL (1U << 23) /* 23: RO - DAT3 signal level */ +#define EMMC_SD_SRS09_DAT2_LVL (1U << 22) /* 22: RO - DAT2 signal level */ +#define EMMC_SD_SRS09_DAT1_LVL (1U << 21) /* 21: RO - DAT1 signal level */ +#define EMMC_SD_SRS09_DAT0_LVL (1U << 20) /* 20: RO - DAT0 signal level */ +#define EMMC_SD_SRS09_WPSL (1U << 19) /* 19: RO - Write Protect Switch Level */ +#define EMMC_SD_SRS09_CDSL (1U << 18) /* 18: RO - Card Detect Pin Level */ +#define EMMC_SD_SRS09_CSS (1U << 17) /* 17: RO - Card State Stable */ +#define EMMC_SD_SRS09_CI (1U << 16) /* 16: RO - Card Inserted */ +#define EMMC_SD_SRS09_BRE (1U << 11) /* 11: RO - Buffer Read Enable */ +#define EMMC_SD_SRS09_BWE (1U << 10) /* 10: RO - Buffer Write Enable */ +#define EMMC_SD_SRS09_RTA (1U << 9) /* 9: RO - Read Transfer Active */ +#define EMMC_SD_SRS09_WTA (1U << 8) /* 8: RO - Write Transfer Active */ +#define EMMC_SD_SRS09_DATSL2_SHIFT 4 /* 7:4: RO - DAT[7:4] Line Signal Level */ +#define EMMC_SD_SRS09_DATSL2_MASK (0xFU << 4) +#define EMMC_SD_SRS09_DLA (1U << 2) /* 2: RO - DAT Line Active */ +#define EMMC_SD_SRS09_CIDAT (1U << 1) /* 1: RO - Command Inhibit (DAT) */ +#define EMMC_SD_SRS09_CICMD (1U << 0) /* 0: RO - Command Inhibit (CMD) */ + +/* SRS10 - Host Control 1 Register (Power/Block-Gap/Wake-Up) */ +#define EMMC_SD_SRS10 *((volatile uint32_t*)(EMMC_SD_BASE + 0x228)) +#define EMMC_SD_SRS10_WORM (1U << 26) /* 26: RW - Wakeup on Card Removal */ +#define EMMC_SD_SRS10_WOIS (1U << 25) /* 25: RW - Wakeup on Card Insertion */ +#define EMMC_SD_SRS10_WOIQ (1U << 24) /* 24: RW - Wakeup on Card Interrupt */ +#define EMMC_SD_SRS10_IBG (1U << 19) /* 19: RW - Interrupt at Block Gap */ +#define EMMC_SD_SRS10_RWC (1U << 18) /* 18: RW - Read Wait Control */ +#define EMMC_SD_SRS10_CREQ (1U << 17) /* 17: RW - Continue Request */ +#define EMMC_SD_SRS10_SBGR (1U << 16) /* 16: RW - Stop at Block Gap Request */ +#define EMMC_SD_SRS10_BVS2_SHIFT 13 /* 15:13: RW - SD Bus Voltage Select (VDD2) */ +#define EMMC_SD_SRS10_BVS2_MASK (0x7U << 13) +#define EMMC_SD_SRS10_BP2 (1U << 12) /* 12: RW - Bus Power (VDD2) */ +#define EMMC_SD_SRS10_BVS_SHIFT 9 /* 11:9: RW - SD Bus Voltage Select */ +#define EMMC_SD_SRS10_BVS_MASK (0x7U << 9) +#define EMMC_SD_SRS10_BVS_3_3V (0x7U << 9) /* SD bus voltage 3.3V */ +#define EMMC_SD_SRS10_BVS_3_0V (0x6U << 9) /* SD bus voltage 3.0V */ +#define EMMC_SD_SRS10_BVS_1_8V (0x5U << 9) /* SD bus voltage 1.8V */ +#define EMMC_SD_SRS10_BVS_CLR (0x7U << 9) /* Clear voltage field mask */ +#define EMMC_SD_SRS10_BP (1U << 8) /* 8: RW - SD Bus Power */ +/* Power-on sequences: combine voltage selection with bus power enable */ +#define EMMC_SD_SRS10_PWR_3_3V (EMMC_SD_SRS10_BVS_3_3V | EMMC_SD_SRS10_BP) +#define EMMC_SD_SRS10_PWR_3_0V (EMMC_SD_SRS10_BVS_3_0V | EMMC_SD_SRS10_BP) +#define EMMC_SD_SRS10_PWR_1_8V (EMMC_SD_SRS10_BVS_1_8V | EMMC_SD_SRS10_BP) +#define EMMC_SD_SRS10_CDSS (1U << 7) /* 7: RW - Card Detect Signal Selection */ +#define EMMC_SD_SRS10_CDTL (1U << 6) /* 6: RW - Card Detect Test Level */ +#define EMMC_SD_SRS10_EDTW (1U << 5) /* 5: RW - Extended Data Transfer Width (8-bit) */ +#define EMMC_SD_SRS10_DMASEL_SHIFT 3 /* 4:3: RW - DMA Select */ +#define EMMC_SD_SRS10_DMASEL_MASK (0x3U << 3) +#define EMMC_SD_SRS10_DMA_SDMA (0x0U << 3) /* SDMA mode */ +#define EMMC_SD_SRS10_DMA_ADMA1 (0x1U << 3) /* ADMA1 mode */ +#define EMMC_SD_SRS10_DMA_ADMA2 (0x2U << 3) /* ADMA2 mode */ +#define EMMC_SD_SRS10_HSE (1U << 2) /* 2: RW - High Speed Enable */ +#define EMMC_SD_SRS10_DTW (1U << 1) /* 1: RW - Data Transfer Width (1=4-bit) */ +#define EMMC_SD_SRS10_LEDC (1U << 0) /* 0: RW - LED Control */ + +/* SRS11 - Host Control 2 Register (Clock/Timeout/Reset) */ +#define EMMC_SD_SRS11 *((volatile uint32_t*)(EMMC_SD_BASE + 0x22C)) +#define EMMC_SD_SRS11_SRDA (1U << 26) /* 26: RW - Software Reset for DAT Line */ +#define EMMC_SD_SRS11_SRCD (1U << 25) /* 25: RW - Software Reset for CMD Line */ +#define EMMC_SD_SRS11_SRFA (1U << 24) /* 24: RW - Software Reset for All */ +#define EMMC_SD_SRS11_RESET_DAT_CMD (EMMC_SD_SRS11_SRDA | EMMC_SD_SRS11_SRCD) /* Reset DAT+CMD lines */ +#define EMMC_SD_SRS11_DTCV_SHIFT 16 /* 19:16: RW - Data Timeout Counter Value */ +#define EMMC_SD_SRS11_DTCV_MASK (0xFU << 16) +#define EMMC_SD_SRS11_SDCFSL_SHIFT 8 /* 15:8: RW - SDCLK Freq Select (lower 8 bits) */ +#define EMMC_SD_SRS11_SDCFSL_MASK (0xFFU << 8) +#define EMMC_SD_SRS11_SDCFSH_SHIFT 6 /* 7:6: RW - SDCLK Freq Select (upper 2 bits) */ +#define EMMC_SD_SRS11_SDCFSH_MASK (0x3U << 6) +#define EMMC_SD_SRS11_SDCFS_MASK (0xFF00U | 0x00C0U) /* Full SDCLK Freq Select mask */ +#define EMMC_SD_SRS11_CGS (1U << 5) /* 5: RW - Clock Generator Select */ +#define EMMC_SD_SRS11_SDCE (1U << 2) /* 2: RW - SD Clock Enable */ +#define EMMC_SD_SRS11_ICS (1U << 1) /* 1: RO - Internal Clock Stable */ +#define EMMC_SD_SRS11_ICE (1U << 0) /* 0: RW - Internal Clock Enable */ + +/* SRS12 - Error/Normal Interrupt Status Register */ +#define EMMC_SD_SRS12 *((volatile uint32_t*)(EMMC_SD_BASE + 0x230)) +#define EMMC_SD_SRS12_ERSP (1U << 27) /* 27: RO - Response Error */ +#define EMMC_SD_SRS12_ETUNE (1U << 26) /* 26: RO - Tuning Error */ +#define EMMC_SD_SRS12_EADMA (1U << 25) /* 25: RO - ADMA Error */ +#define EMMC_SD_SRS12_EAC (1U << 24) /* 24: RO - Auto CMD Error */ +#define EMMC_SD_SRS12_ECL (1U << 23) /* 23: RO - Current Limit Error */ +#define EMMC_SD_SRS12_EDEB (1U << 22) /* 22: RO - Data End Bit Error */ +#define EMMC_SD_SRS12_EDCRC (1U << 21) /* 21: RO - Data CRC Error */ +#define EMMC_SD_SRS12_EDT (1U << 20) /* 20: RO - Data Timeout Error */ +#define EMMC_SD_SRS12_ECI (1U << 19) /* 19: RO - Command Index Error */ +#define EMMC_SD_SRS12_ECEB (1U << 18) /* 18: RO - Command End Bit Error */ +#define EMMC_SD_SRS12_ECCRC (1U << 17) /* 17: RO - Command CRC Error */ +#define EMMC_SD_SRS12_ECT (1U << 16) /* 16: RO - Command Timeout Error */ +#define EMMC_SD_SRS12_EINT (1U << 15) /* 15: RO - Error Interrupt */ +#define EMMC_SD_SRS12_CQI (1U << 14) /* 14: RO - Command Queuing Interrupt */ +#define EMMC_SD_SRS12_CINT (1U << 8) /* 8: RO - Card Interrupt */ +#define EMMC_SD_SRS12_CR (1U << 7) /* 7: RW - Card Removal */ +#define EMMC_SD_SRS12_CIN (1U << 6) /* 6: RW - Card Insertion */ +#define EMMC_SD_SRS12_BRR (1U << 5) /* 5: RO - Buffer Read Ready */ +#define EMMC_SD_SRS12_BWR (1U << 4) /* 4: RO - Buffer Write Ready */ +#define EMMC_SD_SRS12_DMAINT (1U << 3) /* 3: RW - DMA Interrupt */ +#define EMMC_SD_SRS12_BGE (1U << 2) /* 2: RW - Block Gap Event */ +#define EMMC_SD_SRS12_TC (1U << 1) /* 1: RW - Transfer Complete */ +#define EMMC_SD_SRS12_CC (1U << 0) /* 0: RW - Command Complete */ +/* Interrupt status masks */ +#define EMMC_SD_SRS12_NORM_STAT 0x00007FFFU /* Normal interrupt status mask */ +#define EMMC_SD_SRS12_ERR_STAT 0xFFFF8000U /* Error interrupt status mask */ +#define EMMC_SD_SRS12_CMD_ERR (EMMC_SD_SRS12_ECT | EMMC_SD_SRS12_ECCRC | \ + EMMC_SD_SRS12_ECEB | EMMC_SD_SRS12_ECI) + +#define EMMC_SD_SRS13 *((volatile uint32_t*)(EMMC_SD_BASE + 0x234)) /* Error/Normal Status Enable */ +#define EMMC_SD_SRS13_ERSP_SE (1U << 27) /* 27: RW - Response Error Status Enable (SD mode only) */ +#define EMMC_SD_SRS13_EADMA_SE (1U << 25) /* 25: RW - ADMA Error Status Enable (SD mode only) */ +#define EMMC_SD_SRS13_EAC_SE (1U << 24) /* 24: RW - Auto CMD Error Status Enable (SD mode only) */ +#define EMMC_SD_SRS13_ECL_SE (1U << 23) /* 23: RW - Current Limit Error Status Enable (SD mode only) */ +#define EMMC_SD_SRS13_EDEB_SE (1U << 22) /* 22: RW - Data End Bit Error Status Enable (SD mode only) */ +#define EMMC_SD_SRS13_EDCRC_SE (1U << 21) /* 21: RW - Data CRC Error Status Enable (SD mode only) */ +#define EMMC_SD_SRS13_EDT_SE (1U << 20) /* 20: RW - Data Timeout Error Status Enable (SD mode only) */ +#define EMMC_SD_SRS13_ECI_SE (1U << 19) /* 19: RW - Command Index Error Status Enable (SD mode only) */ +#define EMMC_SD_SRS13_ECEB_SE (1U << 18) /* 18: RW - Command End Bit Error Status Enable (SD mode only) */ +#define EMMC_SD_SRS13_ECCRC_SE (1U << 17) /* 17: RW - Command CRC Error Status Enable (SD mode only) */ +#define EMMC_SD_SRS13_ECT_SE (1U << 16) /* 16: RW - Command Timeout Error Status Enable (SD mode only) */ +#define EMMC_SD_SRS13_CQINT_SE (1U << 14) /* 14: RW - Command Queuing Status Enable */ +#define EMMC_SD_SRS13_CINT_SE (1U << 8) /* 8: RW - Card Interrupt Status Enable */ +#define EMMC_SD_SRS13_CR_SE (1U << 7) /* 7: RW - Card Removal Status Enable */ +#define EMMC_SD_SRS13_CIN_SE (1U << 6) /* 6: RW - Card Insertion Status Enable */ +#define EMMC_SD_SRS13_BRR_SE (1U << 5) /* 5: RW - Buffer Read Ready Status Enable */ +#define EMMC_SD_SRS13_BWR_SE (1U << 4) /* 4: RW - Buffer Write Ready Status Enable */ +#define EMMC_SD_SRS13_DMAINT_SE (1U << 3) /* 3: RW - DMA Interrupt Status Enable */ +#define EMMC_SD_SRS13_BGE_SE (1U << 2) /* 2: RW - Block Gap Event Status Enable */ +#define EMMC_SD_SRS13_TC_SE (1U << 1) /* 1: RW - Transfer Complete Status Enable */ +#define EMMC_SD_SRS13_CC_SE (1U << 0) /* 0: RW - Command Complete Status Enable */ + +#define EMMC_SD_SRS14 *((volatile uint32_t*)(EMMC_SD_BASE + 0x238)) /* Error/Normal Signal Enable */ +#define EMMC_SD_SRS14_ERSP_IE (1U << 27) /* 27: RW - Response Error Interrupt Enable (SD mode only) */ +#define EMMC_SD_SRS14_EADMA_IE (1U << 25) /* 25: RW - ADMA Error Interrupt Enable (SD mode only) */ +#define EMMC_SD_SRS14_EAC_IE (1U << 24) /* 24: RW - Auto CMD Error Interrupt Enable (SD mode only) */ +#define EMMC_SD_SRS14_ECL_IE (1U << 23) /* 23: RW - Current Limit Error Interrupt Enable (SD mode only) */ +#define EMMC_SD_SRS14_EDEB_IE (1U << 22) /* 22: RW - Data End Bit Error Interrupt Enable (SD mode only) */ +#define EMMC_SD_SRS14_EDCRC_IE (1U << 21) /* 21: RW - Data CRC Error Interrupt Enable (SD mode only) */ +#define EMMC_SD_SRS14_EDT_IE (1U << 20) /* 20: RW - Data Timeout Error Interrupt Enable (SD mode only) */ +#define EMMC_SD_SRS14_ECI_IE (1U << 19) /* 19: RW - Command Index Error Interrupt Enable (SD mode only) */ +#define EMMC_SD_SRS14_ECEB_IE (1U << 18) /* 18: RW - Command End Bit Error Interrupt Enable (SD mode only) */ +#define EMMC_SD_SRS14_ECCRC_IE (1U << 17) /* 17: RW - Command CRC Error Interrupt Enable (SD mode only) */ +#define EMMC_SD_SRS14_ECT_IE (1U << 16) /* 16: RW - Command Timeout Error Interrupt Enable (SD mode only) */ +#define EMMC_SD_SRS14_CQINT_IE (1U << 14) /* 14: RW - Command Queuing Interrupt Enable */ +#define EMMC_SD_SRS14_CINT_IE (1U << 8) /* 8: RW - Card Interrupt Interrupt Enable */ +#define EMMC_SD_SRS14_CR_IE (1U << 7) /* 7: RW - Card Removal Interrupt Enable */ +#define EMMC_SD_SRS14_CIN_IE (1U << 6) /* 6: RW - Card Insertion Interrupt Enable */ +#define EMMC_SD_SRS14_BRR_IE (1U << 5) /* 5: RW - Buffer Read Ready Interrupt Enable */ +#define EMMC_SD_SRS14_BWR_IE (1U << 4) /* 4: RW - Buffer Write Ready Interrupt Enable */ +#define EMMC_SD_SRS14_DMAINT_IE (1U << 3) /* 3: RW - DMA Interrupt Interrupt Enable */ +#define EMMC_SD_SRS14_BGE_IE (1U << 2) /* 2: RW - Block Gap Event Interrupt Enable */ +#define EMMC_SD_SRS14_TC_IE (1U << 1) /* 1: RW - Transfer Complete Interrupt Enable */ +#define EMMC_SD_SRS14_CC_IE (1U << 0) /* 0: RW - Command Complete Interrupt Enable */ + +/* SRS15 - Host Control #2 / Auto CMD Error Status Register */ +#define EMMC_SD_SRS15 *((volatile uint32_t*)(EMMC_SD_BASE + 0x23C)) +#define EMMC_SD_SRS15_PVE (1U << 31) /* 31: RW - Preset Value Enable */ +#define EMMC_SD_SRS15_AIE (1U << 30) /* 30: RW - Async Interrupt Enable */ +#define EMMC_SD_SRS15_A64 (1U << 29) /* 29: RW - 64-bit Addressing */ +#define EMMC_SD_SRS15_HV4E (1U << 28) /* 28: RW - Host Version 4 Enable */ +#define EMMC_SD_SRS15_UHSII (1U << 24) /* 24: RW - UHS-II Interface Enable */ +#define EMMC_SD_SRS15_SCS (1U << 23) /* 23: RW - Sampling Clock Select */ +#define EMMC_SD_SRS15_EXTNG (1U << 22) /* 22: RW - Execute Tuning */ +#define EMMC_SD_SRS15_DSS_SHIFT 20 /* 21:20: RW - Driver Strength Select */ +#define EMMC_SD_SRS15_DSS_MASK (0x3U << 20) +#define EMMC_SD_SRS15_DSS_TYPE_B (0x0U << 20) /* Driver Type B (default) */ +#define EMMC_SD_SRS15_DSS_TYPE_A (0x1U << 20) /* Driver Type A */ +#define EMMC_SD_SRS15_DSS_TYPE_C (0x2U << 20) /* Driver Type C */ +#define EMMC_SD_SRS15_DSS_TYPE_D (0x3U << 20) /* Driver Type D */ +#define EMMC_SD_SRS15_V18SE (1U << 19) /* 19: RW - 1.8V Signaling Enable */ +#define EMMC_SD_SRS15_UMS_SHIFT 16 /* 18:16: RW - UHS Mode Select */ +#define EMMC_SD_SRS15_UMS_MASK (0x7U << 16) +#define EMMC_SD_SRS15_UMS_SDR12 (0x0U << 16) /* SDR12 mode */ +#define EMMC_SD_SRS15_UMS_SDR25 (0x1U << 16) /* SDR25 mode (High Speed) */ +#define EMMC_SD_SRS15_UMS_SDR50 (0x2U << 16) /* SDR50 mode */ +#define EMMC_SD_SRS15_UMS_SDR104 (0x3U << 16) /* SDR104 mode */ +#define EMMC_SD_SRS15_UMS_DDR50 (0x4U << 16) /* DDR50 mode */ +#define EMMC_SD_SRS15_UMS_UHSII (0x7U << 16) /* UHS-II mode */ +/* Auto CMD Error Status bits (lower byte) */ +#define EMMC_SD_SRS15_CNIACE (1U << 7) /* 7: RO - CMD Not Issued by Auto CMD12 */ +#define EMMC_SD_SRS15_ACIE (1U << 4) /* 4: RO - Auto CMD12 Index Error */ +#define EMMC_SD_SRS15_ACEBE (1U << 3) /* 3: RO - Auto CMD12 End Bit Error */ +#define EMMC_SD_SRS15_ACCE (1U << 2) /* 2: RO - Auto CMD12 CRC Error */ +#define EMMC_SD_SRS15_ACTE (1U << 1) /* 1: RO - Auto CMD12 Timeout Error */ +#define EMMC_SD_SRS15_ACNE (1U << 0) /* 0: RO - Auto CMD12 Not Executed */ + +/* SRS16 - Capabilities Register #1 */ +#define EMMC_SD_SRS16 *((volatile uint32_t*)(EMMC_SD_BASE + 0x240)) +#define EMMC_SD_SRS16_SLT_SHIFT 30 /* 31:30: RO - Slot Type */ +#define EMMC_SD_SRS16_SLT_MASK (0x3U << 30) +#define EMMC_SD_SRS16_AIS (1U << 29) /* 29: RO - Async Interrupt Support */ +#define EMMC_SD_SRS16_A64S (1U << 28) /* 28: RO - 64-bit System Bus Support */ +#define EMMC_SD_SRS16_VS18 (1U << 26) /* 26: RO - Voltage Support 1.8V */ +#define EMMC_SD_SRS16_VS30 (1U << 25) /* 25: RO - Voltage Support 3.0V */ +#define EMMC_SD_SRS16_VS33 (1U << 24) /* 24: RO - Voltage Support 3.3V */ +#define EMMC_SD_SRS16_SRS (1U << 23) /* 23: RO - Suspend/Resume Support */ +#define EMMC_SD_SRS16_DMAS (1U << 22) /* 22: RO - SDMA Support */ +#define EMMC_SD_SRS16_HSS (1U << 21) /* 21: RO - High Speed Support */ +#define EMMC_SD_SRS16_ADMA1S (1U << 20) /* 20: RO - ADMA1 Support */ +#define EMMC_SD_SRS16_ADMA2S (1U << 19) /* 19: RO - ADMA2 Support */ +#define EMMC_SD_SRS16_EDS8 (1U << 18) /* 18: RO - 8-bit Data Support */ +#define EMMC_SD_SRS16_MBL_SHIFT 16 /* 17:16: RO - Max Block Length */ +#define EMMC_SD_SRS16_MBL_MASK (0x3U << 16) +#define EMMC_SD_SRS16_MBL_512 (0x0U << 16) /* Max 512 bytes */ +#define EMMC_SD_SRS16_MBL_1024 (0x1U << 16) /* Max 1024 bytes */ +#define EMMC_SD_SRS16_MBL_2048 (0x2U << 16) /* Max 2048 bytes */ +#define EMMC_SD_SRS16_BCSDCLK_SHIFT 8 /* 15:8: RO - Base Clock for SD Clock (in MHz) */ +#define EMMC_SD_SRS16_BCSDCLK_MASK (0xFFU << 8) +#define EMMC_SD_SRS16_TCU (1U << 7) /* 7: RO - Timeout Clock Unit (1=MHz) */ +#define EMMC_SD_SRS16_TCF_SHIFT 0 /* 5:0: RO - Timeout Clock Frequency */ +#define EMMC_SD_SRS16_TCF_MASK (0x3FU << 0) + +/* SRS17 - Capabilities Register #2 */ +#define EMMC_SD_SRS17 *((volatile uint32_t*)(EMMC_SD_BASE + 0x244)) +#define EMMC_SD_SRS17_VDD2S (1U << 28) /* 28: RO - VDD2 Support */ +#define EMMC_SD_SRS17_CLKMPR_SHIFT 16 /* 23:16: RO - Clock Multiplier */ +#define EMMC_SD_SRS17_CLKMPR_MASK (0xFFU << 16) +#define EMMC_SD_SRS17_RTNGM_SHIFT 14 /* 15:14: RO - Re-Tuning Modes */ +#define EMMC_SD_SRS17_RTNGM_MASK (0x3U << 14) +#define EMMC_SD_SRS17_RTNGM_MODE1 (0x0U << 14) /* Re-tuning mode 1 */ +#define EMMC_SD_SRS17_RTNGM_MODE2 (0x1U << 14) /* Re-tuning mode 2 */ +#define EMMC_SD_SRS17_RTNGM_MODE3 (0x2U << 14) /* Re-tuning mode 3 */ +#define EMMC_SD_SRS17_TSDR50 (1U << 13) /* 13: RO - Tuning for SDR50 */ +#define EMMC_SD_SRS17_TCRT_SHIFT 8 /* 11:8: RO - Timer Count for Re-Tuning */ +#define EMMC_SD_SRS17_TCRT_MASK (0xFU << 8) +#define EMMC_SD_SRS17_UHSII (1U << 8) /* 8: RO - UHS-II Support */ +#define EMMC_SD_SRS17_DRVD (1U << 6) /* 6: RO - Driver Type D Support */ +#define EMMC_SD_SRS17_DRVC (1U << 5) /* 5: RO - Driver Type C Support */ +#define EMMC_SD_SRS17_DRVA (1U << 4) /* 4: RO - Driver Type A Support */ +#define EMMC_SD_SRS17_DDR50 (1U << 2) /* 2: RO - DDR50 Support */ +#define EMMC_SD_SRS17_SDR104 (1U << 1) /* 1: RO - SDR104 Support */ +#define EMMC_SD_SRS17_SDR50 (1U << 0) /* 0: RO - SDR50 Support */ + +#define EMMC_SD_SRS18 *((volatile uint32_t*)(EMMC_SD_BASE + 0x248)) /* Capabilities #3 */ +#define EMMC_SD_SRS18_MC18_SHIFT 16 /* 23:16: RO - Maximym current for 1.8v */ +#define EMMC_SD_SRS18_MC18_MASK (0xFFU << 16) +#define EMMC_SD_SRS18_MC30_SHIFT 8 /* 15:8: RO - Maximym current for 3.0v */ +#define EMMC_SD_SRS18_MC30_MASK (0xFFU << 8) +#define EMMC_SD_SRS18_MC33_SHIFT 0 /* 7:0: RO - Maximym current for 3.3v */ +#define EMMC_SD_SRS18_MC33_MASK (0xFFU << 0) + +#define EMMC_SD_SRS19 *((volatile uint32_t*)(EMMC_SD_BASE + 0x24C)) /* Capabilities #4 */ +#define EMMC_SD_SRS19_MC18V2_SHIFT 0 /* 7:0: RO */ +#define EMMC_SD_SRS19_MC18V2_MASK (0xFFU << 0) + +#define EMMC_SD_SRS20 *((volatile uint32_t*)(EMMC_SD_BASE + 0x250)) /* Force Event */ +#define EMMC_SD_SRS20_ERESP_FE (1U << 27) /* 27: WO - Force Response Error */ +#define EMMC_SD_SRS20_ETUNE_FE (1U << 26) /* 26: WO - Force Tuning Error */ +#define EMMC_SD_SRS20_EADMA_FE (1U << 25) /* 25: WO - Force ADMA Error */ +#define EMMC_SD_SRS20_EAC_FE (1U << 24) /* 24: WO - Force Auto CMD Error */ +#define EMMC_SD_SRS20_ECL_FE (1U << 23) /* 23: WO - Force Current Limit Error */ +#define EMMC_SD_SRS20_EDEB_FE (1U << 22) /* 22: WO - Force Data End Bit Error */ +#define EMMC_SD_SRS20_EDCRC_FE (1U << 21) /* 21: WO - Force Data CRC Error */ +#define EMMC_SD_SRS20_EDT_FE (1U << 20) /* 20: WO - Force Data Timeout Error */ +#define EMMC_SD_SRS20_ECI_FE (1U << 19) /* 19: WO - Force Command Index Error */ +#define EMMC_SD_SRS20_ECEB_FE (1U << 18) /* 18: WO - Force Command End Bit Error */ +#define EMMC_SD_SRS20_ECCRC_FE (1U << 17) /* 17: WO - Force Command CRC Error */ +#define EMMC_SD_SRS20_ECT_FE (1U << 16) /* 16: WO - Force Command Timeout Error */ + +#define EMMC_SD_SRS21 *((volatile uint32_t*)(EMMC_SD_BASE + 0x254)) /* ADMA Error Status */ +#define EMMC_SD_SRS21_EADMAL (1U << 2) /* 2: RO - ADMA Length Mismatch Error */ +#define EMMC_SD_SRS21_EADMAS_SHIFT 0 /* 1:0: RO */ +#define EMMC_SD_SRS21_EADMAS_MASK (0x3U << 0) + +#define EMMC_SD_SRS22 *((volatile uint32_t*)(EMMC_SD_BASE + 0x258)) /* ADMA System Address 1 */ +#define EMMC_SD_SRS22_DMASA1_SHIFT 0 /* 31:0: RW */ +#define EMMC_SD_SRS22_DMASA1_MASK (0xFFFFFFFFU << 0) + +#define EMMC_SD_SRS23 *((volatile uint32_t*)(EMMC_SD_BASE + 0x25C)) /* ADMA System Address 2 */ +#define EMMC_SD_SRS23_DMASA2_SHIFT 0 /* 31:0: RW */ +#define EMMC_SD_SRS23_DMASA2_MASK (0xFFFFFFFFU << 0) + +#define EMMC_SD_SRS24 *((volatile uint32_t*)(EMMC_SD_BASE + 0x260)) /* Preset Value (Default Speed) */ +#define EMMC_SD_SRS25 *((volatile uint32_t*)(EMMC_SD_BASE + 0x264)) /* Preset Value (High Speed/SDR12) */ +#define EMMC_SD_SRS26 *((volatile uint32_t*)(EMMC_SD_BASE + 0x268)) /* Preset Value (SDR25/SDR50) */ +#define EMMC_SD_SRS27 *((volatile uint32_t*)(EMMC_SD_BASE + 0x26C)) /* Preset Value (SDR104/DDR50) */ +#define EMMC_SD_SRS29 *((volatile uint32_t*)(EMMC_SD_BASE + 0x274)) /* Preset Value for UHS-II */ + +/* ---------------------------------------------------------------------------- + * CQRS - Command Queuing Register Set (eMMC 5.1 Command Queuing) + * ---------------------------------------------------------------------------- */ + +/* CQRS00 - Command Queuing Version Register */ +#define EMMC_SD_CQRS00 *((volatile uint32_t*)(EMMC_SD_BASE + 0x400)) +#define EMMC_SD_CQRS00_CQVN1_SHIFT 8 /* 11:8: RO - CQ Version (major) */ +#define EMMC_SD_CQRS00_CQVN1_MASK (0xFU << 8) +#define EMMC_SD_CQRS00_CQVN2_SHIFT 4 /* 7:4: RO - CQ Version (minor) */ +#define EMMC_SD_CQRS00_CQVN2_MASK (0xFU << 4) +#define EMMC_SD_CQRS00_CQVN3_SHIFT 0 /* 3:0: RO - CQ Version (suffix) */ +#define EMMC_SD_CQRS00_CQVN3_MASK (0xFU << 0) + +/* CQRS01 - Command Queuing Capabilities Register */ +#define EMMC_SD_CQRS01 *((volatile uint32_t*)(EMMC_SD_BASE + 0x404)) +#define EMMC_SD_CQRS01_ITCFMUL_SHIFT 12 /* 15:12: RO - Internal Timer Clock Freq Multiplier */ +#define EMMC_SD_CQRS01_ITCFMUL_MASK (0xFU << 12) +#define EMMC_SD_CQRS01_ITCFVAL_SHIFT 0 /* 9:0: RO - Internal Timer Clock Freq Value */ +#define EMMC_SD_CQRS01_ITCFVAL_MASK (0x3FFU << 0) + +/* CQRS02 - Command Queuing Configuration Register */ +#define EMMC_SD_CQRS02 *((volatile uint32_t*)(EMMC_SD_BASE + 0x408)) +#define EMMC_SD_CQRS02_CQDCE (1U << 12) /* 12: RW - Direct Command (DCMD) Enable */ +#define EMMC_SD_CQRS02_CQTDS (1U << 8) /* 8: RW - Task Desc Size (0=64bit, 1=128bit) */ +#define EMMC_SD_CQRS02_CQTDS_64 (0x0U << 8) /* Task descriptor 64 bits */ +#define EMMC_SD_CQRS02_CQTDS_128 (0x1U << 8) /* Task descriptor 128 bits */ +#define EMMC_SD_CQRS02_CQE (1U << 0) /* 0: RW - Command Queuing Enable */ + +/* CQRS03 - Command Queuing Control Register */ +#define EMMC_SD_CQRS03 *((volatile uint32_t*)(EMMC_SD_BASE + 0x40C)) +#define EMMC_SD_CQRS03_CQHLT (1U << 0) /* 0: RW - Halt CQ Engine */ + +/* CQRS04 - Command Queuing Interrupt Status Register */ +#define EMMC_SD_CQRS04 *((volatile uint32_t*)(EMMC_SD_BASE + 0x410)) +#define EMMC_SD_CQRS04_CQTCL (1U << 3) /* 3: RW - Task Cleared Interrupt */ +#define EMMC_SD_CQRS04_CQRED (1U << 2) /* 2: RW - Response Error Detected */ +#define EMMC_SD_CQRS04_CQTCC (1U << 1) /* 1: RW - Task Complete Interrupt */ +#define EMMC_SD_CQRS04_CQHAC (1U << 0) /* 0: RW - Halt Complete Interrupt */ + +/* CQRS05 - Command Queuing Interrupt Status Enable Register */ +#define EMMC_SD_CQRS05 *((volatile uint32_t*)(EMMC_SD_BASE + 0x414)) +#define EMMC_SD_CQRS05_CQTCLST (1U << 3) /* 3: RW - Task Cleared Status Enable */ +#define EMMC_SD_CQRS05_CQREDST (1U << 2) /* 2: RW - Response Error Status Enable */ +#define EMMC_SD_CQRS05_CQTCCST (1U << 1) /* 1: RW - Task Complete Status Enable */ +#define EMMC_SD_CQRS05_CQHACST (1U << 0) /* 0: RW - Halt Complete Status Enable */ + +/* CQRS06 - Command Queuing Interrupt Signal Enable Register */ +#define EMMC_SD_CQRS06 *((volatile uint32_t*)(EMMC_SD_BASE + 0x418)) +#define EMMC_SD_CQRS06_CQTCLSI (1U << 3) /* 3: RW - Task Cleared Signal Enable */ +#define EMMC_SD_CQRS06_CQREDSI (1U << 2) /* 2: RW - Response Error Signal Enable */ +#define EMMC_SD_CQRS06_CQTCCSI (1U << 1) /* 1: RW - Task Complete Signal Enable */ +#define EMMC_SD_CQRS06_CQHACSI (1U << 0) /* 0: RW - Halt Complete Signal Enable */ + +/* CQRS07 - Interrupt Coalescing Register */ +#define EMMC_SD_CQRS07 *((volatile uint32_t*)(EMMC_SD_BASE + 0x41C)) +#define EMMC_SD_CQRS07_CQICED (1U << 31) /* 31: RW - Int Coalescing Enable/Disable */ +#define EMMC_SD_CQRS07_CQICSB (1U << 20) /* 20: RO - Int Coalescing Status Bit */ +#define EMMC_SD_CQRS07_CQICCTR (1U << 16) /* 16: WO - Counter and Timer Reset */ +#define EMMC_SD_CQRS07_CQICCTHWEN (1U << 15) /* 15: WO - Counter Threshold Write Enable */ +#define EMMC_SD_CQRS07_CQICCTH_SHIFT 8 /* 12:8: RW - Int Coalescing Counter Threshold */ +#define EMMC_SD_CQRS07_CQICCTH_MASK (0x1FU << 8) +#define EMMC_SD_CQRS07_CQICTOVALEN (1U << 7) /* 7: WO - Timeout Value Write Enable */ +#define EMMC_SD_CQRS07_CQICTOVAL_SHIFT 0 /* 6:0: RW - Int Coalescing Timeout Value */ +#define EMMC_SD_CQRS07_CQICTOVAL_MASK (0x7FU << 0) + +#define EMMC_SD_CQRS08 *((volatile uint32_t*)(EMMC_SD_BASE + 0x420)) /* Task Descriptor List Base Address */ +#define EMMC_SD_CQRS08_CQTDLBA_SHIFT 0 /* 31:0: RW */ +#define EMMC_SD_CQRS08_CQTDLBA_MASK (0xFFFFFFFFU << 0) + +#define EMMC_SD_CQRS09 *((volatile uint32_t*)(EMMC_SD_BASE + 0x424)) /* Task Descriptor List Base Address Upper */ +#define EMMC_SD_CQRS09_CQTDLBAU_SHIFT 0 /* 31:0: RW */ +#define EMMC_SD_CQRS09_CQTDLBAU_MASK (0xFFFFFFFFU << 0) + +#define EMMC_SD_CQRS10 *((volatile uint32_t*)(EMMC_SD_BASE + 0x428)) /* Command Queuing Task Doorbell */ +#define EMMC_SD_CQRS11 *((volatile uint32_t*)(EMMC_SD_BASE + 0x42C)) /* Task Complete Notification */ +#define EMMC_SD_CQRS12 *((volatile uint32_t*)(EMMC_SD_BASE + 0x430)) /* Device Queue Status */ +#define EMMC_SD_CQRS12_CQDQS_SHIFT 0 /* 31:0: RO */ +#define EMMC_SD_CQRS12_CQDQS_MASK (0xFFFFFFFFU << 0) + +#define EMMC_SD_CQRS13 *((volatile uint32_t*)(EMMC_SD_BASE + 0x434)) /* Device Pending Tasks */ +#define EMMC_SD_CQRS14 *((volatile uint32_t*)(EMMC_SD_BASE + 0x438)) /* Task Clear */ + +#define EMMC_SD_CQRS16 *((volatile uint32_t*)(EMMC_SD_BASE + 0x440)) /* Send Status Configuration 1 */ +#define EMMC_SD_CQRS16_CQSSCBC_SHIFT 16 /* 19:16: RW */ +#define EMMC_SD_CQRS16_CQSSCBC_MASK (0xFU << 16) +#define EMMC_SD_CQRS16_CQSSCIT_SHIFT 0 /* 15:0: RW */ +#define EMMC_SD_CQRS16_CQSSCIT_MASK (0xFFFFU << 0) + +#define EMMC_SD_CQRS17 *((volatile uint32_t*)(EMMC_SD_BASE + 0x444)) /* Send Status Configuration 2 */ +#define EMMC_SD_CQRS17_CQSQSR_SHIFT 0 /* 15:0: RW */ +#define EMMC_SD_CQRS17_CQSQSR_MASK (0xFFFFU << 0) + +#define EMMC_SD_CQRS18 *((volatile uint32_t*)(EMMC_SD_BASE + 0x448)) /* Command Response for Direct-Command */ +#define EMMC_SD_CQRS18_CQDCLR_SHIFT 0 /* 31:0: RO */ +#define EMMC_SD_CQRS18_CQDCLR_MASK (0xFFFFFFFFU << 0) + +#define EMMC_SD_CQRS20 *((volatile uint32_t*)(EMMC_SD_BASE + 0x450)) /* Response Mode Error Mask */ +#define EMMC_SD_CQRS20_CQRMEM_SHIFT 0 /* 31:0: RW */ +#define EMMC_SD_CQRS20_CQRMEM_MASK (0xFFFFFFFFU << 0) + +#define EMMC_SD_CQRS21 *((volatile uint32_t*)(EMMC_SD_BASE + 0x454)) /* Task Error Information */ +#define EMMC_SD_CQRS21_CQDTEFV (1U << 31) /* 31: RO */ +#define EMMC_SD_CQRS21_CQDTETID_SHIFT 24 /* 28:24: RO */ +#define EMMC_SD_CQRS21_CQDTETID_MASK (0x1FU << 24) +#define EMMC_SD_CQRS21_CQDTECI_SHIFT 16 /* 21:16: RO */ +#define EMMC_SD_CQRS21_CQDTECI_MASK (0x3FU << 16) +#define EMMC_SD_CQRS21_CQRMEFV (1U << 15) /* 15: RO */ +#define EMMC_SD_CQRS21_CQRMETID_SHIFT 8 /* 12:8: RO */ +#define EMMC_SD_CQRS21_CQRMETID_MASK (0x1FU << 8) +#define EMMC_SD_CQRS21_CQRMECI_SHIFT 0 /* 5:0: RO */ +#define EMMC_SD_CQRS21_CQRMECI_MASK (0x3FU << 0) + +#define EMMC_SD_CQRS22 *((volatile uint32_t*)(EMMC_SD_BASE + 0x458)) /* Command Response Index */ +#define EMMC_SD_CQRS22_CQLCRI_SHIFT 0 /* 5:0: RO */ +#define EMMC_SD_CQRS22_CQLCRI_MASK (0x3FU << 0) + +#define EMMC_SD_CQRS23 *((volatile uint32_t*)(EMMC_SD_BASE + 0x45C)) /* Command Response Argument */ +#define EMMC_SD_CQRS23_CQLCRA_SHIFT 0 /* 31:0: RO */ +#define EMMC_SD_CQRS23_CQLCRA_MASK (0xFFFFFFFFU << 0) + +/* ---------------------------------------------------------------------------- + * EMMC/SD - Common Constants and Helper Macros + * ---------------------------------------------------------------------------- */ + +/* Clock Frequencies (in KHz) */ +#define EMMC_SD_CLK_400KHZ 400U /* Initial identification clock */ +#define EMMC_SD_CLK_25MHZ 25000U /* Default Speed / SDR12 */ +#define EMMC_SD_CLK_50MHZ 50000U /* High Speed / SDR25 */ +#define EMMC_SD_CLK_100MHZ 100000U /* SDR50 */ +#define EMMC_SD_CLK_200MHZ 200000U /* SDR104 / HS200 / HS400 */ + +/* Block Size */ +#define EMMC_SD_BLOCK_SIZE 512U /* Standard block size */ + +/* SD Interface Conditions */ +#define IF_COND_27V_33V (1u << 8u) + +/* SD OCR register bits definitions */ +#define SDCARD_REG_OCR_2_7_2_8 (1U << 15) +#define SDCARD_REG_OCR_2_8_2_9 (1U << 16) +#define SDCARD_REG_OCR_2_9_3_0 (1U << 17) +#define SDCARD_REG_OCR_3_0_3_1 (1U << 18) +#define SDCARD_REG_OCR_3_1_3_2 (1U << 19) +#define SDCARD_REG_OCR_3_2_3_3 (1U << 20) +#define SDCARD_REG_OCR_3_3_3_4 (1U << 21) +#define SDCARD_REG_OCR_3_4_3_5 (1U << 22) +#define SDCARD_REG_OCR_3_5_3_6 (1U << 23) +#define SDCARD_REG_OCR_S18RA (1U << 24) /* Switching to 1.8V request/accept bit */ +#define SDCARD_REG_OCR_XPC (1U << 28) /* eXtended Power Control (XPC) bit */ +#define SDCARD_REG_OCR_CCS (1U << 30) /* Card Capacity Status bit */ +#define SDCARD_REG_OCR_READY (1U << 31) /* OCR ready bit */ + +#define SDCARD_ACMD41_HCS (1U << 30) /* High Capacity Support bit */ + +/* Common MMC/SD Commands (for use with SRS03) */ +#define MMC_CMD0_GO_IDLE 0 /* Reset card to idle state */ +#define MMC_CMD1_SEND_OP_COND 1 /* MMC: Send operating conditions */ +#define MMC_CMD2_ALL_SEND_CID 2 /* Get card identification */ +#define MMC_CMD3_SET_REL_ADDR 3 /* MMC: Set relative address */ +#define SD_CMD3_SEND_REL_ADDR 3 /* SD: Get relative address */ +#define MMC_CMD_4_SET_DSR 4 +#define MMC_CMD6_SWITCH 6 /* Switch/set EXT_CSD */ +#define MMC_CMD7_SELECT_CARD 7 /* Select/deselect card */ +#define MMC_CMD8_SEND_EXT_CSD 8 /* MMC: Get EXT_CSD */ +#define SD_CMD8_SEND_IF_COND 8 /* SD: Send interface condition */ +#define MMC_CMD9_SEND_CSD 9 /* Get card-specific data */ +#define MMC_CMD12_STOP_TRANS 12 /* Stop transmission */ +#define MMC_CMD13_SEND_STATUS 13 /* Get card status */ +#define MMC_CMD_15_GOTO_INACT_ST 15 +#define MMC_CMD17_READ_SINGLE 17 /* Read single block */ +#define MMC_CMD18_READ_MULTIPLE 18 /* Read multiple blocks */ +#define MMC_CMD24_WRITE_SINGLE 24 /* Write single block */ +#define MMC_CMD25_WRITE_MULTIPLE 25 /* Write multiple blocks */ +#define SD_CMD55_APP_CMD 55 /* Prefix for ACMD */ +#define SD_ACMD41_SD_SEND_OP 41 /* SD: Send operating conditions */ +#define SD_ACMD51_SEND_SCR 51 /* SD: Get SCR register */ + +/* Debouncing time for card detect */ +#define EMMC_SD_DEBOUNCE_TIME 0x300000U + +/* Timeout values */ +#define EMMC_SD_DATA_TIMEOUT_US 500000U /* 500ms data timeout */ +#define EMMC_SD_CMD_TIMEOUT_MS 3000U /* 3s command timeout */ + +#define WOLFBOOT_CARDTYPE_SD 1 +#define WOLFBOOT_CARDTYPE_EMMC 2 + +#define WOLFBOOT_CARDTYPE WOLFBOOT_CARDTYPE_SD + +#define MAX_CURRENT_MA 150 /* mA */ + +#if 0 +EMMC MSSIO_B4 +EMMC_DATA_7_4 MSSIO_B4 +EMMC_SD_CLK_SOURCE MSS_PLL +EMMC_SD_SDIO_FREQ 200 +EMMC_SD_SWITCHING ENABLED_SD +EMMC_SPEED_MODE HIGH_SPEED_200 +#endif + + + +/* Crypto Engine: Athena F5200 TeraFire Crypto Processor (1x), 200 MHz */ +#define ATHENA_BASE (SYSREG_BASE + 0x125000) #endif /* MPFS250_DEF_INCLUDED */ From 7897bd8ec1d019add8bbdafdb4033e20b676d4f4 Mon Sep 17 00:00:00 2001 From: David Garske Date: Mon, 15 Dec 2025 16:10:03 -0800 Subject: [PATCH 03/13] Progress with eMMC/SD driver --- .github/workflows/test-build-riscv.yml | 3 +- docs/Targets.md | 34 ++ hal/mpfs250.c | 419 ++++++++++++++++++++++--- hal/mpfs250.h | 46 ++- src/boot_riscv64.c | 10 +- 5 files changed, 459 insertions(+), 53 deletions(-) diff --git a/.github/workflows/test-build-riscv.yml b/.github/workflows/test-build-riscv.yml index eae92fbf0e..a88ee6bc5e 100644 --- a/.github/workflows/test-build-riscv.yml +++ b/.github/workflows/test-build-riscv.yml @@ -111,7 +111,8 @@ jobs: - name: Build wolfboot (riscv32) if: ${{ inputs.arch == 'riscv' }} run: | - make CROSS_COMPILE=riscv32-unknown-elf- FREEDOM_E_SDK=$GITHUB_WORKSPACE/freedom-e-sdk ${{inputs.make-args}} + # using riscv64 for now since riscv32 is missing "zicsr" extension + make CROSS_COMPILE=riscv64-unknown-elf- FREEDOM_E_SDK=$GITHUB_WORKSPACE/freedom-e-sdk ${{inputs.make-args}} - name: Build wolfboot (riscv64)) if: ${{ inputs.arch == 'riscv64' }} diff --git a/docs/Targets.md b/docs/Targets.md index 3ebfe880da..0ad955f792 100644 --- a/docs/Targets.md +++ b/docs/Targets.md @@ -876,6 +876,40 @@ set architecture riscv:rv64 #thread apply all set $pc=_start ``` +### PolarFire Example Boot Output + +``` +disk_open: drv = 0 +mmc_set_timeout: timeout_us: 500000, tcfclk_khz: -824320848 (mhz: 3470646), timeout_val: 500000, dtcv: 15 +mmc_set_clock: clock_khz: 400, freq_khz: 400 +mmc_send_cmd: cmd_index: 0, cmd_arg: 00000000, resp_type: 0 +mmc_send_cmd: cmd_index: 8, cmd_arg: 00000100, resp_type: 9 +mmc_init: xpc:0, si8r:1, max_ma (3.3v:128 1.8v:128) +mmc_send_cmd: cmd_index: 55, cmd_arg: 00000000, resp_type: 1 +mmc_send_cmd: cmd_index: 41, cmd_arg: 00000000, resp_type: 4 +ocr_reg: 0x40FF8000 +mmc_init: sending OCR arg: 0x41200000 +mmc_send_cmd: cmd_index: 55, cmd_arg: 00000000, resp_type: 1 +mmc_send_cmd: cmd_index: 41, cmd_arg: 41200000, resp_type: 4 +ocr_reg: 0x40FF8000 +mmc_send_cmd: cmd_index: 55, cmd_arg: 00000000, resp_type: 1 +mmc_send_cmd: cmd_index: 41, cmd_arg: 41200000, resp_type: 4 +ocr_reg: 0xC1FF8000 +mmc_send_cmd: cmd_index: 11, cmd_arg: 00000000, resp_type: 1 +mmc_send_cmd: cmd_index: 2, cmd_arg: 00000000, resp_type: 3 +mmc_send_cmd: cmd_index: 3, cmd_arg: 00000000, resp_type: 8 +mmc_init: rca: 43690 +mmc_send_cmd: cmd_index: 9, cmd_arg: AAAA0000, resp_type: 3 +mmc_init: sector size: 512 +mmc_init: sector count: 62333952 +mmc_send_cmd: cmd_index: 7, cmd_arg: AAAA0000, resp_type: 2 +Checking primary OS image in 0,1... +Checking secondary OS image in 0,2... +No valid OS image found in either partition 1 or 2 +wolfBoot: PANIC! +``` + + ### PolarFire TODO 1) Add support for full HSS replacement using wolfboot. diff --git a/hal/mpfs250.c b/hal/mpfs250.c index 84ff5e506c..1805560b10 100644 --- a/hal/mpfs250.c +++ b/hal/mpfs250.c @@ -43,6 +43,8 @@ #include "loader.h" #include "disk.h" +#define DEBUG_MMC + /* Placeholder functions - to be implemented */ void hal_init(void) { @@ -132,6 +134,16 @@ void* hal_get_dts_address(void) } #endif + +static uint32_t g_sector_count; +static uint32_t g_sector_size; +static uint32_t g_bus_width = 1; +static uint32_t g_rca = 0; /* SD Card Relative Address */ + +#ifndef DEFAULT_DELAY +#define DEFAULT_DELAY 0xFFFF +#endif + int mmc_set_timeout(uint32_t timeout_us) { uint32_t reg, i, tcfclk, tcfclk_mhz, tcfclk_khz, timeout_val, dtcv; @@ -170,17 +182,21 @@ int mmc_set_timeout(uint32_t timeout_us) } dtcv *= 2; } + dtcv = i; - /* set the data timeout counter value */ + /* set the data timeout counter value - CHECK: 0xc0207 */ reg = EMMC_SD_SRS11; reg &= ~EMMC_SD_SRS11_DTCV_MASK; - reg |= (timeout_val << EMMC_SD_SRS11_DTCV_SHIFT) & EMMC_SD_SRS11_DTCV_MASK; + reg |= (dtcv << EMMC_SD_SRS11_DTCV_SHIFT) & EMMC_SD_SRS11_DTCV_MASK; EMMC_SD_SRS11 = reg; +#ifdef DEBUG_MMC + wolfBoot_printf("mmc_set_timeout: dtcv 0x%08X, srs11 0x%08X\n", dtcv, reg); +#endif + return 0; } -#define DEFAULT_DELAY 0x00FFFFFF void mmc_delay(uint32_t delay) { while (delay--) { @@ -213,15 +229,16 @@ int mmc_set_power(uint32_t voltage) reg |= EMMC_SD_SRS10_BP | EMMC_SD_SRS10_BVS_1_8V; } else if (voltage == EMMC_SD_SRS10_BVS_3_0V && (cap2 & EMMC_SD_SRS16_VS30)) { - reg |= EMMC_SD_SRS10_BVS_3_0V; + reg |= EMMC_SD_SRS10_BP | EMMC_SD_SRS10_BVS_3_0V; } else if (voltage == EMMC_SD_SRS10_BVS_3_3V && (cap2 & EMMC_SD_SRS16_VS33)) { - reg |= EMMC_SD_SRS10_BVS_3_3V; + reg |= EMMC_SD_SRS10_BP | EMMC_SD_SRS10_BVS_3_3V; } else { /* voltage not supported */ return -1; } + /* should be - 0xf06 */ EMMC_SD_SRS10 = reg; mmc_delay(DEFAULT_DELAY); /* delay after bus power is applied */ } @@ -231,8 +248,14 @@ int mmc_set_power(uint32_t voltage) /* returns actual frequency in kHz */ uint32_t mmc_set_clock(uint32_t clock_khz) { + static uint32_t last_clock_khz = 0; uint32_t reg, base_clk_khz, i, mclk, freq_khz; + if (last_clock_khz != 0 && last_clock_khz == clock_khz) { + /* clock already set */ + return 0; + } + /* disable clock */ EMMC_SD_SRS11 &= ~EMMC_SD_SRS11_SDCE; @@ -243,6 +266,7 @@ uint32_t mmc_set_clock(uint32_t clock_khz) /* error getting base clock */ return 0; } + base_clk_khz *= 1000; /* convert MHz to kHz */ /* select clock frequency */ reg = EMMC_SD_SRS11; @@ -254,18 +278,25 @@ uint32_t mmc_set_clock(uint32_t clock_khz) break; } } - mclk = ((i / 2) << EMMC_SD_SRS11_SDCFSL_SHIFT); - reg |= (mclk & EMMC_SD_SRS11_SDCFSL_MASK) | ((mclk & 0x30000) >> 10); + mclk = (i / 2); + reg |= ((mclk << EMMC_SD_SRS11_SDCFSL_SHIFT) & EMMC_SD_SRS11_SDCFSL_MASK) /* lower 8 bits */ + | ((mclk << EMMC_SD_SRS11_SDCFSH_SHIFT) & EMMC_SD_SRS11_SDCFSH_SHIFT); /* upper 2 bits */ reg |= EMMC_SD_SRS11_ICE; /* clock enable */ reg &= ~EMMC_SD_SRS11_CGS; /* select clock */ EMMC_SD_SRS11 = reg; freq_khz = base_clk_khz / i; /* wait for clock to stabilize */ - while ((EMMC_SD_SRS11 & EMMC_SD_SRS11_ICE) == 0); + while ((EMMC_SD_SRS11 & EMMC_SD_SRS11_ICS) == 0); /* enable clock */ EMMC_SD_SRS11 |= EMMC_SD_SRS11_SDCE; + last_clock_khz = clock_khz; + +#ifdef DEBUG_MMC + wolfBoot_printf("mmc_set_clock: clock_khz: %d, freq_khz: %d\n", + clock_khz, freq_khz); +#endif mmc_delay(DEFAULT_DELAY); /* delay after clock changed */ @@ -316,8 +347,10 @@ static uint32_t mmc_get_response_type(uint8_t resp_type) return cmd_reg; } +#define DEVICE_BUSY 1 int mmc_send_cmd(uint32_t cmd_index, uint32_t cmd_arg, uint8_t resp_type) { + int status = 0; uint32_t cmd_reg; uint32_t cmd_type = EMMC_SD_SRS03_CMD_NORMAL; /* TODO: Add support for suspend and resume */ @@ -338,15 +371,22 @@ int mmc_send_cmd(uint32_t cmd_index, uint32_t cmd_arg, uint8_t resp_type) /* set command argument and command transfer registers */ EMMC_SD_SRS02 = cmd_arg; cmd_reg = - ((cmd_index & EMMC_SD_SRS03_CIDX_MASK) << EMMC_SD_SRS03_CIDX_SHIFT) | - ((cmd_type & EMMC_SD_SRS03_CT_MASK) << EMMC_SD_SRS03_CT_SHIFT) | + ((cmd_index << EMMC_SD_SRS03_CIDX_SHIFT) & EMMC_SD_SRS03_CIDX_MASK) | + ((cmd_type << EMMC_SD_SRS03_CT_SHIFT) & EMMC_SD_SRS03_CT_MASK) | mmc_get_response_type(resp_type); EMMC_SD_SRS03 = cmd_reg; - if (resp_type != EMMC_SD_RESP_NONE) { - /* wait for command complete or error - TODO: Add timeout */ - while ((EMMC_SD_SRS12 & (EMMC_SD_SRS12_CC | EMMC_SD_SRS12_ERR_STAT)) == 0); + /* wait for command complete or error - TODO: Add timeout */ + while ((EMMC_SD_SRS12 & (EMMC_SD_SRS12_CC | EMMC_SD_SRS12_EINT)) == 0); + + /* check for device busy */ + if (resp_type == EMMC_SD_RESP_R1 || resp_type == EMMC_SD_RESP_R1B) { + uint32_t resp = EMMC_SD_SRS04; + #define CARD_STATUS_READY_FOR_DATA (0x1 << 8) + if ((resp & CARD_STATUS_READY_FOR_DATA) == 0) { + status = DEVICE_BUSY; /* card is busy */ + } } /* clear all status interrupts (except current limit, card interrupt/removal/insert) */ @@ -355,11 +395,25 @@ int mmc_send_cmd(uint32_t cmd_index, uint32_t cmd_arg, uint8_t resp_type) EMMC_SD_SRS12_CR | EMMC_SD_SRS12_CIN); - return 0; + return status; +} + +/* TODO: Add timeout */ +int mmc_wait_busy(int check_dat0) +{ + uint32_t status; + if (check_dat0) { + /* wait for DATA0 not busy */ + while ((EMMC_SD_SRS09 & EMMC_SD_SRS09_DAT0_LVL) == 0); + } + /* wait for CMD13 */ + while ((status = mmc_send_cmd(MMC_CMD13_SEND_STATUS, + (g_rca << SD_RCA_SHIFT), EMMC_SD_RESP_R1)) == DEVICE_BUSY); + return status; } /* Set power and send initialization commands */ -/* voltage: 0=off or EMMC_SD_SRS10_BVS_ */ +/* voltage: 0=off or EMMC_SD_SRS10_BVS_[X_X]V */ int mmc_power_init_seq(uint32_t voltage) { /* Set power to specified voltage */ @@ -383,11 +437,169 @@ int mmc_card_init(uint32_t acmd41_arg, uint32_t *ocr_reg) { int status = mmc_send_cmd(SD_CMD55_APP_CMD, 0, EMMC_SD_RESP_R1); if (status == 0) { - status = mmc_send_cmd(SD_ACMD41_SD_SEND_OP, acmd41_arg, + status = mmc_send_cmd(SD_ACMD41_SEND_OP_COND, acmd41_arg, EMMC_SD_RESP_R3); + if (status == 0) { + *ocr_reg = EMMC_SD_SRS04; + #ifdef DEBUG_MMC + wolfBoot_printf("ocr_reg: 0x%08X\n", *ocr_reg); + #endif + } + } + return status; +} + +/* MMC_CMD17_READ_SINGLE */ +int mmc_block_read(uint32_t cmd_index, uint32_t block_addr, uint32_t* dst, + uint32_t sz) +{ + int status; + uint32_t reg; + + /* wait for idle */ + status = mmc_wait_busy(0); + + /* reset data and command lines */ + EMMC_SD_SRS11 |= EMMC_SD_SRS11_RESET_DAT_CMD; + mmc_delay(0xFF); + + /* set transfer block count */ + EMMC_SD_SRS01 = (1 << EMMC_SD_SRS01_BCCT_SHIFT) | sz; + + /* wait for command and data line busy to clear */ + while ((EMMC_SD_SRS09 & (EMMC_SD_SRS09_CICMD | EMMC_SD_SRS09_CIDAT)) != 0); + + EMMC_SD_SRS01 = block_addr; /* cmd argument */ + /* execute command */ + EMMC_SD_SRS03 = ((cmd_index << EMMC_SD_SRS03_CIDX_SHIFT) | + EMMC_SD_SRS03_DPS | EMMC_SD_SRS03_DTDS | + EMMC_SD_SRS03_BCE | EMMC_SD_SRS03_RECE | EMMC_SD_SRS03_RID | + EMMC_SD_SRS03_RECT | EMMC_SD_SRS03_RESP_48 | EMMC_SD_SRS03_CRCCE | + EMMC_SD_SRS03_CICE); + + /* wait for buffer read ready */ + while (((reg = EMMC_SD_SRS12) & (EMMC_SD_SRS12_BRR | EMMC_SD_SRS12_EINT)) == 0); + + /* read in buffer - read 4 bytes at a time */ + if (reg & EMMC_SD_SRS12_BRR) { + uint32_t i; + for (i=0; i> shft; + if (from + shft > 32) { + ret |= resp[off + 1] << (32 - shft) % 32; + } + return ret & mask; +} + +int mmc_send_switch_function(uint32_t mode, uint32_t function_number, uint32_t group_number) +{ + int status; + uint32_t timeout = 4; /* up to 5 tries */ + uint32_t cmd_arg; + uint32_t func_status[64/sizeof(uint32_t)]; /* fixed 512 bits */ + uint8_t* p_func_status = (uint8_t*)func_status; + + if (group_number > 6 || function_number > 15) { + return -1; /* Invalid group or function number */ } + + cmd_arg = (function_number << ((group_number - 1) * 4)); + do { + /* first run check to see if function is supported */ + status = mmc_block_read(SD_CMD_6_SWITCH_FUNC, + (mode | cmd_arg), + func_status, sizeof(func_status)); + if (status == 0) { + /* check if busy */ + /* data structure version 368:375 + * (0=supported only, 1=supported and busy) */ + if (p_func_status[17] == 1) { + /* busy status: group 1 272:287 */ + if ((p_func_status[29 - + ((group_number-1)*2)] & (1 << function_number))) { + continue; /* busy */ + } + } + + /* supported: group 1 415:400 */ + if ((p_func_status[13 - + ((group_number-1)*2)] & (1 << function_number))) { + break; /* supported */ + } + else { + return -1; /* not supported */ + } + } + } while (status == 0 && --timeout > 0); /* retry until function not busy */ + return status; +} + +int mmc_set_function(uint32_t function_number, uint32_t group_number) +{ + /* send check first */ + int status = mmc_send_switch_function(SDCARD_SWITCH_FUNC_MODE_CHECK, + function_number, group_number); if (status == 0) { - *ocr_reg = EMMC_SD_SRS04; + /* send switch function */ + status = mmc_send_switch_function(SDCARD_SWITCH_FUNC_MODE_SWITCH, + function_number, group_number); } return status; } @@ -396,19 +608,22 @@ int mmc_init(void) { int status = 0; uint32_t reg, cap; - uint32_t ctrl_volts = EMMC_SD_SRS10_BVS_3_3V; /* default to 3.3v */ - uint32_t card_volts; - int is_xpc, is_si8r; + uint32_t ctrl_volts, card_volts; + uint32_t irq_restore; + int xpc, si8r; /* Reset the MMC controller */ SYSREG_SOFT_RESET_CR &= ~SYSREG_SOFT_RESET_CR_MMC; + /* Disable the EMMC/SD IRQ */ + /* Reset the host controller */ EMMC_SD_HRS00 |= EMMC_SD_HRS00_SWR; /* Bit will clear when reset is done */ while ((EMMC_SD_HRS00 & EMMC_SD_HRS00_SWR) != 0); /* Set debounce period to ~15ms (at 200MHz) */ - EMMC_SD_HRS01 = (EMMC_SD_DEBOUNCE_TIME & EMMC_SD_HRS01_DP_MASK); + EMMC_SD_HRS01 = ((EMMC_SD_DEBOUNCE_TIME << EMMC_SD_HRS01_DP_SHIFT) & + EMMC_SD_HRS01_DP_MASK); /* Select SDCard Mode */ reg = EMMC_SD_HRS06; @@ -427,8 +642,19 @@ int mmc_init(void) reg |= EMMC_SD_SRS15_HV4E; EMMC_SD_SRS15 = reg; } - /* Set all status enables */ - EMMC_SD_SRS13 = 0xFFFFFFFF; + /* Set all status enables - 0xbff40ff */ + EMMC_SD_SRS13 = ( + EMMC_SD_SRS13_ETUNE_SE | EMMC_SD_SRS13_EADMA_SE | EMMC_SD_SRS13_EAC_SE | + EMMC_SD_SRS13_ECL_SE | EMMC_SD_SRS13_EDEB_SE | + EMMC_SD_SRS13_EDCRC_SE | EMMC_SD_SRS13_EDT_SE | + EMMC_SD_SRS13_ECI_SE | EMMC_SD_SRS13_ECEB_SE | EMMC_SD_SRS13_ECCRC_SE | + EMMC_SD_SRS13_ECT_SE | EMMC_SD_SRS13_RTUNE_SE | + EMMC_SD_SRS13_INT_ONC | EMMC_SD_SRS13_INT_ONB | EMMC_SD_SRS13_INT_ONA | + EMMC_SD_SRS13_CR_SE | EMMC_SD_SRS13_CIN_SE | + EMMC_SD_SRS13_BRR_SE | EMMC_SD_SRS13_BWR_SE | EMMC_SD_SRS13_DMAINT_SE | + EMMC_SD_SRS13_BGE_SE | EMMC_SD_SRS13_TC_SE | EMMC_SD_SRS13_CC_SE | + EMMC_SD_SRS13_ERSP_SE | EMMC_SD_SRS13_CQINT_SE + ); /* Clear all signal enables */ EMMC_SD_SRS14 = 0; /* Set initial timeout to 500ms */ @@ -452,32 +678,35 @@ int mmc_init(void) } /* Start in 1-bit bus mode */ - reg = EMMC_SD_SRS10; - reg &= ~EMMC_SD_SRS10_DTW; - reg &= ~EMMC_SD_SRS10_EDTW; - EMMC_SD_SRS10 = reg; + EMMC_SD_SRS10 &= ~(EMMC_SD_SRS10_EDTW | EMMC_SD_SRS10_DTW); /* Setup 400khz starting clock */ mmc_set_clock(EMMC_SD_CLK_400KHZ); /* Set power to 3.3v and send init commands */ + ctrl_volts = EMMC_SD_SRS10_BVS_3_3V; /* default to 3.3v */ status = mmc_power_init_seq(ctrl_volts); if (status == 0) { uint32_t max_ma_3_3v, max_ma_1_8v; /* determine host controller capabilities */ reg = EMMC_SD_SRS18; - max_ma_3_3v = (reg & EMMC_SD_SRS18_MC33_MASK) >> EMMC_SD_SRS18_MC33_SHIFT; - max_ma_1_8v = (reg & EMMC_SD_SRS18_MC18_MASK) >> EMMC_SD_SRS18_MC18_SHIFT; - /* does it support eXtended Power Control (XPC)? */ - is_xpc = (max_ma_1_8v >= 150) && (max_ma_3_3v >= 150) ? 1 : 0; - /* does it support UHS-I (Ultra High Speed Interface) v1.8 signaling? */ - is_si8r =((EMMC_SD_SRS16 & EMMC_SD_SRS16_VS18) && /* 1.8v supported */ - (EMMC_SD_SRS17 & (EMMC_SD_SRS17_DDR50 | /* DDR50, SDR104, SDR50 or supported */ - EMMC_SD_SRS17_SDR104 | - EMMC_SD_SRS17_SDR50))) ? 1: 0; + max_ma_3_3v = ((reg & EMMC_SD_SRS18_MC33_MASK) >> EMMC_SD_SRS18_MC33_SHIFT) * 4; + max_ma_1_8v = ((reg & EMMC_SD_SRS18_MC18_MASK) >> EMMC_SD_SRS18_MC18_SHIFT) * 4; + /* does controller support eXtended Power Control (XPC)? */ + xpc = (max_ma_1_8v >= 150) && (max_ma_3_3v >= 150) ? 1 : 0; + /* does controller support UHS-I (Ultra High Speed Interface) v1.8 signaling? */ + si8r =((EMMC_SD_SRS16 & EMMC_SD_SRS16_VS18) && /* 1.8v supported */ + (EMMC_SD_SRS17 & (EMMC_SD_SRS17_DDR50 | /* DDR50, SDR104 or SDR50 supported */ + EMMC_SD_SRS17_SDR104 | + EMMC_SD_SRS17_SDR50))) ? 1: 0; + #ifdef DEBUG_MMC + wolfBoot_printf("mmc_init: xpc:%d, si8r:%d, max_ma (3.3v:%d 1.8v:%d)\n", + xpc, si8r, max_ma_3_3v, max_ma_1_8v); + #endif } if (status == 0) { reg = 0; + /* get operating conditions */ status = mmc_card_init(0, ®); if (status == 0) { /* pick host and card operating voltages */ @@ -503,6 +732,9 @@ int mmc_init(void) } /* if needed change operating volage and re-init */ if (ctrl_volts != EMMC_SD_SRS10_BVS_3_3V) { + #ifdef DEBUG_MMC + wolfBoot_printf("mmc_init: changing operating voltage to 3.0v\n"); + #endif status = mmc_power_init_seq(ctrl_volts); } } @@ -511,19 +743,130 @@ int mmc_init(void) /* configure operating conditions */ uint32_t cmd_arg = SDCARD_ACMD41_HCS; cmd_arg |= card_volts; - if (is_si8r) { + if (si8r) { cmd_arg |= SDCARD_REG_OCR_S18RA; } - if (is_xpc) { + if (xpc) { cmd_arg |= SDCARD_REG_OCR_XPC; } + #ifdef DEBUG_MMC + wolfBoot_printf("mmc_init: sending OCR arg: 0x%08X\n", cmd_arg); + #endif /* retry until OCR ready */ do { status = mmc_card_init(cmd_arg, ®); } while (status == 0 && (reg & SDCARD_REG_OCR_READY) == 0); + } + if (status == 0) { + /* Get card identification */ + status = mmc_send_cmd(MMC_CMD2_ALL_SEND_CID, 0, EMMC_SD_RESP_R2); + } + if (status == 0) { + /* Set relative address */ + status = mmc_send_cmd(MMC_CMD3_SET_REL_ADDR, 0, EMMC_SD_RESP_R6); + } + if (status == 0) { + g_rca = ((EMMC_SD_SRS04 >> SD_RCA_SHIFT) & 0xFFFF); + #ifdef DEBUG_MMC + wolfBoot_printf("mmc_init: rca: %d\n", g_rca); + #endif + } + if (status == 0) { + /* read CSD register from device */ + status = mmc_send_cmd(MMC_CMD9_SEND_CSD, g_rca << SD_RCA_SHIFT, + EMMC_SD_RESP_R2); + } + if (status == 0) { + /* Get sector size and count */ + uint32_t csd_struct; + uint32_t c_size = 0; + #define SECT_SIZE_CSD_MASK 0x03C000 + #define SECT_SIZE_CSD_SHIFT 14 + c_size = (EMMC_SD_SRS04 & SECT_SIZE_CSD_MASK) >> SECT_SIZE_CSD_SHIFT; + if (c_size < 32) { + g_sector_size = (1 << c_size); + #ifdef DEBUG_MMC + wolfBoot_printf("mmc_init: sector size: %d\n", g_sector_size); + #endif + } + + csd_struct = get_srs_bits(126,2); + switch (csd_struct) { + case 0: + c_size = get_srs_bits(62, 12); + g_sector_count = (c_size + 1) << (get_srs_bits(47, 3) + 2); + break; + case 1: + c_size = get_srs_bits(48, 22); + g_sector_count = (c_size + 1) << 10; + break; + default: + /* invalid CSR structure */ + status = -1; + break; + } + #ifdef DEBUG_MMC + wolfBoot_printf("mmc_init: sector count: %d\n", g_sector_count); + #endif + } + if (status == 0) { + /* select card */ + status = mmc_send_cmd(MMC_CMD7_SELECT_CARD, g_rca << SD_RCA_SHIFT, + EMMC_SD_RESP_R1B); + if (status == DEVICE_BUSY) { + status = mmc_wait_busy(1); + } + } + if (status == 0) { + /* disable card insert interrupt while changing bus width to avoid false triggers */ + irq_restore = EMMC_SD_SRS13; + EMMC_SD_SRS13 = (irq_restore & ~EMMC_SD_SRS13_CINT_SE); + mmc_delay(DEFAULT_DELAY); + + status = mmc_set_bus_width(4); + } + if (status == 0) { + /* Get SCR registers - 8 bytes */ + uint32_t scr_reg[SCR_REG_DATA_SIZE/sizeof(uint32_t)]; + + status = mmc_send_cmd(SD_CMD_16, sizeof(scr_reg), EMMC_SD_RESP_R1); + if (status == 0) { + status = mmc_send_cmd(SD_CMD55_APP_CMD, (g_rca << SD_RCA_SHIFT), + EMMC_SD_RESP_R1); + } + if (status == 0) { + status = mmc_block_read(SD_ACMD51_SEND_SCR, 0, scr_reg, + sizeof(scr_reg)); + } + } + if (status == 0) { + /* set UHS mode to SDR25 and driver strength to Type B */ + uint32_t card_access_mode = SDCARD_SWITCH_ACCESS_MODE_SDR25; + status = mmc_set_function(card_access_mode, 1); + if (status == 0) { + /* set driver strength */ + reg = EMMC_SD_SRS15; + reg &= ~EMMC_SD_SRS15_DSS_MASK; + reg |= EMMC_SD_SRS15_DSS_TYPE_B; /* default */ + EMMC_SD_SRS15 = reg; + + /* eanble high speed */ + EMMC_SD_SRS10 |= EMMC_SD_SRS10_HSE; + + /* set UHS mode */ + reg = EMMC_SD_SRS15; + reg &= ~EMMC_SD_SRS15_UMS_MASK; + reg |= EMMC_SD_SRS15_UMS_SDR25; + EMMC_SD_SRS15 = reg; + } + } + if (status == 0) { + mmc_set_clock(EMMC_SD_CLK_50MHZ); + /* TODO: Phy training at SDR25 (50MHz) */ + EMMC_SD_SRS13 = irq_restore; /* re-enable interrupt */ } return status; } diff --git a/hal/mpfs250.h b/hal/mpfs250.h index e203e893ec..619dd1b595 100644 --- a/hal/mpfs250.h +++ b/hal/mpfs250.h @@ -96,6 +96,10 @@ #define SIE_STIE (1 << IRQ_S_TIMER) #define SIE_SEIE (1 << IRQ_S_EXT) +#define MCAUSE64_INT 0x8000000000000000LLU +#define MCAUSE64_CAUSE 0x7FFFFFFFFFFFFFFFLLU + + /* UART */ #define MSS_UART0_LO_BASE 0x20000000UL @@ -401,6 +405,7 @@ #define EMMC_SD_SRS09_DAT2_LVL (1U << 22) /* 22: RO - DAT2 signal level */ #define EMMC_SD_SRS09_DAT1_LVL (1U << 21) /* 21: RO - DAT1 signal level */ #define EMMC_SD_SRS09_DAT0_LVL (1U << 20) /* 20: RO - DAT0 signal level */ +#define EMMC_SD_SRS09_DATS_LVL (EMMC_SD_SRS09_DAT0_LVL | EMMC_SD_SRS09_DAT1_LVL | EMMC_SD_SRS09_DAT2_LVL | EMMC_SD_SRS09_DAT3_LVL) #define EMMC_SD_SRS09_WPSL (1U << 19) /* 19: RO - Write Protect Switch Level */ #define EMMC_SD_SRS09_CDSL (1U << 18) /* 18: RO - Card Detect Pin Level */ #define EMMC_SD_SRS09_CSS (1U << 17) /* 17: RO - Card State Stable */ @@ -462,7 +467,6 @@ #define EMMC_SD_SRS11_SDCFSL_MASK (0xFFU << 8) #define EMMC_SD_SRS11_SDCFSH_SHIFT 6 /* 7:6: RW - SDCLK Freq Select (upper 2 bits) */ #define EMMC_SD_SRS11_SDCFSH_MASK (0x3U << 6) -#define EMMC_SD_SRS11_SDCFS_MASK (0xFF00U | 0x00C0U) /* Full SDCLK Freq Select mask */ #define EMMC_SD_SRS11_CGS (1U << 5) /* 5: RW - Clock Generator Select */ #define EMMC_SD_SRS11_SDCE (1U << 2) /* 2: RW - SD Clock Enable */ #define EMMC_SD_SRS11_ICS (1U << 1) /* 1: RO - Internal Clock Stable */ @@ -501,6 +505,7 @@ #define EMMC_SD_SRS13 *((volatile uint32_t*)(EMMC_SD_BASE + 0x234)) /* Error/Normal Status Enable */ #define EMMC_SD_SRS13_ERSP_SE (1U << 27) /* 27: RW - Response Error Status Enable (SD mode only) */ +#define EMMC_SD_SRS13_ETUNE_SE (1U << 26) /* 26: RW - Tuning Error Status Enable (SD mode only) */ #define EMMC_SD_SRS13_EADMA_SE (1U << 25) /* 25: RW - ADMA Error Status Enable (SD mode only) */ #define EMMC_SD_SRS13_EAC_SE (1U << 24) /* 24: RW - Auto CMD Error Status Enable (SD mode only) */ #define EMMC_SD_SRS13_ECL_SE (1U << 23) /* 23: RW - Current Limit Error Status Enable (SD mode only) */ @@ -512,6 +517,10 @@ #define EMMC_SD_SRS13_ECCRC_SE (1U << 17) /* 17: RW - Command CRC Error Status Enable (SD mode only) */ #define EMMC_SD_SRS13_ECT_SE (1U << 16) /* 16: RW - Command Timeout Error Status Enable (SD mode only) */ #define EMMC_SD_SRS13_CQINT_SE (1U << 14) /* 14: RW - Command Queuing Status Enable */ +#define EMMC_SD_SRS13_RTUNE_SE (1U << 12) /* 12: RW - Retuning event status enable */ +#define EMMC_SD_SRS13_INT_ONC (1U << 11) /* 11: RW - Interrupt On Line C status enable */ +#define EMMC_SD_SRS13_INT_ONB (1U << 10) /* 10: RW - Interrupt On Line B status enable */ +#define EMMC_SD_SRS13_INT_ONA (1U << 9) /* 9: RW - Interrupt On Line A status enable */ #define EMMC_SD_SRS13_CINT_SE (1U << 8) /* 8: RW - Card Interrupt Status Enable */ #define EMMC_SD_SRS13_CR_SE (1U << 7) /* 7: RW - Card Removal Status Enable */ #define EMMC_SD_SRS13_CIN_SE (1U << 6) /* 6: RW - Card Insertion Status Enable */ @@ -804,7 +813,7 @@ #define EMMC_SD_BLOCK_SIZE 512U /* Standard block size */ /* SD Interface Conditions */ -#define IF_COND_27V_33V (1u << 8u) +#define IF_COND_27V_33V (1U << 8) /* SD OCR register bits definitions */ #define SDCARD_REG_OCR_2_7_2_8 (1U << 15) @@ -830,20 +839,24 @@ #define MMC_CMD3_SET_REL_ADDR 3 /* MMC: Set relative address */ #define SD_CMD3_SEND_REL_ADDR 3 /* SD: Get relative address */ #define MMC_CMD_4_SET_DSR 4 -#define MMC_CMD6_SWITCH 6 /* Switch/set EXT_CSD */ +#define SD_CMD_6_SWITCH_FUNC 6 /* SD: Switch function */ #define MMC_CMD7_SELECT_CARD 7 /* Select/deselect card */ #define MMC_CMD8_SEND_EXT_CSD 8 /* MMC: Get EXT_CSD */ #define SD_CMD8_SEND_IF_COND 8 /* SD: Send interface condition */ #define MMC_CMD9_SEND_CSD 9 /* Get card-specific data */ +#define SD_CMD11_VOLAGE_SWITCH 11 /* R1 Rsp */ #define MMC_CMD12_STOP_TRANS 12 /* Stop transmission */ #define MMC_CMD13_SEND_STATUS 13 /* Get card status */ #define MMC_CMD_15_GOTO_INACT_ST 15 +#define SD_CMD_16 16 /* R1 Rsp */ #define MMC_CMD17_READ_SINGLE 17 /* Read single block */ #define MMC_CMD18_READ_MULTIPLE 18 /* Read multiple blocks */ #define MMC_CMD24_WRITE_SINGLE 24 /* Write single block */ #define MMC_CMD25_WRITE_MULTIPLE 25 /* Write multiple blocks */ + #define SD_CMD55_APP_CMD 55 /* Prefix for ACMD */ -#define SD_ACMD41_SD_SEND_OP 41 /* SD: Send operating conditions */ +#define SD_ACMD6_SET_BUS_WIDTH 6 /* SD: Set bus width */ +#define SD_ACMD41_SEND_OP_COND 41 /* SD: Send operating conditions */ #define SD_ACMD51_SEND_SCR 51 /* SD: Get SCR register */ /* Debouncing time for card detect */ @@ -860,15 +873,24 @@ #define MAX_CURRENT_MA 150 /* mA */ -#if 0 -EMMC MSSIO_B4 -EMMC_DATA_7_4 MSSIO_B4 -EMMC_SD_CLK_SOURCE MSS_PLL -EMMC_SD_SDIO_FREQ 200 -EMMC_SD_SWITCHING ENABLED_SD -EMMC_SPEED_MODE HIGH_SPEED_200 -#endif +#define SD_RCA_SHIFT 16 + +#define SCR_REG_DATA_SIZE 8 + +/* Switch Function Command Arguments */ +#define SDCARD_SWITCH_FUNC_MODE_SWITCH (0x1u << 31) /* Set function mode */ +#define SDCARD_SWITCH_FUNC_MODE_CHECK (0x0u << 31) /* Check mode */ +/* group 1 - function 1 */ +#define SDCARD_SWITCH_ACCESS_MODE_SDR12 0x0U /* Card access mode - SDR12 default */ +#define SDCARD_SWITCH_ACCESS_MODE_SDR25 0x1U /* Card access mode - SDR25 high speed */ +#define SDCARD_SWITCH_ACCESS_MODE_SDR50 0x2U /* Card access mode - SDR50 */ +#define SDCARD_SWITCH_ACCESS_MODE_SDR104 0x3U /* Card access mode - SDR104 */ +#define SDCARD_SWITCH_ACCESS_MODE_DDR50 0x4U /* Card access mode - DDR50 */ +#define SDCARD_SWITCH_DRIVER_STRENGTH_TYPE_B 0x0U /* Card driver strength - Type B default */ +#define SDCARD_SWITCH_DRIVER_STRENGTH_TYPE_A 0x1U /* Card driver strength - Type A */ +#define SDCARD_SWITCH_DRIVER_STRENGTH_TYPE_C 0x2U /* Card driver strength - Type C */ +#define SDCARD_SWITCH_DRIVER_STRENGTH_TYPE_D 0x3U /* Card driver strength - Type D */ /* Crypto Engine: Athena F5200 TeraFire Crypto Processor (1x), 200 MHz */ diff --git a/src/boot_riscv64.c b/src/boot_riscv64.c index 9824564d7b..b71733002f 100644 --- a/src/boot_riscv64.c +++ b/src/boot_riscv64.c @@ -47,9 +47,15 @@ extern void (* const trap_vector_table[])(void); /* reloc_trap_vector is implemented in boot_riscv64_start.S */ extern void reloc_trap_vector(const uint32_t *address); -unsigned long handle_trap(unsigned long cause, unsigned long epc, unsigned long tval) +static uint64_t last_cause = 0; +static uint64_t last_epc = 0; +static uint64_t last_tval = 0; + +unsigned long WEAKFUNCTION handle_trap(unsigned long cause, unsigned long epc, unsigned long tval) { - /* TODO: Implement trap handling */ + last_cause = cause; + last_epc = epc; + last_tval = tval; return epc; } From 2e8cd5fc1891a97b0955844627b9bab86c81b525 Mon Sep 17 00:00:00 2001 From: David Garske Date: Wed, 17 Dec 2025 12:01:17 -0800 Subject: [PATCH 04/13] Fixes to get uSD driver working --- .github/workflows/test-build-riscv.yml | 15 ++---- docs/Targets.md | 18 ++++++- hal/mpfs250.c | 71 +++++++++++++++----------- 3 files changed, 62 insertions(+), 42 deletions(-) diff --git a/.github/workflows/test-build-riscv.yml b/.github/workflows/test-build-riscv.yml index a88ee6bc5e..f6488c71df 100644 --- a/.github/workflows/test-build-riscv.yml +++ b/.github/workflows/test-build-riscv.yml @@ -80,18 +80,13 @@ jobs: - name: Update repository run: sudo apt-get update -o Acquire::Retries=3 - - name: Download and install RISC-V toolchain - if: ${{ inputs.arch == 'riscv' }} + - name: Download and install RISC-V toolchains run: | # Download latest prebuilt RISC-V toolchains - wget -q https://github.com/RISCV-Tools/riscv-gnu-toolchain/releases/latest/download/riscv32-elf-ubuntu-24.04-gcc.tar.xz - tar -xf riscv32-elf-ubuntu-24.04-gcc.tar.xz - echo "$GITHUB_WORKSPACE/riscv/bin" >> $GITHUB_PATH + #wget -q https://github.com/RISCV-Tools/riscv-gnu-toolchain/releases/latest/download/riscv32-elf-ubuntu-24.04-gcc.tar.xz + #tar -xf riscv32-elf-ubuntu-24.04-gcc.tar.xz + #echo "$GITHUB_WORKSPACE/riscv/bin" >> $GITHUB_PATH - - name: Download and install RISC-V toolchain - if: ${{ inputs.arch == 'riscv64' }} - run: | - # Download latest prebuilt RISC-V toolchains wget -q https://github.com/RISCV-Tools/riscv-gnu-toolchain/releases/latest/download/riscv64-elf-ubuntu-24.04-gcc.tar.xz tar -xf riscv64-elf-ubuntu-24.04-gcc.tar.xz echo "$GITHUB_WORKSPACE/riscv/bin" >> $GITHUB_PATH @@ -111,7 +106,7 @@ jobs: - name: Build wolfboot (riscv32) if: ${{ inputs.arch == 'riscv' }} run: | - # using riscv64 for now since riscv32 is missing "zicsr" extension + # using riscv64 for now since riscv64-unknown-elf- is missing "zicsr" extension make CROSS_COMPILE=riscv64-unknown-elf- FREEDOM_E_SDK=$GITHUB_WORKSPACE/freedom-e-sdk ${{inputs.make-args}} - name: Build wolfboot (riscv64)) diff --git a/docs/Targets.md b/docs/Targets.md index 0ad955f792..781a9eb874 100644 --- a/docs/Targets.md +++ b/docs/Targets.md @@ -879,8 +879,9 @@ set architecture riscv:rv64 ### PolarFire Example Boot Output ``` +wolfBoot Version: 2.7.0 (Dec 17 2025 11:59:22) disk_open: drv = 0 -mmc_set_timeout: timeout_us: 500000, tcfclk_khz: -824320848 (mhz: 3470646), timeout_val: 500000, dtcv: 15 +mmc_set_timeout: timeout_val 500000 (12) mmc_set_clock: clock_khz: 400, freq_khz: 400 mmc_send_cmd: cmd_index: 0, cmd_arg: 00000000, resp_type: 0 mmc_send_cmd: cmd_index: 8, cmd_arg: 00000100, resp_type: 9 @@ -895,7 +896,6 @@ ocr_reg: 0x40FF8000 mmc_send_cmd: cmd_index: 55, cmd_arg: 00000000, resp_type: 1 mmc_send_cmd: cmd_index: 41, cmd_arg: 41200000, resp_type: 4 ocr_reg: 0xC1FF8000 -mmc_send_cmd: cmd_index: 11, cmd_arg: 00000000, resp_type: 1 mmc_send_cmd: cmd_index: 2, cmd_arg: 00000000, resp_type: 3 mmc_send_cmd: cmd_index: 3, cmd_arg: 00000000, resp_type: 8 mmc_init: rca: 43690 @@ -903,6 +903,20 @@ mmc_send_cmd: cmd_index: 9, cmd_arg: AAAA0000, resp_type: 3 mmc_init: sector size: 512 mmc_init: sector count: 62333952 mmc_send_cmd: cmd_index: 7, cmd_arg: AAAA0000, resp_type: 2 +mmc_send_cmd: cmd_index: 55, cmd_arg: AAAA0000, resp_type: 1 +mmc_send_cmd: cmd_index: 6, cmd_arg: 00000002, resp_type: 1 +mmc_send_cmd: cmd_index: 13, cmd_arg: AAAA0000, resp_type: 1 +mmc_send_cmd: cmd_index: 16, cmd_arg: 00000008, resp_type: 1 +mmc_send_cmd: cmd_index: 55, cmd_arg: AAAA0000, resp_type: 1 +mmc_block_read: cmd_index: 51, block_addr: 00000000, dst 0x801FFCE0, sz: 8 +mmc_send_cmd: cmd_index: 13, cmd_arg: AAAA0000, resp_type: 1 +mmc_send_cmd: cmd_index: 13, cmd_arg: AAAA0000, resp_type: 1 +mmc_block_read: cmd_index: 6, block_addr: 00000001, dst 0x801FFC48, sz: 64 +mmc_send_cmd: cmd_index: 13, cmd_arg: AAAA0000, resp_type: 1 +mmc_send_cmd: cmd_index: 13, cmd_arg: AAAA0000, resp_type: 1 +mmc_block_read: cmd_index: 6, block_addr: 80000001, dst 0x801FFC48, sz: 64 +mmc_send_cmd: cmd_index: 13, cmd_arg: AAAA0000, resp_type: 1 +mmc_set_clock: clock_khz: 50000, freq_khz: 50000 Checking primary OS image in 0,1... Checking secondary OS image in 0,2... No valid OS image found in either partition 1 or 2 diff --git a/hal/mpfs250.c b/hal/mpfs250.c index 1805560b10..a9e72073f4 100644 --- a/hal/mpfs250.c +++ b/hal/mpfs250.c @@ -48,6 +48,8 @@ /* Placeholder functions - to be implemented */ void hal_init(void) { + wolfBoot_printf("wolfBoot Version: %s (%s %s)\n", + LIBWOLFBOOT_VERSION_STRING,__DATE__, __TIME__); } @@ -150,7 +152,8 @@ int mmc_set_timeout(uint32_t timeout_us) /* read capabilities to determine timeout clock frequency and unit (MHz or kHz) */ reg = EMMC_SD_SRS16; - tcfclk_khz = (reg * EMMC_SD_SRS16_TCF_MASK); + tcfclk_khz = (reg & EMMC_SD_SRS16_TCF_MASK) >> EMMC_SD_SRS16_TCF_SHIFT; + /* Default timeout clock frequency should be 50MHz */ if (((reg & EMMC_SD_SRS16_TCU) == 0) && (timeout_us < 1000)) { /* invalid timeout_us value */ @@ -184,14 +187,14 @@ int mmc_set_timeout(uint32_t timeout_us) } dtcv = i; - /* set the data timeout counter value - CHECK: 0xc0207 */ + /* set the data timeout counter value */ reg = EMMC_SD_SRS11; reg &= ~EMMC_SD_SRS11_DTCV_MASK; reg |= (dtcv << EMMC_SD_SRS11_DTCV_SHIFT) & EMMC_SD_SRS11_DTCV_MASK; EMMC_SD_SRS11 = reg; #ifdef DEBUG_MMC - wolfBoot_printf("mmc_set_timeout: dtcv 0x%08X, srs11 0x%08X\n", dtcv, reg); + wolfBoot_printf("mmc_set_timeout: timeout_val %d (%d)\n", timeout_val, dtcv); #endif return 0; @@ -268,9 +271,6 @@ uint32_t mmc_set_clock(uint32_t clock_khz) } base_clk_khz *= 1000; /* convert MHz to kHz */ - /* select clock frequency */ - reg = EMMC_SD_SRS11; - reg &= ~(EMMC_SD_SRS11_SDCFSL_MASK | EMMC_SD_SRS11_SDCFSH_MASK); /* calculate divider */ for (i=1; i<2046; i++) { if (((base_clk_khz / i) < clock_khz) || @@ -279,8 +279,12 @@ uint32_t mmc_set_clock(uint32_t clock_khz) } } mclk = (i / 2); - reg |= ((mclk << EMMC_SD_SRS11_SDCFSL_SHIFT) & EMMC_SD_SRS11_SDCFSL_MASK) /* lower 8 bits */ - | ((mclk << EMMC_SD_SRS11_SDCFSH_SHIFT) & EMMC_SD_SRS11_SDCFSH_SHIFT); /* upper 2 bits */ + + /* select clock frequency */ + reg = EMMC_SD_SRS11; + reg &= ~(EMMC_SD_SRS11_SDCFSL_MASK | EMMC_SD_SRS11_SDCFSH_MASK); + reg |= (((mclk & 0x0FF) << EMMC_SD_SRS11_SDCFSL_SHIFT) & EMMC_SD_SRS11_SDCFSL_MASK); /* lower 8 bits */ + reg |= (((mclk & 0x300) << EMMC_SD_SRS11_SDCFSH_SHIFT) & EMMC_SD_SRS11_SDCFSH_SHIFT); /* upper 2 bits */ reg |= EMMC_SD_SRS11_ICE; /* clock enable */ reg &= ~EMMC_SD_SRS11_CGS; /* select clock */ EMMC_SD_SRS11 = reg; @@ -383,7 +387,7 @@ int mmc_send_cmd(uint32_t cmd_index, uint32_t cmd_arg, uint8_t resp_type) /* check for device busy */ if (resp_type == EMMC_SD_RESP_R1 || resp_type == EMMC_SD_RESP_R1B) { uint32_t resp = EMMC_SD_SRS04; - #define CARD_STATUS_READY_FOR_DATA (0x1 << 8) + #define CARD_STATUS_READY_FOR_DATA (1U << 8) if ((resp & CARD_STATUS_READY_FOR_DATA) == 0) { status = DEVICE_BUSY; /* card is busy */ } @@ -469,13 +473,26 @@ int mmc_block_read(uint32_t cmd_index, uint32_t block_addr, uint32_t* dst, /* wait for command and data line busy to clear */ while ((EMMC_SD_SRS09 & (EMMC_SD_SRS09_CICMD | EMMC_SD_SRS09_CIDAT)) != 0); - EMMC_SD_SRS01 = block_addr; /* cmd argument */ + if (cmd_index == SD_ACMD51_SEND_SCR) { + status = mmc_send_cmd(SD_CMD_16, sz, EMMC_SD_RESP_R1); + if (status == 0) { + status = mmc_send_cmd(SD_CMD55_APP_CMD, (g_rca << SD_RCA_SHIFT), + EMMC_SD_RESP_R1); + } + status = 0; /* ignore error */ + } + +#ifdef DEBUG_MMC + wolfBoot_printf("mmc_block_read: cmd_index: %d, block_addr: %08X, dst %p, sz: %d\n", + cmd_index, block_addr, dst, sz); +#endif + + EMMC_SD_SRS02 = block_addr; /* cmd argument */ /* execute command */ EMMC_SD_SRS03 = ((cmd_index << EMMC_SD_SRS03_CIDX_SHIFT) | EMMC_SD_SRS03_DPS | EMMC_SD_SRS03_DTDS | EMMC_SD_SRS03_BCE | EMMC_SD_SRS03_RECE | EMMC_SD_SRS03_RID | - EMMC_SD_SRS03_RECT | EMMC_SD_SRS03_RESP_48 | EMMC_SD_SRS03_CRCCE | - EMMC_SD_SRS03_CICE); + EMMC_SD_SRS03_RESP_48 | EMMC_SD_SRS03_CRCCE | EMMC_SD_SRS03_CICE); /* wait for buffer read ready */ while (((reg = EMMC_SD_SRS12) & (EMMC_SD_SRS12_BRR | EMMC_SD_SRS12_EINT)) == 0); @@ -489,15 +506,17 @@ int mmc_block_read(uint32_t cmd_index, uint32_t block_addr, uint32_t* dst, } } - /* check for any errors */ + /* check for any errors and wait for idle */ reg = EMMC_SD_SRS12; - if (reg & EMMC_SD_SRS12_ERR_STAT) { + if ((reg & EMMC_SD_SRS12_ERR_STAT) == 0) { + mmc_delay(0xFF); + status = mmc_wait_busy(0); + } + else { #ifdef DEBUG_MMC wolfBoot_printf("mmc_block_read: error: 0x%08X\n", reg); #endif - /* wait for idle */ - mmc_delay(0xFF); - status = mmc_wait_busy(0); + status = -1; } return status; @@ -538,7 +557,7 @@ static uint32_t get_srs_bits(int from, int count) int off, shft; from -= 8; - mask = (count < 32 ? 1 << count : 0) - 1; + mask = ((count < 32) ? (1U << (uint32_t)count) : 0) - 1; off = from / 32; shft = from & 31; ret = resp[off] >> shft; @@ -785,13 +804,13 @@ int mmc_init(void) #define SECT_SIZE_CSD_SHIFT 14 c_size = (EMMC_SD_SRS04 & SECT_SIZE_CSD_MASK) >> SECT_SIZE_CSD_SHIFT; if (c_size < 32) { - g_sector_size = (1 << c_size); + g_sector_size = (1U << c_size); #ifdef DEBUG_MMC wolfBoot_printf("mmc_init: sector size: %d\n", g_sector_size); #endif } - csd_struct = get_srs_bits(126,2); + csd_struct = get_srs_bits(126, 2); switch (csd_struct) { case 0: c_size = get_srs_bits(62, 12); @@ -829,16 +848,8 @@ int mmc_init(void) if (status == 0) { /* Get SCR registers - 8 bytes */ uint32_t scr_reg[SCR_REG_DATA_SIZE/sizeof(uint32_t)]; - - status = mmc_send_cmd(SD_CMD_16, sizeof(scr_reg), EMMC_SD_RESP_R1); - if (status == 0) { - status = mmc_send_cmd(SD_CMD55_APP_CMD, (g_rca << SD_RCA_SHIFT), - EMMC_SD_RESP_R1); - } - if (status == 0) { - status = mmc_block_read(SD_ACMD51_SEND_SCR, 0, scr_reg, - sizeof(scr_reg)); - } + status = mmc_block_read(SD_ACMD51_SEND_SCR, 0, scr_reg, + sizeof(scr_reg)); } if (status == 0) { /* set UHS mode to SDR25 and driver strength to Type B */ From 77ebc8a441a8c4f87ec66aa27a3a7bb5d9bb05be Mon Sep 17 00:00:00 2001 From: David Garske Date: Wed, 17 Dec 2025 14:54:54 -0800 Subject: [PATCH 05/13] Refactor disk.c for generic use. Wired up uSD read for MBR/GPT --- .github/workflows/test-build-riscv.yml | 11 ++- Makefile | 2 +- arch.mk | 5 +- docs/Targets.md | 115 ++++++++++++++++++++++-- hal/mpfs250.c | 116 +++++++++++++++++-------- hal/mpfs250.h | 1 + hal/x86_fsp_tgl.c | 57 ++++++++++-- include/disk.h | 43 ++++++++- include/gpt.h | 3 +- src/{x86 => }/disk.c | 102 ++++++++-------------- src/update_disk.c | 37 ++++---- 11 files changed, 347 insertions(+), 145 deletions(-) rename src/{x86 => }/disk.c (80%) diff --git a/.github/workflows/test-build-riscv.yml b/.github/workflows/test-build-riscv.yml index f6488c71df..c195d756ed 100644 --- a/.github/workflows/test-build-riscv.yml +++ b/.github/workflows/test-build-riscv.yml @@ -81,12 +81,21 @@ jobs: run: sudo apt-get update -o Acquire::Retries=3 - name: Download and install RISC-V toolchains + if: ${{ inputs.arch == 'riscv' }} run: | + # Download SiFive prebuilt toolchain with newlib + wget -q https://static.dev.sifive.com/dev-tools/freedom-tools/v2020.12/riscv64-unknown-elf-toolchain-10.2.0-2020.12.8-x86_64-linux-ubuntu14.tar.gz + tar xzf riscv64-unknown-elf-toolchain-10.2.0-2020.12.8-x86_64-linux-ubuntu14.tar.gz + echo "$GITHUB_WORKSPACE/riscv64-unknown-elf-toolchain-10.2.0-2020.12.8-x86_64-linux-ubuntu14/bin" >> $GITHUB_PATH + # Download latest prebuilt RISC-V toolchains #wget -q https://github.com/RISCV-Tools/riscv-gnu-toolchain/releases/latest/download/riscv32-elf-ubuntu-24.04-gcc.tar.xz #tar -xf riscv32-elf-ubuntu-24.04-gcc.tar.xz #echo "$GITHUB_WORKSPACE/riscv/bin" >> $GITHUB_PATH + - name: Download and install RISC-V toolchains + if: ${{ inputs.arch == 'riscv64' }} + run: | wget -q https://github.com/RISCV-Tools/riscv-gnu-toolchain/releases/latest/download/riscv64-elf-ubuntu-24.04-gcc.tar.xz tar -xf riscv64-elf-ubuntu-24.04-gcc.tar.xz echo "$GITHUB_WORKSPACE/riscv/bin" >> $GITHUB_PATH @@ -106,7 +115,7 @@ jobs: - name: Build wolfboot (riscv32) if: ${{ inputs.arch == 'riscv' }} run: | - # using riscv64 for now since riscv64-unknown-elf- is missing "zicsr" extension + # using riscv64 for now since riscv32-unknown-elf- is missing "zicsr" extension make CROSS_COMPILE=riscv64-unknown-elf- FREEDOM_E_SDK=$GITHUB_WORKSPACE/freedom-e-sdk ${{inputs.make-args}} - name: Build wolfboot (riscv64)) diff --git a/Makefile b/Makefile index 08d6ed0cfa..a6739678fa 100644 --- a/Makefile +++ b/Makefile @@ -528,7 +528,7 @@ line-count-nrf52: cloc --force-lang-def cloc_lang_def.txt src/boot_arm.c src/image.c src/libwolfboot.c src/loader.c src/update_flash.c hal/nrf52.c line-count-x86: - cloc --force-lang-def cloc_lang_def.txt src/boot_x86_fsp.c src/boot_x86_fsp_payload.c src/boot_x86_fsp_start.S src/image.c src/keystore.c src/libwolfboot.c src/loader.c src/string.c src/update_disk.c src/gpt.c src/x86/ahci.c src/x86/ata.c src/x86/common.c src/x86/disk.c src/x86/hob.c src/pci.c src/x86/tgl_fsp.c hal/x86_fsp_tgl.c hal/x86_uart.c + cloc --force-lang-def cloc_lang_def.txt src/boot_x86_fsp.c src/boot_x86_fsp_payload.c src/boot_x86_fsp_start.S src/image.c src/keystore.c src/libwolfboot.c src/loader.c src/string.c src/update_disk.c src/gpt.c src/x86/ahci.c src/x86/ata.c src/x86/common.c src/disk.c src/x86/hob.c src/pci.c src/x86/tgl_fsp.c hal/x86_fsp_tgl.c hal/x86_uart.c stack-usage: wolfboot.bin $(Q)echo $(STACK_USAGE) > .stack_usage diff --git a/arch.mk b/arch.mk index 6250482125..838cade67d 100644 --- a/arch.mk +++ b/arch.mk @@ -563,9 +563,10 @@ endif ifeq ($(ARCH),RISCV64) CROSS_COMPILE?=riscv64-unknown-elf- CFLAGS+=-DMMU -DWOLFBOOT_DUALBOOT - CFLAGS+=-DWOLFBOOT_UPDATE_DISK + CFLAGS+=-DWOLFBOOT_UPDATE_DISK -DMAX_DISKS=1 UPDATE_OBJS:=src/update_disk.o OBJS += src/gpt.o + OBJS += src/disk.o ARCH_FLAGS=-march=rv64imafd -mabi=lp64d -mcmodel=medany CFLAGS+=-fno-builtin-printf -DUSE_M_TIME -g -nostartfiles -DARCH_RISCV64 CFLAGS+=$(ARCH_FLAGS) @@ -1117,7 +1118,7 @@ ifeq ("${FSP}", "1") OBJS += src/x86/ahci.o OBJS += src/x86/ata.o OBJS += src/gpt.o - OBJS += src/x86/disk.o + OBJS += src/disk.o OBJS += src/x86/mptable.o OBJS += src/stage2_params.o OBJS += src/x86/exceptions.o diff --git a/docs/Targets.md b/docs/Targets.md index 781a9eb874..916eb18d1a 100644 --- a/docs/Targets.md +++ b/docs/Targets.md @@ -799,7 +799,10 @@ All build settings come from .config file. For this platform use `TARGET=mpfs250 See example configuration at `config/examples/polarfire_mpfs250.config`. ```sh +# Setup .config (build settings) cp config/examples/polarfire_mpfs250.config .config + +# build boot loader make wolfboot.elf ``` @@ -822,13 +825,48 @@ hss-payload-generator -vvv -c ./hal/mpfs.yaml wolfboot.bin Any customizations to the Device Tree can be made in mpfs.dts and it can be recompiled using: `dtc -I dts -O dtb mpfs.dts -o mpfs.dtb` - Example one-shot command: ```sh cp ./config/examples/polarfire_mpfs250.config .config && make clean && make wolfboot.elf && size wolfboot.elf && hss-payload-generator -vvv -c ./hal/mpfs.yaml wolfboot.bin && file wolfboot.bin && ls -la wolfboot.bin ``` +#### Build PolarFire test-application, sign it and apply to uSD + +```sh +# make test-app +make test-app/image.elf + +# assemble GPT image +dd if=/dev/zero of=app.bin bs=1M count=64 +/sbin/fdisk app.bin < #include -#include +#include "target.h" #include "mpfs250.h" #include "image.h" @@ -42,6 +42,7 @@ #include "printf.h" #include "loader.h" #include "disk.h" +#include "gpt.h" #define DEBUG_MMC @@ -200,6 +201,7 @@ int mmc_set_timeout(uint32_t timeout_us) return 0; } +/* TODO: Fix with real timer */ void mmc_delay(uint32_t delay) { while (delay--) { @@ -298,7 +300,7 @@ uint32_t mmc_set_clock(uint32_t clock_khz) last_clock_khz = clock_khz; #ifdef DEBUG_MMC - wolfBoot_printf("mmc_set_clock: clock_khz: %d, freq_khz: %d\n", + wolfBoot_printf("mmc_set_clock: requested khz: %d, actual khz: %d\n", clock_khz, freq_khz); #endif @@ -453,8 +455,8 @@ int mmc_card_init(uint32_t acmd41_arg, uint32_t *ocr_reg) return status; } -/* MMC_CMD17_READ_SINGLE */ -int mmc_block_read(uint32_t cmd_index, uint32_t block_addr, uint32_t* dst, +/* MMC_CMD17_READ_SINGLE, MMC_CMD18_READ_MULTIPLE */ +int mmc_read(uint32_t cmd_index, uint32_t block_addr, uint32_t* dst, uint32_t sz) { int status; @@ -467,12 +469,12 @@ int mmc_block_read(uint32_t cmd_index, uint32_t block_addr, uint32_t* dst, EMMC_SD_SRS11 |= EMMC_SD_SRS11_RESET_DAT_CMD; mmc_delay(0xFF); - /* set transfer block count */ - EMMC_SD_SRS01 = (1 << EMMC_SD_SRS01_BCCT_SHIFT) | sz; - /* wait for command and data line busy to clear */ while ((EMMC_SD_SRS09 & (EMMC_SD_SRS09_CICMD | EMMC_SD_SRS09_CIDAT)) != 0); + /* set transfer block count */ + EMMC_SD_SRS01 = (1 << EMMC_SD_SRS01_BCCT_SHIFT) | sz; + if (cmd_index == SD_ACMD51_SEND_SCR) { status = mmc_send_cmd(SD_CMD_16, sz, EMMC_SD_RESP_R1); if (status == 0) { @@ -483,7 +485,7 @@ int mmc_block_read(uint32_t cmd_index, uint32_t block_addr, uint32_t* dst, } #ifdef DEBUG_MMC - wolfBoot_printf("mmc_block_read: cmd_index: %d, block_addr: %08X, dst %p, sz: %d\n", + wolfBoot_printf("mmc_read: cmd_index: %d, block_addr: %08X, dst %p, sz: %d\n", cmd_index, block_addr, dst, sz); #endif @@ -513,12 +515,13 @@ int mmc_block_read(uint32_t cmd_index, uint32_t block_addr, uint32_t* dst, status = mmc_wait_busy(0); } else { - #ifdef DEBUG_MMC - wolfBoot_printf("mmc_block_read: error: 0x%08X\n", reg); - #endif - status = -1; + status = -1; /* error */ } +#ifdef DEBUG_MMC + wolfBoot_printf("mmc_read: status: %d\n", status); +#endif + return status; } @@ -567,10 +570,13 @@ static uint32_t get_srs_bits(int from, int count) return ret & mask; } -int mmc_send_switch_function(uint32_t mode, uint32_t function_number, uint32_t group_number) +/* check or set switch function/group: + * returns 0 if supported */ +int mmc_send_switch_function(uint32_t mode, uint32_t function_number, + uint32_t group_number) { int status; - uint32_t timeout = 4; /* up to 5 tries */ + uint32_t timeout = 4; uint32_t cmd_arg; uint32_t func_status[64/sizeof(uint32_t)]; /* fixed 512 bits */ uint8_t* p_func_status = (uint8_t*)func_status; @@ -582,7 +588,7 @@ int mmc_send_switch_function(uint32_t mode, uint32_t function_number, uint32_t g cmd_arg = (function_number << ((group_number - 1) * 4)); do { /* first run check to see if function is supported */ - status = mmc_block_read(SD_CMD_6_SWITCH_FUNC, + status = mmc_read(SD_CMD_6_SWITCH_FUNC, (mode | cmd_arg), func_status, sizeof(func_status)); if (status == 0) { @@ -600,11 +606,12 @@ int mmc_send_switch_function(uint32_t mode, uint32_t function_number, uint32_t g /* supported: group 1 415:400 */ if ((p_func_status[13 - ((group_number-1)*2)] & (1 << function_number))) { - break; /* supported */ + status = 0; /* supported */ } else { - return -1; /* not supported */ + status = -1; /* not supported */ } + break; } } while (status == 0 && --timeout > 0); /* retry until function not busy */ return status; @@ -848,7 +855,7 @@ int mmc_init(void) if (status == 0) { /* Get SCR registers - 8 bytes */ uint32_t scr_reg[SCR_REG_DATA_SIZE/sizeof(uint32_t)]; - status = mmc_block_read(SD_ACMD51_SEND_SCR, 0, scr_reg, + status = mmc_read(SD_ACMD51_SEND_SCR, 0, scr_reg, sizeof(scr_reg)); } if (status == 0) { @@ -882,37 +889,72 @@ int mmc_init(void) return status; } -/* TODO: Add support for reading uSD card with GPT (Global Partition Table) */ -/* The partition ID's are determined using BOOT_PART_A and BOOT_PART_B. */ -int disk_open(int drv) +/* returns number of bytes read on success or negative on error */ +int disk_read(int drv, uint64_t start, uint32_t count, uint32_t *buf) { - wolfBoot_printf("disk_open: drv = %d\r\n", drv); - (void)drv; - return mmc_init(); + int status = 0; + uint32_t read_sz, block_addr; + uint8_t* p_buf = (uint8_t*)buf; + uint32_t tmp_block[EMMC_SD_BLOCK_SIZE/sizeof(uint32_t)]; + (void)drv; /* only one drive supported */ + +#ifdef DEBUG_MMC + wolfBoot_printf("disk_read: drv:%d, start:%llu, count:%d, dst:%p\n", + drv, start, count, buf); +#endif + + while (count > 0) { + block_addr = (start / EMMC_SD_BLOCK_SIZE); + read_sz = count; + if (read_sz < EMMC_SD_BLOCK_SIZE) { + /* last partial block read */ + status = mmc_read(MMC_CMD17_READ_SINGLE, block_addr, + tmp_block, EMMC_SD_BLOCK_SIZE); + if (status == 0) { + memcpy(p_buf, tmp_block, read_sz); + break; /* last partial block read */ + } + } + else { + /* full block read */ + read_sz = EMMC_SD_BLOCK_SIZE; + status = mmc_read(MMC_CMD17_READ_SINGLE, block_addr, + (uint32_t*)p_buf, read_sz); + } + if (status != 0) { + break; + } + + start += read_sz; + p_buf += read_sz; + count -= read_sz; + } + return status; } -int disk_read(int drv, int part, uint64_t off, uint64_t sz, uint8_t *buf) + +int disk_write(int drv, uint64_t start, uint32_t count, const uint32_t *buf) { + /* not supported */ (void)drv; - (void)part; - (void)off; - (void)sz; + (void)start; + (void)count; (void)buf; return 0; } -int disk_write(int drv, int part, uint64_t off, uint64_t sz, const uint8_t *buf) + +int disk_init(int drv) { + int r = mmc_init(); + if (r != 0) { + wolfBoot_printf("Failed to initialize MMC\n"); + } (void)drv; - (void)part; - (void)off; - (void)sz; - (void)buf; - return 0; + return r; } -int disk_find_partition_by_label(int drv, const char *label) + +void disk_close(int drv) { (void)drv; - (void)label; - return 0; } #ifdef DEBUG_UART diff --git a/hal/mpfs250.h b/hal/mpfs250.h index 619dd1b595..8aeb74f432 100644 --- a/hal/mpfs250.h +++ b/hal/mpfs250.h @@ -877,6 +877,7 @@ #define SCR_REG_DATA_SIZE 8 + /* Switch Function Command Arguments */ #define SDCARD_SWITCH_FUNC_MODE_SWITCH (0x1u << 31) /* Set function mode */ #define SDCARD_SWITCH_FUNC_MODE_CHECK (0x0u << 31) /* Check mode */ diff --git a/hal/x86_fsp_tgl.c b/hal/x86_fsp_tgl.c index d148dfac9a..6b23ecf01e 100644 --- a/hal/x86_fsp_tgl.c +++ b/hal/x86_fsp_tgl.c @@ -19,16 +19,22 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ -#include +#include "wolfboot/wolfboot.h" #include -#include -#include -#include -#include -#include #ifdef __WOLFBOOT +#include "uart_drv.h" +#include "printf.h" +#include "loader.h" + +#ifdef WOLFBOOT_FSP +#include "x86/ahci.h" +#include "x86/ata.h" +#include "x86/common.h" +#include "x86/tgl_fsp.h" +#endif + #if defined(TARGET_kontron_vx3060_s2) #define PCI_AHCI_BUS 0 #define PCI_AHCI_DEV 0x17 @@ -39,6 +45,45 @@ #define PCI_AHCI_FUN 2 #endif +#ifdef WOLFBOOT_FSP +static uint32_t sata_bar; +#endif + +int disk_init(int drv) +{ + int ret = 0; +#ifdef WOLFBOOT_FSP + ret = x86_fsp_tgl_init_sata(&sata_bar); + if (ret != 0) + wolfBoot_panic(); +#ifdef WOLFBOOT_ATA_DISK_LOCK + ret = sata_unlock_disk(drv, 1); + if (ret != 0) + wolfBoot_panic(); +#endif +#endif /* WOLFBOOT_FSP */ + (void)drv; + return ret; +} + +void disk_close(int drv) +{ +#ifdef WOLFBOOT_FSP + sata_disable(sata_bar); +#endif + (void)drv; +} + +int disk_read(int drv, uint64_t start, uint32_t count, uint32_t *buf) +{ + return ata_drive_read(drv, start, count, (uint8_t*)buf); +} + +int disk_write(int drv, uint64_t start, uint32_t count, const uint32_t *buf) +{ + return ata_drive_write(drv, start, count, (const uint8_t*)buf); +} + /*! * \brief Initializes the SATA controller. * diff --git a/include/disk.h b/include/disk.h index 75c09576cc..8c2212314a 100644 --- a/include/disk.h +++ b/include/disk.h @@ -23,10 +23,49 @@ #define _WOLFBOOT_DISK_H #include +#include "gpt.h" +#ifndef MAX_PARTITIONS +#define MAX_PARTITIONS 16 +#endif +#ifndef MAX_DISKS +#define MAX_DISKS 4 +#endif + +/** + * @brief This structure holds information about a disk partition, including + * the drive it belongs to, partition number, start, and end offsets. + */ +struct disk_partition { + int drv; + int part_no; + uint64_t start; + uint64_t end; + uint16_t name[GPT_PART_NAME_SIZE]; +}; + +/** + * @brief This structure holds information about a disk drive, including its + * drive number, open status, the number of partitions, and an array of disk + * partitions. + */ +struct disk_drive { + int drv; + int is_open; + int n_parts; + struct disk_partition part[MAX_PARTITIONS]; +}; + +/* user supplied functions */ +int disk_init(int drv); +int disk_read(int drv, uint64_t start, uint32_t count, uint32_t *buf); +int disk_write(int drv, uint64_t start, uint32_t count, const uint32_t *buf); +void disk_close(int drv); + +/* standard functions */ int disk_open(int drv); -int disk_read(int drv, int part, uint64_t off, uint64_t sz, uint8_t *buf); -int disk_write(int drv, int part, uint64_t off, uint64_t sz, const uint8_t *buf); +int disk_part_read(int drv, int part, uint64_t off, uint64_t sz, uint32_t *buf); +int disk_part_write(int drv, int part, uint64_t off, uint64_t sz, const uint32_t *buf); int disk_find_partition_by_label(int drv, const char *label); #endif /* _WOLFBOOT_DISK_H */ diff --git a/include/gpt.h b/include/gpt.h index fb92ceebdb..20eebb2641 100644 --- a/include/gpt.h +++ b/include/gpt.h @@ -27,13 +27,14 @@ #include /* GPT Constants */ -#define GPT_SECTOR_SIZE 0x200 +#define GPT_SECTOR_SIZE 512 /* 0x200 */ #define GPT_SIGNATURE 0x5452415020494645ULL /* "EFI PART" */ #define GPT_PTYPE_PROTECTIVE 0xEE #define GPT_PART_NAME_SIZE 36 #define GPT_MBR_ENTRY_START 0x01BE #define GPT_MBR_BOOTSIG_OFFSET 0x01FE #define GPT_MBR_BOOTSIG_VALUE 0xAA55 +#define GPT_PART_ENTRY_SIZE 256 /** * @brief MBR partition table entry structure. diff --git a/src/x86/disk.c b/src/disk.c similarity index 80% rename from src/x86/disk.c rename to src/disk.c index 5bdf26c4f3..569298d106 100644 --- a/src/x86/disk.c +++ b/src/disk.c @@ -20,51 +20,21 @@ * */ /** - * @file x86/disk.c - * @brief x86 GPT disk driver implementation. + * @file disk.c + * @brief GPT disk driver implementation. * - * This file contains the x86-specific GPT disk driver that uses ATA for - * disk I/O operations. It uses the generic GPT parsing functions from - * src/gpt.c for partition table parsing. + * This file contains the GPT disk driver that uses disk I/O operations. + * It uses the generic GPT parsing functions from src/gpt.c for partition + * table parsing. */ -#ifndef X86_DISK_C -#define X86_DISK_C +#ifndef _WOLFBOOT_DISK_C_ +#define _WOLFBOOT_DISK_C_ #include #include -#include -#include -#include -#include -#include -#define MAX_PARTITIONS 16 -#define MAX_DISKS 4 - -/** - * @brief This structure holds information about a disk partition, including - * the drive it belongs to, partition number, start, and end offsets. - */ -struct disk_partition -{ - int drv; - int part_no; - uint64_t start; - uint64_t end; - uint16_t name[GPT_PART_NAME_SIZE]; -}; - -/** - * @brief This structure holds information about a disk drive, including its - * drive number, open status, the number of partitions, and an array of disk - * partitions. - */ -struct disk_drive { - int drv; - int is_open; - int n_parts; - struct disk_partition part[MAX_PARTITIONS]; -}; +#include "disk.h" +#include "printf.h" /** * @brief This array holds instances of the `struct disk_drive` representing @@ -91,7 +61,7 @@ int disk_open(int drv) uint32_t n_parts = 0; uint32_t gpt_lba = 0; struct guid_ptable ptable; - uint8_t sector[GPT_SECTOR_SIZE]; + uint32_t sector[GPT_SECTOR_SIZE/sizeof(uint32_t)]; if ((drv < 0) || (drv > MAX_DISKS)) { wolfBoot_printf("Attempting to access invalid drive %d\r\n", drv); @@ -101,14 +71,14 @@ int disk_open(int drv) wolfBoot_printf("Reading MBR...\r\n"); /* Read MBR sector */ - r = ata_drive_read(drv, 0, GPT_SECTOR_SIZE, sector); - if (r <= 0) { + r = disk_read(drv, 0, GPT_SECTOR_SIZE, sector); + if (r < 0) { wolfBoot_printf("Failed to read MBR\r\n"); return -1; } /* Check for protective MBR and get GPT header location */ - if (gpt_check_mbr_protective(sector, &gpt_lba) != 0) { + if (gpt_check_mbr_protective((uint8_t*)sector, &gpt_lba) != 0) { wolfBoot_printf("Cannot find valid partition table entry for GPT\r\n"); return -1; } @@ -120,14 +90,14 @@ int disk_open(int drv) Drives[drv].n_parts = 0; /* Read GPT header */ - r = ata_drive_read(drv, GPT_SECTOR_SIZE * gpt_lba, GPT_SECTOR_SIZE, sector); - if (r <= 0) { - wolfBoot_printf("ATA: Read failed\r\n"); + r = disk_read(drv, GPT_SECTOR_SIZE * gpt_lba, GPT_SECTOR_SIZE, sector); + if (r < 0) { + wolfBoot_printf("Disk read failed\r\n"); return -1; } /* Parse and validate GPT header */ - if (gpt_parse_header(sector, &ptable) != 0) { + if (gpt_parse_header((uint8_t*)sector, &ptable) != 0) { wolfBoot_printf("Invalid partition table\r\n"); return -1; } @@ -151,20 +121,20 @@ int disk_open(int drv) struct gpt_part_info part_info; uint64_t address = ptable.start_array * GPT_SECTOR_SIZE + i * ptable.array_sz; - uint8_t entry_buf[256]; /* Max partition entry size */ + uint32_t entry_buf[GPT_PART_ENTRY_SIZE/sizeof(uint32_t)]; /* Max partition entry size */ if (ptable.array_sz > sizeof(entry_buf)) { wolfBoot_printf("Partition entry size too large\r\n"); break; } - r = ata_drive_read(drv, address, ptable.array_sz, entry_buf); + r = disk_read(drv, address, ptable.array_sz, entry_buf); if (r < 0) { return -1; } /* Parse partition entry using generic function */ - if (gpt_parse_partition(entry_buf, ptable.array_sz, &part_info) == 0) { + if (gpt_parse_partition((uint8_t*)entry_buf, ptable.array_sz, &part_info) == 0) { uint64_t size; uint32_t part_count; @@ -198,7 +168,7 @@ int disk_open(int drv) * * This function opens a disk partition with the specified drive number and * partition number and returns a pointer to its disk_partition structure. - * It is a static helper function used internally by the disk_read and disk_write + * It is a static helper function used internally by the disk_part_read and disk_part_write * functions to validate the partition before performing read/write operations. * * @param[in] drv The drive number of the disk containing the partition (0 to `MAX_DISKS - 1`). @@ -241,21 +211,24 @@ static struct disk_partition *open_part(int drv, int part) * * @return The number of bytes read into the buffer on success, or -1 if an error occurs. */ -int disk_read(int drv, int part, uint64_t off, uint64_t sz, uint8_t *buf) +int disk_part_read(int drv, int part, uint64_t off, uint64_t sz, uint32_t *buf) { struct disk_partition *p = open_part(drv, part); int len = sz; int ret; - if (p == NULL) + if (p == NULL) { return -1; - + } if ((p->end - (p->start + off)) < sz) { len = p->end - (p->start + off); } if (len < 0) { return -1; } - ret = ata_drive_read(drv, p->start + off, len, buf); + ret = disk_read(drv, p->start + off, len, buf); + if (ret == 0) { + ret = len; + } return ret; } @@ -273,21 +246,21 @@ int disk_read(int drv, int part, uint64_t off, uint64_t sz, uint8_t *buf) * * @return The number of bytes written to the partition on success, or -1 if an error occurs. */ -int disk_write(int drv, int part, uint64_t off, uint64_t sz, const uint8_t *buf) +int disk_part_write(int drv, int part, uint64_t off, uint64_t sz, const uint32_t *buf) { struct disk_partition *p = open_part(drv, part); int len = sz; int ret; - if (p == NULL) + if (p == NULL) { return -1; - + } if ((p->end - (p->start + off)) < sz) { len = p->end - (p->start + off); } if (len < 0) { return -1; } - ret = ata_drive_write(drv, p->start + off, len, buf); + ret = disk_write(drv, p->start + off, len, buf); return ret; } @@ -306,12 +279,12 @@ int disk_find_partition_by_label(int drv, const char *label) struct disk_partition *p; int i; - if ((drv < 0) || (drv > MAX_DISKS)) + if ((drv < 0) || (drv > MAX_DISKS)) { return -1; - - if (Drives[drv].is_open == 0) + } + if (Drives[drv].is_open == 0) { return -1; - + } for (i = 0; i < Drives[drv].n_parts; i++) { p = open_part(drv, i); if (gpt_part_name_eq(p->name, label) == 1) @@ -320,5 +293,4 @@ int disk_find_partition_by_label(int drv, const char *label) return -1; } -#endif /* X86_DISK_C */ - +#endif /* _WOLFBOOT_DISK_C_ */ diff --git a/src/update_disk.c b/src/update_disk.c index 8b8db2b930..231364f51f 100644 --- a/src/update_disk.c +++ b/src/update_disk.c @@ -99,7 +99,10 @@ extern uint8_t _end_wb[]; */ void RAMFUNCTION wolfBoot_start(void) { - uint8_t p_hdr[IMAGE_HEADER_SIZE] XALIGNED_STACK(16); + uint32_t p_hdr[IMAGE_HEADER_SIZE/sizeof(uint32_t)] XALIGNED_STACK(16); +#ifdef WOLFBOOT_FSP + struct stage2_parameter *stage2_params; +#endif struct wolfBoot_image os_image; int pA_ver = 0, pB_ver = 0; uint32_t cur_part = 0; @@ -114,18 +117,10 @@ void RAMFUNCTION wolfBoot_start(void) #endif char part_name[4] = {'P', ':', 'X', '\0'}; -#ifdef WOLFBOOT_FSP - struct stage2_parameter *stage2_params; - uint32_t sata_bar; - ret = x86_fsp_tgl_init_sata(&sata_bar); - if (ret != 0) - wolfBoot_panic(); -#ifdef WOLFBOOT_ATA_DISK_LOCK - ret = sata_unlock_disk(BOOT_DISK, 1); - if (ret != 0) + ret = disk_init(BOOT_DISK); + if (ret != 0) { wolfBoot_panic(); -#endif -#endif /* WOLFBOOT_FSP */ + } if (disk_open(BOOT_DISK) < 0) { wolfBoot_printf("Error opening disk %d\r\n", BOOT_DISK); @@ -134,16 +129,16 @@ void RAMFUNCTION wolfBoot_start(void) wolfBoot_printf("Checking primary OS image in %d,%d...\r\n", BOOT_DISK, BOOT_PART_A); - if (disk_read(BOOT_DISK, BOOT_PART_A, 0, IMAGE_HEADER_SIZE, p_hdr) + if (disk_part_read(BOOT_DISK, BOOT_PART_A, 0, IMAGE_HEADER_SIZE, p_hdr) == IMAGE_HEADER_SIZE) { - pA_ver = wolfBoot_get_blob_version(p_hdr); + pA_ver = wolfBoot_get_blob_version((uint8_t*)p_hdr); } wolfBoot_printf("Checking secondary OS image in %d,%d...\r\n", BOOT_DISK, BOOT_PART_B); - if (disk_read(BOOT_DISK, BOOT_PART_B, 0, IMAGE_HEADER_SIZE, p_hdr) + if (disk_part_read(BOOT_DISK, BOOT_PART_B, 0, IMAGE_HEADER_SIZE, p_hdr) == IMAGE_HEADER_SIZE) { - pB_ver = wolfBoot_get_blob_version(p_hdr); + pB_ver = wolfBoot_get_blob_version((uint8_t*)p_hdr); } if ((pB_ver == 0) && (pA_ver == 0)) { @@ -181,7 +176,7 @@ void RAMFUNCTION wolfBoot_start(void) wolfBoot_printf("Attempting boot from %s\r\n", part_name); /* Fetch header only */ - if (disk_read(BOOT_DISK, cur_part, 0, IMAGE_HEADER_SIZE, p_hdr) + if (disk_part_read(BOOT_DISK, cur_part, 0, IMAGE_HEADER_SIZE, p_hdr) != IMAGE_HEADER_SIZE) { wolfBoot_printf("Error reading image header from disk: p%d\r\n", cur_part); @@ -215,8 +210,8 @@ void RAMFUNCTION wolfBoot_start(void) wolfBoot_printf("Loading image from disk..."); load_off = 0; do { - ret = disk_read(BOOT_DISK, cur_part, load_off, - DISK_BLOCK_SIZE, (uint8_t*)load_address + load_off); + ret = disk_part_read(BOOT_DISK, cur_part, load_off, + DISK_BLOCK_SIZE, (uint32_t*)(load_address + load_off)); if (ret < 0) break; load_off += ret; @@ -264,9 +259,7 @@ void RAMFUNCTION wolfBoot_start(void) wolfBoot_panic(); } -#ifdef WOLFBOOT_FSP - sata_disable(sata_bar); -#endif + disk_close(BOOT_DISK); wolfBoot_printf("Firmware Valid.\r\n"); From 414b256d3be6efc301c5d23be13189f1ad3a53b8 Mon Sep 17 00:00:00 2001 From: David Garske Date: Fri, 19 Dec 2025 15:41:19 -0800 Subject: [PATCH 06/13] Cleanups and improvements --- config/examples/polarfire_mpfs250.config | 2 + docs/Targets.md | 87 ++++++++++++++++-------- hal/mpfs250.c | 62 ++++++++--------- hal/mpfs250.h | 7 +- hal/x86_fsp_tgl.c | 11 +-- include/disk.h | 8 +-- src/disk.c | 18 +++-- src/update_disk.c | 8 +-- 8 files changed, 116 insertions(+), 87 deletions(-) diff --git a/config/examples/polarfire_mpfs250.config b/config/examples/polarfire_mpfs250.config index 3b224c1865..48f26e0bf9 100644 --- a/config/examples/polarfire_mpfs250.config +++ b/config/examples/polarfire_mpfs250.config @@ -22,6 +22,8 @@ DUALBANK_SWAP?=0 PKA?=0 ENCRYPT=0 WOLFTPM?=0 +ELF?=1 +#DEBUG_ELF?=1 # Optionally allow downgrade to older valid version in update partition ALLOW_DOWNGRADE?=0 diff --git a/docs/Targets.md b/docs/Targets.md index 916eb18d1a..c5c8a83c73 100644 --- a/docs/Targets.md +++ b/docs/Targets.md @@ -831,63 +831,92 @@ Example one-shot command: cp ./config/examples/polarfire_mpfs250.config .config && make clean && make wolfboot.elf && size wolfboot.elf && hss-payload-generator -vvv -c ./hal/mpfs.yaml wolfboot.bin && file wolfboot.bin && ls -la wolfboot.bin ``` -#### Build PolarFire test-application, sign it and apply to uSD +### Flashing PolarFire SoC + +The HSS MMC boot source looks for GPT with GUID "21686148-6449-6E6F-744E-656564454649" or sector "0" if no GPT found. That GUID is the default "BIOS" boot partition. + +The resulting image from `hss-payload-generator` can be directly placed into GPT BIOS partition. The HSS tinyCLI supports the `USBDMSC` command to mount the eMMC or SD card as a USB device. You can then use "dd" to copy the boot image to the BOOT partition 2. Example: + +``` +sudo dd if=wolfboot.bin of=/dev/sdc2 bs=512 +``` + +### PolarFire testing + +This section describes how to build the test-application, create a custom uSD with required partitions and copying signing test-application to uSD partitions. + +To use your own application (Linux FIT Image, ELF, etc) just replace test-app/image.elf with your own filename. ```sh # make test-app make test-app/image.elf +``` -# assemble GPT image -dd if=/dev/zero of=app.bin bs=1M count=64 -/sbin/fdisk app.bin <> EMMC_SD_SRS16_BCSDCLK_SHIFT; if (base_clk_khz == 0) { /* error getting base clock */ - return 0; + return -1; } base_clk_khz *= 1000; /* convert MHz to kHz */ @@ -427,14 +426,13 @@ int mmc_power_init_seq(uint32_t voltage) if (status == 0) { /* send CMD0 (go idle) to reset card */ status = mmc_send_cmd(MMC_CMD0_GO_IDLE, 0, EMMC_SD_RESP_NONE); + } + if (status == 0) { + mmc_delay(DEFAULT_DELAY); - if (status == 0) { - mmc_delay(DEFAULT_DELAY); - - /* send the operating conditions command */ - status = mmc_send_cmd(SD_CMD8_SEND_IF_COND, IF_COND_27V_33V, - EMMC_SD_RESP_R7); - } + /* send the operating conditions command */ + status = mmc_send_cmd(SD_CMD8_SEND_IF_COND, IF_COND_27V_33V, + EMMC_SD_RESP_R7); } return status; } @@ -553,6 +551,7 @@ int mmc_set_bus_width(uint32_t bus_width) return status; } +/* helper to get bits from the response registers */ static uint32_t get_srs_bits(int from, int count) { volatile uint32_t *resp = ((volatile uint32_t*)(EMMC_SD_BASE + 0x210)); @@ -564,8 +563,8 @@ static uint32_t get_srs_bits(int from, int count) off = from / 32; shft = from & 31; ret = resp[off] >> shft; - if (from + shft > 32) { - ret |= resp[off + 1] << (32 - shft) % 32; + if ((from + shft) > 32) { + ret |= resp[off + 1] << ((32 - shft) % 32); } return ret & mask; } @@ -806,34 +805,29 @@ int mmc_init(void) if (status == 0) { /* Get sector size and count */ uint32_t csd_struct; - uint32_t c_size = 0; - #define SECT_SIZE_CSD_MASK 0x03C000 - #define SECT_SIZE_CSD_SHIFT 14 - c_size = (EMMC_SD_SRS04 & SECT_SIZE_CSD_MASK) >> SECT_SIZE_CSD_SHIFT; - if (c_size < 32) { - g_sector_size = (1U << c_size); - #ifdef DEBUG_MMC - wolfBoot_printf("mmc_init: sector size: %d\n", g_sector_size); - #endif - } + uint32_t bl_len, c_size, c_size_mult; + bl_len = get_srs_bits(22, 4); + g_sector_size = (1U << bl_len); csd_struct = get_srs_bits(126, 2); switch (csd_struct) { case 0: c_size = get_srs_bits(62, 12); - g_sector_count = (c_size + 1) << (get_srs_bits(47, 3) + 2); + c_size_mult = get_srs_bits(47, 3); + g_sector_count = (c_size + 1) << (c_size_mult + 2); break; case 1: c_size = get_srs_bits(48, 22); g_sector_count = (c_size + 1) << 10; break; default: - /* invalid CSR structure */ + /* invalid CSD structure */ status = -1; break; } #ifdef DEBUG_MMC - wolfBoot_printf("mmc_init: sector count: %d\n", g_sector_count); + wolfBoot_printf("mmc_init: csd_version: %d, sector: size %d count %d\n", + csd_struct, g_sector_size, g_sector_count); #endif } if (status == 0) { @@ -890,11 +884,10 @@ int mmc_init(void) } /* returns number of bytes read on success or negative on error */ -int disk_read(int drv, uint64_t start, uint32_t count, uint32_t *buf) +int disk_read(int drv, uint64_t start, uint32_t count, uint8_t *buf) { int status = 0; uint32_t read_sz, block_addr; - uint8_t* p_buf = (uint8_t*)buf; uint32_t tmp_block[EMMC_SD_BLOCK_SIZE/sizeof(uint32_t)]; (void)drv; /* only one drive supported */ @@ -906,33 +899,34 @@ int disk_read(int drv, uint64_t start, uint32_t count, uint32_t *buf) while (count > 0) { block_addr = (start / EMMC_SD_BLOCK_SIZE); read_sz = count; - if (read_sz < EMMC_SD_BLOCK_SIZE) { - /* last partial block read */ + if (read_sz > EMMC_SD_BLOCK_SIZE) { + read_sz = EMMC_SD_BLOCK_SIZE; + } + if (read_sz < EMMC_SD_BLOCK_SIZE || ((uintptr_t)buf % 4) != 0) { + /* partial or unaligned block read */ status = mmc_read(MMC_CMD17_READ_SINGLE, block_addr, tmp_block, EMMC_SD_BLOCK_SIZE); if (status == 0) { - memcpy(p_buf, tmp_block, read_sz); - break; /* last partial block read */ + memcpy(buf, tmp_block, read_sz); } } else { /* full block read */ - read_sz = EMMC_SD_BLOCK_SIZE; status = mmc_read(MMC_CMD17_READ_SINGLE, block_addr, - (uint32_t*)p_buf, read_sz); + (uint32_t*)buf, read_sz); } if (status != 0) { break; } start += read_sz; - p_buf += read_sz; + buf += read_sz; count -= read_sz; } return status; } -int disk_write(int drv, uint64_t start, uint32_t count, const uint32_t *buf) +int disk_write(int drv, uint64_t start, uint32_t count, const uint8_t *buf) { /* not supported */ (void)drv; diff --git a/hal/mpfs250.h b/hal/mpfs250.h index 8aeb74f432..2c4c7c2efd 100644 --- a/hal/mpfs250.h +++ b/hal/mpfs250.h @@ -836,8 +836,7 @@ #define MMC_CMD0_GO_IDLE 0 /* Reset card to idle state */ #define MMC_CMD1_SEND_OP_COND 1 /* MMC: Send operating conditions */ #define MMC_CMD2_ALL_SEND_CID 2 /* Get card identification */ -#define MMC_CMD3_SET_REL_ADDR 3 /* MMC: Set relative address */ -#define SD_CMD3_SEND_REL_ADDR 3 /* SD: Get relative address */ +#define MMC_CMD3_SET_REL_ADDR 3 /* Set relative address */ #define MMC_CMD_4_SET_DSR 4 #define SD_CMD_6_SWITCH_FUNC 6 /* SD: Switch function */ #define MMC_CMD7_SELECT_CARD 7 /* Select/deselect card */ @@ -873,11 +872,11 @@ #define MAX_CURRENT_MA 150 /* mA */ -#define SD_RCA_SHIFT 16 +#define SD_RCA_SHIFT 16 /* relative card address */ +#define SD_RCA_MASK (0xFFFFU << SD_RCA_SHIFT) /* relative card address mask */ #define SCR_REG_DATA_SIZE 8 - /* Switch Function Command Arguments */ #define SDCARD_SWITCH_FUNC_MODE_SWITCH (0x1u << 31) /* Set function mode */ #define SDCARD_SWITCH_FUNC_MODE_CHECK (0x0u << 31) /* Check mode */ diff --git a/hal/x86_fsp_tgl.c b/hal/x86_fsp_tgl.c index 6b23ecf01e..833cb5a923 100644 --- a/hal/x86_fsp_tgl.c +++ b/hal/x86_fsp_tgl.c @@ -1,4 +1,4 @@ -/* fsp_tgl.c +/* x86_fsp_tgl.c * * Copyright (C) 2025 wolfSSL Inc. * @@ -70,18 +70,19 @@ void disk_close(int drv) { #ifdef WOLFBOOT_FSP sata_disable(sata_bar); + sata_bar = 0; #endif (void)drv; } -int disk_read(int drv, uint64_t start, uint32_t count, uint32_t *buf) +int disk_read(int drv, uint64_t start, uint32_t count, uint8_t *buf) { - return ata_drive_read(drv, start, count, (uint8_t*)buf); + return ata_drive_read(drv, start, count, buf); } -int disk_write(int drv, uint64_t start, uint32_t count, const uint32_t *buf) +int disk_write(int drv, uint64_t start, uint32_t count, const uint8_t *buf) { - return ata_drive_write(drv, start, count, (const uint8_t*)buf); + return ata_drive_write(drv, start, count, buf); } /*! diff --git a/include/disk.h b/include/disk.h index 8c2212314a..fb128fe6cc 100644 --- a/include/disk.h +++ b/include/disk.h @@ -58,14 +58,14 @@ struct disk_drive { /* user supplied functions */ int disk_init(int drv); -int disk_read(int drv, uint64_t start, uint32_t count, uint32_t *buf); -int disk_write(int drv, uint64_t start, uint32_t count, const uint32_t *buf); +int disk_read(int drv, uint64_t start, uint32_t count, uint8_t *buf); +int disk_write(int drv, uint64_t start, uint32_t count, const uint8_t *buf); void disk_close(int drv); /* standard functions */ int disk_open(int drv); -int disk_part_read(int drv, int part, uint64_t off, uint64_t sz, uint32_t *buf); -int disk_part_write(int drv, int part, uint64_t off, uint64_t sz, const uint32_t *buf); +int disk_part_read(int drv, int part, uint64_t off, uint64_t sz, uint8_t *buf); +int disk_part_write(int drv, int part, uint64_t off, uint64_t sz, const uint8_t *buf); int disk_find_partition_by_label(int drv, const char *label); #endif /* _WOLFBOOT_DISK_H */ diff --git a/src/disk.c b/src/disk.c index 569298d106..951febe03e 100644 --- a/src/disk.c +++ b/src/disk.c @@ -33,6 +33,7 @@ #include #include +#include "wolfboot/wolfboot.h" #include "disk.h" #include "printf.h" @@ -61,7 +62,7 @@ int disk_open(int drv) uint32_t n_parts = 0; uint32_t gpt_lba = 0; struct guid_ptable ptable; - uint32_t sector[GPT_SECTOR_SIZE/sizeof(uint32_t)]; + uint8_t sector[GPT_SECTOR_SIZE] XALIGNED(4); if ((drv < 0) || (drv > MAX_DISKS)) { wolfBoot_printf("Attempting to access invalid drive %d\r\n", drv); @@ -119,9 +120,9 @@ int disk_open(int drv) /* Read and parse partition entries */ for (i = 0; i < n_parts; i++) { struct gpt_part_info part_info; - uint64_t address = ptable.start_array * GPT_SECTOR_SIZE + - i * ptable.array_sz; - uint32_t entry_buf[GPT_PART_ENTRY_SIZE/sizeof(uint32_t)]; /* Max partition entry size */ + uint64_t address = (ptable.start_array * GPT_SECTOR_SIZE) + + (i * ptable.array_sz); + uint8_t entry_buf[GPT_PART_ENTRY_SIZE] XALIGNED(4); /* Max partition entry size */ if (ptable.array_sz > sizeof(entry_buf)) { wolfBoot_printf("Partition entry size too large\r\n"); @@ -211,7 +212,7 @@ static struct disk_partition *open_part(int drv, int part) * * @return The number of bytes read into the buffer on success, or -1 if an error occurs. */ -int disk_part_read(int drv, int part, uint64_t off, uint64_t sz, uint32_t *buf) +int disk_part_read(int drv, int part, uint64_t off, uint64_t sz, uint8_t *buf) { struct disk_partition *p = open_part(drv, part); int len = sz; @@ -227,7 +228,7 @@ int disk_part_read(int drv, int part, uint64_t off, uint64_t sz, uint32_t *buf) } ret = disk_read(drv, p->start + off, len, buf); if (ret == 0) { - ret = len; + ret = len; /* success expects to return the number of bytes read */ } return ret; } @@ -246,7 +247,7 @@ int disk_part_read(int drv, int part, uint64_t off, uint64_t sz, uint32_t *buf) * * @return The number of bytes written to the partition on success, or -1 if an error occurs. */ -int disk_part_write(int drv, int part, uint64_t off, uint64_t sz, const uint32_t *buf) +int disk_part_write(int drv, int part, uint64_t off, uint64_t sz, const uint8_t *buf) { struct disk_partition *p = open_part(drv, part); int len = sz; @@ -261,6 +262,9 @@ int disk_part_write(int drv, int part, uint64_t off, uint64_t sz, const uint32_t return -1; } ret = disk_write(drv, p->start + off, len, buf); + if (ret == 0) { + ret = len; /* success expects to return the number of bytes written */ + } return ret; } diff --git a/src/update_disk.c b/src/update_disk.c index 231364f51f..5dfe8cb17a 100644 --- a/src/update_disk.c +++ b/src/update_disk.c @@ -69,10 +69,10 @@ #define BOOT_DISK 0 #endif #ifndef BOOT_PART_A -#define BOOT_PART_A 1 +#define BOOT_PART_A 0 #endif #ifndef BOOT_PART_B -#define BOOT_PART_B 2 +#define BOOT_PART_B 1 #endif #ifndef MAX_FAILURES @@ -99,7 +99,7 @@ extern uint8_t _end_wb[]; */ void RAMFUNCTION wolfBoot_start(void) { - uint32_t p_hdr[IMAGE_HEADER_SIZE/sizeof(uint32_t)] XALIGNED_STACK(16); + uint8_t p_hdr[IMAGE_HEADER_SIZE] XALIGNED_STACK(16); #ifdef WOLFBOOT_FSP struct stage2_parameter *stage2_params; #endif @@ -211,7 +211,7 @@ void RAMFUNCTION wolfBoot_start(void) load_off = 0; do { ret = disk_part_read(BOOT_DISK, cur_part, load_off, - DISK_BLOCK_SIZE, (uint32_t*)(load_address + load_off)); + DISK_BLOCK_SIZE, (uint8_t *)(load_address + load_off)); if (ret < 0) break; load_off += ret; From a95f15031b8cbb36cb77cf4921060384f2ebadac Mon Sep 17 00:00:00 2001 From: David Garske Date: Mon, 22 Dec 2025 09:38:29 -0800 Subject: [PATCH 07/13] Fix for uSD read to handle start that is not block aligned --- config/examples/polarfire_mpfs250.config | 21 ++--- docs/Targets.md | 12 +-- hal/mpfs250.c | 19 ++-- src/libwolfboot.c | 6 +- test-app/app_mpfs250.c | 105 ----------------------- 5 files changed, 32 insertions(+), 131 deletions(-) diff --git a/config/examples/polarfire_mpfs250.config b/config/examples/polarfire_mpfs250.config index 48f26e0bf9..f7dd892265 100644 --- a/config/examples/polarfire_mpfs250.config +++ b/config/examples/polarfire_mpfs250.config @@ -39,18 +39,19 @@ NO_ARM_ASM?=0 WOLFBOOT_SECTOR_SIZE?=0x1000 # Load Partition to RAM Address -WOLFBOOT_LOAD_ADDRESS?=0xA0000000 +WOLFBOOT_LOAD_ADDRESS?=0x80200000 # Partition layout for PolarFire SoC MPFS250T -# TODO: Update with actual flash layout based on your system design -WOLFBOOT_PARTITION_SIZE?=0x10000 -WOLFBOOT_PARTITION_BOOT_ADDRESS?=0x08080000 -WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x08090000 -WOLFBOOT_PARTITION_SWAP_ADDRESS?=0x080FF000 +# Using update_disk loader we just need to specify the partition number or A/B +WOLFBOOT_NO_PARTITIONS=1 +CFLAGS_EXTRA+=-DBOOT_PART_A=1 +CFLAGS_EXTRA+=-DBOOT_PART_B=2 # DTS (Device Tree) -WOLFBOOT_LOAD_DTS_ADDRESS?=0x80000000 -WOLFBOOT_DTS_BOOT_ADDRESS?=0x20F00000 -WOLFBOOT_DTS_UPDATE_ADDRESS?=0x20F00000 +WOLFBOOT_LOAD_DTS_ADDRESS?=0x8a000000 -#CFLAGS_EXTRA+=-DDEBUG_EXT_FLASH +#CFLAGS_EXTRA+=-DDEBUG_MMC + +# Used by test-application for ELF +WOLFBOOT_PARTITION_BOOT_ADDRESS=0x80200000 +WOLFBOOT_PARTITION_SIZE=0x4000000 diff --git a/docs/Targets.md b/docs/Targets.md index c5c8a83c73..9b77ed1788 100644 --- a/docs/Targets.md +++ b/docs/Targets.md @@ -847,13 +847,9 @@ This section describes how to build the test-application, create a custom uSD wi To use your own application (Linux FIT Image, ELF, etc) just replace test-app/image.elf with your own filename. -```sh -# make test-app -make test-app/image.elf -``` +1) Partition uSD card (replace /dev/sdc with your actual media, find using `lsblk`): ```sh -# Partition uSD card sudo fdisk /dev/sdc < EMMC_SD_BLOCK_SIZE) { read_sz = EMMC_SD_BLOCK_SIZE; } - if (read_sz < EMMC_SD_BLOCK_SIZE || ((uintptr_t)buf % 4) != 0) { - /* partial or unaligned block read */ + if (read_sz < EMMC_SD_BLOCK_SIZE || /* last partial */ + start_offset != 0 || /* start not block aligned */ + ((uintptr_t)buf % 4) != 0) /* buf not 4-byte aligned */ + { + /* block read to temporary buffer */ status = mmc_read(MMC_CMD17_READ_SINGLE, block_addr, tmp_block, EMMC_SD_BLOCK_SIZE); if (status == 0) { - memcpy(buf, tmp_block, read_sz); + uint8_t* tmp_buf = (uint8_t*)tmp_block; + memcpy(buf, tmp_buf + start_offset, read_sz); + start_offset = 0; } } else { - /* full block read */ + /* direct full block read */ status = mmc_read(MMC_CMD17_READ_SINGLE, block_addr, (uint32_t*)buf, read_sz); } diff --git a/src/libwolfboot.c b/src/libwolfboot.c index 409b17852b..5647d53a8d 100644 --- a/src/libwolfboot.c +++ b/src/libwolfboot.c @@ -136,7 +136,7 @@ int wolfBoot_initialize_encryption(void) #undef WOLFBOOT_FIXED_PARTITIONS #endif -#ifdef EXT_FLASH +#if defined(EXT_FLASH) && !defined(WOLFBOOT_NO_PARTITIONS) static uint32_t ext_cache; #endif @@ -154,8 +154,8 @@ static uint32_t wb_reverse_word32(uint32_t x) #endif #endif -#if defined(WOLFBOOT_FIXED_PARTITIONS) || defined(EXT_FLASH) || \ - defined(NVM_FLASH_WRITEONCE) +#if (defined(WOLFBOOT_FIXED_PARTITIONS) || defined(EXT_FLASH) || \ + defined(NVM_FLASH_WRITEONCE)) && !defined(WOLFBOOT_NO_PARTITIONS) static const uint32_t wolfboot_magic_trail = WOLFBOOT_MAGIC_TRAIL; #endif diff --git a/test-app/app_mpfs250.c b/test-app/app_mpfs250.c index af05c96fba..49513c1752 100644 --- a/test-app/app_mpfs250.c +++ b/test-app/app_mpfs250.c @@ -30,125 +30,20 @@ #include "wolfboot/wolfboot.h" #include "target.h" #include "printf.h" -#include "keystore.h" #include "../hal/mpfs250.h" -static uint8_t boot_part_state = IMG_STATE_NEW; -static uint8_t update_part_state = IMG_STATE_NEW; - -const char part_state_names[6][16] = { - "NEW", - "UPDATING", - "FFLAGS", - "TESTING", - "CONFIRMED", - "[Invalid state]" -}; - -static const char *part_state_name(uint8_t state) -{ - switch(state) { - case IMG_STATE_NEW: - return part_state_names[0]; - case IMG_STATE_UPDATING: - return part_state_names[1]; - case IMG_STATE_FINAL_FLAGS: - return part_state_names[2]; - case IMG_STATE_TESTING: - return part_state_names[3]; - case IMG_STATE_SUCCESS: - return part_state_names[4]; - default: - return part_state_names[5]; - } -} - -static int print_info(void) -{ - int i, j; - uint32_t cur_fw_version, update_fw_version; - uint32_t n_keys; - uint16_t hdrSz; - - cur_fw_version = wolfBoot_current_firmware_version(); - update_fw_version = wolfBoot_update_firmware_version(); - - wolfBoot_get_partition_state(PART_BOOT, &boot_part_state); - wolfBoot_get_partition_state(PART_UPDATE, &update_part_state); - - wolfBoot_printf("\r\n"); - wolfBoot_printf("System information\r\n"); - wolfBoot_printf("====================================\r\n"); - wolfBoot_printf("Firmware version : 0x%lx\r\n", wolfBoot_current_firmware_version()); - wolfBoot_printf("Current firmware state: %s\r\n", part_state_name(boot_part_state)); - if (update_fw_version != 0) { - if (update_part_state == IMG_STATE_UPDATING) - wolfBoot_printf("Candidate firmware version : 0x%lx\r\n", update_fw_version); - else - wolfBoot_printf("Backup firmware version : 0x%lx\r\n", update_fw_version); - wolfBoot_printf("Update state: %s\r\n", part_state_name(update_part_state)); - if (update_fw_version > cur_fw_version) { - wolfBoot_printf("'reboot' to initiate update.\r\n"); - } else { - wolfBoot_printf("Update image older than current.\r\n"); - } - } else { - wolfBoot_printf("No image in update partition.\r\n"); - } - - wolfBoot_printf("\r\n"); - wolfBoot_printf("Bootloader OTP keystore information\r\n"); - wolfBoot_printf("====================================\r\n"); - n_keys = keystore_num_pubkeys(); - wolfBoot_printf("Number of public keys: %lu\r\n", n_keys); - for (i = 0; i < n_keys; i++) { - uint32_t size = keystore_get_size(i); - uint32_t type = keystore_get_key_type(i); - uint32_t mask = keystore_get_mask(i); - uint8_t *keybuf = keystore_get_buffer(i); - - wolfBoot_printf("\r\n"); - wolfBoot_printf(" Public Key #%d: size %lu, type %lx, mask %08lx\r\n", i, - size, type, mask); - wolfBoot_printf(" ====================================\r\n "); - for (j = 0; j < size; j++) { - wolfBoot_printf("%02X ", keybuf[j]); - if (j % 16 == 15) { - wolfBoot_printf("\r\n "); - } - } - wolfBoot_printf("\r\n"); - } - return 0; -} void main(void) { - uint32_t app_version; - hal_init(); - app_version = wolfBoot_current_firmware_version(); - wolfBoot_printf("========================\r\n"); wolfBoot_printf("PolarFire SoC MPFS250 wolfBoot demo Application\r\n"); wolfBoot_printf("Copyright 2025 wolfSSL Inc\r\n"); wolfBoot_printf("GPL v3\r\n"); - wolfBoot_printf("Version : 0x%lx\r\n", app_version); wolfBoot_printf("========================\r\n"); - print_info(); - - if (app_version > 1) { - if (boot_part_state == IMG_STATE_TESTING) { - wolfBoot_printf("Booting new firmware, marking successful boot\n"); - - /* Mark successful boot, so update won't be rolled back */ - wolfBoot_success(); - } - } - /* TODO: Add application-specific code here */ while(1) { From aff2bcdd168e1065cfaf4cda2879c09b620cfc65 Mon Sep 17 00:00:00 2001 From: David Garske Date: Mon, 22 Dec 2025 11:03:52 -0800 Subject: [PATCH 08/13] Fix issue with pointer increment in update_disk.c loader refactor --- src/update_disk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/update_disk.c b/src/update_disk.c index 5dfe8cb17a..fa20f2fe7b 100644 --- a/src/update_disk.c +++ b/src/update_disk.c @@ -211,7 +211,7 @@ void RAMFUNCTION wolfBoot_start(void) load_off = 0; do { ret = disk_part_read(BOOT_DISK, cur_part, load_off, - DISK_BLOCK_SIZE, (uint8_t *)(load_address + load_off)); + DISK_BLOCK_SIZE, ((uint8_t *)load_address) + load_off); if (ret < 0) break; load_off += ret; From ca9c8112beb77a2869be0e147a684ff7ce8440d8 Mon Sep 17 00:00:00 2001 From: David Garske Date: Mon, 22 Dec 2025 16:20:29 -0800 Subject: [PATCH 09/13] Working Secure boot of PolarFire SoC --- config/examples/polarfire_mpfs250.config | 9 +- docs/Targets.md | 229 ++++++++++++----------- hal/mpfs.yaml | 9 +- hal/mpfs250.its | 44 +++++ hal/mpfs250.ld | 2 +- hal/zynq.c | 2 +- src/disk.c | 9 + src/fdt.c | 2 +- test-app/Makefile | 4 + test-app/RISCV64-mpfs250.ld | 5 + test-app/app_mpfs250.c | 1 + 11 files changed, 200 insertions(+), 116 deletions(-) create mode 100644 hal/mpfs250.its diff --git a/config/examples/polarfire_mpfs250.config b/config/examples/polarfire_mpfs250.config index f7dd892265..2b05d8e21a 100644 --- a/config/examples/polarfire_mpfs250.config +++ b/config/examples/polarfire_mpfs250.config @@ -9,7 +9,7 @@ DEBUG?=0 DEBUG_SYMBOLS?=1 DEBUG_UART?=1 VTOR?=1 -EXT_FLASH?=1 +EXT_FLASH?=0 SPI_FLASH?=0 NO_XIP?=1 NVM_FLASH_WRITEONCE?=0 @@ -39,7 +39,7 @@ NO_ARM_ASM?=0 WOLFBOOT_SECTOR_SIZE?=0x1000 # Load Partition to RAM Address -WOLFBOOT_LOAD_ADDRESS?=0x80200000 +WOLFBOOT_LOAD_ADDRESS?=0x8E000000 # Partition layout for PolarFire SoC MPFS250T # Using update_disk loader we just need to specify the partition number or A/B @@ -48,9 +48,12 @@ CFLAGS_EXTRA+=-DBOOT_PART_A=1 CFLAGS_EXTRA+=-DBOOT_PART_B=2 # DTS (Device Tree) -WOLFBOOT_LOAD_DTS_ADDRESS?=0x8a000000 +WOLFBOOT_LOAD_DTS_ADDRESS?=0x8A000000 +# Optional EMMC_SD debugging logs #CFLAGS_EXTRA+=-DDEBUG_MMC +# Optional disk debugging logs +#CFLAGS_EXTRA+=-DDEBUG_DISK # Used by test-application for ELF WOLFBOOT_PARTITION_BOOT_ADDRESS=0x80200000 diff --git a/docs/Targets.md b/docs/Targets.md index 9b77ed1788..b44ca7bb65 100644 --- a/docs/Targets.md +++ b/docs/Targets.md @@ -792,6 +792,15 @@ The PolarFire SoC is a 64-bit RISC-V SoC featuring a five-core CPU cluster (1× * Low power consumption * External flash support +### PolarFire SoC Files + +`hal/mpfs250.c` - Hardware abstraction layer implementation (UART and uSD) +`hal/mpfs250.h` - Register definitions and hardware interfaces +`hal/mpfs250.ld` - Linker script for the platform +`hal/mpfs.dts` / `hal/mpfs.dtb` - Device tree source and binary +`hal/mpfs.yaml` - HSS payload generator configuration +`hal/mpfs250.its` - For creating new FIT images with Kernel and DTB + ### Building PolarFire SoC All build settings come from .config file. For this platform use `TARGET=mpfs250` and `ARCH=RISCV64`. @@ -837,18 +846,20 @@ The HSS MMC boot source looks for GPT with GUID "21686148-6449-6E6F-744E-6565644 The resulting image from `hss-payload-generator` can be directly placed into GPT BIOS partition. The HSS tinyCLI supports the `USBDMSC` command to mount the eMMC or SD card as a USB device. You can then use "dd" to copy the boot image to the BOOT partition 2. Example: -``` -sudo dd if=wolfboot.bin of=/dev/sdc2 bs=512 +```sh +sudo dd if=wolfboot.bin of=/dev/sdc1 bs=512 && sudo cmp wolfboot.bin /dev/sdc1 ``` ### PolarFire testing This section describes how to build the test-application, create a custom uSD with required partitions and copying signing test-application to uSD partitions. -To use your own application (Linux FIT Image, ELF, etc) just replace test-app/image.elf with your own filename. +To use your own application (Linux FIT Image, ELF, etc) just replace test-app/image.elf with your own file (example "fitImage"). 1) Partition uSD card (replace /dev/sdc with your actual media, find using `lsblk`): +Note: adjust +64M for larger OFP A/B + ```sh sudo fdisk /dev/sdc < kernel.bin +$ mkimage -f hal/mpfs250.its fitImageNew +FIT description: PolarFire SoC MPFS250T +Created: Mon Dec 22 15:29:32 2025 + Image 0 (kernel-1) + Description: Kernel Image + Created: Mon Dec 22 15:29:32 2025 + Type: Kernel Image + Compression: uncompressed + Data Size: 19745280 Bytes = 19282.50 KiB = 18.83 MiB + Architecture: RISC-V + OS: Linux + Load Address: 0x80200000 + Entry Point: 0x80200000 + Hash algo: sha256 + Hash value: 800ce147fa91f367ec620936a59a1035c49971ed4b9080c96bdc547471e80487 + Image 1 (fdt-1) + Description: Flattened Device Tree blob + Created: Mon Dec 22 15:29:32 2025 + Type: Flat Device Tree + Compression: uncompressed + Data Size: 19897 Bytes = 19.43 KiB = 0.02 MiB + Architecture: RISC-V + Load Address: 0x8a000000 + Hash algo: sha256 + Hash value: 0b4efca8c0607c9a8f4f9a00ccb7691936e019f3181aab45e6d52dae91975039 + Default Configuration: 'conf@1' + Configuration 0 (conf@1) + Description: PolarFire SoC MPFS250T + Kernel: kernel-1 + FDT: fdt-1 + Hash algo: sha256 + Hash value: unavailable +``` ### Debugging PolarFire Soc @@ -946,117 +1016,66 @@ set architecture riscv:rv64 ### PolarFire Example Boot Output ``` -wolfBoot Version: 2.7.0 (Dec 17 2025 17:03:55) -mmc_set_timeout: timeout_val 500000 (12) -mmc_set_clock: requested khz: 400, actual khz: 400 -mmc_send_cmd: cmd_index: 0, cmd_arg: 00000000, resp_type: 0 -mmc_send_cmd: cmd_index: 8, cmd_arg: 00000100, resp_type: 9 -mmc_init: xpc:0, si8r:1, max_ma (3.3v:128 1.8v:128) -mmc_send_cmd: cmd_index: 55, cmd_arg: 00000000, resp_type: 1 -mmc_send_cmd: cmd_index: 41, cmd_arg: 00000000, resp_type: 4 -ocr_reg: 0x40FF8000 -mmc_init: sending OCR arg: 0x41200000 -mmc_send_cmd: cmd_index: 55, cmd_arg: 00000000, resp_type: 1 -mmc_send_cmd: cmd_index: 41, cmd_arg: 41200000, resp_type: 4 -ocr_reg: 0x40FF8000 -mmc_send_cmd: cmd_index: 55, cmd_arg: 00000000, resp_type: 1 -mmc_send_cmd: cmd_index: 41, cmd_arg: 41200000, resp_type: 4 -ocr_reg: 0xC1FF8000 -mmc_send_cmd: cmd_index: 2, cmd_arg: 00000000, resp_type: 3 -mmc_send_cmd: cmd_index: 3, cmd_arg: 00000000, resp_type: 8 -mmc_init: rca: 43690 -mmc_send_cmd: cmd_index: 9, cmd_arg: AAAA0000, resp_type: 3 -mmc_init: sector size: 512 -mmc_init: sector count: 62333952 -mmc_send_cmd: cmd_index: 7, cmd_arg: AAAA0000, resp_type: 2 -mmc_send_cmd: cmd_index: 55, cmd_arg: AAAA0000, resp_type: 1 -mmc_send_cmd: cmd_index: 6, cmd_arg: 00000002, resp_type: 1 -mmc_send_cmd: cmd_index: 13, cmd_arg: AAAA0000, resp_type: 1 -mmc_send_cmd: cmd_index: 16, cmd_arg: 00000008, resp_type: 1 -mmc_send_cmd: cmd_index: 55, cmd_arg: AAAA0000, resp_type: 1 -mmc_read: cmd_index: 51, block_addr: 00000000, dst 0x801FFCD0, sz: 8 -mmc_send_cmd: cmd_index: 13, cmd_arg: AAAA0000, resp_type: 1 -mmc_read: status: 0 -mmc_send_cmd: cmd_index: 13, cmd_arg: AAAA0000, resp_type: 1 -mmc_read: cmd_index: 6, block_addr: 00000001, dst 0x801FFC38, sz: 64 -mmc_send_cmd: cmd_index: 13, cmd_arg: AAAA0000, resp_type: 1 -mmc_read: status: 0 -mmc_send_cmd: cmd_index: 13, cmd_arg: AAAA0000, resp_type: 1 -mmc_read: cmd_index: 6, block_addr: 80000001, dst 0x801FFC38, sz: 64 -mmc_send_cmd: cmd_index: 13, cmd_arg: AAAA0000, resp_type: 1 -mmc_read: status: 0 -mmc_set_clock: requested khz: 50000, actual khz: 50000 +wolfBoot Version: 2.7.0 (Dec 22 2025 14:14:37) Reading MBR... -disk_read: drv:0, start:0, count:512, dst:0x801FF918 -mmc_send_cmd: cmd_index: 13, cmd_arg: AAAA0000, resp_type: 1 -mmc_read: cmd_index: 17, block_addr: 00000000, dst 0x801FF918, sz: 512 -mmc_send_cmd: cmd_index: 13, cmd_arg: AAAA0000, resp_type: 1 -mmc_read: status: 0 Found GPT PTE at sector 1 Found valid boot signature in MBR -disk_read: drv:0, start:512, count:512, dst:0x801FF918 -mmc_send_cmd: cmd_index: 13, cmd_arg: AAAA0000, resp_type: 1 -mmc_read: cmd_index: 17, block_addr: 00000001, dst 0x801FF918, sz: 512 -mmc_send_cmd: cmd_index: 13, cmd_arg: AAAA0000, resp_type: 1 -mmc_read: status: 0 Valid GPT partition table Current LBA: 0x1 Backup LBA: 0x3B723FF Max number of partitions: 128 Software limited: only allowing up to 16 partitions per disk. -Disk size: 1850178048 -disk_read: drv:0, start:1024, count:128, dst:0x801FF818 -mmc_send_cmd: cmd_index: 13, cmd_arg: AAAA0000, resp_type: 1 -mmc_read: cmd_index: 17, block_addr: 00000002, dst 0x801FF588, sz: 512 -mmc_send_cmd: cmd_index: 13, cmd_arg: AAAA0000, resp_type: 1 -mmc_read: status: 0 -disk0.p0 (0_3FFFE00h@ 0_400000) -disk_read: drv:0, start:1152, count:128, dst:0x801FF818 -mmc_send_cmd: cmd_index: 13, cmd_arg: AAAA0000, resp_type: 1 -mmc_read: cmd_index: 17, block_addr: 00000002, dst 0x801FF588, sz: 512 -mmc_send_cmd: cmd_index: 13, cmd_arg: AAAA0000, resp_type: 1 -mmc_read: status: 0 -disk0.p1 (0_3FFFE00h@ 0_400000) -disk_read: drv:0, start:1280, count:128, dst:0x801FF818 -mmc_send_cmd: cmd_index: 13, cmd_arg: AAAA0000, resp_type: 1 -mmc_read: cmd_index: 17, block_addr: 00000002, dst 0x801FF588, sz: 512 -mmc_send_cmd: cmd_index: 13, cmd_arg: AAAA0000, resp_type: 1 -mmc_read: status: 0 -disk0.p2 (0_3FFFE00h@ 0_400000) -disk_read: drv:0, start:1408, count:128, dst:0x801FF818 -mmc_send_cmd: cmd_index: 13, cmd_arg: AAAA0000, resp_type: 1 -mmc_read: cmd_index: 17, block_addr: 00000002, dst 0x801FF588, sz: 512 -mmc_send_cmd: cmd_index: 13, cmd_arg: AAAA0000, resp_type: 1 -mmc_read: status: 0 -disk0.p3 (0_3FFFE00h@ 0_400000) -disk_read: drv:0, start:1536, count:128, dst:0x801FF818 -mmc_send_cmd: cmd_index: 13, cmd_arg: AAAA0000, resp_type: 1 -mmc_read: cmd_index: 17, block_addr: 00000003, dst 0x801FF588, sz: 512 -mmc_send_cmd: cmd_index: 13, cmd_arg: AAAA0000, resp_type: 1 -mmc_read: status: 0 +Disk size: 1849146880 +disk0.p0 (0_7FFE00h@ 0_100000) +disk0.p1 (0_3FFFE00h@ 0_900000) +disk0.p2 (0_3FFFE00h@ 0_4900000) +disk0.p3 (7_65AFFE00h@ 0_8900000) Total partitions on disk0: 4 Checking primary OS image in 0,1... -disk_read: drv:0, start:4194304, count:512, dst:0x801FFDA0 -mmc_send_cmd: cmd_index: 13, cmd_arg: AAAA0000, resp_type: 1 -mmc_read: cmd_index: 17, block_addr: 00002000, dst 0x801FFDA0, sz: 512 -mmc_send_cmd: cmd_index: 13, cmd_arg: AAAA0000, resp_type: 1 -mmc_read: status: 0 Checking secondary OS image in 0,2... -disk_read: drv:0, start:4194304, count:512, dst:0x801FFDA0 -mmc_send_cmd: cmd_index: 13, cmd_arg: AAAA0000, resp_type: 1 -mmc_read: cmd_index: 17, block_addr: 00002000, dst 0x801FFDA0, sz: 512 -mmc_send_cmd: cmd_index: 13, cmd_arg: AAAA0000, resp_type: 1 -mmc_read: status: 0 -No valid OS image found in either partition 1 or 2 -wolfBoot: PANIC! +Versions, A:1 B:1 +Load address 0x8E000000 +Attempting boot from P:A +Boot partition: 0x801FFDA0 (sz 19767000, ver 0x1, type 0x601) +Loading image from disk...done. +Boot partition: 0x8E000000 (sz 19767000, ver 0x1, type 0x601) +Checking image integrity...done. +Verifying image signature...done. +Firmware Valid. +Flattened uImage Tree: Version 17, Size 19767000 +Loading Image kernel-1: 0x8E0002C8 -> 0x80200000 (19745280 bytes) +Image kernel-1: 0x80200000 (19745280 bytes) +Loading Image fdt-1: 0x8F2D4DCC -> 0x8A000000 (19897 bytes) +Image fdt-1: 0x8A000000 (19897 bytes) +Loading DTS: 0x8A000000 -> 0x8A000000 (19897 bytes) +Loading elf at 0x80200000 +Invalid elf, falling back to raw binary +Booting at 80200000 +[ 0.000000] Linux version 6.12.22-linux4microchip+fpga-2025.07-g032a7095303a (oe-user@oe-host) (riscv64-oe-linux-gcc (GCC) 13.3.0, GNU ld (GNU Binutils) 2.42.0.20240723) #1 SMP Tue Jul 22 10:04:20 UTC 2025 +[ 0.000000] Machine model: Microchip PolarFire-SoC VIDEO Kit +[ 0.000000] SBI specification v1.0 detected +[ 0.000000] SBI implementation ID=0x8 Version=0x10002 +[ 0.000000] SBI TIME extension detected +[ 0.000000] SBI IPI extension detected +[ 0.000000] SBI RFENCE extension detected +[ 0.000000] SBI SRST extension detected +[ 0.000000] earlycon: ns16550a0 at MMIO32 0x0000000020100000 (options '115200n8') +... ``` ### PolarFire TODO -1) Add support for full HSS replacement using wolfboot. -2) Add support for eMMC and QSPI NOR flash - +* Add eMMC/SD features: + - Multi-block read (CMD18 support) + - DMA read support + - Write support + - eMMC support (not just SD) +* Add support for reading serial number and modifying ethernet MAC in device tree +* Add support for QSPI NOR flash +* Add support for full HSS replacement using wolfboot + - Machine level assembly startup + - DDR driver ## STM32F7 diff --git a/hal/mpfs.yaml b/hal/mpfs.yaml index ab397c940d..3f29d1d1d7 100644 --- a/hal/mpfs.yaml +++ b/hal/mpfs.yaml @@ -4,14 +4,13 @@ set-name: 'PolarFire-SoC-HSS::wolfBoot' hart-entry-points: { - u54_1: '0x80200000', - u54_2: '0x80200000', - u54_3: '0x80200000', - u54_4: '0x80200000' + u54_1: '0x80000000', + u54_2: '0x80000000', + u54_3: '0x80000000', + u54_4: '0x80000000' } payloads: wolfboot.elf: { - exec-addr: '0x80200000', owner-hart: u54_1, secondary-hart: u54_2, secondary-hart: u54_3, diff --git a/hal/mpfs250.its b/hal/mpfs250.its new file mode 100644 index 0000000000..f7465bba8e --- /dev/null +++ b/hal/mpfs250.its @@ -0,0 +1,44 @@ +/dts-v1/; + +/ { + description = "PolarFire SoC MPFS250T"; + #address-cells = <1>; + + images { + kernel-1 { + description = "Kernel Image"; + data = /incbin/("../kernel.bin"); + type = "kernel"; + arch = "riscv"; + os = "linux"; + compression = "none"; + load = <0x80200000>; + entry = <0x80200000>; + hash { + algo = "sha256"; + }; + }; + fdt-1 { + description = "Flattened Device Tree blob"; + data = /incbin/("mpfs.dtb"); + type = "flat_dt"; + arch = "riscv"; + compression = "none"; + load = <0x8a000000>; + hash { + algo = "sha256"; + }; + }; + }; + configurations { + default = "conf@1"; + conf@1 { + description = "PolarFire SoC MPFS250T"; + kernel = "kernel-1"; + fdt = "fdt-1"; + hash { + algo = "sha256"; + }; + }; + }; +}; \ No newline at end of file diff --git a/hal/mpfs250.ld b/hal/mpfs250.ld index 1542d663c8..49d1e6400b 100644 --- a/hal/mpfs250.ld +++ b/hal/mpfs250.ld @@ -9,7 +9,7 @@ MEMORY { /* The first 0x100 bytes of eNVM are used for boot ROM secure boot meta information */ FLASH_ENVM (rx) : ORIGIN = 0x20220100, LENGTH = 128k - 0x100 - DDR (rx) : ORIGIN = 0x80200000, LENGTH = 1028k + DDR (rx) : ORIGIN = 0x80000000, LENGTH = 1028k L2_SCRATCH (rwx) : ORIGIN = 0x0A000000, LENGTH = 256k } diff --git a/hal/zynq.c b/hal/zynq.c index 0585b6473a..2a0f3e187e 100644 --- a/hal/zynq.c +++ b/hal/zynq.c @@ -200,7 +200,7 @@ typedef struct pmu_aes { /* requires PMU built with -DENABLE_EFUSE_ACCESS=1 */ #define PM_EFUSE_ACCESS 0x35 typedef struct pmu_efuse { - uint64_t src; /* adress of data buffer */ + uint64_t src; /* address of data buffer */ uint32_t size; /* size in words */ uint32_t offset; /* offset */ uint32_t flag; /* 0: to read efuse, 1: to write efuse */ diff --git a/src/disk.c b/src/disk.c index 951febe03e..692e865e4c 100644 --- a/src/disk.c +++ b/src/disk.c @@ -226,7 +226,12 @@ int disk_part_read(int drv, int part, uint64_t off, uint64_t sz, uint8_t *buf) if (len < 0) { return -1; } + ret = disk_read(drv, p->start + off, len, buf); +#ifdef DEBUG_DISK + wolfBoot_printf("disk_part_read: drv: %d, part: %d, off: %llu, sz: %llu, " + "buf: %p, ret %d\r\n", drv, part, p->start + off, len, buf, ret); +#endif if (ret == 0) { ret = len; /* success expects to return the number of bytes read */ } @@ -262,6 +267,10 @@ int disk_part_write(int drv, int part, uint64_t off, uint64_t sz, const uint8_t return -1; } ret = disk_write(drv, p->start + off, len, buf); +#ifdef DEBUG_DISK + wolfBoot_printf("disk_part_write: drv: %d, part: %d, off: %llu, sz: %llu, " + "buf: %p, ret %d\r\n", drv, part, p->start + off, sz, buf, ret); +#endif if (ret == 0) { ret = len; /* success expects to return the number of bytes written */ } diff --git a/src/fdt.c b/src/fdt.c index 85259591ca..a688974259 100644 --- a/src/fdt.c +++ b/src/fdt.c @@ -836,7 +836,7 @@ void* fit_load_image(void* fdt, const char* image, int* lenp) image, data, load, len); memcpy(load, data, len); - /* load should always have entry, but if not use load adress */ + /* load should always have entry, but if not use load address */ data = (entry != NULL) ? entry : load; } wolfBoot_printf("Image %s: %p (%d bytes)\n", image, data, len); diff --git a/test-app/Makefile b/test-app/Makefile index c2480d63e6..de44353976 100644 --- a/test-app/Makefile +++ b/test-app/Makefile @@ -139,6 +139,10 @@ ifeq ($(ARCH),RISCV) APP_OBJS+=startup_riscv.o vector_riscv.o endif +ifeq ($(ARCH),RISCV64) + APP_OBJS+=startup_riscv.o vector_riscv.o +endif + ifeq ($(ARCH),ARM) APP_OBJS+=startup_arm.o endif diff --git a/test-app/RISCV64-mpfs250.ld b/test-app/RISCV64-mpfs250.ld index 975a44e606..7c6d6104d1 100644 --- a/test-app/RISCV64-mpfs250.ld +++ b/test-app/RISCV64-mpfs250.ld @@ -6,6 +6,10 @@ _Min_Heap_Size = 0x00002000; /* required amount of heap */ _Min_Stack_Size = 0x00002000; /* required amount of stack */ +OUTPUT_ARCH( "riscv" ) + +ENTRY( _reset ) + /* Memory areas */ MEMORY { @@ -24,6 +28,7 @@ SECTIONS { . = ALIGN(8); KEEP(*(.isr_vector)) /* Startup code */ + _start_vector = .; . = ALIGN(8); } >IRAM diff --git a/test-app/app_mpfs250.c b/test-app/app_mpfs250.c index 49513c1752..57d219b817 100644 --- a/test-app/app_mpfs250.c +++ b/test-app/app_mpfs250.c @@ -36,6 +36,7 @@ void main(void) { + uart_init(); hal_init(); wolfBoot_printf("========================\r\n"); From 49fafd8eec7d47ad6ab473f32516e5e1cd9bbcc6 Mon Sep 17 00:00:00 2001 From: David Garske Date: Tue, 23 Dec 2025 11:34:06 -0800 Subject: [PATCH 10/13] Documentation cleanups --- docs/Targets.md | 101 ++++++++++++++++++++++++++---------------------- hal/mpfs250.its | 14 +++---- 2 files changed, 62 insertions(+), 53 deletions(-) diff --git a/docs/Targets.md b/docs/Targets.md index b44ca7bb65..ae190a4978 100644 --- a/docs/Targets.md +++ b/docs/Targets.md @@ -799,9 +799,9 @@ The PolarFire SoC is a 64-bit RISC-V SoC featuring a five-core CPU cluster (1× `hal/mpfs250.ld` - Linker script for the platform `hal/mpfs.dts` / `hal/mpfs.dtb` - Device tree source and binary `hal/mpfs.yaml` - HSS payload generator configuration -`hal/mpfs250.its` - For creating new FIT images with Kernel and DTB +`hal/mpfs250.its` - Example FIT image creation template -### Building PolarFire SoC +### PolarFire SoC Building wolfBoot All build settings come from .config file. For this platform use `TARGET=mpfs250` and `ARCH=RISCV64`. @@ -826,6 +826,10 @@ make sudo cp hss-payload-generator /usr/local/bin/ ``` +The HSS MMC boot source looks for GPT with GUID "21686148-6449-6E6F-744E-656564454649" or sector "0" if no GPT found. That GUID is the default "BIOS" boot partition. + +The resulting image from `hss-payload-generator` can be directly placed into GPT BIOS partition. + Use this command to assemble a bootable wolfboot image: ```sh @@ -837,24 +841,20 @@ Any customizations to the Device Tree can be made in mpfs.dts and it can be reco Example one-shot command: ```sh -cp ./config/examples/polarfire_mpfs250.config .config && make clean && make wolfboot.elf && size wolfboot.elf && hss-payload-generator -vvv -c ./hal/mpfs.yaml wolfboot.bin && file wolfboot.bin && ls -la wolfboot.bin +cp ./config/examples/polarfire_mpfs250.config .config && make clean && make wolfboot.elf && size wolfboot.elf && hss-payload-generator -vvv -c ./hal/mpfs.yaml wolfboot.bin ``` -### Flashing PolarFire SoC - -The HSS MMC boot source looks for GPT with GUID "21686148-6449-6E6F-744E-656564454649" or sector "0" if no GPT found. That GUID is the default "BIOS" boot partition. - -The resulting image from `hss-payload-generator` can be directly placed into GPT BIOS partition. The HSS tinyCLI supports the `USBDMSC` command to mount the eMMC or SD card as a USB device. You can then use "dd" to copy the boot image to the BOOT partition 2. Example: +The HSS tinyCLI supports the `USBDMSC` command to mount the eMMC or SD card as a USB device. You can then use "dd" to copy the boot image to the BOOT partition. Use `lsblk` to locate the boot partition and replace /dev/sdc1 in the example: ```sh sudo dd if=wolfboot.bin of=/dev/sdc1 bs=512 && sudo cmp wolfboot.bin /dev/sdc1 ``` -### PolarFire testing +Note: -This section describes how to build the test-application, create a custom uSD with required partitions and copying signing test-application to uSD partitions. +### PolarFire testing -To use your own application (Linux FIT Image, ELF, etc) just replace test-app/image.elf with your own file (example "fitImage"). +This section describes how to build the test-application, create a custom uSD with required partitions and copying signed test-application to uSD partitions. 1) Partition uSD card (replace /dev/sdc with your actual media, find using `lsblk`): @@ -914,6 +914,7 @@ Device Start End Sectors Size Type ``` 2) Build, Sign and copy images + ```sh # make test-app make test-app/image.elf @@ -921,45 +922,44 @@ make test-app/image.elf # Sign test-app/image with version 1 ./tools/keytools/sign --ecc384 --sha384 test-app/image.elf wolfboot_signing_private_key.der 1 sudo dd if=test-app/image_v1_signed.bin of=/dev/sdc2 bs=512 && sudo cmp test-app/image_v1_signed.bin /dev/sdc2 +``` -# OR +4) Insert SDCARD into PolarFire and let HSS start wolfBoot. You may need to use `boot sdcard` or configure/build HSS to disable MMC / enable SDCARD. -# Sign FIT image with version 1 -./tools/keytools/sign --ecc384 --sha384 fitImage wolfboot_signing_private_key.der 1 -sudo dd if=fitImage_v1_signed.bin of=/dev/sdc2 bs=512 && sudo cmp fitImage_v1_signed.bin /dev/sdc2 +### PolarFire building Yocto-SDK Linux -# Copy root file system -sudo fdisk -l mchp-base-image-mpfs-video-kit.rootfs-20250725105640.wic -sudo dd if=mchp-base-image-mpfs-video-kit.rootfs-20250725105640.wic skip=155648 of=/dev/sdc4 bs=512 count=944898 status=progress +See: +* https://github.com/linux4microchip/meta-mchp/blob/scarthgap/meta-mchp-common/README.md +* https://github.com/linux4microchip/meta-mchp/blob/scarthgap/meta-mchp-polarfire-soc/README.md + +Building mchp-base-image Yocto Linux: + +```sh +cd yocto-dev-polarfire/ +export TEMPLATECONF=${TEMPLATECONF:-../meta-mchp/meta-mchp-polarfire-soc/meta-mchp-polarfire-soc-bsp/conf/templates/default} +source openembedded-core/oe-init-build-env +# A Microchip base image with standard Linux utilities, as well as some Microchip apps and examples +MACHINE=mpfs-video-kit bitbake mchp-base-image +OR +# A Microchip base image with additional support for software development, including toolchains and debug tools +MACHINE=mpfs-video-kit bitbake mchp-base-image-sdk ``` -4) Insert SDCARD into PolarFire and let HSS start wolfBoot. You may need to use `boot sdcard` or configure/build HSS to disable MMC / enable SDCARD. +Build images are output to: `./tmp-glibc/deploy/images/mpfs-video-kit/` -### FIT Image Creation (decompress Linux Kernel Image) +#### Building custom FIT image, signing and coping to SDCard ```sh -$ dumpimage -l fitImage -$ dumpimage -T flat_dt -p 0 fitImage -o kernel.gz -Extracted: - Image 0 (kernel-1) - Description: Linux kernel - Created: Tue Jul 22 03:04:20 2025 - Type: Kernel Image - Compression: gzip compressed - Data Size: 5831831 Bytes = 5695.15 KiB = 5.56 MiB - Architecture: RISC-V - OS: Linux - Load Address: 0x80200000 - Entry Point: 0x80200000 - Hash algo: sha256 - Hash value: 296034c3100d21e6edc417d2406c9d27ec6578fa03c4e333307d0b0b65e0092b -$ gzip -cdvk kernel.gz > kernel.bin -$ mkimage -f hal/mpfs250.its fitImageNew +# Extract GZIP compressed linux kernel to wolfboot root +gzip -cdvk ../yocto-dev-polarfire/build/tmp-glibc/work/mpfs_video_kit-oe-linux/linux-mchp/6.12.22+git/build/linux.bin > kernel.bin + +# Create custom FIT image +mkimage -f hal/mpfs250.its fitImage FIT description: PolarFire SoC MPFS250T -Created: Mon Dec 22 15:29:32 2025 +Created: Tue Dec 23 11:29:02 2025 Image 0 (kernel-1) - Description: Kernel Image - Created: Mon Dec 22 15:29:32 2025 + Description: Linux Kernel + Created: Tue Dec 23 11:29:02 2025 Type: Kernel Image Compression: uncompressed Data Size: 19745280 Bytes = 19282.50 KiB = 18.83 MiB @@ -971,7 +971,7 @@ Created: Mon Dec 22 15:29:32 2025 Hash value: 800ce147fa91f367ec620936a59a1035c49971ed4b9080c96bdc547471e80487 Image 1 (fdt-1) Description: Flattened Device Tree blob - Created: Mon Dec 22 15:29:32 2025 + Created: Tue Dec 23 11:29:02 2025 Type: Flat Device Tree Compression: uncompressed Data Size: 19897 Bytes = 19.43 KiB = 0.02 MiB @@ -979,16 +979,26 @@ Created: Mon Dec 22 15:29:32 2025 Load Address: 0x8a000000 Hash algo: sha256 Hash value: 0b4efca8c0607c9a8f4f9a00ccb7691936e019f3181aab45e6d52dae91975039 - Default Configuration: 'conf@1' - Configuration 0 (conf@1) - Description: PolarFire SoC MPFS250T + Default Configuration: 'conf1' + Configuration 0 (conf1) + Description: Linux kernel and FDT blob Kernel: kernel-1 FDT: fdt-1 Hash algo: sha256 Hash value: unavailable + +# Sign FIT image with version 1 +./tools/keytools/sign --ecc384 --sha384 fitImage wolfboot_signing_private_key.der 1 + +# Copy signed FIT image to both OFP A/B partitions +sudo dd if=fitImage_v1_signed.bin of=/dev/sdc2 bs=512 status=progress && sudo cmp fitImage_v1_signed.bin /dev/sdc2 +sudo dd if=fitImage_v1_signed.bin of=/dev/sdc3 bs=512 status=progress && sudo cmp fitImage_v1_signed.bin /dev/sdc3 + +# Copy root file system +sudo dd if=../yocto-dev-polarfire/build/tmp-glibc/deploy/images/mpfs-video-kit/mchp-base-image-sdk-mpfs-video-kit.rootfs.ext4 of=/dev/sdb4 bs=512 status=progress ``` -### Debugging PolarFire Soc +### PolarFire Soc Debugging Start GDB server: @@ -1063,7 +1073,6 @@ Booting at 80200000 ... ``` - ### PolarFire TODO * Add eMMC/SD features: diff --git a/hal/mpfs250.its b/hal/mpfs250.its index f7465bba8e..9f4b609972 100644 --- a/hal/mpfs250.its +++ b/hal/mpfs250.its @@ -6,7 +6,7 @@ images { kernel-1 { - description = "Kernel Image"; + description = "Linux Kernel"; data = /incbin/("../kernel.bin"); type = "kernel"; arch = "riscv"; @@ -14,7 +14,7 @@ compression = "none"; load = <0x80200000>; entry = <0x80200000>; - hash { + hash-1 { algo = "sha256"; }; }; @@ -25,18 +25,18 @@ arch = "riscv"; compression = "none"; load = <0x8a000000>; - hash { + hash-1 { algo = "sha256"; }; }; }; configurations { - default = "conf@1"; - conf@1 { - description = "PolarFire SoC MPFS250T"; + default = "conf1"; + conf1 { + description = "Linux kernel and FDT blob"; kernel = "kernel-1"; fdt = "fdt-1"; - hash { + hash-1 { algo = "sha256"; }; }; From 363b62de5fe3bf1f27e4206eea7efdc1ad677020 Mon Sep 17 00:00:00 2001 From: David Garske Date: Tue, 23 Dec 2025 11:57:51 -0800 Subject: [PATCH 11/13] Peer review fixes --- .../e2studio/RZN2L/flash_app/src/Flash_wrappedkey_public.s | 2 +- docs/Targets.md | 5 +++-- hal/armv8m_tz.h | 2 +- hal/hifive1.c | 6 ++---- hal/mpfs250.c | 2 +- hal/mpfs250.h | 2 +- hal/mpfs250.ld | 2 +- hal/nxp_ls1028a.c | 2 +- hal/nxp_ls1028a.h | 2 +- hal/nxp_p1021.c | 2 +- hal/stm32h5.c | 2 +- hal/stm32h5.h | 2 +- hal/va416x0.h | 2 +- include/x86/exceptions.h | 2 +- include/x86/fsp.h | 2 +- include/x86/gdt.h | 2 +- src/stage2_params.c | 4 ++-- src/x86/exceptions.c | 2 +- src/x86/fsp.c | 2 +- src/x86/gdt.c | 4 ++-- test-app/app_nxp_ls1028a.c | 2 +- test-app/app_stm32h5.c | 2 +- test-app/app_x86_fsp_qemu.c | 2 +- 23 files changed, 28 insertions(+), 29 deletions(-) diff --git a/IDE/Renesas/e2studio/RZN2L/flash_app/src/Flash_wrappedkey_public.s b/IDE/Renesas/e2studio/RZN2L/flash_app/src/Flash_wrappedkey_public.s index 415e8816d2..67b3e67810 100644 --- a/IDE/Renesas/e2studio/RZN2L/flash_app/src/Flash_wrappedkey_public.s +++ b/IDE/Renesas/e2studio/RZN2L/flash_app/src/Flash_wrappedkey_public.s @@ -6,7 +6,7 @@ * * 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 + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * wolfBoot is distributed in the hope that it will be useful, diff --git a/docs/Targets.md b/docs/Targets.md index ae190a4978..13d80ce959 100644 --- a/docs/Targets.md +++ b/docs/Targets.md @@ -926,11 +926,12 @@ sudo dd if=test-app/image_v1_signed.bin of=/dev/sdc2 bs=512 && sudo cmp test-app 4) Insert SDCARD into PolarFire and let HSS start wolfBoot. You may need to use `boot sdcard` or configure/build HSS to disable MMC / enable SDCARD. -### PolarFire building Yocto-SDK Linux +### PolarFire Building Yocto-SDK Linux See: * https://github.com/linux4microchip/meta-mchp/blob/scarthgap/meta-mchp-common/README.md * https://github.com/linux4microchip/meta-mchp/blob/scarthgap/meta-mchp-polarfire-soc/README.md +* https://github.com/polarfire-soc/polarfire-soc-documentation/blob/master/reference-designs-fpga-and-development-kits/mpfs-video-kit-embedded-software-user-guide.md Building mchp-base-image Yocto Linux: @@ -947,7 +948,7 @@ MACHINE=mpfs-video-kit bitbake mchp-base-image-sdk Build images are output to: `./tmp-glibc/deploy/images/mpfs-video-kit/` -#### Building custom FIT image, signing and coping to SDCard +#### Custom FIT image, signing and coping to SDCard ```sh # Extract GZIP compressed linux kernel to wolfboot root diff --git a/hal/armv8m_tz.h b/hal/armv8m_tz.h index 975cc155c8..1f5286cd6a 100644 --- a/hal/armv8m_tz.h +++ b/hal/armv8m_tz.h @@ -6,7 +6,7 @@ * * 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 + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * wolfBoot is distributed in the hope that it will be useful, diff --git a/hal/hifive1.c b/hal/hifive1.c index a7b10666f6..94c6da4825 100644 --- a/hal/hifive1.c +++ b/hal/hifive1.c @@ -269,7 +269,7 @@ void fespi_init(uint32_t cpu_clock, uint32_t flash_freq) static RAMFUNCTION void fespi_swmode(void) { asm volatile("fence"); - + asm volatile("fence.i"); if (FESPI_REG_FCTRL & FESPI_FCTRL_MODE_SEL) FESPI_REG_FCTRL &= ~FESPI_FCTRL_MODE_SEL; } @@ -280,7 +280,7 @@ static RAMFUNCTION void fespi_hwmode(void) if ((FESPI_REG_FCTRL & FESPI_FCTRL_MODE_SEL) == 0) FESPI_REG_FCTRL |= FESPI_FCTRL_MODE_SEL; asm volatile("fence"); - + asm volatile("fence.i"); /* Wait two milliseconds for the eSPI device * to reboot into hw-mapped mode and link to the * instruction cache @@ -575,13 +575,11 @@ int RAMFUNCTION hal_flash_erase(uint32_t address, int len) address -= FLASH_BASE; end = address + len - 1; - FESPI_REG_TXMARK = 1; fespi_wait_txwm(); fespi_swmode(); fespi_wait_flash_busy(); - for (p = address; p <= end; p += FESPI_FLASH_SECTOR_SIZE) { fespi_write_enable(); fespi_csmode_hold(); diff --git a/hal/mpfs250.c b/hal/mpfs250.c index b23500673c..f0865f3d37 100644 --- a/hal/mpfs250.c +++ b/hal/mpfs250.c @@ -861,7 +861,7 @@ int mmc_init(void) reg |= EMMC_SD_SRS15_DSS_TYPE_B; /* default */ EMMC_SD_SRS15 = reg; - /* eanble high speed */ + /* enable high speed */ EMMC_SD_SRS10 |= EMMC_SD_SRS10_HSE; /* set UHS mode */ diff --git a/hal/mpfs250.h b/hal/mpfs250.h index 2c4c7c2efd..0066e24f37 100644 --- a/hal/mpfs250.h +++ b/hal/mpfs250.h @@ -6,7 +6,7 @@ * * 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 + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * wolfBoot is distributed in the hope that it will be useful, diff --git a/hal/mpfs250.ld b/hal/mpfs250.ld index 49d1e6400b..732b8c5088 100644 --- a/hal/mpfs250.ld +++ b/hal/mpfs250.ld @@ -57,4 +57,4 @@ SECTIONS } PROVIDE(_start_heap = _end); -PROVIDE(_end_stack = ORIGIN(RAM_L2_SCRATCH) + (LENGTH(RAM_L2_SCRATCH)) ); +PROVIDE(_end_stack = ORIGIN(L2_SCRATCH) + (LENGTH(L2_SCRATCH)) ); diff --git a/hal/nxp_ls1028a.c b/hal/nxp_ls1028a.c index d886a217dd..fb39f977c5 100644 --- a/hal/nxp_ls1028a.c +++ b/hal/nxp_ls1028a.c @@ -6,7 +6,7 @@ * * 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 + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * wolfBoot is distributed in the hope that it will be useful, diff --git a/hal/nxp_ls1028a.h b/hal/nxp_ls1028a.h index b383f277ca..17fbdcb65d 100644 --- a/hal/nxp_ls1028a.h +++ b/hal/nxp_ls1028a.h @@ -6,7 +6,7 @@ * * 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 + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * wolfBoot is distributed in the hope that it will be useful, diff --git a/hal/nxp_p1021.c b/hal/nxp_p1021.c index c96b9ef79e..7b173e9575 100644 --- a/hal/nxp_p1021.c +++ b/hal/nxp_p1021.c @@ -1564,7 +1564,7 @@ static void hal_irq_init(void) set32(PIC_GCR, PIC_GCR_RST); while (get32(PIC_GCR) & PIC_GCR_RST); - set32(PIC_GCR, PIC_GCR_M); /* eanble mixed-mode */ + set32(PIC_GCR, PIC_GCR_M); /* enable mixed-mode */ reg = get32(PIC_GCR); /* read back */ (void)reg; } diff --git a/hal/stm32h5.c b/hal/stm32h5.c index c271ae81bd..14b7913594 100644 --- a/hal/stm32h5.c +++ b/hal/stm32h5.c @@ -6,7 +6,7 @@ * * 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 + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * wolfBoot is distributed in the hope that it will be useful, diff --git a/hal/stm32h5.h b/hal/stm32h5.h index c6f9478eb7..e87f894a83 100644 --- a/hal/stm32h5.h +++ b/hal/stm32h5.h @@ -6,7 +6,7 @@ * * 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 + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * wolfBoot is distributed in the hope that it will be useful, diff --git a/hal/va416x0.h b/hal/va416x0.h index e86de44663..74d4d39be3 100644 --- a/hal/va416x0.h +++ b/hal/va416x0.h @@ -6,7 +6,7 @@ * * 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 + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * wolfBoot is distributed in the hope that it will be useful, diff --git a/include/x86/exceptions.h b/include/x86/exceptions.h index 3097ab815b..e0452208dc 100644 --- a/include/x86/exceptions.h +++ b/include/x86/exceptions.h @@ -6,7 +6,7 @@ * * 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 + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * wolfBoot is distributed in the hope that it will be useful, diff --git a/include/x86/fsp.h b/include/x86/fsp.h index cbd42f70b0..bfd8a3dca1 100644 --- a/include/x86/fsp.h +++ b/include/x86/fsp.h @@ -6,7 +6,7 @@ * * 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 + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * wolfBoot is distributed in the hope that it will be useful, diff --git a/include/x86/gdt.h b/include/x86/gdt.h index 3b74d4dbe4..720885c727 100644 --- a/include/x86/gdt.h +++ b/include/x86/gdt.h @@ -6,7 +6,7 @@ * * 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 + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * wolfBoot is distributed in the hope that it will be useful, diff --git a/src/stage2_params.c b/src/stage2_params.c index fd13252f80..069b9e9da6 100644 --- a/src/stage2_params.c +++ b/src/stage2_params.c @@ -6,7 +6,7 @@ * * 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 + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * wolfBoot is distributed in the hope that it will be useful, @@ -80,7 +80,7 @@ struct idt_descriptor { void stage2_set_parameters(struct stage2_parameter *p, struct stage2_ptr_holder *holder) { struct idt_descriptor idt; - + idt.limit = sizeof(holder->dummy_idt) - 1; idt.base = (uint32_t)&holder->dummy_idt; memset(holder->dummy_idt, 0, sizeof(holder->dummy_idt)); diff --git a/src/x86/exceptions.c b/src/x86/exceptions.c index 761ac9de90..c9cdaab9c1 100644 --- a/src/x86/exceptions.c +++ b/src/x86/exceptions.c @@ -6,7 +6,7 @@ * * 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 + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * wolfBoot is distributed in the hope that it will be useful, diff --git a/src/x86/fsp.c b/src/x86/fsp.c index 28e944d498..e21e499e33 100644 --- a/src/x86/fsp.c +++ b/src/x86/fsp.c @@ -6,7 +6,7 @@ * * 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 + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * wolfBoot is distributed in the hope that it will be useful, diff --git a/src/x86/gdt.c b/src/x86/gdt.c index ee2fcbeb9d..df09306658 100644 --- a/src/x86/gdt.c +++ b/src/x86/gdt.c @@ -6,7 +6,7 @@ * * 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 + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * wolfBoot is distributed in the hope that it will be useful, @@ -89,7 +89,7 @@ int gdt_update_segments(void) "retfq\r\n" "seg_cs:\r\n" : - : "i"(GDT_DS), "i" (GDT_CS_64BIT) + : "i"(GDT_DS), "i" (GDT_CS_64BIT) : "rax" ); return 0; diff --git a/test-app/app_nxp_ls1028a.c b/test-app/app_nxp_ls1028a.c index e90028906a..3502e941ef 100644 --- a/test-app/app_nxp_ls1028a.c +++ b/test-app/app_nxp_ls1028a.c @@ -6,7 +6,7 @@ * * 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 + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * wolfBoot is distributed in the hope that it will be useful, diff --git a/test-app/app_stm32h5.c b/test-app/app_stm32h5.c index ddf199c987..787ea59ace 100644 --- a/test-app/app_stm32h5.c +++ b/test-app/app_stm32h5.c @@ -8,7 +8,7 @@ * * 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 + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * wolfBoot is distributed in the hope that it will be useful, diff --git a/test-app/app_x86_fsp_qemu.c b/test-app/app_x86_fsp_qemu.c index eb50fdcc4e..feed83eba3 100644 --- a/test-app/app_x86_fsp_qemu.c +++ b/test-app/app_x86_fsp_qemu.c @@ -8,7 +8,7 @@ * * 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 + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * wolfBoot is distributed in the hope that it will be useful, From d76c6bcd62d072ad4f58b4a506229381d4b4e2db Mon Sep 17 00:00:00 2001 From: David Garske Date: Tue, 23 Dec 2025 17:13:42 -0800 Subject: [PATCH 12/13] Add support for multi-block reads (performance improvements) --- arch.mk | 1 + config/examples/polarfire_mpfs250.config | 2 + docs/Targets.md | 7 ++- hal/mpfs250.c | 77 ++++++++++++++++-------- hal/mpfs250.h | 8 +-- 5 files changed, 63 insertions(+), 32 deletions(-) diff --git a/arch.mk b/arch.mk index 838cade67d..c14284ed19 100644 --- a/arch.mk +++ b/arch.mk @@ -586,6 +586,7 @@ ifeq ($(ARCH),RISCV64) endif ifneq ($(NO_ASM),1) + CFLAGS+=-DWOLFSSL_RISCV_ASM MATH_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/riscv/riscv-64-sha256.o \ $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/riscv/riscv-64-sha512.o \ $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/riscv/riscv-64-sha3.o \ diff --git a/config/examples/polarfire_mpfs250.config b/config/examples/polarfire_mpfs250.config index 2b05d8e21a..6d44badf8f 100644 --- a/config/examples/polarfire_mpfs250.config +++ b/config/examples/polarfire_mpfs250.config @@ -46,6 +46,8 @@ WOLFBOOT_LOAD_ADDRESS?=0x8E000000 WOLFBOOT_NO_PARTITIONS=1 CFLAGS_EXTRA+=-DBOOT_PART_A=1 CFLAGS_EXTRA+=-DBOOT_PART_B=2 +# Speed up disk partition read (1MB chunks) +CFLAGS_EXTRA+=-DDISK_BLOCK_SIZE=0x100000 # DTS (Device Tree) WOLFBOOT_LOAD_DTS_ADDRESS?=0x8A000000 diff --git a/docs/Targets.md b/docs/Targets.md index 13d80ce959..d28018340b 100644 --- a/docs/Targets.md +++ b/docs/Targets.md @@ -936,7 +936,10 @@ See: Building mchp-base-image Yocto Linux: ```sh -cd yocto-dev-polarfire/ +mkdir ../yocto-dev-polarfire +cd ../yocto-dev-polarfire +repo init -u https://github.com/linux4microchip/meta-mchp-manifest.git -b refs/tags/linux4microchip+fpga-2025.10 -m polarfire-soc/default.xml +repo sync export TEMPLATECONF=${TEMPLATECONF:-../meta-mchp/meta-mchp-polarfire-soc/meta-mchp-polarfire-soc-bsp/conf/templates/default} source openembedded-core/oe-init-build-env # A Microchip base image with standard Linux utilities, as well as some Microchip apps and examples @@ -1077,7 +1080,7 @@ Booting at 80200000 ### PolarFire TODO * Add eMMC/SD features: - - Multi-block read (CMD18 support) + - Improve mmc_delay and timeout handling - DMA read support - Write support - eMMC support (not just SD) diff --git a/hal/mpfs250.c b/hal/mpfs250.c index f0865f3d37..aef12dd804 100644 --- a/hal/mpfs250.c +++ b/hal/mpfs250.c @@ -456,7 +456,8 @@ int mmc_read(uint32_t cmd_index, uint32_t block_addr, uint32_t* dst, uint32_t sz) { int status; - uint32_t reg; + uint32_t block_count; + uint32_t reg, cmd_reg; /* wait for idle */ status = mmc_wait_busy(0); @@ -468,46 +469,66 @@ int mmc_read(uint32_t cmd_index, uint32_t block_addr, uint32_t* dst, /* wait for command and data line busy to clear */ while ((EMMC_SD_SRS09 & (EMMC_SD_SRS09_CICMD | EMMC_SD_SRS09_CIDAT)) != 0); + /* get block count (round up) */ + block_count = (sz + (EMMC_SD_BLOCK_SIZE - 1)) / EMMC_SD_BLOCK_SIZE; /* set transfer block count */ - EMMC_SD_SRS01 = (1 << EMMC_SD_SRS01_BCCT_SHIFT) | sz; + EMMC_SD_SRS01 = (block_count << EMMC_SD_SRS01_BCCT_SHIFT) | sz; + + cmd_reg = ((cmd_index << EMMC_SD_SRS03_CIDX_SHIFT) | + EMMC_SD_SRS03_DPS | EMMC_SD_SRS03_DTDS | + EMMC_SD_SRS03_BCE | EMMC_SD_SRS03_RECE | EMMC_SD_SRS03_RID | + EMMC_SD_SRS03_RESP_48 | EMMC_SD_SRS03_CRCCE | EMMC_SD_SRS03_CICE); if (cmd_index == SD_ACMD51_SEND_SCR) { - status = mmc_send_cmd(SD_CMD_16, sz, EMMC_SD_RESP_R1); + status = mmc_send_cmd(SD_CMD16, sz, EMMC_SD_RESP_R1); if (status == 0) { status = mmc_send_cmd(SD_CMD55_APP_CMD, (g_rca << SD_RCA_SHIFT), EMMC_SD_RESP_R1); } status = 0; /* ignore error */ } + else if (cmd_index == MMC_CMD18_READ_MULTIPLE) { + cmd_reg |= EMMC_SD_SRS03_MSBS; /* enable multi-block select */ + EMMC_SD_SRS01 = (block_count << EMMC_SD_SRS01_BCCT_SHIFT) | + EMMC_SD_BLOCK_SIZE; + } #ifdef DEBUG_MMC - wolfBoot_printf("mmc_read: cmd_index: %d, block_addr: %08X, dst %p, sz: %d\n", - cmd_index, block_addr, dst, sz); + wolfBoot_printf("mmc_read: cmd_index: %d, block_addr: %08X, dst %p, sz: %d (%d blocks)\n", + cmd_index, block_addr, dst, sz, block_count); #endif EMMC_SD_SRS02 = block_addr; /* cmd argument */ - /* execute command */ - EMMC_SD_SRS03 = ((cmd_index << EMMC_SD_SRS03_CIDX_SHIFT) | - EMMC_SD_SRS03_DPS | EMMC_SD_SRS03_DTDS | - EMMC_SD_SRS03_BCE | EMMC_SD_SRS03_RECE | EMMC_SD_SRS03_RID | - EMMC_SD_SRS03_RESP_48 | EMMC_SD_SRS03_CRCCE | EMMC_SD_SRS03_CICE); - - /* wait for buffer read ready */ - while (((reg = EMMC_SD_SRS12) & (EMMC_SD_SRS12_BRR | EMMC_SD_SRS12_EINT)) == 0); - - /* read in buffer - read 4 bytes at a time */ - if (reg & EMMC_SD_SRS12_BRR) { - uint32_t i; - for (i=0; i 0) { + /* wait for buffer read ready */ + while (((reg = EMMC_SD_SRS12) & + (EMMC_SD_SRS12_BRR | EMMC_SD_SRS12_EINT)) == 0); + + /* read in buffer - read 4 bytes at a time */ + if (reg & EMMC_SD_SRS12_BRR) { + uint32_t i, read_sz = sz; + if (read_sz > EMMC_SD_BLOCK_SIZE) { + read_sz = EMMC_SD_BLOCK_SIZE; + } + for (i=0; i 1 ? + MMC_CMD18_READ_MULTIPLE : + MMC_CMD17_READ_SINGLE, + block_addr, (uint32_t*)buf, read_sz); } if (status != 0) { break; diff --git a/hal/mpfs250.h b/hal/mpfs250.h index 0066e24f37..af48aab2a6 100644 --- a/hal/mpfs250.h +++ b/hal/mpfs250.h @@ -837,8 +837,8 @@ #define MMC_CMD1_SEND_OP_COND 1 /* MMC: Send operating conditions */ #define MMC_CMD2_ALL_SEND_CID 2 /* Get card identification */ #define MMC_CMD3_SET_REL_ADDR 3 /* Set relative address */ -#define MMC_CMD_4_SET_DSR 4 -#define SD_CMD_6_SWITCH_FUNC 6 /* SD: Switch function */ +#define MMC_CMD4_SET_DSR 4 +#define SD_CMD6_SWITCH_FUNC 6 /* SD: Switch function */ #define MMC_CMD7_SELECT_CARD 7 /* Select/deselect card */ #define MMC_CMD8_SEND_EXT_CSD 8 /* MMC: Get EXT_CSD */ #define SD_CMD8_SEND_IF_COND 8 /* SD: Send interface condition */ @@ -846,8 +846,8 @@ #define SD_CMD11_VOLAGE_SWITCH 11 /* R1 Rsp */ #define MMC_CMD12_STOP_TRANS 12 /* Stop transmission */ #define MMC_CMD13_SEND_STATUS 13 /* Get card status */ -#define MMC_CMD_15_GOTO_INACT_ST 15 -#define SD_CMD_16 16 /* R1 Rsp */ +#define MMC_CMD15_GOTO_INACT_ST 15 +#define SD_CMD16 16 /* R1 Rsp */ #define MMC_CMD17_READ_SINGLE 17 /* Read single block */ #define MMC_CMD18_READ_MULTIPLE 18 /* Read multiple blocks */ #define MMC_CMD24_WRITE_SINGLE 24 /* Write single block */ From dddc195b887ab1009210140681be7f7266dfa0ef Mon Sep 17 00:00:00 2001 From: David Garske Date: Wed, 24 Dec 2025 09:10:25 -0800 Subject: [PATCH 13/13] Peer review fixes --- config/examples/polarfire_mpfs250.config | 6 ++++-- docs/Targets.md | 10 +++++++--- hal/mpfs250.c | 13 ++++++------- hal/mpfs250.ld | 3 ++- tools/scripts/x86_fsp/qemu/qemu.sh | 8 +++++++- 5 files changed, 26 insertions(+), 14 deletions(-) diff --git a/config/examples/polarfire_mpfs250.config b/config/examples/polarfire_mpfs250.config index 6d44badf8f..7a709403a6 100644 --- a/config/examples/polarfire_mpfs250.config +++ b/config/examples/polarfire_mpfs250.config @@ -28,13 +28,15 @@ ELF?=1 # Optionally allow downgrade to older valid version in update partition ALLOW_DOWNGRADE?=0 -# Use assembly version of ECDSA and SHA +# Use RISC-V assembly version of ECDSA and SHA NO_ASM?=0 NO_ARM_ASM?=0 - # Optional: Use smaller SHA512 #CFLAGS_EXTRA+=-DUSE_SLOW_SHA512 +# DDR Address for wolfBoot to start from +WOLFBOOT_ORIGIN?=0x80000000 + # Flash sector size (4KB typical) WOLFBOOT_SECTOR_SIZE?=0x1000 diff --git a/docs/Targets.md b/docs/Targets.md index d28018340b..013c934258 100644 --- a/docs/Targets.md +++ b/docs/Targets.md @@ -797,7 +797,7 @@ The PolarFire SoC is a 64-bit RISC-V SoC featuring a five-core CPU cluster (1× `hal/mpfs250.c` - Hardware abstraction layer implementation (UART and uSD) `hal/mpfs250.h` - Register definitions and hardware interfaces `hal/mpfs250.ld` - Linker script for the platform -`hal/mpfs.dts` / `hal/mpfs.dtb` - Device tree source and binary +`hal/mpfs.dts` - Device tree source `hal/mpfs.yaml` - HSS payload generator configuration `hal/mpfs250.its` - Example FIT image creation template @@ -836,12 +836,16 @@ Use this command to assemble a bootable wolfboot image: hss-payload-generator -vvv -c ./hal/mpfs.yaml wolfboot.bin ``` -Any customizations to the Device Tree can be made in mpfs.dts and it can be recompiled using: `dtc -I dts -O dtb mpfs.dts -o mpfs.dtb` +You must generated the Device Tree Binary using: + +```sh +dtc -I dts -O dtb hal/mpfs.dts -o hal/mpfs.dtb` +``` Example one-shot command: ```sh -cp ./config/examples/polarfire_mpfs250.config .config && make clean && make wolfboot.elf && size wolfboot.elf && hss-payload-generator -vvv -c ./hal/mpfs.yaml wolfboot.bin +cp ./config/examples/polarfire_mpfs250.config .config && make clean && make wolfboot.elf && size wolfboot.elf && dtc -I dts -O dtb hal/mpfs.dts -o hal/mpfs.dtb && hss-payload-generator -vvv -c ./hal/mpfs.yaml wolfboot.bin ``` The HSS tinyCLI supports the `USBDMSC` command to mount the eMMC or SD card as a USB device. You can then use "dd" to copy the boot image to the BOOT partition. Use `lsblk` to locate the boot partition and replace /dev/sdc1 in the example: diff --git a/hal/mpfs250.c b/hal/mpfs250.c index aef12dd804..ef80fee784 100644 --- a/hal/mpfs250.c +++ b/hal/mpfs250.c @@ -144,7 +144,7 @@ static uint32_t g_rca = 0; /* SD Card Relative Address */ #define DEFAULT_DELAY 0xFFFF #endif -int mmc_set_timeout(uint32_t timeout_us) +static int mmc_set_timeout(uint32_t timeout_us) { uint32_t reg, i, tcfclk, tcfclk_mhz, tcfclk_khz, timeout_val, dtcv; @@ -198,8 +198,7 @@ int mmc_set_timeout(uint32_t timeout_us) return 0; } -/* TODO: Fix with real timer */ -void mmc_delay(uint32_t delay) +static void mmc_delay(uint32_t delay) { while (delay--) { asm volatile("nop"); @@ -212,7 +211,7 @@ void mmc_delay(uint32_t delay) * EMMC_SD_SRS10_BVS_3_0V * EMMC_SD_SRS10_BVS_3_3V */ -int mmc_set_power(uint32_t voltage) +static int mmc_set_power(uint32_t voltage) { uint32_t reg; @@ -248,7 +247,7 @@ int mmc_set_power(uint32_t voltage) } /* returns actual frequency in kHz */ -uint32_t mmc_set_clock(uint32_t clock_khz) +static uint32_t mmc_set_clock(uint32_t clock_khz) { static uint32_t last_clock_khz = 0; uint32_t reg, base_clk_khz, i, mclk, freq_khz; @@ -355,7 +354,7 @@ int mmc_send_cmd(uint32_t cmd_index, uint32_t cmd_arg, uint8_t resp_type) { int status = 0; uint32_t cmd_reg; - uint32_t cmd_type = EMMC_SD_SRS03_CMD_NORMAL; /* TODO: Add support for suspend and resume */ + uint32_t cmd_type = EMMC_SD_SRS03_CMD_NORMAL; #ifdef DEBUG_MMC wolfBoot_printf("mmc_send_cmd: cmd_index: %d, cmd_arg: %08X, resp_type: %d\n", @@ -402,7 +401,7 @@ int mmc_send_cmd(uint32_t cmd_index, uint32_t cmd_arg, uint8_t resp_type) } /* TODO: Add timeout */ -int mmc_wait_busy(int check_dat0) +static int mmc_wait_busy(int check_dat0) { uint32_t status; if (check_dat0) { diff --git a/hal/mpfs250.ld b/hal/mpfs250.ld index 732b8c5088..be10e65df5 100644 --- a/hal/mpfs250.ld +++ b/hal/mpfs250.ld @@ -9,7 +9,8 @@ MEMORY { /* The first 0x100 bytes of eNVM are used for boot ROM secure boot meta information */ FLASH_ENVM (rx) : ORIGIN = 0x20220100, LENGTH = 128k - 0x100 - DDR (rx) : ORIGIN = 0x80000000, LENGTH = 1028k + /* DDR 32-bit cached range is 0x8000_0000 to 0xFFFF_FFFF */ + DDR (rx) : ORIGIN = @WOLFBOOT_ORIGIN@, LENGTH = 1028k L2_SCRATCH (rwx) : ORIGIN = 0x0A000000, LENGTH = 256k } diff --git a/tools/scripts/x86_fsp/qemu/qemu.sh b/tools/scripts/x86_fsp/qemu/qemu.sh index 2ad6d19e20..0c8b2da32f 100755 --- a/tools/scripts/x86_fsp/qemu/qemu.sh +++ b/tools/scripts/x86_fsp/qemu/qemu.sh @@ -53,11 +53,15 @@ while getopts "d:wpt" opt; do ;; t) ENABLE_TPM=true ;; + c) + CLEAR_TPM_NV=true + ;; *) echo "Usage: $0 [-d DEBUG_STAGE1 | DEBUG_STAGE2] [-w] [-p]" echo "-p : create /tmp/qemu_mon.in and /tmp/qemu_mon.out pipes for monitor qemu" echo "-w : wait for GDB to connect to the QEMU gdb server" echo "-t : enable TPM emulation (requires swtpm)" + echo "-c : clear TPM NV" exit 1 ;; esac @@ -110,7 +114,9 @@ if [ "$ENABLE_TPM" = true ]; then killall swtpm || true sleep 1 echo TPM Emulation ON - rm -rf /tmp/swtpm || true + if [ "$CLEAR_TPM_NV" = true ]; then + rm -rf /tmp/swtpm || true + fi mkdir -p /tmp/swtpm swtpm socket --tpm2 --tpmstate dir=/tmp/swtpm \ --ctrl type=unixio,path=/tmp/swtpm/swtpm-sock --log level=20 &