u-boot.lists.denx.de archive mirror
 help / color / mirror / Atom feed
From: Simon Glass <sjg@chromium.org>
To: U-Boot Mailing List <u-boot@lists.denx.de>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>,
	Alexandru Gagniuc <mr.nuke.me@gmail.com>,
	Bin Meng <bmeng.cn@gmail.com>, Tom Rini <trini@konsulko.com>,
	Simon Glass <sjg@chromium.org>
Subject: [PATCH v4 02/15] Add support for an owned buffer
Date: Sat, 25 Sep 2021 07:03:07 -0600	[thread overview]
Message-ID: <20210925070255.v4.2.Iac016f2b531889277f63e4999494a967a823659b@changeid> (raw)
In-Reply-To: <20210925130320.7824-1-sjg@chromium.org>

When passing a data buffer back from a function, it is not always clear
who owns the buffer, i.e. who is responsible for freeing the memory used.
An example of this is where multiple files are decompressed from the
firmware image, using a temporary buffer for reading (since the
compressed data has to live somewhere) and producing a temporary or
permanent buffer with the resuilts.

Where the firmware image can be memory-mapped, as on x86, the compressed
data does not need to be buffered, but the complexity of having a buffer
which is either allocated or not, makes the code hard to understand.

Introduce a new 'abuf' which supports simple buffer operations:

- encapsulating a buffer and its size
- either allocated with malloc() or not
- able to be reliably freed if necessary
- able to be converted to an allocated buffer if needed

This simple API makes it easier to deal with allocated and memory-mapped
buffers.

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

(no changes since v2)

Changes in v2:
- Add new abuf_init_set() function
- Update abuf_realloc() to return after every case
- Use const for abuf_data() and abuf_size()
- Make use of memdup()
- Add abuf_init_move()
- Add comments about the assumptions made by lib_test_abuf_realloc()
- Add better comments about why some tests are skipped at present

 include/abuf.h    | 159 +++++++++++++++++++++
 lib/Makefile      |   1 +
 lib/abuf.c        | 109 +++++++++++++++
 test/lib/Makefile |   1 +
 test/lib/abuf.c   | 344 ++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 614 insertions(+)
 create mode 100644 include/abuf.h
 create mode 100644 lib/abuf.c
 create mode 100644 test/lib/abuf.c

