Merge branch '2018-11-25-master-imports'

- Bring in the series from Simon for SPL logging support and bloblist
This commit is contained in:
Tom Rini 2018-11-26 12:40:22 -05:00
commit 6b21502229
44 changed files with 1524 additions and 114 deletions

View file

@ -91,6 +91,7 @@ config SANDBOX
select SPI
select SUPPORT_OF_CONTROL
imply BITREVERSE
select BLOBLIST
imply CMD_DM
imply CMD_GETTIME
imply CMD_HASH

View file

@ -8,7 +8,4 @@
#define BOOT_DEVICE_NOR 1
/* Linker symbols */
extern char __bss_start[], __bss_end[];
#endif

View file

@ -11,6 +11,7 @@
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -23,6 +24,8 @@
#include <linux/if_ether.h>
#include <linux/if_packet.h>
#include <os.h>
struct sandbox_eth_raw_if_nameindex *sandbox_eth_raw_if_nameindex(void)
{
return (struct sandbox_eth_raw_if_nameindex *)if_nameindex();
@ -71,7 +74,7 @@ static int _raw_packet_start(struct eth_sandbox_raw_priv *priv,
/* Prepare device struct */
priv->local_bind_sd = -1;
priv->device = malloc(sizeof(struct sockaddr_ll));
priv->device = os_malloc(sizeof(struct sockaddr_ll));
if (priv->device == NULL)
return -ENOMEM;
device = priv->device;
@ -144,7 +147,7 @@ static int _local_inet_start(struct eth_sandbox_raw_priv *priv)
/* Prepare device struct */
priv->local_bind_sd = -1;
priv->local_bind_udp_port = 0;
priv->device = malloc(sizeof(struct sockaddr_in));
priv->device = os_malloc(sizeof(struct sockaddr_in));
if (priv->device == NULL)
return -ENOMEM;
device = priv->device;
@ -279,7 +282,7 @@ int sandbox_eth_raw_os_recv(void *packet, int *length,
void sandbox_eth_raw_os_stop(struct eth_sandbox_raw_priv *priv)
{
free(priv->device);
os_free(priv->device);
priv->device = NULL;
close(priv->sd);
priv->sd = -1;

View file

@ -381,7 +381,7 @@ void os_dirent_free(struct os_dirent_node *node)
while (node) {
next = node->next;
free(node);
os_free(node);
node = next;
}
}
@ -406,7 +406,7 @@ int os_dirent_ls(const char *dirname, struct os_dirent_node **headp)
/* Create a buffer upfront, with typically sufficient size */
dirlen = strlen(dirname) + 2;
len = dirlen + 256;
fname = malloc(len);
fname = os_malloc(len);
if (!fname) {
ret = -ENOMEM;
goto done;
@ -419,7 +419,7 @@ int os_dirent_ls(const char *dirname, struct os_dirent_node **headp)
ret = errno;
break;
}
next = malloc(sizeof(*node) + strlen(entry->d_name) + 1);
next = os_malloc(sizeof(*node) + strlen(entry->d_name) + 1);
if (!next) {
os_dirent_free(head);
ret = -ENOMEM;
@ -428,10 +428,10 @@ int os_dirent_ls(const char *dirname, struct os_dirent_node **headp)
if (dirlen + strlen(entry->d_name) > len) {
len = dirlen + strlen(entry->d_name);
old_fname = fname;
fname = realloc(fname, len);
fname = os_realloc(fname, len);
if (!fname) {
free(old_fname);
free(next);
os_free(old_fname);
os_free(next);
os_dirent_free(head);
ret = -ENOMEM;
goto done;
@ -465,7 +465,7 @@ int os_dirent_ls(const char *dirname, struct os_dirent_node **headp)
done:
closedir(dir);
free(fname);
os_free(fname);
return ret;
}
@ -563,20 +563,48 @@ static int make_exec(char *fname, const void *data, int size)
return 0;
}
static int add_args(char ***argvp, const char *add_args[], int count)
/**
* add_args() - Allocate a new argv with the given args
*
* This is used to create a new argv array with all the old arguments and some
* new ones that are passed in
*
* @argvp: Returns newly allocated args list
* @add_args: Arguments to add, each a string
* @count: Number of arguments in @add_args
* @return 0 if OK, -ENOMEM if out of memory
*/
static int add_args(char ***argvp, char *add_args[], int count)
{
char **argv;
char **argv, **ap;
int argc;
for (argv = *argvp, argc = 0; (*argvp)[argc]; argc++)
for (argc = 0; (*argvp)[argc]; argc++)
;
argv = malloc((argc + count + 1) * sizeof(char *));
argv = os_malloc((argc + count + 1) * sizeof(char *));
if (!argv) {
printf("Out of memory for %d argv\n", count);
return -ENOMEM;
}
memcpy(argv, *argvp, argc * sizeof(char *));
for (ap = *argvp, argc = 0; *ap; ap++) {
char *arg = *ap;
/* Drop args that we don't want to propagate */
if (*arg == '-' && strlen(arg) == 2) {
switch (arg[1]) {
case 'j':
case 'm':
ap++;
continue;
}
} else if (!strcmp(arg, "--rm_memory")) {
ap++;
continue;
}
argv[argc++] = arg;
}
memcpy(argv + argc, add_args, count * sizeof(char *));
argv[argc + count] = NULL;
@ -584,21 +612,27 @@ static int add_args(char ***argvp, const char *add_args[], int count)
return 0;
}
int os_jump_to_image(const void *dest, int size)
/**
* os_jump_to_file() - Jump to a new program
*
* This saves the memory buffer, sets up arguments to the new process, then
* execs it.
*
* @fname: Filename to exec
* @return does not return on success, any return value is an error
*/
static int os_jump_to_file(const char *fname)
{
struct sandbox_state *state = state_get_current();
char fname[30], mem_fname[30];
char mem_fname[30];
int fd, err;
const char *extra_args[5];
char *extra_args[5];
char **argv = state->argv;
int argc;
#ifdef DEBUG
int argc, i;
int i;
#endif
err = make_exec(fname, dest, size);
if (err)
return err;
strcpy(mem_fname, "/tmp/u-boot.mem.XXXXXX");
fd = mkstemp(mem_fname);
if (fd < 0)
@ -611,14 +645,16 @@ int os_jump_to_image(const void *dest, int size)
os_fd_restore();
extra_args[0] = "-j";
extra_args[1] = fname;
extra_args[1] = (char *)fname;
extra_args[2] = "-m";
extra_args[3] = mem_fname;
extra_args[4] = "--rm_memory";
err = add_args(&argv, extra_args,
sizeof(extra_args) / sizeof(extra_args[0]));
argc = 4;
if (state->ram_buf_rm)
extra_args[argc++] = "--rm_memory";
err = add_args(&argv, extra_args, argc);
if (err)
return err;
argv[0] = (char *)fname;
#ifdef DEBUG
for (i = 0; argv[i]; i++)
@ -629,11 +665,26 @@ int os_jump_to_image(const void *dest, int size)
os_exit(2);
err = execv(fname, argv);
free(argv);
os_free(argv);
if (err) {
perror("Unable to run image");
printf("Image filename '%s'\n", mem_fname);
return err;
}
return unlink(fname);
}
int os_jump_to_image(const void *dest, int size)
{
char fname[30];
int err;
err = make_exec(fname, dest, size);
if (err)
return err;
return unlink(fname);
return os_jump_to_file(fname);
}
int os_find_u_boot(char *fname, int maxlen)
@ -699,17 +750,7 @@ int os_find_u_boot(char *fname, int maxlen)
int os_spl_to_uboot(const char *fname)
{
struct sandbox_state *state = state_get_current();
char *argv[state->argc + 1];
int ret;
memcpy(argv, state->argv, sizeof(char *) * (state->argc + 1));
argv[0] = (char *)fname;
ret = execv(fname, argv);
if (ret)
return ret;
return unlink(fname);
return os_jump_to_file(fname);
}
void os_localtime(struct rtc_time *rt)

View file

@ -37,12 +37,39 @@ static int spl_board_load_image(struct spl_image_info *spl_image,
return ret;
}
/* Hopefully this will not return */
return os_spl_to_uboot(fname);
/* Set up spl_image to boot from jump_to_image_no_args() */
spl_image->arg = strdup(fname);
if (!spl_image->arg)
return log_msg_ret("Setup exec filename", -ENOMEM);
return 0;
}
SPL_LOAD_IMAGE_METHOD("sandbox", 0, BOOT_DEVICE_BOARD, spl_board_load_image);
void spl_board_init(void)
{
struct sandbox_state *state = state_get_current();
struct udevice *dev;
preloader_console_init();
if (state->show_of_platdata) {
/*
* Scan all the devices so that we can output their platform
* data. See sandbox_spl_probe().
*/
printf("Scanning misc devices\n");
for (uclass_first_device(UCLASS_MISC, &dev);
dev;
uclass_next_device(&dev))
;
}
}
void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image)
{
const char *fname = spl_image->arg;
os_fd_restore();
os_spl_to_uboot(fname);
hang();
}

View file

@ -283,6 +283,15 @@ static int sandbox_cmdline_cb_log_level(struct sandbox_state *state,
SANDBOX_CMDLINE_OPT_SHORT(log_level, 'L', 1,
"Set log level (0=panic, 7=debug)");
static int sandbox_cmdline_cb_show_of_platdata(struct sandbox_state *state,
const char *arg)
{
state->show_of_platdata = true;
return 0;
}
SANDBOX_CMDLINE_OPT(show_of_platdata, 0, "Show of-platdata in SPL");
int board_run_command(const char *cmdline)
{
printf("## Commands are disabled. Please enable CONFIG_CMDLINE.\n");
@ -296,6 +305,16 @@ static void setup_ram_buf(struct sandbox_state *state)
gd->ram_size = state->ram_size;
}
void state_show(struct sandbox_state *state)
{
char **p;
printf("Arguments:\n");
for (p = state->argv; *p; p++)
printf("%s ", *p);
printf("\n");
}
int main(int argc, char *argv[])
{
struct sandbox_state *state;

View file

@ -14,7 +14,7 @@ SECTIONS
}
__u_boot_sandbox_option_start = .;
_u_boot_sandbox_getopt : { *(.u_boot_sandbox_getopt) }
_u_boot_sandbox_getopt : { KEEP(*(.u_boot_sandbox_getopt)) }
__u_boot_sandbox_option_end = .;
__bss_start = .;

View file

@ -0,0 +1,18 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Architecture-specific SPL handoff information for sandbox
*
* Copyright 2018 Google, Inc
* Written by Simon Glass <sjg@chromium.org>
*/
#ifndef __handoff_h
#define __handoff_h
#define TEST_HANDOFF_MAGIC 0x14f93c7b
struct arch_spl_handoff {
ulong magic; /* Used for testing */
};
#endif

View file

@ -89,6 +89,7 @@ struct sandbox_state {
bool skip_delays; /* Ignore any time delays (for test) */
bool show_test_output; /* Don't suppress stdout in tests */
int default_log_level; /* Default log level for sandbox */
bool show_of_platdata; /* Show of-platdata in SPL */
/* Pointer to information for each SPI bus/cs */
struct sandbox_spi_info spi[CONFIG_SANDBOX_SPI_MAX_BUS]
@ -241,6 +242,13 @@ bool state_get_skip_delays(void);
*/
void state_reset_for_test(struct sandbox_state *state);
/**
* state_show() - Show information about the sandbox state
*
* @param state Sandbox state to show
*/
void state_show(struct sandbox_state *state);
/**
* Initialize the test system state
*/

View file

@ -422,7 +422,19 @@ coverage in U-Boot is limited, as we need to work to improve it.
Note that many of these tests are implemented as commands which you can
run natively on your board if desired (and enabled).
It would be useful to have a central script to run all of these.
To run all tests use "make check".
Memory Map
----------
Sandbox has its own emulated memory starting at 0. Here are some of the things
that are mapped into that memory:
0 CONFIG_SYS_FDT_LOAD_ADDR Device tree
e000 CONFIG_BLOBLIST_ADDR Blob list
10000 CONFIG_MALLOC_F_ADDR Early memory allocation
--
Simon Glass <sjg@chromium.org>

View file

@ -115,6 +115,7 @@ obj-$(CONFIG_CMD_ROCKUSB) += rockusb.o
obj-$(CONFIG_SANDBOX) += host.o
obj-$(CONFIG_CMD_SATA) += sata.o
obj-$(CONFIG_CMD_NVME) += nvme.o
obj-$(CONFIG_SANDBOX) += sb.o
obj-$(CONFIG_CMD_SF) += sf.o
obj-$(CONFIG_CMD_SCSI) += scsi.o disk.o
obj-$(CONFIG_CMD_SHA1SUM) += sha1sum.o

View file

@ -167,11 +167,6 @@ static int do_host(cmd_tbl_t *cmdtp, int flag, int argc,
return CMD_RET_USAGE;
}
U_BOOT_CMD(
sb, 8, 1, do_host,
"Deprecated: use 'host' command instead.", ""
);
U_BOOT_CMD(
host, 8, 1, do_host,
"Miscellaneous host commands",

65
cmd/sb.c Normal file
View file

@ -0,0 +1,65 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2018, Google Inc.
* Written by Simon Glass <sjg@chromium.org>
*/
#include <common.h>
#include <dm.h>
#include <spl.h>
#include <asm/state.h>
static int do_sb_handoff(cmd_tbl_t *cmdtp, int flag, int argc,
char *const argv[])
{
#if CONFIG_IS_ENABLED(HANDOFF)
if (gd->spl_handoff)
printf("SPL handoff magic %lx\n", gd->spl_handoff->arch.magic);
else
printf("SPL handoff info not received\n");
return 0;
#else
printf("Command not supported\n");
return CMD_RET_USAGE;
#endif
}
static int do_sb_state(cmd_tbl_t *cmdtp, int flag, int argc,
char * const argv[])
{
struct sandbox_state *state;
state = state_get_current();
state_show(state);
return 0;
}
static cmd_tbl_t cmd_sb_sub[] = {
U_BOOT_CMD_MKENT(handoff, 1, 0, do_sb_handoff, "", ""),
U_BOOT_CMD_MKENT(state, 1, 0, do_sb_state, "", ""),
};
static int do_sb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
cmd_tbl_t *c;
/* Skip past 'sb' */
argc--;
argv++;
c = find_cmd_tbl(argv[0], cmd_sb_sub, ARRAY_SIZE(cmd_sb_sub));
if (c)
return c->cmd(cmdtp, flag, argc, argv);
else
return CMD_RET_USAGE;
}
U_BOOT_CMD(
sb, 8, 1, do_sb,
"Sandbox status commands",
"handoff - Show handoff data received from SPL\n"
"sb state - Show sandbox state"
);

View file

@ -299,6 +299,10 @@ config SPL_LOGLEVEL
int
default LOGLEVEL
config TPL_LOGLEVEL
int
default LOGLEVEL
config SILENT_CONSOLE
bool "Support a silent console"
help
@ -505,6 +509,24 @@ config SPL_LOG_MAX_LEVEL
6 - detail
7 - debug
config TPL_LOG_MAX_LEVEL
int "Maximum log level to record in TPL"
depends on TPL_LOG
default 3
help
This selects the maximum log level that will be recorded. Any value
higher than this will be ignored. If possible log statements below
this level will be discarded at build time. Levels:
0 - panic
1 - critical
2 - error
3 - warning
4 - note
5 - info
6 - detail
7 - debug
config LOG_CONSOLE
bool "Allow log output to the console"
depends on LOG
@ -515,9 +537,19 @@ config LOG_CONSOLE
log message is shown - other details like level, category, file and
line number are omitted.
config LOG_SPL_CONSOLE
config SPL_LOG_CONSOLE
bool "Allow log output to the console in SPL"
depends on LOG_SPL
depends on SPL_LOG
default y
help
Enables a log driver which writes log records to the console.
Generally the console is the serial port or LCD display. Only the
log message is shown - other details like level, category, file and
line number are omitted.
config TPL_LOG_CONSOLE
bool "Allow log output to the console in SPL"
depends on TPL_LOG
default y
help
Enables a log driver which writes log records to the console.
@ -718,4 +750,52 @@ config UPDATE_TFTP_MSEC_MAX
endmenu
menu "Blob list"
config BLOBLIST
bool "Support for a bloblist"
help
This enables support for a bloblist in U-Boot, which can be passed
from TPL to SPL to U-Boot proper (and potentially to Linux). The
blob list supports multiple binary blobs of data, each with a tag,
so that different U-Boot components can store data which can survive
through to the next stage of the boot.
config SPL_BLOBLIST
bool "Support for a bloblist in SPL"
depends on BLOBLIST
default y if SPL
help
This enables a bloblist in SPL. If this is the first part of U-Boot
to run, then the bloblist is set up in SPL and passed to U-Boot
proper. If TPL also has a bloblist, then SPL uses the one from there.
config TPL_BLOBLIST
bool "Support for a bloblist in TPL"
depends on BLOBLIST
default y if TPL
help
This enables a bloblist in TPL. The bloblist is set up in TPL and
passed to SPL and U-Boot proper.
config BLOBLIST_SIZE
hex "Size of bloblist"
depends on BLOBLIST
default 0x400
help
Sets the size of the bloblist in bytes. This must include all
overhead (alignment, bloblist header, record header). The bloblist
is set up in the first part of U-Boot to run (TPL, SPL or U-Boot
proper), and this sane bloblist is used for subsequent stages.
config BLOBLIST_ADDR
hex "Address of bloblist"
depends on BLOBLIST
default 0xe000 if SANDBOX
help
Sets the address of the bloblist, set up by the first part of U-Boot
which runs. Subsequent U-Boot stages typically use the same address.
endmenu
source "common/spl/Kconfig"

View file

@ -61,6 +61,7 @@ obj-$(CONFIG_CMDLINE) += cli_readline.o cli_simple.o
endif # !CONFIG_SPL_BUILD
obj-$(CONFIG_$(SPL_TPL_)BOOTSTAGE) += bootstage.o
obj-$(CONFIG_$(SPL_TPL_)BLOBLIST) += bloblist.o
ifdef CONFIG_SPL_BUILD
ifdef CONFIG_SPL_DFU_SUPPORT
@ -122,8 +123,8 @@ obj-y += cli.o
obj-$(CONFIG_FSL_DDR_INTERACTIVE) += cli_simple.o cli_readline.o
obj-$(CONFIG_DFU_OVER_USB) += dfu.o
obj-y += command.o
obj-$(CONFIG_$(SPL_)LOG) += log.o
obj-$(CONFIG_$(SPL_)LOG_CONSOLE) += log_console.o
obj-$(CONFIG_$(SPL_TPL_)LOG) += log.o
obj-$(CONFIG_$(SPL_TPL_)LOG_CONSOLE) += log_console.o
obj-y += s_record.o
obj-$(CONFIG_CMD_LOADB) += xyzModem.o
obj-$(CONFIG_$(SPL_TPL_)YMODEM_SUPPORT) += xyzModem.o

239
common/bloblist.c Normal file
View file

@ -0,0 +1,239 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2018 Google, Inc
* Written by Simon Glass <sjg@chromium.org>
*/
#include <common.h>
#include <bloblist.h>
#include <log.h>
#include <mapmem.h>
#include <spl.h>
DECLARE_GLOBAL_DATA_PTR;
struct bloblist_rec *bloblist_first_blob(struct bloblist_hdr *hdr)
{
if (hdr->alloced <= hdr->hdr_size)
return NULL;
return (struct bloblist_rec *)((void *)hdr + hdr->hdr_size);
}
struct bloblist_rec *bloblist_next_blob(struct bloblist_hdr *hdr,
struct bloblist_rec *rec)
{
ulong offset;
offset = (void *)rec - (void *)hdr;
offset += rec->hdr_size + ALIGN(rec->size, BLOBLIST_ALIGN);
if (offset >= hdr->alloced)
return NULL;
return (struct bloblist_rec *)((void *)hdr + offset);
}
#define foreach_rec(_rec, _hdr) \
for (_rec = bloblist_first_blob(_hdr); \
_rec; \
_rec = bloblist_next_blob(_hdr, _rec))
static struct bloblist_rec *bloblist_findrec(uint tag)
{
struct bloblist_hdr *hdr = gd->bloblist;
struct bloblist_rec *rec;
if (!hdr)
return NULL;
foreach_rec(rec, hdr) {
if (rec->tag == tag)
return rec;
}
return NULL;
}
static int bloblist_addrec(uint tag, int size, struct bloblist_rec **recp)
{
struct bloblist_hdr *hdr = gd->bloblist;
struct bloblist_rec *rec;
int new_alloced;
new_alloced = hdr->alloced + sizeof(*rec) +
ALIGN(size, BLOBLIST_ALIGN);
if (new_alloced >= hdr->size) {
log(LOGC_BLOBLIST, LOGL_ERR,
"Failed to allocate %x bytes size=%x, need size>=%x\n",
size, hdr->size, new_alloced);
return log_msg_ret("bloblist add", -ENOSPC);
}
rec = (void *)hdr + hdr->alloced;
hdr->alloced = new_alloced;
rec->tag = tag;
rec->hdr_size = sizeof(*rec);
rec->size = size;
rec->spare = 0;
*recp = rec;
return 0;
}
static int bloblist_ensurerec(uint tag, struct bloblist_rec **recp, int size)
{
struct bloblist_rec *rec;
rec = bloblist_findrec(tag);
if (rec) {
if (size && size != rec->size)
return -ESPIPE;
} else {
int ret;
ret = bloblist_addrec(tag, size, &rec);
if (ret)
return ret;
}
*recp = rec;
return 0;
}
void *bloblist_find(uint tag, int size)
{
struct bloblist_rec *rec;
rec = bloblist_findrec(tag);
if (!rec)
return NULL;
if (size && size != rec->size)
return NULL;
return (void *)rec + rec->hdr_size;
}
void *bloblist_add(uint tag, int size)
{
struct bloblist_rec *rec;
if (bloblist_addrec(tag, size, &rec))
return NULL;
return rec + 1;
}
int bloblist_ensure_size(uint tag, int size, void **blobp)
{
struct bloblist_rec *rec;
int ret;
ret = bloblist_ensurerec(tag, &rec, size);
if (ret)
return ret;
*blobp = (void *)rec + rec->hdr_size;
return 0;
}
void *bloblist_ensure(uint tag, int size)
{
struct bloblist_rec *rec;
if (bloblist_ensurerec(tag, &rec, size))
return NULL;
return (void *)rec + rec->hdr_size;
}
static u32 bloblist_calc_chksum(struct bloblist_hdr *hdr)
{
struct bloblist_rec *rec;
u32 chksum;
chksum = crc32(0, (unsigned char *)hdr,
offsetof(struct bloblist_hdr, chksum));
foreach_rec(rec, hdr) {
chksum = crc32(chksum, (void *)rec, rec->hdr_size);
chksum = crc32(chksum, (void *)rec + rec->hdr_size, rec->size);
}
return chksum;
}
int bloblist_new(ulong addr, uint size, uint flags)
{
struct bloblist_hdr *hdr;
if (size < sizeof(*hdr))
return log_ret(-ENOSPC);
if (addr & (BLOBLIST_ALIGN - 1))
return log_ret(-EFAULT);
hdr = map_sysmem(addr, size);
memset(hdr, '\0', sizeof(*hdr));
hdr->version = BLOBLIST_VERSION;
hdr->hdr_size = sizeof(*hdr);
hdr->flags = flags;
hdr->magic = BLOBLIST_MAGIC;
hdr->size = size;
hdr->alloced = hdr->hdr_size;
hdr->chksum = 0;
gd->bloblist = hdr;
return 0;
}
int bloblist_check(ulong addr, uint size)
{
struct bloblist_hdr *hdr;
u32 chksum;
hdr = map_sysmem(addr, sizeof(*hdr));
if (hdr->magic != BLOBLIST_MAGIC)
return log_msg_ret("Bad magic", -ENOENT);
if (hdr->version != BLOBLIST_VERSION)
return log_msg_ret("Bad version", -EPROTONOSUPPORT);
if (size && hdr->size != size)
return log_msg_ret("Bad size", -EFBIG);
chksum = bloblist_calc_chksum(hdr);
if (hdr->chksum != chksum) {
log(LOGC_BLOBLIST, LOGL_ERR, "Checksum %x != %x\n", hdr->chksum,
chksum);
return log_msg_ret("Bad checksum", -EIO);
}
gd->bloblist = hdr;
return 0;
}
int bloblist_finish(void)
{
struct bloblist_hdr *hdr = gd->bloblist;
hdr->chksum = bloblist_calc_chksum(hdr);
return 0;
}
int bloblist_init(void)
{
bool expected;
int ret = -ENOENT;
/**
* Wed expect to find an existing bloblist in the first phase of U-Boot
* that runs
*/
expected = !u_boot_first_phase();
if (expected)
ret = bloblist_check(CONFIG_BLOBLIST_ADDR,
CONFIG_BLOBLIST_SIZE);
if (ret) {
log(LOGC_BLOBLIST, expected ? LOGL_WARNING : LOGL_DEBUG,
"Existing bloblist not found: creating new bloblist\n");
ret = bloblist_new(CONFIG_BLOBLIST_ADDR, CONFIG_BLOBLIST_SIZE,
0);
} else {
log(LOGC_BLOBLIST, LOGL_DEBUG, "Found existing bloblist\n");
}
return ret;
}

View file

@ -10,6 +10,7 @@
*/
#include <common.h>
#include <bloblist.h>
#include <console.h>
#include <cpu.h>
#include <dm.h>
@ -24,6 +25,9 @@
#include <post.h>
#include <relocate.h>
#include <spi.h>
#ifdef CONFIG_SPL
#include <spl.h>
#endif
#include <status_led.h>
#include <sysreset.h>
#include <timer.h>
@ -285,6 +289,17 @@ static int setup_mon_len(void)
return 0;
}
static int setup_spl_handoff(void)
{
#if CONFIG_IS_ENABLED(HANDOFF)
gd->spl_handoff = bloblist_find(BLOBLISTT_SPL_HANDOFF,
sizeof(struct spl_handoff));
debug("Found SPL hand-off info %p\n", gd->spl_handoff);
#endif
return 0;
}
__weak int arch_cpu_init(void)
{
return 0;
@ -560,6 +575,16 @@ static int reserve_stacks(void)
return arch_reserve_stacks();
}
static int reserve_bloblist(void)
{
#ifdef CONFIG_BLOBLIST
gd->start_addr_sp -= CONFIG_BLOBLIST_SIZE;
gd->new_bloblist = map_sysmem(gd->start_addr_sp, CONFIG_BLOBLIST_SIZE);
#endif
return 0;
}
static int display_new_sp(void)
{
debug("New Stack Pointer is: %08lx\n", gd->start_addr_sp);
@ -666,6 +691,24 @@ static int reloc_bootstage(void)
return 0;
}
static int reloc_bloblist(void)
{
#ifdef CONFIG_BLOBLIST
if (gd->flags & GD_FLG_SKIP_RELOC)
return 0;
if (gd->new_bloblist) {
int size = CONFIG_BLOBLIST_SIZE;
debug("Copying bloblist from %p to %p, size %x\n",
gd->bloblist, gd->new_bloblist, size);
memcpy(gd->new_bloblist, gd->bloblist, size);
gd->bloblist = gd->new_bloblist;
}
#endif
return 0;
}
static int setup_reloc(void)
{
if (gd->flags & GD_FLG_SKIP_RELOC) {
@ -813,6 +856,10 @@ static const init_fnc_t init_sequence_f[] = {
initf_malloc,
log_init,
initf_bootstage, /* uses its own timer, so does not need DM */
#ifdef CONFIG_BLOBLIST
bloblist_init,
#endif
setup_spl_handoff,
initf_console_record,
#if defined(CONFIG_HAVE_FSP)
arch_fsp_init,
@ -913,6 +960,7 @@ static const init_fnc_t init_sequence_f[] = {
reserve_global_data,
reserve_fdt,
reserve_bootstage,
reserve_bloblist,
reserve_arch,
reserve_stacks,
dram_init_banksize,
@ -932,6 +980,7 @@ static const init_fnc_t init_sequence_f[] = {
INIT_FUNC_WATCHDOG_RESET
reloc_fdt,
reloc_bootstage,
reloc_bloblist,
setup_reloc,
#if defined(CONFIG_X86) || defined(CONFIG_ARC)
copy_uboot_to_ram,

View file

@ -535,6 +535,13 @@ void putc(const char c)
void puts(const char *s)
{
#ifdef CONFIG_SANDBOX
/* sandbox can send characters to stdout before it has a console */
if (!gd || !(gd->flags & GD_FLG_SERIAL_READY)) {
os_puts(s);
return;
}
#endif
#ifdef CONFIG_DEBUG_UART
if (!gd || !(gd->flags & GD_FLG_SERIAL_READY)) {
while (*s) {

View file

@ -5,3 +5,4 @@
#
obj-y += board_init.o
obj-$(CONFIG_$(SPL_TPL_)HANDOFF) += handoff.o

47
common/init/handoff.c Normal file
View file

@ -0,0 +1,47 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Passing basic information from SPL to U-Boot proper
*
* Copyright 2018 Google, Inc
*/
#include <common.h>
#include <handoff.h>
DECLARE_GLOBAL_DATA_PTR;
void handoff_save_dram(struct spl_handoff *ho)
{
ho->ram_size = gd->ram_size;
#ifdef CONFIG_NR_DRAM_BANKS
{
struct bd_info *bd = gd->bd;
int i;
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;
}
}
#endif
}
void handoff_load_dram_size(struct spl_handoff *ho)
{
gd->ram_size = ho->ram_size;
}
void handoff_load_dram_banks(struct spl_handoff *ho)
{
#ifdef CONFIG_NR_DRAM_BANKS
{
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;
}
}
#endif
}

View file

@ -25,8 +25,28 @@ config SPL_FRAMEWORK
supports MMC, NAND and YMODEM and other methods loading of U-Boot
and the Linux Kernel. If unsure, say Y.
config HANDOFF
bool "Pass hand-off information from SPL to U-Boot proper"
depends on BLOBLIST
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.
Enable this to locate the handoff information in U-Boot proper, early
in boot. It is available in gd->handoff. The state state is set up
in SPL (or TPL if that is being used).
if SPL
config SPL_HANDOFF
bool "Pass hand-off information from SPL to U-Boot proper"
depends on HANDOFF
default y
help
This option enables SPL to write handoff information. This can be
used to pass information like the size of SDRAM from SPL to U-Boot
proper. Also SPL can receive information from TPL in the same place
if that is enabled.
config SPL_LDSCRIPT
string "Linker script for the SPL stage"
default "arch/$(ARCH)/cpu/u-boot-spl.lds"
@ -135,12 +155,21 @@ config SPL_SEPARATE_BSS
location is used. Normally we put the device tree at the end of BSS
but with this option enabled, it goes at _image_binary_end.
config SPL_DISABLE_BANNER_PRINT
bool "Disable output of the SPL banner 'U-Boot SPL ...'"
config SPL_BANNER_PRINT
bool "Enable output of the SPL banner 'U-Boot SPL ...'"
default y
help
If this option is enabled, SPL will print the banner with version
info. Disabling this option could be useful to reduce TPL boot time
(e.g. approx. 6 ms faster, when output on i.MX6 with 115200 baud).
config TPL_BANNER_PRINT
bool "Enable output of the TPL banner 'U-Boot TPL ...'"
default y
help
If this option is enabled, SPL will not print the banner with version
info. Selecting this option could be useful to reduce SPL boot time
(e.g. approx. 6 ms slower, when output on i.MX6 with 115200 baud).
info. Disabling this option could be useful to reduce SPL boot time
(e.g. approx. 6 ms faster, when output on i.MX6 with 115200 baud).
config SPL_DISPLAY_PRINT
bool "Display a board-specific message in SPL"
@ -295,6 +324,16 @@ config SPL_HASH_SUPPORT
this option to build system-specific drivers for hash acceleration
as part of an SPL build.
config TPL_HASH_SUPPORT
bool "Support hashing drivers in TPL"
select SHA1
select SHA256
help
Enable hashing drivers in SPL. These drivers can be used to
accelerate secure boot processing in secure applications. Enable
this option to build system-specific drivers for hash acceleration
as part of an SPL build.
config SPL_DMA_SUPPORT
bool "Support DMA drivers"
help
@ -376,7 +415,7 @@ config SPL_FPGA_SUPPORT
within SPL.
config SPL_GPIO_SUPPORT
bool "Support GPIO"
bool "Support GPIO in 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
@ -848,6 +887,16 @@ config TPL
if TPL
config TPL_HANDOFF
bool "Pass hand-off information from TPL to SPL and U-Boot proper"
depends on HANDOFF
default y
help
This option enables TPL to write handoff information. This can be
used to pass information like the size of SDRAM from TPL to U-Boot
proper. The information is also available to SPL if it is useful
there.
config TPL_BOARD_INIT
bool "Call board-specific initialization in TPL"
help
@ -928,6 +977,17 @@ config TPL_ENV_SUPPORT
help
Enable environment support in TPL. See SPL_ENV_SUPPORT for details.
config TPL_GPIO_SUPPORT
bool "Support GPIO in TPL"
help
Enable support for GPIOs (General-purpose Input/Output) in TPL.
GPIOs allow U-Boot to read the state of an input line (high or
low) and set the state of an output line. This can be used to
drive LEDs, control power to various system parts and read user
input. GPIOs can be useful in TPL to enable a 'sign-of-life' LED,
for example. Enable this option to build the drivers in
drivers/gpio as part of an TPL build.
config TPL_I2C_SUPPORT
bool "Support I2C"
help
@ -963,6 +1023,22 @@ config TPL_NAND_SUPPORT
help
Enable support for NAND in TPL. See SPL_NAND_SUPPORT for details.
config TPL_PCI_SUPPORT
bool "Support PCI drivers"
help
Enable support for PCI in TPL. For platforms that need PCI to boot,
or must perform some init using PCI in SPL, this provides the
necessary driver support. This enables the drivers in drivers/pci
as part of a TPL build.
config TPL_PCH_SUPPORT
bool "Support PCH drivers"
help
Enable support for PCH (Platform Controller Hub) devices in TPL.
These are used to set up GPIOs and the SPI peripheral early in
boot. This enables the drivers in drivers/pch as part of a TPL
build.
config TPL_RAM_SUPPORT
bool "Support booting from RAM"
help
@ -977,6 +1053,15 @@ config TPL_RAM_DEVICE
be already in memory when TPL takes over, e.g. loaded by the boot
ROM.
config TPL_RTC_SUPPORT
bool "Support RTC drivers"
help
Enable RTC (Real-time Clock) support in TPL. This includes support
for reading and setting the time. Some RTC devices also have some
non-volatile (battery-backed) memory which is accessible if
needed. This enables the drivers in drivers/rtc as part of an TPL
build.
config TPL_SERIAL_SUPPORT
bool "Support serial"
select TPL_PRINTF

View file

@ -7,8 +7,10 @@
*/
#include <common.h>
#include <bloblist.h>
#include <binman_sym.h>
#include <dm.h>
#include <handoff.h>
#include <spl.h>
#include <asm/u-boot.h>
#include <nand.h>
@ -44,6 +46,14 @@ static bd_t bdata __attribute__ ((section(".data")));
*/
__weak void show_boot_progress(int val) {}
#if defined(CONFIG_SPL_OS_BOOT) || CONFIG_IS_ENABLED(HANDOFF)
/* weak, default platform-specific function to initialize dram banks */
__weak int dram_init_banksize(void)
{
return 0;
}
#endif
/*
* Default function to determine if u-boot or the OS should
* be started. This implementation always returns 1.
@ -57,19 +67,12 @@ __weak void show_boot_progress(int val) {}
#ifdef CONFIG_SPL_OS_BOOT
__weak int spl_start_uboot(void)
{
puts("SPL: Please implement spl_start_uboot() for your board\n");
puts("SPL: Direct Linux boot not active!\n");
puts(SPL_TPL_PROMPT
"Please implement spl_start_uboot() for your board\n");
puts(SPL_TPL_PROMPT "Direct Linux boot not active!\n");
return 1;
}
/* weak default platform specific function to initialize
* dram banks
*/
__weak int dram_init_banksize(void)
{
return 0;
}
/*
* Weak default function for arch specific zImage check. Return zero
* and fill start and end address if image is recognized.
@ -100,13 +103,13 @@ void spl_fixup_fdt(void)
/* fixup the memory dt node */
err = fdt_shrink_to_minimum(fdt_blob, 0);
if (err == 0) {
printf("spl: fdt_shrink_to_minimum err - %d\n", err);
printf(SPL_TPL_PROMPT "fdt_shrink_to_minimum err - %d\n", err);
return;
}
err = arch_fixup_fdt(fdt_blob);
if (err) {
printf("spl: arch_fixup_fdt err - %d\n", err);
printf(SPL_TPL_PROMPT "arch_fixup_fdt err - %d\n", err);
return;
}
#endif
@ -185,7 +188,7 @@ static int spl_load_fit_image(struct spl_image_info *spl_image,
spl_image->os = IH_OS_U_BOOT;
spl_image->name = "U-Boot";
debug("spl: payload image: %32s load addr: 0x%lx size: %d\n",
debug(SPL_TPL_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
@ -255,7 +258,8 @@ int spl_parse_image_header(struct spl_image_info *spl_image,
}
spl_image->os = image_get_os(header);
spl_image->name = image_get_name(header);
debug("spl: payload image: %32s load addr: 0x%lx size: %d\n",
debug(SPL_TPL_PROMPT
"payload image: %32s load addr: 0x%lx size: %d\n",
spl_image->name, spl_image->load_addr, spl_image->size);
#else
/* LEGACY image not supported */
@ -284,7 +288,8 @@ int spl_parse_image_header(struct spl_image_info *spl_image,
spl_image->load_addr = CONFIG_SYS_LOAD_ADDR;
spl_image->entry_point = CONFIG_SYS_LOAD_ADDR;
spl_image->size = end - start;
debug("spl: payload zImage, load addr: 0x%lx size: %d\n",
debug(SPL_TPL_PROMPT
"payload zImage, load addr: 0x%lx size: %d\n",
spl_image->load_addr, spl_image->size);
return 0;
}
@ -316,6 +321,44 @@ __weak void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image)
image_entry();
}
#if CONFIG_IS_ENABLED(HANDOFF)
/**
* Set up the SPL hand-off information
*
* This is initially empty (zero) but can be written by
*/
static int setup_spl_handoff(void)
{
struct spl_handoff *ho;
ho = bloblist_ensure(BLOBLISTT_SPL_HANDOFF, sizeof(struct spl_handoff));
if (!ho)
return -ENOENT;
return 0;
}
static int write_spl_handoff(void)
{
struct spl_handoff *ho;
ho = bloblist_find(BLOBLISTT_SPL_HANDOFF, sizeof(struct spl_handoff));
if (!ho)
return -ENOENT;
handoff_save_dram(ho);
#ifdef CONFIG_SANDBOX
ho->arch.magic = TEST_HANDOFF_MAGIC;
#endif
debug(SPL_TPL_PROMPT "Wrote SPL handoff\n");
return 0;
}
#else
static inline int setup_spl_handoff(void) { return 0; }
static inline int write_spl_handoff(void) { return 0; }
#endif /* HANDOFF */
static int spl_common_init(bool setup_malloc)
{
int ret;
@ -336,6 +379,30 @@ static int spl_common_init(bool setup_malloc)
return ret;
}
bootstage_mark_name(BOOTSTAGE_ID_START_SPL, "spl");
#if CONFIG_IS_ENABLED(LOG)
ret = log_init();
if (ret) {
debug("%s: Failed to set up logging\n", __func__);
return ret;
}
#endif
if (CONFIG_IS_ENABLED(BLOBLIST)) {
ret = bloblist_init();
if (ret) {
debug("%s: Failed to set up bloblist: ret=%d\n",
__func__, ret);
return ret;
}
}
if (CONFIG_IS_ENABLED(HANDOFF)) {
int ret;
ret = setup_spl_handoff();
if (ret) {
puts(SPL_TPL_PROMPT "Cannot set up SPL handoff\n");
hang();
}
}
if (CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)) {
ret = fdtdec_setup();
if (ret) {
@ -359,6 +426,10 @@ static int spl_common_init(bool setup_malloc)
void spl_set_bd(void)
{
/*
* NOTE: On some platforms (e.g. x86) bdata may be in flash and not
* writeable.
*/
if (!gd->bd)
gd->bd = &bdata;
}
@ -453,7 +524,7 @@ static int boot_from_devices(struct spl_image_info *spl_image,
if (loader)
printf("Trying to boot from %s\n", loader->name);
else
puts("SPL: Unsupported Boot Device!\n");
puts(SPL_TPL_PROMPT "Unsupported Boot Device!\n");
#endif
if (loader && !spl_load_image(spl_image, loader)) {
spl_image->boot_device = spl_boot_list[i];
@ -474,15 +545,12 @@ void board_init_r(gd_t *dummy1, ulong dummy2)
BOOT_DEVICE_NONE,
};
struct spl_image_info spl_image;
int ret;
debug(">>spl:board_init_r()\n");
debug(">>" SPL_TPL_PROMPT "board_init_r()\n");
spl_set_bd();
#ifdef CONFIG_SPL_OS_BOOT
dram_init_banksize();
#endif
#if defined(CONFIG_SYS_SPL_MALLOC_START)
mem_malloc_init(CONFIG_SYS_SPL_MALLOC_START,
CONFIG_SYS_SPL_MALLOC_SIZE);
@ -504,6 +572,9 @@ void board_init_r(gd_t *dummy1, ulong dummy2)
spl_board_init();
#endif
if (IS_ENABLED(CONFIG_SPL_OS_BOOT) || CONFIG_IS_ENABLED(HANDOFF))
dram_init_banksize();
bootcount_inc();
memset(&spl_image, '\0', sizeof(spl_image));
@ -515,11 +586,23 @@ void board_init_r(gd_t *dummy1, ulong dummy2)
if (boot_from_devices(&spl_image, spl_boot_list,
ARRAY_SIZE(spl_boot_list))) {
puts("SPL: failed to boot from all boot devices\n");
puts(SPL_TPL_PROMPT "failed to boot from all boot devices\n");
hang();
}
spl_perform_fixups(&spl_image);
if (CONFIG_IS_ENABLED(HANDOFF)) {
ret = write_spl_handoff();
if (ret)
printf(SPL_TPL_PROMPT
"SPL hand-off write failed (err=%d)\n", ret);
}
if (CONFIG_IS_ENABLED(BLOBLIST)) {
ret = bloblist_finish();
if (ret)
printf("Warning: Failed to finish bloblist (ret=%d)\n",
ret);
}
#ifdef CONFIG_CPU_V7M
spl_image.entry_point |= 0x1;
@ -556,8 +639,6 @@ void board_init_r(gd_t *dummy1, ulong dummy2)
gd->malloc_ptr / 1024);
#endif
#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);
@ -583,8 +664,8 @@ void preloader_console_init(void)
gd->have_console = 1;
#ifndef CONFIG_SPL_DISABLE_BANNER_PRINT
puts("\nU-Boot SPL " PLAIN_VERSION " (" U_BOOT_DATE " - " \
#if CONFIG_IS_ENABLED(BANNER_PRINT)
puts("\nU-Boot " SPL_TPL_NAME " " PLAIN_VERSION " (" U_BOOT_DATE " - "
U_BOOT_TIME " " U_BOOT_TZ ")\n");
#endif
#ifdef CONFIG_SPL_DISPLAY_PRINT

View file

@ -22,6 +22,7 @@ CONFIG_CONSOLE_RECORD=y
CONFIG_CONSOLE_RECORD_OUT_SIZE=0x1000
CONFIG_SILENT_CONSOLE=y
CONFIG_DISPLAY_BOARDINFO_LATE=y
CONFIG_HANDOFF=y
CONFIG_SPL_BOARD_INIT=y
CONFIG_SPL_ENV_SUPPORT=y
CONFIG_CMD_CPU=y

82
doc/README.bloblist Normal file
View file

@ -0,0 +1,82 @@
# SPDX-License-Identifier: GPL-2.0+
Blob Lists - bloblist
=====================
Introduction
------------
A bloblist provides a way to store collections of binary information (blobs) in
a central structure. Each record of information is assigned a tag so that its
owner can find it and update it. Each record is generally described by a C
structure defined by the code that owns it.
Passing state through the boot process
--------------------------------------
The bloblist is created when the first U-Boot component runs (often SPL,
sometimes TPL). It is passed through to each successive part of the boot and
can be accessed as needed. This provides a way to transfer state from one part
to the next. For example, TPL may determine that a watchdog reset occurred by
reading an SoC register. Reading the register may reset the value, so that it
cannot be read a second time. So TPL can store that in a bloblist record which
can be passed through to SPL and U-Boot proper, which can print a message
indicating that something went wrong and the watchdog fired.
Blobs
-----
While each blob in the bloblist can be of any length, bloblists are designed to
hold small amounts of data, typically a few KB at most. It is not possible to
change the length of a blob once it has been written. Each blob is normally
created from a C structure which can beused to access its fields.
Blob tags
---------
Each blob has a tag which is a 32-bit number. This uniquely identifies the
owner of the blob. Blob tags are listed in enum blob_tag_t and are named
with a BLOBT_ prefix.
Single structure
----------------
There is normally only one bloblist in U-Boot. Since a bloblist can store
multiple blobs it does not seem useful to allow multiple bloblists. Of course
there could be reasons for this, such as needing to spread the blobs around in
different memory areas due to fragmented memory, but it is simpler to just have
a single bloblist.
API
---
Bloblist provides a fairly simple API which allows blobs to be created and
found. All access is via the blob's tag.
Finishing the bloblist
----------------------
When a part of U-Boot is about to jump to the next part, it can 'finish' the
bloblist in preparation for the next stage. This involves adding a checksum so
that the next stage can make sure that the data arrived safely. While the
bloblist is in use, changes can be made which will affect the checksum, so it
is easier to calculate the checksum at the end after all changes are made.
Future work
-----------
Bootstage has a mechanism to 'stash' its records for passing to the next part.
This should move to using bloblist, to avoid having its own mechanism for
passing information between U-Boot parts.
Simon Glass
sjg@chromium.org
12-Aug-2018

View file

@ -88,7 +88,7 @@ stdin=serial
stdout=serial
Environment size: 117/8188 bytes
=>sb save host 0 trace 0 ${profoffset}
=>host save host 0 trace 0 ${profoffset}
11405888 bytes written in 10 ms (1.1 GiB/s)
=>reset

View file

@ -2,14 +2,19 @@
obj-$(CONFIG_$(SPL_TPL_)CLK) += clk/
obj-$(CONFIG_$(SPL_TPL_)DM) += core/
obj-$(CONFIG_$(SPL_TPL_)GPIO_SUPPORT) += gpio/
obj-$(CONFIG_$(SPL_TPL_)DRIVERS_MISC_SUPPORT) += misc/ sysreset/ firmware/
obj-$(CONFIG_$(SPL_TPL_)I2C_SUPPORT) += i2c/
obj-$(CONFIG_$(SPL_TPL_)INPUT) += input/
obj-$(CONFIG_$(SPL_TPL_)LED) += led/
obj-$(CONFIG_$(SPL_TPL_)MMC_SUPPORT) += mmc/
obj-$(CONFIG_$(SPL_TPL_)NAND_SUPPORT) += mtd/nand/raw/
obj-$(CONFIG_$(SPL_TPL_)PCH_SUPPORT) += pch/
obj-$(CONFIG_$(SPL_TPL_)PCI_SUPPORT) += pci/
obj-$(CONFIG_$(SPL_TPL_)PHY) += phy/
obj-$(CONFIG_$(SPL_TPL_)PINCTRL) += pinctrl/
obj-$(CONFIG_$(SPL_TPL_)RAM) += ram/
obj-$(CONFIG_$(SPL_TPL_)RTC_SUPPORT) += rtc/
obj-$(CONFIG_$(SPL_TPL_)SERIAL_SUPPORT) += serial/
obj-$(CONFIG_$(SPL_TPL_)SPI_FLASH_SUPPORT) += mtd/spi/
obj-$(CONFIG_$(SPL_TPL_)SPI_SUPPORT) += spi/
@ -17,6 +22,7 @@ obj-$(CONFIG_$(SPL_TPL_)TIMER) += timer/
obj-$(CONFIG_$(SPL_TPL_)VIRTIO) += virtio/
obj-$(CONFIG_$(SPL_)DM_MAILBOX) += mailbox/
obj-$(CONFIG_$(SPL_)REMOTEPROC) += remoteproc/
obj-$(CONFIG_$(SPL_TPL_)TPM) += tpm/
ifndef CONFIG_TPL_BUILD
ifdef CONFIG_SPL_BUILD
@ -24,7 +30,6 @@ ifdef CONFIG_SPL_BUILD
obj-$(CONFIG_SPL_BOOTCOUNT_LIMIT) += bootcount/
obj-$(CONFIG_SPL_CPU_SUPPORT) += cpu/
obj-$(CONFIG_SPL_CRYPTO_SUPPORT) += crypto/
obj-$(CONFIG_SPL_GPIO_SUPPORT) += gpio/
obj-$(CONFIG_SPL_MPC8XXX_INIT_DDR_SUPPORT) += ddr/fsl/
obj-$(CONFIG_ARMADA_38X) += ddr/marvell/a38x/
obj-$(CONFIG_ARMADA_XP) += ddr/marvell/axp/
@ -40,9 +45,6 @@ obj-$(CONFIG_SPL_DMA_SUPPORT) += dma/
obj-$(CONFIG_SPL_ETH_SUPPORT) += net/
obj-$(CONFIG_SPL_ETH_SUPPORT) += net/phy/
obj-$(CONFIG_SPL_USB_ETHER) += net/phy/
obj-$(CONFIG_SPL_PCI_SUPPORT) += pci/
obj-$(CONFIG_SPL_PCH_SUPPORT) += pch/
obj-$(CONFIG_SPL_RTC_SUPPORT) += rtc/
obj-$(CONFIG_SPL_MUSB_NEW_SUPPORT) += usb/musb-new/
obj-$(CONFIG_SPL_USB_GADGET_SUPPORT) += usb/gadget/
obj-$(CONFIG_SPL_USB_GADGET_SUPPORT) += usb/gadget/udc/
@ -92,7 +94,6 @@ obj-y += scsi/
obj-y += sound/
obj-y += spmi/
obj-y += sysreset/
obj-y += tpm/
obj-y += video/
obj-y += watchdog/
obj-$(CONFIG_QE) += qe/

View file

@ -122,6 +122,13 @@ typedef struct global_data {
struct list_head log_head; /* List of struct log_device */
int log_fmt; /* Mask containing log format info */
#endif
#if CONFIG_IS_ENABLED(BLOBLIST)
struct bloblist_hdr *bloblist; /* Bloblist information */
struct bloblist_hdr *new_bloblist; /* Relocated blolist info */
# ifdef CONFIG_SPL
struct spl_handoff *spl_handoff;
# endif
#endif
} gd_t;
#endif

195
include/bloblist.h Normal file
View file

@ -0,0 +1,195 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* This provides a standard way of passing information between boot phases
* (TPL -> SPL -> U-Boot proper.)
*
* A list of blobs of data, tagged with their owner. The list resides in memory
* and can be updated by SPL, U-Boot, etc.
*
* Copyright 2018 Google, Inc
* Written by Simon Glass <sjg@chromium.org>
*/
#ifndef __BLOBLIST_H
#define __BLOBLIST_H
enum {
BLOBLIST_VERSION = 0,
BLOBLIST_MAGIC = 0xb00757a3,
BLOBLIST_ALIGN = 16,
};
enum bloblist_tag_t {
BLOBLISTT_NONE = 0,
/* Vendor-specific tags are permitted here */
BLOBLISTT_EC_HOSTEVENT, /* Chromium OS EC host-event mask */
BLOBLISTT_SPL_HANDOFF, /* Hand-off info from SPL */
BLOBLISTT_VBOOT_CTX, /* Chromium OS verified boot context */
BLOBLISTT_VBOOT_HANDOFF, /* Chromium OS internal handoff info */
};
/**
* struct bloblist_hdr - header for the bloblist
*
* This is stored at the start of the bloblist which is always on a 16-byte
* boundary. Records follow this header. The bloblist normally stays in the
* same place in memory as SPL and U-Boot execute, but it can be safely moved
* around.
*
* None of the bloblist structures contain pointers but it is possible to put
* pointers inside a bloblist record if desired. This is not encouraged,
* since it can make part of the bloblist inaccessible if the pointer is
* no-longer valid. It is better to just store all the data inside a bloblist
* record.
*
* Each bloblist record is aligned to a 16-byte boundary and follows immediately
* from the last.
*
* @version: BLOBLIST_VERSION
* @hdr_size: Size of this header, normally sizeof(struct bloblist_hdr). The
* first bloblist_rec starts at this offset from the start of the header
* @flags: Space for BLOBLISTF_... flags (none yet)
* @magic: BLOBLIST_MAGIC
* @size: Total size of all records (non-zero if valid) including this header.
* The bloblist extends for this many bytes from the start of this header.
* @alloced: Total size allocated for this bloblist. When adding new records,
* the bloblist can grow up to this size. This starts out as
* sizeof(bloblist_hdr) since we need at least that much space to store a
* valid bloblist
* @spare: Space space
* @chksum: CRC32 for the entire bloblist allocated area. Since any of the
* blobs can be altered after being created, this checksum is only valid
* when the bloblist is finalised before jumping to the next stage of boot.
* Note: @chksum is last to make it easier to exclude it from the checksum
* calculation.
*/
struct bloblist_hdr {
u32 version;
u32 hdr_size;
u32 flags;
u32 magic;
u32 size;
u32 alloced;
u32 spare;
u32 chksum;
};
/**
* struct bloblist_rec - record for the bloblist
*
* NOTE: Only exported for testing purposes. Do not use this struct.
*
* The bloblist contains a number of records each consisting of this record
* structure followed by the data contained. Each records is 16-byte aligned.
*
* @tag: Tag indicating what the record contains
* @hdr_size: Size of this header, normally sizeof(struct bloblist_rec). The
* record's data starts at this offset from the start of the record
* @size: Size of record in bytes, excluding the header size. This does not
* need to be aligned (e.g. 3 is OK).
* @spare: Spare space for other things
*/
struct bloblist_rec {
u32 tag;
u32 hdr_size;
u32 size;
u32 spare;
};
/**
* bloblist_find() - Find a blob
*
* Searches the bloblist and returns the blob with the matching tag
*
* @tag: Tag to search for (enum bloblist_tag_t)
* @size: Expected size of the blob
* @return pointer to blob if found, or NULL if not found, or a blob was found
* but it is the wrong size
*/
void *bloblist_find(uint tag, int size);
/**
* bloblist_add() - Add a new blob
*
* Add a new blob to the bloblist
*
* This should only be called if you konw there is no existing blob for a
* particular tag. It is typically safe to call in the first phase of U-Boot
* (e.g. TPL or SPL). After that, bloblist_ensure() should be used instead.
*
* @tag: Tag to add (enum bloblist_tag_t)
* @size: Size of the blob
* @return pointer to the newly added block, or NULL if there is not enough
* space for the blob
*/
void *bloblist_add(uint tag, int size);
/**
* bloblist_ensure_size() - Find or add a blob
*
* Find an existing blob, or add a new one if not found
*
* @tag: Tag to add (enum bloblist_tag_t)
* @size: Size of the blob
* @blobp: Returns a pointer to blob on success
* @return 0 if OK, -ENOSPC if it is missing and could not be added due to lack
* of space, or -ESPIPE it exists but has the wrong size
*/
int bloblist_ensure_size(uint tag, int size, void **blobp);
/**
* bloblist_ensure() - Find or add a blob
*
* Find an existing blob, or add a new one if not found
*
* @tag: Tag to add (enum bloblist_tag_t)
* @size: Size of the blob
* @return pointer to blob, or NULL if it is missing and could not be added due
* to lack of space, or it exists but has the wrong size
*/
void *bloblist_ensure(uint tag, int size);
/**
* bloblist_new() - Create a new, empty bloblist of a given size
*
* @addr: Address of bloblist
* @size: Initial size for bloblist
* @flags: Flags to use for bloblist
* @return 0 if OK, -EFAULT if addr is not aligned correctly, -ENOSPC is the
* area is not large enough
*/
int bloblist_new(ulong addr, uint size, uint flags);
/**
* bloblist_check() - Check if a bloblist exists
*
* @addr: Address of bloblist
* @size: Expected size of blobsize, or 0 to detect the size
* @return 0 if OK, -ENOENT if the magic number doesn't match (indicating that
* there problem is no bloblist at the given address), -EPROTONOSUPPORT
* if the version does not match, -EIO if the checksum does not match,
* -EFBIG if the expected size does not match the detected size
*/
int bloblist_check(ulong addr, uint size);
/**
* bloblist_finish() - Set up the bloblist for the next U-Boot part
*
* This sets the correct checksum for the bloblist. This ensures that the
* bloblist will be detected correctly by the next phase of U-Boot.
*
* @return 0
*/
int bloblist_finish(void);
/**
* bloblist_init() - Init the bloblist system with a single bloblist
*
* This uses CONFIG_BLOBLIST_ADDR and CONFIG_BLOBLIST_SIZE to set up a bloblist
* for use by U-Boot.
*/
int bloblist_init(void);
#endif /* __BLOBLIST_H */

36
include/handoff.h Normal file
View file

@ -0,0 +1,36 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Passing basic information from SPL to U-Boot proper
*
* Copyright 2018 Google, Inc
*/
#ifndef __HANDOFF_H
#define __HANDOFF_H
#if CONFIG_IS_ENABLED(HANDOFF)
#include <asm/handoff.h>
/**
* struct spl_handoff - information passed from SPL to U-Boot proper
*
* @ram_size: Value to use for gd->ram_size
*/
struct spl_handoff {
struct arch_spl_handoff arch;
u64 ram_size;
#ifdef CONFIG_NR_DRAM_BANKS
struct {
u64 start;
u64 size;
} ram_bank[CONFIG_NR_DRAM_BANKS];
#endif
};
void handoff_save_dram(struct spl_handoff *ho);
void handoff_load_dram_size(struct spl_handoff *ho);
void handoff_load_dram_banks(struct spl_handoff *ho);
#endif
#endif

View file

@ -48,6 +48,7 @@ enum log_category_t {
LOGC_EFI, /* EFI implementation */
LOGC_ALLOC, /* Memory allocation */
LOGC_SANDBOX, /* Related to the sandbox board */
LOGC_BLOBLIST, /* Bloblist */
LOGC_COUNT, /* Number of log categories */
LOGC_END, /* Sentinel value for a list of log categories */
@ -108,6 +109,8 @@ int _log(enum log_category_t cat, enum log_level_t level, const char *file,
#define log_io(_fmt...)
#endif
#if CONFIG_IS_ENABLED(LOG)
/* Emit a log record if the level is less that the maximum */
#define log(_cat, _level, _fmt, _args...) ({ \
int _l = _level; \
@ -116,6 +119,9 @@ int _log(enum log_category_t cat, enum log_level_t level, const char *file,
__func__, \
pr_fmt(_fmt), ##_args); \
})
#else
#define log(_cat, _level, _fmt, _args...)
#endif
#ifdef DEBUG
#define _DEBUG 1
@ -175,7 +181,16 @@ void __assert_fail(const char *assertion, const char *file, unsigned int line,
({ if (!(x) && _DEBUG) \
__assert_fail(#x, __FILE__, __LINE__, __func__); })
#ifdef CONFIG_LOG_ERROR_RETURN
#if CONFIG_IS_ENABLED(LOG) && defined(CONFIG_LOG_ERROR_RETURN)
/*
* Log an error return value, possibly with a message. Usage:
*
* return log_ret(fred_call());
*
* or:
*
* return log_msg_ret("fred failed", fred_call());
*/
#define log_ret(_ret) ({ \
int __ret = (_ret); \
if (__ret < 0) \
@ -190,8 +205,9 @@ void __assert_fail(const char *assertion, const char *file, unsigned int line,
__ret; \
})
#else
/* Non-logging versions of the above which just return the error code */
#define log_ret(_ret) (_ret)
#define log_msg_ret(_msg, _ret) (_ret)
#define log_msg_ret(_msg, _ret) ((void)(_msg), _ret)
#endif
/**

View file

@ -11,6 +11,7 @@
/* Platform-specific defines */
#include <linux/compiler.h>
#include <asm/spl.h>
#include <handoff.h>
/* Value in r0 indicates we booted from U-Boot */
#define UBOOT_NOT_LOADED_FROM_SPL 0x13578642
@ -21,6 +22,46 @@
#define MMCSD_MODE_FS 2
#define MMCSD_MODE_EMMCBOOT 3
/*
* u_boot_first_phase() - check if this is the first U-Boot phase
*
* U-Boot has up to three phases: TPL, SPL and U-Boot proper. Depending on the
* build flags we can determine whether the current build is for the first
* phase of U-Boot or not. If there is no SPL, then this is U-Boot proper. If
* there is SPL but no TPL, the the first phase is SPL. If there is TPL, then
* it is the first phase.
*
* @returns true if this is the first phase of U-Boot
*
*/
static inline bool u_boot_first_phase(void)
{
if (IS_ENABLED(CONFIG_TPL)) {
if (IS_ENABLED(CONFIG_TPL_BUILD))
return true;
} else if (IS_ENABLED(CONFIG_SPL)) {
if (IS_ENABLED(CONFIG_SPL_BUILD))
return true;
} else {
return true;
}
return false;
}
/* A string name for SPL or TPL */
#ifdef CONFIG_SPL_BUILD
# ifdef CONFIG_TPL_BUILD
# define SPL_TPL_NAME "tpl"
# else
# define SPL_TPL_NAME "spl"
# endif
# define SPL_TPL_PROMPT SPL_TPL_NAME ": "
#else
# define SPL_TPL_NAME ""
# define SPL_TPL_PROMPT ""
#endif
struct spl_image_info {
const char *name;
u8 os;

View file

@ -23,6 +23,7 @@ struct unit_test;
int cmd_ut_category(const char *name, struct unit_test *tests, int n_ents,
int argc, char * const argv[]);
int do_ut_bloblist(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]);
int do_ut_compression(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]);
int do_ut_dm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
int do_ut_env(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);

View file

@ -2,6 +2,7 @@
#
# (C) Copyright 2012 The Chromium Authors
obj-$(CONFIG_SANDBOX) += bloblist.o
obj-$(CONFIG_UNIT_TEST) += cmd_ut.o
obj-$(CONFIG_UNIT_TEST) += ut.o
obj-$(CONFIG_SANDBOX) += command_ut.o

187
test/bloblist.c Normal file
View file

@ -0,0 +1,187 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (c) 2018, Google Inc. All rights reserved.
*/
#include <common.h>
#include <bloblist.h>
#include <log.h>
#include <mapmem.h>
#include <test/suites.h>
#include <test/test.h>
#include <test/ut.h>
DECLARE_GLOBAL_DATA_PTR;
/* Declare a new compression test */
#define BLOBLIST_TEST(_name, _flags) \
UNIT_TEST(_name, _flags, bloblist_test)
enum {
TEST_TAG = 1,
TEST_TAG2 = 2,
TEST_TAG_MISSING = 3,
TEST_SIZE = 10,
TEST_SIZE2 = 20,
TEST_ADDR = CONFIG_BLOBLIST_ADDR,
TEST_BLOBLIST_SIZE = 0x100,
};
static struct bloblist_hdr *clear_bloblist(void)
{
struct bloblist_hdr *hdr;
/* Clear out any existing bloblist so we have a clean slate */
hdr = map_sysmem(CONFIG_BLOBLIST_ADDR, TEST_BLOBLIST_SIZE);
memset(hdr, '\0', TEST_BLOBLIST_SIZE);
return hdr;
}
static int bloblist_test_init(struct unit_test_state *uts)
{
struct bloblist_hdr *hdr;
hdr = clear_bloblist();
ut_asserteq(-ENOENT, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
hdr->version++;
ut_asserteq(-EPROTONOSUPPORT, bloblist_check(TEST_ADDR,
TEST_BLOBLIST_SIZE));
ut_asserteq(-ENOSPC, bloblist_new(TEST_ADDR, 0x10, 0));
ut_asserteq(-EFAULT, bloblist_new(1, TEST_BLOBLIST_SIZE, 0));
ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
ut_assertok(bloblist_finish());
ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
hdr->flags++;
ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
return 1;
}
BLOBLIST_TEST(bloblist_test_init, 0);
static int bloblist_test_blob(struct unit_test_state *uts)
{
struct bloblist_hdr *hdr;
struct bloblist_rec *rec, *rec2;
char *data;
/* At the start there should be no records */
hdr = clear_bloblist();
ut_assertnull(bloblist_find(TEST_TAG, TEST_BLOBLIST_SIZE));
ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
/* Add a record and check that we can find it */
data = bloblist_add(TEST_TAG, TEST_SIZE);
rec = (void *)(hdr + 1);
ut_asserteq_ptr(rec + 1, data);
data = bloblist_find(TEST_TAG, TEST_SIZE);
ut_asserteq_ptr(rec + 1, data);
/* Check the 'ensure' method */
ut_asserteq_ptr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
ut_assertnull(bloblist_ensure(TEST_TAG, TEST_SIZE2));
rec2 = (struct bloblist_rec *)(data + ALIGN(TEST_SIZE, BLOBLIST_ALIGN));
/* Check for a non-existent record */
ut_asserteq_ptr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
ut_asserteq_ptr(rec2 + 1, bloblist_ensure(TEST_TAG2, TEST_SIZE2));
ut_assertnull(bloblist_find(TEST_TAG_MISSING, 0));
return 0;
}
BLOBLIST_TEST(bloblist_test_blob, 0);
static int bloblist_test_bad_blob(struct unit_test_state *uts)
{
struct bloblist_hdr *hdr;
void *data;
hdr = clear_bloblist();
ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
data = hdr + 1;
data += sizeof(struct bloblist_rec);
ut_asserteq_ptr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
ut_asserteq_ptr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
return 0;
}
BLOBLIST_TEST(bloblist_test_bad_blob, 0);
static int bloblist_test_checksum(struct unit_test_state *uts)
{
struct bloblist_hdr *hdr;
char *data, *data2;
hdr = clear_bloblist();
ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
ut_assertok(bloblist_finish());
ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
/*
* Now change things amd make sure that the checksum notices. We cannot
* change the size or alloced fields, since that will crash the code.
* It has to rely on these being correct.
*/
hdr->flags--;
ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
hdr->flags++;
hdr->size--;
ut_asserteq(-EFBIG, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
hdr->size++;
hdr->spare++;
ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
hdr->spare--;
hdr->chksum++;
ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
hdr->chksum--;
/* Make sure the checksum changes when we add blobs */
data = bloblist_add(TEST_TAG, TEST_SIZE);
ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
data2 = bloblist_add(TEST_TAG2, TEST_SIZE2);
ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
ut_assertok(bloblist_finish());
/* It should also change if we change the data */
ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
*data += 1;
ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
*data -= 1;
ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
*data2 += 1;
ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
*data2 -= 1;
/*
* Changing data outside the range of valid data should not affect
* the checksum.
*/
ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
data[TEST_SIZE]++;
data2[TEST_SIZE2]++;
ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
return 0;
}
BLOBLIST_TEST(bloblist_test_checksum, 0);
int do_ut_bloblist(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
{
struct unit_test *tests = ll_entry_start(struct unit_test,
bloblist_test);
const int n_ents = ll_entry_count(struct unit_test, bloblist_test);
return cmd_ut_category("bloblist", tests, n_ents, argc, argv);
}

View file

@ -55,6 +55,8 @@ static cmd_tbl_t cmd_ut_sub[] = {
#ifdef CONFIG_SANDBOX
U_BOOT_CMD_MKENT(compression, CONFIG_SYS_MAXARGS, 1, do_ut_compression,
"", ""),
U_BOOT_CMD_MKENT(bloblist, CONFIG_SYS_MAXARGS, 1, do_ut_bloblist,
"", ""),
#endif
};
@ -97,6 +99,7 @@ static int do_ut(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
static char ut_help_text[] =
"all - execute all enabled tests\n"
#ifdef CONFIG_SANDBOX
"ut bloblist - Test bloblist implementation\n"
"ut compression - Test compressors and bootm decompression\n"
#endif
#ifdef CONFIG_UT_DM

View file

@ -79,7 +79,7 @@ static int dm_test_spi_flash_func(struct unit_test_state *uts)
* benefit is worth the extra complexity.
*/
ut_asserteq(0, run_command_list(
"sb save hostfs - 0 spi.bin 200000;"
"host save hostfs - 0 spi.bin 200000;"
"sf probe;"
"sf test 0 10000", -1, 0));
/*

View file

@ -194,7 +194,7 @@ function test_image() {
;;
sb)
PREFIX="sb "
PREFIX="host "
WRITE="save"
SUFFIX="fs -"
;;
@ -217,11 +217,11 @@ function test_image() {
# In u-boot commands, <interface> stands for host or hostfs
# hostfs maps to the host fs.
# host maps to the "sb bind" that we do
# host maps to the "host bind" that we do
$UBOOT << EOF
sb=$5
setenv bind 'if test "\$sb" != sb; then sb bind 0 "$1"; fi'
setenv bind 'if test "\$sb" != sb; then host bind 0 "$1"; fi'
run bind
# Test Case 1 - ls
${PREFIX}ls host${SUFFIX} $6
@ -229,7 +229,7 @@ ${PREFIX}ls host${SUFFIX} $6
${PREFIX}ls host${SUFFIX} invalid_d
#
# We want ${PREFIX}size host 0:0 $3 for host commands and
# sb size hostfs - $3 for hostfs commands.
# host size hostfs - $3 for hostfs commands.
# 1MB is 0x0010 0000
# Test Case 2a - size of small file
${PREFIX}size host${SUFFIX} ${FPATH}$FILE_SMALL
@ -575,7 +575,7 @@ TOTAL_PASS=0
# In each loop, for a given file system image, we test both the
# fs command, like load/size/write, the file system specific command
# like: ext4load/ext4size/ext4write and the sb load/ls/save commands.
# like: ext4load/ext4size/ext4write and the host load/ls/save commands.
for fs in ext4 fat16 fat32; do
echo "Creating $fs image if not already present."
@ -583,11 +583,11 @@ for fs in ext4 fat16 fat32; do
MD5_FILE_FS="${MD5_FILE}.${fs}"
create_image $IMAGE $fs
# sb commands test
# host commands test
echo "Creating files in $fs image if not already present."
create_files $IMAGE $MD5_FILE_FS
# Lets mount the image and test sb hostfs commands
# Lets mount the image and test host hostfs commands
mkdir -p "$MOUNT_DIR"
case "$fs" in
fat*)

View file

@ -99,15 +99,15 @@ base_fdt = '''
# then run the 'bootm' command, then save out memory from the places where
# we expect 'bootm' to write things. Then quit.
base_script = '''
sb load hostfs 0 %(fit_addr)x %(fit)s
host load hostfs 0 %(fit_addr)x %(fit)s
fdt addr %(fit_addr)x
bootm start %(fit_addr)x
bootm loados
sb save hostfs 0 %(kernel_addr)x %(kernel_out)s %(kernel_size)x
sb save hostfs 0 %(fdt_addr)x %(fdt_out)s %(fdt_size)x
sb save hostfs 0 %(ramdisk_addr)x %(ramdisk_out)s %(ramdisk_size)x
sb save hostfs 0 %(loadables1_addr)x %(loadables1_out)s %(loadables1_size)x
sb save hostfs 0 %(loadables2_addr)x %(loadables2_out)s %(loadables2_size)x
host save hostfs 0 %(kernel_addr)x %(kernel_out)s %(kernel_size)x
host save hostfs 0 %(fdt_addr)x %(fdt_out)s %(fdt_size)x
host save hostfs 0 %(ramdisk_addr)x %(ramdisk_out)s %(ramdisk_size)x
host save hostfs 0 %(loadables1_addr)x %(loadables1_out)s %(loadables1_size)x
host save hostfs 0 %(loadables2_addr)x %(loadables2_out)s %(loadables2_size)x
'''
@pytest.mark.boardspec('sandbox')

View file

@ -0,0 +1,15 @@
# SPDX-License-Identifier: GPL-2.0+
# Copyright (c) 2016 Google, Inc
import pytest
# Magic number to check that SPL handoff is working
TEST_HANDOFF_MAGIC = 0x14f93c7b
@pytest.mark.boardspec('sandbox')
@pytest.mark.buildconfigspec('spl')
def test_handoff(u_boot_console):
"""Test that of-platdata can be generated and used in sandbox"""
cons = u_boot_console
response = cons.run_command('sb handoff')
assert ('SPL handoff magic %x' % TEST_HANDOFF_MAGIC) in response

View file

@ -3,11 +3,40 @@
import pytest
OF_PLATDATA_OUTPUT = ''
OF_PLATDATA_OUTPUT = '''
of-platdata probe:
bool 1
byte 05
bytearray 06 00 00
int 1
intarray 2 3 4 0
longbytearray 09 0a 0b 0c 0d 0e 0f 10 11
string message
stringarray "multi-word" "message" ""
of-platdata probe:
bool 0
byte 08
bytearray 01 23 34
int 3
intarray 5 0 0 0
longbytearray 09 00 00 00 00 00 00 00 00
string message2
stringarray "another" "multi-word" "message"
of-platdata probe:
bool 0
byte 00
bytearray 00 00 00
int 0
intarray 0 0 0 0
longbytearray 00 00 00 00 00 00 00 00 00
string <NULL>
stringarray "one" "" ""
'''
@pytest.mark.buildconfigspec('spl_of_platdata')
def test_ofplatdata(u_boot_console):
"""Test that of-platdata can be generated and used in sandbox"""
cons = u_boot_console
cons.restart_uboot_with_flags(['--show_of_platdata'])
output = cons.get_spawn_output().replace('\r', '')
assert OF_PLATDATA_OUTPUT in output

View file

@ -74,7 +74,7 @@ def test_vboot(u_boot_console):
cons.restart_uboot()
with cons.log.section('Verified boot %s %s' % (sha_algo, test_type)):
output = cons.run_command_list(
['sb load hostfs - 100 %stest.fit' % tmpdir,
['host load hostfs - 100 %stest.fit' % tmpdir,
'fdt addr 100',
'bootm 100'])
assert(expect_string in ''.join(output))

View file

@ -16,7 +16,7 @@ import sys
import u_boot_spawn
# Regexes for text we expect U-Boot to send to the console.
pattern_u_boot_spl_signon = re.compile('(U-Boot SPL \\d{4}\\.\\d{2}[^\r\n]*\\))')
pattern_u_boot_spl_signon = re.compile('(U-Boot spl \\d{4}\\.\\d{2}[^\r\n]*\\))')
pattern_u_boot_main_signon = re.compile('(U-Boot \\d{4}\\.\\d{2}[^\r\n]*\\))')
pattern_stop_autoboot_prompt = re.compile('Hit any key to stop autoboot: ')
pattern_unknown_command = re.compile('Unknown command \'.*\' - try \'help\'')

View file

@ -24,6 +24,7 @@ class ConsoleSandbox(ConsoleBase):
"""
super(ConsoleSandbox, self).__init__(log, config, max_fifo_fill=1024)
self.sandbox_flags = []
def get_spawn(self):
"""Connect to a fresh U-Boot instance.
@ -51,8 +52,25 @@ class ConsoleSandbox(ConsoleBase):
'-d',
self.config.dtb
]
cmd += self.sandbox_flags
return Spawn(cmd, cwd=self.config.source_dir)
def restart_uboot_with_flags(self, flags):
"""Run U-Boot with the given command-line flags
Args:
flags: List of flags to pass, each a string
Returns:
A u_boot_spawn.Spawn object that is attached to U-Boot.
"""
try:
self.sandbox_flags = flags
return self.restart_uboot()
finally:
self.sandbox_flags = []
def kill(self, sig):
"""Send a specific Unix signal to the sandbox process.

View file

@ -19,7 +19,7 @@ run_test "sandbox" ./test/py/test.py --bd sandbox --build
# Run tests which require sandbox_spl
run_test "sandbox_spl" ./test/py/test.py --bd sandbox_spl --build \
-k test_ofplatdata.py
-k 'test_ofplatdata or test_handoff'
# Run tests for the flat-device-tree version of sandbox. This is a special
# build which does not enable CONFIG_OF_LIVE for the live device tree, so we can