mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-17 02:08:38 +00:00
Merge branch '2018-11-25-master-imports'
- Bring in the series from Simon for SPL logging support and bloblist
This commit is contained in:
commit
6b21502229
44 changed files with 1524 additions and 114 deletions
|
@ -91,6 +91,7 @@ config SANDBOX
|
||||||
select SPI
|
select SPI
|
||||||
select SUPPORT_OF_CONTROL
|
select SUPPORT_OF_CONTROL
|
||||||
imply BITREVERSE
|
imply BITREVERSE
|
||||||
|
select BLOBLIST
|
||||||
imply CMD_DM
|
imply CMD_DM
|
||||||
imply CMD_GETTIME
|
imply CMD_GETTIME
|
||||||
imply CMD_HASH
|
imply CMD_HASH
|
||||||
|
|
|
@ -8,7 +8,4 @@
|
||||||
|
|
||||||
#define BOOT_DEVICE_NOR 1
|
#define BOOT_DEVICE_NOR 1
|
||||||
|
|
||||||
/* Linker symbols */
|
|
||||||
extern char __bss_start[], __bss_end[];
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <netinet/ip.h>
|
#include <netinet/ip.h>
|
||||||
#include <netinet/udp.h>
|
#include <netinet/udp.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -23,6 +24,8 @@
|
||||||
#include <linux/if_ether.h>
|
#include <linux/if_ether.h>
|
||||||
#include <linux/if_packet.h>
|
#include <linux/if_packet.h>
|
||||||
|
|
||||||
|
#include <os.h>
|
||||||
|
|
||||||
struct sandbox_eth_raw_if_nameindex *sandbox_eth_raw_if_nameindex(void)
|
struct sandbox_eth_raw_if_nameindex *sandbox_eth_raw_if_nameindex(void)
|
||||||
{
|
{
|
||||||
return (struct sandbox_eth_raw_if_nameindex *)if_nameindex();
|
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 */
|
/* Prepare device struct */
|
||||||
priv->local_bind_sd = -1;
|
priv->local_bind_sd = -1;
|
||||||
priv->device = malloc(sizeof(struct sockaddr_ll));
|
priv->device = os_malloc(sizeof(struct sockaddr_ll));
|
||||||
if (priv->device == NULL)
|
if (priv->device == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
device = priv->device;
|
device = priv->device;
|
||||||
|
@ -144,7 +147,7 @@ static int _local_inet_start(struct eth_sandbox_raw_priv *priv)
|
||||||
/* Prepare device struct */
|
/* Prepare device struct */
|
||||||
priv->local_bind_sd = -1;
|
priv->local_bind_sd = -1;
|
||||||
priv->local_bind_udp_port = 0;
|
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)
|
if (priv->device == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
device = priv->device;
|
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)
|
void sandbox_eth_raw_os_stop(struct eth_sandbox_raw_priv *priv)
|
||||||
{
|
{
|
||||||
free(priv->device);
|
os_free(priv->device);
|
||||||
priv->device = NULL;
|
priv->device = NULL;
|
||||||
close(priv->sd);
|
close(priv->sd);
|
||||||
priv->sd = -1;
|
priv->sd = -1;
|
||||||
|
|
|
@ -381,7 +381,7 @@ void os_dirent_free(struct os_dirent_node *node)
|
||||||
|
|
||||||
while (node) {
|
while (node) {
|
||||||
next = node->next;
|
next = node->next;
|
||||||
free(node);
|
os_free(node);
|
||||||
node = next;
|
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 */
|
/* Create a buffer upfront, with typically sufficient size */
|
||||||
dirlen = strlen(dirname) + 2;
|
dirlen = strlen(dirname) + 2;
|
||||||
len = dirlen + 256;
|
len = dirlen + 256;
|
||||||
fname = malloc(len);
|
fname = os_malloc(len);
|
||||||
if (!fname) {
|
if (!fname) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto done;
|
goto done;
|
||||||
|
@ -419,7 +419,7 @@ int os_dirent_ls(const char *dirname, struct os_dirent_node **headp)
|
||||||
ret = errno;
|
ret = errno;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
next = malloc(sizeof(*node) + strlen(entry->d_name) + 1);
|
next = os_malloc(sizeof(*node) + strlen(entry->d_name) + 1);
|
||||||
if (!next) {
|
if (!next) {
|
||||||
os_dirent_free(head);
|
os_dirent_free(head);
|
||||||
ret = -ENOMEM;
|
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) {
|
if (dirlen + strlen(entry->d_name) > len) {
|
||||||
len = dirlen + strlen(entry->d_name);
|
len = dirlen + strlen(entry->d_name);
|
||||||
old_fname = fname;
|
old_fname = fname;
|
||||||
fname = realloc(fname, len);
|
fname = os_realloc(fname, len);
|
||||||
if (!fname) {
|
if (!fname) {
|
||||||
free(old_fname);
|
os_free(old_fname);
|
||||||
free(next);
|
os_free(next);
|
||||||
os_dirent_free(head);
|
os_dirent_free(head);
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto done;
|
goto done;
|
||||||
|
@ -465,7 +465,7 @@ int os_dirent_ls(const char *dirname, struct os_dirent_node **headp)
|
||||||
|
|
||||||
done:
|
done:
|
||||||
closedir(dir);
|
closedir(dir);
|
||||||
free(fname);
|
os_free(fname);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -563,20 +563,48 @@ static int make_exec(char *fname, const void *data, int size)
|
||||||
return 0;
|
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;
|
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) {
|
if (!argv) {
|
||||||
printf("Out of memory for %d argv\n", count);
|
printf("Out of memory for %d argv\n", count);
|
||||||
return -ENOMEM;
|
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 *));
|
memcpy(argv + argc, add_args, count * sizeof(char *));
|
||||||
argv[argc + count] = NULL;
|
argv[argc + count] = NULL;
|
||||||
|
|
||||||
|
@ -584,21 +612,27 @@ static int add_args(char ***argvp, const char *add_args[], int count)
|
||||||
return 0;
|
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();
|
struct sandbox_state *state = state_get_current();
|
||||||
char fname[30], mem_fname[30];
|
char mem_fname[30];
|
||||||
int fd, err;
|
int fd, err;
|
||||||
const char *extra_args[5];
|
char *extra_args[5];
|
||||||
char **argv = state->argv;
|
char **argv = state->argv;
|
||||||
|
int argc;
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
int argc, i;
|
int i;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
err = make_exec(fname, dest, size);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
strcpy(mem_fname, "/tmp/u-boot.mem.XXXXXX");
|
strcpy(mem_fname, "/tmp/u-boot.mem.XXXXXX");
|
||||||
fd = mkstemp(mem_fname);
|
fd = mkstemp(mem_fname);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
|
@ -611,14 +645,16 @@ int os_jump_to_image(const void *dest, int size)
|
||||||
os_fd_restore();
|
os_fd_restore();
|
||||||
|
|
||||||
extra_args[0] = "-j";
|
extra_args[0] = "-j";
|
||||||
extra_args[1] = fname;
|
extra_args[1] = (char *)fname;
|
||||||
extra_args[2] = "-m";
|
extra_args[2] = "-m";
|
||||||
extra_args[3] = mem_fname;
|
extra_args[3] = mem_fname;
|
||||||
extra_args[4] = "--rm_memory";
|
argc = 4;
|
||||||
err = add_args(&argv, extra_args,
|
if (state->ram_buf_rm)
|
||||||
sizeof(extra_args) / sizeof(extra_args[0]));
|
extra_args[argc++] = "--rm_memory";
|
||||||
|
err = add_args(&argv, extra_args, argc);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
argv[0] = (char *)fname;
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
for (i = 0; argv[i]; i++)
|
for (i = 0; argv[i]; i++)
|
||||||
|
@ -629,11 +665,26 @@ int os_jump_to_image(const void *dest, int size)
|
||||||
os_exit(2);
|
os_exit(2);
|
||||||
|
|
||||||
err = execv(fname, argv);
|
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)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
return unlink(fname);
|
return os_jump_to_file(fname);
|
||||||
}
|
}
|
||||||
|
|
||||||
int os_find_u_boot(char *fname, int maxlen)
|
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)
|
int os_spl_to_uboot(const char *fname)
|
||||||
{
|
{
|
||||||
struct sandbox_state *state = state_get_current();
|
return os_jump_to_file(fname);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void os_localtime(struct rtc_time *rt)
|
void os_localtime(struct rtc_time *rt)
|
||||||
|
|
|
@ -37,12 +37,39 @@ static int spl_board_load_image(struct spl_image_info *spl_image,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Hopefully this will not return */
|
/* Set up spl_image to boot from jump_to_image_no_args() */
|
||||||
return os_spl_to_uboot(fname);
|
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);
|
SPL_LOAD_IMAGE_METHOD("sandbox", 0, BOOT_DEVICE_BOARD, spl_board_load_image);
|
||||||
|
|
||||||
void spl_board_init(void)
|
void spl_board_init(void)
|
||||||
{
|
{
|
||||||
|
struct sandbox_state *state = state_get_current();
|
||||||
|
struct udevice *dev;
|
||||||
|
|
||||||
preloader_console_init();
|
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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -283,6 +283,15 @@ static int sandbox_cmdline_cb_log_level(struct sandbox_state *state,
|
||||||
SANDBOX_CMDLINE_OPT_SHORT(log_level, 'L', 1,
|
SANDBOX_CMDLINE_OPT_SHORT(log_level, 'L', 1,
|
||||||
"Set log level (0=panic, 7=debug)");
|
"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)
|
int board_run_command(const char *cmdline)
|
||||||
{
|
{
|
||||||
printf("## Commands are disabled. Please enable CONFIG_CMDLINE.\n");
|
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;
|
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[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
struct sandbox_state *state;
|
struct sandbox_state *state;
|
||||||
|
|
|
@ -14,7 +14,7 @@ SECTIONS
|
||||||
}
|
}
|
||||||
|
|
||||||
__u_boot_sandbox_option_start = .;
|
__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 = .;
|
__u_boot_sandbox_option_end = .;
|
||||||
|
|
||||||
__bss_start = .;
|
__bss_start = .;
|
||||||
|
|
18
arch/sandbox/include/asm/handoff.h
Normal file
18
arch/sandbox/include/asm/handoff.h
Normal 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
|
|
@ -89,6 +89,7 @@ struct sandbox_state {
|
||||||
bool skip_delays; /* Ignore any time delays (for test) */
|
bool skip_delays; /* Ignore any time delays (for test) */
|
||||||
bool show_test_output; /* Don't suppress stdout in tests */
|
bool show_test_output; /* Don't suppress stdout in tests */
|
||||||
int default_log_level; /* Default log level for sandbox */
|
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 */
|
/* Pointer to information for each SPI bus/cs */
|
||||||
struct sandbox_spi_info spi[CONFIG_SANDBOX_SPI_MAX_BUS]
|
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);
|
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
|
* Initialize the test system state
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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
|
Note that many of these tests are implemented as commands which you can
|
||||||
run natively on your board if desired (and enabled).
|
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>
|
Simon Glass <sjg@chromium.org>
|
||||||
|
|
|
@ -115,6 +115,7 @@ obj-$(CONFIG_CMD_ROCKUSB) += rockusb.o
|
||||||
obj-$(CONFIG_SANDBOX) += host.o
|
obj-$(CONFIG_SANDBOX) += host.o
|
||||||
obj-$(CONFIG_CMD_SATA) += sata.o
|
obj-$(CONFIG_CMD_SATA) += sata.o
|
||||||
obj-$(CONFIG_CMD_NVME) += nvme.o
|
obj-$(CONFIG_CMD_NVME) += nvme.o
|
||||||
|
obj-$(CONFIG_SANDBOX) += sb.o
|
||||||
obj-$(CONFIG_CMD_SF) += sf.o
|
obj-$(CONFIG_CMD_SF) += sf.o
|
||||||
obj-$(CONFIG_CMD_SCSI) += scsi.o disk.o
|
obj-$(CONFIG_CMD_SCSI) += scsi.o disk.o
|
||||||
obj-$(CONFIG_CMD_SHA1SUM) += sha1sum.o
|
obj-$(CONFIG_CMD_SHA1SUM) += sha1sum.o
|
||||||
|
|
|
@ -167,11 +167,6 @@ static int do_host(cmd_tbl_t *cmdtp, int flag, int argc,
|
||||||
return CMD_RET_USAGE;
|
return CMD_RET_USAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
U_BOOT_CMD(
|
|
||||||
sb, 8, 1, do_host,
|
|
||||||
"Deprecated: use 'host' command instead.", ""
|
|
||||||
);
|
|
||||||
|
|
||||||
U_BOOT_CMD(
|
U_BOOT_CMD(
|
||||||
host, 8, 1, do_host,
|
host, 8, 1, do_host,
|
||||||
"Miscellaneous host commands",
|
"Miscellaneous host commands",
|
||||||
|
|
65
cmd/sb.c
Normal file
65
cmd/sb.c
Normal 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"
|
||||||
|
);
|
|
@ -299,6 +299,10 @@ config SPL_LOGLEVEL
|
||||||
int
|
int
|
||||||
default LOGLEVEL
|
default LOGLEVEL
|
||||||
|
|
||||||
|
config TPL_LOGLEVEL
|
||||||
|
int
|
||||||
|
default LOGLEVEL
|
||||||
|
|
||||||
config SILENT_CONSOLE
|
config SILENT_CONSOLE
|
||||||
bool "Support a silent console"
|
bool "Support a silent console"
|
||||||
help
|
help
|
||||||
|
@ -505,6 +509,24 @@ config SPL_LOG_MAX_LEVEL
|
||||||
6 - detail
|
6 - detail
|
||||||
7 - debug
|
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
|
config LOG_CONSOLE
|
||||||
bool "Allow log output to the console"
|
bool "Allow log output to the console"
|
||||||
depends on LOG
|
depends on LOG
|
||||||
|
@ -515,9 +537,19 @@ config LOG_CONSOLE
|
||||||
log message is shown - other details like level, category, file and
|
log message is shown - other details like level, category, file and
|
||||||
line number are omitted.
|
line number are omitted.
|
||||||
|
|
||||||
config LOG_SPL_CONSOLE
|
config SPL_LOG_CONSOLE
|
||||||
bool "Allow log output to the console in SPL"
|
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
|
default y
|
||||||
help
|
help
|
||||||
Enables a log driver which writes log records to the console.
|
Enables a log driver which writes log records to the console.
|
||||||
|
@ -718,4 +750,52 @@ config UPDATE_TFTP_MSEC_MAX
|
||||||
|
|
||||||
endmenu
|
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"
|
source "common/spl/Kconfig"
|
||||||
|
|
|
@ -61,6 +61,7 @@ obj-$(CONFIG_CMDLINE) += cli_readline.o cli_simple.o
|
||||||
endif # !CONFIG_SPL_BUILD
|
endif # !CONFIG_SPL_BUILD
|
||||||
|
|
||||||
obj-$(CONFIG_$(SPL_TPL_)BOOTSTAGE) += bootstage.o
|
obj-$(CONFIG_$(SPL_TPL_)BOOTSTAGE) += bootstage.o
|
||||||
|
obj-$(CONFIG_$(SPL_TPL_)BLOBLIST) += bloblist.o
|
||||||
|
|
||||||
ifdef CONFIG_SPL_BUILD
|
ifdef CONFIG_SPL_BUILD
|
||||||
ifdef CONFIG_SPL_DFU_SUPPORT
|
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_FSL_DDR_INTERACTIVE) += cli_simple.o cli_readline.o
|
||||||
obj-$(CONFIG_DFU_OVER_USB) += dfu.o
|
obj-$(CONFIG_DFU_OVER_USB) += dfu.o
|
||||||
obj-y += command.o
|
obj-y += command.o
|
||||||
obj-$(CONFIG_$(SPL_)LOG) += log.o
|
obj-$(CONFIG_$(SPL_TPL_)LOG) += log.o
|
||||||
obj-$(CONFIG_$(SPL_)LOG_CONSOLE) += log_console.o
|
obj-$(CONFIG_$(SPL_TPL_)LOG_CONSOLE) += log_console.o
|
||||||
obj-y += s_record.o
|
obj-y += s_record.o
|
||||||
obj-$(CONFIG_CMD_LOADB) += xyzModem.o
|
obj-$(CONFIG_CMD_LOADB) += xyzModem.o
|
||||||
obj-$(CONFIG_$(SPL_TPL_)YMODEM_SUPPORT) += xyzModem.o
|
obj-$(CONFIG_$(SPL_TPL_)YMODEM_SUPPORT) += xyzModem.o
|
||||||
|
|
239
common/bloblist.c
Normal file
239
common/bloblist.c
Normal 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;
|
||||||
|
}
|
|
@ -10,6 +10,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <common.h>
|
#include <common.h>
|
||||||
|
#include <bloblist.h>
|
||||||
#include <console.h>
|
#include <console.h>
|
||||||
#include <cpu.h>
|
#include <cpu.h>
|
||||||
#include <dm.h>
|
#include <dm.h>
|
||||||
|
@ -24,6 +25,9 @@
|
||||||
#include <post.h>
|
#include <post.h>
|
||||||
#include <relocate.h>
|
#include <relocate.h>
|
||||||
#include <spi.h>
|
#include <spi.h>
|
||||||
|
#ifdef CONFIG_SPL
|
||||||
|
#include <spl.h>
|
||||||
|
#endif
|
||||||
#include <status_led.h>
|
#include <status_led.h>
|
||||||
#include <sysreset.h>
|
#include <sysreset.h>
|
||||||
#include <timer.h>
|
#include <timer.h>
|
||||||
|
@ -285,6 +289,17 @@ static int setup_mon_len(void)
|
||||||
return 0;
|
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)
|
__weak int arch_cpu_init(void)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -560,6 +575,16 @@ static int reserve_stacks(void)
|
||||||
return arch_reserve_stacks();
|
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)
|
static int display_new_sp(void)
|
||||||
{
|
{
|
||||||
debug("New Stack Pointer is: %08lx\n", gd->start_addr_sp);
|
debug("New Stack Pointer is: %08lx\n", gd->start_addr_sp);
|
||||||
|
@ -666,6 +691,24 @@ static int reloc_bootstage(void)
|
||||||
return 0;
|
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)
|
static int setup_reloc(void)
|
||||||
{
|
{
|
||||||
if (gd->flags & GD_FLG_SKIP_RELOC) {
|
if (gd->flags & GD_FLG_SKIP_RELOC) {
|
||||||
|
@ -813,6 +856,10 @@ static const init_fnc_t init_sequence_f[] = {
|
||||||
initf_malloc,
|
initf_malloc,
|
||||||
log_init,
|
log_init,
|
||||||
initf_bootstage, /* uses its own timer, so does not need DM */
|
initf_bootstage, /* uses its own timer, so does not need DM */
|
||||||
|
#ifdef CONFIG_BLOBLIST
|
||||||
|
bloblist_init,
|
||||||
|
#endif
|
||||||
|
setup_spl_handoff,
|
||||||
initf_console_record,
|
initf_console_record,
|
||||||
#if defined(CONFIG_HAVE_FSP)
|
#if defined(CONFIG_HAVE_FSP)
|
||||||
arch_fsp_init,
|
arch_fsp_init,
|
||||||
|
@ -913,6 +960,7 @@ static const init_fnc_t init_sequence_f[] = {
|
||||||
reserve_global_data,
|
reserve_global_data,
|
||||||
reserve_fdt,
|
reserve_fdt,
|
||||||
reserve_bootstage,
|
reserve_bootstage,
|
||||||
|
reserve_bloblist,
|
||||||
reserve_arch,
|
reserve_arch,
|
||||||
reserve_stacks,
|
reserve_stacks,
|
||||||
dram_init_banksize,
|
dram_init_banksize,
|
||||||
|
@ -932,6 +980,7 @@ static const init_fnc_t init_sequence_f[] = {
|
||||||
INIT_FUNC_WATCHDOG_RESET
|
INIT_FUNC_WATCHDOG_RESET
|
||||||
reloc_fdt,
|
reloc_fdt,
|
||||||
reloc_bootstage,
|
reloc_bootstage,
|
||||||
|
reloc_bloblist,
|
||||||
setup_reloc,
|
setup_reloc,
|
||||||
#if defined(CONFIG_X86) || defined(CONFIG_ARC)
|
#if defined(CONFIG_X86) || defined(CONFIG_ARC)
|
||||||
copy_uboot_to_ram,
|
copy_uboot_to_ram,
|
||||||
|
|
|
@ -535,6 +535,13 @@ void putc(const char c)
|
||||||
|
|
||||||
void puts(const char *s)
|
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
|
#ifdef CONFIG_DEBUG_UART
|
||||||
if (!gd || !(gd->flags & GD_FLG_SERIAL_READY)) {
|
if (!gd || !(gd->flags & GD_FLG_SERIAL_READY)) {
|
||||||
while (*s) {
|
while (*s) {
|
||||||
|
|
|
@ -5,3 +5,4 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
obj-y += board_init.o
|
obj-y += board_init.o
|
||||||
|
obj-$(CONFIG_$(SPL_TPL_)HANDOFF) += handoff.o
|
||||||
|
|
47
common/init/handoff.c
Normal file
47
common/init/handoff.c
Normal 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
|
||||||
|
}
|
|
@ -25,8 +25,28 @@ config SPL_FRAMEWORK
|
||||||
supports MMC, NAND and YMODEM and other methods loading of U-Boot
|
supports MMC, NAND and YMODEM and other methods loading of U-Boot
|
||||||
and the Linux Kernel. If unsure, say Y.
|
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
|
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
|
config SPL_LDSCRIPT
|
||||||
string "Linker script for the SPL stage"
|
string "Linker script for the SPL stage"
|
||||||
default "arch/$(ARCH)/cpu/u-boot-spl.lds"
|
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
|
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.
|
but with this option enabled, it goes at _image_binary_end.
|
||||||
|
|
||||||
config SPL_DISABLE_BANNER_PRINT
|
config SPL_BANNER_PRINT
|
||||||
bool "Disable output of the SPL banner 'U-Boot SPL ...'"
|
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
|
help
|
||||||
If this option is enabled, SPL will not print the banner with version
|
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
|
info. Disabling this option could be useful to reduce SPL boot time
|
||||||
(e.g. approx. 6 ms slower, when output on i.MX6 with 115200 baud).
|
(e.g. approx. 6 ms faster, when output on i.MX6 with 115200 baud).
|
||||||
|
|
||||||
config SPL_DISPLAY_PRINT
|
config SPL_DISPLAY_PRINT
|
||||||
bool "Display a board-specific message in SPL"
|
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
|
this option to build system-specific drivers for hash acceleration
|
||||||
as part of an SPL build.
|
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
|
config SPL_DMA_SUPPORT
|
||||||
bool "Support DMA drivers"
|
bool "Support DMA drivers"
|
||||||
help
|
help
|
||||||
|
@ -376,7 +415,7 @@ config SPL_FPGA_SUPPORT
|
||||||
within SPL.
|
within SPL.
|
||||||
|
|
||||||
config SPL_GPIO_SUPPORT
|
config SPL_GPIO_SUPPORT
|
||||||
bool "Support GPIO"
|
bool "Support GPIO in SPL"
|
||||||
help
|
help
|
||||||
Enable support for GPIOs (General-purpose Input/Output) in SPL.
|
Enable support for GPIOs (General-purpose Input/Output) in SPL.
|
||||||
GPIOs allow U-Boot to read the state of an input line (high or
|
GPIOs allow U-Boot to read the state of an input line (high or
|
||||||
|
@ -848,6 +887,16 @@ config TPL
|
||||||
|
|
||||||
if 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
|
config TPL_BOARD_INIT
|
||||||
bool "Call board-specific initialization in TPL"
|
bool "Call board-specific initialization in TPL"
|
||||||
help
|
help
|
||||||
|
@ -928,6 +977,17 @@ config TPL_ENV_SUPPORT
|
||||||
help
|
help
|
||||||
Enable environment support in TPL. See SPL_ENV_SUPPORT for details.
|
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
|
config TPL_I2C_SUPPORT
|
||||||
bool "Support I2C"
|
bool "Support I2C"
|
||||||
help
|
help
|
||||||
|
@ -963,6 +1023,22 @@ config TPL_NAND_SUPPORT
|
||||||
help
|
help
|
||||||
Enable support for NAND in TPL. See SPL_NAND_SUPPORT for details.
|
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
|
config TPL_RAM_SUPPORT
|
||||||
bool "Support booting from RAM"
|
bool "Support booting from RAM"
|
||||||
help
|
help
|
||||||
|
@ -977,6 +1053,15 @@ config TPL_RAM_DEVICE
|
||||||
be already in memory when TPL takes over, e.g. loaded by the boot
|
be already in memory when TPL takes over, e.g. loaded by the boot
|
||||||
ROM.
|
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
|
config TPL_SERIAL_SUPPORT
|
||||||
bool "Support serial"
|
bool "Support serial"
|
||||||
select TPL_PRINTF
|
select TPL_PRINTF
|
||||||
|
|
135
common/spl/spl.c
135
common/spl/spl.c
|
@ -7,8 +7,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <common.h>
|
#include <common.h>
|
||||||
|
#include <bloblist.h>
|
||||||
#include <binman_sym.h>
|
#include <binman_sym.h>
|
||||||
#include <dm.h>
|
#include <dm.h>
|
||||||
|
#include <handoff.h>
|
||||||
#include <spl.h>
|
#include <spl.h>
|
||||||
#include <asm/u-boot.h>
|
#include <asm/u-boot.h>
|
||||||
#include <nand.h>
|
#include <nand.h>
|
||||||
|
@ -44,6 +46,14 @@ static bd_t bdata __attribute__ ((section(".data")));
|
||||||
*/
|
*/
|
||||||
__weak void show_boot_progress(int val) {}
|
__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
|
* Default function to determine if u-boot or the OS should
|
||||||
* be started. This implementation always returns 1.
|
* be started. This implementation always returns 1.
|
||||||
|
@ -57,19 +67,12 @@ __weak void show_boot_progress(int val) {}
|
||||||
#ifdef CONFIG_SPL_OS_BOOT
|
#ifdef CONFIG_SPL_OS_BOOT
|
||||||
__weak int spl_start_uboot(void)
|
__weak int spl_start_uboot(void)
|
||||||
{
|
{
|
||||||
puts("SPL: Please implement spl_start_uboot() for your board\n");
|
puts(SPL_TPL_PROMPT
|
||||||
puts("SPL: Direct Linux boot not active!\n");
|
"Please implement spl_start_uboot() for your board\n");
|
||||||
|
puts(SPL_TPL_PROMPT "Direct Linux boot not active!\n");
|
||||||
return 1;
|
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
|
* Weak default function for arch specific zImage check. Return zero
|
||||||
* and fill start and end address if image is recognized.
|
* and fill start and end address if image is recognized.
|
||||||
|
@ -100,13 +103,13 @@ void spl_fixup_fdt(void)
|
||||||
/* fixup the memory dt node */
|
/* fixup the memory dt node */
|
||||||
err = fdt_shrink_to_minimum(fdt_blob, 0);
|
err = fdt_shrink_to_minimum(fdt_blob, 0);
|
||||||
if (err == 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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = arch_fixup_fdt(fdt_blob);
|
err = arch_fixup_fdt(fdt_blob);
|
||||||
if (err) {
|
if (err) {
|
||||||
printf("spl: arch_fixup_fdt err - %d\n", err);
|
printf(SPL_TPL_PROMPT "arch_fixup_fdt err - %d\n", err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#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->os = IH_OS_U_BOOT;
|
||||||
spl_image->name = "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);
|
spl_image->name, spl_image->load_addr, spl_image->size);
|
||||||
|
|
||||||
#ifdef CONFIG_SPL_FIT_SIGNATURE
|
#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->os = image_get_os(header);
|
||||||
spl_image->name = image_get_name(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);
|
spl_image->name, spl_image->load_addr, spl_image->size);
|
||||||
#else
|
#else
|
||||||
/* LEGACY image not supported */
|
/* 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->load_addr = CONFIG_SYS_LOAD_ADDR;
|
||||||
spl_image->entry_point = CONFIG_SYS_LOAD_ADDR;
|
spl_image->entry_point = CONFIG_SYS_LOAD_ADDR;
|
||||||
spl_image->size = end - start;
|
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);
|
spl_image->load_addr, spl_image->size);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -316,6 +321,44 @@ __weak void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image)
|
||||||
image_entry();
|
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)
|
static int spl_common_init(bool setup_malloc)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -336,6 +379,30 @@ static int spl_common_init(bool setup_malloc)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
bootstage_mark_name(BOOTSTAGE_ID_START_SPL, "spl");
|
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)) {
|
if (CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)) {
|
||||||
ret = fdtdec_setup();
|
ret = fdtdec_setup();
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
@ -359,6 +426,10 @@ static int spl_common_init(bool setup_malloc)
|
||||||
|
|
||||||
void spl_set_bd(void)
|
void spl_set_bd(void)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* NOTE: On some platforms (e.g. x86) bdata may be in flash and not
|
||||||
|
* writeable.
|
||||||
|
*/
|
||||||
if (!gd->bd)
|
if (!gd->bd)
|
||||||
gd->bd = &bdata;
|
gd->bd = &bdata;
|
||||||
}
|
}
|
||||||
|
@ -453,7 +524,7 @@ static int boot_from_devices(struct spl_image_info *spl_image,
|
||||||
if (loader)
|
if (loader)
|
||||||
printf("Trying to boot from %s\n", loader->name);
|
printf("Trying to boot from %s\n", loader->name);
|
||||||
else
|
else
|
||||||
puts("SPL: Unsupported Boot Device!\n");
|
puts(SPL_TPL_PROMPT "Unsupported Boot Device!\n");
|
||||||
#endif
|
#endif
|
||||||
if (loader && !spl_load_image(spl_image, loader)) {
|
if (loader && !spl_load_image(spl_image, loader)) {
|
||||||
spl_image->boot_device = spl_boot_list[i];
|
spl_image->boot_device = spl_boot_list[i];
|
||||||
|
@ -474,15 +545,12 @@ void board_init_r(gd_t *dummy1, ulong dummy2)
|
||||||
BOOT_DEVICE_NONE,
|
BOOT_DEVICE_NONE,
|
||||||
};
|
};
|
||||||
struct spl_image_info spl_image;
|
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();
|
spl_set_bd();
|
||||||
|
|
||||||
#ifdef CONFIG_SPL_OS_BOOT
|
|
||||||
dram_init_banksize();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(CONFIG_SYS_SPL_MALLOC_START)
|
#if defined(CONFIG_SYS_SPL_MALLOC_START)
|
||||||
mem_malloc_init(CONFIG_SYS_SPL_MALLOC_START,
|
mem_malloc_init(CONFIG_SYS_SPL_MALLOC_START,
|
||||||
CONFIG_SYS_SPL_MALLOC_SIZE);
|
CONFIG_SYS_SPL_MALLOC_SIZE);
|
||||||
|
@ -504,6 +572,9 @@ void board_init_r(gd_t *dummy1, ulong dummy2)
|
||||||
spl_board_init();
|
spl_board_init();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (IS_ENABLED(CONFIG_SPL_OS_BOOT) || CONFIG_IS_ENABLED(HANDOFF))
|
||||||
|
dram_init_banksize();
|
||||||
|
|
||||||
bootcount_inc();
|
bootcount_inc();
|
||||||
|
|
||||||
memset(&spl_image, '\0', sizeof(spl_image));
|
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,
|
if (boot_from_devices(&spl_image, spl_boot_list,
|
||||||
ARRAY_SIZE(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();
|
hang();
|
||||||
}
|
}
|
||||||
|
|
||||||
spl_perform_fixups(&spl_image);
|
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
|
#ifdef CONFIG_CPU_V7M
|
||||||
spl_image.entry_point |= 0x1;
|
spl_image.entry_point |= 0x1;
|
||||||
|
@ -556,8 +639,6 @@ void board_init_r(gd_t *dummy1, ulong dummy2)
|
||||||
gd->malloc_ptr / 1024);
|
gd->malloc_ptr / 1024);
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_BOOTSTAGE_STASH
|
#ifdef CONFIG_BOOTSTAGE_STASH
|
||||||
int ret;
|
|
||||||
|
|
||||||
bootstage_mark_name(BOOTSTAGE_ID_END_SPL, "end_spl");
|
bootstage_mark_name(BOOTSTAGE_ID_END_SPL, "end_spl");
|
||||||
ret = bootstage_stash((void *)CONFIG_BOOTSTAGE_STASH_ADDR,
|
ret = bootstage_stash((void *)CONFIG_BOOTSTAGE_STASH_ADDR,
|
||||||
CONFIG_BOOTSTAGE_STASH_SIZE);
|
CONFIG_BOOTSTAGE_STASH_SIZE);
|
||||||
|
@ -583,9 +664,9 @@ void preloader_console_init(void)
|
||||||
|
|
||||||
gd->have_console = 1;
|
gd->have_console = 1;
|
||||||
|
|
||||||
#ifndef CONFIG_SPL_DISABLE_BANNER_PRINT
|
#if CONFIG_IS_ENABLED(BANNER_PRINT)
|
||||||
puts("\nU-Boot SPL " PLAIN_VERSION " (" U_BOOT_DATE " - " \
|
puts("\nU-Boot " SPL_TPL_NAME " " PLAIN_VERSION " (" U_BOOT_DATE " - "
|
||||||
U_BOOT_TIME " " U_BOOT_TZ ")\n");
|
U_BOOT_TIME " " U_BOOT_TZ ")\n");
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_SPL_DISPLAY_PRINT
|
#ifdef CONFIG_SPL_DISPLAY_PRINT
|
||||||
spl_display_print();
|
spl_display_print();
|
||||||
|
|
|
@ -22,6 +22,7 @@ CONFIG_CONSOLE_RECORD=y
|
||||||
CONFIG_CONSOLE_RECORD_OUT_SIZE=0x1000
|
CONFIG_CONSOLE_RECORD_OUT_SIZE=0x1000
|
||||||
CONFIG_SILENT_CONSOLE=y
|
CONFIG_SILENT_CONSOLE=y
|
||||||
CONFIG_DISPLAY_BOARDINFO_LATE=y
|
CONFIG_DISPLAY_BOARDINFO_LATE=y
|
||||||
|
CONFIG_HANDOFF=y
|
||||||
CONFIG_SPL_BOARD_INIT=y
|
CONFIG_SPL_BOARD_INIT=y
|
||||||
CONFIG_SPL_ENV_SUPPORT=y
|
CONFIG_SPL_ENV_SUPPORT=y
|
||||||
CONFIG_CMD_CPU=y
|
CONFIG_CMD_CPU=y
|
||||||
|
|
82
doc/README.bloblist
Normal file
82
doc/README.bloblist
Normal 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
|
|
@ -88,7 +88,7 @@ stdin=serial
|
||||||
stdout=serial
|
stdout=serial
|
||||||
|
|
||||||
Environment size: 117/8188 bytes
|
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)
|
11405888 bytes written in 10 ms (1.1 GiB/s)
|
||||||
=>reset
|
=>reset
|
||||||
|
|
||||||
|
|
|
@ -2,14 +2,19 @@
|
||||||
|
|
||||||
obj-$(CONFIG_$(SPL_TPL_)CLK) += clk/
|
obj-$(CONFIG_$(SPL_TPL_)CLK) += clk/
|
||||||
obj-$(CONFIG_$(SPL_TPL_)DM) += core/
|
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_)DRIVERS_MISC_SUPPORT) += misc/ sysreset/ firmware/
|
||||||
obj-$(CONFIG_$(SPL_TPL_)I2C_SUPPORT) += i2c/
|
obj-$(CONFIG_$(SPL_TPL_)I2C_SUPPORT) += i2c/
|
||||||
|
obj-$(CONFIG_$(SPL_TPL_)INPUT) += input/
|
||||||
obj-$(CONFIG_$(SPL_TPL_)LED) += led/
|
obj-$(CONFIG_$(SPL_TPL_)LED) += led/
|
||||||
obj-$(CONFIG_$(SPL_TPL_)MMC_SUPPORT) += mmc/
|
obj-$(CONFIG_$(SPL_TPL_)MMC_SUPPORT) += mmc/
|
||||||
obj-$(CONFIG_$(SPL_TPL_)NAND_SUPPORT) += mtd/nand/raw/
|
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_)PHY) += phy/
|
||||||
obj-$(CONFIG_$(SPL_TPL_)PINCTRL) += pinctrl/
|
obj-$(CONFIG_$(SPL_TPL_)PINCTRL) += pinctrl/
|
||||||
obj-$(CONFIG_$(SPL_TPL_)RAM) += ram/
|
obj-$(CONFIG_$(SPL_TPL_)RAM) += ram/
|
||||||
|
obj-$(CONFIG_$(SPL_TPL_)RTC_SUPPORT) += rtc/
|
||||||
obj-$(CONFIG_$(SPL_TPL_)SERIAL_SUPPORT) += serial/
|
obj-$(CONFIG_$(SPL_TPL_)SERIAL_SUPPORT) += serial/
|
||||||
obj-$(CONFIG_$(SPL_TPL_)SPI_FLASH_SUPPORT) += mtd/spi/
|
obj-$(CONFIG_$(SPL_TPL_)SPI_FLASH_SUPPORT) += mtd/spi/
|
||||||
obj-$(CONFIG_$(SPL_TPL_)SPI_SUPPORT) += 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_TPL_)VIRTIO) += virtio/
|
||||||
obj-$(CONFIG_$(SPL_)DM_MAILBOX) += mailbox/
|
obj-$(CONFIG_$(SPL_)DM_MAILBOX) += mailbox/
|
||||||
obj-$(CONFIG_$(SPL_)REMOTEPROC) += remoteproc/
|
obj-$(CONFIG_$(SPL_)REMOTEPROC) += remoteproc/
|
||||||
|
obj-$(CONFIG_$(SPL_TPL_)TPM) += tpm/
|
||||||
|
|
||||||
ifndef CONFIG_TPL_BUILD
|
ifndef CONFIG_TPL_BUILD
|
||||||
ifdef CONFIG_SPL_BUILD
|
ifdef CONFIG_SPL_BUILD
|
||||||
|
@ -24,7 +30,6 @@ ifdef CONFIG_SPL_BUILD
|
||||||
obj-$(CONFIG_SPL_BOOTCOUNT_LIMIT) += bootcount/
|
obj-$(CONFIG_SPL_BOOTCOUNT_LIMIT) += bootcount/
|
||||||
obj-$(CONFIG_SPL_CPU_SUPPORT) += cpu/
|
obj-$(CONFIG_SPL_CPU_SUPPORT) += cpu/
|
||||||
obj-$(CONFIG_SPL_CRYPTO_SUPPORT) += crypto/
|
obj-$(CONFIG_SPL_CRYPTO_SUPPORT) += crypto/
|
||||||
obj-$(CONFIG_SPL_GPIO_SUPPORT) += gpio/
|
|
||||||
obj-$(CONFIG_SPL_MPC8XXX_INIT_DDR_SUPPORT) += ddr/fsl/
|
obj-$(CONFIG_SPL_MPC8XXX_INIT_DDR_SUPPORT) += ddr/fsl/
|
||||||
obj-$(CONFIG_ARMADA_38X) += ddr/marvell/a38x/
|
obj-$(CONFIG_ARMADA_38X) += ddr/marvell/a38x/
|
||||||
obj-$(CONFIG_ARMADA_XP) += ddr/marvell/axp/
|
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/
|
||||||
obj-$(CONFIG_SPL_ETH_SUPPORT) += net/phy/
|
obj-$(CONFIG_SPL_ETH_SUPPORT) += net/phy/
|
||||||
obj-$(CONFIG_SPL_USB_ETHER) += 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_MUSB_NEW_SUPPORT) += usb/musb-new/
|
||||||
obj-$(CONFIG_SPL_USB_GADGET_SUPPORT) += usb/gadget/
|
obj-$(CONFIG_SPL_USB_GADGET_SUPPORT) += usb/gadget/
|
||||||
obj-$(CONFIG_SPL_USB_GADGET_SUPPORT) += usb/gadget/udc/
|
obj-$(CONFIG_SPL_USB_GADGET_SUPPORT) += usb/gadget/udc/
|
||||||
|
@ -92,7 +94,6 @@ obj-y += scsi/
|
||||||
obj-y += sound/
|
obj-y += sound/
|
||||||
obj-y += spmi/
|
obj-y += spmi/
|
||||||
obj-y += sysreset/
|
obj-y += sysreset/
|
||||||
obj-y += tpm/
|
|
||||||
obj-y += video/
|
obj-y += video/
|
||||||
obj-y += watchdog/
|
obj-y += watchdog/
|
||||||
obj-$(CONFIG_QE) += qe/
|
obj-$(CONFIG_QE) += qe/
|
||||||
|
|
|
@ -122,6 +122,13 @@ typedef struct global_data {
|
||||||
struct list_head log_head; /* List of struct log_device */
|
struct list_head log_head; /* List of struct log_device */
|
||||||
int log_fmt; /* Mask containing log format info */
|
int log_fmt; /* Mask containing log format info */
|
||||||
#endif
|
#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;
|
} gd_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
195
include/bloblist.h
Normal file
195
include/bloblist.h
Normal 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
36
include/handoff.h
Normal 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
|
|
@ -48,6 +48,7 @@ enum log_category_t {
|
||||||
LOGC_EFI, /* EFI implementation */
|
LOGC_EFI, /* EFI implementation */
|
||||||
LOGC_ALLOC, /* Memory allocation */
|
LOGC_ALLOC, /* Memory allocation */
|
||||||
LOGC_SANDBOX, /* Related to the sandbox board */
|
LOGC_SANDBOX, /* Related to the sandbox board */
|
||||||
|
LOGC_BLOBLIST, /* Bloblist */
|
||||||
|
|
||||||
LOGC_COUNT, /* Number of log categories */
|
LOGC_COUNT, /* Number of log categories */
|
||||||
LOGC_END, /* Sentinel value for a list 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...)
|
#define log_io(_fmt...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if CONFIG_IS_ENABLED(LOG)
|
||||||
|
|
||||||
/* Emit a log record if the level is less that the maximum */
|
/* Emit a log record if the level is less that the maximum */
|
||||||
#define log(_cat, _level, _fmt, _args...) ({ \
|
#define log(_cat, _level, _fmt, _args...) ({ \
|
||||||
int _l = _level; \
|
int _l = _level; \
|
||||||
|
@ -116,6 +119,9 @@ int _log(enum log_category_t cat, enum log_level_t level, const char *file,
|
||||||
__func__, \
|
__func__, \
|
||||||
pr_fmt(_fmt), ##_args); \
|
pr_fmt(_fmt), ##_args); \
|
||||||
})
|
})
|
||||||
|
#else
|
||||||
|
#define log(_cat, _level, _fmt, _args...)
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
#define _DEBUG 1
|
#define _DEBUG 1
|
||||||
|
@ -175,7 +181,16 @@ void __assert_fail(const char *assertion, const char *file, unsigned int line,
|
||||||
({ if (!(x) && _DEBUG) \
|
({ if (!(x) && _DEBUG) \
|
||||||
__assert_fail(#x, __FILE__, __LINE__, __func__); })
|
__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) ({ \
|
#define log_ret(_ret) ({ \
|
||||||
int __ret = (_ret); \
|
int __ret = (_ret); \
|
||||||
if (__ret < 0) \
|
if (__ret < 0) \
|
||||||
|
@ -190,8 +205,9 @@ void __assert_fail(const char *assertion, const char *file, unsigned int line,
|
||||||
__ret; \
|
__ret; \
|
||||||
})
|
})
|
||||||
#else
|
#else
|
||||||
|
/* Non-logging versions of the above which just return the error code */
|
||||||
#define log_ret(_ret) (_ret)
|
#define log_ret(_ret) (_ret)
|
||||||
#define log_msg_ret(_msg, _ret) (_ret)
|
#define log_msg_ret(_msg, _ret) ((void)(_msg), _ret)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
/* Platform-specific defines */
|
/* Platform-specific defines */
|
||||||
#include <linux/compiler.h>
|
#include <linux/compiler.h>
|
||||||
#include <asm/spl.h>
|
#include <asm/spl.h>
|
||||||
|
#include <handoff.h>
|
||||||
|
|
||||||
/* Value in r0 indicates we booted from U-Boot */
|
/* Value in r0 indicates we booted from U-Boot */
|
||||||
#define UBOOT_NOT_LOADED_FROM_SPL 0x13578642
|
#define UBOOT_NOT_LOADED_FROM_SPL 0x13578642
|
||||||
|
@ -21,6 +22,46 @@
|
||||||
#define MMCSD_MODE_FS 2
|
#define MMCSD_MODE_FS 2
|
||||||
#define MMCSD_MODE_EMMCBOOT 3
|
#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 {
|
struct spl_image_info {
|
||||||
const char *name;
|
const char *name;
|
||||||
u8 os;
|
u8 os;
|
||||||
|
|
|
@ -23,6 +23,7 @@ struct unit_test;
|
||||||
int cmd_ut_category(const char *name, struct unit_test *tests, int n_ents,
|
int cmd_ut_category(const char *name, struct unit_test *tests, int n_ents,
|
||||||
int argc, char * const argv[]);
|
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_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_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[]);
|
int do_ut_env(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#
|
#
|
||||||
# (C) Copyright 2012 The Chromium Authors
|
# (C) Copyright 2012 The Chromium Authors
|
||||||
|
|
||||||
|
obj-$(CONFIG_SANDBOX) += bloblist.o
|
||||||
obj-$(CONFIG_UNIT_TEST) += cmd_ut.o
|
obj-$(CONFIG_UNIT_TEST) += cmd_ut.o
|
||||||
obj-$(CONFIG_UNIT_TEST) += ut.o
|
obj-$(CONFIG_UNIT_TEST) += ut.o
|
||||||
obj-$(CONFIG_SANDBOX) += command_ut.o
|
obj-$(CONFIG_SANDBOX) += command_ut.o
|
||||||
|
|
187
test/bloblist.c
Normal file
187
test/bloblist.c
Normal 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);
|
||||||
|
}
|
|
@ -55,6 +55,8 @@ static cmd_tbl_t cmd_ut_sub[] = {
|
||||||
#ifdef CONFIG_SANDBOX
|
#ifdef CONFIG_SANDBOX
|
||||||
U_BOOT_CMD_MKENT(compression, CONFIG_SYS_MAXARGS, 1, do_ut_compression,
|
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
|
#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[] =
|
static char ut_help_text[] =
|
||||||
"all - execute all enabled tests\n"
|
"all - execute all enabled tests\n"
|
||||||
#ifdef CONFIG_SANDBOX
|
#ifdef CONFIG_SANDBOX
|
||||||
|
"ut bloblist - Test bloblist implementation\n"
|
||||||
"ut compression - Test compressors and bootm decompression\n"
|
"ut compression - Test compressors and bootm decompression\n"
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_UT_DM
|
#ifdef CONFIG_UT_DM
|
||||||
|
|
|
@ -79,7 +79,7 @@ static int dm_test_spi_flash_func(struct unit_test_state *uts)
|
||||||
* benefit is worth the extra complexity.
|
* benefit is worth the extra complexity.
|
||||||
*/
|
*/
|
||||||
ut_asserteq(0, run_command_list(
|
ut_asserteq(0, run_command_list(
|
||||||
"sb save hostfs - 0 spi.bin 200000;"
|
"host save hostfs - 0 spi.bin 200000;"
|
||||||
"sf probe;"
|
"sf probe;"
|
||||||
"sf test 0 10000", -1, 0));
|
"sf test 0 10000", -1, 0));
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -194,7 +194,7 @@ function test_image() {
|
||||||
;;
|
;;
|
||||||
|
|
||||||
sb)
|
sb)
|
||||||
PREFIX="sb "
|
PREFIX="host "
|
||||||
WRITE="save"
|
WRITE="save"
|
||||||
SUFFIX="fs -"
|
SUFFIX="fs -"
|
||||||
;;
|
;;
|
||||||
|
@ -217,11 +217,11 @@ function test_image() {
|
||||||
|
|
||||||
# In u-boot commands, <interface> stands for host or hostfs
|
# In u-boot commands, <interface> stands for host or hostfs
|
||||||
# hostfs maps to the host fs.
|
# 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
|
$UBOOT << EOF
|
||||||
sb=$5
|
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
|
run bind
|
||||||
# Test Case 1 - ls
|
# Test Case 1 - ls
|
||||||
${PREFIX}ls host${SUFFIX} $6
|
${PREFIX}ls host${SUFFIX} $6
|
||||||
|
@ -229,7 +229,7 @@ ${PREFIX}ls host${SUFFIX} $6
|
||||||
${PREFIX}ls host${SUFFIX} invalid_d
|
${PREFIX}ls host${SUFFIX} invalid_d
|
||||||
#
|
#
|
||||||
# We want ${PREFIX}size host 0:0 $3 for host commands and
|
# 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
|
# 1MB is 0x0010 0000
|
||||||
# Test Case 2a - size of small file
|
# Test Case 2a - size of small file
|
||||||
${PREFIX}size host${SUFFIX} ${FPATH}$FILE_SMALL
|
${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
|
# In each loop, for a given file system image, we test both the
|
||||||
# fs command, like load/size/write, the file system specific command
|
# 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
|
for fs in ext4 fat16 fat32; do
|
||||||
|
|
||||||
echo "Creating $fs image if not already present."
|
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}"
|
MD5_FILE_FS="${MD5_FILE}.${fs}"
|
||||||
create_image $IMAGE $fs
|
create_image $IMAGE $fs
|
||||||
|
|
||||||
# sb commands test
|
# host commands test
|
||||||
echo "Creating files in $fs image if not already present."
|
echo "Creating files in $fs image if not already present."
|
||||||
create_files $IMAGE $MD5_FILE_FS
|
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"
|
mkdir -p "$MOUNT_DIR"
|
||||||
case "$fs" in
|
case "$fs" in
|
||||||
fat*)
|
fat*)
|
||||||
|
|
|
@ -99,15 +99,15 @@ base_fdt = '''
|
||||||
# then run the 'bootm' command, then save out memory from the places where
|
# then run the 'bootm' command, then save out memory from the places where
|
||||||
# we expect 'bootm' to write things. Then quit.
|
# we expect 'bootm' to write things. Then quit.
|
||||||
base_script = '''
|
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
|
fdt addr %(fit_addr)x
|
||||||
bootm start %(fit_addr)x
|
bootm start %(fit_addr)x
|
||||||
bootm loados
|
bootm loados
|
||||||
sb save hostfs 0 %(kernel_addr)x %(kernel_out)s %(kernel_size)x
|
host 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
|
host 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
|
host 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
|
host 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 %(loadables2_addr)x %(loadables2_out)s %(loadables2_size)x
|
||||||
'''
|
'''
|
||||||
|
|
||||||
@pytest.mark.boardspec('sandbox')
|
@pytest.mark.boardspec('sandbox')
|
||||||
|
|
15
test/py/tests/test_handoff.py
Normal file
15
test/py/tests/test_handoff.py
Normal 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
|
|
@ -3,11 +3,40 @@
|
||||||
|
|
||||||
import pytest
|
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')
|
@pytest.mark.buildconfigspec('spl_of_platdata')
|
||||||
def test_ofplatdata(u_boot_console):
|
def test_ofplatdata(u_boot_console):
|
||||||
"""Test that of-platdata can be generated and used in sandbox"""
|
"""Test that of-platdata can be generated and used in sandbox"""
|
||||||
cons = u_boot_console
|
cons = u_boot_console
|
||||||
|
cons.restart_uboot_with_flags(['--show_of_platdata'])
|
||||||
output = cons.get_spawn_output().replace('\r', '')
|
output = cons.get_spawn_output().replace('\r', '')
|
||||||
assert OF_PLATDATA_OUTPUT in output
|
assert OF_PLATDATA_OUTPUT in output
|
||||||
|
|
|
@ -74,7 +74,7 @@ def test_vboot(u_boot_console):
|
||||||
cons.restart_uboot()
|
cons.restart_uboot()
|
||||||
with cons.log.section('Verified boot %s %s' % (sha_algo, test_type)):
|
with cons.log.section('Verified boot %s %s' % (sha_algo, test_type)):
|
||||||
output = cons.run_command_list(
|
output = cons.run_command_list(
|
||||||
['sb load hostfs - 100 %stest.fit' % tmpdir,
|
['host load hostfs - 100 %stest.fit' % tmpdir,
|
||||||
'fdt addr 100',
|
'fdt addr 100',
|
||||||
'bootm 100'])
|
'bootm 100'])
|
||||||
assert(expect_string in ''.join(output))
|
assert(expect_string in ''.join(output))
|
||||||
|
|
|
@ -16,7 +16,7 @@ import sys
|
||||||
import u_boot_spawn
|
import u_boot_spawn
|
||||||
|
|
||||||
# Regexes for text we expect U-Boot to send to the console.
|
# 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_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_stop_autoboot_prompt = re.compile('Hit any key to stop autoboot: ')
|
||||||
pattern_unknown_command = re.compile('Unknown command \'.*\' - try \'help\'')
|
pattern_unknown_command = re.compile('Unknown command \'.*\' - try \'help\'')
|
||||||
|
|
|
@ -24,6 +24,7 @@ class ConsoleSandbox(ConsoleBase):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
super(ConsoleSandbox, self).__init__(log, config, max_fifo_fill=1024)
|
super(ConsoleSandbox, self).__init__(log, config, max_fifo_fill=1024)
|
||||||
|
self.sandbox_flags = []
|
||||||
|
|
||||||
def get_spawn(self):
|
def get_spawn(self):
|
||||||
"""Connect to a fresh U-Boot instance.
|
"""Connect to a fresh U-Boot instance.
|
||||||
|
@ -51,8 +52,25 @@ class ConsoleSandbox(ConsoleBase):
|
||||||
'-d',
|
'-d',
|
||||||
self.config.dtb
|
self.config.dtb
|
||||||
]
|
]
|
||||||
|
cmd += self.sandbox_flags
|
||||||
return Spawn(cmd, cwd=self.config.source_dir)
|
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):
|
def kill(self, sig):
|
||||||
"""Send a specific Unix signal to the sandbox process.
|
"""Send a specific Unix signal to the sandbox process.
|
||||||
|
|
||||||
|
|
2
test/run
2
test/run
|
@ -19,7 +19,7 @@ run_test "sandbox" ./test/py/test.py --bd sandbox --build
|
||||||
|
|
||||||
# Run tests which require sandbox_spl
|
# Run tests which require sandbox_spl
|
||||||
run_test "sandbox_spl" ./test/py/test.py --bd sandbox_spl --build \
|
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
|
# 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
|
# build which does not enable CONFIG_OF_LIVE for the live device tree, so we can
|
||||||
|
|
Loading…
Reference in a new issue