diff --git a/include/abuf.h b/include/abuf.h
new file mode 100644
index 00000000000..d230f72806d
--- /dev/null
+++ b/include/abuf.h
@@ -0,0 +1,159 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Handles a buffer that can be allocated and freed
+ *
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#ifndef __ABUF_H
+#define __ABUF_H
+
+#include <linux/types.h>
+
+/**
+ * struct abuf - buffer that can be allocated and freed
+ *
+ * This is useful for a block of data which may be allocated with malloc(), or
+ * not, so that it needs to be freed correctly when finished with.
+ *
+ * For now it has a very simple purpose.
+ *
+ * Using memset() to zero all fields is guaranteed to be equivalent to
+ * abuf_init().
+ *
+ * @data: Pointer to data
+ * @size: Size of data in bytes
+ * @alloced: true if allocated with malloc(), so must be freed after use
+ */
+struct abuf {
+	void *data;
+	size_t size;
+	bool alloced;
+};
+
+static inline void *abuf_data(const struct abuf *abuf)
+{
+	return abuf->data;
+}
+
+static inline size_t abuf_size(const struct abuf *abuf)
+{
+	return abuf->size;
+}
+
+/**
+ * abuf_set() - set the (unallocated) data in a buffer
+ *
+ * This simply makes the abuf point to the supplied data, which must be live
+ * for the lifetime of the abuf. It is not alloced.
+ *
+ * Any existing data in the abuf is freed and the alloced member is set to
+ * false.
+ *
+ * @abuf: abuf to adjust
+ * @data: New contents of abuf
+ * @size: New size of abuf
+ */
+void abuf_set(struct abuf *abuf, void *data, size_t size);
+
+/**
+ * abuf_map_sysmem() - calls map_sysmem() to set up an abuf
+ *
+ * This is equivalent to abuf_set(abuf, map_sysmem(addr, size), size)
+ *
+ * Any existing data in the abuf is freed and the alloced member is set to
+ * false.
+ *
+ * @abuf: abuf to adjust
+ * @addr: Address to set the abuf to
+ * @size: New size of abuf
+ */
+void abuf_map_sysmem(struct abuf *abuf, ulong addr, size_t size);
+
+/**
+ * abuf_realloc() - Change the size of a buffer
+ *
+ * This uses realloc() to change the size of the buffer, with the same semantics
+ * as that function. If the abuf is not currently alloced, then it will alloc
+ * it if the size needs to increase (i.e. set the alloced member to true)
+ *
+ * @abuf: abuf to adjust
+ * @new_size: new size in bytes.
+ *	if 0, the abuf is freed
+ *	if greater than the current size, the abuf is extended and the new
+ *	   space is not inited. The alloced member is set to true
+ *	if less than the current size, the abuf is contracted and the data at
+ *	   the end is lost. If @new_size is 0, this sets the alloced member to
+ *	   false
+ * @return true if OK, false if out of memory
+ */
+bool abuf_realloc(struct abuf *abuf, size_t new_size);
+
+/**
+ * abuf_uninit_move() - Return the allocated contents and uninit the abuf
+ *
+ * This returns the abuf data to the caller, allocating it if necessary, so that
+ * the caller receives data that it can be sure will hang around. The caller is
+ * responsible for freeing the data.
+ *
+ * If the abuf has allocated data, it is returned. If the abuf has data but it
+ * is not allocated, then it is first allocated, then returned.
+ *
+ * If the abuf size is 0, this returns NULL
+ *
+ * The abuf is uninited as part of this, except if the allocation fails, in
+ * which NULL is returned and the abuf remains untouched.
+ *
+ * The abuf must be inited before this can be called.
+ *
+ * @abuf: abuf to uninit
+ * @sizep: if non-NULL, returns the size of the returned data
+ * @return data contents, allocated with malloc(), or NULL if the data could not
+ *	be allocated, or the data size is 0
+ */
+void *abuf_uninit_move(struct abuf *abuf, size_t *sizep);
+
+/**
+ * abuf_init_move() - Make abuf take over the management of an allocated region
+ *
+ * After this, @data must not be used. All access must be via the abuf.
+ *
+ * @abuf: abuf to init
+ * @data: Existing allocated buffer to place in the abuf
+ * @size: Size of allocated buffer
+ */
+void abuf_init_move(struct abuf *abuf, void *data, size_t size);
+
+/**
+ * abuf_init_set() - Set up a new abuf
+ *
+ * Inits a new abuf and sets up its (unallocated) data
+ *
+ * @abuf: abuf to set up
+ * @data: New contents of abuf
+ * @size: New size of abuf
+ */
+void abuf_init_set(struct abuf *abuf, void *data, size_t size);
+
+/**
+ * abuf_uninit() - Free any memory used by an abuf
+ *
+ * The buffer must be inited before this can be called.
+ *
+ * @abuf: abuf to uninit
+ */
+void abuf_uninit(struct abuf *abuf);
+
+/**
+ * abuf_init() - Set up a new abuf
+ *
+ * This initially has no data and alloced is set to false. This is equivalent to
+ * setting all fields to 0, e.g. with memset(), so callers can do that instead
+ * if desired.
+ *
+ * @abuf: abuf to set up
+ */
+void abuf_init(struct abuf *abuf);
+
+#endif
diff --git a/lib/Makefile b/lib/Makefile
index dfe772aaff5..9c0373e2955 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -137,6 +137,7 @@ obj-$(CONFIG_OID_REGISTRY) += oid_registry.o
 obj-$(CONFIG_SSCANF) += sscanf.o
 endif
 
