[PATCH 00/17] arm: semihosting: Cleanups and new features

This cleans up the semihosting code and adds the following new features:
- hostfs support (like sandbox) - support for being used as a SPL boot device - serial device support
The main device affected by these changes is vexpress64, so I'd appreciate if Linus (or anyone else) could try booting.
These changes are motivated by bringup for ls1046a. When forcing JTAG boot, this device disables most communication peripherals, including serial and ethernet devices. This appears to be fixed in later generation devices, but we are stuck with it for now. Semihosting provides an easy way to run a few console commands.
Future work could include modifying one of the reset handlers to catch semihosting calls not handled by a debugger. This would allow using the same U-Boot when booting from JTAG and when booting normally. Additionally, we could use puts in more places. DM serial is especially slow with semihisting because all we have is putc.
The patches in this series are organized as follows: 0-3: rST conversions and other documentation updates 4-8: Semihosting cleanups 9-13: Filesystem support (including SPL boot device) 14-15: Serial support 16: Documentation update 17: JTAG boot support for LS1046A
Patch 17 depends on [1].
[1] https://lore.kernel.org/u-boot/20220222183840.1355337-2-sean.anderson@seco.c...
Sean Anderson (17): doc: Convert semihosting readme to rST nxp: ls1046ardb: Convert README to rST doc: ls1046ardb: Expand boot mode section arm: smh: Add semihosting entry to MAINTAINERS arm: smh: Export semihosting functions arm: smh: Use numeric modes for smh_open arm: smh: Return errno on error arm: smh: Document functions in header arm: smh: Add some file manipulation commands spl: Add semihosting boot method fs: Add semihosting filesystem cmd: fdt: Use start/size for chosen instead of start/end arm: smh: Remove smhload command arm: smh: Add some functions for working with the host console serial: Add semihosting driver doc: smh: Update semihosting documentation ls1046ardb: Add support for JTAG boot
MAINTAINERS | 4 + arch/arm/Kconfig | 25 ++- arch/arm/cpu/armv8/fsl-layerscape/spl.c | 2 + arch/arm/include/asm/spl.h | 1 + arch/arm/lib/semihosting.c | 209 ++++++++++-------------- board/freescale/ls1046ardb/MAINTAINERS | 1 + board/freescale/ls1046ardb/README | 76 --------- cmd/fdt.c | 6 +- common/spl/Makefile | 1 + common/spl/spl_semihosting.c | 71 ++++++++ configs/vexpress_aemv8a_semi_defconfig | 2 +- disk/part.c | 4 +- doc/README.semihosting | 38 ----- doc/board/nxp/index.rst | 1 + doc/board/nxp/ls1046ardb.rst | 182 +++++++++++++++++++++ doc/usage/index.rst | 1 + doc/usage/semihosting.rst | 51 ++++++ drivers/serial/Kconfig | 22 +++ drivers/serial/Makefile | 1 + drivers/serial/serial.c | 2 + drivers/serial/serial_semihosting.c | 108 ++++++++++++ fs/Makefile | 1 + fs/fs.c | 20 +++ fs/semihostingfs.c | 115 +++++++++++++ include/configs/ls1046ardb.h | 2 + include/fs.h | 1 + include/semihosting.h | 108 ++++++++++++ include/semihostingfs.h | 21 +++ 28 files changed, 832 insertions(+), 244 deletions(-) delete mode 100644 board/freescale/ls1046ardb/README create mode 100644 common/spl/spl_semihosting.c delete mode 100644 doc/README.semihosting create mode 100644 doc/board/nxp/ls1046ardb.rst create mode 100644 doc/usage/semihosting.rst create mode 100644 drivers/serial/serial_semihosting.c create mode 100644 fs/semihostingfs.c create mode 100644 include/semihosting.h create mode 100644 include/semihostingfs.h

This converts the semihosting readme to rST. I have tried to make only cosmetic changes, but I did fix up the first link (which was broken).
Signed-off-by: Sean Anderson sean.anderson@seco.com ---
doc/usage/index.rst | 1 + .../semihosting.rst} | 35 +++++++++++-------- 2 files changed, 21 insertions(+), 15 deletions(-) rename doc/{README.semihosting => usage/semihosting.rst} (53%)
diff --git a/doc/usage/index.rst b/doc/usage/index.rst index 964d761e13..569da2bdd1 100644 --- a/doc/usage/index.rst +++ b/doc/usage/index.rst @@ -11,6 +11,7 @@ Use U-Boot netconsole partitions cmdline + semihosting
Shell commands -------------- diff --git a/doc/README.semihosting b/doc/usage/semihosting.rst similarity index 53% rename from doc/README.semihosting rename to doc/usage/semihosting.rst index f382d0131e..ed16e4d582 100644 --- a/doc/README.semihosting +++ b/doc/usage/semihosting.rst @@ -1,35 +1,40 @@ -SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright 2014 Broadcom Corporation. - */ +.. SPDX-License-Identifier: GPL-2.0+ +.. Copyright 2014 Broadcom Corporation. + +Semihosting +===========
Semihosting is ARM's way of having a real or virtual target communicate with a host or host debugger for basic operations such as file I/O, -console I/O, etc. Please see -http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0471c/Bgbjjgi... for more information. +console I/O, etc. Please see `Arm's semihosting documentation +https://developer.arm.com/documentation/100863/latest/`_ for more +information.
For developing on armv8 virtual fastmodel platforms, semihosting is a valuable tool since it allows access to image/configuration files before eMMC or other NV media are available.
There are two main ARM virtual Fixed Virtual Platform (FVP) models, -Versatile Express (VE) FVP and BASE FVP (See -http://www.arm.com/products/tools/models/fast-models/foundation-model.php) +`Versatile Express (VE) FVP and BASE FVP +http://www.arm.com/products/tools/models/fast-models/foundation-model.php`_. The initial vexpress64 u-boot board created here runs on the VE virtual platform using the license-free Foundation_v8 simulator. Fortunately, the Foundation_v8 simulator also supports the BASE_FVP model which companies can purchase licenses for and contain much more functionality. -So we can, in u-boot, run either model by either using the VE FVP (default), -or turning on CONFIG_BASE_FVP for the more full featured model. +So we can, in U-Boot, run either model by either using the VE FVP (default), +or turning on ``CONFIG_BASE_FVP`` for the more full featured model.
-Rather than create a new armv8 board similar to armltd/vexpress64, add -semihosting calls to the existing one, enabled with CONFIG_SEMIHOSTING -and CONFIG_BASE_FVP both set. Also reuse the existing board config file +Rather than create a new armv8 board similar to ``armltd/vexpress64``, add +semihosting calls to the existing one, enabled with ``CONFIG_SEMIHOSTING`` +and ``CONFIG_BASE_FVP`` both set. Also reuse the existing board config file vexpress_aemv8.h but differentiate the two models by the presence or -absence of CONFIG_BASE_FVP. This change is tested and works on both the +absence of ``CONFIG_BASE_FVP``. This change is tested and works on both the Foundation and Base fastmodel simulators.
-The semihosting code adds a command: +Loading files +------------- + +The semihosting code adds a "hostfs"::
smhload <image> <address> [env var]

This converts the readme for this board to rST. I have tried not to change any semantics from the original (though I did convert MB to M).
Signed-off-by: Sean Anderson sean.anderson@seco.com ---
board/freescale/ls1046ardb/MAINTAINERS | 1 + board/freescale/ls1046ardb/README | 76 ------------------- doc/board/nxp/index.rst | 1 + doc/board/nxp/ls1046ardb.rst | 100 +++++++++++++++++++++++++ 4 files changed, 102 insertions(+), 76 deletions(-) delete mode 100644 board/freescale/ls1046ardb/README create mode 100644 doc/board/nxp/ls1046ardb.rst
diff --git a/board/freescale/ls1046ardb/MAINTAINERS b/board/freescale/ls1046ardb/MAINTAINERS index efdea22bde..3c8cfe720d 100644 --- a/board/freescale/ls1046ardb/MAINTAINERS +++ b/board/freescale/ls1046ardb/MAINTAINERS @@ -14,3 +14,4 @@ F: configs/ls1046ardb_tfa_SECURE_BOOT_defconfig F: configs/ls1046ardb_SECURE_BOOT_defconfig F: configs/ls1046ardb_sdcard_SECURE_BOOT_defconfig F: configs/ls1046ardb_qspi_SECURE_BOOT_defconfig +F: doc/board/nxp/ls1046ardb.rst diff --git a/board/freescale/ls1046ardb/README b/board/freescale/ls1046ardb/README deleted file mode 100644 index 90c44f4bce..0000000000 --- a/board/freescale/ls1046ardb/README +++ /dev/null @@ -1,76 +0,0 @@ -Overview --------- -The LS1046A Reference Design Board (RDB) is a high-performance computing, -evaluation, and development platform that supports the QorIQ LS1046A -LayerScape Architecture processor. The LS1046ARDB provides SW development -platform for the Freescale LS1046A processor series, with a complete -debugging environment. The LS1046A RDB is lead-free and RoHS-compliant. - -LS1046A SoC Overview --------------------- -Please refer arch/arm/cpu/armv8/fsl-layerscape/doc/README.soc for LS1046A -SoC overview. - - LS1046ARDB board Overview - ----------------------- - - SERDES1 Connections, 4 lanes supporting: - - Lane0: 10GBase-R with x1 RJ45 connector - - Lane1: 10GBase-R Cage - - Lane2: SGMII.5 - - Lane3: SGMII.6 - - SERDES2 Connections, 4 lanes supporting: - - Lane0: PCIe1 with miniPCIe slot - - Lane1: PCIe2 with PCIe x2 slot - - Lane2: PCIe3 with PCIe x4 slot - - Lane3: SATA - - DDR Controller - - 8GB 64bits DDR4 SDRAM. Support rates of up to 2133MT/s - -IFC/Local Bus - - One 512 MB NAND flash with ECC support - - CPLD connection - - USB 3.0 - - one Type A port, one Micro-AB port - - SDHC: connects directly to a full SD/MMC slot - - DSPI: 64 MB high-speed flash Memory for boot code and storage (up to 108MHz) - - 4 I2C controllers - - UART - - Two 4-pin serial ports at up to 115.2 Kbit/s - - Two DB9 D-Type connectors supporting one Serial port each - - ARM JTAG support - -Memory map from core's view ----------------------------- -Start Address End Address Description Size -0x00_0000_0000 - 0x00_000F_FFFF Secure Boot ROM 1MB -0x00_0100_0000 - 0x00_0FFF_FFFF CCSRBAR 240MB -0x00_1000_0000 - 0x00_1000_FFFF OCRAM0 64KB -0x00_1001_0000 - 0x00_1001_FFFF OCRAM1 64KB -0x00_2000_0000 - 0x00_20FF_FFFF DCSR 16MB -0x00_7E80_0000 - 0x00_7E80_FFFF IFC - NAND Flash 64KB -0x00_7FB0_0000 - 0x00_7FB0_0FFF IFC - CPLD 4KB -0x00_8000_0000 - 0x00_FFFF_FFFF DRAM1 2GB -0x05_0000_0000 - 0x05_07FF_FFFF QMAN S/W Portal 128M -0x05_0800_0000 - 0x05_0FFF_FFFF BMAN S/W Portal 128M -0x08_8000_0000 - 0x09_FFFF_FFFF DRAM2 6GB -0x40_0000_0000 - 0x47_FFFF_FFFF PCI Express1 32G -0x48_0000_0000 - 0x4F_FFFF_FFFF PCI Express2 32G -0x50_0000_0000 - 0x57_FFFF_FFFF PCI Express3 32G - -QSPI flash map: -Start Address End Address Description Size -0x00_4000_0000 - 0x00_400F_FFFF RCW + PBI 1MB -0x00_4010_0000 - 0x00_402F_FFFF U-Boot 2MB -0x00_4030_0000 - 0x00_403F_FFFF U-Boot Env 1MB -0x00_4040_0000 - 0x00_405F_FFFF PPA 2MB -0x00_4060_0000 - 0x00_408F_FFFF Secure boot header - + bootscript 3MB -0x00_4090_0000 - 0x00_4093_FFFF FMan ucode 256KB -0x00_4094_0000 - 0x00_4097_FFFF QE/uQE firmware 256KB -0x00_4098_0000 - 0x00_40FF_FFFF Reserved 6MB -0x00_4100_0000 - 0x00_43FF_FFFF FIT Image 48MB - -Booting Options ---------------- -a) QSPI boot -b) SD boot -c) eMMC boot diff --git a/doc/board/nxp/index.rst b/doc/board/nxp/index.rst index 63956287c5..4514b8951b 100644 --- a/doc/board/nxp/index.rst +++ b/doc/board/nxp/index.rst @@ -13,6 +13,7 @@ NXP Semiconductors imx8qxp_mek imxrt1020-evk imxrt1050-evk + ls1046ardb mx6sabreauto mx6sabresd mx6ul_14x14_evk diff --git a/doc/board/nxp/ls1046ardb.rst b/doc/board/nxp/ls1046ardb.rst new file mode 100644 index 0000000000..4bfeaa93dd --- /dev/null +++ b/doc/board/nxp/ls1046ardb.rst @@ -0,0 +1,100 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +LS1046ARDB +========== + +The LS1046A Reference Design Board (RDB) is a high-performance computing, +evaluation, and development platform that supports the QorIQ LS1046A +LayerScape Architecture processor. The LS1046ARDB provides SW development +platform for the Freescale LS1046A processor series, with a complete +debugging environment. The LS1046A RDB is lead-free and RoHS-compliant. + +LS1046A SoC Overview +-------------------- +Please refer arch/arm/cpu/armv8/fsl-layerscape/doc/README.soc for LS1046A +SoC overview. + +LS1046ARDB board Overview +------------------------- +- SERDES1 Connections, 4 lanes supporting: + + - Lane0: 10GBase-R with x1 RJ45 connector + - Lane1: 10GBase-R Cage + - Lane2: SGMII.5 + - Lane3: SGMII.6 + +- SERDES2 Connections, 4 lanes supporting: + + - Lane0: PCIe1 with miniPCIe slot + - Lane1: PCIe2 with PCIe x2 slot + - Lane2: PCIe3 with PCIe x4 slot + - Lane3: SATA + +- DDR Controller + + - 8GB 64bits DDR4 SDRAM. Support rates of up to 2133MT/s + +- IFC/Local Bus + + - One 512 MB NAND flash with ECC support + - CPLD connection + +- USB 3.0 + + - one Type A port, one Micro-AB port + +- SDHC: connects directly to a full SD/MMC slot +- DSPI: 64 MB high-speed flash Memory for boot code and storage (up to 108MHz) +- 4 I2C controllers +- UART + + - Two 4-pin serial ports at up to 115.2 Kbit/s + - Two DB9 D-Type connectors supporting one Serial port each + +- ARM JTAG support + +Memory map from core's view +---------------------------- + +================== ================== ================ ===== +Start Address End Address Description Size +================== ================== ================ ===== +``0x00_0000_0000`` ``0x00_000F_FFFF`` Secure Boot ROM 1M +``0x00_0100_0000`` ``0x00_0FFF_FFFF`` CCSRBAR 240M +``0x00_1000_0000`` ``0x00_1000_FFFF`` OCRAM0 64K +``0x00_1001_0000`` ``0x00_1001_FFFF`` OCRAM1 64K +``0x00_2000_0000`` ``0x00_20FF_FFFF`` DCSR 16M +``0x00_7E80_0000`` ``0x00_7E80_FFFF`` IFC - NAND Flash 64K +``0x00_7FB0_0000`` ``0x00_7FB0_0FFF`` IFC - CPLD 4K +``0x00_8000_0000`` ``0x00_FFFF_FFFF`` DRAM1 2G +``0x05_0000_0000`` ``0x05_07FF_FFFF`` QMAN S/W Portal 128M +``0x05_0800_0000`` ``0x05_0FFF_FFFF`` BMAN S/W Portal 128M +``0x08_8000_0000`` ``0x09_FFFF_FFFF`` DRAM2 6G +``0x40_0000_0000`` ``0x47_FFFF_FFFF`` PCI Express1 32G +``0x48_0000_0000`` ``0x4F_FFFF_FFFF`` PCI Express2 32G +``0x50_0000_0000`` ``0x57_FFFF_FFFF`` PCI Express3 32G +================== ================== ================ ===== + +QSPI flash map +-------------- + +================== ================== ================== ===== +Start Address End Address Description Size +================== ================== ================== ===== +``0x00_4000_0000`` ``0x00_400F_FFFF`` RCW + PBI 1M +``0x00_4010_0000`` ``0x00_402F_FFFF`` U-Boot 2M +``0x00_4030_0000`` ``0x00_403F_FFFF`` U-Boot Env 1M +``0x00_4040_0000`` ``0x00_405F_FFFF`` PPA 2M +``0x00_4060_0000`` ``0x00_408F_FFFF`` Secure boot header 3M + + bootscript +``0x00_4090_0000`` ``0x00_4093_FFFF`` FMan ucode 256K +``0x00_4094_0000`` ``0x00_4097_FFFF`` QE/uQE firmware 256K +``0x00_4098_0000`` ``0x00_40FF_FFFF`` Reserved 6M +``0x00_4100_0000`` ``0x00_43FF_FFFF`` FIT Image 48M +================== ================== ================== ===== + +Booting Options +--------------- +- QSPI boot +- SD boot +- eMMC boot

This adds some additional info about booting from different sources, including the correct switch positions.
Signed-off-by: Sean Anderson sean.anderson@seco.com ---
doc/board/nxp/ls1046ardb.rst | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-)
diff --git a/doc/board/nxp/ls1046ardb.rst b/doc/board/nxp/ls1046ardb.rst index 4bfeaa93dd..c73516c070 100644 --- a/doc/board/nxp/ls1046ardb.rst +++ b/doc/board/nxp/ls1046ardb.rst @@ -95,6 +95,17 @@ Start Address End Address Description Size
Booting Options --------------- -- QSPI boot -- SD boot -- eMMC boot + +NB: The reference manual documents the RCW source with the *least-significant +bit first*. + +QSPI boot +^^^^^^^^^ + +This is the default. ``{ SW5[0:8], SW4[0] }`` should be ``0010_0010_0``. + +SD boot and eMMC boot +^^^^^^^^^^^^^^^^^^^^^ + +``{ SW5[0:8], SW4[0] }`` should be ``0010_0000_0``. eMMC is selected only if +there is no SD card in the slot.

