summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
Diffstat (limited to 'common')
-rw-r--r--common/Kconfig18
-rw-r--r--common/Makefile3
-rw-r--r--common/board_f.c64
-rw-r--r--common/board_r.c17
-rw-r--r--common/bootstage.c257
-rw-r--r--common/dlmalloc.c2
-rw-r--r--common/spl/Kconfig97
-rw-r--r--common/spl/spl.c18
8 files changed, 292 insertions, 184 deletions
diff --git a/common/Kconfig b/common/Kconfig
index 5c39663..c49199b 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
diff --git a/common/Makefile b/common/Makefile
index c7c8ea4..539cf98 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 a212f2b..46e5284 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
@@ -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;
@@ -602,6 +619,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) {
@@ -670,8 +705,29 @@ 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)
{
+#if defined(CONFIG_SPL_BOOTSTAGE) && defined(CONFIG_BOOTSTAGE_STASH)
+ bool from_spl = true;
+#else
+ bool from_spl = false;
+#endif
+ 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 +747,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 +782,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 +791,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 +877,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 +899,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 00ba319..15977e4 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>
@@ -296,8 +297,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 +320,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 +337,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;
@@ -726,6 +735,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 +747,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
diff --git a/common/bootstage.c b/common/bootstage.c
index 35bce3d..61479d7 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 adc680e..fc1e8b3 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/spl/Kconfig b/common/spl/Kconfig
index eabb2d0..732690c 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,7 @@ 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
permits U-Boot (or Linux in Falcon mode) to be loaded from a FAT
@@ -314,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
@@ -326,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
@@ -338,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
@@ -352,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,
@@ -362,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
@@ -376,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,
@@ -386,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
@@ -397,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
@@ -406,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
@@ -416,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
@@ -425,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.
@@ -434,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
@@ -455,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
@@ -464,7 +431,6 @@ 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
@@ -473,7 +439,6 @@ config SPL_NOR_SUPPORT
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
@@ -482,7 +447,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.
@@ -491,7 +456,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.
@@ -500,7 +465,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
@@ -509,7 +473,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
@@ -518,7 +481,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
@@ -528,7 +490,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
@@ -541,7 +502,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
@@ -558,7 +518,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
@@ -568,7 +527,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
@@ -579,7 +537,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
@@ -589,7 +546,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
@@ -600,7 +556,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
@@ -611,7 +566,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
@@ -620,7 +574,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
@@ -641,7 +594,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.
@@ -689,7 +641,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
@@ -698,7 +649,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
@@ -707,7 +657,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).
@@ -719,71 +669,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/spl.c b/common/spl/spl.c
index 0a49766..f493a3a 100644
--- a/common/spl/spl.c
+++ b/common/spl/spl.c
@@ -232,6 +232,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 +247,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;
@@ -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);
}