+obj-y += abuf.o
 obj-y += date.o
 obj-y += rtc-lib.o
 obj-$(CONFIG_LIB_ELF) += elf.o
diff --git a/lib/abuf.c b/lib/abuf.c
new file mode 100644
index 00000000000..4b17e0b8c0d
--- /dev/null
+++ b/lib/abuf.c
@@ -0,0 +1,109 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Handles a buffer that can be allocated and freed
+ *
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <abuf.h>
+#include <malloc.h>
+#include <mapmem.h>
+#include <string.h>
+
+void abuf_set(struct abuf *abuf, void *data, size_t size)
+{
+	abuf_uninit(abuf);
+	abuf->data = data;
+	abuf->size = size;
+}
+
+void abuf_map_sysmem(struct abuf *abuf, ulong addr, size_t size)
+{
+	abuf_set(abuf, map_sysmem(addr, size), size);
+}
+
+bool abuf_realloc(struct abuf *abuf, size_t new_size)
+{
+	void *ptr;
+
+	if (!new_size) {
+		/* easy case, just need to uninit, freeing any allocation */
+		abuf_uninit(abuf);
+		return true;
+	} else if (abuf->alloced) {
+		/* currently allocated, so need to reallocate */
+		ptr = realloc(abuf->data, new_size);
+		if (!ptr)
+			return false;
+		abuf->data = ptr;
+		abuf->size = new_size;
+		return true;
+	} else if (new_size <= abuf->size) {
+		/*
+		 * not currently alloced and new size is no larger. Just update
+		 * it. Data is lost off the end if new_size < abuf->size
+		 */
+		abuf->size = new_size;
+		return true;
+	} else {
+		/* not currently allocated and new size is larger. Alloc and
+		 * copy in data. The new space is not inited.
+		 */
+		ptr = memdup(abuf->data, new_size);
+		if (!ptr)
+			return false;
+		abuf->data = ptr;
+		abuf->size = new_size;
+		abuf->alloced = true;
+		return true;
+	}
+}
+
+void *abuf_uninit_move(struct abuf *abuf, size_t *sizep)
+{
+	void *ptr;
+
+	if (sizep)
+		*sizep = abuf->size;
+	if (!abuf->size)
+		return NULL;
+	if (abuf->alloced) {
+		ptr = abuf->data;
+	} else {
+		ptr = memdup(abuf->data, abuf->size);
+		if (!ptr)
+			return NULL;
+	}
+	/* Clear everything out so there is no record of the data */
+	abuf_init(abuf);
+
+	return ptr;
+}
+
+void abuf_init_set(struct abuf *abuf, void *data, size_t size)
+{
+	abuf_init(abuf);
+	abuf_set(abuf, data, size);
+}
+
+void abuf_init_move(struct abuf *abuf, void *data, size_t size)
+{
+	abuf_init_set(abuf, data, size);
+	abuf->alloced = true;
+}
+
+void abuf_uninit(struct abuf *abuf)
+{
+	if (abuf->alloced)
+		free(abuf->data);
+	abuf_init(abuf);
+}
+
+void abuf_init(struct abuf *abuf)
+{
+	abuf->data = NULL;
+	abuf->size = 0;
+	abuf->alloced = false;
+}
diff --git a/test/lib/Makefile b/test/lib/Makefile
index 6fd05142510..d244bb431d4 100644
--- a/test/lib/Makefile
+++ b/test/lib/Makefile
@@ -3,6 +3,7 @@
 # (C) Copyright 2018
 # Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
 obj-y += cmd_ut_lib.o
+obj-y += abuf.o
 obj-$(CONFIG_EFI_LOADER) += efi_device_path.o
 obj-$(CONFIG_EFI_SECURE_BOOT) += efi_image_region.o
 obj-y += hexdump.o
