summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/fdtdec.c18
-rw-r--r--lib/string.c31
-rw-r--r--lib/vsprintf.c37
3 files changed, 86 insertions, 0 deletions
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index fb3375ea157..90d34ae105f 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -714,6 +714,24 @@ int fdtdec_get_int_array(const void *blob, int node, const char *prop_name,
return err;
}
+int fdtdec_get_long_array(const void *blob, int node, const char *prop_name,
+ u64 *array, int count)
+{
+ const u64 *cell;
+ int err = 0;
+
+ debug("%s: %s\n", __func__, prop_name);
+ cell = get_prop_check_min_len(blob, node, prop_name,
+ sizeof(u64) * count, &err);
+ if (!err) {
+ int i;
+
+ for (i = 0; i < count; i++)
+ array[i] = fdt64_to_cpu(cell[i]);
+ }
+ return err;
+}
+
int fdtdec_get_int_array_count(const void *blob, int node,
const char *prop_name, u32 *array, int count)
{
diff --git a/lib/string.c b/lib/string.c
index d56f88d4a84..302efe048b0 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -379,6 +379,37 @@ char * strndup(const char *s, size_t n)
return new;
}
+
+/**
+ * strdup_const - conditionally duplicate an existing const string
+ * @s: the string to duplicate
+ *
+ * Note: Strings allocated by kstrdup_const should be freed by kfree_const and
+ * must not be passed to krealloc().
+ *
+ * Return: source string if it is in .rodata section otherwise
+ * fallback to kstrdup.
+ */
+const char *strdup_const(const char *s)
+{
+ if (is_kernel_rodata((unsigned long)s))
+ return s;
+
+ return strdup(s);
+}
+
+/**
+ * kfree_const - conditionally free memory
+ * @x: pointer to the memory
+ *
+ * Function calls kfree only if @x is not in .rodata section.
+ */
+void kfree_const(const void *x)
+{
+ if (!is_kernel_rodata((unsigned long)x))
+ free((void *)x);
+}
+
#endif
#ifndef __HAVE_ARCH_STRSPN
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index c7340a047b2..49dc9c38c65 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -26,6 +26,11 @@
#include <linux/types.h>
#include <linux/string.h>
+/* For %pOF */
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+#include <dm/ofnode.h>
+#endif
+
/* we use this so that we can do without the ctype library */
#define is_digit(c) ((c) >= '0' && (c) <= '9')
@@ -438,6 +443,30 @@ static char *uuid_string(char *buf, char *end, u8 *addr, int field_width,
}
#endif
+#if CONFIG_IS_ENABLED(OF_CONTROL) && !defined(API_BUILD)
+static char *ofnode_string(char *buf, char *end, ofnode *dp, int field_width,
+ int precision, int flags)
+{
+#define NP_PATH_MAX 64
+ char str[NP_PATH_MAX] = { 0 };
+ const char *err = "...";
+
+ /* If dp == NULL output the string '<NULL>' */
+ if (!dp || !ofnode_valid(*dp))
+ return string(buf, end, NULL, field_width, precision, flags);
+
+ /* Get the path and indicate if it got cut off */
+ if (ofnode_get_path(*dp, str, NP_PATH_MAX)) {
+ str[NP_PATH_MAX - 1] = '\0';
+ char *p = str + min((NP_PATH_MAX - 2) - strlen(err), strlen(str));
+ memcpy(p, err, strlen(err) + 1);
+ }
+
+ return string(buf, end, str, field_width, precision, flags);
+#undef NP_PATH_MAX
+}
+#endif
+
/*
* Show a '%p' thing. A kernel extension is that the '%p' is followed
* by an extra set of alphanumeric characters that are extended format
@@ -474,6 +503,14 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr,
return device_path_string(buf, end, ptr, field_width,
precision, flags);
#endif
+/* Device paths only exist in the EFI context. */
+#if CONFIG_IS_ENABLED(OF_CONTROL) && !defined(API_BUILD)
+ case 'O':
+ if (fmt[1] == 'F')
+ return ofnode_string(buf, end, ptr, field_width,
+ precision, flags);
+ break;
+#endif
case 'a':
flags |= SPECIAL | ZEROPAD;