pxe: Return the file size from the getfile() function

It is pretty strange that the pxe code uses the 'filesize' environment
variable find the size of a file it has just read.

Partly this is because it uses the command-line interpreter to parse its
request to load the file.

As a first step towards unwinding this, return it directly from the
getfile() function. This makes the code a bit longer, for now, but will be
cleaned up in future patches.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Artem Lapkin <email2tema@gmail.com>
Tested-by: Artem Lapkin <email2tema@gmail.com>
Reviewed-by: Ramon Fried <rfried.dev@gmail.com>
diff --git a/boot/pxe_utils.c b/boot/pxe_utils.c
index 48fb707..a7a84f2 100644
--- a/boot/pxe_utils.c
+++ b/boot/pxe_utils.c
@@ -30,6 +30,20 @@
 
 #define MAX_TFTP_PATH_LEN 512
 
+int pxe_get_file_size(ulong *sizep)
+{
+	const char *val;
+
+	val = from_env("filesize");
+	if (!val)
+		return -ENOENT;
+
+	if (strict_strtoul(val, 16, sizep) < 0)
+		return -EINVAL;
+
+	return 0;
+}
+
 /**
  * format_mac_pxe() - obtain a MAC address in the PXE format
  *
@@ -75,14 +89,17 @@
  * @ctx: PXE context
  * @file_path: File path to read (relative to the PXE file)
  * @file_addr: Address to load file to
+ * @filesizep: If not NULL, returns the file size in bytes
  * Returns 1 for success, or < 0 on error
  */
 static int get_relfile(struct pxe_context *ctx, const char *file_path,
-		       unsigned long file_addr)
+		       unsigned long file_addr, ulong *filesizep)
 {
 	size_t path_len;
 	char relfile[MAX_TFTP_PATH_LEN + 1];
 	char addr_buf[18];
+	ulong size;
+	int ret;
 
 	if (file_path[0] == '/' && ctx->allow_abs_path)
 		*relfile = '\0';
@@ -103,7 +120,13 @@
 
 	sprintf(addr_buf, "%lx", file_addr);
 
-	return ctx->getfile(ctx, relfile, addr_buf);
+	ret = ctx->getfile(ctx, relfile, addr_buf, &size);
+	if (ret < 0)
+		return log_msg_ret("get", ret);
+	if (filesizep)
+		*filesizep = size;
+
+	return 1;
 }
 
 /**
@@ -117,29 +140,17 @@
  * Returns 1 for success, or < 0 on error
  */
 int get_pxe_file(struct pxe_context *ctx, const char *file_path,
-		 unsigned long file_addr)
+		 ulong file_addr)
 {
-	unsigned long config_file_size;
-	char *tftp_filesize;
+	ulong size;
 	int err;
 	char *buf;
 
-	err = get_relfile(ctx, file_path, file_addr);
+	err = get_relfile(ctx, file_path, file_addr, &size);
 	if (err < 0)
 		return err;
 
-	/*
-	 * the file comes without a NUL byte at the end, so find out its size
-	 * and add the NUL byte.
-	 */
-	tftp_filesize = from_env("filesize");
-	if (!tftp_filesize)
-		return -ENOENT;
-
-	if (strict_strtoul(tftp_filesize, 16, &config_file_size) < 0)
-		return -EINVAL;
-
-	buf = map_sysmem(file_addr + config_file_size, 1);
+	buf = map_sysmem(file_addr + size, 1);
 	*buf = '\0';
 	unmap_sysmem(buf);
 
@@ -184,12 +195,13 @@
  * @file_path: File path to read (relative to the PXE file)
  * @envaddr_name: Name of environment variable which contains the address to
  *	load to
+ * @filesizep: Returns the file size in bytes
  * Returns 1 on success, -ENOENT if @envaddr_name does not exist as an
  *	environment variable, -EINVAL if its format is not valid hex, or other
  *	value < 0 on other error
  */
 static int get_relfile_envaddr(struct pxe_context *ctx, const char *file_path,
-			       const char *envaddr_name)
+			       const char *envaddr_name, ulong *filesizep)
 {
 	unsigned long file_addr;
 	char *envaddr;
@@ -201,7 +213,7 @@
 	if (strict_strtoul(envaddr, 16, &file_addr) < 0)
 		return -EINVAL;
 
-	return get_relfile(ctx, file_path, file_addr);
+	return get_relfile(ctx, file_path, file_addr, filesizep);
 }
 
 /**
@@ -357,8 +369,8 @@
 			goto skip_overlay;
 
 		/* Load overlay file */
-		err = get_relfile_envaddr(ctx, overlayfile,
-					  "fdtoverlay_addr_r");
+		err = get_relfile_envaddr(ctx, overlayfile, "fdtoverlay_addr_r",
+					  NULL);
 		if (err < 0) {
 			printf("Failed loading overlay %s\n", overlayfile);
 			goto skip_overlay;
@@ -443,21 +455,25 @@
 	}
 
 	if (label->initrd) {
-		if (get_relfile_envaddr(ctx, label->initrd, "ramdisk_addr_r") < 0) {
+		ulong size;
+
+		if (get_relfile_envaddr(ctx, label->initrd, "ramdisk_addr_r",
+					&size) < 0) {
 			printf("Skipping %s for failure retrieving initrd\n",
 			       label->name);
 			return 1;
 		}
 
 		initrd_addr_str = env_get("ramdisk_addr_r");
-		strncpy(initrd_filesize, env_get("filesize"), 9);
+		strcpy(initrd_filesize, simple_xtoa(size));
 
 		strncpy(initrd_str, initrd_addr_str, 18);
 		strcat(initrd_str, ":");
 		strncat(initrd_str, initrd_filesize, 9);
 	}
 
-	if (get_relfile_envaddr(ctx, label->kernel, "kernel_addr_r") < 0) {
+	if (get_relfile_envaddr(ctx, label->kernel, "kernel_addr_r",
+				NULL) < 0) {
 		printf("Skipping %s for failure retrieving kernel\n",
 		       label->name);
 		return 1;
@@ -599,7 +615,7 @@
 
 		if (fdtfile) {
 			int err = get_relfile_envaddr(ctx, fdtfile,
-						      "fdt_addr_r");
+						      "fdt_addr_r", NULL);
 
 			free(fdtfilefree);
 			if (err < 0) {
@@ -1403,7 +1419,7 @@
 	if (IS_ENABLED(CONFIG_CMD_BMP)) {
 		/* display BMP if available */
 		if (cfg->bmp) {
-			if (get_relfile(ctx, cfg->bmp, image_load_addr)) {
+			if (get_relfile(ctx, cfg->bmp, image_load_addr, NULL)) {
 				if (CONFIG_IS_ENABLED(CMD_CLS))
 					run_command("cls", 0);
 				bmp_display(image_load_addr,