diff --git a/test/lib/abuf.c b/test/lib/abuf.c
new file mode 100644
index 00000000000..086c9b22821
--- /dev/null
+++ b/test/lib/abuf.c
@@ -0,0 +1,344 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <abuf.h>
+#include <mapmem.h>
+#include <test/lib.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+static char test_data[] = "1234";
+#define TEST_DATA_LEN	sizeof(test_data)
+
+/* Test abuf_set() */
+static int lib_test_abuf_set(struct unit_test_state *uts)
+{
+	struct abuf buf;
+	ulong start;
+
+	start = ut_check_free();
+
+	abuf_init(&buf);
+	abuf_set(&buf, test_data, TEST_DATA_LEN);
+	ut_asserteq_ptr(test_data, buf.data);
+	ut_asserteq(TEST_DATA_LEN, buf.size);
+	ut_asserteq(false, buf.alloced);
+
+	/* Force it to allocate */
+	ut_asserteq(true, abuf_realloc(&buf, TEST_DATA_LEN + 1));
+	ut_assertnonnull(buf.data);
+	ut_asserteq(TEST_DATA_LEN + 1, buf.size);
+	ut_asserteq(true, buf.alloced);
+
+	/* Now set it again, to force it to free */
+	abuf_set(&buf, test_data, TEST_DATA_LEN);
+	ut_asserteq_ptr(test_data, buf.data);
+	ut_asserteq(TEST_DATA_LEN, buf.size);
+	ut_asserteq(false, buf.alloced);
+
+	/* Check for memory leaks */
+	ut_assertok(ut_check_delta(start));
+
+	return 0;
+}
+LIB_TEST(lib_test_abuf_set, 0);
+
+/* Test abuf_map_sysmem() */
+static int lib_test_abuf_map_sysmem(struct unit_test_state *uts)
+{
+	struct abuf buf;
+	ulong addr;
+
+	abuf_init(&buf);
+	addr = 0x100;
+	abuf_map_sysmem(&buf, addr, TEST_DATA_LEN);
+
+	ut_asserteq_ptr(map_sysmem(0x100, 0), buf.data);
+	ut_asserteq(TEST_DATA_LEN, buf.size);
+	ut_asserteq(false, buf.alloced);
+
+	return 0;
+}
+LIB_TEST(lib_test_abuf_map_sysmem, 0);
+
+/* Test abuf_realloc() */
+static int lib_test_abuf_realloc(struct unit_test_state *uts)
+{
+	struct abuf buf;
+	ulong start;
+	void *ptr;
+
+	/*
+	 * TODO: crashes on sandbox sometimes due to an apparent bug in
+	 * realloc().
+	 */
+	return 0;
+
+	start = ut_check_free();
+
+	abuf_init(&buf);
+
+	/* Allocate an empty buffer */
+	ut_asserteq(true, abuf_realloc(&buf, 0));
+	ut_assertnull(buf.data);
+	ut_asserteq(0, buf.size);
+	ut_asserteq(false, buf.alloced);
+
+	/* Allocate a non-empty abuf */
+	ut_asserteq(true, abuf_realloc(&buf, TEST_DATA_LEN));
+	ut_assertnonnull(buf.data);
+	ut_asserteq(TEST_DATA_LEN, buf.size);
+	ut_asserteq(true, buf.alloced);
+	ptr = buf.data;
+
+	/*
+	 * Make it smaller; the pointer should remain the same. Note this relies
+	 * on knowledge of how U-Boot's realloc() works
+	 */
+	ut_asserteq(true, abuf_realloc(&buf, TEST_DATA_LEN - 1));
+	ut_asserteq(TEST_DATA_LEN - 1, buf.size);
+	ut_asserteq(true, buf.alloced);
+	ut_asserteq_ptr(ptr, buf.data);
+
+	/*
+	 * Make it larger, forcing reallocation. Note this relies on knowledge
+	 * of how U-Boot's realloc() works
+	 */
+	ut_asserteq(true, abuf_realloc(&buf, 0x1000));
+	ut_assert(buf.data != ptr);
+	ut_asserteq(0x1000, buf.size);
+	ut_asserteq(true, buf.alloced);
+
+	/* Free it */
+	ut_asserteq(true, abuf_realloc(&buf, 0));
+	ut_assertnull(buf.data);
+	ut_asserteq(0, buf.size);
+	ut_asserteq(false, buf.alloced);
+
+	/* Check for memory leaks */
+	ut_assertok(ut_check_delta(start));
+
+	return 0;
+}
+LIB_TEST(lib_test_abuf_realloc, 0);
+
+/* Test handling of buffers that are too large */
+static int lib_test_abuf_large(struct unit_test_state *uts)
+{
+	struct abuf buf;
+	ulong start;
+	size_t size;
+	int delta;
+	void *ptr;
+
+	/*
+	 * This crashes at present due to trying to allocate more memory than
+	 * available, which breaks something on sandbox.
+	 */
+	return 0;
+
+	start = ut_check_free();
+
+	/* Try an impossible size */
+	abuf_init(&buf);
+	ut_asserteq(false, abuf_realloc(&buf, CONFIG_SYS_MALLOC_LEN));
+	ut_assertnull(buf.data);
+	ut_asserteq(0, buf.size);
+	ut_asserteq(false, buf.alloced);
+
+	abuf_uninit(&buf);
+	ut_assertnull(buf.data);
+	ut_asserteq(0, buf.size);
+	ut_asserteq(false, buf.alloced);
+
+	/* Start with a normal size then try to increase it, to check realloc */
+	ut_asserteq(true, abuf_realloc(&buf, TEST_DATA_LEN));
+	ut_assertnonnull(buf.data);
+	ut_asserteq(TEST_DATA_LEN, buf.size);
+	ut_asserteq(true, buf.alloced);
+	ptr = buf.data;
+	delta = ut_check_delta(start);
+	ut_assert(delta > 0);
+
+	/* try to increase it */
+	ut_asserteq(false, abuf_realloc(&buf, CONFIG_SYS_MALLOC_LEN));
+	ut_asserteq_ptr(ptr, buf.data);
+	ut_asserteq(TEST_DATA_LEN, buf.size);
+	ut_asserteq(true, buf.alloced);
+	ut_asserteq(delta, ut_check_delta(start));
+
+	/* Check for memory leaks */
+	abuf_uninit(&buf);
+	ut_assertok(ut_check_delta(start));
+
+	/* Start with a huge unallocated buf and try to move it */
+	abuf_init(&buf);
+	abuf_map_sysmem(&buf, 0, CONFIG_SYS_MALLOC_LEN);
+	ut_asserteq(CONFIG_SYS_MALLOC_LEN, buf.size);
+	ut_asserteq(false, buf.alloced);
+	ut_assertnull(abuf_uninit_move(&buf, &size));
+
+	/* Check for memory leaks */
+	abuf_uninit(&buf);
+	ut_assertok(ut_check_delta(start));
+
+	return 0;
+}
+LIB_TEST(lib_test_abuf_large, 0);
+
+/* Test abuf_uninit_move() */
+static int lib_test_abuf_uninit_move(struct unit_test_state *uts)
+{
+	void *ptr, *orig_ptr;
+	struct abuf buf;
+	size_t size;
+	ulong start;
+	int delta;
+
+	start = ut_check_free();
+
+	/*
+	 * TODO: crashes on sandbox sometimes due to an apparent bug in
+	 * realloc().
+	 */
+	return 0;
+
+	/* Move an empty buffer */
+	abuf_init(&buf);
+	ut_assertnull(abuf_uninit_move(&buf, &size));
+	ut_asserteq(0, size);
+	ut_assertnull(abuf_uninit_move(&buf, NULL));
+
+	/* Move an unallocated buffer */
+	abuf_set(&buf, test_data, TEST_DATA_LEN);
+	ut_assertok(ut_check_delta(start));
+	ptr = abuf_uninit_move(&buf, &size);
+	ut_asserteq(TEST_DATA_LEN, size);
+	ut_asserteq_str(ptr, test_data);
+	ut_assertnonnull(ptr);
+	ut_assertnull(buf.data);
+	ut_asserteq(0, buf.size);
+	ut_asserteq(false, buf.alloced);
+
+	/* Check that freeing it frees the only allocation */
+	delta = ut_check_delta(start);
+	ut_assert(delta > 0);
+	free(ptr);
+	ut_assertok(ut_check_delta(start));
+
+	/* Move an allocated buffer */
+	ut_asserteq(true, abuf_realloc(&buf, TEST_DATA_LEN));
+	orig_ptr = buf.data;
+	strcpy(orig_ptr, test_data);
+
+	delta = ut_check_delta(start);
+	ut_assert(delta > 0);
+	ptr = abuf_uninit_move(&buf, &size);
+	ut_asserteq(TEST_DATA_LEN, size);
+	ut_assertnonnull(ptr);
+	ut_asserteq_ptr(ptr, orig_ptr);
+	ut_asserteq_str(ptr, test_data);
+	ut_assertnull(buf.data);
+	ut_asserteq(0, buf.size);
+	ut_asserteq(false, buf.alloced);
+
+	/* Check there was no new allocation */
+	ut_asserteq(delta, ut_check_delta(start));
+
+	/* Check that freeing it frees the only allocation */
+	free(ptr);
+	ut_assertok(ut_check_delta(start));
+
+	/* Move an unallocated buffer, without the size */
+	abuf_set(&buf, test_data, TEST_DATA_LEN);
+	ut_assertok(ut_check_delta(start));
+	ptr = abuf_uninit_move(&buf, NULL);
+	ut_asserteq_str(ptr, test_data);
+
+	return 0;
+}
+LIB_TEST(lib_test_abuf_uninit_move, 0);
+
+/* Test abuf_uninit() */
+static int lib_test_abuf_uninit(struct unit_test_state *uts)
+{
+	struct abuf buf;
+
+	/* Nothing in the buffer */
+	abuf_init(&buf);
+	abuf_uninit(&buf);
+	ut_assertnull(buf.data);
+	ut_asserteq(0, buf.size);
+	ut_asserteq(false, buf.alloced);
+
+	/* Not allocated */
+	abuf_set(&buf, test_data, TEST_DATA_LEN);
+	abuf_uninit(&buf);
+	ut_assertnull(buf.data);
+	ut_asserteq(0, buf.size);
+	ut_asserteq(false, buf.alloced);
+
+	return 0;
+}
+LIB_TEST(lib_test_abuf_uninit, 0);
+
+/* Test abuf_init_set() */
+static int lib_test_abuf_init_set(struct unit_test_state *uts)
+{
+	struct abuf buf;
+
+	abuf_init_set(&buf, test_data, TEST_DATA_LEN);
+	ut_asserteq_ptr(test_data, buf.data);
+	ut_asserteq(TEST_DATA_LEN, buf.size);
+	ut_asserteq(false, buf.alloced);
+
+	return 0;
+}
+LIB_TEST(lib_test_abuf_init_set, 0);
+
+/* Test abuf_init_move() */
+static int lib_test_abuf_init_move(struct unit_test_state *uts)
+{
+	struct abuf buf;
+	void *ptr;
+
+	/*
+	 * TODO: crashes on sandbox sometimes due to an apparent bug in
+	 * realloc().
+	 */
+	return 0;
+
+	ptr = strdup(test_data);
+	ut_assertnonnull(ptr);
+
+	free(ptr);
+
+	abuf_init_move(&buf, ptr, TEST_DATA_LEN);
+	ut_asserteq_ptr(ptr, abuf_data(&buf));
+	ut_asserteq(TEST_DATA_LEN, abuf_size(&buf));
+	ut_asserteq(true, buf.alloced);
+
+	return 0;
+}
+LIB_TEST(lib_test_abuf_init_move, 0);
+
+/* Test abuf_init() */
+static int lib_test_abuf_init(struct unit_test_state *uts)
+{
+	struct abuf buf;
+
+	buf.data = &buf;
+	buf.size = 123;
+	buf.alloced = true;
+	abuf_init(&buf);
+	ut_assertnull(buf.data);
+	ut_asserteq(0, buf.size);
+	ut_asserteq(false, buf.alloced);
+
+	return 0;
+}
+LIB_TEST(lib_test_abuf_init, 0);
-- 
2.33.0.685.g46640cef36-goog


  parent reply	other threads:[~2021-09-25 13:05 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-09-25 13:03 [PATCH v4 00/15] image: A partial series for the image clean-up Simon Glass
2021-09-25 13:03 ` [PATCH v4 01/15] lib: Add memdup() Simon Glass
2021-10-09  1:38   ` Tom Rini
2021-09-25 13:03 ` Simon Glass [this message]
2021-10-09  1:38   ` [PATCH v4 02/15] Add support for an owned buffer Tom Rini
2021-09-25 13:03 ` [PATCH v4 03/15] compiler: Add a comment to host_build() Simon Glass
2021-10-09  1:38   ` Tom Rini
2021-09-25 13:03 ` [PATCH v4 04/15] zstd: Create a function for use from U-Boot Simon Glass
2021-10-09  1:38   ` Tom Rini
2021-09-25 13:03 ` [PATCH v4 05/15] btrfs: Use U-Boot API for decompression Simon Glass
2021-10-09  1:38   ` Tom Rini
2021-09-25 13:03 ` [PATCH v4 06/15] image: Avoid switch default in image_decomp() Simon Glass
2021-10-09  1:38   ` Tom Rini
2021-09-25 13:03 ` [PATCH v4 07/15] image: Update zstd to avoid reporting error twice Simon Glass
2021-10-09  1:38   ` Tom Rini
2021-09-25 13:03 ` [PATCH v4 08/15] gzip: Avoid use of u64 Simon Glass
2021-10-09  1:38   ` Tom Rini
2021-09-25 13:03 ` [PATCH v4 09/15] image: Update image_decomp() to avoid ifdefs Simon Glass
2021-10-09  1:38   ` Tom Rini
2021-09-25 13:03 ` [PATCH v4 10/15] image: Split board code out into its own file Simon Glass
2021-10-09  1:38   ` Tom Rini
2021-09-25 13:03 ` [PATCH v4 11/15] image: Fix up checkpatch warnings in image-board.c Simon Glass
2021-10-09  1:38   ` Tom Rini
2021-09-25 13:03 ` [PATCH v4 12/15] image: Split host code out into its own file Simon Glass
2021-10-09  1:38   ` Tom Rini
2021-09-25 13:03 ` [PATCH v4 13/15] image: Create a function to do manual relocation Simon Glass
2021-10-09  1:39   ` Tom Rini
2021-09-25 13:03 ` [PATCH v4 14/15] image: Avoid #ifdefs for " Simon Glass
2021-10-09  1:39   ` Tom Rini
2021-09-25 13:03 ` [PATCH v4 15/15] image: Remove ifdefs around image_setup_linux() el at Simon Glass
2021-10-09  1:39   ` Tom Rini

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=20210925070255.v4.2.Iac016f2b531889277f63e4999494a967a823659b@changeid \
    --to=sjg@chromium.org \
    --cc=bmeng.cn@gmail.com \
    --cc=mr.nuke.me@gmail.com \
    --cc=trini@konsulko.com \
    --cc=u-boot@lists.denx.de \
    --cc=xypron.glpk@gmx.de \
    /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;
as well as URLs for NNTP newsgroup(s).