mail archive of the barebox mailing list
 help / color / mirror / Atom feed
From: Sascha Hauer <s.hauer@pengutronix.de>
To: "open list:BAREBOX" <barebox@lists.infradead.org>
Subject: [PATCH v2 09/20] fip: add fip_image_open()
Date: Wed, 12 Feb 2025 15:09:22 +0100	[thread overview]
Message-ID: <20250212-k3-emmc-v2-9-8dd1bb0ce60a@pengutronix.de> (raw)
In-Reply-To: <20250212-k3-emmc-v2-0-8dd1bb0ce60a@pengutronix.de>

This adds a fip_image_open() function as an alternative to fip_parse().
Unline fip_parse() the new function:

- Allows to specify an offset with the file for reading a FIP image from
  partitions
- Does not read past the image when the FIP image is on a partition
  which is bigger than the FIP image
- less memory consumption

fip_image_open() is mainly useful for reading a FIP image without the
intent of modifying it.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 include/fiptool.h |   4 ++
 lib/fip.c         | 132 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 135 insertions(+), 1 deletion(-)

diff --git a/include/fiptool.h b/include/fiptool.h
index 6a12466c29..bc42f7edd6 100644
--- a/include/fiptool.h
+++ b/include/fiptool.h
@@ -30,12 +30,14 @@ struct fip_image_desc {
 struct fip_image {
 	struct fip_toc_entry toc_e;
 	void                *buffer;
+	bool                 buf_no_free;
 };
 
 struct fip_state {
 	struct list_head descs;
 	size_t nr_image_descs;
 	int verbose;
+	void *buffer;
 };
 
 #define pr_verbose(...) do { \
@@ -92,4 +94,6 @@ extern toc_entry_t plat_def_toc_entries[];
 #define fip_for_each_desc_safe(fip, e, tmp) \
         list_for_each_entry_safe(e, tmp, &(fip)->descs, list)
 
+struct fip_state *fip_image_open(const char *filename, size_t offset);
+
 #endif /* FIPTOOL_H */
diff --git a/lib/fip.c b/lib/fip.c
index 075cd0e1e6..39b0fd20aa 100644
--- a/lib/fip.c
+++ b/lib/fip.c
@@ -58,7 +58,8 @@ void fip_free_image_desc(struct fip_image_desc *desc)
 	free(desc->cmdline_name);
 	free(desc->action_arg);
 	if (desc->image) {
-		free(desc->image->buffer);
+		if (!desc->image->buf_no_free)
+			free(desc->image->buffer);
 		free(desc->image);
 	}
 	free(desc);
@@ -92,6 +93,7 @@ void fip_free(struct fip_state *fip)
 
 	ASSERT(fip->nr_image_descs == 0);
 
+	free(fip->buffer);
 	free(fip);
 }
 
@@ -430,3 +432,131 @@ int fip_update(struct fip_state *fip)
 
 	return 0;
 }
+
+/*
+ * fip_image_open - open a FIP image for readonly access
+ * @filename: The filename of the FIP image
+ * @offset: The offset of the FIP image in the file
+ *
+ * This opens a FIP image for readonly access. This is an alternative
+ * implementation for fip_parse() with these differences:
+ * - suitable for reading FIP images from raw partitions. This function
+ *   only reads the FIP image, even when the partition is bigger than the
+ *   image
+ * - Allows to specify an offset within the partition where the FIP image
+ *   starts
+ * - Do not memdup the images from the full FIP image
+ *
+ * This function is for easy readonly access to the images within the FIP
+ * image. Do not call any of the above FIP manipulation functions other than
+ * fip_free() on an image opened with this function.
+ */
+struct fip_state *fip_image_open(const char *filename, size_t offset)
+{
+	fip_toc_header_t toc_header;
+	int ret;
+	int fd;
+	struct fip_state *fip_state;
+	LIST_HEAD(entries);
+	size_t fip_headers_size, total = 0;
+	struct fip_image_desc *desc;
+	off_t pos;
+	int n_entries = 0;
+
+	fd = open(filename, O_RDONLY);
+	if (fd < 0)
+		return ERR_PTR(fd);
+
+	fip_state = fip_new();
+
+	pos = lseek(fd, offset, SEEK_SET);
+	if (pos != offset) {
+		ret = -EINVAL;
+		goto err;
+	}
+
+	ret = read_full(fd, &toc_header, sizeof(toc_header));
+	if (ret < 0)
+		goto err;
+
+	if (ret < sizeof(toc_header)) {
+		ret = -ENODATA;
+		goto err;
+	}
+
+	if (toc_header.name != TOC_HEADER_NAME) {
+		pr_err("%s is not a FIP file: unknown magic = 0x%08x\n",
+		       filename, toc_header.name);
+		ret = -EINVAL;
+		goto err;
+	}
+
+	/* read all toc entries */
+	while (1) {
+		struct fip_image_desc *desc = xzalloc(sizeof(*desc));
+		struct fip_image *image = xzalloc(sizeof(*image));
+		struct fip_toc_entry *toc_entry = &image->toc_e;
+
+		desc->image = image;
+
+		ret = read_full(fd, toc_entry, sizeof(*toc_entry));
+		if (ret < 0)
+			goto err;
+		if (ret < sizeof(*toc_entry)) {
+			ret = -ENODATA;
+			goto err;
+		}
+
+		list_add_tail(&desc->list, &fip_state->descs);
+
+		pr_debug("Read TOC entry %pU %llu %llu\n", &toc_entry->uuid,
+			 toc_entry->offset_address, toc_entry->size);
+
+		/* Found the ToC terminator, we are done. */
+		if (uuid_is_null(&toc_entry->uuid))
+			break;
+	}
+
+	/* determine buffer size */
+	fip_for_each_desc(fip_state, desc) {
+		uint64_t this_end = desc->image->toc_e.offset_address + desc->image->toc_e.size;
+
+		if (this_end > total)
+			total = this_end;
+		n_entries++;
+	}
+
+	fip_headers_size = n_entries * sizeof(struct fip_toc_entry) + sizeof(fip_toc_header_t);
+
+	total -= fip_headers_size;
+
+	fip_state->buffer = malloc(total);
+	if (!fip_state->buffer) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	ret = read_full(fd, fip_state->buffer, total);
+	if (ret < 0)
+		goto err;
+
+	if (ret < total) {
+		ret = -ENODATA;
+		goto err;
+	}
+
+	close(fd);
+
+	fip_for_each_desc(fip_state, desc) {
+		desc->image->buffer = fip_state->buffer +
+			desc->image->toc_e.offset_address - fip_headers_size;
+		desc->image->buf_no_free = true;
+	}
+
+	return fip_state;
+err:
+	close(fd);
+	fip_free(fip_state);
+
+	return ERR_PTR(ret);
+}

