diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/Kconfig | 20 | ||||
-rw-r--r-- | common/Makefile | 3 | ||||
-rw-r--r-- | common/board_f.c | 82 | ||||
-rw-r--r-- | common/board_r.c | 31 | ||||
-rw-r--r-- | common/bootm_os.c | 14 | ||||
-rw-r--r-- | common/bootstage.c | 257 | ||||
-rw-r--r-- | common/dlmalloc.c | 2 | ||||
-rw-r--r-- | common/edid.c | 6 | ||||
-rw-r--r-- | common/env_mmc.c | 7 | ||||
-rw-r--r-- | common/fb_mmc.c | 168 | ||||
-rw-r--r-- | common/lcd.c | 4 | ||||
-rw-r--r-- | common/lynxkdi.c | 2 | ||||
-rw-r--r-- | common/spl/Kconfig | 105 | ||||
-rw-r--r-- | common/spl/Makefile | 1 | ||||
-rw-r--r-- | common/spl/spl.c | 24 | ||||
-rw-r--r-- | common/spl/spl_xip.c | 28 |
16 files changed, 517 insertions, 237 deletions
diff --git a/common/Kconfig b/common/Kconfig index 5c39663f56..27dde11b14 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -18,6 +18,15 @@ config BOOTSTAGE Calls to show_boot_progress() will also result in log entries but these will not have names. +config SPL_BOOTSTAGE + bool "Boot timing and reported in SPL" + depends on BOOTSTAGE + help + Enable recording of boot time in SPL. To make this visible to U-Boot + proper, enable BOOTSTAGE_STASH as well. This will stash the timing + information when SPL finishes and load it when U-Boot proper starts + up. + config BOOTSTAGE_REPORT bool "Display a detailed boot timing report before booting the OS" depends on BOOTSTAGE @@ -38,7 +47,7 @@ config BOOTSTAGE_REPORT 30,361,327 445,160 start_kernel config BOOTSTAGE_USER_COUNT - hex "Number of boot ID numbers available for user use" + int "Number of boot ID numbers available for user use" default 20 help This is the number of available user bootstage records. @@ -46,6 +55,13 @@ config BOOTSTAGE_USER_COUNT a new ID will be allocated from this stash. If you exceed the limit, recording will stop. +config BOOTSTAGE_RECORD_COUNT + int "Number of boot stage records to store" + default 30 + help + This is the size of the bootstage record list and is the maximum + number of bootstage records that can be recorded. + config BOOTSTAGE_FDT bool "Store boot timing information in the OS device tree" depends on BOOTSTAGE @@ -448,7 +464,7 @@ config BOARD_LATE_INIT config DISPLAY_CPUINFO bool "Display information about the CPU during start up" - default y if ARM || NIOS2 || X86 || XTENSA || MPC5xxx + default y if ARM || NIOS2 || X86 || XTENSA help Display information about the CPU that U-Boot is running on when U-Boot starts up. The function print_cpuinfo() is called diff --git a/common/Makefile b/common/Makefile index c7c8ea42c6..539cf98e19 100644 --- a/common/Makefile +++ b/common/Makefile @@ -65,7 +65,6 @@ obj-$(CONFIG_USB_STORAGE) += usb_storage.o endif # others -obj-$(CONFIG_BOOTSTAGE) += bootstage.o obj-$(CONFIG_CONSOLE_MUX) += iomux.o obj-$(CONFIG_MTD_NOR_FLASH) += flash.o obj-$(CONFIG_CMD_KGDB) += kgdb.o kgdb_stubs.o @@ -89,6 +88,8 @@ obj-$(CONFIG_CMDLINE) += cli_readline.o cli_simple.o endif # !CONFIG_SPL_BUILD +obj-$(CONFIG_$(SPL_)BOOTSTAGE) += bootstage.o + ifdef CONFIG_SPL_BUILD obj-$(CONFIG_SPL_DFU_SUPPORT) += dfu.o obj-$(CONFIG_SPL_DFU_SUPPORT) += cli_hush.o diff --git a/common/board_f.c b/common/board_f.c index a212f2b539..850d19db75 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -31,6 +31,9 @@ #include <trace.h> #include <video.h> #include <watchdog.h> +#ifdef CONFIG_MACH_TYPE +#include <asm/mach-types.h> +#endif #if defined(CONFIG_MP) && defined(CONFIG_PPC) #include <asm/mp.h> #endif @@ -384,7 +387,7 @@ static int reserve_video(void) gd->fb_base = gd->relocaddr; # endif /* CONFIG_FB_ADDR */ #elif defined(CONFIG_VIDEO) && \ - (!defined(CONFIG_PPC) || defined(CONFIG_8xx)) && \ + (!defined(CONFIG_PPC)) && \ !defined(CONFIG_ARM) && !defined(CONFIG_X86) && \ !defined(CONFIG_M68K) /* reserve memory for video display (always full pages) */ @@ -488,6 +491,20 @@ static int reserve_fdt(void) return 0; } +static int reserve_bootstage(void) +{ +#ifdef CONFIG_BOOTSTAGE + int size = bootstage_get_size(); + + gd->start_addr_sp -= size; + gd->new_bootstage = map_sysmem(gd->start_addr_sp, size); + debug("Reserving %#x Bytes for bootstage at: %08lx\n", size, + gd->start_addr_sp); +#endif + + return 0; +} + int arch_reserve_stacks(void) { return 0; @@ -530,11 +547,10 @@ static int setup_board_part1(void) bd->bi_sramsize = CONFIG_SYS_SRAM_SIZE; /* size of SRAM */ #endif -#if defined(CONFIG_8xx) || defined(CONFIG_MPC8260) || defined(CONFIG_5xx) || \ - defined(CONFIG_E500) || defined(CONFIG_MPC86xx) +#if defined(CONFIG_E500) || defined(CONFIG_MPC86xx) bd->bi_immr_base = CONFIG_SYS_IMMR; /* base of IMMR register */ #endif -#if defined(CONFIG_MPC5xxx) || defined(CONFIG_M68K) +#if defined(CONFIG_M68K) bd->bi_mbar_base = CONFIG_SYS_MBAR; /* base of internal registers */ #endif #if defined(CONFIG_MPC83xx) @@ -558,13 +574,6 @@ static int setup_board_part2(void) bd->bi_sccfreq = gd->arch.scc_clk; bd->bi_vco = gd->arch.vco_out; #endif /* CONFIG_CPM2 */ -#if defined(CONFIG_MPC512X) - bd->bi_ipsfreq = gd->arch.ips_clk; -#endif /* CONFIG_MPC512X */ -#if defined(CONFIG_MPC5xxx) - bd->bi_ipbfreq = gd->arch.ipb_clk; - bd->bi_pcifreq = gd->pci_clk; -#endif /* CONFIG_MPC5xxx */ #if defined(CONFIG_M68K) && defined(CONFIG_PCI) bd->bi_pcifreq = gd->pci_clk; #endif @@ -602,6 +611,24 @@ static int reloc_fdt(void) return 0; } +static int reloc_bootstage(void) +{ +#ifdef CONFIG_BOOTSTAGE + if (gd->flags & GD_FLG_SKIP_RELOC) + return 0; + if (gd->new_bootstage) { + int size = bootstage_get_size(); + + debug("Copying bootstage from %p to %p, size %x\n", + gd->bootstage, gd->new_bootstage, size); + memcpy(gd->new_bootstage, gd->bootstage, size); + gd->bootstage = gd->new_bootstage; + } +#endif + + return 0; +} + static int setup_reloc(void) { if (gd->flags & GD_FLG_SKIP_RELOC) { @@ -610,13 +637,16 @@ static int setup_reloc(void) } #ifdef CONFIG_SYS_TEXT_BASE - gd->reloc_off = gd->relocaddr - CONFIG_SYS_TEXT_BASE; -#ifdef CONFIG_M68K +#ifdef ARM + gd->reloc_off = gd->relocaddr - (unsigned long)__image_copy_start; +#elif defined(CONFIG_M68K) /* * On all ColdFire arch cpu, monitor code starts always * just after the default vector table location, so at 0x400 */ gd->reloc_off = gd->relocaddr - (CONFIG_SYS_TEXT_BASE + 0x400); +#else + gd->reloc_off = gd->relocaddr - CONFIG_SYS_TEXT_BASE; #endif #endif memcpy(gd->new_gd, (char *)gd, sizeof(gd_t)); @@ -670,8 +700,26 @@ static int jump_to_copy(void) #endif /* Record the board_init_f() bootstage (after arch_cpu_init()) */ -static int mark_bootstage(void) +static int initf_bootstage(void) { + bool from_spl = IS_ENABLED(CONFIG_SPL_BOOTSTAGE) && + IS_ENABLED(CONFIG_BOOTSTAGE_STASH); + int ret; + + ret = bootstage_init(!from_spl); + if (ret) + return ret; + if (from_spl) { + const void *stash = map_sysmem(CONFIG_BOOTSTAGE_STASH_ADDR, + CONFIG_BOOTSTAGE_STASH_SIZE); + + ret = bootstage_unstash(stash, CONFIG_BOOTSTAGE_STASH_SIZE); + if (ret && ret != -ENOENT) { + debug("Failed to unstash bootstage: err=%d\n", ret); + return ret; + } + } + bootstage_mark_name(BOOTSTAGE_ID_START_UBOOT_F, "board_init_f"); return 0; @@ -691,7 +739,9 @@ static int initf_dm(void) #if defined(CONFIG_DM) && defined(CONFIG_SYS_MALLOC_F_LEN) int ret; + bootstage_start(BOOTSTATE_ID_ACCUM_DM_F, "dm_f"); ret = dm_init_and_scan(true); + bootstage_accum(BOOTSTATE_ID_ACCUM_DM_F); if (ret) return ret; #endif @@ -724,6 +774,7 @@ static const init_fnc_t init_sequence_f[] = { trace_early_init, #endif initf_malloc, + initf_bootstage, /* uses its own timer, so does not need DM */ initf_console_record, #if defined(CONFIG_HAVE_FSP) arch_fsp_init, @@ -732,7 +783,6 @@ static const init_fnc_t init_sequence_f[] = { mach_cpu_init, /* SoC/machine dependent CPU setup */ initf_dm, arch_cpu_init_dm, - mark_bootstage, /* need timer, go after init dm */ #if defined(CONFIG_BOARD_EARLY_INIT_F) board_early_init_f, #endif @@ -819,6 +869,7 @@ static const init_fnc_t init_sequence_f[] = { setup_machine, reserve_global_data, reserve_fdt, + reserve_bootstage, reserve_arch, reserve_stacks, dram_init_banksize, @@ -840,6 +891,7 @@ static const init_fnc_t init_sequence_f[] = { #endif INIT_FUNC_WATCHDOG_RESET reloc_fdt, + reloc_bootstage, setup_reloc, #if defined(CONFIG_X86) || defined(CONFIG_ARC) copy_uboot_to_ram, diff --git a/common/board_r.c b/common/board_r.c index 00ba319ca7..adc1f1937e 100644 --- a/common/board_r.c +++ b/common/board_r.c @@ -11,6 +11,7 @@ */ #include <common.h> +#include <api.h> /* TODO: can we just include all these headers whether needed or not? */ #if defined(CONFIG_CMD_BEDBUG) #include <bedbug/type.h> @@ -226,13 +227,6 @@ static int initr_post_backlog(void) } #endif -#ifdef CONFIG_SYS_DELAYED_ICACHE -static int initr_icache_enable(void) -{ - return 0; -} -#endif - #if defined(CONFIG_SYS_INIT_RAM_LOCK) && defined(CONFIG_E500) static int initr_unlock_ram_in_cache(void) { @@ -296,8 +290,15 @@ static int initr_noncached(void) #ifdef CONFIG_OF_LIVE static int initr_of_live(void) { - return of_live_build(gd->fdt_blob, - (struct device_node **)&gd->of_root); + int ret; + + bootstage_start(BOOTSTAGE_ID_ACCUM_OF_LIVE, "of_live"); + ret = of_live_build(gd->fdt_blob, (struct device_node **)&gd->of_root); + bootstage_accum(BOOTSTAGE_ID_ACCUM_OF_LIVE); + if (ret) + return ret; + + return 0; } #endif @@ -312,7 +313,9 @@ static int initr_dm(void) #ifdef CONFIG_TIMER gd->timer = NULL; #endif + bootstage_start(BOOTSTATE_ID_ACCUM_DM_R, "dm_r"); ret = dm_init_and_scan(false); + bootstage_accum(BOOTSTATE_ID_ACCUM_DM_R); if (ret) return ret; #ifdef CONFIG_TIMER_EARLY @@ -327,7 +330,6 @@ static int initr_dm(void) static int initr_bootstage(void) { - /* We cannot do this before initr_dm() */ bootstage_mark_name(BOOTSTAGE_ID_START_UBOOT_R, "board_init_r"); return 0; @@ -630,11 +632,7 @@ static int initr_pcmcia(void) #if defined(CONFIG_IDE) static int initr_ide(void) { -#ifdef CONFIG_IDE_8xx_PCCARD - puts("PCMCIA:"); -#else puts("IDE: "); -#endif #if defined(CONFIG_START_IDE) if (board_start_ide()) ide_init(); @@ -726,6 +724,7 @@ static init_fnc_t init_sequence_r[] = { #endif initr_barrier, initr_malloc, + initr_bootstage, /* Needs malloc() but has its own timer */ initr_console_record, #ifdef CONFIG_SYS_NONCACHED_MEMORY initr_noncached, @@ -737,7 +736,6 @@ static init_fnc_t init_sequence_r[] = { #ifdef CONFIG_DM initr_dm, #endif - initr_bootstage, #if defined(CONFIG_ARM) || defined(CONFIG_NDS32) board_init, /* Setup chipselects */ #endif @@ -777,9 +775,6 @@ static init_fnc_t init_sequence_r[] = { initr_post_backlog, #endif INIT_FUNC_WATCHDOG_RESET -#ifdef CONFIG_SYS_DELAYED_ICACHE - initr_icache_enable, -#endif #if defined(CONFIG_PCI) && defined(CONFIG_SYS_EARLY_PCI_INIT) /* * Do early PCI configuration _before_ the flash gets initialised, diff --git a/common/bootm_os.c b/common/bootm_os.c index e102406976..d9e6e937f7 100644 --- a/common/bootm_os.c +++ b/common/bootm_os.c @@ -56,7 +56,6 @@ static int do_bootm_netbsd(int flag, int argc, char * const argv[], void (*loader)(bd_t *, image_header_t *, char *, char *); image_header_t *os_hdr, *hdr; ulong kernel_data, kernel_len; - char *consdev; char *cmdline; if (flag != BOOTM_STATE_OS_GO) @@ -88,17 +87,6 @@ static int do_bootm_netbsd(int flag, int argc, char * const argv[], os_hdr = hdr; } - consdev = ""; -#if defined(CONFIG_8xx_CONS_SMC1) - consdev = "smc1"; -#elif defined(CONFIG_8xx_CONS_SMC2) - consdev = "smc2"; -#elif defined(CONFIG_8xx_CONS_SCC2) - consdev = "scc2"; -#elif defined(CONFIG_8xx_CONS_SCC3) - consdev = "scc3"; -#endif - if (argc > 0) { ulong len; int i; @@ -127,7 +115,7 @@ static int do_bootm_netbsd(int flag, int argc, char * const argv[], * arg[2]: char pointer to the console device to use * arg[3]: char pointer to the boot arguments */ - (*loader)(gd->bd, os_hdr, consdev, cmdline); + (*loader)(gd->bd, os_hdr, "", cmdline); return 1; } diff --git a/common/bootstage.c b/common/bootstage.c index 35bce3d881..61479d7f07 100644 --- a/common/bootstage.c +++ b/common/bootstage.c @@ -8,8 +8,6 @@ /* * This module records the progress of boot and arbitrary commands, and * permits accurate timestamping of each. - * - * TBD: Pass timings to kernel in the FDT */ #include <common.h> @@ -19,6 +17,10 @@ DECLARE_GLOBAL_DATA_PTR; +enum { + RECORD_COUNT = CONFIG_BOOTSTAGE_RECORD_COUNT, +}; + struct bootstage_record { ulong time_us; uint32_t start_us; @@ -27,8 +29,11 @@ struct bootstage_record { enum bootstage_id id; }; -static struct bootstage_record record[BOOTSTAGE_ID_COUNT] = { {1} }; -static int next_id = BOOTSTAGE_ID_USER; +struct bootstage_data { + uint rec_count; + uint next_id; + struct bootstage_record record[RECORD_COUNT]; +}; enum { BOOTSTAGE_VERSION = 0, @@ -45,41 +50,72 @@ struct bootstage_hdr { int bootstage_relocate(void) { + struct bootstage_data *data = gd->bootstage; int i; /* * Duplicate all strings. They may point to an old location in the * program .text section that can eventually get trashed. */ - for (i = 0; i < BOOTSTAGE_ID_COUNT; i++) - if (record[i].name) - record[i].name = strdup(record[i].name); + debug("Relocating %d records\n", data->rec_count); + for (i = 0; i < data->rec_count; i++) + data->record[i].name = strdup(data->record[i].name); return 0; } +struct bootstage_record *find_id(struct bootstage_data *data, + enum bootstage_id id) +{ + struct bootstage_record *rec; + struct bootstage_record *end; + + for (rec = data->record, end = rec + data->rec_count; rec < end; + rec++) { + if (rec->id == id) + return rec; + } + + return NULL; +} + +struct bootstage_record *ensure_id(struct bootstage_data *data, + enum bootstage_id id) +{ + struct bootstage_record *rec; + + rec = find_id(data, id); + if (!rec && data->rec_count < RECORD_COUNT) { + rec = &data->record[data->rec_count++]; + rec->id = id; + return rec; + } + + return rec; +} + ulong bootstage_add_record(enum bootstage_id id, const char *name, int flags, ulong mark) { + struct bootstage_data *data = gd->bootstage; struct bootstage_record *rec; if (flags & BOOTSTAGEF_ALLOC) - id = next_id++; - - if (id < BOOTSTAGE_ID_COUNT) { - rec = &record[id]; - - /* Only record the first event for each */ - if (!rec->time_us) { - rec->time_us = mark; - rec->name = name; - rec->flags = flags; - rec->id = id; - } + id = data->next_id++; + + /* Only record the first event for each */ + rec = find_id(data, id); + if (!rec && data->rec_count < RECORD_COUNT) { + rec = &data->record[data->rec_count++]; + rec->time_us = mark; + rec->name = name; + rec->flags = flags; + rec->id = id; } /* Tell the board about this progress */ show_boot_progress(flags & BOOTSTAGEF_ERROR ? -id : id); + return mark; } @@ -101,6 +137,7 @@ ulong bootstage_mark_name(enum bootstage_id id, const char *name) if (id == BOOTSTAGE_ID_ALLOC) flags = BOOTSTAGEF_ALLOC; + return bootstage_add_record(id, name, flags, timer_get_boot_us()); } @@ -133,20 +170,29 @@ ulong bootstage_mark_code(const char *file, const char *func, int linenum) uint32_t bootstage_start(enum bootstage_id id, const char *name) { - struct bootstage_record *rec = &record[id]; + struct bootstage_data *data = gd->bootstage; + struct bootstage_record *rec = ensure_id(data, id); + ulong start_us = timer_get_boot_us(); + + if (rec) { + rec->start_us = start_us; + rec->name = name; + } - rec->start_us = timer_get_boot_us(); - rec->name = name; - return rec->start_us; + return start_us; } uint32_t bootstage_accum(enum bootstage_id id) { - struct bootstage_record *rec = &record[id]; + struct bootstage_data *data = gd->bootstage; + struct bootstage_record *rec = ensure_id(data, id); uint32_t duration; + if (!rec) + return 0; duration = (uint32_t)timer_get_boot_us() - rec->start_us; rec->time_us += duration; + return duration; } @@ -159,7 +205,7 @@ uint32_t bootstage_accum(enum bootstage_id id) * @return pointer to name, either from the record or pointing to buf. */ static const char *get_record_name(char *buf, int len, - struct bootstage_record *rec) + const struct bootstage_record *rec) { if (rec->name) return rec->name; @@ -171,8 +217,7 @@ static const char *get_record_name(char *buf, int len, return buf; } -static uint32_t print_time_record(enum bootstage_id id, - struct bootstage_record *rec, uint32_t prev) +static uint32_t print_time_record(struct bootstage_record *rec, uint32_t prev) { char buf[20]; @@ -204,9 +249,10 @@ static int h_compare_record(const void *r1, const void *r2) */ static int add_bootstages_devicetree(struct fdt_header *blob) { + struct bootstage_data *data = gd->bootstage; int bootstage; char buf[20]; - int id; + int recnum; int i; if (!blob) @@ -218,17 +264,17 @@ static int add_bootstages_devicetree(struct fdt_header *blob) */ bootstage = fdt_add_subnode(blob, 0, "bootstage"); if (bootstage < 0) - return -1; + return -EINVAL; /* * Insert the timings to the device tree in the reverse order so * that they can be printed in the Linux kernel in the right order. */ - for (id = BOOTSTAGE_ID_COUNT - 1, i = 0; id >= 0; id--, i++) { - struct bootstage_record *rec = &record[id]; + for (recnum = data->rec_count - 1, i = 0; recnum >= 0; recnum--, i++) { + struct bootstage_record *rec = &data->record[recnum]; int node; - if (id != BOOTSTAGE_ID_AWAKE && rec->time_us == 0) + if (rec->id != BOOTSTAGE_ID_AWAKE && rec->time_us == 0) continue; node = fdt_add_subnode(blob, bootstage, simple_itoa(i)); @@ -237,14 +283,14 @@ static int add_bootstages_devicetree(struct fdt_header *blob) /* add properties to the node. */ if (fdt_setprop_string(blob, node, "name", - get_record_name(buf, sizeof(buf), rec))) - return -1; + get_record_name(buf, sizeof(buf), rec))) + return -EINVAL; /* Check if this is a 'mark' or 'accum' record */ if (fdt_setprop_cell(blob, node, rec->start_us ? "accum" : "mark", rec->time_us)) - return -1; + return -EINVAL; } return 0; @@ -261,54 +307,36 @@ int bootstage_fdt_add_report(void) void bootstage_report(void) { - struct bootstage_record *rec = record; - int id; + struct bootstage_data *data = gd->bootstage; + struct bootstage_record *rec = data->record; uint32_t prev; + int i; - puts("Timer summary in microseconds:\n"); + printf("Timer summary in microseconds (%d records):\n", + data->rec_count); printf("%11s%11s %s\n", "Mark", "Elapsed", "Stage"); - /* Fake the first record - we could get it from early boot */ - rec->name = "reset"; - rec->time_us = 0; - prev = print_time_record(BOOTSTAGE_ID_AWAKE, rec, 0); + prev = print_time_record(rec, 0); /* Sort records by increasing time */ - qsort(record, ARRAY_SIZE(record), sizeof(*rec), h_compare_record); + qsort(data->record, data->rec_count, sizeof(*rec), h_compare_record); - for (id = 0; id < BOOTSTAGE_ID_COUNT; id++, rec++) { - if (rec->time_us != 0 && !rec->start_us) - prev = print_time_record(rec->id, rec, prev); + for (i = 1, rec++; i < data->rec_count; i++, rec++) { + if (rec->id && !rec->start_us) + prev = print_time_record(rec, prev); } - if (next_id > BOOTSTAGE_ID_COUNT) - printf("(Overflowed internal boot id table by %d entries\n" - "- please increase CONFIG_BOOTSTAGE_USER_COUNT\n", - next_id - BOOTSTAGE_ID_COUNT); + if (data->rec_count > RECORD_COUNT) + printf("Overflowed internal boot id table by %d entries\n" + "- please increase CONFIG_BOOTSTAGE_RECORD_COUNT\n", + data->rec_count - RECORD_COUNT); puts("\nAccumulated time:\n"); - for (id = 0, rec = record; id < BOOTSTAGE_ID_COUNT; id++, rec++) { + for (i = 0, rec = data->record; i < data->rec_count; i++, rec++) { if (rec->start_us) - prev = print_time_record(id, rec, -1); + prev = print_time_record(rec, -1); } } -ulong __timer_get_boot_us(void) -{ - static ulong base_time; - - /* - * We can't implement this properly. Return 0 on the first call and - * larger values after that. - */ - if (base_time) - return get_timer(base_time) * 1000; - base_time = get_timer(0); - return 0; -} - -ulong timer_get_boot_us(void) - __attribute__((weak, alias("__timer_get_boot_us"))); - /** * Append data to a memory buffer * @@ -333,25 +361,26 @@ static void append_data(char **ptrp, char *end, const void *data, int size) int bootstage_stash(void *base, int size) { + const struct bootstage_data *data = gd->bootstage; struct bootstage_hdr *hdr = (struct bootstage_hdr *)base; - struct bootstage_record *rec; + const struct bootstage_record *rec; char buf[20]; char *ptr = base, *end = ptr + size; uint32_t count; - int id; + int i; if (hdr + 1 > (struct bootstage_hdr *)end) { debug("%s: Not enough space for bootstage hdr\n", __func__); - return -1; + return -ENOSPC; } /* Write an arbitrary version number */ hdr->version = BOOTSTAGE_VERSION; /* Count the number of records, and write that value first */ - for (rec = record, id = count = 0; id < BOOTSTAGE_ID_COUNT; - id++, rec++) { - if (rec->time_us != 0) + for (rec = data->record, i = count = 0; i < data->rec_count; + i++, rec++) { + if (rec->id != 0) count++; } hdr->count = count; @@ -360,89 +389,88 @@ int bootstage_stash(void *base, int size) ptr += sizeof(*hdr); /* Write the records, silently stopping when we run out of space */ - for (rec = record, id = 0; id < BOOTSTAGE_ID_COUNT; id++, rec++) { - if (rec->time_us != 0) - append_data(&ptr, end, rec, sizeof(*rec)); + for (rec = data->record, i = 0; i < data->rec_count; i++, rec++) { + append_data(&ptr, end, rec, sizeof(*rec)); } /* Write the name strings */ - for (rec = record, id = 0; id < BOOTSTAGE_ID_COUNT; id++, rec++) { - if (rec->time_us != 0) { - const char *name; + for (rec = data->record, i = 0; i < data->rec_count; i++, rec++) { + const char *name; - name = get_record_name(buf, sizeof(buf), rec); - append_data(&ptr, end, name, strlen(name) + 1); - } + name = get_record_name(buf, sizeof(buf), rec); + append_data(&ptr, end, name, strlen(name) + 1); } /* Check for buffer overflow */ if (ptr > end) { debug("%s: Not enough space for bootstage stash\n", __func__); - return -1; + return -ENOSPC; } /* Update total data size */ hdr->size = ptr - (char *)base; - printf("Stashed %d records\n", hdr->count); + debug("Stashed %d records\n", hdr->count); return 0; } -int bootstage_unstash(void *base, int size) +int bootstage_unstash(const void *base, int size) { - struct bootstage_hdr *hdr = (struct bootstage_hdr *)base; + const struct bootstage_hdr *hdr = (struct bootstage_hdr *)base; + struct bootstage_data *data = gd->bootstage; + const char *ptr = base, *end = ptr + size; struct bootstage_record *rec; - char *ptr = base, *end = ptr + size; uint rec_size; - int id; + int i; if (size == -1) end = (char *)(~(uintptr_t)0); if (hdr + 1 > (struct bootstage_hdr *)end) { debug("%s: Not enough space for bootstage hdr\n", __func__); - return -1; + return -EPERM; } if (hdr->magic != BOOTSTAGE_MAGIC) { debug("%s: Invalid bootstage magic\n", __func__); - return -1; + return -ENOENT; } if (ptr + hdr->size > end) { debug("%s: Bootstage data runs past buffer end\n", __func__); - return -1; + return -ENOSPC; } if (hdr->count * sizeof(*rec) > hdr->size) { debug("%s: Bootstage has %d records needing %lu bytes, but " "only %d bytes is available\n", __func__, hdr->count, (ulong)hdr->count * sizeof(*rec), hdr->size); - return -1; + return -ENOSPC; } if (hdr->version != BOOTSTAGE_VERSION) { debug("%s: Bootstage data version %#0x unrecognised\n", __func__, hdr->version); - return -1; + return -EINVAL; } - if (next_id + hdr->count > BOOTSTAGE_ID_COUNT) { + if (data->rec_count + hdr->count > RECORD_COUNT) { debug("%s: Bootstage has %d records, we have space for %d\n" "- please increase CONFIG_BOOTSTAGE_USER_COUNT\n", - __func__, hdr->count, BOOTSTAGE_ID_COUNT - next_id); - return -1; + __func__, hdr->count, RECORD_COUNT - data->rec_count); + return -ENOSPC; } ptr += sizeof(*hdr); /* Read the records */ - rec_size = hdr->count * sizeof(*record); - memcpy(record + next_id, ptr, rec_size); + rec_size = hdr->count * sizeof(*data->record); + memcpy(data->record + data->rec_count, ptr, rec_size); /* Read the name strings */ ptr += rec_size; - for (rec = record + next_id, id = 0; id < hdr->count; id++, rec++) { + for (rec = data->record + data->next_id, i = 0; i < hdr->count; + i++, rec++) { rec->name = ptr; /* Assume no data corruption here */ @@ -450,8 +478,31 @@ int bootstage_unstash(void *base, int size) } /* Mark the records as read */ - next_id += hdr->count; - printf("Unstashed %d records\n", hdr->count); + data->rec_count += hdr->count; + debug("Unstashed %d records\n", hdr->count); + + return 0; +} + +int bootstage_get_size(void) +{ + return sizeof(struct bootstage_data); +} + +int bootstage_init(bool first) +{ + struct bootstage_data *data; + int size = sizeof(struct bootstage_data); + + gd->bootstage = (struct bootstage_data *)malloc(size); + if (!gd->bootstage) + return -ENOMEM; + data = gd->bootstage; + memset(data, '\0', size); + if (first) { + data->next_id = BOOTSTAGE_ID_USER; + bootstage_add_record(BOOTSTAGE_ID_AWAKE, "reset", 0, 0); + } return 0; } diff --git a/common/dlmalloc.c b/common/dlmalloc.c index adc680e959..fc1e8b391c 100644 --- a/common/dlmalloc.c +++ b/common/dlmalloc.c @@ -1,6 +1,6 @@ #include <common.h> -#ifdef CONFIG_SANDBOX +#if defined(CONFIG_UNIT_TEST) #define DEBUG #endif diff --git a/common/edid.c b/common/edid.c index 19410aa4fc..3d0809ad11 100644 --- a/common/edid.c +++ b/common/edid.c @@ -148,8 +148,8 @@ static bool cea_is_hdmi_vsdb_present(struct edid_cea861_info *info) /* check for end of data block */ end = info->dtd_offset; if (end == 0) - end = 127; - if (end < 4 || end > 127) + end = sizeof(info->data); + if (end < 4 || end > sizeof(info->data)) return false; end -= 4; @@ -295,7 +295,7 @@ static void edid_print_dtd(struct edid_monitor_descriptor *monitor, h_total = h_active + h_blanking; v_total = v_active + v_blanking; - if (v_total * h_total) + if (v_total > 0 && h_total > 0) vfreq = pixclock / (v_total * h_total); else vfreq = 1; /* Error case */ diff --git a/common/env_mmc.c b/common/env_mmc.c index 404de85062..88b043ec35 100644 --- a/common/env_mmc.c +++ b/common/env_mmc.c @@ -121,7 +121,12 @@ static const char *init_mmc_for_env(struct mmc *mmc) if (!mmc) return "!No MMC card found"; -#ifndef CONFIG_BLK +#ifdef CONFIG_BLK + struct udevice *dev; + + if (blk_get_from_parent(mmc->dev, &dev)) + return "!No block device"; +#else if (mmc_init(mmc)) return "!MMC init failed"; #endif diff --git a/common/fb_mmc.c b/common/fb_mmc.c index 866982e41c..2113b6c372 100644 --- a/common/fb_mmc.c +++ b/common/fb_mmc.c @@ -13,6 +13,8 @@ #include <part.h> #include <mmc.h> #include <div64.h> +#include <linux/compat.h> +#include <android_image.h> /* * FIXME: Ensure we always set these names via Kconfig once xxx_PARTITION is @@ -27,6 +29,8 @@ #define CONFIG_FASTBOOT_MBR_NAME "mbr" #endif +#define BOOT_PARTITION_NAME "boot" + struct fb_mmc_sparse { struct blk_desc *dev_desc; }; @@ -99,6 +103,163 @@ static void write_raw_image(struct blk_desc *dev_desc, disk_partition_t *info, fastboot_okay(""); } +#ifdef CONFIG_ANDROID_BOOT_IMAGE +/** + * Read Android boot image header from boot partition. + * + * @param[in] dev_desc MMC device descriptor + * @param[in] info Boot partition info + * @param[out] hdr Where to store read boot image header + * + * @return Boot image header sectors count or 0 on error + */ +static lbaint_t fb_mmc_get_boot_header(struct blk_desc *dev_desc, + disk_partition_t *info, + struct andr_img_hdr *hdr) +{ + ulong sector_size; /* boot partition sector size */ + lbaint_t hdr_sectors; /* boot image header sectors count */ + int res; + + /* Calculate boot image sectors count */ + sector_size = info->blksz; + hdr_sectors = DIV_ROUND_UP(sizeof(struct andr_img_hdr), sector_size); + if (hdr_sectors == 0) { + error("invalid number of boot sectors: 0"); + fastboot_fail("invalid number of boot sectors: 0"); + return 0; + } + + /* Read the boot image header */ + res = blk_dread(dev_desc, info->start, hdr_sectors, (void *)hdr); + if (res == 0) { + error("cannot read header from boot partition"); + fastboot_fail("cannot read header from boot partition"); + return 0; + } + + /* Check boot header magic string */ + res = android_image_check_header(hdr); + if (res != 0) { + error("bad boot image magic"); + fastboot_fail("boot partition not initialized"); + return 0; + } + + return hdr_sectors; +} + +/** + * Write downloaded zImage to boot partition and repack it properly. + * + * @param dev_desc MMC device descriptor + * @param download_buffer Address to fastboot buffer with zImage in it + * @param download_bytes Size of fastboot buffer, in bytes + * + * @return 0 on success or -1 on error + */ +static int fb_mmc_update_zimage(struct blk_desc *dev_desc, + void *download_buffer, + unsigned int download_bytes) +{ + u32 hdr_addr; /* boot image header address */ + struct andr_img_hdr *hdr; /* boot image header */ + lbaint_t hdr_sectors; /* boot image header sectors */ + u8 *ramdisk_buffer; + u32 ramdisk_sector_start; + u32 ramdisk_sectors; + u32 kernel_sector_start; + u32 kernel_sectors; + u32 sectors_per_page; + disk_partition_t info; + int res; + + puts("Flashing zImage\n"); + + /* Get boot partition info */ + res = part_get_info_by_name(dev_desc, BOOT_PARTITION_NAME, &info); + if (res < 0) { + error("cannot find boot partition"); + fastboot_fail("cannot find boot partition"); + return -1; + } + + /* Put boot image header in fastboot buffer after downloaded zImage */ + hdr_addr = (u32)download_buffer + ALIGN(download_bytes, PAGE_SIZE); + hdr = (struct andr_img_hdr *)hdr_addr; + + /* Read boot image header */ + hdr_sectors = fb_mmc_get_boot_header(dev_desc, &info, hdr); + if (hdr_sectors == 0) { + error("unable to read boot image header"); + fastboot_fail("unable to read boot image header"); + return -1; + } + + /* Check if boot image has second stage in it (we don't support it) */ + if (hdr->second_size > 0) { + error("moving second stage is not supported yet"); + fastboot_fail("moving second stage is not supported yet"); + return -1; + } + + /* Extract ramdisk location */ + sectors_per_page = hdr->page_size / info.blksz; + ramdisk_sector_start = info.start + sectors_per_page; + ramdisk_sector_start += DIV_ROUND_UP(hdr->kernel_size, hdr->page_size) * + sectors_per_page; + ramdisk_sectors = DIV_ROUND_UP(hdr->ramdisk_size, hdr->page_size) * + sectors_per_page; + + /* Read ramdisk and put it in fastboot buffer after boot image header */ + ramdisk_buffer = (u8 *)hdr + (hdr_sectors * info.blksz); + res = blk_dread(dev_desc, ramdisk_sector_start, ramdisk_sectors, + ramdisk_buffer); + if (res == 0) { + error("cannot read ramdisk from boot partition"); + fastboot_fail("cannot read ramdisk from boot partition"); + return -1; + } + + /* Write new kernel size to boot image header */ + hdr->kernel_size = download_bytes; + res = blk_dwrite(dev_desc, info.start, hdr_sectors, (void *)hdr); + if (res == 0) { + error("cannot writeback boot image header"); + fastboot_fail("cannot write back boot image header"); + return -1; + } + + /* Write the new downloaded kernel */ + kernel_sector_start = info.start + sectors_per_page; + kernel_sectors = DIV_ROUND_UP(hdr->kernel_size, hdr->page_size) * + sectors_per_page; + res = blk_dwrite(dev_desc, kernel_sector_start, kernel_sectors, + download_buffer); + if (res == 0) { + error("cannot write new kernel"); + fastboot_fail("cannot write new kernel"); + return -1; + } + + /* Write the saved ramdisk back */ + ramdisk_sector_start = info.start + sectors_per_page; + ramdisk_sector_start += DIV_ROUND_UP(hdr->kernel_size, hdr->page_size) * + sectors_per_page; + res = blk_dwrite(dev_desc, ramdisk_sector_start, ramdisk_sectors, + ramdisk_buffer); + if (res == 0) { + error("cannot write back original ramdisk"); + fastboot_fail("cannot write back original ramdisk"); + return -1; + } + + puts("........ zImage was updated in boot partition\n"); + fastboot_okay(""); + return 0; +} +#endif + void fb_mmc_flash_write(const char *cmd, void *download_buffer, unsigned int download_bytes) { @@ -153,6 +314,13 @@ void fb_mmc_flash_write(const char *cmd, void *download_buffer, } #endif +#ifdef CONFIG_ANDROID_BOOT_IMAGE + if (strncasecmp(cmd, "zimage", 6) == 0) { + fb_mmc_update_zimage(dev_desc, download_buffer, download_bytes); + return; + } +#endif + if (part_get_info_by_name_or_alias(dev_desc, cmd, &info) < 0) { error("cannot find partition: '%s'\n", cmd); fastboot_fail("cannot find partition"); diff --git a/common/lcd.c b/common/lcd.c index 2405146cf0..7e399cee2d 100644 --- a/common/lcd.c +++ b/common/lcd.c @@ -562,11 +562,7 @@ __weak void lcd_set_cmap(struct bmp_image *bmp, unsigned colors) *cmap = (((cte.red) << 8) & 0xf800) | (((cte.green) << 3) & 0x07e0) | (((cte.blue) >> 3) & 0x001f); -#if defined(CONFIG_MPC823) - cmap--; -#else cmap++; -#endif } } diff --git a/common/lynxkdi.c b/common/lynxkdi.c index 22ad384ef6..98560159fe 100644 --- a/common/lynxkdi.c +++ b/common/lynxkdi.c @@ -22,7 +22,7 @@ DECLARE_GLOBAL_DATA_PTR; -#if defined(CONFIG_MPC8260) || defined(CONFIG_440EP) || defined(CONFIG_440GR) +#if defined(CONFIG_440EP) || defined(CONFIG_440GR) void lynxkdi_boot(image_header_t *hdr) { void (*lynxkdi)(void) = (void(*)(void))image_get_ep(hdr); diff --git a/common/spl/Kconfig b/common/spl/Kconfig index 48a0fadb5f..4de81392b0 100644 --- a/common/spl/Kconfig +++ b/common/spl/Kconfig @@ -16,8 +16,9 @@ config SPL help If you want to build SPL as well as the normal image, say Y. +if SPL + config SPL_BOARD_INIT - depends on SPL bool "Call board-specific initialization in SPL" help If this option is enabled, U-Boot will call the function @@ -26,7 +27,6 @@ config SPL_BOARD_INIT config SPL_RAW_IMAGE_SUPPORT bool "Support SPL loading and booting of RAW images" - depends on SPL default n if (ARCH_MX6 && (SPL_MMC_SUPPORT || SPL_SATA_SUPPORT)) default y if !TI_SECURE_DEVICE help @@ -44,7 +44,6 @@ config SPL_LEGACY_IMAGE_SUPPORT config SPL_SYS_MALLOC_SIMPLE bool - depends on SPL prompt "Only use malloc_simple functions in the SPL" help Say Y here to only use the *_simple malloc functions from @@ -53,7 +52,6 @@ config SPL_SYS_MALLOC_SIMPLE usage as the *_simple malloc functions do not re-use free-ed mem. config SPL_STACK_R - depends on SPL bool "Enable SDRAM location for SPL stack" help SPL starts off execution in SRAM and thus typically has only a small @@ -81,7 +79,6 @@ config SPL_STACK_R_MALLOC_SIMPLE_LEN SRAM which is limited to SYS_MALLOC_F_LEN bytes. config SPL_SEPARATE_BSS - depends on SPL bool "BSS section is in a different memory region from text" help Some platforms need a large BSS region in SPL and can provide this @@ -91,7 +88,6 @@ config SPL_SEPARATE_BSS but with this option enabled, it goes at _image_binary_end. config SPL_DISPLAY_PRINT - depends on SPL bool "Display a board-specific message in SPL" help If this option is enabled, U-Boot will call the function @@ -101,7 +97,6 @@ config SPL_DISPLAY_PRINT config SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR bool "MMC raw mode: by sector" - depends on SPL default y if ARCH_SUNXI || ARCH_DAVINCI || ARCH_UNIPHIER ||ARCH_MX6 || \ ARCH_ROCKCHIP || ARCH_MVEBU || ARCH_SOCFPGA || \ ARCH_AT91 || ARCH_ZYNQ || ARCH_KEYSTONE || OMAP34XX || \ @@ -112,7 +107,7 @@ config SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR config SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR hex "Address on the MMC to load U-Boot from" - depends on SPL && SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR + depends on SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR default 0x50 if ARCH_SUNXI default 0x75 if ARCH_DAVINCI default 0x8a if ARCH_MX6 @@ -127,13 +122,12 @@ config SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR config SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION bool "MMC Raw mode: by partition" - depends on SPL help Use a partition for loading U-Boot when using MMC/SD in raw mode. config SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION hex "Partition to use to load U-Boot from" - depends on SPL && SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION + depends on SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION default 1 help Partition on the MMC to load U-Boot from when the MMC is being @@ -141,8 +135,7 @@ config SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION config SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION_TYPE bool "MMC raw mode: by partition type" - depends on SPL && DOS_PARTITION && \ - SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION + depends on DOS_PARTITION && SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION help Use partition type for specifying U-Boot partition on MMC/SD in raw mode. U-Boot will be loaded from the first partition of this @@ -150,18 +143,11 @@ config SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION_TYPE config SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION_TYPE hex "Partition Type on the MMC to load U-Boot from" - depends on SPL && SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION_TYPE + depends on SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION_TYPE help Partition Type on the MMC to load U-Boot from, when the MMC is being used in raw mode. -config TPL - bool - depends on SPL && SUPPORT_TPL - prompt "Enable TPL" - help - If you want to build TPL as well as the normal image and SPL, say Y. - config SPL_CRC32_SUPPORT bool "Support CRC32" depends on SPL_FIT @@ -212,7 +198,6 @@ config SPL_SHA256_SUPPORT config SPL_CPU_SUPPORT bool "Support CPU drivers" - depends on SPL help Enable this to support CPU drivers in SPL. These drivers can set up CPUs and provide information about them such as the model and @@ -222,7 +207,6 @@ config SPL_CPU_SUPPORT config SPL_CRYPTO_SUPPORT bool "Support crypto drivers" - depends on SPL help Enable crypto drivers in SPL. These drivers can be used to accelerate secure boot processing in secure applications. Enable @@ -233,7 +217,6 @@ config SPL_HASH_SUPPORT bool "Support hashing drivers" select SHA1 select SHA256 - depends on SPL help Enable hashing drivers in SPL. These drivers can be used to accelerate secure boot processing in secure applications. Enable @@ -242,7 +225,6 @@ config SPL_HASH_SUPPORT config SPL_DMA_SUPPORT bool "Support DMA drivers" - depends on SPL help Enable DMA (direct-memory-access) drivers in SPL. These drivers can be used to handle memory-to-peripheral data transfer without @@ -251,7 +233,6 @@ config SPL_DMA_SUPPORT config SPL_DRIVERS_MISC_SUPPORT bool "Support misc drivers" - depends on SPL help Enable miscellaneous drivers in SPL. These drivers perform various tasks that don't fall nicely into other categories, Enable this @@ -260,7 +241,6 @@ config SPL_DRIVERS_MISC_SUPPORT config SPL_ENV_SUPPORT bool "Support an environment" - depends on SPL help Enable environment support in SPL. The U-Boot environment provides a number of settings (essentially name/value pairs) which can @@ -273,7 +253,7 @@ config SPL_ENV_SUPPORT config SPL_SAVEENV bool "Support save environment" - depends on SPL && SPL_ENV_SUPPORT + depends on SPL_ENV_SUPPORT help Enable save environment support in SPL after setenv. By default the saveenv option is not provided in SPL, but some boards need @@ -296,7 +276,6 @@ config SPL_ETH_SUPPORT config SPL_EXT_SUPPORT bool "Support EXT filesystems" - depends on SPL help Enable support for EXT2/3/4 filesystems with SPL. This permits U-Boot (or Linux in Falcon mode) to be loaded from an EXT @@ -305,7 +284,6 @@ config SPL_EXT_SUPPORT config SPL_FAT_SUPPORT bool "Support FAT filesystems" - depends on SPL select FS_FAT help Enable support for FAT and VFAT filesystems with SPL. This @@ -315,7 +293,6 @@ config SPL_FAT_SUPPORT config SPL_FPGA_SUPPORT bool "Support FPGAs" - depends on SPL help Enable support for FPGAs in SPL. Field-programmable Gate Arrays provide software-configurable hardware which is typically used to @@ -327,7 +304,6 @@ config SPL_FPGA_SUPPORT config SPL_GPIO_SUPPORT bool "Support GPIO" - depends on SPL help Enable support for GPIOs (General-purpose Input/Output) in SPL. GPIOs allow U-Boot to read the state of an input line (high or @@ -339,7 +315,6 @@ config SPL_GPIO_SUPPORT config SPL_I2C_SUPPORT bool "Support I2C" - depends on SPL help Enable support for the I2C (Inter-Integrated Circuit) bus in SPL. I2C works with a clock and data line which can be driven by a @@ -353,7 +328,6 @@ config SPL_I2C_SUPPORT config SPL_LIBCOMMON_SUPPORT bool "Support common libraries" - depends on SPL help Enable support for common U-Boot libraries within SPL. These libraries include common code to deal with U-Boot images, @@ -363,7 +337,6 @@ config SPL_LIBCOMMON_SUPPORT config SPL_LIBDISK_SUPPORT bool "Support disk paritions" - depends on SPL help Enable support for disk partitions within SPL. 'Disk' is something of a misnomer as it includes non-spinning media such as flash (as @@ -377,7 +350,6 @@ config SPL_LIBDISK_SUPPORT config SPL_LIBGENERIC_SUPPORT bool "Support generic libraries" - depends on SPL help Enable support for generic U-Boot libraries within SPL. These libraries include generic code to deal with device tree, hashing, @@ -387,7 +359,7 @@ config SPL_LIBGENERIC_SUPPORT config SPL_MMC_SUPPORT bool "Support MMC" - depends on SPL && MMC + depends on MMC help Enable support for MMC (Multimedia Card) within SPL. This enables the MMC protocol implementation and allows any enabled drivers to @@ -398,7 +370,6 @@ config SPL_MMC_SUPPORT config SPL_MPC8XXX_INIT_DDR_SUPPORT bool "Support MPC8XXX DDR init" - depends on SPL help Enable support for DDR-SDRAM (double-data-rate synchronous dynamic random-access memory) on the MPC8XXX family within SPL. This @@ -407,7 +378,6 @@ config SPL_MPC8XXX_INIT_DDR_SUPPORT config SPL_MTD_SUPPORT bool "Support MTD drivers" - depends on SPL help Enable support for MTD (Memory Technology Device) within SPL. MTD provides a block interface over raw NAND and can also be used with @@ -417,7 +387,6 @@ config SPL_MTD_SUPPORT config SPL_MUSB_NEW_SUPPORT bool "Support new Mentor Graphics USB" - depends on SPL help Enable support for Mentor Graphics USB in SPL. This is a new driver used by some boards. Enable this option to build @@ -426,7 +395,6 @@ config SPL_MUSB_NEW_SUPPORT config SPL_NAND_SUPPORT bool "Support NAND flash" - depends on SPL help Enable support for NAND (Negative AND) flash in SPL. NAND flash can be used to allow SPL to load U-Boot from supported devices. @@ -435,7 +403,6 @@ config SPL_NAND_SUPPORT config SPL_NET_SUPPORT bool "Support networking" - depends on SPL help Enable support for network devices (such as Ethernet) in SPL. This permits SPL to load U-Boot over a network link rather than @@ -456,7 +423,6 @@ endif # if SPL_NET_SUPPORT config SPL_NO_CPU_SUPPORT bool "Drop CPU code in SPL" - depends on SPL help This is specific to the ARM926EJ-S CPU. It disables the standard start.S start-up code, presumably so that a replacement can be @@ -465,16 +431,23 @@ config SPL_NO_CPU_SUPPORT config SPL_NOR_SUPPORT bool "Support NOR flash" - depends on SPL help Enable support for loading U-Boot from memory-mapped NOR (Negative OR) flash in SPL. NOR flash is slow to write but fast to read, and a memory-mapped device makes it very easy to access. Loading from NOR is typically achieved with just a memcpy(). +config SPL_XIP_SUPPORT + bool "Support XIP" + depends on SPL + help + Enable support for execute in place of U-Boot or kernel image. There + is no need to copy image from flash to ram if flash supports execute + in place. Its very useful in systems having enough flash but not + enough ram to load the image. + config SPL_ONENAND_SUPPORT bool "Support OneNAND flash" - depends on SPL help Enable support for OneNAND (Negative AND) flash in SPL. OneNAND is a type of NAND flash and therefore can be used to allow SPL to @@ -483,7 +456,7 @@ config SPL_ONENAND_SUPPORT config SPL_OS_BOOT bool "Activate Falcon Mode" - depends on SPL && !TI_SECURE_DEVICE + depends on !TI_SECURE_DEVICE default n help Enable booting directly to an OS from SPL. @@ -492,7 +465,7 @@ config SPL_OS_BOOT if SPL_OS_BOOT config SYS_OS_BASE hex "addr, where OS is found" - depends on SPL && SPL_NOR_SUPPORT + depends on SPL_NOR_SUPPORT help Specify the address, where the OS image is found, which gets booted. @@ -501,7 +474,6 @@ endif # SPL_OS_BOOT config SPL_PCI_SUPPORT bool "Support PCI drivers" - depends on SPL help Enable support for PCI in SPL. For platforms that need PCI to boot, or must perform some init using PCI in SPL, this provides the @@ -510,7 +482,6 @@ config SPL_PCI_SUPPORT config SPL_PCH_SUPPORT bool "Support PCH drivers" - depends on SPL help Enable support for PCH (Platform Controller Hub) devices in SPL. These are used to set up GPIOs and the SPI peripheral early in @@ -519,7 +490,6 @@ config SPL_PCH_SUPPORT config SPL_POST_MEM_SUPPORT bool "Support POST drivers" - depends on SPL help Enable support for POST (Power-on Self Test) in SPL. POST is a procedure that checks that the hardware (CPU or board) appears to @@ -529,7 +499,6 @@ config SPL_POST_MEM_SUPPORT config SPL_POWER_SUPPORT bool "Support power drivers" - depends on SPL help Enable support for power control in SPL. This includes support for PMICs (Power-management Integrated Circuits) and some of the @@ -542,7 +511,6 @@ config SPL_POWER_SUPPORT config SPL_RAM_SUPPORT bool "Support booting from RAM" - depends on SPL default y if MICROBLAZE || ARCH_SOCFPGA || TEGRA || ARCH_ZYNQ help Enable booting of an image in RAM. The image can be preloaded or @@ -559,7 +527,6 @@ config SPL_RAM_DEVICE config SPL_RTC_SUPPORT bool "Support RTC drivers" - depends on SPL help Enable RTC (Real-time Clock) support in SPL. This includes support for reading and setting the time. Some RTC devices also have some @@ -569,7 +536,6 @@ config SPL_RTC_SUPPORT config SPL_SATA_SUPPORT bool "Support loading from SATA" - depends on SPL help Enable support for SATA (Serial AT attachment) in SPL. This allows use of SATA devices such as hard drives and flash drivers for @@ -580,7 +546,6 @@ config SPL_SATA_SUPPORT config SPL_SERIAL_SUPPORT bool "Support serial" - depends on SPL help Enable support for serial in SPL. This allows use of a serial UART for displaying messages while SPL is running. It also brings in @@ -590,7 +555,6 @@ config SPL_SERIAL_SUPPORT config SPL_SPI_FLASH_SUPPORT bool "Support SPI flash drivers" - depends on SPL help Enable support for using SPI flash in SPL, and loading U-Boot from SPI flash. SPI flash (Serial Peripheral Bus flash) is named after @@ -601,7 +565,6 @@ config SPL_SPI_FLASH_SUPPORT config SPL_SPI_SUPPORT bool "Support SPI drivers" - depends on SPL help Enable support for using SPI in SPL. This is used for connecting to SPI flash for loading U-Boot. See SPL_SPI_FLASH_SUPPORT for @@ -612,7 +575,6 @@ config SPL_SPI_SUPPORT config SPL_TIMER_SUPPORT bool "Support timer drivers" - depends on SPL help Enable support for timer drivers in SPL. These can be used to get a timer value when in SPL, or perhaps for implementing a delay @@ -621,7 +583,6 @@ config SPL_TIMER_SUPPORT config SPL_USB_HOST_SUPPORT bool "Support USB host drivers" - depends on SPL help Enable access to USB (Universal Serial Bus) host devices so that SPL can load U-Boot from a connected USB peripheral, such as a USB @@ -642,7 +603,6 @@ config SPL_USB_SUPPORT config SPL_USB_GADGET_SUPPORT bool "Suppport USB Gadget drivers" - depends on SPL help Enable USB Gadget API which allows to enable USB device functions in SPL. @@ -690,7 +650,6 @@ endif config SPL_WATCHDOG_SUPPORT bool "Support watchdog drivers" - depends on SPL help Enable support for watchdog drivers in SPL. A watchdog is typically a hardware peripheral which can reset the system when it @@ -699,7 +658,6 @@ config SPL_WATCHDOG_SUPPORT config SPL_YMODEM_SUPPORT bool "Support loading using Ymodem" - depends on SPL help While loading from serial is slow it can be a useful backup when there is no other option. The Ymodem protocol provides a reliable @@ -708,7 +666,7 @@ config SPL_YMODEM_SUPPORT config SPL_ATF_SUPPORT bool "Support ARM Trusted Firmware" - depends on SPL && ARM64 + depends on ARM64 help ATF(ARM Trusted Firmware) is a component for ARM arch64 which which is loaded by SPL(which is considered as BL2 in ATF terminology). @@ -720,71 +678,74 @@ config SPL_ATF_TEXT_BASE help This is the base address in memory for ATF BL31 text and entry point. +config TPL + bool + depends on SUPPORT_TPL + prompt "Enable TPL" + help + If you want to build TPL as well as the normal image and SPL, say Y. + +if TPL + config TPL_ENV_SUPPORT bool "Support an environment" - depends on TPL help Enable environment support in TPL. See SPL_ENV_SUPPORT for details. config TPL_I2C_SUPPORT bool "Support I2C" - depends on TPL help Enable support for the I2C bus in SPL. See SPL_I2C_SUPPORT for details. config TPL_LIBCOMMON_SUPPORT bool "Support common libraries" - depends on TPL help Enable support for common U-Boot libraries within TPL. See SPL_LIBCOMMON_SUPPORT for details. config TPL_LIBGENERIC_SUPPORT bool "Support generic libraries" - depends on TPL help Enable support for generic U-Boot libraries within TPL. See SPL_LIBGENERIC_SUPPORT for details. config TPL_MPC8XXX_INIT_DDR_SUPPORT bool "Support MPC8XXX DDR init" - depends on TPL help Enable support for DDR-SDRAM on the MPC8XXX family within TPL. See SPL_MPC8XXX_INIT_DDR_SUPPORT for details. config TPL_MMC_SUPPORT bool "Support MMC" - depends on TPL && MMC + depends on MMC help Enable support for MMC within TPL. See SPL_MMC_SUPPORT for details. config TPL_NAND_SUPPORT bool "Support NAND flash" - depends on TPL help Enable support for NAND in SPL. See SPL_NAND_SUPPORT for details. config TPL_SERIAL_SUPPORT bool "Support serial" - depends on TPL help Enable support for serial in SPL. See SPL_SERIAL_SUPPORT for details. config TPL_SPI_FLASH_SUPPORT bool "Support SPI flash drivers" - depends on TPL help Enable support for using SPI flash in SPL. See SPL_SPI_FLASH_SUPPORT for details. config TPL_SPI_SUPPORT bool "Support SPI drivers" - depends on TPL help Enable support for using SPI in SPL. See SPL_SPI_SUPPORT for details. +endif # TPL + +endif # SPL endmenu diff --git a/common/spl/Makefile b/common/spl/Makefile index b3b34d6277..47a64dd7d0 100644 --- a/common/spl/Makefile +++ b/common/spl/Makefile @@ -12,6 +12,7 @@ ifdef CONFIG_SPL_BUILD obj-$(CONFIG_SPL_FRAMEWORK) += spl.o obj-$(CONFIG_SPL_LOAD_FIT) += spl_fit.o obj-$(CONFIG_SPL_NOR_SUPPORT) += spl_nor.o +obj-$(CONFIG_SPL_XIP_SUPPORT) += spl_xip.o obj-$(CONFIG_SPL_YMODEM_SUPPORT) += spl_ymodem.o ifndef CONFIG_SPL_UBI obj-$(CONFIG_SPL_NAND_SUPPORT) += spl_nand.o diff --git a/common/spl/spl.c b/common/spl/spl.c index 0a49766f21..7f3fd925ba 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -121,9 +121,6 @@ void spl_set_header_raw_uboot(struct spl_image_info *spl_image) { spl_image->size = CONFIG_SYS_MONITOR_LEN; spl_image->entry_point = CONFIG_SYS_UBOOT_START; -#ifdef CONFIG_CPU_V7M - spl_image->entry_point |= 0x1; -#endif spl_image->load_addr = CONFIG_SYS_TEXT_BASE; spl_image->os = IH_OS_U_BOOT; spl_image->name = "U-Boot"; @@ -232,6 +229,13 @@ static int spl_common_init(bool setup_malloc) gd->malloc_ptr = 0; } #endif + ret = bootstage_init(true); + if (ret) { + debug("%s: Failed to set up bootstage: ret=%d\n", __func__, + ret); + return ret; + } + bootstage_mark_name(BOOTSTAGE_ID_START_SPL, "spl"); if (CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)) { ret = fdtdec_setup(); if (ret) { @@ -240,8 +244,10 @@ static int spl_common_init(bool setup_malloc) } } if (IS_ENABLED(CONFIG_SPL_DM)) { + bootstage_start(BOOTSTATE_ID_ACCUM_DM_SPL, "dm_spl"); /* With CONFIG_SPL_OF_PLATDATA, bring in all devices */ ret = dm_init_and_scan(!CONFIG_IS_ENABLED(OF_PLATDATA)); + bootstage_accum(BOOTSTATE_ID_ACCUM_DM_SPL); if (ret) { debug("dm_init_and_scan() returned error %d\n", ret); return ret; @@ -396,6 +402,9 @@ void board_init_r(gd_t *dummy1, ulong dummy2) hang(); } +#ifdef CONFIG_CPU_V7M + spl_image.entry_point |= 0x1; +#endif switch (spl_image.os) { case IH_OS_U_BOOT: debug("Jumping to U-Boot\n"); @@ -421,6 +430,15 @@ void board_init_r(gd_t *dummy1, ulong dummy2) } debug("loaded - jumping to U-Boot...\n"); +#ifdef CONFIG_BOOTSTAGE_STASH + int ret; + + bootstage_mark_name(BOOTSTAGE_ID_END_SPL, "end_spl"); + ret = bootstage_stash((void *)CONFIG_BOOTSTAGE_STASH_ADDR, + CONFIG_BOOTSTAGE_STASH_SIZE); + if (ret) + debug("Failed to stash bootstage: err=%d\n", ret); +#endif spl_board_prepare_for_boot(); jump_to_image_no_args(&spl_image); } diff --git a/common/spl/spl_xip.c b/common/spl/spl_xip.c new file mode 100644 index 0000000000..18c7d11f2d --- /dev/null +++ b/common/spl/spl_xip.c @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2017 Vikas Manocha <vikas.manocha@st.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <spl.h> + +static int spl_xip(struct spl_image_info *spl_image, + struct spl_boot_device *bootdev) +{ +#ifdef CONFIG_SPL_OS_BOOT + if (!spl_start_uboot()) { + spl_image->arg = (void *)CONFIG_SYS_FDT_BASE; + spl_image->name = "Linux"; + spl_image->os = IH_OS_LINUX; + spl_image->load_addr = CONFIG_SYS_LOAD_ADDR; + spl_image->entry_point = CONFIG_SYS_LOAD_ADDR; + debug("spl: payload xipImage, load addr: 0x%lx\n", + spl_image->load_addr); + return 0; + } +#endif + return(spl_parse_image_header(spl_image, (const struct image_header *) + CONFIG_SYS_UBOOT_BASE)); +} +SPL_LOAD_IMAGE_METHOD("XIP", 0, BOOT_DEVICE_XIP, spl_xip); |