These files are spread all over the tree, so just use a regex. Orphaned for now, since this is more of a "one-off" series. Though I'll be happy to review patches.
Signed-off-by: Sean Anderson sean.anderson@seco.com ---
MAINTAINERS | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS index fb171e0c68..8d9792c8b2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1148,6 +1148,10 @@ F: arch/sandbox/ F: doc/arch/sandbox.rst F: include/dt-bindings/*/sandbox*.h
+SEMIHOSTING +S: Orphaned +N: semihosting + SETEXPR M: Roland Gaudig roland.gaudig@weidmueller.com S: Maintained

This exports semihosting functions for use in other files. The header is in include/ and not arm/include/asm because I anticipate that RISC-V may want to add their own implementation at some point.
smh_len_fd has been renamed to smh_flen to more closely match the semihosting spec.
Signed-off-by: Sean Anderson sean.anderson@seco.com ---
arch/arm/lib/semihosting.c | 11 ++++++----- include/semihosting.h | 14 ++++++++++++++ 2 files changed, 20 insertions(+), 5 deletions(-) create mode 100644 include/semihosting.h
diff --git a/arch/arm/lib/semihosting.c b/arch/arm/lib/semihosting.c index 9fd82459b2..c38892fdd8 100644 --- a/arch/arm/lib/semihosting.c +++ b/arch/arm/lib/semihosting.c @@ -15,6 +15,7 @@ #include <command.h> #include <env.h> #include <log.h> +#include <semihosting.h>
#define SYSOPEN 0x01 #define SYSCLOSE 0x02 @@ -45,7 +46,7 @@ static noinline long smh_trap(unsigned int sysnum, void *addr) * Open a file on the host. Mode is "r" or "rb" currently. Returns a file * descriptor or -1 on error. */ -static long smh_open(const char *fname, char *modestr) +long smh_open(const char *fname, char *modestr) { long fd; unsigned long mode; @@ -84,7 +85,7 @@ static long smh_open(const char *fname, char *modestr) /* * Read 'len' bytes of file into 'memp'. Returns 0 on success, else failure */ -static long smh_read(long fd, void *memp, size_t len) +long smh_read(long fd, void *memp, size_t len) { long ret; struct smh_read_s { @@ -118,7 +119,7 @@ static long smh_read(long fd, void *memp, size_t len) /* * Close the file using the file descriptor */ -static long smh_close(long fd) +long smh_close(long fd) { long ret;
@@ -134,7 +135,7 @@ static long smh_close(long fd) /* * Get the file length from the file descriptor */ -static long smh_len_fd(long fd) +long smh_flen(long fd) { long ret;
@@ -158,7 +159,7 @@ static int smh_load_file(const char * const name, ulong load_addr, if (fd == -1) return -1;
- len = smh_len_fd(fd); + len = smh_flen(fd); if (len < 0) { smh_close(fd); return -1; diff --git a/include/semihosting.h b/include/semihosting.h new file mode 100644 index 0000000000..3843863046 --- /dev/null +++ b/include/semihosting.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2022 Sean Anderson sean.anderson@seco.com + */ + +#ifndef _SEMIHOSTING_H +#define _SEMIHOSTING_H + +long smh_open(const char *fname, char *modestr); +long smh_read(long fd, void *memp, size_t len); +long smh_close(long fd); +long smh_flen(long fd); + +#endif /* _SEMIHOSTING_H */

There's no point in using string constants for smh_open if we are just going to have to parse them. Instead, use numeric modes. The user needs to be a bit careful with these, since they are much closer semantically to string modes used by fopen(3) than the numeric modes used with open(2).
Signed-off-by: Sean Anderson sean.anderson@seco.com ---
arch/arm/lib/semihosting.c | 21 +++------------------ include/semihosting.h | 25 ++++++++++++++++++++++++- 2 files changed, 27 insertions(+), 19 deletions(-)
diff --git a/arch/arm/lib/semihosting.c b/arch/arm/lib/semihosting.c index c38892fdd8..b983cc3935 100644 --- a/arch/arm/lib/semihosting.c +++ b/arch/arm/lib/semihosting.c @@ -22,9 +22,6 @@ #define SYSREAD 0x06 #define SYSFLEN 0x0C
-#define MODE_READ 0x0 -#define MODE_READBIN 0x1 - /* * Call the handler */ @@ -46,28 +43,16 @@ static noinline long smh_trap(unsigned int sysnum, void *addr) * Open a file on the host. Mode is "r" or "rb" currently. Returns a file * descriptor or -1 on error. */ -long smh_open(const char *fname, char *modestr) +long smh_open(const char *fname, enum smh_open_mode mode) { long fd; - unsigned long mode; struct smh_open_s { const char *fname; unsigned long mode; size_t len; } open;
- debug("%s: file '%s', mode '%s'\n", __func__, fname, modestr); - - /* Check the file mode */ - if (!(strcmp(modestr, "r"))) { - mode = MODE_READ; - } else if (!(strcmp(modestr, "rb"))) { - mode = MODE_READBIN; - } else { - printf("%s: ERROR mode '%s' not supported\n", __func__, - modestr); - return -1; - } + debug("%s: file '%s', mode '%u'\n", __func__, fname, mode);
open.fname = fname; open.len = strlen(fname); @@ -155,7 +140,7 @@ static int smh_load_file(const char * const name, ulong load_addr, long len; long ret;
- fd = smh_open(name, "rb"); + fd = smh_open(name, MODE_READ | MODE_BINARY); if (fd == -1) return -1;
diff --git a/include/semihosting.h b/include/semihosting.h index 3843863046..cf54819192 100644 --- a/include/semihosting.h +++ b/include/semihosting.h @@ -6,7 +6,30 @@ #ifndef _SEMIHOSTING_H #define _SEMIHOSTING_H
-long smh_open(const char *fname, char *modestr); +/** + * enum smh_open_mode - Numeric file modes for use with smh_open() + * MODE_READ: 'r' + * MODE_BINARY: 'b' + * MODE_PLUS: '+' + * MODE_WRITE: 'w' + * MODE_APPEND: 'a' + * + * These modes represent the mode string used by fopen(3) in a form which can + * be passed to smh_open(). These do NOT correspond directly to %O_RDONLY, + * %O_CREAT, etc; see fopen(3) for details. In particular, @MODE_PLUS + * effectively results in adding %O_RDWR, and @MODE_WRITE will add %O_TRUNC. + * For compatibility, @MODE_BINARY should be added when opening non-text files + * (such as images). + */ +enum smh_open_mode { + MODE_READ = 0x0, + MODE_BINARY = 0x1, + MODE_PLUS = 0x2, + MODE_WRITE = 0x4, + MODE_APPEND = 0x8, +}; + +long smh_open(const char *fname, enum smh_open_mode mode); long smh_read(long fd, void *memp, size_t len); long smh_close(long fd); long smh_flen(long fd);

Instead of printing in what are now library functions, try to return a numeric error code. This also adjust some functions (such as read) to behave more similarly to read(2). For example, we now return the number of bytes read instead of failing immediately on a short read.
Signed-off-by: Sean Anderson sean.anderson@seco.com ---
arch/arm/lib/semihosting.c | 67 ++++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 31 deletions(-)
diff --git a/arch/arm/lib/semihosting.c b/arch/arm/lib/semihosting.c index b983cc3935..1686457685 100644 --- a/arch/arm/lib/semihosting.c +++ b/arch/arm/lib/semihosting.c @@ -21,6 +21,7 @@ #define SYSCLOSE 0x02 #define SYSREAD 0x06 #define SYSFLEN 0x0C +#define SYSERRNO 0x13
/* * Call the handler @@ -39,10 +40,24 @@ static noinline long smh_trap(unsigned int sysnum, void *addr) return result; }
-/* - * Open a file on the host. Mode is "r" or "rb" currently. Returns a file - * descriptor or -1 on error. +/** + * smh_errno() - Read the host's errno + * + * This gets the value of the host's errno and negates it. The host's errno may + * or may not be set, so only call this function if a previous semihosting call + * has failed. + * + * Return: a negative error value */ +static int smh_errno(void) +{ + long ret = smh_trap(SYSERRNO, NULL); + + if (ret > 0 && ret < INT_MAX) + return -ret; + return -EIO; +} + long smh_open(const char *fname, enum smh_open_mode mode) { long fd; @@ -61,9 +76,7 @@ long smh_open(const char *fname, enum smh_open_mode mode) /* Open the file on the host */ fd = smh_trap(SYSOPEN, &open); if (fd == -1) - printf("%s: ERROR fd %ld for file '%s'\n", __func__, fd, - fname); - + return smh_errno(); return fd; }
@@ -86,19 +99,9 @@ long smh_read(long fd, void *memp, size_t len) read.len = len;
ret = smh_trap(SYSREAD, &read); - if (ret < 0) { - /* - * The ARM handler allows for returning partial lengths, - * but in practice this never happens so rather than create - * hard to maintain partial read loops and such, just fail - * with an error message. - */ - printf("%s: ERROR ret %ld, fd %ld, len %zu memp %p\n", - __func__, ret, fd, len, memp); - return -1; - } - - return 0; + if (ret < 0) + return smh_errno(); + return len - ret; }
/* @@ -112,9 +115,8 @@ long smh_close(long fd)
ret = smh_trap(SYSCLOSE, &fd); if (ret == -1) - printf("%s: ERROR fd %ld\n", __func__, fd); - - return ret; + return smh_errno(); + return 0; }
/* @@ -128,8 +130,7 @@ long smh_flen(long fd)
ret = smh_trap(SYSFLEN, &fd); if (ret == -1) - printf("%s: ERROR ret %ld, fd %ld\n", __func__, ret, fd); - + return smh_errno(); return ret; }
@@ -141,28 +142,32 @@ static int smh_load_file(const char * const name, ulong load_addr, long ret;
fd = smh_open(name, MODE_READ | MODE_BINARY); - if (fd == -1) - return -1; + if (fd < 0) + return fd;
len = smh_flen(fd); if (len < 0) { smh_close(fd); - return -1; + return len; }
ret = smh_read(fd, (void *)load_addr, len); smh_close(fd);
- if (ret == 0) { + if (ret == len) { *end_addr = load_addr + len - 1; printf("loaded file %s from %08lX to %08lX, %08lX bytes\n", name, load_addr, *end_addr, len); - } else { - printf("read failed\n"); - return 0; + } else if (ret >= 0) { + ret = -EAGAIN; + } + + if (ret < 0) { + printf("read failed: %ld\n", ret); + return ret; }
return 0;

This adds some documentation for semihosting functions in the header.
Signed-off-by: Sean Anderson sean.anderson@seco.com ---
arch/arm/lib/semihosting.c | 9 --------- include/semihosting.h | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 9 deletions(-)
diff --git a/arch/arm/lib/semihosting.c b/arch/arm/lib/semihosting.c index 1686457685..2943f7b82f 100644 --- a/arch/arm/lib/semihosting.c +++ b/arch/arm/lib/semihosting.c @@ -80,9 +80,6 @@ long smh_open(const char *fname, enum smh_open_mode mode) return fd; }
-/* - * Read 'len' bytes of file into 'memp'. Returns 0 on success, else failure - */ long smh_read(long fd, void *memp, size_t len) { long ret; @@ -104,9 +101,6 @@ long smh_read(long fd, void *memp, size_t len) return len - ret; }
-/* - * Close the file using the file descriptor - */ long smh_close(long fd) { long ret; @@ -119,9 +113,6 @@ long smh_close(long fd) return 0; }
-/* - * Get the file length from the file descriptor - */ long smh_flen(long fd) { long ret; diff --git a/include/semihosting.h b/include/semihosting.h index cf54819192..d8337b6269 100644 --- a/include/semihosting.h +++ b/include/semihosting.h @@ -29,9 +29,41 @@ enum smh_open_mode { MODE_APPEND = 0x8, };
+/** + * smh_open() - Open a file on the host + * @fname: The name of the file to open + * @mode: The mode to use when opening the file + * + * Return: Either a file descriptor or a negative error on failure + */ long smh_open(const char *fname, enum smh_open_mode mode); + +/** + * smh_read() - Read data from a file + * @fd: A file descriptor returned from smh_open() + * @memp: Pointer to a buffer of memory of at least @len bytes + * @len: The number of bytes to read + * + * Return: + * * The number of bytes read on success, with 0 indicating %EOF + * * A negative error on failure + */ long smh_read(long fd, void *memp, size_t len); + +/** + * smh_close() - Close an open file + * @fd: A file descriptor returned from smh_open() + * + * Return: 0 on success or negative error on failure + */ long smh_close(long fd); + +/** + * smh_flen() - Get the length of a file + * @fd: A file descriptor returned from smh_open() + * + * Return: The length of the file, in bytes, or a negative error on failure + */ long smh_flen(long fd);
#endif /* _SEMIHOSTING_H */

In order to add filesystem support, we will need to be able to seek and write files. Add the appropriate helper functions.
Signed-off-by: Sean Anderson sean.anderson@seco.com ---
arch/arm/lib/semihosting.c | 67 +++++++++++++++++++++++++++++++------- include/semihosting.h | 20 ++++++++++++ 2 files changed, 76 insertions(+), 11 deletions(-)
diff --git a/arch/arm/lib/semihosting.c b/arch/arm/lib/semihosting.c index 2943f7b82f..d08003cef1 100644 --- a/arch/arm/lib/semihosting.c +++ b/arch/arm/lib/semihosting.c @@ -1,15 +1,13 @@ // SPDX-License-Identifier: GPL-2.0+ /* + * Copyright (C) 2022 Sean Anderson sean.anderson@seco.com * Copyright 2014 Broadcom Corporation */
/* - * Minimal semihosting implementation for reading files into memory. If more - * features like writing files or console output are required they can be - * added later. This code has been tested on arm64/aarch64 fastmodel only. - * An untested placeholder exists for armv7 architectures, but since they - * are commonly available in silicon now, fastmodel usage makes less sense - * for them. + * This code has been tested on arm64/aarch64 fastmodel only. An untested + * placeholder exists for armv7 architectures, but since they are commonly + * available in silicon now, fastmodel usage makes less sense for them. */ #include <common.h> #include <command.h> @@ -19,7 +17,9 @@
#define SYSOPEN 0x01 #define SYSCLOSE 0x02 +#define SYSWRITE 0x05 #define SYSREAD 0x06 +#define SYSSEEK 0x0A #define SYSFLEN 0x0C #define SYSERRNO 0x13
@@ -80,14 +80,22 @@ long smh_open(const char *fname, enum smh_open_mode mode) return fd; }
+/** + * struct smg_rdwr_s - Arguments for read and write + * @fd: A file descriptor returned from smh_open() + * @memp: Pointer to a buffer of memory of at least @len bytes + * @len: The number of bytes to read or write + */ +struct smh_rdwr_s { + long fd; + void *memp; + size_t len; +}; + long smh_read(long fd, void *memp, size_t len) { long ret; - struct smh_read_s { - long fd; - void *memp; - size_t len; - } read; + struct smh_rdwr_s read;
debug("%s: fd %ld, memp %p, len %zu\n", __func__, fd, memp, len);
@@ -101,6 +109,24 @@ long smh_read(long fd, void *memp, size_t len) return len - ret; }
+long smh_write(long fd, const void *memp, size_t len, ulong *written) +{ + long ret; + struct smh_rdwr_s write; + + debug("%s: fd %ld, memp %p, len %zu\n", __func__, fd, memp, len); + + write.fd = fd; + write.memp = (void *)memp; + write.len = len; + + ret = smh_trap(SYSWRITE, &write); + *written = len - ret; + if (ret) + return smh_errno(); + return 0; +} + long smh_close(long fd) { long ret; @@ -125,6 +151,25 @@ long smh_flen(long fd) return ret; }
+long smh_seek(long fd, long pos) +{ + long ret; + struct smh_seek_s { + long fd; + long pos; + } seek; + + debug("%s: fd %ld pos %ld\n", __func__, fd, pos); + + seek.fd = fd; + seek.pos = pos; + + ret = smh_trap(SYSSEEK, &seek); + if (ret) + return smh_errno(); + return 0; +} + static int smh_load_file(const char * const name, ulong load_addr, ulong *end_addr) { diff --git a/include/semihosting.h b/include/semihosting.h index d8337b6269..b53c650444 100644 --- a/include/semihosting.h +++ b/include/semihosting.h @@ -50,6 +50,17 @@ long smh_open(const char *fname, enum smh_open_mode mode); */ long smh_read(long fd, void *memp, size_t len);
+/** + * smh_write() - Write data to a file + * @fd: A file descriptor returned from smh_open() + * @memp: Pointer to a buffer of memory of at least @len bytes + * @len: The number of bytes to read + * @written: Pointer which will be updated with the actual bytes written + * + * Return: 0 on success or negative error on failure + */ +long smh_write(long fd, const void *memp, size_t len, ulong *written); + /** * smh_close() - Close an open file * @fd: A file descriptor returned from smh_open() @@ -66,4 +77,13 @@ long smh_close(long fd); */ long smh_flen(long fd);
+/** + * smh_seek() - Seek to a position in a file + * @fd: A file descriptor returned from smh_open() + * @pos: The offset (in bytes) to seek to + * + * Return: 0 on success or negative error on failure + */ +long smh_seek(long fd, long pos); + #endif /* _SEMIHOSTING_H */

This adds a boot method for loading the next stage from the host. It is mostly modeled off of spl_load_image_ext. I am not really sure why/how spl_load_image_fat uses three different methods to load the image, but the simple case seems to work OK for now.
To control the presence of this boot method, we add a config symbol. While we're at it, we update the original semihosting config symbol.
I think semihosting has some advantages of other forms of JTAG boot. Common other ways to boot from JTAG include:
- Implementing DDR initialization through JTAG (typically with dozens of lines of TCL) and then loading U-Boot. The DDR initialization typically uses hard-coded register writes, and is not easily adapted to different boards. BOOT_DEVICE_SMH allows booting with SPL, leveraging U-Boot's existing DDR initialization code. This is the method used by NXP's CodeWarrior IDE on Layerscape processors (see AN12270). - Loading a bootloader into SDRAM, waiting for it to initialize DDR, and then loading U-Boot. This is tricky, because the debugger must stop the boot after the bootloader has completed its work. Trying to load U-Boot too early can cause failure to boot. This is the method used by Xilinx with its Zynq(MP) processors. - Loading SPL with BOOT_DEVICE_RAM and breaking before SPL loads the image to load U-Boot at the appropriate place. This can be a bit tricky, because the load address is dependent on the header size. An elf with symbols must also be used in order to stop at the appropriate point. BOOT_DEVICE_SMH can be viewed as an extension of this process, where SPL automatically stops and tells the host where to place the image.
Signed-off-by: Sean Anderson sean.anderson@seco.com ---
arch/arm/Kconfig | 25 +++++++++++-- arch/arm/include/asm/spl.h | 1 + common/spl/Makefile | 1 + common/spl/spl_semihosting.c | 71 ++++++++++++++++++++++++++++++++++++ 4 files changed, 94 insertions(+), 4 deletions(-) create mode 100644 common/spl/spl_semihosting.c
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 391a77c2b4..5cacb292b5 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -403,11 +403,28 @@ config ARM_SMCCC firmware (for example, PSCI) according to SMCCC.
config SEMIHOSTING - bool "support boot from semihosting" + bool "Support ARM semihosting" help - In emulated environments, semihosting is a way for - the hosted environment to call out to the emulator to - retrieve files from the host machine. + Semihosting is a method for a target to communicate with a host + debugger. It uses special instructions which the debugger will trap + on and interpret. This allows U-Boot to read/write files, print to + the console, and execute arbitrary commands on the host system. + + Enabling this option will add support for reading and writing files + on the host system. If you don't have a debugger attached then trying + to do this will likely cause U-Boot to hang. Say 'n' if you are unsure. + +config SPL_SEMIHOSTING + bool "Support ARM semihosting in SPL" + help + Semihosting is a method for a target to communicate with a host + debugger. It uses special instructions which the debugger will trap + on and interpret. This allows U-Boot to read/write files, print to + the console, and execute arbitrary commands on the host system. + + Enabling this option will add support for reading and writing files + on the host system. If you don't have a debugger attached then trying + to do this will likely cause U-Boot to hang. Say 'n' if you are unsure.
config SYS_THUMB_BUILD bool "Build U-Boot using the Thumb instruction set" diff --git a/arch/arm/include/asm/spl.h b/arch/arm/include/asm/spl.h index e568af2561..b5790bd0bc 100644 --- a/arch/arm/include/asm/spl.h +++ b/arch/arm/include/asm/spl.h @@ -30,6 +30,7 @@ enum { BOOT_DEVICE_DFU, BOOT_DEVICE_XIP, BOOT_DEVICE_BOOTROM, + BOOT_DEVICE_SMH, BOOT_DEVICE_NONE }; #endif diff --git a/common/spl/Makefile b/common/spl/Makefile index db8fd36a26..e71e7bee66 100644 --- a/common/spl/Makefile +++ b/common/spl/Makefile @@ -28,6 +28,7 @@ obj-$(CONFIG_$(SPL_TPL_)USB_STORAGE) += spl_usb.o obj-$(CONFIG_$(SPL_TPL_)FS_FAT) += spl_fat.o obj-$(CONFIG_$(SPL_TPL_)FS_EXT4) += spl_ext.o obj-$(CONFIG_$(SPL_TPL_)SATA) += spl_sata.o +obj-$(CONFIG_$(SPL_TPL_)SEMIHOSTING) += spl_semihosting.o obj-$(CONFIG_$(SPL_TPL_)DFU) += spl_dfu.o obj-$(CONFIG_$(SPL_TPL_)SPI_LOAD) += spl_spi.o obj-$(CONFIG_$(SPL_TPL_)RAM_SUPPORT) += spl_ram.o diff --git a/common/spl/spl_semihosting.c b/common/spl/spl_semihosting.c new file mode 100644 index 0000000000..df6aeb2951 --- /dev/null +++ b/common/spl/spl_semihosting.c @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2022 Sean Anderson sean.anderson@seco.com + */ + +#include <common.h> +#include <image.h> +#include <log.h> +#include <semihosting.h> +#include <spl.h> + +static int smh_read_full(long fd, void *memp, size_t len) +{ + long read; + + read = smh_read(fd, memp, len); + if (read < 0) + return read; + if (read != len) + return -EIO; + return 0; +} + +static int spl_smh_load_image(struct spl_image_info *spl_image, + struct spl_boot_device *bootdev) +{ + const char *filename = CONFIG_SPL_FS_LOAD_PAYLOAD_NAME; + int ret; + long fd, len; + struct image_header *header = + spl_get_load_buffer(-sizeof(*header), sizeof(*header)); + + fd = smh_open(filename, MODE_READ | MODE_BINARY); + if (fd < 0) { + log_debug("could not open %s: %ld\n", filename, fd); + return fd; + } + + ret = smh_flen(fd); + if (ret < 0) { + log_debug("could not get length of image: %d\n", ret); + goto out; + } + len = ret; + + ret = smh_read_full(fd, header, sizeof(struct image_header)); + if (ret) { + log_debug("could not read image header: %d\n", ret); + goto out; + } + + ret = spl_parse_image_header(spl_image, bootdev, header); + if (ret) { + log_debug("failed to parse image header: %d\n", ret); + goto out; + } + + ret = smh_seek(fd, 0); + if (ret) { + log_debug("could not seek to start of image: %d\n", ret); + goto out; + } + + ret = smh_read_full(fd, (void *)spl_image->load_addr, len); + if (ret) + log_debug("could not read %s: %d\n", filename, ret); +out: + smh_close(fd); + return ret; +} +SPL_LOAD_IMAGE_METHOD("SEMIHOSTING", 0, BOOT_DEVICE_SMH, spl_smh_load_image);

This adds a filesystem which is backed by the host's filesystem. It is modeled off of sandboxfs, which has very similar aims. Semihosting doesn't support listing directories (except with SYS_SYSTEM), so neither do we. it's possible to optimize a bit for the common case of reading a whole file by omitting a call to smh_seek, but this is left as a future optimization.
Signed-off-by: Sean Anderson sean.anderson@seco.com ---
disk/part.c | 4 +- fs/Makefile | 1 + fs/fs.c | 20 +++++++ fs/semihostingfs.c | 115 ++++++++++++++++++++++++++++++++++++++++ include/fs.h | 1 + include/semihostingfs.h | 21 ++++++++ 6 files changed, 160 insertions(+), 2 deletions(-) create mode 100644 fs/semihostingfs.c create mode 100644 include/semihostingfs.h
diff --git a/disk/part.c b/disk/part.c index 49e39a24e8..b95405bb49 100644 --- a/disk/part.c +++ b/disk/part.c @@ -455,7 +455,7 @@ int blk_get_device_part_str(const char *ifname, const char *dev_part_str, int part; struct disk_partition tmpinfo;
-#ifdef CONFIG_SANDBOX +#if IS_ENABLED(CONFIG_SANDBOX) || IS_ENABLED(CONFIG_SEMIHOSTING) /* * Special-case a pseudo block device "hostfs", to allow access to the * host's own filesystem. @@ -467,7 +467,7 @@ int blk_get_device_part_str(const char *ifname, const char *dev_part_str, info->blksz = 0; info->bootable = 0; strcpy((char *)info->type, BOOT_PART_TYPE); - strcpy((char *)info->name, "Sandbox host"); + strcpy((char *)info->name, "Host filesystem"); #if CONFIG_IS_ENABLED(PARTITION_UUIDS) info->uuid[0] = 0; #endif diff --git a/fs/Makefile b/fs/Makefile index 937cbcf6e8..c25d022946 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -21,6 +21,7 @@ obj-$(CONFIG_FS_FAT) += fat/ obj-$(CONFIG_FS_JFFS2) += jffs2/ obj-$(CONFIG_CMD_REISER) += reiserfs/ obj-$(CONFIG_SANDBOX) += sandbox/ +obj-$(CONFIG_SEMIHOSTING) += semihostingfs.o obj-$(CONFIG_CMD_UBIFS) += ubifs/ obj-$(CONFIG_YAFFS2) += yaffs2/ obj-$(CONFIG_CMD_ZFS) += zfs/ diff --git a/fs/fs.c b/fs/fs.c index 023f89cafe..bba010ea99 100644 --- a/fs/fs.c +++ b/fs/fs.c @@ -18,6 +18,7 @@ #include <fat.h> #include <fs.h> #include <sandboxfs.h> +#include <semihostingfs.h> #include <ubifs_uboot.h> #include <btrfs.h> #include <asm/global_data.h> @@ -246,6 +247,25 @@ static struct fstype_info fstypes[] = { .ln = fs_ln_unsupported, }, #endif +#ifdef CONFIG_SEMIHOSTING + { + .fstype = FS_TYPE_SEMIHOSTING, + .name = "semihosting", + .null_dev_desc_ok = true, + .probe = smh_fs_set_blk_dev, + .close = fs_close_unsupported, + .ls = fs_ls_unsupported, + .exists = fs_exists_unsupported, + .size = smh_fs_size, + .read = smh_fs_read, + .write = smh_fs_write, + .uuid = fs_uuid_unsupported, + .opendir = fs_opendir_unsupported, + .unlink = fs_unlink_unsupported, + .mkdir = fs_mkdir_unsupported, + .ln = fs_ln_unsupported, + }, +#endif #ifdef CONFIG_CMD_UBIFS { .fstype = FS_TYPE_UBIFS, diff --git a/fs/semihostingfs.c b/fs/semihostingfs.c new file mode 100644 index 0000000000..96eb3349a2 --- /dev/null +++ b/fs/semihostingfs.c @@ -0,0 +1,115 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2022, Sean Anderson sean.anderson@seco.com + * Copyright (c) 2012, Google Inc. + */ + +#include <common.h> +#include <fs.h> +#include <malloc.h> +#include <os.h> +#include <semihosting.h> +#include <semihostingfs.h> + +int smh_fs_set_blk_dev(struct blk_desc *rbdd, struct disk_partition *info) +{ + /* + * Only accept a NULL struct blk_desc for the semihosting, which is when + * hostfs interface is used + */ + return !!rbdd; +} + +static int smh_fs_read_at(const char *filename, loff_t pos, void *buffer, + loff_t maxsize, loff_t *actread) +{ + long fd, size, ret; + + fd = smh_open(filename, MODE_READ | MODE_BINARY); + if (fd < 0) + return fd; + ret = smh_seek(fd, pos); + if (ret < 0) { + smh_close(fd); + return ret; + } + if (!maxsize) { + size = smh_flen(fd); + if (ret < 0) { + smh_close(fd); + return size; + } + + maxsize = size; + } + + size = smh_read(fd, buffer, maxsize); + smh_close(fd); + if (size < 0) + return size; + + *actread = size; + return 0; +} + +static int smh_fs_write_at(const char *filename, loff_t pos, void *buffer, + loff_t towrite, loff_t *actwrite) +{ + long fd, size, ret; + + fd = smh_open(filename, MODE_READ | MODE_BINARY | MODE_PLUS); + if (fd < 0) + return fd; + ret = smh_seek(fd, pos); + if (ret < 0) { + smh_close(fd); + return ret; + } + + ret = smh_write(fd, buffer, towrite, &size); + smh_close(fd); + *actwrite = size; + return ret; +} + +int smh_fs_size(const char *filename, loff_t *result) +{ + long fd, size; + + fd = smh_open(filename, MODE_READ | MODE_BINARY); + if (fd < 0) + return fd; + + size = smh_flen(fd); + smh_close(fd); + + if (size < 0) + return size; + + *result = size; + return 0; +} + +int smh_fs_read(const char *filename, void *buf, loff_t offset, loff_t len, + loff_t *actread) +{ + int ret; + + ret = smh_fs_read_at(filename, offset, buf, len, actread); + if (ret) + printf("** Unable to read file %s **\n", filename); + + return ret; +} + +int smh_fs_write(const char *filename, void *buf, loff_t offset, + loff_t len, loff_t *actwrite) +{ + int ret; + + ret = smh_fs_write_at(filename, offset, buf, len, actwrite); + if (ret) + printf("** Unable to write file %s **\n", filename); + + return ret; +} diff --git a/include/fs.h b/include/fs.h index c8df3886ac..2f631624b5 100644 --- a/include/fs.h +++ b/include/fs.h @@ -17,6 +17,7 @@ struct cmd_tbl; #define FS_TYPE_UBIFS 4 #define FS_TYPE_BTRFS 5 #define FS_TYPE_SQUASHFS 6 +#define FS_TYPE_SEMIHOSTING 7
struct blk_desc;
diff --git a/include/semihostingfs.h b/include/semihostingfs.h new file mode 100644 index 0000000000..25ebdbbeff --- /dev/null +++ b/include/semihostingfs.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2022, Sean Anderson sean.anderson@seco.com + * Copyright (c) 2012, Google Inc. + */ + +#ifndef __SEMIHOSTING_FS__ +#define __SEMIHOSTING_FS__ + +struct blk_desc; +struct disk_partition; + +int smh_fs_set_blk_dev(struct blk_desc *rbdd, struct disk_partition *info); +void smh_fs_close(void); +int smh_fs_size(const char *filename, loff_t *size); +int smh_fs_read(const char *filename, void *buf, loff_t offset, loff_t len, + loff_t *actread); +int smh_fs_write(const char *filename, void *buf, loff_t offset, + loff_t len, loff_t *actwrite); + +#endif

Most U-Boot command deal with start/size instead of start/end. Convert the "fdt chosen" command to use these semantics as well. The only user of this subcommand is vexpress, so convert the smhload command to use this as well. We don't bother renaming the variable in vexpress64's bootcommand, since it will be rewritten in the next commit.
Signed-off-by: Sean Anderson sean.anderson@seco.com ---
arch/arm/lib/semihosting.c | 16 ++++++++-------- cmd/fdt.c | 6 +++--- 2 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/arch/arm/lib/semihosting.c b/arch/arm/lib/semihosting.c index d08003cef1..45cd566cfc 100644 --- a/arch/arm/lib/semihosting.c +++ b/arch/arm/lib/semihosting.c @@ -171,7 +171,7 @@ long smh_seek(long fd, long pos) }
static int smh_load_file(const char * const name, ulong load_addr, - ulong *end_addr) + ulong *size) { long fd; long len; @@ -191,11 +191,11 @@ static int smh_load_file(const char * const name, ulong load_addr, smh_close(fd);
if (ret == len) { - *end_addr = load_addr + len - 1; + *size = len; printf("loaded file %s from %08lX to %08lX, %08lX bytes\n", name, load_addr, - *end_addr, + load_addr + len - 1, len); } else if (ret >= 0) { ret = -EAGAIN; @@ -214,22 +214,22 @@ static int do_smhload(struct cmd_tbl *cmdtp, int flag, int argc, { if (argc == 3 || argc == 4) { ulong load_addr; - ulong end_addr = 0; + ulong size = 0; int ret; - char end_str[64]; + char size_str[64];
load_addr = hextoul(argv[2], NULL); if (!load_addr) return -1;
- ret = smh_load_file(argv[1], load_addr, &end_addr); + ret = smh_load_file(argv[1], load_addr, &size); if (ret < 0) return CMD_RET_FAILURE;
/* Optionally save returned end to the environment */ if (argc == 4) { - sprintf(end_str, "0x%08lx", end_addr); - env_set(argv[3], end_str); + sprintf(size_str, "0x%08lx", size); + env_set(argv[3], size_str); } } else { return CMD_RET_USAGE; diff --git a/cmd/fdt.c b/cmd/fdt.c index 2a207bf2b5..7d7cae88a2 100644 --- a/cmd/fdt.c +++ b/cmd/fdt.c @@ -638,7 +638,7 @@ static int do_fdt(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
if (argc == 4) { initrd_start = hextoul(argv[2], NULL); - initrd_end = hextoul(argv[3], NULL); + initrd_end = initrd_start + hextoul(argv[3], NULL) - 1; }
fdt_chosen(working_fdt); @@ -1083,8 +1083,8 @@ static char fdt_help_text[] = "fdt rsvmem print - Show current mem reserves\n" "fdt rsvmem add <addr> <size> - Add a mem reserve\n" "fdt rsvmem delete <index> - Delete a mem reserves\n" - "fdt chosen [<start> <end>] - Add/update the /chosen branch in the tree\n" - " <start>/<end> - initrd start/end addr\n" + "fdt chosen [<start> <size>] - Add/update the /chosen branch in the tree\n" + " <start>/<size> - initrd start addr/size\n" #if defined(CONFIG_FIT_SIGNATURE) "fdt checksign [<addr>] - check FIT signature\n" " <start> - addr of key blob\n"

This command's functionality is now completely implemented by the standard fs load command. Convert the vexpress64 boot command (which is the only user) and remove the implementation.
Signed-off-by: Sean Anderson sean.anderson@seco.com ---
arch/arm/lib/semihosting.c | 76 -------------------------- configs/vexpress_aemv8a_semi_defconfig | 2 +- 2 files changed, 1 insertion(+), 77 deletions(-)
diff --git a/arch/arm/lib/semihosting.c b/arch/arm/lib/semihosting.c index 45cd566cfc..57ab25294f 100644 --- a/arch/arm/lib/semihosting.c +++ b/arch/arm/lib/semihosting.c @@ -10,8 +10,6 @@ * available in silicon now, fastmodel usage makes less sense for them. */ #include <common.h> -#include <command.h> -#include <env.h> #include <log.h> #include <semihosting.h>
@@ -169,77 +167,3 @@ long smh_seek(long fd, long pos) return smh_errno(); return 0; } - -static int smh_load_file(const char * const name, ulong load_addr, - ulong *size) -{ - long fd; - long len; - long ret; - - fd = smh_open(name, MODE_READ | MODE_BINARY); - if (fd < 0) - return fd; - - len = smh_flen(fd); - if (len < 0) { - smh_close(fd); - return len; - } - - ret = smh_read(fd, (void *)load_addr, len); - smh_close(fd); - - if (ret == len) { - *size = len; - printf("loaded file %s from %08lX to %08lX, %08lX bytes\n", - name, - load_addr, - load_addr + len - 1, - len); - } else if (ret >= 0) { - ret = -EAGAIN; - } - - if (ret < 0) { - printf("read failed: %ld\n", ret); - return ret; - } - - return 0; -} - -static int do_smhload(struct cmd_tbl *cmdtp, int flag, int argc, - char *const argv[]) -{ - if (argc == 3 || argc == 4) { - ulong load_addr; - ulong size = 0; - int ret; - char size_str[64]; - - load_addr = hextoul(argv[2], NULL); - if (!load_addr) - return -1; - - ret = smh_load_file(argv[1], load_addr, &size); - if (ret < 0) - return CMD_RET_FAILURE; - - /* Optionally save returned end to the environment */ - if (argc == 4) { - sprintf(size_str, "0x%08lx", size); - env_set(argv[3], size_str); - } - } else { - return CMD_RET_USAGE; - } - return 0; -} - -U_BOOT_CMD(smhload, 4, 0, do_smhload, "load a file using semihosting", - "<file> 0x<address> [end var]\n" - " - load a semihosted file to the address specified\n" - " if the optional [end var] is specified, the end\n" - " address of the file will be stored in this environment\n" - " variable.\n"); diff --git a/configs/vexpress_aemv8a_semi_defconfig b/configs/vexpress_aemv8a_semi_defconfig index 82a5b52f1e..d7771f6260 100644 --- a/configs/vexpress_aemv8a_semi_defconfig +++ b/configs/vexpress_aemv8a_semi_defconfig @@ -17,7 +17,7 @@ CONFIG_ANDROID_BOOT_IMAGE=y CONFIG_BOOTDELAY=1 CONFIG_USE_BOOTARGS=y CONFIG_BOOTARGS="console=ttyAMA0 earlycon=pl011,0x1c090000 debug user_debug=31 loglevel=9" -CONFIG_BOOTCOMMAND="if smhload ${boot_name} ${boot_addr_r}; then set bootargs; abootimg addr ${boot_addr_r}; abootimg get dtb --index=0 fdt_addr_r; bootm ${boot_addr_r} ${boot_addr_r} ${fdt_addr_r}; else; set fdt_high 0xffffffffffffffff; set initrd_high 0xffffffffffffffff; smhload ${kernel_name} ${kernel_addr}; smhload ${fdtfile} ${fdt_addr_r}; smhload ${ramdisk_name} ${ramdisk_addr_r} ramdisk_end; fdt addr ${fdt_addr_r}; fdt resize; fdt chosen ${ramdisk_addr_r} ${ramdisk_end}; booti $kernel_addr - $fdt_addr_r; fi" +CONFIG_BOOTCOMMAND="if load hostfs ${boot_addr_r} ${boot_name}; then set bootargs; abootimg addr ${boot_addr_r}; abootimg get dtb --index=0 fdt_addr_r; bootm ${boot_addr_r} ${boot_addr_r} ${fdt_addr_r}; else; set fdt_high 0xffffffffffffffff; set initrd_high 0xffffffffffffffff; load hostfs ${kernel_addr} ${kernel_name}; load hostfs ${fdt_addr_r} ${fdtfile}; load ${ramdisk_addr_r} ${ramdisk_name}; fdt addr ${fdt_addr_r}; fdt resize; fdt chosen ${ramdisk_addr_r} ${filesize}; booti $kernel_addr - $fdt_addr_r; fi" # CONFIG_DISPLAY_CPUINFO is not set # CONFIG_DISPLAY_BOARDINFO is not set CONFIG_SYS_PROMPT="VExpress64# "

This adds three wrappers around the semihosting commands for reading and writing to the host console. We use the more standard getc/putc/puts names instead of readc/writec/write0 for familiarity.
Signed-off-by: Sean Anderson sean.anderson@seco.com ---
arch/arm/lib/semihosting.c | 18 ++++++++++++++++++ include/semihosting.h | 19 +++++++++++++++++++ 2 files changed, 37 insertions(+)
diff --git a/arch/arm/lib/semihosting.c b/arch/arm/lib/semihosting.c index 57ab25294f..7595dbc4a9 100644 --- a/arch/arm/lib/semihosting.c +++ b/arch/arm/lib/semihosting.c @@ -15,8 +15,11 @@
#define SYSOPEN 0x01 #define SYSCLOSE 0x02 +#define SYSWRITEC 0x03 +#define SYSWRITE0 0x04 #define SYSWRITE 0x05 #define SYSREAD 0x06 +#define SYSREADC 0x07 #define SYSSEEK 0x0A #define SYSFLEN 0x0C #define SYSERRNO 0x13 @@ -167,3 +170,18 @@ long smh_seek(long fd, long pos) return smh_errno(); return 0; } + +int smh_getc(void) +{ + return smh_trap(SYSREADC, NULL); +} + +void smh_putc(char ch) +{ + smh_trap(SYSWRITEC, &ch); +} + +void smh_puts(const char *s) +{ + smh_trap(SYSWRITE0, (char *)s); +} diff --git a/include/semihosting.h b/include/semihosting.h index b53c650444..6f3c29786c 100644 --- a/include/semihosting.h +++ b/include/semihosting.h @@ -86,4 +86,23 @@ long smh_flen(long fd); */ long smh_seek(long fd, long pos);
+/** + * smh_getc() - Read a character from stdin + * + * Return: The character read, or a negative error on failure + */ +int smh_getc(void); + +/** + * smh_putc() - Print a character on stdout + * @ch: The character to print + */ +void smh_putc(char ch); + +/** + * smh_write0() - Print a nul-terminated string on stdout + * @s: The string to print + */ +void smh_puts(const char *s); + #endif /* _SEMIHOSTING_H */

This adds a serial driver which uses semihosting calls to read and write to the host's console. For convenience, if CONFIG_DM_SERIAL is enabled, we will instantiate a serial driver. This allows users to enable this driver (which has no physical device) without modifying their device trees or board files. We also implement a non-DM driver for SPL, or for much faster output in U-Boot proper.
There are three ways to print to the console:
Method Baud ================== ==== smh_putc in a loop 17 smh_puts 160 smh_write with :tt 2000 ================== ====
These speeds were mesured using a 175 character message with a J-Link adapter. For reference, U-Boot typically prints around 2700 characters during boot on this board. There are two major factors affecting the speed of these functions. First, each breakpoint incurs a delay. Second, each debugger memory transaction incurs a delay. smh_putc has a breakpoint and memory transaction for every character. smh_puts has one breakpoint, but still has to use a transaction for every character. This is because we don't know the length up front, so OpenOCD has to check if each character is nul. smh_write has only one breakpoint and one memory transfer.
DM serial drivers can only implement a putc interface, so we are stuck with the slowest API. Non-DM drivers can implement puts, which is vastly more efficient. When the driver starts up, we try to open :tt. Since this is an extension, this may fail. If it does, we fall back to smh_puts. We don't check :semihosting-features, since there are nonconforming imlementations (OpenOCD) which don't implement it (but *do* implement :tt).
There is no non-blocking I/O available, so we don't implement pending. This will cause __serial_tstc to always return true. If CONFIG_SERIAL_RX_BUFFER is enabled, _serial_tstc will try and read characters forever. To avoid this, we depend on this config being disabled.
Signed-off-by: Sean Anderson sean.anderson@seco.com ---
drivers/serial/Kconfig | 22 ++++++ drivers/serial/Makefile | 1 + drivers/serial/serial.c | 2 + drivers/serial/serial_semihosting.c | 108 ++++++++++++++++++++++++++++ 4 files changed, 133 insertions(+) create mode 100644 drivers/serial/serial_semihosting.c
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 345d1881f5..cc20759505 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -399,6 +399,15 @@ config DEBUG_UART_SANDBOX start up driver model. The driver will be available until the real driver model serial is running.
+config DEBUG_UART_SEMIHOSTING + bool "semihosting" + depends on SEMIHOSTING_SERIAL + help + Select this to enable the debug UART using the semihosting driver. + This provides basic serial output from the console without needing to + start up driver model. The driver will be available until the real + driver model serial is running. + config DEBUG_UART_SIFIVE bool "SiFive UART" depends on SIFIVE_SERIAL @@ -778,6 +787,19 @@ config SCIF_CONSOLE on systems with RCar or SH SoCs, say Y to this option. If unsure, say N.
+config SEMIHOSTING_SERIAL + bool "Semihosting UART support" + depends on SEMIHOSTING && !SERIAL_RX_BUFFER + help + Select this to enable a serial UART using semihosting. Special halt + instructions will be issued which an external debugger (such as a + JTAG emulator) may interpret. The debugger will display U-Boot's + console output on the host system. + + Enable this option only if you are using a debugger which supports + semihosting. If you are not using a debugger, this driver will halt + the boot. + config UNIPHIER_SERIAL bool "Support for UniPhier on-chip UART" depends on ARCH_UNIPHIER diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 52e70aa191..b68b5e7b2b 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -52,6 +52,7 @@ endif obj-$(CONFIG_XILINX_UARTLITE) += serial_xuartlite.o obj-$(CONFIG_SANDBOX_SERIAL) += sandbox.o obj-$(CONFIG_SCIF_CONSOLE) += serial_sh.o +obj-$(CONFIG_SEMIHOSTING_SERIAL) += serial_semihosting.o obj-$(CONFIG_ZYNQ_SERIAL) += serial_zynq.o obj-$(CONFIG_FSL_LPUART) += serial_lpuart.o obj-$(CONFIG_FSL_LINFLEXUART) += serial_linflexuart.o diff --git a/drivers/serial/serial.c b/drivers/serial/serial.c index ebbd21916d..6cdbb89841 100644 --- a/drivers/serial/serial.c +++ b/drivers/serial/serial.c @@ -126,6 +126,7 @@ serial_initfunc(mxc_serial_initialize); serial_initfunc(ns16550_serial_initialize); serial_initfunc(pl01x_serial_initialize); serial_initfunc(pxa_serial_initialize); +serial_initfunc(smh_serial_initialize); serial_initfunc(sh_serial_initialize); serial_initfunc(mtk_serial_initialize);
@@ -180,6 +181,7 @@ int serial_initialize(void) ns16550_serial_initialize(); pl01x_serial_initialize(); pxa_serial_initialize(); + smh_serial_initialize(); sh_serial_initialize(); mtk_serial_initialize();
diff --git a/drivers/serial/serial_semihosting.c b/drivers/serial/serial_semihosting.c new file mode 100644 index 0000000000..44a67c5cb6 --- /dev/null +++ b/drivers/serial/serial_semihosting.c @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2022 Sean Anderson sean.anderson@seco.com + */ + +#include <common.h> +#include <dm.h> +#include <serial.h> +#include <semihosting.h> + +#if CONFIG_IS_ENABLED(DM_SERIAL) +static int smh_serial_getc(struct udevice *dev) +{ + return smh_getc(); +} + +static int smh_serial_putc(struct udevice *dev, const char ch) +{ + smh_putc(ch); + return 0; +} + +static const struct dm_serial_ops smh_serial_ops = { + .putc = smh_serial_putc, + .getc = smh_serial_getc, +}; + +U_BOOT_DRIVER(smh_serial) = { + .name = "serial_semihosting", + .id = UCLASS_SERIAL, + .ops = &smh_serial_ops, + .flags = DM_FLAG_PRE_RELOC, +}; + +U_BOOT_DRVINFO(smh_serial) = { + .name = "serial_semihosting", +}; +#else /* DM_SERIAL */ +static int outfd = -ENODEV; + +static int smh_serial_start(void) +{ + outfd = smh_open(":tt", MODE_WRITE); + return 0; +} + +static int smh_serial_stop(void) +{ + if (outfd >= 0) + smh_close(outfd); + return 0; +} + +static void smh_serial_setbrg(void) +{ +} + +static int smh_serial_tstc(void) +{ + return 1; +} + +static void smh_serial_puts(const char *s) +{ + ulong unused; + + if (outfd < 0) + smh_puts(s); + else + smh_write(outfd, s, strlen(s), &unused); +} + +static struct serial_device smh_serial_drv = { + .name = "serial_smh", + .start = smh_serial_start, + .stop = smh_serial_stop, + .setbrg = smh_serial_setbrg, + .getc = smh_getc, + .tstc = smh_serial_tstc, + .putc = smh_putc, + .puts = smh_serial_puts, +}; + +void smh_serial_initialize(void) +{ + serial_register(&smh_serial_drv); +} + +struct serial_device *default_serial_console(void) +{ + return &smh_serial_drv; +} +#endif + +#ifdef CONFIG_DEBUG_UART_SEMIHOSTING +#include <debug_uart.h> + +static inline void _debug_uart_init(void) +{ +} + +static inline void _debug_uart_putc(int c) +{ + smh_putc(c); +} + +DEBUG_UART_FUNCS +#endif

This documents the new semihosting features added in the past few commits.
Signed-off-by: Sean Anderson sean.anderson@seco.com ---
doc/usage/semihosting.rst | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/doc/usage/semihosting.rst b/doc/usage/semihosting.rst index ed16e4d582..986a821819 100644 --- a/doc/usage/semihosting.rst +++ b/doc/usage/semihosting.rst @@ -34,10 +34,18 @@ Foundation and Base fastmodel simulators. Loading files -------------
-The semihosting code adds a "hostfs":: +The semihosting code adds a "semihosting filesystem"::
- smhload <image> <address> [env var] + load hostfs <address> <image>
That will load an image from the host filesystem into RAM at the specified -address and optionally store the load end address in the specified -environment variable. +address. If you are using U-Boot SPL, you can also use ``BOOT_DEVICE_SMH`` +which will load ``CONFIG_SPL_FS_LOAD_PAYLOAD_NAME``. + +Host console +------------ + +U-Boot can use the host's console instead of a physical serial device by +enabling ``CONFIG_SERIAL_SEMIHOSTING``. If you don't have +``CONFIG_DM_SERIAL`` enabled, make sure you disable any other serial +drivers.

This adds support for booting entirely from JTAG while using a hard-coded RCW. With these steps, it is not necessary to program a "good" RCW using CodeWarrior. The method here can be performed with any JTAG adapter supported by OpenOCD, including the on-board CMSIS-DAP (albeit very slowly).
These steps require LS1046A support in OpenOCD, which is currently in the process of being upstreamed [1].
[1] https://review.openocd.org/c/openocd/+/6855
Signed-off-by: Sean Anderson sean.anderson@seco.com ---
arch/arm/cpu/armv8/fsl-layerscape/spl.c | 2 + doc/board/nxp/ls1046ardb.rst | 71 +++++++++++++++++++++++++ include/configs/ls1046ardb.h | 2 + 3 files changed, 75 insertions(+)
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/spl.c b/arch/arm/cpu/armv8/fsl-layerscape/spl.c index 564cc27c8b..1a7dde30a5 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/spl.c +++ b/arch/arm/cpu/armv8/fsl-layerscape/spl.c @@ -27,6 +27,8 @@ DECLARE_GLOBAL_DATA_PTR;
u32 spl_boot_device(void) { + if (IS_ENABLED(CONFIG_SPL_SEMIHOSTING)) + return BOOT_DEVICE_SMH; #ifdef CONFIG_SPL_MMC return BOOT_DEVICE_MMC1; #endif diff --git a/doc/board/nxp/ls1046ardb.rst b/doc/board/nxp/ls1046ardb.rst index c73516c070..ffb9d4550b 100644 --- a/doc/board/nxp/ls1046ardb.rst +++ b/doc/board/nxp/ls1046ardb.rst @@ -109,3 +109,74 @@ SD boot and eMMC boot
``{ SW5[0:8], SW4[0] }`` should be ``0010_0000_0``. eMMC is selected only if there is no SD card in the slot. + +JTAG boot +^^^^^^^^^ + +To recover a bricked board, or to perform initial programming, the ls1046 +supports using two hard-coded Reset Configuration Words (RCWs). Unfortunately, +this configuration disables most functionality, including the uarts and ethernet. +However, the SD/MMC and flash controllers are still functional. To get around +the lack of a serial console, we will use ARM semihosting instead. When +enabled, OpenOCD will interpret certain instructions as calls to the host +operating system. This allows U-Boot to use the console, read/write files, or +run arbitrary commands (!). + +When configuring U-Boot, ensure that ``CONFIG_SEMIHOSTING``, +``CONFIG_SPL_SEMIHOSTING``, and ``CONFIG_SEMIHOSTING_SERIAL`` are enabled, and +``CONFIG_SYS_NS16550`` is disabled. ``{ SW5[0:8], SW4[0] }`` should be +``0100_1111_0``. Additionally, ``SW4[7]`` should be set to ``0``. Connect to +the "console" USB connector on the front of the enclosure. + +Create a new file called ``u-boot.tcl`` (or whatever you choose) with the +following contents:: + + # Load the configuration for the LS1046ARDB + source [find board/nxp_rdb-ls1046a.cfg] + # Initialize the scan chain + init + # Stop the processor + halt + # Enable semihosting + arm semihosting enable + # Load U-Boot SPL + load_image spl/u-boot-spl 0 elf + # Start executing SPL at the beginning of OCRAM + resume 0x10000000 + +Then, launch openocd like:: + + openocd -f u-boot.tcl + +You should see the U-boot SPL banner followed by the banner for U-Boot proper +in the output of openocd. The CMSIS-DAP adapter is slow, so this can take a +long time. If you don't see it, something has gone wrong. After a while, you +should see the prompt. You can load an image using semihosting by running:: + + => load hostfs $loadaddr <name of file> + +Note that openocd's terminal is "cooked," so commands will only be sent to +U-Boot when you press enter, and all commands will be echoed twice. +Additionally, openocd will block when waiting for input, ignoring gdb, JTAG +events, and Ctrl-Cs. To make openocd process these events, just hit enter. + +Using an external JTAG adapter +"""""""""""""""""""""""""""""" + +The CMSIS-DAP adapter can be rather slow. To speed up booting, use an external +JTAG adapter. The following examples assume you are using a J-Link, though any +adapter supported by OpenOCD will do. Ensure that ``SW4[7]`` is ``1``. Attach +your jtag adapter to J22. Modify ``u-boot.tcl`` and replace the first two lines +with the following:: + + # Load the J-Link configuration (or whatever your adapter is) + source [find interface/jlink.cfg] + # Use JTAG, since the J-Link also supports SWD + transport select jtag + # The reset pin resets the whole CPU + reset_config srst_only + # Load the LS1046A config + source [find target/ls1046a.cfg] + +You can proceed as normal through the rest of the steps above. I got a speedup +of around 100x by using a J-Link. diff --git a/include/configs/ls1046ardb.h b/include/configs/ls1046ardb.h index 8ed1dceb23..ed549c33b6 100644 --- a/include/configs/ls1046ardb.h +++ b/include/configs/ls1046ardb.h @@ -143,6 +143,8 @@ #endif #endif
+#define CONFIG_SPL_FS_LOAD_PAYLOAD_NAME "u-boot.img" + #include <asm/fsl_secure_boot.h>
#endif /* __LS1046ARDB_H__ */

Hi Sean,
I like the ambition in this series!
On Thu, Mar 3, 2022 at 9:44 PM Sean Anderson sean.anderson@seco.com wrote:
The main device affected by these changes is vexpress64, so I'd appreciate if Linus (or anyone else) could try booting.
I am currently on parental leave and pretty far removed from that hardware and have very little bandwidth. I added Andre Przywara to the header (include him in the future) because currently he does much more U-Boot work on these platforms than me.
The actual user of the semihosting commands is (IIRC) FVP, the software-only version of vexpress-variants. The semihosting creates software traps inside the emulated environment.
Yours, Linus Walleij

On Fri, 4 Mar 2022 02:06:03 +0100 Linus Walleij linus.walleij@linaro.org wrote:
Hi,
Linus, thanks for the heads up, much appreciated!
On Thu, Mar 3, 2022 at 9:44 PM Sean Anderson sean.anderson@seco.com wrote:
The main device affected by these changes is vexpress64, so I'd appreciate if Linus (or anyone else) could try booting.
As it happens, I am sitting on a series updating vexpress_aemv8a_semi, and letting it use OF_CONTROL. I will send this ASAP. As it turned out, the automatic semihosting boot command is actually broken in v2022.01, the fix is the first patch in my series. This clashes with this series, but it's easy to resolve.
From skimming over this series here, it looks quite nice, I especially love promoting the semihosting load to a proper filesystem. The only drawback seems to be that this will break existing scripts used by people in their deployments, which rely on the smhload command. I don't really know if there are actually any users doing so, but I guess we will find out.
Is there any official U-Boot policy for changing commands, which might break scripts? For instance I was always tempted to fix the "afs" command, or make that an fs as well.
I will test and review this series ASAP.
Thanks, Andre
I am currently on parental leave and pretty far removed from that hardware and have very little bandwidth. I added Andre Przywara to the header (include him in the future) because currently he does much more U-Boot work on these platforms than me.
The actual user of the semihosting commands is (IIRC) FVP, the software-only version of vexpress-variants. The semihosting creates software traps inside the emulated environment.
Yours, Linus Walleij

Hi Andre,
On 3/4/22 6:47 AM, Andre Przywara wrote:
On Fri, 4 Mar 2022 02:06:03 +0100 Linus Walleij linus.walleij@linaro.org wrote:
Hi,
Linus, thanks for the heads up, much appreciated!
On Thu, Mar 3, 2022 at 9:44 PM Sean Anderson sean.anderson@seco.com wrote:
The main device affected by these changes is vexpress64, so I'd appreciate if Linus (or anyone else) could try booting.
As it happens, I am sitting on a series updating vexpress_aemv8a_semi, and letting it use OF_CONTROL. I will send this ASAP. As it turned out, the automatic semihosting boot command is actually broken in v2022.01, the fix is the first patch in my series. This clashes with this series, but it's easy to resolve.
I, for one, appreciate that the boot command is no longer all one line after your series.
Simon/Tom, which series would you like to be based off the other?
From skimming over this series here, it looks quite nice, I especially love promoting the semihosting load to a proper filesystem. The only drawback seems to be that this will break existing scripts used by people in their deployments, which rely on the smhload command. I don't really know if there are actually any users doing so, but I guess we will find out.
Yeah, I'm not sure what the stance on shell compatibility is. As I understand it, for the C API only in-tree users matter. However, shell commands are more of an "external" API, used by distro boot scripts. Simon/Tom, what's the process for this?
There are two ABI breaks introduced by this series: - Changing smh_load to set the size and not the end address - Removing the smh_load command altogether
The first one could be avoided by loading a FIT instead of individual images (since we would no longer need to fix up chosen to point at the ramdisk). The second could be avoided by providing a small shim like do_ext4_load. However, if at all possible I would just like to remove the command entirely.
Is there any official U-Boot policy for changing commands, which might break scripts? For instance I was always tempted to fix the "afs" command, or make that an fs as well.
I will test and review this series ASAP.
Thanks. BTW what does U-Boot use for its console on this platform? From the bootargs, it appears that Linux uses pl011, but that doesn't seem to be enabled for U-Boot.
I am currently on parental leave and pretty far removed from that hardware and have very little bandwidth. I added Andre Przywara to the header (include him in the future) because currently he does much more U-Boot work on these platforms than me.
Thanks for pointing me to the right person.
--Sean

On Fri, Mar 04, 2022 at 12:19:27PM -0500, Sean Anderson wrote:
Hi Andre,
On 3/4/22 6:47 AM, Andre Przywara wrote:
On Fri, 4 Mar 2022 02:06:03 +0100 Linus Walleij linus.walleij@linaro.org wrote:
Hi,
Linus, thanks for the heads up, much appreciated!
On Thu, Mar 3, 2022 at 9:44 PM Sean Anderson sean.anderson@seco.com wrote:
The main device affected by these changes is vexpress64, so I'd appreciate if Linus (or anyone else) could try booting.
As it happens, I am sitting on a series updating vexpress_aemv8a_semi, and letting it use OF_CONTROL. I will send this ASAP. As it turned out, the automatic semihosting boot command is actually broken in v2022.01, the fix is the first patch in my series. This clashes with this series, but it's easy to resolve.
I, for one, appreciate that the boot command is no longer all one line after your series.
Simon/Tom, which series would you like to be based off the other?
I think it's however it's easiest for you two to collaborate.
From skimming over this series here, it looks quite nice, I especially love promoting the semihosting load to a proper filesystem. The only drawback seems to be that this will break existing scripts used by people in their deployments, which rely on the smhload command. I don't really know if there are actually any users doing so, but I guess we will find out.
Yeah, I'm not sure what the stance on shell compatibility is. As I understand it, for the C API only in-tree users matter. However, shell commands are more of an "external" API, used by distro boot scripts. Simon/Tom, what's the process for this?
Well, in this case we can be a bit more cavalier than typical because of the very limited user base. So long as we have good documentation around it including something around how to transition to the new commands, it should be fine to do so, when the code is otherwise ready.

Hi Tom/Andre,
On 3/4/22 1:46 PM, Tom Rini wrote:
On Fri, Mar 04, 2022 at 12:19:27PM -0500, Sean Anderson wrote:
Hi Andre,
On 3/4/22 6:47 AM, Andre Przywara wrote:
On Fri, 4 Mar 2022 02:06:03 +0100 Linus Walleij linus.walleij@linaro.org wrote:
Hi,
Linus, thanks for the heads up, much appreciated!
On Thu, Mar 3, 2022 at 9:44 PM Sean Anderson sean.anderson@seco.com wrote:
The main device affected by these changes is vexpress64, so I'd appreciate if Linus (or anyone else) could try booting.
As it happens, I am sitting on a series updating vexpress_aemv8a_semi, and letting it use OF_CONTROL. I will send this ASAP. As it turned out, the automatic semihosting boot command is actually broken in v2022.01, the fix is the first patch in my series. This clashes with this series, but it's easy to resolve.
I, for one, appreciate that the boot command is no longer all one line after your series.
Simon/Tom, which series would you like to be based off the other?
I think it's however it's easiest for you two to collaborate.
I think it will be cleaner for me to base my series on his, but I just want to avoid having to rebase a lot :)
From skimming over this series here, it looks quite nice, I especially love promoting the semihosting load to a proper filesystem. The only drawback seems to be that this will break existing scripts used by people in their deployments, which rely on the smhload command. I don't really know if there are actually any users doing so, but I guess we will find out.
Yeah, I'm not sure what the stance on shell compatibility is. As I understand it, for the C API only in-tree users matter. However, shell commands are more of an "external" API, used by distro boot scripts. Simon/Tom, what's the process for this?
Well, in this case we can be a bit more cavalier than typical because of the very limited user base. So long as we have good documentation around it including something around how to transition to the new commands, it should be fine to do so, when the code is otherwise ready.
OK, I will add some more documentation about transitioning to this series.
--Sean

On Thu, 10 Mar 2022 11:48:50 -0500 Sean Anderson sean.anderson@seco.com wrote:
Hi,
On 3/4/22 1:46 PM, Tom Rini wrote:
On Fri, Mar 04, 2022 at 12:19:27PM -0500, Sean Anderson wrote:
Hi Andre,
On 3/4/22 6:47 AM, Andre Przywara wrote:
On Fri, 4 Mar 2022 02:06:03 +0100 Linus Walleij linus.walleij@linaro.org wrote:
Hi,
Linus, thanks for the heads up, much appreciated!
On Thu, Mar 3, 2022 at 9:44 PM Sean Anderson sean.anderson@seco.com wrote:
The main device affected by these changes is vexpress64, so I'd appreciate if Linus (or anyone else) could try booting.
As it happens, I am sitting on a series updating vexpress_aemv8a_semi, and letting it use OF_CONTROL. I will send this ASAP. As it turned out, the automatic semihosting boot command is actually broken in v2022.01, the fix is the first patch in my series. This clashes with this series, but it's easy to resolve.
I, for one, appreciate that the boot command is no longer all one line after your series.
Simon/Tom, which series would you like to be based off the other?
I think it's however it's easiest for you two to collaborate.
I think it will be cleaner for me to base my series on his, but I just want to avoid having to rebase a lot :)
Yeah, it should just be this one line, though, right? Tom, would you consider taking patch 01/11 now, as this fixes a regression? The Sean could at least rebase on top of this. Rebasing on top of the rest should be more straight-forward, because it's not one super-long line anymore.
From skimming over this series here, it looks quite nice, I especially love promoting the semihosting load to a proper filesystem. The only drawback seems to be that this will break existing scripts used by people in their deployments, which rely on the smhload command. I don't really know if there are actually any users doing so, but I guess we will find out.
Yeah, I'm not sure what the stance on shell compatibility is. As I understand it, for the C API only in-tree users matter. However, shell commands are more of an "external" API, used by distro boot scripts. Simon/Tom, what's the process for this?
Well, in this case we can be a bit more cavalier than typical because of the very limited user base. So long as we have good documentation
Yes, I agree. I don't think there are many users. The fact that it's broken in v2022.01 and nobody complained so far tells you something. And I can certainly handle a good part of the users internally here. I guess the other half is in Linaro ;-)
Cheers, Andre
around it including something around how to transition to the new commands, it should be fine to do so, when the code is otherwise ready.
OK, I will add some more documentation about transitioning to this series.
--Sean

On 3/10/22 12:01 PM, Andre Przywara wrote:
On Thu, 10 Mar 2022 11:48:50 -0500 Sean Anderson sean.anderson@seco.com wrote:
Hi,
On 3/4/22 1:46 PM, Tom Rini wrote:
On Fri, Mar 04, 2022 at 12:19:27PM -0500, Sean Anderson wrote:
Hi Andre,
On 3/4/22 6:47 AM, Andre Przywara wrote:
On Fri, 4 Mar 2022 02:06:03 +0100 Linus Walleij linus.walleij@linaro.org wrote:
Hi,
Linus, thanks for the heads up, much appreciated!
On Thu, Mar 3, 2022 at 9:44 PM Sean Anderson sean.anderson@seco.com wrote:
> The main device affected by these changes is vexpress64, so I'd appreciate > if Linus (or anyone else) could try booting.
As it happens, I am sitting on a series updating vexpress_aemv8a_semi, and letting it use OF_CONTROL. I will send this ASAP. As it turned out, the automatic semihosting boot command is actually broken in v2022.01, the fix is the first patch in my series. This clashes with this series, but it's easy to resolve.
I, for one, appreciate that the boot command is no longer all one line after your series.
Simon/Tom, which series would you like to be based off the other?
I think it's however it's easiest for you two to collaborate.
I think it will be cleaner for me to base my series on his, but I just want to avoid having to rebase a lot :)
Yeah, it should just be this one line, though, right? Tom, would you consider taking patch 01/11 now, as this fixes a regression? The Sean could at least rebase on top of this. Rebasing on top of the rest should be more straight-forward, because it's not one super-long line anymore.
The patch which makes the boot command multi-line is [PATCH 07/11] vexpress64: fvp: add distro_boot support. I'm not sure how much that patch depends on the others, but presumably you would need to apply 5 and 6 as well.
--Sean
From skimming over this series here, it looks quite nice, I especially love promoting the semihosting load to a proper filesystem. The only drawback seems to be that this will break existing scripts used by people in their deployments, which rely on the smhload command. I don't really know if there are actually any users doing so, but I guess we will find out.
Yeah, I'm not sure what the stance on shell compatibility is. As I understand it, for the C API only in-tree users matter. However, shell commands are more of an "external" API, used by distro boot scripts. Simon/Tom, what's the process for this?
Well, in this case we can be a bit more cavalier than typical because of the very limited user base. So long as we have good documentation
Yes, I agree. I don't think there are many users. The fact that it's broken in v2022.01 and nobody complained so far tells you something. And I can certainly handle a good part of the users internally here. I guess the other half is in Linaro ;-)
Cheers, Andre
around it including something around how to transition to the new commands, it should be fine to do so, when the code is otherwise ready.
OK, I will add some more documentation about transitioning to this series.
--Sean

On Thu, Mar 10, 2022 at 12:06:48PM -0500, Sean Anderson wrote:
On 3/10/22 12:01 PM, Andre Przywara wrote:
On Thu, 10 Mar 2022 11:48:50 -0500 Sean Anderson sean.anderson@seco.com wrote:
Hi,
On 3/4/22 1:46 PM, Tom Rini wrote:
On Fri, Mar 04, 2022 at 12:19:27PM -0500, Sean Anderson wrote:
Hi Andre,
On 3/4/22 6:47 AM, Andre Przywara wrote:
On Fri, 4 Mar 2022 02:06:03 +0100 Linus Walleij linus.walleij@linaro.org wrote:
Hi,
Linus, thanks for the heads up, much appreciated!
> On Thu, Mar 3, 2022 at 9:44 PM Sean Anderson sean.anderson@seco.com wrote: > > > The main device affected by these changes is vexpress64, so I'd appreciate > > if Linus (or anyone else) could try booting.
As it happens, I am sitting on a series updating vexpress_aemv8a_semi, and letting it use OF_CONTROL. I will send this ASAP. As it turned out, the automatic semihosting boot command is actually broken in v2022.01, the fix is the first patch in my series. This clashes with this series, but it's easy to resolve.
I, for one, appreciate that the boot command is no longer all one line after your series.
Simon/Tom, which series would you like to be based off the other?
I think it's however it's easiest for you two to collaborate.
I think it will be cleaner for me to base my series on his, but I just want to avoid having to rebase a lot :)
Yeah, it should just be this one line, though, right? Tom, would you consider taking patch 01/11 now, as this fixes a regression? The Sean could at least rebase on top of this. Rebasing on top of the rest should be more straight-forward, because it's not one super-long line anymore.
The patch which makes the boot command multi-line is [PATCH 07/11] vexpress64: fvp: add distro_boot support. I'm not sure how much that patch depends on the others, but presumably you would need to apply 5 and 6 as well.
Um, so for clarity, should I take: https://patchwork.ozlabs.org/project/uboot/patch/20220304163018.3167841-2-an... or if it's more than just that, how about a regression-fixes-only series for me to take for this release? Thanks!

On Thu, 10 Mar 2022 12:16:16 -0500 Tom Rini trini@konsulko.com wrote:
On Thu, Mar 10, 2022 at 12:06:48PM -0500, Sean Anderson wrote:
On 3/10/22 12:01 PM, Andre Przywara wrote:
On Thu, 10 Mar 2022 11:48:50 -0500 Sean Anderson sean.anderson@seco.com wrote:
Hi,
On 3/4/22 1:46 PM, Tom Rini wrote:
On Fri, Mar 04, 2022 at 12:19:27PM -0500, Sean Anderson wrote:
Hi Andre,
On 3/4/22 6:47 AM, Andre Przywara wrote: > On Fri, 4 Mar 2022 02:06:03 +0100 > Linus Walleij linus.walleij@linaro.org wrote: > > Hi, > > Linus, thanks for the heads up, much appreciated! > >> On Thu, Mar 3, 2022 at 9:44 PM Sean Anderson sean.anderson@seco.com wrote: >> >> > The main device affected by these changes is vexpress64, so I'd appreciate >> > if Linus (or anyone else) could try booting. > > As it happens, I am sitting on a series updating vexpress_aemv8a_semi, and > letting it use OF_CONTROL. I will send this ASAP. > As it turned out, the automatic semihosting boot command is actually broken > in v2022.01, the fix is the first patch in my series. This clashes with > this series, but it's easy to resolve.
I, for one, appreciate that the boot command is no longer all one line after your series.
Simon/Tom, which series would you like to be based off the other?
I think it's however it's easiest for you two to collaborate.
I think it will be cleaner for me to base my series on his, but I just want to avoid having to rebase a lot :)
Yeah, it should just be this one line, though, right? Tom, would you consider taking patch 01/11 now, as this fixes a regression? The Sean could at least rebase on top of this. Rebasing on top of the rest should be more straight-forward, because it's not one super-long line anymore.
The patch which makes the boot command multi-line is [PATCH 07/11] vexpress64: fvp: add distro_boot support. I'm not sure how much that patch depends on the others, but presumably you would need to apply 5 and 6 as well.
Um, so for clarity, should I take: https://patchwork.ozlabs.org/project/uboot/patch/20220304163018.3167841-2-an...
Yes, please, it's really just this one patch that fixes the regression. This is also the reason I refrained from sending a separate series, plus the other patches (trivially) depend on it.
Thanks! Andre
or if it's more than just that, how about a regression-fixes-only series for me to take for this release? Thanks!
participants (4)
-
Andre Przywara
-
Linus Walleij
-
Sean Anderson
-
Tom Rini