diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c index 0d21827e1b..a8aa9def27 100644 --- a/arch/sandbox/cpu/os.c +++ b/arch/sandbox/cpu/os.c @@ -783,12 +783,14 @@ int os_jump_to_image(const void *dest, int size) return os_jump_to_file(fname, true); } -int os_find_u_boot(char *fname, int maxlen, bool use_img) +int os_find_u_boot(char *fname, int maxlen, bool use_img, + const char *cur_prefix, const char *next_prefix) { struct sandbox_state *state = state_get_current(); const char *progname = state->argv[0]; int len = strlen(progname); - const char *suffix; + char subdir[10]; + char *suffix; char *p; int fd; @@ -798,45 +800,36 @@ int os_find_u_boot(char *fname, int maxlen, bool use_img) strcpy(fname, progname); suffix = fname + len - 4; - /* If we are TPL, boot to SPL */ - if (!strcmp(suffix, "-tpl")) { - fname[len - 3] = 's'; - fd = os_open(fname, O_RDONLY); - if (fd >= 0) { - close(fd); - return 0; - } + /* Change the existing suffix to the new one */ + if (*suffix != '-') + return -EINVAL; - /* Look for 'u-boot-spl' in the spl/ directory */ - p = strstr(fname, "/spl/"); - if (p) { - p[1] = 's'; - fd = os_open(fname, O_RDONLY); - if (fd >= 0) { - close(fd); - return 0; - } - } - return -ENOENT; + if (*next_prefix) + strcpy(suffix + 1, next_prefix); /* e.g. "-tpl" to "-spl" */ + else + *suffix = '\0'; /* e.g. "-spl" to "" */ + fd = os_open(fname, O_RDONLY); + if (fd >= 0) { + close(fd); + return 0; } - /* Look for 'u-boot' in the same directory as 'u-boot-spl' */ - if (!strcmp(suffix, "-spl")) { - fname[len - 4] = '\0'; - fd = os_open(fname, O_RDONLY); - if (fd >= 0) { - close(fd); - return 0; - } - } - - /* Look for 'u-boot' in the parent directory of spl/ */ - p = strstr(fname, "spl/"); + /* + * We didn't find it, so try looking for 'u-boot-xxx' in the xxx/ + * directory. Replace the old dirname with the new one. + */ + snprintf(subdir, sizeof(subdir), "/%s/", cur_prefix); + p = strstr(fname, subdir); if (p) { - /* Remove the "spl" characters */ - memmove(p, p + 4, strlen(p + 4) + 1); + if (*next_prefix) + /* e.g. ".../tpl/u-boot-spl" to "../spl/u-boot-spl" */ + memcpy(p + 1, next_prefix, strlen(next_prefix)); + else + /* e.g. ".../spl/u-boot" to ".../u-boot" */ + strcpy(p, p + 1 + strlen(cur_prefix)); if (use_img) strcat(p, ".img"); + fd = os_open(fname, O_RDONLY); if (fd >= 0) { close(fd); diff --git a/arch/sandbox/cpu/spl.c b/arch/sandbox/cpu/spl.c index f82b0d3de1..650bdb0a70 100644 --- a/arch/sandbox/cpu/spl.c +++ b/arch/sandbox/cpu/spl.c @@ -17,6 +17,20 @@ DECLARE_GLOBAL_DATA_PTR; +int sandbox_find_next_phase(char *fname, int maxlen, bool use_img) +{ + const char *cur_prefix, *next_prefix; + int ret; + + cur_prefix = spl_phase_prefix(spl_phase()); + next_prefix = spl_phase_prefix(spl_next_phase()); + ret = os_find_u_boot(fname, maxlen, use_img, cur_prefix, next_prefix); + if (ret) + return log_msg_ret("find", ret); + + return 0; +} + /* SPL / TPL init function */ void board_init_f(ulong flag) { @@ -37,7 +51,7 @@ static int spl_board_load_image(struct spl_image_info *spl_image, char fname[256]; int ret; - ret = os_find_u_boot(fname, sizeof(fname), false); + ret = sandbox_find_next_phase(fname, sizeof(fname), false); if (ret) { printf("(%s not found, error %d)\n", fname, ret); return ret; diff --git a/arch/sandbox/include/asm/spl.h b/arch/sandbox/include/asm/spl.h index 51e9d95d55..d25dc7c82a 100644 --- a/arch/sandbox/include/asm/spl.h +++ b/arch/sandbox/include/asm/spl.h @@ -12,4 +12,17 @@ enum { BOOT_DEVICE_BOARD, }; +/** + * sandbox_find_next_phase() - Find the next phase of U-Boot + * + * This function is intended to be called from within sandbox SPL. It uses + * a few rules to find the filename of the next U-Boot phase. See also + * os_find_u_boot(). + * + * @fname: place to put full path to U-Boot + * @maxlen: maximum size of @fname + * @use_img: select the 'u-boot.img' file instead of the 'u-boot' ELF file + */ +int sandbox_find_next_phase(char *fname, int maxlen, bool use_img); + #endif diff --git a/include/os.h b/include/os.h index bd1096eb8b..7b20d606dd 100644 --- a/include/os.h +++ b/include/os.h @@ -327,9 +327,12 @@ int os_jump_to_image(const void *dest, int size); * @fname: place to put full path to U-Boot * @maxlen: maximum size of @fname * @use_img: select the 'u-boot.img' file instead of the 'u-boot' ELF file + * @cur_prefix: prefix of current executable, e.g. "spl" or "tpl" + * @next_prefix: prefix of executable to find, e.g. "spl" or "" * Return: 0 if OK, -NOSPC if the filename is too large, -ENOENT if not found */ -int os_find_u_boot(char *fname, int maxlen, bool use_img); +int os_find_u_boot(char *fname, int maxlen, bool use_img, + const char *cur_prefix, const char *next_prefix); /** * os_spl_to_uboot() - Run U-Boot proper diff --git a/include/spl.h b/include/spl.h index c643943482..d88fb79a67 100644 --- a/include/spl.h +++ b/include/spl.h @@ -176,6 +176,27 @@ static inline const char *spl_phase_name(enum u_boot_phase phase) } } +/** + * spl_phase_prefix() - Get the prefix of the current phase + * + * @phase: Phase to look up + * @return phase prefix ("spl", "tpl", etc.) + */ +static inline const char *spl_phase_prefix(enum u_boot_phase phase) +{ + switch (phase) { + case PHASE_TPL: + return "tpl"; + case PHASE_SPL: + return "spl"; + case PHASE_BOARD_F: + case PHASE_BOARD_R: + return ""; + default: + return "phase?"; + } +} + /* A string name for SPL or TPL */ #ifdef CONFIG_SPL_BUILD # ifdef CONFIG_TPL_BUILD diff --git a/test/image/spl_load.c b/test/image/spl_load.c index 851603ddd7..e7cabf5680 100644 --- a/test/image/spl_load.c +++ b/test/image/spl_load.c @@ -56,6 +56,7 @@ struct image_header *spl_get_load_buffer(ssize_t offset, size_t size) static int spl_test_load(struct unit_test_state *uts) { + const char *cur_prefix, *next_prefix; struct spl_image_info image; struct image_header *header; struct text_ctx text_ctx; @@ -68,7 +69,10 @@ static int spl_test_load(struct unit_test_state *uts) load.bl_len = 512; load.read = read_fit_image; - ret = os_find_u_boot(fname, sizeof(fname), true); + cur_prefix = spl_phase_prefix(spl_phase()); + next_prefix = spl_phase_prefix(spl_next_phase()); + ret = os_find_u_boot(fname, sizeof(fname), true, cur_prefix, + next_prefix); if (ret) { printf("(%s not found, error %d)\n", fname, ret); return ret;