sandbox: Support executables for more phases

The SPL header has a function for obtaining the phase in capital letters,
e.g. 'SPL'. Add one for lower-case also, as used by sandbox.

Use this to generalise the sandbox logic for determining the filename of
the next sandbox executable. This can provide support for VPL.

Signed-off-by: Simon Glass <sjg@chromium.org>
diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c
index 0d21827..a8aa9de 100644
--- a/arch/sandbox/cpu/os.c
+++ b/arch/sandbox/cpu/os.c
@@ -783,12 +783,14 @@
 	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 @@
 	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 f82b0d3..650bdb0 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 @@
 	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 51e9d95..d25dc7c 100644
--- a/arch/sandbox/include/asm/spl.h
+++ b/arch/sandbox/include/asm/spl.h
@@ -12,4 +12,17 @@
 	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