summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAhmad Fatoum <a.fatoum@pengutronix.de>2024-03-04 20:00:14 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2024-03-05 16:28:06 +0100
commit8d242311041cc0224cc1bab2634723233e25a12f (patch)
treef65e34aa6261d3756d614ea210a5848a9c89216f
parente5bf6b3e56b5352eb83ce15872cf005942c41b5e (diff)
downloadbarebox-8d242311041c.tar.gz
barebox-8d242311041c.tar.xz
efi: devicepath: implement device_path_to_str_buf variant
Existing device_path_to_str() formats a buffer once to determines the amount of space necessary and then allocates it and formats it again. To make this functionality available as printf format specifier, we need a variant that doesn't allocate memory and that's preferably single pass, which we add here. No functional change for users of device_path_to_str(). Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de> Link: https://lore.barebox.org/20240304190038.3486881-90-a.fatoum@pengutronix.de Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
-rw-r--r--efi/devicepath.c69
-rw-r--r--include/efi.h1
2 files changed, 52 insertions, 18 deletions
diff --git a/efi/devicepath.c b/efi/devicepath.c
index d562bf4829..0c2fc4d869 100644
--- a/efi/devicepath.c
+++ b/efi/devicepath.c
@@ -6,11 +6,13 @@
#include <malloc.h>
#include <string.h>
#include <wchar.h>
+#include <linux/overflow.h>
#include <efi/device-path.h>
struct string {
char *str;
- int len;
+ unsigned allocated;
+ unsigned used;
};
char *cprintf(struct string *str, const char *fmt, ...)
@@ -18,17 +20,22 @@ char *cprintf(struct string *str, const char *fmt, ...)
char *cprintf(struct string *str, const char *fmt, ...)
{
+ void *buf = str->str;
+ unsigned bufsize = 0;
va_list args;
int len;
+ if (str->str) {
+ buf += str->used;
+ if (check_sub_overflow(str->allocated, str->used, &bufsize))
+ bufsize = 0;
+ }
+
va_start(args, fmt);
- if (str->str)
- len = vsprintf(str->str + str->len, fmt, args);
- else
- len = vsnprintf(NULL, 0, fmt, args);
+ len = vsnprintf(buf, bufsize, fmt, args);
va_end(args);
- str->len += len;
+ str->used += len;
return NULL;
}
@@ -717,8 +724,8 @@ struct {
0, 0, NULL}
};
-static int __device_path_to_str(struct string *str,
- const struct efi_device_path *dev_path)
+static void __device_path_to_str(struct string *str,
+ const struct efi_device_path *dev_path)
{
const struct efi_device_path *dev_path_node;
void (*dump_node) (struct string *, const void *);
@@ -743,32 +750,58 @@ static int __device_path_to_str(struct string *str,
if (!dump_node)
dump_node = dev_path_node_unknown;
- if (str->len && dump_node != dev_path_end_instance)
+ if (str->used && dump_node != dev_path_end_instance)
cprintf(str, "/");
dump_node(str, dev_path_node);
dev_path_node = next_device_path_node(dev_path_node);
}
+}
+
+/**
+ * device_path_to_str_buf() - formats a device path into a preallocated buffer
+ *
+ * @dev_path: The EFI device path to format
+ * @buf: The buffer to format into or optionally NULL if @len is zero
+ * @len: The number of bytes that may be written into @buf
+ * Return: total number of bytes that are required to store the formatted
+ * result, excluding the terminating NUL byte, which is always
+ * written.
+ */
+size_t device_path_to_str_buf(const struct efi_device_path *dev_path,
+ char *buf, size_t len)
+{
+ struct string str = {
+ .str = buf,
+ .allocated = len,
+ };
+
+ __device_path_to_str(&str, dev_path);
- return 0;
+ return str.used;
}
+/**
+ * device_path_to_str() - formats a device path into a newly allocated buffer
+ *
+ * @dev_path: The EFI device path to format
+ * Return: A pointer to the nul-terminated formatted device path.
+ */
char *device_path_to_str(const struct efi_device_path *dev_path)
{
- struct string str = {};
+ void *buf;
+ size_t size;
- __device_path_to_str(&str, dev_path);
+ size = device_path_to_str_buf(dev_path, NULL, 0);
- str.str = malloc(str.len + 1);
- if (!str.str)
+ buf = malloc(size + 1);
+ if (!buf)
return NULL;
- str.len = 0;
-
- __device_path_to_str(&str, dev_path);
+ device_path_to_str_buf(dev_path, buf, size + 1);
- return str.str;
+ return buf;
}
u8 device_path_to_type(const struct efi_device_path *dev_path)
diff --git a/include/efi.h b/include/efi.h
index 6795dc414c..45e4080fac 100644
--- a/include/efi.h
+++ b/include/efi.h
@@ -880,6 +880,7 @@ struct efi_simple_text_input_protocol {
const struct efi_device_path *device_path_from_handle(efi_handle_t handle);
char *device_path_to_str(const struct efi_device_path *dev_path);
+size_t device_path_to_str_buf(const struct efi_device_path *dev_path, char buf[], size_t size);
u8 device_path_to_type(const struct efi_device_path *dev_path);
u8 device_path_to_subtype(const struct efi_device_path *dev_path);
char *device_path_to_partuuid(const struct efi_device_path *dev_path);