[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 1/2] fdtdump: add grub_fdt_prop_to_string() for safe string conve
From: |
Tobias Heider |
Subject: |
[PATCH 1/2] fdtdump: add grub_fdt_prop_to_string() for safe string conversion |
Date: |
Thu, 8 Aug 2024 17:37:46 +0200 |
Device tree properties are not explicitly typed but values can take
multiple forms from strings to arrays and byte-strings.
grub_fdt_prop_to_string() adds a heuristic to determine the type and
convert it to a string for printing.
Signed-off-by: Tobias Heider <tobias.heider@canonical.com>
---
grub-core/lib/fdt.c | 87 ++++++++++++++++++++++++++++++++++++++
grub-core/loader/efi/fdt.c | 15 +++++--
include/grub/fdt.h | 3 ++
3 files changed, 101 insertions(+), 4 deletions(-)
diff --git a/grub-core/lib/fdt.c b/grub-core/lib/fdt.c
index 73cfa94a2..5ec32ac56 100644
--- a/grub-core/lib/fdt.c
+++ b/grub-core/lib/fdt.c
@@ -1,6 +1,7 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2013 Free Software Foundation, Inc.
+ * Copyright (C) 2024 Canonical, Ltd.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -501,6 +502,92 @@ int grub_fdt_set_prop (void *fdt, unsigned int nodeoffset,
const char *name,
return 0;
}
+static int
+prop_isstring (const unsigned char *str, grub_uint32_t len)
+{
+ grub_uint32_t i;
+ int is_nonzero = 0;
+
+ if (!len || str[len - 1])
+ return 0;
+
+ for (i = 0; i < len; i++)
+ {
+ if (!str[i])
+ {
+ if (!is_nonzero)
+ return 0;
+
+ is_nonzero = 0;
+ continue;
+ }
+ if (!grub_isprint (str[i]))
+ return 0;
+
+ is_nonzero = 1;
+ }
+ return 1;
+}
+
+char *
+grub_fdt_prop_to_string (const unsigned char *val, grub_uint32_t len)
+{
+ char *str;
+ int pos, slen;
+ grub_uint32_t i;
+
+ if (prop_isstring (val, len))
+ {
+ /* string */
+ return grub_strdup ((const char *)val);
+ }
+ else if (len & 0x3)
+ {
+ /* byte string */
+ grub_printf ("[");
+
+ slen = (len * 3) + 2;
+ str = grub_malloc (slen);
+ if (str == NULL)
+ return NULL;
+
+ pos = 0;
+ str[pos++] = '[';
+ for (i = 0; i < len; i++)
+ {
+ pos += grub_snprintf (&str[pos], slen - pos, "%02x", val[i]);
+ if (i != len - 1)
+ str[pos++] = ' ';
+ }
+ str[pos++] = ']';
+ str[pos] = '\0';
+ }
+ else
+ {
+ /* cell list */
+ const grub_uint32_t *cell = (const grub_uint32_t *)val;
+
+ slen = (len * 11) + 2;
+ str = grub_malloc (slen);
+ if (str == NULL)
+ return NULL;
+
+ pos = 0;
+ str[pos++] = '<';
+ for (i = 0, len /= 4; i < len; i++)
+ {
+ pos += grub_snprintf (&str[pos], slen - pos, "0x%08x",
+ grub_be_to_cpu32 (cell[i]));
+ if (i != len - 1)
+ str[pos++] = ' ';
+ }
+ str[pos++] = '>';
+ str[pos] = '\0';
+ }
+
+ return str;
+}
+
int
grub_fdt_create_empty_tree (void *fdt, unsigned int size)
{
diff --git a/grub-core/loader/efi/fdt.c b/grub-core/loader/efi/fdt.c
index e510b3491..b43ff730d 100644
--- a/grub-core/loader/efi/fdt.c
+++ b/grub-core/loader/efi/fdt.c
@@ -183,8 +183,10 @@ grub_cmd_fdtdump (grub_extcmd_context_t ctxt,
char **argv __attribute__ ((unused)))
{
struct grub_arg_list *state = ctxt->state;
- const char *value = NULL;
+ const unsigned char *value = NULL;
+ char *str;
void *fw_fdt;
+ grub_uint32_t len;
fw_fdt = grub_efi_get_firmware_fdt ();
if (fw_fdt == NULL)
@@ -192,17 +194,22 @@ grub_cmd_fdtdump (grub_extcmd_context_t ctxt,
N_("No device tree found"));
if (state[0].set)
- value = grub_fdt_get_prop (fw_fdt, 0, state[0].arg, NULL);
+ value = grub_fdt_get_prop (fw_fdt, 0, state[0].arg, &len);
if (value == NULL)
return grub_error (GRUB_ERR_OUT_OF_RANGE,
N_("failed to retrieve the prop field"));
+ str = grub_fdt_prop_to_string (value, len);
+ if (str == NULL)
+ return grub_error (GRUB_ERR_IO, N_("Failed to print string"));
+
if (state[1].set)
- grub_env_set (state[1].arg, value);
+ grub_env_set (state[1].arg, str);
else
- grub_printf ("%s\n", value);
+ grub_printf ("%s", str);
+ grub_free (str);
return GRUB_ERR_NONE;
}
diff --git a/include/grub/fdt.h b/include/grub/fdt.h
index e609c7e41..4db644544 100644
--- a/include/grub/fdt.h
+++ b/include/grub/fdt.h
@@ -118,6 +118,9 @@ EXPORT_FUNC(grub_fdt_get_nodename) (const void *fdt,
unsigned int nodeoffset);
const void *EXPORT_FUNC(grub_fdt_get_prop) (const void *fdt, unsigned int
nodeoffset, const char *name,
grub_uint32_t *len);
+char *EXPORT_FUNC(grub_fdt_prop_to_string) (const unsigned char *val,
+ grub_uint32_t len);
+
int EXPORT_FUNC(grub_fdt_set_prop) (void *fdt, unsigned int nodeoffset, const
char *name,
const void *val, grub_uint32_t len);
#define grub_fdt_set_prop32(fdt, nodeoffset, name, val) \
--
2.43.0
- [PATCH 1/2] fdtdump: add grub_fdt_prop_to_string() for safe string conversion,
Tobias Heider <=