-- 
2.39.5




  parent reply	other threads:[~2025-02-12 14:10 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-02-12 14:09 [PATCH v2 00/20] ARM: K3 updates Sascha Hauer
2025-02-12 14:09 ` [PATCH v2 01/20] ARM: k3: Add function to enable 32k crystal Sascha Hauer
2025-02-12 14:09 ` [PATCH v2 02/20] ARM: k3: add function to detect eMMC boot Sascha Hauer
2025-02-12 14:09 ` [PATCH v2 03/20] ARM: k3: do not mount /boot when booting from eMMC Sascha Hauer
2025-02-12 14:09 ` [PATCH v2 04/20] fip: drop typedefs Sascha Hauer
2025-02-12 14:09 ` [PATCH v2 05/20] fip: use linux list implementation Sascha Hauer
2025-02-12 14:09 ` [PATCH v2 06/20] fip: use uuid_equal() and uuid_is_null() Sascha Hauer
2025-02-12 14:09 ` [PATCH v2 07/20] fiptool: do not typedef structs Sascha Hauer
2025-02-12 14:09 ` [PATCH v2 08/20] fip: add fip_ prefix Sascha Hauer
2025-02-12 14:09 ` Sascha Hauer [this message]
2025-02-12 14:09 ` [PATCH v2 10/20] ARM: k3: r5: add USB DFU and eMMC boot support Sascha Hauer
2025-02-12 14:09 ` [PATCH v2 11/20] ARM: am625-sk: enable 32k crystal Sascha Hauer
2025-02-12 14:09 ` [PATCH v2 12/20] mci: am654: parse generic mmc node properties Sascha Hauer
2025-02-12 14:09 ` [PATCH v2 13/20] ARM: k3: limit eMMC frequency to 26MHz Sascha Hauer
2025-02-12 14:09 ` [PATCH v2 14/20] ARM: k3: add eMMC barebox update handler Sascha Hauer
2025-02-12 14:09 ` [PATCH v2 15/20] ARM: am625-sk: put environment on eMMC when booting from it Sascha Hauer
2025-02-12 14:09 ` [PATCH v2 16/20] serial: omap: Use ttyS as Linux console name Sascha Hauer
2025-02-12 14:09 ` [PATCH v2 17/20] ARM: k3: remove beagleplay FIT image Sascha Hauer
2025-02-12 14:09 ` [PATCH v2 18/20] ARM: am625-sk: cleanup board entry Sascha Hauer
2025-02-12 14:09 ` [PATCH v2 19/20] ARM: beagleplay: " Sascha Hauer
2025-02-12 14:09 ` [PATCH v2 20/20] ARM: k3: Add k3-r5_defconfig Sascha Hauer
2025-02-17 11:14 ` [PATCH v2 00/20] ARM: K3 updates Sascha Hauer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250212-k3-emmc-v2-9-8dd1bb0ce60a@pengutronix.de \
    --to=s.hauer@pengutronix.de \
    --cc=barebox@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox