summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorTom Rini <[email protected]>2022-04-02 15:28:43 -0400
committerTom Rini <[email protected]>2022-04-02 15:28:43 -0400
commit10d615f2fcc0d2ef1d611844eb6032fe0fca8afd (patch)
treefc64ed7fef66e55214c75b98a90531645a203294 /include
parent5b160c3a13f80708b4a720119cd2a1ef161e57f0 (diff)
parent7a763471894feb58d5a1bdf78ea7014c7a952264 (diff)
Merge branch '2022-04-01-arm-semihosting-cleanups-and-new-features' into next
This brings in two related series. The first from Andre: This series is the continuation of last year's effort to support the new Armv8-R64 application profile. This led to a significant rework of the existing fastmodel (FVP) support, to both upgrade it to newest U-Boot standards (OF_CONTROL and distro_boot support), but also to generalise the code, so that plugging in the v8-R64 support in the last patch gets much easier. This is because apart from the twisted memory map between the two profiles there is actually little difference, when it comes to U-Boot relevant parts of the hardware. I kept the legacy semihosting support (which picks up magic files from the current directory), but if that fails, we go and try virtio-blk (.iso installer images work), then virtio-net. Please have a look, and give it a try, if possible. Both the v8-R and v8-A FVP models are available for free on the Arm website[1]. Patch 01/11 fixes a regression introduced in December, it should be applied now. The rest of the patches are for the next merge window. [1] https://developer.arm.com/tools-and-software/simulation-models/fast-models And the second from Sean (where we exclude 27, 28 and 29 for now): 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 - falling back to normal drivers if semihosting is disabled The main device affected by these changes is vexpress64, so I'd appreciate if Andre (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. The patches in this series are organized as follows: 0-4: rST conversions and other documentation updates 5-9: Semihosting cleanups 10-14: Filesystem support (including SPL boot device) 15-16: Serial support 16: Documentation update 17: JTAG boot support for LS1046A 19-25: Semihosting fallback 26-29: DM puts support The last two groups of patches are "bonus;" the first 17 patches stand on their own. The last two groups could be broken out as separate series, but I have kept them in this one to help with my sanity (and not have to deal with too many outstanding series). Patch 14 depends on [1] to apply cleanly. Patch 17 depends on [2] for correctness. This series should be applied to u-boot/next (in particular, the EROFS series must have been applied). [1] https://lore.kernel.org/u-boot/CACRpkdZ+9fmNjC_mvrbPa9-iuTQVd8UkJ7Zpe7cL0c5vZygsVw@mail.gmail.com/T/ [2] https://lore.kernel.org/u-boot/[email protected]/
Diffstat (limited to 'include')
-rw-r--r--include/configs/ls1046ardb.h2
-rw-r--r--include/configs/vexpress_aemv8.h159
-rw-r--r--include/fs.h1
-rw-r--r--include/semihosting.h149
-rw-r--r--include/semihostingfs.h21
-rw-r--r--include/serial.h19
6 files changed, 311 insertions, 40 deletions
diff --git a/include/configs/ls1046ardb.h b/include/configs/ls1046ardb.h
index 04c3ad02c8f..df699bca34a 100644
--- a/include/configs/ls1046ardb.h
+++ b/include/configs/ls1046ardb.h
@@ -140,6 +140,8 @@
#endif
#endif
+#define CONFIG_SPL_FS_LOAD_PAYLOAD_NAME "u-boot.img"
+
#include <asm/fsl_secure_boot.h>
#endif /* __LS1046ARDB_H__ */
diff --git a/include/configs/vexpress_aemv8.h b/include/configs/vexpress_aemv8.h
index b956bd91478..4f0ff239e68 100644
--- a/include/configs/vexpress_aemv8.h
+++ b/include/configs/vexpress_aemv8.h
@@ -20,8 +20,13 @@
#define CONFIG_SYS_BOOTM_LEN (64 << 20) /* Increase max gunzip size */
/* CS register bases for the original memory map. */
-#define V2M_BASE 0x80000000
+#ifdef CONFIG_TARGET_VEXPRESS64_BASER_FVP
+#define V2M_DRAM_BASE 0x00000000
+#define V2M_PA_BASE 0x80000000
+#else
+#define V2M_DRAM_BASE 0x80000000
#define V2M_PA_BASE 0x00000000
+#endif
#define V2M_PA_CS0 (V2M_PA_BASE + 0x00000000)
#define V2M_PA_CS1 (V2M_PA_BASE + 0x14000000)
@@ -99,10 +104,8 @@
#define CONFIG_PL011_CLOCK 24000000
#endif
-/* Miscellaneous configurable options */
-
/* Physical Memory Map */
-#define PHYS_SDRAM_1 (V2M_BASE) /* SDRAM Bank #1 */
+#define PHYS_SDRAM_1 (V2M_DRAM_BASE) /* SDRAM Bank #1 */
/* Top 16MB reserved for secure world use */
#define DRAM_SEC_SIZE 0x01000000
#define PHYS_SDRAM_1_SIZE 0x80000000 - DRAM_SEC_SIZE
@@ -116,11 +119,7 @@
#define PHYS_SDRAM_2_SIZE 0x80000000
#endif
-/* Enable memtest */
-
-/* Initial environment variables */
-#ifdef CONFIG_TARGET_VEXPRESS64_JUNO
-/* Copy the kernel and FDT to DRAM memory and boot */
+/* Copy the kernel, initrd and FDT from NOR flash to DRAM memory and boot. */
#define BOOTENV_DEV_AFS(devtypeu, devtypel, instance) \
"bootcmd_afs=" \
"afs load ${kernel_name} ${kernel_addr_r} ;"\
@@ -143,6 +142,54 @@
"booti ${kernel_addr_r} ${ramdisk_param} ${fdt_addr_r}\0"
#define BOOTENV_DEV_NAME_AFS(devtypeu, devtypel, instance) "afs "
+/* Boot by executing a U-Boot script pre-loaded into DRAM. */
+#define BOOTENV_DEV_MEM(devtypeu, devtypel, instance) \
+ "bootcmd_mem= " \
+ "source ${scriptaddr}; " \
+ "if test $? -eq 1; then " \
+ " env import -t ${scriptaddr}; " \
+ " if test -n $uenvcmd; then " \
+ " echo Running uenvcmd ...; " \
+ " run uenvcmd; " \
+ " fi; " \
+ "fi\0"
+#define BOOTENV_DEV_NAME_MEM(devtypeu, devtypel, instance) "mem "
+
+#ifdef CONFIG_CMD_VIRTIO
+#define FUNC_VIRTIO(func) func(VIRTIO, virtio, 0)
+#else
+#define FUNC_VIRTIO(func)
+#endif
+
+/*
+ * Boot by loading an Android image, or kernel, initrd and FDT through
+ * semihosting into DRAM.
+ */
+#define BOOTENV_DEV_SMH(devtypeu, devtypel, instance) \
+ "bootcmd_smh= " \
+ "if load hostfs - ${boot_addr_r} ${boot_name}; then" \
+ " setenv 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" \
+ " if load hostfs - ${kernel_addr_r} ${kernel_name}; then" \
+ " setenv fdt_high 0xffffffffffffffff;" \
+ " setenv initrd_high 0xffffffffffffffff;" \
+ " load hostfs - ${fdt_addr_r} ${fdtfile};" \
+ " load hostfs - ${ramdisk_addr_r} ${ramdisk_name};" \
+ " fdt addr ${fdt_addr_r};" \
+ " fdt resize;" \
+ " fdt chosen ${ramdisk_addr_r} ${filesize};" \
+ " booti $kernel_addr_r - $fdt_addr_r;" \
+ " fi;" \
+ "fi\0"
+#define BOOTENV_DEV_NAME_SMH(devtypeu, devtypel, instance) "smh "
+
+/* Boot sources for distro boot and load addresses, per board */
+
+#ifdef CONFIG_TARGET_VEXPRESS64_JUNO /* Arm Juno board */
+
#define BOOT_TARGET_DEVICES(func) \
func(USB, usb, 0) \
func(SATA, sata, 0) \
@@ -151,42 +198,74 @@
func(DHCP, dhcp, na) \
func(AFS, afs, na)
-#include <config_distro_bootcmd.h>
+#define VEXPRESS_KERNEL_ADDR 0x80080000
+#define VEXPRESS_PXEFILE_ADDR 0x8fb00000
+#define VEXPRESS_FDT_ADDR 0x8fc00000
+#define VEXPRESS_SCRIPT_ADDR 0x8fd00000
+#define VEXPRESS_RAMDISK_ADDR 0x8fe00000
-/*
- * Defines where the kernel and FDT exist in NOR flash and where it will
- * be copied into DRAM
- */
-#define CONFIG_EXTRA_ENV_SETTINGS \
- "kernel_name=norkern\0" \
- "kernel_alt_name=Image\0" \
- "kernel_addr_r=0x80080000\0" \
- "ramdisk_name=ramdisk.img\0" \
- "ramdisk_addr_r=0x88000000\0" \
- "fdtfile=board.dtb\0" \
- "fdt_alt_name=juno\0" \
- "fdt_addr_r=0x80000000\0" \
- BOOTENV
-
-#elif CONFIG_TARGET_VEXPRESS64_BASE_FVP
-
-#define VEXPRESS_KERNEL_ADDR 0x80080000
-#define VEXPRESS_FDT_ADDR 0x8fc00000
-#define VEXPRESS_BOOT_ADDR 0x8fd00000
-#define VEXPRESS_RAMDISK_ADDR 0x8fe00000
+#define EXTRA_ENV_NAMES \
+ "kernel_name=norkern\0" \
+ "kernel_alt_name=Image\0" \
+ "ramdisk_name=ramdisk.img\0" \
+ "fdtfile=board.dtb\0" \
+ "fdt_alt_name=juno\0"
-#define CONFIG_EXTRA_ENV_SETTINGS \
- "kernel_name=Image\0" \
- "kernel_addr_r=" __stringify(VEXPRESS_KERNEL_ADDR) "\0" \
- "ramdisk_name=ramdisk.img\0" \
- "ramdisk_addr_r=" __stringify(VEXPRESS_RAMDISK_ADDR) "\0" \
- "fdtfile=devtree.dtb\0" \
- "fdt_addr_r=" __stringify(VEXPRESS_FDT_ADDR) "\0" \
- "boot_name=boot.img\0" \
- "boot_addr_r=" __stringify(VEXPRESS_BOOT_ADDR) "\0"
+#elif CONFIG_TARGET_VEXPRESS64_BASE_FVP /* ARMv8-A base model */
+
+#define BOOT_TARGET_DEVICES(func) \
+ func(SMH, smh, na) \
+ func(MEM, mem, na) \
+ FUNC_VIRTIO(func) \
+ func(PXE, pxe, na) \
+ func(DHCP, dhcp, na)
+
+#define VEXPRESS_KERNEL_ADDR 0x80080000
+#define VEXPRESS_PXEFILE_ADDR 0x8fa00000
+#define VEXPRESS_SCRIPT_ADDR 0x8fb00000
+#define VEXPRESS_FDT_ADDR 0x8fc00000
+#define VEXPRESS_BOOT_ADDR 0x8fd00000
+#define VEXPRESS_RAMDISK_ADDR 0x8fe00000
+
+#define EXTRA_ENV_NAMES \
+ "kernel_name=Image\0" \
+ "ramdisk_name=ramdisk.img\0" \
+ "fdtfile=devtree.dtb\0" \
+ "boot_name=boot.img\0" \
+ "boot_addr_r=" __stringify(VEXPRESS_BOOT_ADDR) "\0"
+#elif CONFIG_TARGET_VEXPRESS64_BASER_FVP /* ARMv8-R base model */
+
+#define BOOT_TARGET_DEVICES(func) \
+ func(MEM, mem, na) \
+ FUNC_VIRTIO(func) \
+ func(PXE, pxe, na) \
+ func(DHCP, dhcp, na)
+
+#define VEXPRESS_KERNEL_ADDR 0x00200000
+#define VEXPRESS_PXEFILE_ADDR 0x0fb00000
+#define VEXPRESS_FDT_ADDR 0x0fc00000
+#define VEXPRESS_SCRIPT_ADDR 0x0fd00000
+#define VEXPRESS_RAMDISK_ADDR 0x0fe00000
+
+#define EXTRA_ENV_NAMES \
+ "kernel_name=Image\0" \
+ "ramdisk_name=ramdisk.img\0" \
+ "fdtfile=board.dtb\0"
#endif
+#include <config_distro_bootcmd.h>
+
+/* Default load addresses and names for the different payloads. */
+#define CONFIG_EXTRA_ENV_SETTINGS \
+ "kernel_addr_r=" __stringify(VEXPRESS_KERNEL_ADDR) "\0" \
+ "ramdisk_addr_r=" __stringify(VEXPRESS_RAMDISK_ADDR) "\0" \
+ "pxefile_addr_r=" __stringify(VEXPRESS_PXEFILE_ADDR) "\0" \
+ "fdt_addr_r=" __stringify(VEXPRESS_FDT_ADDR) "\0" \
+ "scriptaddr=" __stringify(VEXPRESS_SCRIPT_ADDR) "\0" \
+ EXTRA_ENV_NAMES \
+ BOOTENV
+
/* Monitor Command Prompt */
#define CONFIG_SYS_CBSIZE 512 /* Console I/O Buffer Size */
#define CONFIG_SYS_MAXARGS 64 /* max command args */
diff --git a/include/fs.h b/include/fs.h
index b607b0028dc..e2beba36b98 100644
--- a/include/fs.h
+++ b/include/fs.h
@@ -18,6 +18,7 @@ struct cmd_tbl;
#define FS_TYPE_BTRFS 5
#define FS_TYPE_SQUASHFS 6
#define FS_TYPE_EROFS 7
+#define FS_TYPE_SEMIHOSTING 8
struct blk_desc;
diff --git a/include/semihosting.h b/include/semihosting.h
new file mode 100644
index 00000000000..f1f73464e4f
--- /dev/null
+++ b/include/semihosting.h
@@ -0,0 +1,149 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2022 Sean Anderson <[email protected]>
+ */
+
+#ifndef _SEMIHOSTING_H
+#define _SEMIHOSTING_H
+
+/*
+ * These are the encoded instructions used to indicate a semihosting trap. They
+ * are named like SMH_ISA_INSN, where ISA is the instruction set (e.g.
+ * AArch64), and INSN is the mneumonic for the instruction.
+ */
+#define SMH_A64_HLT 0xD45E0000
+#define SMH_A32_SVC 0xEF123456
+#define SMH_A32_HLT 0xE10F0070
+#define SMH_T32_SVC 0xDFAB
+#define SMH_T32_HLT 0xBABC
+
+#if CONFIG_IS_ENABLED(SEMIHOSTING_FALLBACK)
+/**
+ * semihosting_enabled() - Determine whether semihosting is supported
+ *
+ * Semihosting-based drivers should call this function before making other
+ * semihosting calls.
+ *
+ * Return: %true if a debugger is attached which supports semihosting, %false
+ * otherwise
+ */
+bool semihosting_enabled(void);
+
+/**
+ * disable_semihosting() - Cause semihosting_enabled() to return false
+ *
+ * If U-Boot ever receives an unhandled exception caused by a semihosting trap,
+ * the trap handler should call this function.
+ */
+void disable_semihosting(void);
+#else
+static inline bool semihosting_enabled(void)
+{
+ return CONFIG_IS_ENABLED(SEMIHOSTING);
+}
+
+static inline void disable_semihosting(void)
+{
+}
+#endif
+
+/**
+ * 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,
+};
+
+/**
+ * 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_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()
+ *
+ * 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);
+
+/**
+ * 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);
+
+/**
+ * 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 */
diff --git a/include/semihostingfs.h b/include/semihostingfs.h
new file mode 100644
index 00000000000..25ebdbbeff3
--- /dev/null
+++ b/include/semihostingfs.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2022, Sean Anderson <[email protected]>
+ * 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
diff --git a/include/serial.h b/include/serial.h
index 19a8c0c67d2..8c2e7adbc32 100644
--- a/include/serial.h
+++ b/include/serial.h
@@ -23,6 +23,7 @@ struct serial_device {
void default_serial_puts(const char *s);
extern struct serial_device serial_smc_device;
+extern struct serial_device serial_smh_device;
extern struct serial_device serial_scc_device;
extern struct serial_device *default_serial_console(void);
@@ -195,6 +196,24 @@ struct dm_serial_ops {
*/
int (*putc)(struct udevice *dev, const char ch);
/**
+ * puts() - Write a string
+ *
+ * This writes a string. This function should be implemented only if
+ * writing multiple characters at once is more performant than just
+ * calling putc() in a loop.
+ *
+ * If the whole string cannot be written at once, then this function
+ * should return the number of characters written. Returning a negative
+ * error code implies that no characters were written. If this function
+ * returns 0, then it will be called again with the same arguments.
+ *
+ * @dev: Device pointer
+ * @s: The string to write
+ * @len: The length of the string to write.
+ * @return The number of characters written on success, or -ve on error
+ */
+ ssize_t (*puts)(struct udevice *dev, const char *s, size_t len);
+ /**
* pending() - Check if input/output characters are waiting
*
* This can be used to return an indication of the number of waiting