[U-Boot] [PATCH 1/5] armv8: semihosting: do not inline trap call

The semihosting trap call does not like being inlined, probably because that will mean register reordering screwing up the return value in r0, so tag this function "noinline".
Signed-off-by: Linus Walleij linus.walleij@linaro.org --- arch/arm/lib/semihosting.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/lib/semihosting.c b/arch/arm/lib/semihosting.c index fd6d8573f560..d3f724b726e1 100644 --- a/arch/arm/lib/semihosting.c +++ b/arch/arm/lib/semihosting.c @@ -26,7 +26,7 @@ /* * Call the handler */ -static long smh_trap(unsigned int sysnum, void *addr) +static noinline long smh_trap(unsigned int sysnum, void *addr) { register long result asm("r0"); #if defined(CONFIG_ARM64)

Instead of sprinkling custom code and calls over the Vexpress64 boardfile, create a command that loads images using semihosting just like we would load from flash memory of over the network, using a special command:
smhload <image> <address>
This will make it possible to remove some custom calls and code and make the boot easier.
Signed-off-by: Linus Walleij linus.walleij@linaro.org --- arch/arm/lib/semihosting.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++ doc/README.semihosting | 25 ++++------------- 2 files changed, 75 insertions(+), 20 deletions(-)
diff --git a/arch/arm/lib/semihosting.c b/arch/arm/lib/semihosting.c index d3f724b726e1..edacb1187731 100644 --- a/arch/arm/lib/semihosting.c +++ b/arch/arm/lib/semihosting.c @@ -13,6 +13,7 @@ * for them. */ #include <common.h> +#include <command.h> #include <asm/semihosting.h>
#define SYSOPEN 0x01 @@ -234,3 +235,72 @@ long smh_len(const char *fname) /* Return the file length (or -1 error indication) */ return len; } + +static int smh_load_file(const char * const name, ulong load_addr, + ulong *end_addr) +{ + long fd; + long len; + long ret; + + fd = smh_open(name, "rb"); + if (fd == -1) + return -1; + + len = smh_len_fd(fd); + if (len < 0) { + smh_close(fd); + return -1; + } + + ret = smh_read(fd, (void *)load_addr, len); + smh_close(fd); + + if (ret == 0) { + *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; + } + + return 0; +} + +static int do_smhload(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + if (argc == 3 || argc == 4) { + ulong load_addr; + ulong end_addr = 0; + ulong ret; + char end_str[64]; + + load_addr = simple_strtoul(argv[2], NULL, 16); + if (!load_addr) + return -1; + + ret = smh_load_file(argv[1], load_addr, &end_addr); + if (ret < 0) + return 1; + + /* Optionally save returned end to the environment */ + if (argc == 4) { + sprintf(end_str, "0x%08lx", end_addr); + setenv(argv[3], end_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/doc/README.semihosting b/doc/README.semihosting index 724856078069..c016a4f8406d 100644 --- a/doc/README.semihosting +++ b/doc/README.semihosting @@ -30,25 +30,10 @@ vexpress_aemv8a.h but differentiate the two models by the presence or absence of CONFIG_BASE_FVP. This change is tested and works on both the Foundation and Base fastmodel simulators.
-The level of semihosting support is minimal, restricted to just what it -takes to load images to memory. If more semihosting functionality is -required, such as file seek, outputting strings, reading characters, etc, -then it can be easily added later. +The semihosting code adds a command:
-We require that the board include file define these env variables: -- kernel_name e.g. "uImage" -- kernel_addr_r e.g. "0x80000000" -- initrd_name e.g. "ramdisk.img" -- initrd_addr_r e.g. "0x88000000" -- fdt_name e.g. "devtree.dtb" -- fdt_addr_r e.g. "0x83000000" + smhload <image> <address> [env var]
-Optionally, "fdt_high" and "initrd_high" can be specified as per -their rules for allowing or preventing copying of these images. - -For the "fdt chosen" startup macro, this code will then define: -- initrd_end (based on retrieving initrd_addr_r plus actual initrd_size) - -We will then load the kernel, initrd, and fdt into the specified -locations in memory in a similar way that the ATF fastmodel code -uses semihosting calls to load other boot stages and u-boot itself. +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.

On Mon, Mar 23, 2015 at 11:06:11AM +0100, Linus Walleij wrote:
Instead of sprinkling custom code and calls over the Vexpress64 boardfile, create a command that loads images using semihosting just like we would load from flash memory of over the network, using a special command:
smhload <image> <address>
This will make it possible to remove some custom calls and code and make the boot easier.
Signed-off-by: Linus Walleij linus.walleij@linaro.org
Applied to u-boot/master, thanks!

This removes the kludgy late board init from the FVP simulator version of Versatile Express 64bit (ARMv8), and replace it with a default boot command using the new smhload command to load the files using semihosting. Tested on the Foundation Model.
Signed-off-by: Linus Walleij linus.walleij@linaro.org --- board/armltd/vexpress64/vexpress64.c | 96 ------------------------------------ include/configs/vexpress_aemv8a.h | 18 ++++--- 2 files changed, 10 insertions(+), 104 deletions(-)
diff --git a/board/armltd/vexpress64/vexpress64.c b/board/armltd/vexpress64/vexpress64.c index de6286435d97..876cb678eb03 100644 --- a/board/armltd/vexpress64/vexpress64.c +++ b/board/armltd/vexpress64/vexpress64.c @@ -11,7 +11,6 @@ #include <netdev.h> #include <asm/io.h> #include <linux/compiler.h> -#include <asm/semihosting.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -33,101 +32,6 @@ void reset_cpu(ulong addr) { }
-#ifdef CONFIG_BOARD_LATE_INIT -int board_late_init(void) -{ -#ifdef CONFIG_SEMIHOSTING - /* - * Please refer to doc/README.semihosting for a more complete - * description. - * - * We require that the board include file defines these env variables: - * - kernel_name - * - kernel_addr_r - * - initrd_name - * - initrd_addr_r - * - fdt_name - * - fdt_addr_r - * - * For the "fdt chosen" startup macro, this code will then define: - * - initrd_end (based on initrd_addr_r plus actual initrd_size) - * - * We will then load the kernel, initrd, and fdt into the specified - * locations in memory in a similar way that the ATF fastmodel code - * uses semihosting calls to load other boot stages and u-boot itself. - */ - - /* Env variable strings */ - char *kernel_name = getenv("kernel_name"); - char *kernel_addr_str = getenv("kernel_addr_r"); - char *initrd_name = getenv("initrd_name"); - char *initrd_addr_str = getenv("initrd_addr_r"); - char *fdt_name = getenv("fdt_name"); - char *fdt_addr_str = getenv("fdt_addr_r"); - char initrd_end_str[64]; - - /* Actual addresses converted from env variables */ - void *kernel_addr_r; - void *initrd_addr_r; - void *fdt_addr_r; - - /* Actual initrd base and size */ - unsigned long initrd_base; - unsigned long initrd_size; - - /* Space available */ - int avail; - - /* Make sure the environment variables needed are set */ - if (!(kernel_addr_str && initrd_addr_str && fdt_addr_str)) { - printf("%s: Define {kernel/initrd/fdt}_addr_r\n", __func__); - return -1; - } - if (!(kernel_name && initrd_name && fdt_name)) { - printf("%s: Define {kernel/initrd/fdt}_name\n", __func__); - return -1; - } - - /* Get exact initrd_size */ - initrd_size = smh_len(initrd_name); - if (initrd_size == -1) { - printf("%s: Can't get file size for '%s'\n", __func__, - initrd_name); - return -1; - } - - /* Set initrd_end */ - initrd_base = simple_strtoul(initrd_addr_str, NULL, 16); - initrd_addr_r = (void *)initrd_base; - sprintf(initrd_end_str, "0x%lx", initrd_base + initrd_size - 1); - setenv("initrd_end", initrd_end_str); - - /* Load kernel to memory */ - fdt_addr_r = (void *)simple_strtoul(fdt_addr_str, NULL, 16); - kernel_addr_r = (void *)simple_strtoul(kernel_addr_str, NULL, 16); - - /* - * The kernel must be lower in memory than fdt and loading the - * kernel must not trample the fdt or vice versa. - */ - avail = fdt_addr_r - kernel_addr_r; - if (avail < 0) { - printf("%s: fdt must be after kernel\n", __func__); - return -1; - } - smh_load(kernel_name, kernel_addr_r, avail, 1); - - /* Load fdt to memory */ - smh_load(fdt_name, fdt_addr_r, 0x20000, 1); - - /* Load initrd to memory */ - smh_load(initrd_name, initrd_addr_r, initrd_size, 1); - -#endif /* CONFIG_SEMIHOSTING */ - return 0; -} -#endif /* CONFIG_BOARD_LATE_INIT */ - /* * Board specific ethernet initialization routine. */ diff --git a/include/configs/vexpress_aemv8a.h b/include/configs/vexpress_aemv8a.h index e6fc2aeea2b8..cda89d8ca814 100644 --- a/include/configs/vexpress_aemv8a.h +++ b/include/configs/vexpress_aemv8a.h @@ -15,7 +15,6 @@ #ifndef CONFIG_SEMIHOSTING #error CONFIG_TARGET_VEXPRESS64_BASE_FVP requires CONFIG_SEMIHOSTING #endif -#define CONFIG_BOARD_LATE_INIT #define CONFIG_ARMV8_SWITCH_TO_EL1 #endif
@@ -228,11 +227,11 @@ #elif CONFIG_TARGET_VEXPRESS64_BASE_FVP #define CONFIG_EXTRA_ENV_SETTINGS \ "kernel_name=uImage\0" \ - "kernel_addr_r=0x80000000\0" \ + "kernel_addr=0x80000000\0" \ "initrd_name=ramdisk.img\0" \ - "initrd_addr_r=0x88000000\0" \ - "fdt_name=devtree.dtb\0" \ - "fdt_addr_r=0x83000000\0" \ + "initrd_addr=0x88000000\0" \ + "fdt_name=devtree.dtb\0" \ + "fdt_addr=0x83000000\0" \ "fdt_high=0xffffffffffffffff\0" \ "initrd_high=0xffffffffffffffff\0"
@@ -240,9 +239,12 @@ "0x1c090000 debug user_debug=31 "\ "loglevel=9"
-#define CONFIG_BOOTCOMMAND "fdt addr $fdt_addr_r; fdt resize; " \ - "fdt chosen $initrd_addr_r $initrd_end; " \ - "bootm $kernel_addr_r - $fdt_addr_r" +#define CONFIG_BOOTCOMMAND "smhload ${kernel_name} ${kernel_addr}; " \ + "smhload ${fdt_name} $fdt_addr; " \ + "smhload ${initrd_name} $initrd_addr initrd_end; " \ + "fdt addr $fdt_addr; fdt resize; " \ + "fdt chosen $initrd_addr $initrd_end; " \ + "bootm $kernel_addr - $fdt_addr"
#define CONFIG_BOOTDELAY 1

On Mon, Mar 23, 2015 at 11:06:12AM +0100, Linus Walleij wrote:
This removes the kludgy late board init from the FVP simulator version of Versatile Express 64bit (ARMv8), and replace it with a default boot command using the new smhload command to load the files using semihosting. Tested on the Foundation Model.
Signed-off-by: Linus Walleij linus.walleij@linaro.org
Applied to u-boot/master, thanks!

Now that loading files using semihosting can be done using a command in standard scripts, and we have rewritten the boardfile and added it to the Vexpress64, let's delete the external interface to the semihosting file retrieveal and rely solely on these commands, and staticize them inside that file so the whole business is self-contained.
Signed-off-by: Linus Walleij linus.walleij@linaro.org --- arch/arm/include/asm/semihosting.h | 17 ------- arch/arm/lib/semihosting.c | 92 -------------------------------------- 2 files changed, 109 deletions(-) delete mode 100644 arch/arm/include/asm/semihosting.h
diff --git a/arch/arm/include/asm/semihosting.h b/arch/arm/include/asm/semihosting.h deleted file mode 100644 index 835ca7e4b683..000000000000 --- a/arch/arm/include/asm/semihosting.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright 2014 Broadcom Corporation - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#ifndef __SEMIHOSTING_H__ -#define __SEMIHOSTING_H__ - -/* - * ARM semihosting functions for loading images to memory. See the source - * code for more information. - */ -int smh_load(const char *fname, void *memp, int avail, int verbose); -long smh_len(const char *fname); - -#endif /* __SEMIHOSTING_H__ */ diff --git a/arch/arm/lib/semihosting.c b/arch/arm/lib/semihosting.c index edacb1187731..c3e964eabc13 100644 --- a/arch/arm/lib/semihosting.c +++ b/arch/arm/lib/semihosting.c @@ -14,7 +14,6 @@ */ #include <common.h> #include <command.h> -#include <asm/semihosting.h>
#define SYSOPEN 0x01 #define SYSCLOSE 0x02 @@ -145,97 +144,6 @@ static long smh_len_fd(long fd) return ret; }
-/* - * Open, load a file into memory, and close it. Check that the available space - * is sufficient to store the entire file. Return the bytes actually read from - * the file as seen by the read function. The verbose flag enables some extra - * printing of successful read status. - */ -int smh_load(const char *fname, void *memp, int avail, int verbose) -{ - long ret; - long fd; - size_t len; - - ret = -1; - - debug("%s: fname '%s', avail %u, memp %p\n", __func__, fname, - avail, memp); - - /* Open the file */ - fd = smh_open(fname, "rb"); - if (fd == -1) - return -1; - - /* Get the file length */ - ret = smh_len_fd(fd); - if (ret == -1) { - smh_close(fd); - return -1; - } - - /* Check that the file will fit in the supplied buffer */ - if (ret > avail) { - printf("%s: ERROR ret %ld, avail %u\n", __func__, ret, - avail); - smh_close(fd); - return -1; - } - - len = ret; - - /* Read the file into the buffer */ - ret = smh_read(fd, memp, len); - if (ret == 0) { - /* Print successful load information if requested */ - if (verbose) { - printf("\n%s\n", fname); - printf(" 0x%8p dest\n", memp); - printf(" 0x%08lx size\n", len); - printf(" 0x%08x avail\n", avail); - } - } - - /* Close the file */ - smh_close(fd); - - return ret; -} - -/* - * Get the file length from the filename - */ -long smh_len(const char *fname) -{ - long ret; - long fd; - long len; - - debug("%s: file '%s'\n", __func__, fname); - - /* Open the file */ - fd = smh_open(fname, "rb"); - if (fd < 0) - return fd; - - /* Get the file length */ - len = smh_len_fd(fd); - if (len < 0) { - smh_close(fd); - return len; - } - - /* Close the file */ - ret = smh_close(fd); - if (ret < 0) - return ret; - - debug("%s: returning len %ld\n", __func__, len); - - /* Return the file length (or -1 error indication) */ - return len; -} - static int smh_load_file(const char * const name, ulong load_addr, ulong *end_addr) {

On Mon, Mar 23, 2015 at 11:06:13AM +0100, Linus Walleij wrote:
Now that loading files using semihosting can be done using a command in standard scripts, and we have rewritten the boardfile and added it to the Vexpress64, let's delete the external interface to the semihosting file retrieveal and rely solely on these commands, and staticize them inside that file so the whole business is self-contained.
Signed-off-by: Linus Walleij linus.walleij@linaro.org
Applied to u-boot/master, thanks!

This variant that is neither FVP / Base Model or Juno Versatile Express 64bit is confusing. Get rid of it unless someone can point out what machine that really is. Seems to be an evolutional artifact in the config base.
Signed-off-by: Linus Walleij linus.walleij@linaro.org --- board/armltd/vexpress64/Kconfig | 13 ------------- configs/vexpress_aemv8a_defconfig | 3 --- include/configs/vexpress_aemv8a.h | 28 ++++------------------------ 3 files changed, 4 insertions(+), 40 deletions(-) delete mode 100644 configs/vexpress_aemv8a_defconfig
diff --git a/board/armltd/vexpress64/Kconfig b/board/armltd/vexpress64/Kconfig index 7d5e7bee8b9a..f5693aebacc5 100644 --- a/board/armltd/vexpress64/Kconfig +++ b/board/armltd/vexpress64/Kconfig @@ -1,16 +1,3 @@ -if TARGET_VEXPRESS64_AEMV8A - -config SYS_BOARD - default "vexpress64" - -config SYS_VENDOR - default "armltd" - -config SYS_CONFIG_NAME - default "vexpress_aemv8a" - -endif - if TARGET_VEXPRESS64_BASE_FVP
config SYS_BOARD diff --git a/configs/vexpress_aemv8a_defconfig b/configs/vexpress_aemv8a_defconfig deleted file mode 100644 index 9f4b87655613..000000000000 --- a/configs/vexpress_aemv8a_defconfig +++ /dev/null @@ -1,3 +0,0 @@ -CONFIG_ARM=y -CONFIG_TARGET_VEXPRESS64_AEMV8A=y -CONFIG_DEFAULT_DEVICE_TREE="vexpress64" diff --git a/include/configs/vexpress_aemv8a.h b/include/configs/vexpress_aemv8a.h index cda89d8ca814..027c7d1555ba 100644 --- a/include/configs/vexpress_aemv8a.h +++ b/include/configs/vexpress_aemv8a.h @@ -20,14 +20,6 @@
#define CONFIG_REMAKE_ELF
-#if !defined(CONFIG_TARGET_VEXPRESS64_BASE_FVP) && \ - !defined(CONFIG_TARGET_VEXPRESS64_JUNO) -/* Base FVP and Juno not using GICv3 yet */ -#define CONFIG_GICV3 -#endif - -/*#define CONFIG_ARMV8_SWITCH_TO_EL1*/ - #define CONFIG_SUPPORT_RAW_INITRD
/* Cache Definitions */ @@ -46,8 +38,7 @@ #define CONFIG_SYS_TEXT_BASE 0xe0000000 #define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_SDRAM_BASE + 0x7fff0) #else -#define CONFIG_SYS_TEXT_BASE 0x80000000 -#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_SDRAM_BASE + 0x7fff0) +#error "Unknown board variant" #endif
/* Flat Device Tree Definitions */ @@ -117,10 +108,9 @@ #define GICD_BASE (0x2C010000) #define GICC_BASE (0x2C02f000) #else -#define GICD_BASE (0x2C001000) -#define GICC_BASE (0x2C002000) -#endif +#error "Unknown board variant" #endif +#endif /* !CONFIG_GICV3 */
#define CONFIG_SYS_MEMTEST_START V2M_BASE #define CONFIG_SYS_MEMTEST_END (V2M_BASE + 0x80000000) @@ -249,17 +239,7 @@ #define CONFIG_BOOTDELAY 1
#else - -#define CONFIG_EXTRA_ENV_SETTINGS \ - "kernel_addr_r=0x80000000\0" \ - "initrd_addr_r=0x88000000\0" \ - "fdt_addr_r=0x83000000\0" \ - "fdt_high=0xa0000000\0" - -#define CONFIG_BOOTARGS "console=ttyAMA0,115200n8 root=/dev/ram0" -#define CONFIG_BOOTCOMMAND "bootm $kernel_addr_r " \ - "$initrd_addr_r:$initrd_size $fdt_addr_r" -#define CONFIG_BOOTDELAY -1 +#error "Unknown board variant" #endif
/* Do not preserve environment */

On Mon, Mar 23, 2015 at 11:06:14AM +0100, Linus Walleij wrote:
This variant that is neither FVP / Base Model or Juno Versatile Express 64bit is confusing. Get rid of it unless someone can point out what machine that really is. Seems to be an evolutional artifact in the config base.
Signed-off-by: Linus Walleij linus.walleij@linaro.org
Applied to u-boot/master, thanks!

On Mon, Mar 23, 2015 at 11:06:10AM +0100, Linus Walleij wrote:
The semihosting trap call does not like being inlined, probably because that will mean register reordering screwing up the return value in r0, so tag this function "noinline".
Signed-off-by: Linus Walleij linus.walleij@linaro.org
Applied to u-boot/master, thanks!
participants (2)
-
Linus Walleij
-
Tom Rini