diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Makefile | 1 | ||||
-rw-r--r-- | lib/alist.c | 158 | ||||
-rw-r--r-- | lib/asm-offsets.c | 2 | ||||
-rw-r--r-- | lib/crypto/Kconfig | 2 | ||||
-rw-r--r-- | lib/elf.c | 14 | ||||
-rw-r--r-- | lib/fdtdec.c | 1 | ||||
-rw-r--r-- | lib/fwu_updates/fwu_mtd.c | 5 | ||||
-rw-r--r-- | lib/strto.c | 4 |
8 files changed, 177 insertions, 10 deletions
diff --git a/lib/Makefile b/lib/Makefile index e389ad014f8..81b503ab526 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -147,6 +147,7 @@ endif obj-$(CONFIG_$(SPL_)OID_REGISTRY) += oid_registry.o obj-y += abuf.o +obj-y += alist.o obj-y += date.o obj-y += rtc-lib.o obj-$(CONFIG_LIB_ELF) += elf.o diff --git a/lib/alist.c b/lib/alist.c new file mode 100644 index 00000000000..b7928cad520 --- /dev/null +++ b/lib/alist.c @@ -0,0 +1,158 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Handles a contiguous list of pointers which be allocated and freed + * + * Copyright 2023 Google LLC + * Written by Simon Glass <sjg@chromium.org> + */ + +#include <alist.h> +#include <display_options.h> +#include <malloc.h> +#include <stdio.h> +#include <string.h> + +enum { + ALIST_INITIAL_SIZE = 4, /* default size of unsized list */ +}; + +bool alist_init(struct alist *lst, uint obj_size, uint start_size) +{ + /* Avoid realloc for the initial size to help malloc_simple */ + memset(lst, '\0', sizeof(struct alist)); + if (start_size) { + lst->data = calloc(obj_size, start_size); + if (!lst->data) { + lst->flags = ALISTF_FAIL; + return false; + } + lst->alloc = start_size; + } + lst->obj_size = obj_size; + + return true; +} + +void alist_uninit(struct alist *lst) +{ + free(lst->data); + + /* Clear fields to avoid any confusion */ + memset(lst, '\0', sizeof(struct alist)); +} + +/** + * alist_expand_to() - Expand a list to the given size + * + * @lst: List to modify + * @inc_by: Amount to expand to + * Return: true if OK, false if out of memory + */ +static bool alist_expand_to(struct alist *lst, uint new_alloc) +{ + void *new_data; + + if (lst->flags & ALISTF_FAIL) + return false; + + /* avoid using realloc() since it increases code size */ + new_data = malloc(lst->obj_size * new_alloc); + if (!new_data) { + lst->flags |= ALISTF_FAIL; + return false; + } + + memcpy(new_data, lst->data, lst->obj_size * lst->alloc); + free(lst->data); + + memset(new_data + lst->obj_size * lst->alloc, '\0', + lst->obj_size * (new_alloc - lst->alloc)); + lst->alloc = new_alloc; + lst->data = new_data; + + return true; +} + +bool alist_expand_by(struct alist *lst, uint inc_by) +{ + return alist_expand_to(lst, lst->alloc + inc_by); +} + +/** + * alist_expand_min() - Expand to at least the provided size + * + * Expands to the lowest power of two which can incorporate the new size + * + * @lst: alist to expand + * @min_alloc: Minimum new allocated size; if 0 then ALIST_INITIAL_SIZE is used + * Return: true if OK, false if out of memory + */ +static bool alist_expand_min(struct alist *lst, uint min_alloc) +{ + uint new_alloc; + + for (new_alloc = lst->alloc ?: ALIST_INITIAL_SIZE; + new_alloc < min_alloc;) + new_alloc *= 2; + + return alist_expand_to(lst, new_alloc); +} + +const void *alist_get_ptr(const struct alist *lst, uint index) +{ + if (index >= lst->count) + return NULL; + + return lst->data + index * lst->obj_size; +} + +void *alist_ensure_ptr(struct alist *lst, uint index) +{ + uint minsize = index + 1; + void *ptr; + + if (index >= lst->alloc && !alist_expand_min(lst, minsize)) + return NULL; + + ptr = lst->data + index * lst->obj_size; + if (minsize >= lst->count) + lst->count = minsize; + + return ptr; +} + +void *alist_add_placeholder(struct alist *lst) +{ + return alist_ensure_ptr(lst, lst->count); +} + +void *alist_add_ptr(struct alist *lst, void *obj) +{ + void *ptr; + + ptr = alist_add_placeholder(lst); + if (!ptr) + return NULL; + memcpy(ptr, obj, lst->obj_size); + + return ptr; +} + +void *alist_uninit_move_ptr(struct alist *alist, size_t *countp) +{ + void *ptr; + + if (countp) + *countp = alist->count; + if (!alist->count) { + alist_uninit(alist); + return NULL; + } + + ptr = alist->data; + + /* Clear everything out so there is no record of the data */ + alist_init(alist, alist->obj_size, 0); + + return ptr; +} diff --git a/lib/asm-offsets.c b/lib/asm-offsets.c index 4e2dbda9a71..b6bbcbf76ca 100644 --- a/lib/asm-offsets.c +++ b/lib/asm-offsets.c @@ -44,7 +44,9 @@ int main(void) DEFINE(GD_NEW_GD, offsetof(struct global_data, new_gd)); +#if CONFIG_IS_ENABLED(ENV_SUPPORT) DEFINE(GD_ENV_ADDR, offsetof(struct global_data, env_addr)); +#endif return 0; } diff --git a/lib/crypto/Kconfig b/lib/crypto/Kconfig index 6e0656ad1c5..742f6d9d4ed 100644 --- a/lib/crypto/Kconfig +++ b/lib/crypto/Kconfig @@ -1,6 +1,6 @@ menuconfig ASYMMETRIC_KEY_TYPE bool "Asymmetric (public-key cryptographic) key Support" - depends on FIT_SIGNATURE + depends on FIT_SIGNATURE || RSA_VERIFY_WITH_PKEY help This option provides support for a key type that holds the data for the asymmetric keys used for public key cryptographic operations such diff --git a/lib/elf.c b/lib/elf.c index dc13935e103..e767a42a3b3 100644 --- a/lib/elf.c +++ b/lib/elf.c @@ -86,10 +86,14 @@ unsigned long load_elf64_image_phdr(unsigned long addr) phdr = (Elf64_Phdr *)(addr + (ulong)ehdr->e_phoff); /* Load each program header */ - for (i = 0; i < ehdr->e_phnum; ++i) { + for (i = 0; i < ehdr->e_phnum; ++i, ++phdr) { void *dst = (void *)(ulong)phdr->p_paddr; void *src = (void *)addr + phdr->p_offset; + /* Only load PT_LOAD program header */ + if (phdr->p_type != PT_LOAD) + continue; + debug("Loading phdr %i to 0x%p (%lu bytes)\n", i, dst, (ulong)phdr->p_filesz); if (phdr->p_filesz) @@ -99,7 +103,6 @@ unsigned long load_elf64_image_phdr(unsigned long addr) phdr->p_memsz - phdr->p_filesz); flush_cache(rounddown((unsigned long)dst, ARCH_DMA_MINALIGN), roundup(phdr->p_memsz, ARCH_DMA_MINALIGN)); - ++phdr; } if (ehdr->e_machine == EM_PPC64 && (ehdr->e_flags & @@ -201,10 +204,14 @@ unsigned long load_elf_image_phdr(unsigned long addr) phdr = (Elf32_Phdr *)(addr + ehdr->e_phoff); /* Load each program header */ - for (i = 0; i < ehdr->e_phnum; ++i) { + for (i = 0; i < ehdr->e_phnum; ++i, ++phdr) { void *dst = (void *)(uintptr_t)phdr->p_paddr; void *src = (void *)addr + phdr->p_offset; + /* Only load PT_LOAD program header */ + if (phdr->p_type != PT_LOAD) + continue; + debug("Loading phdr %i to 0x%p (%i bytes)\n", i, dst, phdr->p_filesz); if (phdr->p_filesz) @@ -214,7 +221,6 @@ unsigned long load_elf_image_phdr(unsigned long addr) phdr->p_memsz - phdr->p_filesz); flush_cache(rounddown((unsigned long)dst, ARCH_DMA_MINALIGN), roundup(phdr->p_memsz, ARCH_DMA_MINALIGN)); - ++phdr; } return ehdr->e_entry; diff --git a/lib/fdtdec.c b/lib/fdtdec.c index 6865f78c70d..5edc8dd2f9f 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -1685,6 +1685,7 @@ int fdtdec_setup(void) gd->fdt_src = FDTSRC_BLOBLIST; log_debug("Devicetree is in bloblist at %p\n", gd->fdt_blob); + ret = 0; } else { log_debug("No FDT found in bloblist\n"); ret = -ENOENT; diff --git a/lib/fwu_updates/fwu_mtd.c b/lib/fwu_updates/fwu_mtd.c index ccaba3f3115..c14203b9dd3 100644 --- a/lib/fwu_updates/fwu_mtd.c +++ b/lib/fwu_updates/fwu_mtd.c @@ -60,10 +60,7 @@ int fwu_mtd_get_alt_num(efi_guid_t *image_id, u8 *alt_num, if (ret) return -ENOENT; - nalt = 0; - list_for_each_entry(dfu, &dfu_list, list) - nalt++; - + nalt = list_count_nodes(&dfu_list); if (!nalt) { log_warning("No entities in dfu_alt_info\n"); dfu_free_entities(); diff --git a/lib/strto.c b/lib/strto.c index 5157332d6c1..f83ac67c666 100644 --- a/lib/strto.c +++ b/lib/strto.c @@ -236,12 +236,14 @@ const char **str_to_list(const char *instr) return NULL; /* count the number of space-separated strings */ - for (count = *str != '\0', p = str; *p; p++) { + for (count = 0, p = str; *p; p++) { if (*p == ' ') { count++; *p = '\0'; } } + if (p != str && p[-1]) + count++; /* allocate the pointer array, allowing for a NULL terminator */ ptr = calloc(count + 1, sizeof(char *)); |