diff options
Diffstat (limited to 'common')
| -rw-r--r-- | common/Kconfig | 10 | ||||
| -rw-r--r-- | common/autoboot.c | 11 | ||||
| -rw-r--r-- | common/bloblist.c | 209 | ||||
| -rw-r--r-- | common/board_f.c | 93 | ||||
| -rw-r--r-- | common/board_r.c | 6 | ||||
| -rw-r--r-- | common/cli.c | 8 | ||||
| -rw-r--r-- | common/command.c | 14 | ||||
| -rw-r--r-- | common/console.c | 12 | ||||
| -rw-r--r-- | common/cyclic.c | 10 | ||||
| -rw-r--r-- | common/init/handoff.c | 10 | ||||
| -rw-r--r-- | common/memsize.c | 75 | ||||
| -rw-r--r-- | common/spl/Kconfig | 45 | ||||
| -rw-r--r-- | common/spl/spl_fit.c | 98 | ||||
| -rw-r--r-- | common/spl/spl_imx_container.c | 13 | ||||
| -rw-r--r-- | common/splash_source.c | 7 | ||||
| -rw-r--r-- | common/stdio.c | 18 | ||||
| -rw-r--r-- | common/update.c | 6 | ||||
| -rw-r--r-- | common/usb_onboard_hub.c | 14 |
18 files changed, 445 insertions, 214 deletions
diff --git a/common/Kconfig b/common/Kconfig index 2a167ec3ad3..345be4b8ca1 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -78,7 +78,7 @@ config SYS_PBSIZE config DISABLE_CONSOLE bool "Add functionality to disable console completely" help - Disable console (in & out). + Disable console (in & out). config IDENT_STRING string "Board specific string to be added to uboot version string" @@ -425,7 +425,7 @@ config LOGF_FUNC_PAD config LOG_SYSLOG bool "Log output to syslog server" - depends on NET || NET_LWIP + depends on NET help Enables a log driver which broadcasts log records via UDP port 514 to syslog servers. @@ -884,9 +884,9 @@ config AVB_VERIFY help This option enables compilation of bootloader-dependent operations, used by Android Verified Boot 2.0 library (libavb). Includes: - * Helpers to process strings in order to build OS bootargs. - * Helpers to access MMC, similar to drivers/fastboot/fb_mmc.c. - * Helpers to alloc/init/free avb ops. + * Helpers to process strings in order to build OS bootargs. + * Helpers to access MMC, similar to drivers/fastboot/fb_mmc.c. + * Helpers to alloc/init/free avb ops. if AVB_VERIFY diff --git a/common/autoboot.c b/common/autoboot.c index 1783ef92c94..4b80ddb5b28 100644 --- a/common/autoboot.c +++ b/common/autoboot.c @@ -316,15 +316,6 @@ static int passwd_abort_key(uint64_t etime) } /** - * flush_stdin() - drops all pending characters from stdin - */ -static void flush_stdin(void) -{ - while (tstc()) - (void)getchar(); -} - -/** * fallback_to_sha256() - check whether we should fall back to sha256 * password checking * @@ -354,7 +345,7 @@ static int abortboot_key_sequence(int bootdelay) uint64_t etime = endtick(bootdelay); if (IS_ENABLED(CONFIG_AUTOBOOT_FLUSH_STDIN)) - flush_stdin(); + console_flush_stdin(); # ifdef CONFIG_AUTOBOOT_PROMPT /* * CONFIG_AUTOBOOT_PROMPT includes the %d for all boards. diff --git a/common/bloblist.c b/common/bloblist.c index d5fa62249a9..846c8047f74 100644 --- a/common/bloblist.c +++ b/common/bloblist.c @@ -43,6 +43,7 @@ static struct tag_name { { BLOBLISTT_ACPI_TABLES, "ACPI tables for x86" }, { BLOBLISTT_TPM_EVLOG, "TPM event log defined by TCG EFI" }, { BLOBLISTT_TPM_CRB_BASE, "TPM Command Response Buffer address" }, + { BLOBLISTT_FDT_OVERLAY, "DT overlay" }, /* BLOBLISTT_AREA_FIRMWARE */ { BLOBLISTT_TPM2_TCG_LOG, "TPM v2 log space" }, @@ -96,6 +97,19 @@ static inline uint rec_tag(struct bloblist_rec *rec) BLOBLISTR_TAG_SHIFT; } +static inline void void_blob(struct bloblist_rec *rec) +{ + if (rec_tag(rec) == BLOBLISTT_VOID) + return; + rec->tag_and_hdr_size = BLOBLISTT_VOID | + sizeof(*rec) << BLOBLISTR_HDR_SIZE_SHIFT; +} + +static inline struct bloblist_rec *rec_from_blob(void *blob) +{ + return (blob - sizeof(struct bloblist_rec)); +} + static ulong bloblist_blob_end_ofs(struct bloblist_hdr *hdr, struct bloblist_rec *rec) { @@ -222,6 +236,19 @@ static int bloblist_ensurerec(uint tag, struct bloblist_rec **recp, int size, return 0; } +static int bloblist_get_blob_data_offset(uint tag) +{ + switch (tag) { + case BLOBLISTT_FDT_OVERLAY: + return sizeof(struct dto_blob_hdr); + /* + * return the data offset if it is not following the blob + * header immediately. + */ + } + return 0; +} + void *bloblist_find(uint tag, int size) { void *blob = NULL; @@ -248,6 +275,44 @@ void *bloblist_get_blob(uint tag, int *sizep) return (void *)rec + rec_hdr_size(rec); } +int bloblist_apply_blobs(uint tag, int (*func)(void **data, int size)) +{ + struct bloblist_hdr *hdr = gd->bloblist; + struct bloblist_rec *rec; + + if (!func || !hdr) + return -ENOENT; + + foreach_rec(rec, hdr) { + /* Apply all blobs with the specified tag */ + if (rec_tag(rec) == tag) { + int ret; + int tag = rec_tag(rec); + void *blob = (void *)rec + rec_hdr_size(rec); + int dat_off = bloblist_get_blob_data_offset(tag); + + blob += dat_off; + ret = func(&blob, rec->size - dat_off); + if (ret) { + log_err("Failed to apply blob with tag %d\n", + tag); + return ret; + } + + rec = rec_from_blob(blob - dat_off); + if (!rec) { + log_err("Blob corrupted\n"); + return -ENOENT; + } + + /* Mark applied blob record as void */ + void_blob(rec); + } + } + + return 0; +} + void *bloblist_add(uint tag, int size, int align_log2) { struct bloblist_rec *rec; @@ -322,7 +387,7 @@ static int bloblist_resize_rec(struct bloblist_hdr *hdr, next_ofs = bloblist_blob_end_ofs(hdr, rec); if (next_ofs != hdr->used_size) { memmove((void *)hdr + next_ofs + expand_by, - (void *)hdr + next_ofs, new_alloced - next_ofs); + (void *)hdr + next_ofs, hdr->used_size - next_ofs); } hdr->used_size = new_alloced; @@ -383,6 +448,7 @@ int bloblist_new(ulong addr, uint size, uint flags, uint align_log2) hdr->align_log2 = align_log2 ? align_log2 : BLOBLIST_BLOB_ALIGN_LOG2; hdr->chksum = 0; gd->bloblist = hdr; + gd->flags |= GD_FLG_BLOBLIST_HANDOFF; return 0; } @@ -410,6 +476,7 @@ int bloblist_check(ulong addr, uint size) return log_msg_ret("Bad checksum", -EIO); } gd->bloblist = hdr; + gd->flags |= GD_FLG_BLOBLIST_HANDOFF; return 0; } @@ -511,90 +578,88 @@ int __weak xferlist_from_boot_arg(ulong __always_unused *addr) return -ENOENT; } -int bloblist_init(void) +bool bloblist_exists(void) { - bool fixed = IS_ENABLED(CONFIG_BLOBLIST_FIXED); - int ret = 0; - ulong addr = 0, size; + int ret; + ulong addr = 0; /* Check if a valid transfer list passed in */ - if (!xferlist_from_boot_arg(&addr)) { - size = bloblist_get_total_size(); - } else { - /* - * If U-Boot is not in the first phase, an existing bloblist must - * be at a fixed address. - */ - bool from_addr = fixed && !xpl_is_first_phase(); - - /* - * If Firmware Handoff is mandatory but no transfer list is - * observed, report it as an error. - */ - if (IS_ENABLED(CONFIG_BLOBLIST_PASSAGE_MANDATORY)) - return -ENOENT; - - ret = -ENOENT; + if (!xferlist_from_boot_arg(&addr)) + goto found; - if (xpl_prev_phase() == PHASE_TPL && - !IS_ENABLED(CONFIG_TPL_BLOBLIST)) - from_addr = false; - if (fixed) - addr = IF_ENABLED_INT(CONFIG_BLOBLIST_FIXED, - CONFIG_BLOBLIST_ADDR); - size = CONFIG_BLOBLIST_SIZE; - - if (from_addr) - ret = bloblist_check(addr, size); - - if (ret) - log_warning("Bloblist at %lx not found (err=%d)\n", - addr, ret); - else - /* Get the real size */ - size = gd->bloblist->total_size; - } + /* + * If Firmware Handoff is mandatory but no transfer list is + * observed, report it as an error. + */ + if (IS_ENABLED(CONFIG_BLOBLIST_PASSAGE_MANDATORY)) + return false; - if (ret) { - /* - * If we don't have a bloblist from a fixed address, or the one - * in the fixed address is not valid. we must allocate the - * memory for it now. - */ - if (CONFIG_IS_ENABLED(BLOBLIST_ALLOC)) { - void *ptr = memalign(BLOBLIST_ALIGN, size); + /* + * We have checked for a valid transfer list being passed. At this + * point, if we do not have a fixed address for the bloblist, we cannot + * be provided with one. + */ + if (xpl_is_first_phase() || !IS_ENABLED(CONFIG_BLOBLIST_FIXED)) + return false; - if (!ptr) - return log_msg_ret("alloc", -ENOMEM); - addr = map_to_sysmem(ptr); - } else if (!fixed) { - return log_msg_ret("BLOBLIST_FIXED is not enabled", - ret); - } - log_debug("Creating new bloblist size %lx at %lx\n", size, - addr); - ret = bloblist_new(addr, size, 0, 0); - } else { - log_debug("Found existing bloblist size %lx at %lx\n", size, - addr); - } + /* + * Check for a valid list as the configured address. + */ + addr = IF_ENABLED_INT(CONFIG_BLOBLIST_FIXED, + CONFIG_BLOBLIST_ADDR); + ret = bloblist_check(addr, CONFIG_BLOBLIST_SIZE); + if (!ret) + goto found; - if (ret) - return log_msg_ret("ini", ret); - gd->flags |= GD_FLG_BLOBLIST_READY; + log_debug("Bloblist at %lx not found (err=%d)\n", addr, ret); + return false; +found: #ifdef DEBUG bloblist_show_stats(); bloblist_show_list(); #endif - - return 0; + return true; } -int bloblist_maybe_init(void) +int bloblist_init(void) { - if (CONFIG_IS_ENABLED(BLOBLIST) && !(gd->flags & GD_FLG_BLOBLIST_READY)) - return bloblist_init(); + int ret; + ulong addr = 0, size = CONFIG_BLOBLIST_SIZE; + + if (gd->flags & GD_FLG_BLOBLIST_HANDOFF) { + log_debug("Found existing bloblist size %x at %p\n", + gd->bloblist->total_size, gd->bloblist); + return 0; + } + + /* + * If Firmware Handoff is mandatory but no transfer list has been + * observed by fdtdec_setup, report it as an error. + */ + if (IS_ENABLED(CONFIG_BLOBLIST_PASSAGE_MANDATORY)) + return -ENOENT; + + /* + * If we don't have an existing bloblist, we either need + * to allocate one now, or initialize the fixed address + * space as a bloblist. + */ + if (CONFIG_IS_ENABLED(BLOBLIST_ALLOC)) { + void *ptr = memalign(BLOBLIST_ALIGN, size); + + if (!ptr) + return log_msg_ret("alloc", -ENOMEM); + addr = map_to_sysmem(ptr); + } else + addr = IF_ENABLED_INT(CONFIG_BLOBLIST_FIXED, + CONFIG_BLOBLIST_ADDR); + + log_debug("Creating new bloblist size %lx at %lx\n", size, + addr); + ret = bloblist_new(addr, size, 0, 0); + if (ret) + return log_msg_ret("ini", ret); return 0; } @@ -622,7 +687,9 @@ int bloblist_check_reg_conv(ulong rfdt, ulong rzero, ulong rsig, ulong xlist) return ret; if (rfdt != (ulong)bloblist_find(BLOBLISTT_CONTROL_FDT, 0)) { - gd->bloblist = NULL; /* Reset the gd bloblist pointer */ + /* Remove this bloblist from gd */ + gd->bloblist = NULL; + gd->flags &= ~GD_FLG_BLOBLIST_HANDOFF; return -EIO; } diff --git a/common/board_f.c b/common/board_f.c index 11ad5779115..85b888d4bb8 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -31,6 +31,7 @@ #include <log.h> #include <malloc.h> #include <mapmem.h> +#include <memtop.h> #include <os.h> #include <post.h> #include <relocate.h> @@ -50,6 +51,7 @@ #include <dm/root.h> #include <linux/errno.h> #include <linux/log2.h> +#include <linux/sizes.h> DECLARE_GLOBAL_DATA_PTR; @@ -222,11 +224,11 @@ static int show_dram_config(void) debug("\nRAM Configuration:\n"); for (i = size = 0; i < CONFIG_NR_DRAM_BANKS; i++) { - size += gd->bd->bi_dram[i].size; + size += gd->dram[i].size; debug("Bank #%d: %llx ", i, - (unsigned long long)(gd->bd->bi_dram[i].start)); + (unsigned long long)(gd->dram[i].start)); #ifdef DEBUG - print_size(gd->bd->bi_dram[i].size, "\n"); + print_size(gd->dram[i].size, "\n"); #endif } debug("\nDRAM: "); @@ -244,8 +246,8 @@ static int show_dram_config(void) __weak int dram_init_banksize(void) { - gd->bd->bi_dram[0].start = gd->ram_base; - gd->bd->bi_dram[0].size = get_effective_memsize(); + gd->dram[0].start = gd->ram_base; + gd->dram[0].size = get_effective_memsize(); return 0; } @@ -308,6 +310,9 @@ __weak int mach_cpu_init(void) /* Get the top of usable RAM */ __weak phys_addr_t board_get_usable_ram_top(phys_size_t total_size) { + if (CONFIG_IS_ENABLED(RELOC_ADDR_TOP)) + return gd->ram_top; + #if defined(CFG_SYS_SDRAM_BASE) && CFG_SYS_SDRAM_BASE > 0 /* * Detect whether we have so much RAM that it goes past the end of our @@ -328,14 +333,34 @@ __weak int arch_setup_dest_addr(void) return 0; } -static int setup_dest_addr(void) +static int setup_ram_base(void) +{ +#ifdef CFG_SYS_SDRAM_BASE + gd->ram_base = CFG_SYS_SDRAM_BASE; +#endif + return 0; +} + +static int setup_ram_config(void) { debug("Monitor len: %08x\n", gd->mon_len); - /* - * Ram is setup, size stored in gd !! - */ - debug("Ram size: %08llX\n", (unsigned long long)gd->ram_size); -#if CONFIG_VAL(SYS_MEM_TOP_HIDE) + + if (CONFIG_IS_ENABLED(RELOC_ADDR_TOP)) { + int i; + phys_addr_t top; + + gd->ram_size = 0; + for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { + top = get_mem_top(gd->dram[i].start, gd->dram[i].size, + ALIGN(gd->mon_len, SZ_1M), + (void *)gd->fdt_blob); + gd->ram_top = max(top, gd->ram_top); + gd->ram_size += gd->dram[i].size; + } + } else { + gd->ram_top = gd->ram_base + get_effective_memsize(); + } + gd->ram_top = board_get_usable_ram_top(gd->mon_len); /* * Subtract specified amount of memory to hide so that it won't * get "touched" at all by U-Boot. By fixing up gd->ram_size @@ -346,17 +371,30 @@ static int setup_dest_addr(void) * memory size from the SDRAM controller setup will have to * get fixed. */ +#if CONFIG_VAL(SYS_MEM_TOP_HIDE) + gd->ram_top -= CONFIG_SYS_MEM_TOP_HIDE; gd->ram_size -= CONFIG_SYS_MEM_TOP_HIDE; #endif -#ifdef CFG_SYS_SDRAM_BASE - gd->ram_base = CFG_SYS_SDRAM_BASE; -#endif - gd->ram_top = gd->ram_base + get_effective_memsize(); - gd->ram_top = board_get_usable_ram_top(gd->mon_len); + + debug("Ram top: %08llx\n", (unsigned long long)gd->ram_top); + debug("Ram size: %08llx\n", (unsigned long long)gd->ram_size); + + return 0; +} + +static int setup_dest_addr(void) +{ + int ret; + gd->relocaddr = gd->ram_top; - debug("Ram top: %08llX\n", (unsigned long long)gd->ram_top); + debug("Reloc addr: %08llX\n", (unsigned long long)gd->relocaddr); - return arch_setup_dest_addr(); + ret = arch_setup_dest_addr(); + if (ret) + return ret; + + gd->initial_relocaddr = gd->relocaddr; + return 0; } #ifdef CFG_PRAM @@ -813,7 +851,16 @@ static int initf_dm(void) return 0; bootstage_start(BOOTSTAGE_ID_ACCUM_DM_F, "dm_f"); - ret = dm_init_and_scan(true); + + /* + * If SKIP_EARLY_DM is set then we just create an empty device + * model, the serial port will still be bound later through + * serial_find_console_or_panic() via /chosen/stdout-path + */ + if (!CONFIG_IS_ENABLED(SKIP_EARLY_DM)) + ret = dm_init_and_scan(true); + else + ret = dm_init(false); if (ret) return ret; @@ -885,7 +932,9 @@ static void initcall_run_f(void) INITCALL(log_init); INITCALL(initf_bootstage); /* uses its own timer, so does not need DM */ INITCALL(event_init); - INITCALL(bloblist_maybe_init); +#if CONFIG_IS_ENABLED(BLOBLIST) + INITCALL(bloblist_init); +#endif INITCALL(setup_spl_handoff); #if CONFIG_IS_ENABLED(CONSOLE_RECORD_INIT_F) INITCALL(console_record_init); @@ -959,6 +1008,9 @@ static void initcall_run_f(void) * - monitor code * - board info struct */ + INITCALL(setup_ram_base); + INITCALL(dram_init_banksize); + INITCALL(setup_ram_config); INITCALL(setup_dest_addr); #if CONFIG_IS_ENABLED(OF_BOARD_FIXUP) && \ !CONFIG_IS_ENABLED(OF_INITIAL_DTB_READONLY) @@ -986,7 +1038,6 @@ static void initcall_run_f(void) INITCALL(reserve_bloblist); INITCALL(reserve_arch); INITCALL(reserve_stacks); - INITCALL(dram_init_banksize); INITCALL(show_dram_config); WATCHDOG_RESET(); INITCALL(setup_bdinfo); diff --git a/common/board_r.c b/common/board_r.c index 5d37345ca09..a397e20959d 100644 --- a/common/board_r.c +++ b/common/board_r.c @@ -495,7 +495,7 @@ static int initr_boot_led_on(void) return 0; } -#if CONFIG_IS_ENABLED(NET) || CONFIG_IS_ENABLED(NET_LWIP) +#if CONFIG_IS_ENABLED(NET) static int initr_net(void) { puts("Net: "); @@ -687,7 +687,7 @@ static void initcall_run_r(void) INITCALL(initr_flash); #endif WATCHDOG_RESET(); -#if CONFIG_IS_ENABLED(PPC) || CONFIG_IS_ENABLED(M68K) || CONFIG_IS_ENABLED(X86) +#if IS_ENABLED(CONFIG_PPC) || CONFIG_IS_ENABLED(M68K) || CONFIG_IS_ENABLED(X86) /* initialize higher level parts of CPU like time base and timers */ INITCALL(cpu_init_r); #endif @@ -760,7 +760,7 @@ static void initcall_run_r(void) #if CONFIG_IS_ENABLED(PCI_ENDPOINT) INITCALL(pci_ep_init); #endif -#if CONFIG_IS_ENABLED(NET) || CONFIG_IS_ENABLED(NET_LWIP) +#if CONFIG_IS_ENABLED(NET) WATCHDOG_RESET(); INITCALL(initr_net); #endif diff --git a/common/cli.c b/common/cli.c index 4694a35cd0e..87ce0e4d144 100644 --- a/common/cli.c +++ b/common/cli.c @@ -138,11 +138,9 @@ int run_command_list(const char *cmd, int len, int flag) #endif } if (need_buff) { - buff = malloc(len + 1); + buff = memdup_nul(cmd, len); if (!buff) return 1; - memcpy(buff, cmd, len); - buff[len] = '\0'; } #ifdef CONFIG_HUSH_PARSER if (use_hush_old()) { @@ -295,6 +293,10 @@ err: void cli_loop(void) { bootstage_mark(BOOTSTAGE_ID_ENTER_CLI_LOOP); + + if (IS_ENABLED(CONFIG_CMDLINE_FLUSH_STDIN)) + console_flush_stdin(); + #if CONFIG_IS_ENABLED(HUSH_PARSER) if (gd->flags & GD_FLG_HUSH_MODERN_PARSER) parse_and_run_file(); diff --git a/common/command.c b/common/command.c index 0f9dd06d72b..eb2c2123534 100644 --- a/common/command.c +++ b/common/command.c @@ -367,11 +367,15 @@ int cmd_auto_complete(const char *const prompt, char *buf, int *np, int *colp) int i, j, k, len, seplen, argc; int cnt; char last_char; -#ifdef CONFIG_CMDLINE_PS_SUPPORT - const char *ps_prompt = env_get("PS1"); -#else - const char *ps_prompt = CONFIG_SYS_PROMPT; -#endif + const char *ps_prompt; + + if (IS_ENABLED(CONFIG_CMDLINE_PS_SUPPORT)) { + ps_prompt = env_get("PS1"); + + if (!ps_prompt) + ps_prompt = CONFIG_SYS_PROMPT; + } else + ps_prompt = CONFIG_SYS_PROMPT; if (strcmp(prompt, ps_prompt) != 0) return 0; /* not in normal console */ diff --git a/common/console.c b/common/console.c index 22e554cf203..54d1249422d 100644 --- a/common/console.c +++ b/common/console.c @@ -643,6 +643,15 @@ int tstc(void) return serial_tstc(); } +/** + * console_flush_stdin() - drops all pending characters from stdin + */ +void console_flush_stdin(void) +{ + while (tstc()) + (void)getchar(); +} + #define PRE_CONSOLE_FLUSHPOINT1_SERIAL 0 #define PRE_CONSOLE_FLUSHPOINT2_EVERYTHING_BUT_SERIAL 1 @@ -914,8 +923,7 @@ int confirm_yesno(void) char str_input[5]; /* Flush input */ - while (tstc()) - getchar(); + console_flush_stdin(); i = 0; while (i < sizeof(str_input)) { str_input[i] = getchar(); diff --git a/common/cyclic.c b/common/cyclic.c index ec952a01ee1..573e715587d 100644 --- a/common/cyclic.c +++ b/common/cyclic.c @@ -41,7 +41,7 @@ static bool cyclic_is_registered(const struct cyclic_info *cyclic) } void cyclic_register(struct cyclic_info *cyclic, cyclic_func_t func, - uint64_t delay_us, const char *name) + u64 delay_us, const char *name) { cyclic_unregister(cyclic); @@ -67,26 +67,28 @@ static void cyclic_run(void) { struct cyclic_info *cyclic; struct hlist_node *tmp; - uint64_t now, cpu_time; + u64 now, after, cpu_time; /* Prevent recursion */ if (gd->flags & GD_FLG_CYCLIC_RUNNING) return; gd->flags |= GD_FLG_CYCLIC_RUNNING; + now = get_timer_us(0); hlist_for_each_entry_safe(cyclic, tmp, cyclic_get_list(), list) { /* * Check if this cyclic function needs to get called, e.g. * do not call the cyclic func too often */ - now = get_timer_us(0); if (time_after_eq64(now, cyclic->next_call)) { /* Call cyclic function and account it's cpu-time */ cyclic->next_call = now + cyclic->delay_us; cyclic->func(cyclic); + after = get_timer_us(0); cyclic->run_cnt++; - cpu_time = get_timer_us(0) - now; + cpu_time = after - now; cyclic->cpu_time_us += cpu_time; + now = after; /* Check if cpu-time exceeds max allowed time */ if ((cpu_time > CONFIG_CYCLIC_MAX_CPU_TIME_US) && diff --git a/common/init/handoff.c b/common/init/handoff.c index a7cd065fb38..a4d9d14393b 100644 --- a/common/init/handoff.c +++ b/common/init/handoff.c @@ -12,14 +12,13 @@ DECLARE_GLOBAL_DATA_PTR; void handoff_save_dram(struct spl_handoff *ho) { - struct bd_info *bd = gd->bd; int i; ho->ram_size = gd->ram_size; for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { - ho->ram_bank[i].start = bd->bi_dram[i].start; - ho->ram_bank[i].size = bd->bi_dram[i].size; + ho->ram_bank[i].start = gd->dram[i].start; + ho->ram_bank[i].size = gd->dram[i].size; } } @@ -30,11 +29,10 @@ void handoff_load_dram_size(struct spl_handoff *ho) void handoff_load_dram_banks(struct spl_handoff *ho) { - struct bd_info *bd = gd->bd; int i; for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { - bd->bi_dram[i].start = ho->ram_bank[i].start; - bd->bi_dram[i].size = ho->ram_bank[i].size; + gd->dram[i].start = ho->ram_bank[i].start; + gd->dram[i].size = ho->ram_bank[i].size; } } diff --git a/common/memsize.c b/common/memsize.c index 1abf3fc47d7..fd22f85a164 100644 --- a/common/memsize.c +++ b/common/memsize.c @@ -127,6 +127,81 @@ long get_ram_size(long *base, long maxsize) return (maxsize); } +/** + * probe_ram_size_by_alias() - Detect RAM size using known alias addresses + * @checks: Array of RAM alias probe descriptors, terminated by a NULL + * @probe_addr entry + * + * Probe RAM size by writing a test pattern to each @probe_addr and checking + * whether the same pattern does not appear at the corresponding @alias_addr. + * This is useful on systems where address wrap-around does not alias to the + * base of memory in a linear way, so get_ram_size() cannot be used directly. + * It is also useful on systems where the base of the physical memory cannot + * be safely accessed, so get_ram_size() cannot be used at all. + * + * Return: The size associated with the first matching entry, or 0 if no match + * is found. + */ +long probe_ram_size_by_alias(const struct ram_alias_check *checks) +{ + long save[2]; + long pat; + int dcache_en = 0; + long ret = 0; + + if (!CONFIG_IS_ENABLED(SYS_DCACHE_OFF)) + dcache_en = dcache_status(); + + while (checks->probe_addr && !ret) { + volatile long *d = checks->probe_addr; + volatile long *s = checks->alias_addr; + + save[0] = *s; + save[1] = *d; + /* Ensure s is written and not cached */ + if (dcache_en) + dcache_flush_invalidate(s); + + pat = ~save[0]; + *d = pat; + sync(); + if (dcache_en) + dcache_flush_invalidate(d); + + /* + * Make sure the test pattern is observable at the probe + * address before checking whether it is also visible through + * the alias address. + */ + if (*d != pat) { + *d = save[1]; + sync(); + if (dcache_en) + dcache_flush_invalidate(d); + checks++; + continue; + } + + if (*s != pat) + ret = checks->size; + + /* Restore content */ + *d = save[1]; + sync(); + if (dcache_en) + dcache_flush_invalidate(d); + + *s = save[0]; + sync(); + if (dcache_en) + dcache_flush_invalidate(s); + + checks++; + } + + return ret; +} + phys_size_t __weak get_effective_memsize(void) { phys_size_t ram_size = gd->ram_size; diff --git a/common/spl/Kconfig b/common/spl/Kconfig index a21b71ad5d1..0618f42c941 100644 --- a/common/spl/Kconfig +++ b/common/spl/Kconfig @@ -220,7 +220,7 @@ source "common/spl/Kconfig.nxp" config HANDOFF bool "Pass hand-off information from SPL to U-Boot proper" - depends on BLOBLIST + depends on BLOBLIST_FIXED help It is useful to be able to pass information from SPL to U-Boot proper to preserve state that is known in SPL and is needed in U-Boot. @@ -541,7 +541,7 @@ config SPL_SYS_MMCSD_RAW_MODE ARCH_MX6 || ARCH_MX7 || \ ARCH_ROCKCHIP || ARCH_MVEBU || ARCH_SOCFPGA_GEN5 || \ ARCH_AT91 || ARCH_ZYNQ || ARCH_KEYSTONE || OMAP34XX || \ - OMAP54XX || AM33XX || AM43XX || \ + OMAP44XX || OMAP54XX || AM33XX || AM43XX || \ TARGET_SIFIVE_UNLEASHED || TARGET_SIFIVE_UNMATCHED help Support booting from an MMC without a filesystem. @@ -585,7 +585,7 @@ config SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR default 0x100 if ARCH_UNIPHIER default 0x0 if ARCH_MVEBU default 0x200 if ARCH_SOCFPGA_GEN5 || ARCH_AT91 - default 0x300 if ARCH_ZYNQ || ARCH_KEYSTONE || OMAP34XX || \ + default 0x300 if ARCH_ZYNQ || ARCH_KEYSTONE || OMAP34XX || OMAP44XX || \ OMAP54XX || AM33XX || AM43XX || ARCH_K3 default 0x4000 if ARCH_ROCKCHIP default 0x822 if TARGET_SIFIVE_UNLEASHED || TARGET_SIFIVE_UNMATCHED @@ -1151,7 +1151,7 @@ config SPL_DM_SPI_FLASH config SPL_NET bool "Support networking" - depends on NET + depends on NET_LEGACY select SPL_USE_TINY_PRINTF_POINTER_SUPPORT if SPL_USE_TINY_PRINTF help Enable support for network devices (such as Ethernet) in SPL. @@ -1160,6 +1160,9 @@ config SPL_NET the network stack uses a number of environment variables. See also SPL_ETH. +config SPL_NET_LEGACY + def_bool y if SPL_NET + config SPL_NET_VCI_STRING string "BOOTP Vendor Class Identifier string sent by SPL" depends on SPL_NET @@ -1318,10 +1321,10 @@ config SPL_PCI config SPL_PCI_ENDPOINT bool "Support for PCI endpoint drivers" help - Enable this configuration option to support configurable PCI - endpoints at SPL. This should be enabled if the platform has - a PCI controllers that can operate in endpoint mode (as a device - connected to PCI host or bridge). + Enable this configuration option to support configurable PCI + endpoints at SPL. This should be enabled if the platform has + a PCI controllers that can operate in endpoint mode (as a device + connected to PCI host or bridge). config SPL_PCH bool "Support PCH drivers" @@ -1549,18 +1552,18 @@ config SPL_SPI_FLASH_TINY depends on !SPI_FLASH_BAR default y if SPI_FLASH help - Enable lightweight SPL SPI Flash support that supports just reading - data/images from flash. No support to write/erase flash. Enable - this if you have SPL size limitations and don't need full - fledged SPI flash support. + Enable lightweight SPL SPI Flash support that supports just reading + data/images from flash. No support to write/erase flash. Enable + this if you have SPL size limitations and don't need full + fledged SPI flash support. config SPL_SPI_FLASH_SFDP_SUPPORT bool "SFDP table parsing support for SPI NOR flashes" depends on !SPI_FLASH_BAR && !SPL_SPI_FLASH_TINY help - Enable support for parsing and auto discovery of parameters for - SPI NOR flashes using Serial Flash Discoverable Parameters (SFDP) - tables as per JESD216 standard in SPL. + Enable support for parsing and auto discovery of parameters for + SPI NOR flashes using Serial Flash Discoverable Parameters (SFDP) + tables as per JESD216 standard in SPL. config SPL_SPI_FLASH_MTD bool "Support for SPI flash MTD drivers in SPL" @@ -1581,22 +1584,22 @@ config SYS_SPI_U_BOOT_OFFS default 0x0 depends on SPL_SPI_LOAD || SPL_SPI_SUNXI help - Address within SPI-Flash from where the u-boot payload is fetched - from. + Address within SPI-Flash from where the u-boot payload is fetched + from. config SYS_SPI_KERNEL_OFFS hex "Falcon mode: address of kernel payload in SPI flash" depends on SPL_SPI_FLASH_SUPPORT && SPL_OS_BOOT help - Address within SPI-Flash from where the kernel payload is fetched - in falcon boot. + Address within SPI-Flash from where the kernel payload is fetched + in falcon boot. config SYS_SPI_ARGS_OFFS hex "Falcon mode: address of args payload in SPI flash" depends on SPL_SPI_FLASH_SUPPORT && SPL_OS_BOOT_ARGS help - Address within SPI-Flash from where the args payload (usually the - dtb) is fetched in falcon boot. + Address within SPI-Flash from where the args payload (usually the + dtb) is fetched in falcon boot. config SYS_SPI_ARGS_SIZE hex "Falcon mode: size of args payload in SPI flash" diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c index 46ebcabe56a..18bff7b8d4a 100644 --- a/common/spl/spl_fit.c +++ b/common/spl/spl_fit.c @@ -204,6 +204,9 @@ static int get_aligned_image_size(struct spl_load_info *info, int data_size, * If the FIT node does not contain a "load" (address) property, * the image gets loaded to the address pointed to by the * load_addr member in this struct, if load_addr is not 0 + * @max_size: maximum number of bytes that may be written to the + * destination; an image whose data exceeds this is rejected + * before it is read from the device * * Return: 0 on success, -EBADSLT if this image is not the correct phase * (for CONFIG_BOOTMETH_VBE_SIMPLE_FW), or another negative error number on @@ -211,7 +214,7 @@ static int get_aligned_image_size(struct spl_load_info *info, int data_size, */ static int load_simple_fit(struct spl_load_info *info, ulong fit_offset, const struct spl_fit_info *ctx, int node, - struct spl_image_info *image_info) + struct spl_image_info *image_info, ulong max_size) { int offset; size_t length; @@ -291,6 +294,23 @@ static int load_simple_fit(struct spl_load_info *info, ulong fit_offset, return 0; } + /* + * data-size is excluded from the configuration signature (it + * is in exc_prop[] in image-fit-sig.c), so it stays attacker + * controlled even after fit_config_verify() succeeds. The + * image hash is only verified after the device read below, so + * an oversized value has to be rejected here. + * + * Bail out before get_aligned_image_size() runs on a hostile + * len: that helper does its arithmetic in int and would + * invoke signed-integer overflow on a value close to or above + * INT_MAX. The block-aligned check further down is the + * mathematically binding one, since size is len rounded up to + * the device block length. + */ + if ((ulong)len > max_size) + goto too_big; + if (spl_decompression_enabled() && (image_comp == IH_COMP_GZIP || image_comp == IH_COMP_LZMA)) src_ptr = map_sysmem(ALIGN(CONFIG_SYS_LOAD_ADDR, ARCH_DMA_MINALIGN), len); @@ -302,6 +322,15 @@ static int load_simple_fit(struct spl_load_info *info, ulong fit_offset, size = get_aligned_image_size(info, length, offset); read_offset = fit_offset + get_aligned_image_offset(info, offset); + + /* + * info->read() transfers the block-aligned size into the + * destination, so this is the bound that actually matters; + * len was rejected above only to keep this computation safe. + */ + if (size > max_size) + goto too_big; + log_debug("reading from offset %x / %lx size %lx to %p: ", offset, read_offset, size, src_ptr); @@ -372,6 +401,11 @@ static int load_simple_fit(struct spl_load_info *info, ulong fit_offset, upl_add_image(fit, node, load_addr, length); return 0; + +too_big: + printf("%s: FIT image too large (data-size %u, max %lu)\n", + __func__, (u32)len, max_size); + return -EFBIG; } static bool os_takes_devicetree(uint8_t os) @@ -427,7 +461,8 @@ static int spl_fit_append_fdt(struct spl_image_info *spl_image, spl_image->fdt_addr = map_sysmem(image_info.load_addr, size); memcpy(spl_image->fdt_addr, gd->fdt_blob, size); } else { - ret = load_simple_fit(info, offset, ctx, node, &image_info); + ret = load_simple_fit(info, offset, ctx, node, &image_info, + CONFIG_SYS_BOOTM_LEN); if (ret < 0) return ret; @@ -479,7 +514,8 @@ static int spl_fit_append_fdt(struct spl_image_info *spl_image, } image_info.load_addr = (ulong)tmpbuffer; ret = load_simple_fit(info, offset, ctx, node, - &image_info); + &image_info, + CONFIG_SPL_LOAD_FIT_APPLY_OVERLAY_BUF_SZ); if (ret == -EBADSLT) continue; else if (ret < 0) @@ -687,7 +723,8 @@ static int spl_fit_load_fpga(struct spl_fit_info *ctx, warn_deprecated("'fpga' property in config node. Use 'loadables'"); /* Load the image and set up the fpga_image structure */ - ret = load_simple_fit(info, offset, ctx, node, &fpga_image); + ret = load_simple_fit(info, offset, ctx, node, &fpga_image, + CONFIG_SYS_BOOTM_LEN); if (ret) { printf("%s: Cannot load the FPGA: %i\n", __func__, ret); return ret; @@ -775,7 +812,7 @@ static int spl_simple_fit_parse(struct spl_fit_info *ctx) if (ctx->conf_node < 0) return -EINVAL; - if (IS_ENABLED(CONFIG_SPL_FIT_SIGNATURE)) { + if (CONFIG_IS_ENABLED(FIT_SIGNATURE)) { printf("## Checking hash(es) for config %s ... ", fit_get_name(ctx->fit, ctx->conf_node, NULL)); if (fit_config_verify(ctx->fit, ctx->conf_node)) @@ -849,7 +886,8 @@ int spl_load_simple_fit(struct spl_image_info *spl_image, } /* Load the image and set up the spl_image structure */ - ret = load_simple_fit(info, offset, &ctx, node, spl_image); + ret = load_simple_fit(info, offset, &ctx, node, spl_image, + CONFIG_SYS_BOOTM_LEN); if (ret) return ret; @@ -890,7 +928,8 @@ int spl_load_simple_fit(struct spl_image_info *spl_image, continue; image_info.load_addr = 0; - ret = load_simple_fit(info, offset, &ctx, node, &image_info); + ret = load_simple_fit(info, offset, &ctx, node, &image_info, + CONFIG_SYS_BOOTM_LEN); if (ret < 0 && ret != -EBADSLT) { printf("%s: can't load image loadables index %d (ret = %d)\n", __func__, index, ret); @@ -955,22 +994,12 @@ int spl_load_fit_image(struct spl_image_info *spl_image, int idx, conf_noffset; int ret; -#ifdef CONFIG_SPL_FIT_SIGNATURE - images.verify = 1; -#endif + images.verify = CONFIG_IS_ENABLED(FIT_SIGNATURE); + ret = fit_image_load(&images, virt_to_phys((void *)header), - NULL, &fit_uname_config, - IH_ARCH_DEFAULT, IH_TYPE_STANDALONE, -1, - FIT_LOAD_OPTIONAL, &fw_data, &fw_len); - if (ret >= 0) { - printf("DEPRECATED: 'standalone = ' property."); - printf("Please use either 'firmware =' or 'kernel ='\n"); - } else { - ret = fit_image_load(&images, virt_to_phys((void *)header), - NULL, &fit_uname_config, IH_ARCH_DEFAULT, - IH_TYPE_FIRMWARE, -1, FIT_LOAD_OPTIONAL, - &fw_data, &fw_len); - } + NULL, &fit_uname_config, IH_ARCH_DEFAULT, + IH_TYPE_FIRMWARE, -1, FIT_LOAD_OPTIONAL, + &fw_data, &fw_len); if (ret < 0) { ret = fit_image_load(&images, virt_to_phys((void *)header), @@ -993,21 +1022,21 @@ int spl_load_fit_image(struct spl_image_info *spl_image, debug(PHASE_PROMPT "payload image: %32s load addr: 0x%lx size: %d\n", spl_image->name, spl_image->load_addr, spl_image->size); -#ifdef CONFIG_SPL_FIT_SIGNATURE - images.verify = 1; -#endif + images.verify = CONFIG_IS_ENABLED(FIT_SIGNATURE); + ret = fit_image_load(&images, virt_to_phys((void *)header), NULL, &fit_uname_config, IH_ARCH_DEFAULT, IH_TYPE_FLATDT, -1, FIT_LOAD_OPTIONAL, &dt_data, &dt_len); if (ret >= 0) { - spl_image->fdt_addr = (void *)dt_data; - if (spl_image->os == IH_OS_U_BOOT) { /* HACK: U-Boot expects FDT at a specific address */ - fdt_hack = spl_image->load_addr + spl_image->size; - fdt_hack = (fdt_hack + 3) & ~3; - debug("Relocating FDT to %p\n", spl_image->fdt_addr); - memcpy((void *)fdt_hack, spl_image->fdt_addr, dt_len); + fdt_hack = ALIGN(spl_image->load_addr + spl_image->size, 8); + debug("Relocating FDT to %p\n", (void *)fdt_hack); + memcpy(map_sysmem(fdt_hack, dt_len), + map_sysmem(dt_data, 0), dt_len); + spl_image->fdt_addr = (void *)fdt_hack; + } else { + spl_image->fdt_addr = (void *)dt_data; } } @@ -1021,10 +1050,9 @@ int spl_load_fit_image(struct spl_image_info *spl_image, FIT_LOADABLE_PROP, idx, NULL), uname; idx++) { -#ifdef CONFIG_SPL_FIT_SIGNATURE - images.verify = 1; -#endif - ret = fit_image_load(&images, (ulong)header, + images.verify = CONFIG_IS_ENABLED(FIT_SIGNATURE); + + ret = fit_image_load(&images, virt_to_phys((void *)header), &uname, &fit_uname_config, IH_ARCH_DEFAULT, IH_TYPE_LOADABLE, -1, FIT_LOAD_OPTIONAL_NON_ZERO, diff --git a/common/spl/spl_imx_container.c b/common/spl/spl_imx_container.c index 79d021f81dc..57cd75b9b5e 100644 --- a/common/spl/spl_imx_container.c +++ b/common/spl/spl_imx_container.c @@ -88,6 +88,7 @@ static int read_auth_container(struct spl_image_info *spl_image, struct spl_load_info *info, ulong offset) { struct container_hdr *container = NULL; + struct container_hdr *authhdr; u16 length; int i, size, ret = 0; @@ -140,15 +141,19 @@ static int read_auth_container(struct spl_image_info *spl_image, } } + authhdr = container; + #ifdef CONFIG_AHAB_BOOT - ret = ahab_auth_cntr_hdr(container, length); - if (ret) + authhdr = ahab_auth_cntr_hdr(authhdr, length); + if (!authhdr) { + ret = -EINVAL; goto end_auth; + } #endif - for (i = 0; i < container->num_images; i++) { + for (i = 0; i < authhdr->num_images; i++) { struct boot_img_t *image = read_auth_image(spl_image, info, - container, i, + authhdr, i, offset); if (!image) { diff --git a/common/splash_source.c b/common/splash_source.c index 0710e302ba1..e02f9be05e4 100644 --- a/common/splash_source.c +++ b/common/splash_source.c @@ -159,12 +159,12 @@ static int splash_select_fs_dev(struct splash_location *location) res = -ENODEV; break; default: - printf("Error: unsupported location storage.\n"); + printf("Error: %s: unsupported location storage.\n", __func__); return -ENODEV; } if (res) - printf("Error: could not access storage.\n"); + printf("Error: %s: could not access storage.\n", __func__); return res; } @@ -284,7 +284,8 @@ static int splash_load_fs(struct splash_location *location, ulong bmp_load_addr) res = fs_size(splash_file, &bmp_size); if (res) { - printf("Error (%d): cannot determine file size\n", res); + printf("Error: %s: cannot determine file size (%d)\n", + __func__, res); goto out; } diff --git a/common/stdio.c b/common/stdio.c index fc965944209..038e576147b 100644 --- a/common/stdio.c +++ b/common/stdio.c @@ -217,27 +217,11 @@ struct stdio_dev *stdio_get_by_name(const char *name) return NULL; } -struct stdio_dev *stdio_clone(struct stdio_dev *dev) -{ - struct stdio_dev *_dev; - - if (!dev) - return NULL; - - _dev = calloc(1, sizeof(struct stdio_dev)); - if (!_dev) - return NULL; - - memcpy(_dev, dev, sizeof(struct stdio_dev)); - - return _dev; -} - int stdio_register_dev(struct stdio_dev *dev, struct stdio_dev **devp) { struct stdio_dev *_dev; - _dev = stdio_clone(dev); + _dev = memdup(dev, sizeof(*dev)); if (!_dev) return -ENODEV; list_add_tail(&_dev->list, &devs.list); diff --git a/common/update.c b/common/update.c index 0bafffede9e..06e53cbd402 100644 --- a/common/update.c +++ b/common/update.c @@ -32,7 +32,7 @@ static uchar *saved_prot_info; #endif static int update_load(char *filename, ulong msec_max, int cnt_max, ulong addr) { - int rv; + int rv, ret; ulong saved_timeout_msecs; int saved_timeout_count; char *saved_netretry, *saved_bootfile; @@ -54,9 +54,9 @@ static int update_load(char *filename, ulong msec_max, int cnt_max, ulong addr) /* download the update file */ image_load_addr = addr; copy_filename(net_boot_file_name, filename, sizeof(net_boot_file_name)); - rv = net_loop(TFTPGET); + ret = net_loop(TFTPGET); - if (rv < 0) + if (ret < 0) rv = 1; else flush_cache(addr, net_boot_file_size); diff --git a/common/usb_onboard_hub.c b/common/usb_onboard_hub.c index 6fc34489a98..0684f7bfd47 100644 --- a/common/usb_onboard_hub.c +++ b/common/usb_onboard_hub.c @@ -262,6 +262,12 @@ static int usb_onboard_hub_remove(struct udevice *dev) return ret; } +static const struct onboard_hub_data corechips_sl6341_data = { + .reset_us = 10000, + .num_supplies = 2, + .supply_names = { "vdd1v1-supply", "vdd3v3-supply" }, +}; + static const struct onboard_hub_data usb2514_data = { .power_on_delay_us = 500, .reset_us = 1, @@ -285,7 +291,13 @@ static const struct onboard_hub_data usbhx3_data = { static const struct udevice_id usb_onboard_hub_ids[] = { /* Use generic usbVID,PID dt-bindings (usb-device.yaml) */ - { .compatible = "usb424,2514", /* USB2514B USB 2.0 */ + { .compatible = "usb3431,6241", /* Corechips SL6341 USB 2.0 */ + .data = (ulong)&corechips_sl6341_data, + }, { + .compatible = "usb3431,6341", /* Corechips SL6341 USB 3.0 */ + .data = (ulong)&corechips_sl6341_data, + }, { + .compatible = "usb424,2514", /* USB2514B USB 2.0 */ .data = (ulong)&usb2514_data, }, { .compatible = "usb424,2744", /* USB2744 USB 2.0 */ |
