summaryrefslogtreecommitdiffstats
path: root/pbl
diff options
context:
space:
mode:
Diffstat (limited to 'pbl')
-rw-r--r--pbl/Kconfig27
-rw-r--r--pbl/Makefile3
-rw-r--r--pbl/console.c40
-rw-r--r--pbl/decomp.c32
-rw-r--r--pbl/fdt.c112
-rw-r--r--pbl/misc.c2
-rw-r--r--pbl/string.c21
7 files changed, 210 insertions, 27 deletions
diff --git a/pbl/Kconfig b/pbl/Kconfig
index 6e8cc3ac04..d1877a988d 100644
--- a/pbl/Kconfig
+++ b/pbl/Kconfig
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
config HAVE_PBL_IMAGE
bool
@@ -26,19 +28,38 @@ config PBL_SINGLE_IMAGE
if PBL_IMAGE
+config USE_COMPRESSED_DTB
+ bool
+ depends on ARM || RISCV
+ select LZ4_DECOMPRESS if IMAGE_COMPRESSION_LZ4
+ select LZO_DECOMPRESS if IMAGE_COMPRESSION_LZO
+ select ZLIB if IMAGE_COMPRESSION_GZIP
+ select XZ_DECOMPRESS if IMAGE_COMPRESSION_XZKERN
+
config PBL_RELOCATABLE
- depends on ARM || MIPS
+ depends on ARM || MIPS || RISCV
bool "relocatable pbl image"
help
Generate a pbl binary which can relocate itself during startup to run
on different addresses. This is useful if your memory layout is not
known during compile time.
- This option only inflluences the PBL image. See RELOCATABLE to also make
+ This option only influences the PBL image. See RELOCATABLE to also make
the real image relocatable.
+config PBL_FULLY_PIC
+ bool "fully position-independent pbl image"
+ depends on PBL_RELOCATABLE && ARM && CPU_64
+ help
+ Compared to CONFIG_PBL_RELOCATABLE, this image has no relocations in
+ the code sections.
+
config PBL_VERIFY_PIGGY
depends on ARM
+ bool "Verify barebox proper hash before decompression" if COMPILE_TEST
+
+config BOARD_GENERIC_DT
bool
+ select LIBFDT
config IMAGE_COMPRESSION
bool
@@ -49,7 +70,7 @@ if IMAGE_COMPRESSION
choice
prompt "Compression"
- default IMAGE_COMPRESSION_LZO
+ default IMAGE_COMPRESSION_LZ4
config IMAGE_COMPRESSION_LZ4
bool "lz4"
diff --git a/pbl/Makefile b/pbl/Makefile
index c5a08c1354..f6e98e78be 100644
--- a/pbl/Makefile
+++ b/pbl/Makefile
@@ -1,7 +1,10 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
#
# only unsed by the pbl
#
pbl-y += misc.o
pbl-y += string.o
pbl-y += decomp.o
+pbl-$(CONFIG_LIBFDT) += fdt.o
pbl-$(CONFIG_PBL_CONSOLE) += console.o
diff --git a/pbl/console.c b/pbl/console.c
index 007e4e4b83..d81bf580d5 100644
--- a/pbl/console.c
+++ b/pbl/console.c
@@ -1,12 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
#include <common.h>
#include <debug_ll.h>
+#include <asm/sections.h>
#include <linux/err.h>
/*
* Put these in the data section so that they survive the clearing of the
* BSS segment.
*/
-static __attribute__ ((section(".data"))) void (*__putc)(void *ctx, int c);
+static __attribute__ ((section(".data"))) ulong putc_offset;
static __attribute__ ((section(".data"))) void *putc_ctx;
/**
@@ -19,13 +22,19 @@ static __attribute__ ((section(".data"))) void *putc_ctx;
*/
void pbl_set_putc(void (*putcf)(void *ctx, int c), void *ctx)
{
- __putc = putcf;
+ putc_offset = (ulong)putcf - (ulong)_text;
putc_ctx = ctx;
}
+static void __putc(void *ctx, int c)
+{
+ void (*putc)(void *, int) = (void *)_text + putc_offset;
+ putc(ctx, c);
+}
+
void console_putc(unsigned int ch, char c)
{
- if (__putc)
+ if (putc_offset)
__putc(putc_ctx, c);
else
putc_ll(c);
@@ -37,9 +46,9 @@ int console_puts(unsigned int ch, const char *str)
while (*str) {
if (*str == '\n')
- console_putc(CONSOLE_STDOUT, '\r');
+ console_putc(ch, '\r');
- console_putc(CONSOLE_STDOUT, *str);
+ console_putc(ch, *str);
str++;
n++;
}
@@ -54,7 +63,7 @@ int printf(const char *fmt, ...)
char printbuffer[CFG_PBSIZE];
va_start(args, fmt);
- i = vsprintf(printbuffer, fmt, args);
+ i = vsnprintf(printbuffer, sizeof(printbuffer), fmt, args);
va_end(args);
console_puts(CONSOLE_STDOUT, printbuffer);
@@ -69,10 +78,25 @@ int pr_print(int level, const char *fmt, ...)
char printbuffer[CFG_PBSIZE];
va_start(args, fmt);
- i = vsprintf(printbuffer, fmt, args);
+ i = vsnprintf(printbuffer, sizeof(printbuffer), fmt, args);
va_end(args);
- console_puts(CONSOLE_STDOUT, printbuffer);
+ console_puts(CONSOLE_STDERR, printbuffer);
+
+ return i;
+}
+
+int dev_printf(int level, const struct device *dev, const char *fmt, ...)
+{
+ va_list args;
+ uint i;
+ char printbuffer[CFG_PBSIZE];
+
+ va_start(args, fmt);
+ i = vsnprintf(printbuffer, sizeof(printbuffer), fmt, args);
+ va_end(args);
+
+ console_puts(CONSOLE_STDERR, printbuffer);
return i;
}
diff --git a/pbl/decomp.c b/pbl/decomp.c
index 1e0ef81ada..ebdf81ddfb 100644
--- a/pbl/decomp.c
+++ b/pbl/decomp.c
@@ -54,14 +54,14 @@ static void noinline errorfn(char *error)
extern unsigned char sha_sum[];
extern unsigned char sha_sum_end[];
-static int pbl_barebox_verify(void *compressed_start, unsigned int len, void *hash,
- unsigned int hash_len)
+int pbl_barebox_verify(const void *compressed_start, unsigned int len,
+ const void *hash, unsigned int hash_len)
{
struct sha256_state sha_state = { 0 };
struct digest d = { .ctx = &sha_state };
char computed_hash[SHA256_DIGEST_SIZE];
int i;
- char *char_hash = hash;
+ const char *char_hash = hash;
if (hash_len != SHA256_DIGEST_SIZE)
return -1;
@@ -70,20 +70,20 @@ static int pbl_barebox_verify(void *compressed_start, unsigned int len, void *ha
sha256_update(&d, compressed_start, len);
sha256_final(&d, computed_hash);
if (IS_ENABLED(CONFIG_DEBUG_LL)) {
- putc_ll('C');
- putc_ll('H');
- putc_ll('\n');
- for (i = 0; i < SHA256_DIGEST_SIZE; i++) {
- puthex_ll(computed_hash[i]);
- putc_ll('\n');
- }
- putc_ll('I');
- putc_ll('H');
+ puts_ll("CH ");
+
+ for (i = 0; i < SHA256_DIGEST_SIZE; i++)
+ puthexc_ll(computed_hash[i]);
+
+ puts_ll("\nIH ");
+
+ for (i = 0; i < SHA256_DIGEST_SIZE; i++)
+ puthexc_ll(char_hash[i]);
+
putc_ll('\n');
- for (i = 0; i < SHA256_DIGEST_SIZE; i++) {
- puthex_ll(char_hash[i]);
- putc_ll('\n');
- }
+
+ pr_debug("Hexdump of first 64 bytes of %u\n", len);
+ print_hex_dump_bytes("", DUMP_PREFIX_ADDRESS, compressed_start, 64);
}
return memcmp(hash, computed_hash, SHA256_DIGEST_SIZE);
diff --git a/pbl/fdt.c b/pbl/fdt.c
new file mode 100644
index 0000000000..8e4d129507
--- /dev/null
+++ b/pbl/fdt.c
@@ -0,0 +1,112 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/libfdt.h>
+#include <pbl.h>
+#include <linux/printk.h>
+
+static const __be32 *fdt_parse_reg(const __be32 *reg, uint32_t n,
+ uint64_t *val)
+{
+ int i;
+
+ *val = 0;
+ for (i = 0; i < n; i++)
+ *val = (*val << 32) | fdt32_to_cpu(*reg++);
+
+ return reg;
+}
+
+void fdt_find_mem(const void *fdt, unsigned long *membase, unsigned long *memsize)
+{
+ const __be32 *nap, *nsp, *reg;
+ uint32_t na, ns;
+ uint64_t memsize64, membase64;
+ int node, size;
+
+ /* Make sure FDT blob is sane */
+ if (fdt_check_header(fdt) != 0) {
+ pr_err("Invalid device tree blob\n");
+ goto err;
+ }
+
+ /* Find the #address-cells and #size-cells properties */
+ node = fdt_path_offset(fdt, "/");
+ if (node < 0) {
+ pr_err("Cannot find root node\n");
+ goto err;
+ }
+
+ nap = fdt_getprop(fdt, node, "#address-cells", &size);
+ if (!nap || (size != 4)) {
+ pr_err("Cannot find #address-cells property");
+ goto err;
+ }
+ na = fdt32_to_cpu(*nap);
+
+ nsp = fdt_getprop(fdt, node, "#size-cells", &size);
+ if (!nsp || (size != 4)) {
+ pr_err("Cannot find #size-cells property");
+ goto err;
+ }
+ ns = fdt32_to_cpu(*nsp);
+
+ /* Find the memory range */
+ node = fdt_node_offset_by_prop_value(fdt, -1, "device_type",
+ "memory", sizeof("memory"));
+ if (node < 0) {
+ pr_err("Cannot find memory node\n");
+ goto err;
+ }
+
+ reg = fdt_getprop(fdt, node, "reg", &size);
+ if (size < (na + ns) * sizeof(u32)) {
+ pr_err("cannot get memory range\n");
+ goto err;
+ }
+
+ /* get the memsize and truncate it to under 4G on 32 bit machines */
+ reg = fdt_parse_reg(reg, na, &membase64);
+ reg = fdt_parse_reg(reg, ns, &memsize64);
+
+ *membase = membase64;
+ *memsize = memsize64;
+
+ return;
+err:
+ pr_err("No memory, cannot continue\n");
+ while (1);
+}
+
+const void *fdt_device_get_match_data(const void *fdt, const char *nodepath,
+ const struct fdt_device_id ids[])
+{
+ int node, length;
+ const char *list, *end;
+ const struct fdt_device_id *id;
+
+ node = fdt_path_offset(fdt, nodepath);
+ if (node < 0)
+ return NULL;
+
+ list = fdt_getprop(fdt, node, "compatible", &length);
+ if (!list)
+ return NULL;
+
+ end = list + length;
+
+ while (list < end) {
+ length = strnlen(list, end - list) + 1;
+
+ /* Abort if the last string isn't properly NUL-terminated. */
+ if (list + length > end)
+ return NULL;
+
+ for (id = ids; id->compatible; id++) {
+ if (!strcasecmp(list, id->compatible))
+ return id->data;
+ }
+
+ list += length;
+ }
+
+ return NULL;
+}
diff --git a/pbl/misc.c b/pbl/misc.c
index 201ae38e9a..1f0d992ce0 100644
--- a/pbl/misc.c
+++ b/pbl/misc.c
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
#include <common.h>
#include <init.h>
#include <linux/types.h>
diff --git a/pbl/string.c b/pbl/string.c
index 46bf0b32b3..7c10f064dc 100644
--- a/pbl/string.c
+++ b/pbl/string.c
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
/*
* arch/arm/boot/compressed/string.c
*
@@ -6,6 +8,8 @@
#include <linux/types.h>
#include <linux/string.h>
+#include <linux/compiler.h>
+#include <linux/ctype.h>
void *memcpy(void *__dest, __const void *__src, size_t __n)
{
@@ -41,6 +45,9 @@ void *memcpy(void *__dest, __const void *__src, size_t __n)
return __dest;
}
+void *__memcpy(void *__dest, __const void *__src, size_t __n)
+ __alias(memcpy);
+
void *memmove(void *__dest, __const void *__src, size_t count)
{
unsigned char *d = __dest;
@@ -94,6 +101,17 @@ int strcmp(const char *cs, const char *ct)
return res;
}
+int strcasecmp(const char *s1, const char *s2)
+{
+ int c1, c2;
+
+ do {
+ c1 = tolower(*s1++);
+ c2 = tolower(*s2++);
+ } while (c1 == c2 && c1 != 0);
+ return c1 - c2;
+}
+
void *memchr(const void *s, int c, size_t count)
{
const unsigned char *p = s;
@@ -120,6 +138,9 @@ void *memset(void *s, int c, size_t count)
return s;
}
+void *__memset(void *s, int c, size_t count)
+ __alias(memset);
+
/**
* strnlen - Find the length of a length-limited string
* @s: The string to be sized