diff options
Diffstat (limited to 'pbl')
-rw-r--r-- | pbl/Kconfig | 27 | ||||
-rw-r--r-- | pbl/Makefile | 3 | ||||
-rw-r--r-- | pbl/console.c | 40 | ||||
-rw-r--r-- | pbl/decomp.c | 32 | ||||
-rw-r--r-- | pbl/fdt.c | 112 | ||||
-rw-r--r-- | pbl/misc.c | 2 | ||||
-rw-r--r-- | pbl/string.c | 21 |
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 |