[PATCH 15/24] bootstd: Allow reading a logo for the OS

Simon Glass sjg at chromium.org
Mon Oct 17 22:29:51 CEST 2022


Some operating systems provide a logo in bmp format. Read this in if
present so it can be displayed in the menu.

Signed-off-by: Simon Glass <sjg at chromium.org>
---

 boot/bootmeth-uclass.c | 69 ++++++++++++++++++++++++++++++++++++------
 boot/bootmeth_script.c |  4 +++
 cmd/bootflow.c         |  6 ++++
 include/bootflow.h     |  4 +++
 include/bootmeth.h     | 16 ++++++++++
 test/boot/bootflow.c   |  1 +
 6 files changed, 91 insertions(+), 9 deletions(-)

diff --git a/boot/bootmeth-uclass.c b/boot/bootmeth-uclass.c
index 25552dd96f6..4c3529d1555 100644
--- a/boot/bootmeth-uclass.c
+++ b/boot/bootmeth-uclass.c
@@ -290,25 +290,19 @@ int bootmeth_try_file(struct bootflow *bflow, struct blk_desc *desc,
 	return 0;
 }
 
-int bootmeth_alloc_file(struct bootflow *bflow, uint size_limit, uint align)
+static int alloc_file(const char *fname, uint size, void **bufp)
 {
 	loff_t bytes_read;
 	ulong addr;
 	char *buf;
-	uint size;
 	int ret;
 
-	size = bflow->size;
-	log_debug("   - script file size %x\n", size);
-	if (size > size_limit)
-		return log_msg_ret("chk", -E2BIG);
-
-	buf = memalign(align, size + 1);
+	buf = malloc(size + 1);
 	if (!buf)
 		return log_msg_ret("buf", -ENOMEM);
 	addr = map_to_sysmem(buf);
 
-	ret = fs_read(bflow->fname, addr, 0, 0, &bytes_read);
+	ret = fs_read(fname, addr, 0, size, &bytes_read);
 	if (ret) {
 		free(buf);
 		return log_msg_ret("read", ret);
@@ -316,12 +310,69 @@ int bootmeth_alloc_file(struct bootflow *bflow, uint size_limit, uint align)
 	if (size != bytes_read)
 		return log_msg_ret("bread", -EINVAL);
 	buf[size] = '\0';
+
+	*bufp = buf;
+
+	return 0;
+}
+
+int bootmeth_alloc_file(struct bootflow *bflow, uint size_limit, uint align)
+{
+	void *buf;
+	uint size;
+	int ret;
+
+	size = bflow->size;
+	log_debug("   - script file size %x\n", size);
+	if (size > size_limit)
+		return log_msg_ret("chk", -E2BIG);
+
+	ret = alloc_file(bflow->fname, bflow->size, &buf);
+	if (ret)
+		return log_msg_ret("all", ret);
+
 	bflow->state = BOOTFLOWST_READY;
 	bflow->buf = buf;
 
 	return 0;
 }
 
+int bootmeth_alloc_other(struct bootflow *bflow, const char *fname,
+			 void **bufp, uint *sizep)
+{
+	struct blk_desc *desc = NULL;
+	char path[200];
+	loff_t size;
+	void *buf;
+	int ret;
+
+	snprintf(path, sizeof(path), "%s%s", bflow->subdir, fname);
+	log_debug("trying: %s\n", path);
+
+	if (bflow->blk)
+		desc = dev_get_uclass_plat(bflow->blk);
+
+	ret = setup_fs(bflow, desc);
+	if (ret)
+		return log_msg_ret("fs", ret);
+
+	ret = fs_size(path, &size);
+	log_debug("   %s - err=%d\n", path, ret);
+
+	ret = setup_fs(bflow, desc);
+	if (ret)
+		return log_msg_ret("fs", ret);
+
+	ret = alloc_file(path, size, &buf);
+	if (ret)
+		return log_msg_ret("all", ret);
+
+	*bufp = buf;
+	*sizep = size;
+
+	return 0;
+}
+
 int bootmeth_common_read_file(struct udevice *dev, struct bootflow *bflow,
 			      const char *file_path, ulong addr, ulong *sizep)
 {
diff --git a/boot/bootmeth_script.c b/boot/bootmeth_script.c
index 8ba9d93a080..abfe0580d92 100644
--- a/boot/bootmeth_script.c
+++ b/boot/bootmeth_script.c
@@ -109,6 +109,10 @@ static int script_read_bootflow(struct udevice *dev, struct bootflow *bflow)
 	if (ret)
 		return log_msg_ret("inf", ret);
 
+	ret = bootmeth_alloc_other(bflow, "boot.bmp", &bflow->logo,
+				   &bflow->logo_size);
+	/* ignore error */
+
 	return 0;
 }
 
diff --git a/cmd/bootflow.c b/cmd/bootflow.c
index 6b8ac8c8504..495ef85f25b 100644
--- a/cmd/bootflow.c
+++ b/cmd/bootflow.c
@@ -338,6 +338,12 @@ static int do_bootflow_info(struct cmd_tbl *cmdtp, int flag, int argc,
 	printf("Buffer:    %lx\n", (ulong)map_to_sysmem(bflow->buf));
 	printf("Size:      %x (%d bytes)\n", bflow->size, bflow->size);
 	printf("OS:        %s\n", bflow->os_name ? bflow->os_name : "(none)");
+	printf("Logo:      %s\n", bflow->logo ?
+	       simple_xtoa((ulong)map_to_sysmem(bflow->logo)) : "(none)");
+	if (bflow->logo) {
+		printf("Logo size: %x (%d bytes)\n", bflow->logo_size,
+		       bflow->logo_size);
+	}
 	printf("Error:     %d\n", bflow->err);
 	if (dump && bflow->buf) {
 		/* Set some sort of maximum on the size */
diff --git a/include/bootflow.h b/include/bootflow.h
index 776158c65df..8a07ab30191 100644
--- a/include/bootflow.h
+++ b/include/bootflow.h
@@ -49,6 +49,8 @@ enum bootflow_state_t {
  * @state: Current state (enum bootflow_state_t)
  * @subdir: Subdirectory to fetch files from (with trailing /), or NULL if none
  * @fname: Filename of bootflow file (allocated)
+ * @logo: Logo to display for this bootflow (BMP format)
+ * @logo_size: Size of the logo in bytes
  * @buf: Bootflow file contents (allocated)
  * @size: Size of bootflow file in bytes
  * @err: Error number received (0 if OK)
@@ -67,6 +69,8 @@ struct bootflow {
 	enum bootflow_state_t state;
 	char *subdir;
 	char *fname;
+	void *logo;
+	uint logo_size;
 	char *buf;
 	int size;
 	int err;
diff --git a/include/bootmeth.h b/include/bootmeth.h
index 50ded055f3f..669b14ce81e 100644
--- a/include/bootmeth.h
+++ b/include/bootmeth.h
@@ -265,6 +265,22 @@ int bootmeth_try_file(struct bootflow *bflow, struct blk_desc *desc,
  */
 int bootmeth_alloc_file(struct bootflow *bflow, uint size_limit, uint align);
 
+/**
+ * bootmeth_alloc_other() - Allocate and read a file for a bootflow
+ *
+ * This reads an arbitrary file in the same directory as the bootflow,
+ * allocating memory for it. The buffer is one byte larger than the file length,
+ * so that it can be nul-terminated.
+ *
+ * @bflow: Information about file to read
+ * @fname: Filename to read from (within bootflow->subdir)
+ * @bufp: Returns a pointer to the allocated buffer
+ * @sizep: Returns the size of the buffer
+ * Return: 0 if OK,  -ENOMEM if out of memory, other -ve on other error
+ */
+int bootmeth_alloc_other(struct bootflow *bflow, const char *fname,
+			 void **bufp, uint *sizep);
+
 /**
  * bootmeth_common_read_file() - Common handler for reading a file
  *
diff --git a/test/boot/bootflow.c b/test/boot/bootflow.c
index 3296316cf0d..00dfd990687 100644
--- a/test/boot/bootflow.c
+++ b/test/boot/bootflow.c
@@ -189,6 +189,7 @@ static int bootflow_cmd_info(struct unit_test_state *uts)
 	ut_assert_nextlinen("Buffer:    ");
 	ut_assert_nextline("Size:      253 (595 bytes)");
 	ut_assert_nextline("OS:        Fedora-Workstation-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl)");
+	ut_assert_nextline("Logo:      (none)");
 	ut_assert_nextline("Error:     0");
 	ut_assert_console_end();
 
-- 
2.38.0.413.g74048e4d9e-goog



More information about the U-Boot mailing list