From 418610ebf68b6228382028c285bafe10861d9ad2 Mon Sep 17 00:00:00 2001 From: Eero Nurkkala Date: Wed, 15 May 2024 14:41:29 +0300 Subject: [PATCH] arm64/imx9: provide EL3 bootloader support for iMX9 This provides a capable bootloader that may be run from OCRAM. The OCRAM contains regions that are always zero, so the linker file avoids those with best effort. iMX9 infrastructure expects: - 0x20480000 (Start of OCRAM, AHAB) - 0x2049a000 (NuttX or SPL) - 0x204e0000 (ARM Trustzone, not used) When started from sd-card, the offsets are: - 0x1f000 with AHAB - 0xa000 without AHAB Signed-off-by: Eero Nurkkala --- arch/arm64/src/imx9/Kconfig | 16 ++ arch/arm64/src/imx9/imx9_boot.c | 33 +++- .../imx93-evk/configs/bootloader/defconfig | 64 ++++++++ boards/arm64/imx9/imx93-evk/scripts/Make.defs | 7 +- .../arm64/imx9/imx93-evk/scripts/ocramboot.ld | 155 ++++++++++++++++++ tools/imx9/Config.mk | 33 ++++ 6 files changed, 301 insertions(+), 7 deletions(-) create mode 100644 boards/arm64/imx9/imx93-evk/configs/bootloader/defconfig create mode 100644 boards/arm64/imx9/imx93-evk/scripts/ocramboot.ld create mode 100644 tools/imx9/Config.mk diff --git a/arch/arm64/src/imx9/Kconfig b/arch/arm64/src/imx9/Kconfig index 0d5de6cee5623..2452103b6ae6a 100644 --- a/arch/arm64/src/imx9/Kconfig +++ b/arch/arm64/src/imx9/Kconfig @@ -47,6 +47,22 @@ config IMX9_FLEXIO_PWM select PWM_MULTICHAN default n +config IMX9_BOOTLOADER + bool "Bootloader" + select ARM64_DECODEFIQ + select BOOTLOADER_SYS_CLOCK + default n + ---help--- + Configure NuttX as the bootloader. NuttX will be compiled + into OCRAM. It will run in EL3 secure state. + +config BOOTLOADER_SYS_CLOCK + int "Bootloader system clock for timer" + default 1700000000 + ---help--- + If the sysclk is set to a certain value, this should be it. + The value is used by the timer interrupt infrastructure. + menu "i.MX9 Peripheral Selection" config IMX9_EDMA diff --git a/arch/arm64/src/imx9/imx9_boot.c b/arch/arm64/src/imx9/imx9_boot.c index eb4e7e69d2c7c..6bb9a0163f004 100644 --- a/arch/arm64/src/imx9/imx9_boot.c +++ b/arch/arm64/src/imx9/imx9_boot.c @@ -48,15 +48,29 @@ * Private Data ****************************************************************************/ +#ifdef CONFIG_IMX9_BOOTLOADER +extern uint8_t _szbootloader[]; +#endif + static const struct arm_mmu_region g_mmu_regions[] = { - MMU_REGION_FLAT_ENTRY("DEVICE_REGION", - CONFIG_DEVICEIO_BASEADDR, CONFIG_DEVICEIO_SIZE, - MT_DEVICE_NGNRNE | MT_RW | MT_SECURE), + MMU_REGION_FLAT_ENTRY("DEVICE_REGION", + CONFIG_DEVICEIO_BASEADDR, CONFIG_DEVICEIO_SIZE, + MT_DEVICE_NGNRNE | MT_RW | MT_SECURE), + + MMU_REGION_FLAT_ENTRY("DRAM0_S0", + CONFIG_RAMBANK1_ADDR, CONFIG_RAMBANK1_SIZE, + MT_NORMAL | MT_RW | MT_SECURE), +#ifdef CONFIG_IMX9_BOOTLOADER + /* OCRAM secure region protection keeps the binary at RO mode, + * overriding any MMU settings. However, data and heap accesses + * beyond the binary require RW access. + */ - MMU_REGION_FLAT_ENTRY("DRAM0_S0", - CONFIG_RAMBANK1_ADDR, CONFIG_RAMBANK1_SIZE, - MT_NORMAL | MT_RW | MT_SECURE), + MMU_REGION_FLAT_ENTRY("BOOTLOADER", + (uint64_t)_stext, (uint64_t)_szbootloader, + MT_NORMAL | MT_RW | MT_SECURE), +#endif }; const struct arm_mmu_config g_mmu_config = @@ -84,6 +98,11 @@ const struct arm_mmu_config g_mmu_config = void arm64_el_init(void) { +#ifdef CONFIG_ARCH_BOOT_EL3 + /* At EL3, cntfrq_el0 is uninitialized. It must be set. */ + + write_sysreg(CONFIG_BOOTLOADER_SYS_CLOCK, cntfrq_el0); +#endif } /**************************************************************************** @@ -111,7 +130,9 @@ void arm64_chip_boot(void) #endif #if defined(CONFIG_SMP) || defined(CONFIG_ARCH_HAVE_PSCI) +#ifndef CONFIG_IMX9_BOOTLOADER arm64_psci_init("smc"); +#endif #endif /* Initialize pin interrupt support */ diff --git a/boards/arm64/imx9/imx93-evk/configs/bootloader/defconfig b/boards/arm64/imx9/imx93-evk/configs/bootloader/defconfig new file mode 100644 index 0000000000000..b7b0a0f0cfc20 --- /dev/null +++ b/boards/arm64/imx9/imx93-evk/configs/bootloader/defconfig @@ -0,0 +1,64 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_STANDARD_SERIAL is not set +CONFIG_ARCH="arm64" +CONFIG_ARCH_ARM64=y +CONFIG_ARCH_BOARD="imx93-evk" +CONFIG_ARCH_BOARD_IMX93_EVK=y +CONFIG_ARCH_BOOT_EL3=y +CONFIG_ARCH_CHIP="imx9" +CONFIG_ARCH_CHIP_IMX93=y +CONFIG_ARCH_CHIP_IMX9=y +CONFIG_ARCH_INTERRUPTSTACK=4096 +CONFIG_ARM64_DCACHE_DISABLE=y +CONFIG_BUILTIN=y +CONFIG_DEBUG_ASSERTIONS=y +CONFIG_DEBUG_FEATURES=y +CONFIG_DEBUG_FULLOPT=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DEFAULT_TASK_STACKSIZE=8192 +CONFIG_DEV_ZERO=y +CONFIG_EXAMPLES_HELLO=y +CONFIG_EXPERIMENTAL=y +CONFIG_FS_PROCFS=y +CONFIG_FS_ROMFS=y +CONFIG_HAVE_CXX=y +CONFIG_HAVE_CXXINITIALIZE=y +CONFIG_IDLETHREAD_STACKSIZE=8192 +CONFIG_IMX9_BOOTLOADER=y +CONFIG_IMX9_GPIO_IRQ=y +CONFIG_IMX9_LPUART1=y +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INTELHEX_BINARY=y +CONFIG_LPUART1_SERIAL_CONSOLE=y +CONFIG_MM_FILL_ALLOCATIONS=y +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_READLINE=y +CONFIG_PREALLOC_TIMERS=4 +CONFIG_RAMLOG=y +CONFIG_RAM_SIZE=548864 +CONFIG_RAM_START=0x2049a000 +CONFIG_RAW_BINARY=y +CONFIG_READLINE_CMD_HISTORY=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_HPWORK=y +CONFIG_SCHED_HPWORKPRIORITY=192 +CONFIG_SCHED_LPWORK=y +CONFIG_SCHED_LPWORKPRIORITY=50 +CONFIG_SPINLOCK=y +CONFIG_STACK_COLORATION=y +CONFIG_START_MONTH=3 +CONFIG_START_YEAR=2022 +CONFIG_SYMTAB_ORDEREDBYNAME=y +CONFIG_SYSTEM_NSH=y +CONFIG_SYSTEM_SYSTEM=y +CONFIG_SYSTEM_TIME64=y +CONFIG_TESTING_GETPRIME=y +CONFIG_TESTING_OSTEST=y diff --git a/boards/arm64/imx9/imx93-evk/scripts/Make.defs b/boards/arm64/imx9/imx93-evk/scripts/Make.defs index dd8d6fac4b286..670686a3eb831 100644 --- a/boards/arm64/imx9/imx93-evk/scripts/Make.defs +++ b/boards/arm64/imx9/imx93-evk/scripts/Make.defs @@ -20,9 +20,14 @@ include $(TOPDIR)/.config include $(TOPDIR)/tools/Config.mk +include $(TOPDIR)/tools/imx9/Config.mk include $(TOPDIR)/arch/arm64/src/Toolchain.defs -LDSCRIPT = dramboot.ld +ifeq ($(CONFIG_IMX9_BOOTLOADER),y) + LDSCRIPT = ocramboot.ld +else + LDSCRIPT = dramboot.ld +endif ARCHSCRIPT += $(BOARD_DIR)$(DELIM)scripts$(DELIM)$(LDSCRIPT) diff --git a/boards/arm64/imx9/imx93-evk/scripts/ocramboot.ld b/boards/arm64/imx9/imx93-evk/scripts/ocramboot.ld new file mode 100644 index 0000000000000..0fe7a85fc3811 --- /dev/null +++ b/boards/arm64/imx9/imx93-evk/scripts/ocramboot.ld @@ -0,0 +1,155 @@ +/**************************************************************************** + * boards/arm64/imx9/imx93-evk/scripts/ocramboot.ld + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +OUTPUT_ARCH(aarch64) + +ENTRY(__start) +EXTERN(__start) + +/* Memory is organized as follows: + * - ahab reserves memory from 2048k to 0x2049a000 + * - NuttX is compiled into 0x2049a000, ahab expects NuttX here + * - Heap memory is allocated from ocram end to idlestack top + */ + +MEMORY +{ + ocram (rx) : ORIGIN = 0x2049a000, LENGTH = 0x37ff0 + ocram_data (rw) : ORIGIN = 0x204e0000, LENGTH = 0x2000 + ocram_noload (rw) : ORIGIN = 0x204f0000, LENGTH = 0x30000 +} + +PHDRS +{ + /* R = 100, W = 010, X = 001 */ + + text PT_LOAD FLAGS(5); /* RX */ + rodata PT_LOAD FLAGS(4); /* R */ + data PT_LOAD FLAGS(6); /* RW */ +} + +SECTIONS +{ + .text : + { + _stext = ABSOLUTE(.); /* Text section */ + *(.start .start.*) /* Place __start here */ + *(.text .text.*) + *(.text.cold) + *(.text.unlikely) + *(.fixup) + *(.gnu.warning) + } > ocram :text + + .init_section : + { + _sinit = ABSOLUTE(.); + KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) + KEEP(*(.init_array .ctors)) + _einit = ABSOLUTE(.); + } > ocram :text + + /* Vector table must be page aligned */ + + .vector : ALIGN(4096) + { + _vector_start = ABSOLUTE(.); + KEEP(*(.exc_vector_table)) + KEEP(*(".exc_vector_table.*")) + KEEP(*(.vectors)) + _vector_end = ABSOLUTE(.); + } > ocram :text + + _etext = .; + + .rodata : ALIGN(8) + { + _srodata = ABSOLUTE(.); /* Read-only data */ + *(.rodata .rodata.*) + *(.data.rel.ro) + *(.data.rel.ro.*) + } > ocram :rodata + + _erodata = .; /* End of read-only data */ + _eronly = .; /* End of read-only data */ + + .data : ALIGN(8) + { + _sdata = ABSOLUTE(.); + *(.data.page_aligned) + *(.data .data.*) + . = ALIGN(8); + *(.data.rel) + *(.data.rel.*) + CONSTRUCTORS + . = ALIGN(8); + _edata = ABSOLUTE(.); + } > ocram_data :data + + .bss (NOLOAD) : + { + . = ALIGN(8); + _sbss = ABSOLUTE(.); + *(.bss .bss.*) + . = ALIGN(8); + _ebss = ABSOLUTE(.); + } > ocram_noload :data + + .initstack : + { + _s_initstack = ABSOLUTE(.); + *(.initstack) + } > ocram_noload :data + + /* End of data must be page aligned */ + + . = ALIGN(4096); + + g_idle_topstack = .; + _e_initstack = .; + + /* This makes sure arm64_mmu.c doesn't touch MMU regions, + * we handle it at imx9_boot.c. + */ + _sztext = 0; + _szrodata = 0; + _szbss = 0; + _szdata = 0; + + /* Sections to be discarded */ + /DISCARD/ : { + *(.exit.text) + *(.exit.data) + *(.exitcall.exit) + *(.eh_frame) + } + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } +} + +_heapend = ORIGIN(ocram_noload) + LENGTH(ocram_noload); +_szbootloader = _heapend - _stext; diff --git a/tools/imx9/Config.mk b/tools/imx9/Config.mk new file mode 100644 index 0000000000000..af7f0ee010009 --- /dev/null +++ b/tools/imx9/Config.mk @@ -0,0 +1,33 @@ +############################################################################ +# tools/imx9/Config.mk +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +# These are the macros that will be used in the NuttX make system to compile +# and assembly source files and to insert the resulting object files into an +# archive. These replace the default definitions at tools/Config.mk + +# POSTBUILD -- Perform post build operations + +ifeq ($(CONFIG_IMX9_BOOTLOADER),y) +define POSTBUILD + $(Q) echo "Removing sections" + $(Q) $(OBJCOPY) -O binary -R .bss -R .initstack $(BIN) nuttx.bin + $(Q) ([ $$? -eq 0 ] && echo "Done.") +endef +endif