* [PATCH 2/2] fip: add function to parse FIP from a buffer
2025-02-17 12:25 [PATCH 1/2] fip: Store image data in single buffer Sascha Hauer
@ 2025-02-17 12:25 ` Sascha Hauer
0 siblings, 0 replies; 2+ messages in thread
From: Sascha Hauer @ 2025-02-17 12:25 UTC (permalink / raw)
To: Barebox List
So far we can only parse a FIP image from a file. Provide fip_parse_buf()
to open a FIP image from a buffer.
The bulk of fip_parse() can be re-used for that. While at it use
read_file_2() to read in the FIP image.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
include/fiptool.h | 4 +++
lib/fip.c | 92 ++++++++++++++++++++++++++---------------------
2 files changed, 56 insertions(+), 40 deletions(-)
diff --git a/include/fiptool.h b/include/fiptool.h
index bc42f7edd6..bb63a79c16 100644
--- a/include/fiptool.h
+++ b/include/fiptool.h
@@ -38,6 +38,7 @@ struct fip_state {
size_t nr_image_descs;
int verbose;
void *buffer;
+ bool buf_no_free;
};
#define pr_verbose(...) do { \
@@ -68,6 +69,9 @@ struct fip_image_desc *fip_lookup_image_desc_from_uuid(struct fip_state *fip,
struct fip_image_desc *fip_lookup_image_desc_from_opt(struct fip_state *fip, char **arg);
+int fip_parse_buf(struct fip_state *fip, void *buf, size_t size,
+ fip_toc_header_t *toc_header_out);
+
int fip_parse(struct fip_state *fip,
const char *filename, fip_toc_header_t *toc_header_out);
diff --git a/lib/fip.c b/lib/fip.c
index 806f172318..23e82098da 100644
--- a/lib/fip.c
+++ b/lib/fip.c
@@ -22,6 +22,7 @@
#include <stdlib.h>
#include <string.h>
#include <libfile.h>
+#include <fs.h>
#include <fip.h>
#include <fiptool.h>
@@ -93,7 +94,9 @@ void fip_free(struct fip_state *fip)
ASSERT(fip->nr_image_descs == 0);
- free(fip->buffer);
+ if (!fip->buf_no_free)
+ free(fip->buffer);
+
free(fip);
}
@@ -155,44 +158,20 @@ struct fip_image_desc *fip_lookup_image_desc_from_opt(struct fip_state *fip, cha
return NULL;
}
-int fip_parse(struct fip_state *fip,
- const char *filename, fip_toc_header_t *toc_header_out)
+static int fip_do_parse_buf(struct fip_state *fip, void *buf, size_t size,
+ fip_toc_header_t *toc_header_out)
{
- struct stat st;
- int fd;
char *bufend;
fip_toc_header_t *toc_header;
fip_toc_entry_t *toc_entry;
int terminated = 0;
- size_t st_size;
-
- if (fip->buffer)
- return -EBUSY;
-
- fd = open(filename, O_RDONLY);
- if (fd < 0) {
- pr_err("open %s: %m\n", filename);
- return -errno;
- }
-
- if (fstat(fd, &st) == -1) {
- pr_err("fstat %s: %m\n", filename);
- return -errno;
- }
-
- st_size = st.st_size;
- fip->buffer = xmalloc(st_size);
- if (read_full(fd, fip->buffer, st_size) != st_size) {
- pr_err("Failed to read %s: %m\n", filename);
- return -errno;
- }
+ fip->buffer = buf;
- bufend = fip->buffer + st_size;
- close(fd);
+ bufend = fip->buffer + size;
- if (st_size < sizeof(fip_toc_header_t)) {
- pr_err("FIP %s is truncated\n", filename);
+ if (size < sizeof(fip_toc_header_t)) {
+ pr_err("FIP is truncated\n");
return -ENODATA;
}
@@ -200,8 +179,8 @@ int fip_parse(struct fip_state *fip,
toc_entry = (fip_toc_entry_t *)(toc_header + 1);
if (toc_header->name != TOC_HEADER_NAME) {
- pr_err("%s is not a FIP file: unknown magic = 0x%08x\n",
- filename, toc_header->name);
+ pr_err("not a FIP file: unknown magic = 0x%08x\n",
+ toc_header->name);
return -EINVAL;
}
@@ -230,13 +209,12 @@ int fip_parse(struct fip_state *fip,
image->buf_no_free = true;
/* Overflow checks before memory copy. */
if (toc_entry->size > (uint64_t)-1 - toc_entry->offset_address) {
- pr_err("FIP %s is corrupted: entry size exceeds 64 bit address space\n",
- filename);
+ pr_err("FIP is corrupted: entry size exceeds 64 bit address space\n");
return -EINVAL;
}
- if (toc_entry->size + toc_entry->offset_address > st_size) {
- pr_err("FIP %s is corrupted: entry size (0x%llx) exceeds FIP file size (0x%zx)\n",
- filename, toc_entry->size + toc_entry->offset_address, st_size);
+ if (toc_entry->size + toc_entry->offset_address > size) {
+ pr_err("FIP is corrupted: entry size (0x%llx) exceeds FIP file size (0x%zx)\n",
+ toc_entry->size + toc_entry->offset_address, size);
return -EINVAL;
}
@@ -261,14 +239,48 @@ int fip_parse(struct fip_state *fip,
}
if (terminated == 0) {
- pr_err("FIP %s does not have a ToC terminator entry\n",
- filename);
+ pr_err("FIP does not have a ToC terminator entry\n");
return -EINVAL;
}
return 0;
}
+int fip_parse_buf(struct fip_state *fip, void *buf, size_t size,
+ fip_toc_header_t *toc_header_out)
+{
+ if (fip->buffer)
+ return -EBUSY;
+
+ fip->buf_no_free = true;
+
+ return fip_do_parse_buf(fip, buf, size, toc_header_out);
+}
+
+int fip_parse(struct fip_state *fip,
+ const char *filename, fip_toc_header_t *toc_header_out)
+{
+ size_t size;
+ int ret;
+ void *buf;
+
+ if (fip->buffer)
+ return -EBUSY;
+
+ ret = read_file_2(filename, &size, &buf, FILESIZE_MAX);
+ if (ret) {
+ pr_err("open %s: %m\n", filename);
+ return ret;
+ }
+
+ ret = fip_parse_buf(fip, buf, size, toc_header_out);
+
+ if (ret)
+ free(buf);
+
+ return ret;
+}
+
static struct fip_image *fip_read_image_from_file(const uuid_t *uuid, const char *filename)
{
struct stat st;
--
2.39.5
^ permalink raw reply [flat|nested] 2+ messages in thread