From 858fefd5fc3ae9006a0f545d7744e6f95270b14d Mon Sep 17 00:00:00 2001
From: Simon Glass <sjg@chromium.org>
Date: Fri, 6 Jan 2023 08:52:27 -0600
Subject: [PATCH] image: Add a function to find a script in an image

Split this functionality out of the 'source' command so it can be used
from another place. For now leave it where it is, but a future patch will
move it out of cmd/

Signed-off-by: Simon Glass <sjg@chromium.org>
---
 cmd/source.c    | 217 ++++++++++++++++++++++++++----------------------
 include/image.h |  14 ++++
 2 files changed, 130 insertions(+), 101 deletions(-)

diff --git a/cmd/source.c b/cmd/source.c
index 94da5d8d6a..1186a541bc 100644
--- a/cmd/source.c
+++ b/cmd/source.c
@@ -24,7 +24,6 @@
 #include <asm/byteorder.h>
 #include <asm/io.h>
 
-#if defined(CONFIG_FIT)
 /**
  * get_default_image() - Return default property from /images
  *
@@ -40,149 +39,165 @@ static const char *get_default_image(const void *fit)
 
 	return fdt_getprop(fit, images_noffset, FIT_DEFAULT_PROP, NULL);
 }
-#endif
 
-int image_source_script(ulong addr, const char *fit_uname, const char *confname)
+int image_locate_script(void *buf, int size, const char *fit_uname,
+			const char *confname, char **datap, uint *lenp)
 {
 	ulong		len;
-#if defined(CONFIG_LEGACY_IMAGE_FORMAT)
 	const struct legacy_img_hdr *hdr;
-#endif
 	u32		*data;
 	int		verify;
-	void *buf;
-#if defined(CONFIG_FIT)
 	const void*	fit_hdr;
 	int		noffset;
 	const void	*fit_data;
 	size_t		fit_len;
-#endif
 
 	verify = env_get_yesno("verify");
 
-	buf = map_sysmem(addr, 0);
 	switch (genimg_get_format(buf)) {
-#if defined(CONFIG_LEGACY_IMAGE_FORMAT)
 	case IMAGE_FORMAT_LEGACY:
-		hdr = buf;
+		if (IS_ENABLED(CONFIG_LEGACY_IMAGE_FORMAT)) {
+			hdr = buf;
 
-		if (!image_check_magic (hdr)) {
-			puts ("Bad magic number\n");
-			return 1;
-		}
+			if (!image_check_magic(hdr)) {
+				puts("Bad magic number\n");
+				return 1;
+			}
 
-		if (!image_check_hcrc (hdr)) {
-			puts ("Bad header crc\n");
-			return 1;
-		}
+			if (!image_check_hcrc(hdr)) {
+				puts("Bad header crc\n");
+				return 1;
+			}
+
+			if (verify) {
+				if (!image_check_dcrc(hdr)) {
+					puts("Bad data crc\n");
+					return 1;
+				}
+			}
 
-		if (verify) {
-			if (!image_check_dcrc (hdr)) {
-				puts ("Bad data crc\n");
+			if (!image_check_type(hdr, IH_TYPE_SCRIPT)) {
+				puts("Bad image type\n");
 				return 1;
 			}
-		}
 
-		if (!image_check_type (hdr, IH_TYPE_SCRIPT)) {
-			puts ("Bad image type\n");
-			return 1;
-		}
+			/* get length of script */
+			data = (u32 *)image_get_data(hdr);
 
-		/* get length of script */
-		data = (u32 *)image_get_data (hdr);
+			len = uimage_to_cpu(*data);
+			if (!len) {
+				puts("Empty Script\n");
+				return 1;
+			}
 
-		if ((len = uimage_to_cpu (*data)) == 0) {
-			puts ("Empty Script\n");
-			return 1;
+			/*
+			 * scripts are just multi-image files with one
+			 * component, so seek past the zero-terminated sequence
+			 * of image lengths to get to the actual image data
+			 */
+			while (*data++);
 		}
-
-		/*
-		 * scripts are just multi-image files with one component, seek
-		 * past the zero-terminated sequence of image lengths to get
-		 * to the actual image data
-		 */
-		while (*data++);
 		break;
-#endif
-#if defined(CONFIG_FIT)
 	case IMAGE_FORMAT_FIT:
-		fit_hdr = buf;
-		if (fit_check_format(fit_hdr, IMAGE_SIZE_INVAL)) {
-			puts ("Bad FIT image format\n");
-			return 1;
-		}
-
-		if (!fit_uname) {
-			/* If confname is empty, use the default */
-			if (confname && *confname)
-				noffset = fit_conf_get_node(fit_hdr, confname);
-			else
-				noffset = fit_conf_get_node(fit_hdr, NULL);
-			if (noffset < 0) {
-				if (!confname)
-					goto fallback;
-				printf("Could not find config %s\n", confname);
+		if (IS_ENABLED(CONFIG_FIT)) {
+			fit_hdr = buf;
+			if (fit_check_format(fit_hdr, IMAGE_SIZE_INVAL)) {
+				puts("Bad FIT image format\n");
 				return 1;
 			}
 
-			if (verify && fit_config_verify(fit_hdr, noffset))
-				return 1;
+			if (!fit_uname) {
+				/* If confname is empty, use the default */
+				if (confname && *confname)
+					noffset = fit_conf_get_node(fit_hdr, confname);
+				else
+					noffset = fit_conf_get_node(fit_hdr, NULL);
+				if (noffset < 0) {
+					if (!confname)
+						goto fallback;
+					printf("Could not find config %s\n", confname);
+					return 1;
+				}
+
+				if (verify && fit_config_verify(fit_hdr, noffset))
+					return 1;
+
+				noffset = fit_conf_get_prop_node(fit_hdr,
+								 noffset,
+								 FIT_SCRIPT_PROP,
+								 IH_PHASE_NONE);
+				if (noffset < 0) {
+					if (!confname)
+						goto fallback;
+					printf("Could not find script in %s\n", confname);
+					return 1;
+				}
+			} else {
+fallback:
+				if (!fit_uname || !*fit_uname)
+					fit_uname = get_default_image(fit_hdr);
+				if (!fit_uname) {
+					puts("No FIT subimage unit name\n");
+					return 1;
+				}
+
+				/* get script component image node offset */
+				noffset = fit_image_get_node(fit_hdr, fit_uname);
+				if (noffset < 0) {
+					printf("Can't find '%s' FIT subimage\n",
+					      fit_uname);
+					return 1;
+				}
+			}
 
-			noffset = fit_conf_get_prop_node(fit_hdr, noffset,
-							 FIT_SCRIPT_PROP,
-							 IH_PHASE_NONE);
-			if (noffset < 0) {
-				if (!confname)
-					goto fallback;
-				printf("Could not find script in %s\n", confname);
+			if (!fit_image_check_type(fit_hdr, noffset,
+						  IH_TYPE_SCRIPT)) {
+				puts("Not a image image\n");
 				return 1;
 			}
-		} else {
-fallback:
-			if (!fit_uname || !*fit_uname)
-				fit_uname = get_default_image(fit_hdr);
-			if (!fit_uname) {
-				puts("No FIT subimage unit name\n");
+
+			/* verify integrity */
+			if (verify && !fit_image_verify(fit_hdr, noffset)) {
+				puts("Bad Data Hash\n");
 				return 1;
 			}
 
-			/* get script component image node offset */
-			noffset = fit_image_get_node(fit_hdr, fit_uname);
-			if (noffset < 0) {
-				printf("Can't find '%s' FIT subimage\n",
-				       fit_uname);
+			/* get script subimage data address and length */
+			if (fit_image_get_data(fit_hdr, noffset, &fit_data, &fit_len)) {
+				puts("Could not find script subimage data\n");
 				return 1;
 			}
-		}
-
-		if (!fit_image_check_type (fit_hdr, noffset, IH_TYPE_SCRIPT)) {
-			puts("Not a script image\n");
-			return 1;
-		}
-
-		/* verify integrity */
-		if (verify && !fit_image_verify(fit_hdr, noffset)) {
-			puts("Bad Data Hash\n");
-			return 1;
-		}
 
-		/* get script subimage data address and length */
-		if (fit_image_get_data (fit_hdr, noffset, &fit_data, &fit_len)) {
-			puts ("Could not find script subimage data\n");
-			return 1;
+			data = (u32 *)fit_data;
+			len = (ulong)fit_len;
 		}
-
-		data = (u32 *)fit_data;
-		len = (ulong)fit_len;
 		break;
-#endif
 	default:
-		puts ("Wrong image format for \"source\" command\n");
-		return 1;
+		puts("Wrong image format for \"source\" command\n");
+		return -EPERM;
 	}
 
-	debug("** Script length: %ld\n", len);
-	return run_command_list((char *)data, len, 0);
+	*datap = (char *)data;
+	*lenp = len;
+
+	return 0;
+}
+
+int image_source_script(ulong addr, const char *fit_uname, const char *confname)
+{
+	char *data;
+	void *buf;
+	uint len;
+	int ret;
+
+	buf = map_sysmem(addr, 0);
+	ret = image_locate_script(buf, 0, fit_uname, confname, &data, &len);
+	unmap_sysmem(buf);
+	if (ret)
+		return CMD_RET_FAILURE;
+
+	debug("** Script length: %d\n", len);
+	return run_command_list(data, len, 0);
 }
 
 /**************************************************/
diff --git a/include/image.h b/include/image.h
index bed75ce1b3..f7ebe9cbe8 100644
--- a/include/image.h
+++ b/include/image.h
@@ -729,6 +729,20 @@ int fit_image_load(struct bootm_headers *images, ulong addr,
 int image_source_script(ulong addr, const char *fit_uname,
 			const char *confname);
 
+/**
+ * image_locate_script() - Locate the raw script in an image
+ *
+ * @buf: Address of image
+ * @size: Size of image in bytes
+ * @fit_uname: Node name of FIT image to read
+ * @confname: Node name of FIT config to read
+ * @datap: Returns pointer to raw script on success
+ * @lenp: Returns size of raw script on success
+ * @return 0 if OK, non-zero on error
+ */
+int image_locate_script(void *buf, int size, const char *fit_uname,
+			const char *confname, char **datap, uint *lenp);
+
 /**
  * fit_get_node_from_config() - Look up an image a FIT by type
  *
-- 
2.39.5