diff options
Diffstat (limited to 'arch/sandbox')
| -rw-r--r-- | arch/sandbox/cpu/cpu.c | 21 | ||||
| -rw-r--r-- | arch/sandbox/cpu/os.c | 95 | ||||
| -rw-r--r-- | arch/sandbox/cpu/start.c | 96 | ||||
| -rw-r--r-- | arch/sandbox/cpu/state.c | 353 | ||||
| -rw-r--r-- | arch/sandbox/include/asm/global_data.h | 2 | ||||
| -rw-r--r-- | arch/sandbox/include/asm/state.h | 128 | ||||
| -rw-r--r-- | arch/sandbox/include/asm/u-boot-sandbox.h | 2 | 
7 files changed, 679 insertions, 18 deletions
| diff --git a/arch/sandbox/cpu/cpu.c b/arch/sandbox/cpu/cpu.c index cfc1fda1e..38019e0b4 100644 --- a/arch/sandbox/cpu/cpu.c +++ b/arch/sandbox/cpu/cpu.c @@ -5,13 +5,23 @@  #include <common.h>  #include <os.h> +#include <asm/state.h>  DECLARE_GLOBAL_DATA_PTR; -int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +void reset_cpu(ulong ignored)  { +	if (state_uninit()) +		os_exit(2); +  	/* This is considered normal termination for now */  	os_exit(0); +} + +int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ +	reset_cpu(0); +  	return 0;  } @@ -28,7 +38,14 @@ unsigned long __attribute__((no_instrument_function)) timer_get_us(void)  int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)  { -	return -1; +	if (flag & (BOOTM_STATE_OS_GO | BOOTM_STATE_OS_FAKE_GO)) { +		bootstage_mark(BOOTSTAGE_ID_RUN_OS); +		printf("## Transferring control to Linux (at address %08lx)...\n", +		       images->ep); +		reset_cpu(0); +	} + +	return 0;  }  int cleanup_before_linux(void) diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c index 26f44cb59..725b50517 100644 --- a/arch/sandbox/cpu/os.c +++ b/arch/sandbox/cpu/os.c @@ -27,6 +27,10 @@  /* Operating System Interface */ +struct os_mem_hdr { +	size_t length;		/* number of bytes in the block */ +}; +  ssize_t os_read(int fd, void *buf, size_t count)  {  	return read(fd, buf, count); @@ -128,8 +132,45 @@ void os_tty_raw(int fd)  void *os_malloc(size_t length)  { -	return mmap(NULL, length, PROT_READ | PROT_WRITE, -			MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); +	struct os_mem_hdr *hdr; + +	hdr = mmap(NULL, length + sizeof(*hdr), PROT_READ | PROT_WRITE, +		   MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); +	if (hdr == MAP_FAILED) +		return NULL; +	hdr->length = length; + +	return hdr + 1; +} + +void *os_free(void *ptr) +{ +	struct os_mem_hdr *hdr = ptr; + +	hdr--; +	if (ptr) +		munmap(hdr, hdr->length + sizeof(*hdr)); +} + +void *os_realloc(void *ptr, size_t length) +{ +	struct os_mem_hdr *hdr = ptr; +	void *buf = NULL; + +	hdr--; +	if (length != 0) { +		buf = os_malloc(length); +		if (!buf) +			return buf; +		if (ptr) { +			if (length > hdr->length) +				length = hdr->length; +			memcpy(buf, ptr, length); +		} +	} +	os_free(ptr); + +	return buf;  }  void os_usleep(unsigned long usec) @@ -347,3 +388,53 @@ ssize_t os_get_filesize(const char *fname)  		return ret;  	return buf.st_size;  } + +void os_putc(int ch) +{ +	putchar(ch); +} + +void os_puts(const char *str) +{ +	while (*str) +		os_putc(*str++); +} + +int os_write_ram_buf(const char *fname) +{ +	struct sandbox_state *state = state_get_current(); +	int fd, ret; + +	fd = open(fname, O_CREAT | O_WRONLY, 0777); +	if (fd < 0) +		return -ENOENT; +	ret = write(fd, state->ram_buf, state->ram_size); +	close(fd); +	if (ret != state->ram_size) +		return -EIO; + +	return 0; +} + +int os_read_ram_buf(const char *fname) +{ +	struct sandbox_state *state = state_get_current(); +	int fd, ret; +	int size; + +	size = os_get_filesize(fname); +	if (size < 0) +		return -ENOENT; +	if (size != state->ram_size) +		return -ENOSPC; +	fd = open(fname, O_RDONLY); +	if (fd < 0) +		return -ENOENT; + +	ret = read(fd, state->ram_buf, state->ram_size); +	close(fd); +	if (ret != state->ram_size) +		return -EIO; + +	return 0; +} diff --git a/arch/sandbox/cpu/start.c b/arch/sandbox/cpu/start.c index 1b1545478..1df21d49f 100644 --- a/arch/sandbox/cpu/start.c +++ b/arch/sandbox/cpu/start.c @@ -4,11 +4,12 @@   */  #include <common.h> +#include <os.h>  #include <asm/getopt.h>  #include <asm/sections.h>  #include <asm/state.h> -#include <os.h> +DECLARE_GLOBAL_DATA_PTR;  int sandbox_early_getopt_check(void)  { @@ -50,9 +51,9 @@ int sandbox_early_getopt_check(void)  		/* then the long flag */  		if (opt->has_arg) -			printf("--%-*s", max_noarg_len, opt->flag); -		else  			printf("--%-*s <arg> ", max_arg_len, opt->flag); +		else +			printf("--%-*s", max_noarg_len, opt->flag);  		/* finally the help text */  		printf("  %s\n", opt->help); @@ -75,7 +76,8 @@ int sandbox_main_loop_init(void)  	/* Execute command if required */  	if (state->cmd) {  		run_command_list(state->cmd, -1, 0); -		os_exit(state->exit_type); +		if (!state->interactive) +			os_exit(state->exit_type);  	}  	return 0; @@ -96,25 +98,93 @@ static int sandbox_cmdline_cb_fdt(struct sandbox_state *state, const char *arg)  }  SANDBOX_CMDLINE_OPT_SHORT(fdt, 'd', 1, "Specify U-Boot's control FDT"); -int main(int argc, char *argv[]) +static int sandbox_cmdline_cb_interactive(struct sandbox_state *state, +					  const char *arg) +{ +	state->interactive = true; +	return 0; +} + +SANDBOX_CMDLINE_OPT_SHORT(interactive, 'i', 0, "Enter interactive mode"); + +static int sandbox_cmdline_cb_memory(struct sandbox_state *state, +				     const char *arg)  { -	struct sandbox_state *state;  	int err; -	err = state_init(); -	if (err) +	/* For now assume we always want to write it */ +	state->write_ram_buf = true; +	state->ram_buf_fname = arg; + +	if (os_read_ram_buf(arg)) { +		printf("Failed to read RAM buffer\n");  		return err; +	} + +	return 0; +} +SANDBOX_CMDLINE_OPT_SHORT(memory, 'm', 1, +			  "Read/write ram_buf memory contents from file"); + +static int sandbox_cmdline_cb_state(struct sandbox_state *state, +				    const char *arg) +{ +	state->state_fname = arg; +	return 0; +} +SANDBOX_CMDLINE_OPT_SHORT(state, 's', 1, "Specify the sandbox state FDT"); + +static int sandbox_cmdline_cb_read(struct sandbox_state *state, +				   const char *arg) +{ +	state->read_state = true; +	return 0; +} +SANDBOX_CMDLINE_OPT_SHORT(read, 'r', 0, "Read the state FDT on startup"); + +static int sandbox_cmdline_cb_write(struct sandbox_state *state, +				    const char *arg) +{ +	state->write_state = true; +	return 0; +} +SANDBOX_CMDLINE_OPT_SHORT(write, 'w', 0, "Write state FDT on exit"); + +static int sandbox_cmdline_cb_ignore_missing(struct sandbox_state *state, +					     const char *arg) +{ +	state->ignore_missing_state_on_read = true; +	return 0; +} +SANDBOX_CMDLINE_OPT_SHORT(ignore_missing, 'n', 0, +			  "Ignore missing state on read"); + +int main(int argc, char *argv[]) +{ +	struct sandbox_state *state; +	int ret; + +	ret = state_init(); +	if (ret) +		goto err;  	state = state_get_current();  	if (os_parse_args(state, argc, argv))  		return 1; -	/* -	 * Do pre- and post-relocation init, then start up U-Boot. This will -	 * never return. -	 */ +	ret = sandbox_read_state(state, state->state_fname); +	if (ret) +		goto err; + +	/* Do pre- and post-relocation init */  	board_init_f(0); -	/* NOTREACHED - board_init_f() does not return */ +	board_init_r(gd->new_gd, 0); + +	/* NOTREACHED - board_init_r() does not return */  	return 0; + +err: +	printf("Error %d\n", ret); +	return 1;  } diff --git a/arch/sandbox/cpu/state.c b/arch/sandbox/cpu/state.c index 56d504141..a145808a5 100644 --- a/arch/sandbox/cpu/state.c +++ b/arch/sandbox/cpu/state.c @@ -4,6 +4,9 @@   */  #include <common.h> +#include <errno.h> +#include <fdtdec.h> +#include <os.h>  #include <asm/state.h>  /* Main state record for the sandbox */ @@ -15,6 +18,324 @@ void state_record_exit(enum exit_type_id exit_type)  	state->exit_type = exit_type;  } +static int state_ensure_space(int extra_size) +{ +	void *blob = state->state_fdt; +	int used, size, free; +	void *buf; +	int ret; + +	used = fdt_off_dt_strings(blob) + fdt_size_dt_strings(blob); +	size = fdt_totalsize(blob); +	free = size - used; +	if (free > extra_size) +		return 0; + +	size = used + extra_size; +	buf = os_malloc(size); +	if (!buf) +		return -ENOMEM; + +	ret = fdt_open_into(blob, buf, size); +	if (ret) { +		os_free(buf); +		return -EIO; +	} + +	os_free(blob); +	state->state_fdt = buf; +	return 0; +} + +static int state_read_file(struct sandbox_state *state, const char *fname) +{ +	int size; +	int ret; +	int fd; + +	size = os_get_filesize(fname); +	if (size < 0) { +		printf("Cannot find sandbox state file '%s'\n", fname); +		return -ENOENT; +	} +	state->state_fdt = os_malloc(size); +	if (!state->state_fdt) { +		puts("No memory to read sandbox state\n"); +		return -ENOMEM; +	} +	fd = os_open(fname, OS_O_RDONLY); +	if (fd < 0) { +		printf("Cannot open sandbox state file '%s'\n", fname); +		ret = -EPERM; +		goto err_open; +	} +	if (os_read(fd, state->state_fdt, size) != size) { +		printf("Cannot read sandbox state file '%s'\n", fname); +		ret = -EIO; +		goto err_read; +	} +	os_close(fd); + +	return 0; +err_read: +	os_close(fd); +err_open: +	os_free(state->state_fdt); +	state->state_fdt = NULL; + +	return ret; +} + +/*** + * sandbox_read_state_nodes() - Read state associated with a driver + * + * This looks through all compatible nodes and calls the read function on + * each one, to read in the state. + * + * If nothing is found, it still calls the read function once, to set up a + * single global state for that driver. + * + * @state: Sandbox state + * @io: Method to use for reading state + * @blob: FDT containing state + * @return 0 if OK, -EINVAL if the read function returned failure + */ +int sandbox_read_state_nodes(struct sandbox_state *state, +			     struct sandbox_state_io *io, const void *blob) +{ +	int count; +	int node; +	int ret; + +	debug("   - read %s\n", io->name); +	if (!io->read) +		return 0; + +	node = -1; +	count = 0; +	while (blob) { +		node = fdt_node_offset_by_compatible(blob, node, io->compat); +		if (node < 0) +			return 0;	/* No more */ +		debug("   - read node '%s'\n", fdt_get_name(blob, node, NULL)); +		ret = io->read(blob, node); +		if (ret) { +			printf("Unable to read state for '%s'\n", io->compat); +			return -EINVAL; +		} +		count++; +	} + +	/* +	 * If we got no saved state, call the read function once without a +	 * node, to set up the global state. +	 */ +	if (count == 0) { +		debug("   - read global\n"); +		ret = io->read(NULL, -1); +		if (ret) { +			printf("Unable to read global state for '%s'\n", +			       io->name); +			return -EINVAL; +		} +	} + +	return 0; +} + +int sandbox_read_state(struct sandbox_state *state, const char *fname) +{ +	struct sandbox_state_io *io; +	const void *blob; +	bool got_err; +	int ret; + +	if (state->read_state && fname) { +		ret = state_read_file(state, fname); +		if (ret == -ENOENT && state->ignore_missing_state_on_read) +			ret = 0; +		if (ret) +			return ret; +	} + +	/* Call all the state read funtcions */ +	got_err = false; +	blob = state->state_fdt; +	io = ll_entry_start(struct sandbox_state_io, state_io); +	for (; io < ll_entry_end(struct sandbox_state_io, state_io); io++) { +		ret = sandbox_read_state_nodes(state, io, blob); +		if (ret < 0) +			got_err = true; +	} + +	if (state->read_state && fname) { +		debug("Read sandbox state from '%s'%s\n", fname, +		      got_err ? " (with errors)" : ""); +	} + +	return got_err ? -1 : 0; +} + +/*** + * sandbox_write_state_node() - Write state associated with a driver + * + * This calls the write function to write out global state for that driver. + * + * TODO(sjg@chromium.org): Support writing out state from multiple drivers + * of the same time. We don't need this yet,and it will be much easier to + * do when driver model is available. + * + * @state: Sandbox state + * @io: Method to use for writing state + * @return 0 if OK, -EIO if there is a fatal error (such as out of space + * for adding the data), -EINVAL if the write function failed. + */ +int sandbox_write_state_node(struct sandbox_state *state, +			     struct sandbox_state_io *io) +{ +	void *blob; +	int node; +	int ret; + +	if (!io->write) +		return 0; + +	ret = state_ensure_space(SANDBOX_STATE_MIN_SPACE); +	if (ret) { +		printf("Failed to add more space for state\n"); +		return -EIO; +	} + +	/* The blob location can change when the size increases */ +	blob = state->state_fdt; +	node = fdt_node_offset_by_compatible(blob, -1, io->compat); +	if (node == -FDT_ERR_NOTFOUND) { +		node = fdt_add_subnode(blob, 0, io->name); +		if (node < 0) { +			printf("Cannot create node '%s': %s\n", io->name, +			       fdt_strerror(node)); +			return -EIO; +		} + +		if (fdt_setprop_string(blob, node, "compatible", io->compat)) { +			puts("Cannot set compatible\n"); +			return -EIO; +		} +	} else if (node < 0) { +		printf("Cannot access node '%s': %s\n", io->name, +		       fdt_strerror(node)); +		return -EIO; +	} +	debug("Write state for '%s' to node %d\n", io->compat, node); +	ret = io->write(blob, node); +	if (ret) { +		printf("Unable to write state for '%s'\n", io->compat); +		return -EINVAL; +	} + +	return 0; +} + +int sandbox_write_state(struct sandbox_state *state, const char *fname) +{ +	struct sandbox_state_io *io; +	bool got_err; +	int size; +	int ret; +	int fd; + +	/* Create a state FDT if we don't have one */ +	if (!state->state_fdt) { +		size = 0x4000; +		state->state_fdt = os_malloc(size); +		if (!state->state_fdt) { +			puts("No memory to create FDT\n"); +			return -ENOMEM; +		} +		ret = fdt_create_empty_tree(state->state_fdt, size); +		if (ret < 0) { +			printf("Cannot create empty state FDT: %s\n", +			       fdt_strerror(ret)); +			ret = -EIO; +			goto err_create; +		} +	} + +	/* Call all the state write funtcions */ +	got_err = false; +	io = ll_entry_start(struct sandbox_state_io, state_io); +	ret = 0; +	for (; io < ll_entry_end(struct sandbox_state_io, state_io); io++) { +		ret = sandbox_write_state_node(state, io); +		if (ret == -EIO) +			break; +		else if (ret) +			got_err = true; +	} + +	if (ret == -EIO) { +		printf("Could not write sandbox state\n"); +		goto err_create; +	} + +	ret = fdt_pack(state->state_fdt); +	if (ret < 0) { +		printf("Cannot pack state FDT: %s\n", fdt_strerror(ret)); +		ret = -EINVAL; +		goto err_create; +	} +	size = fdt_totalsize(state->state_fdt); +	fd = os_open(fname, OS_O_WRONLY | OS_O_CREAT); +	if (fd < 0) { +		printf("Cannot open sandbox state file '%s'\n", fname); +		ret = -EIO; +		goto err_create; +	} +	if (os_write(fd, state->state_fdt, size) != size) { +		printf("Cannot write sandbox state file '%s'\n", fname); +		ret = -EIO; +		goto err_write; +	} +	os_close(fd); + +	debug("Wrote sandbox state to '%s'%s\n", fname, +	      got_err ? " (with errors)" : ""); + +	return 0; +err_write: +	os_close(fd); +err_create: +	os_free(state->state_fdt); + +	return ret; +} + +int state_setprop(int node, const char *prop_name, const void *data, int size) +{ +	void *blob; +	int len; +	int ret; + +	fdt_getprop(state->state_fdt, node, prop_name, &len); + +	/* Add space for the new property, its name and some overhead */ +	ret = state_ensure_space(size - len + strlen(prop_name) + 32); +	if (ret) +		return ret; + +	/* This should succeed, barring a mutiny */ +	blob = state->state_fdt; +	ret = fdt_setprop(blob, node, prop_name, data, size); +	if (ret) { +		printf("%s: Unable to set property '%s' in node '%s': %s\n", +		       __func__, prop_name, fdt_get_name(blob, node, NULL), +			fdt_strerror(ret)); +		return -ENOSPC; +	} + +	return 0; +} +  struct sandbox_state *state_get_current(void)  {  	assert(state); @@ -25,6 +346,10 @@ int state_init(void)  {  	state = &main_state; +	state->ram_size = CONFIG_SYS_SDRAM_SIZE; +	state->ram_buf = os_malloc(state->ram_size); +	assert(state->ram_buf); +  	/*  	 * Example of how to use GPIOs:  	 * @@ -33,3 +358,31 @@ int state_init(void)  	 */  	return 0;  } + +int state_uninit(void) +{ +	int err; + +	state = &main_state; + +	if (state->write_ram_buf) { +		err = os_write_ram_buf(state->ram_buf_fname); +		if (err) { +			printf("Failed to write RAM buffer\n"); +			return err; +		} +	} + +	if (state->write_state) { +		if (sandbox_write_state(state, state->state_fname)) { +			printf("Failed to write sandbox state\n"); +			return -1; +		} +	} + +	if (state->state_fdt) +		os_free(state->state_fdt); +	memset(state, '\0', sizeof(*state)); + +	return 0; +} diff --git a/arch/sandbox/include/asm/global_data.h b/arch/sandbox/include/asm/global_data.h index d70532aa4..b2e9b488f 100644 --- a/arch/sandbox/include/asm/global_data.h +++ b/arch/sandbox/include/asm/global_data.h @@ -12,7 +12,7 @@  /* Architecture-specific global data */  struct arch_global_data { -	u8		*ram_buf;	/* emulated RAM buffer */ +	uint8_t		*ram_buf;	/* emulated RAM buffer */  };  #include <asm-generic/global_data.h> diff --git a/arch/sandbox/include/asm/state.h b/arch/sandbox/include/asm/state.h index a38820bde..e8e4fea1b 100644 --- a/arch/sandbox/include/asm/state.h +++ b/arch/sandbox/include/asm/state.h @@ -7,6 +7,8 @@  #define __SANDBOX_STATE_H  #include <config.h> +#include <stdbool.h> +#include <linux/stringify.h>  /* How we exited U-Boot */  enum exit_type_id { @@ -23,17 +25,92 @@ struct sandbox_spi_info {  /* The complete state of the test system */  struct sandbox_state {  	const char *cmd;		/* Command to execute */ +	bool interactive;		/* Enable cmdline after execute */  	const char *fdt_fname;		/* Filename of FDT binary */  	enum exit_type_id exit_type;	/* How we exited U-Boot */  	const char *parse_err;		/* Error to report from parsing */  	int argc;			/* Program arguments */  	char **argv; +	uint8_t *ram_buf;		/* Emulated RAM buffer */ +	unsigned int ram_size;		/* Size of RAM buffer */ +	const char *ram_buf_fname;	/* Filename to use for RAM buffer */ +	bool write_ram_buf;		/* Write RAM buffer on exit */ +	const char *state_fname;	/* File containing sandbox state */ +	void *state_fdt;		/* Holds saved state for sandbox */ +	bool read_state;		/* Read sandbox state on startup */ +	bool write_state;		/* Write sandbox state on exit */ +	bool ignore_missing_state_on_read;	/* No error if state missing */  	/* Pointer to information for each SPI bus/cs */  	struct sandbox_spi_info spi[CONFIG_SANDBOX_SPI_MAX_BUS]  					[CONFIG_SANDBOX_SPI_MAX_CS];  }; +/* Minimum space we guarantee in the state FDT when calling read/write*/ +#define SANDBOX_STATE_MIN_SPACE		0x1000 + +/** + * struct sandbox_state_io - methods to saved/restore sandbox state + * @name: Name of of the device tree node, also the name of the variable + *	holding this data so it should be an identifier (use underscore + *	instead of minus) + * @compat: Compatible string for the node containing this state + * + * @read: Function to read state from FDT + *	If data is available, then blob and node will provide access to it. If + *	not (blob == NULL and node == -1) this function should set up an empty + *	data set for start-of-day. + *	@param blob: Pointer to device tree blob, or NULL if no data to read + *	@param node: Node offset to read from + *	@return 0 if OK, -ve on error + * + * @write: Function to write state to FDT + *	The caller will ensure that there is a node ready for the state. The + *	node may already contain the old state, in which case it should be + *	overridden. There is guaranteed to be SANDBOX_STATE_MIN_SPACE bytes + *	of free space, so error checking is not required for fdt_setprop...() + *	calls which add up to less than this much space. + * + *	For adding larger properties, use state_setprop(). + * + * @param blob: Device tree blob holding state + * @param node: Node to write our state into + * + * Note that it is possible to save data as large blobs or as individual + * hierarchical properties. However, unless you intend to keep state files + * around for a long time and be able to run an old state file on a new + * sandbox, it might not be worth using individual properties for everything. + * This is certainly supported, it is just a matter of the effort you wish + * to put into the state read/write feature. + */ +struct sandbox_state_io { +	const char *name; +	const char *compat; +	int (*write)(void *blob, int node); +	int (*read)(const void *blob, int node); +}; + +/** + * SANDBOX_STATE_IO - Declare sandbox state to read/write + * + * Sandbox permits saving state from one run and restoring it in another. This + * allows the test system to retain state between runs and thus better + * emulate a real system. Examples of state that might be useful to save are + * the emulated GPIOs pin settings, flash memory contents and TPM private + * data. U-Boot memory contents is dealth with separately since it is large + * and it is not normally useful to save it (since a normal system does not + * preserve DRAM between runs). See the '-m' option for this. + * + * See struct sandbox_state_io above for member documentation. + */ +#define SANDBOX_STATE_IO(_name, _compat, _read, _write) \ +	ll_entry_declare(struct sandbox_state_io, _name, state_io) = { \ +		.name = __stringify(_name), \ +		.read = _read, \ +		.write = _write, \ +		.compat = _compat, \ +	} +  /**   * Record the exit type to be reported by the test program.   * @@ -49,8 +126,59 @@ void state_record_exit(enum exit_type_id exit_type);  struct sandbox_state *state_get_current(void);  /** + * Read the sandbox state from the supplied device tree file + * + * This calls all registered state handlers to read in the sandbox state + * from a previous test run. + * + * @param state		Sandbox state to update + * @param fname		Filename of device tree file to read from + * @return 0 if OK, -ve on error + */ +int sandbox_read_state(struct sandbox_state *state, const char *fname); + +/** + * Write the sandbox state to the supplied device tree file + * + * This calls all registered state handlers to write out the sandbox state + * so that it can be preserved for a future test run. + * + * If the file exists it is overwritten. + * + * @param state		Sandbox state to update + * @param fname		Filename of device tree file to write to + * @return 0 if OK, -ve on error + */ +int sandbox_write_state(struct sandbox_state *state, const char *fname); + +/** + * Add a property to a sandbox state node + * + * This is equivalent to fdt_setprop except that it automatically enlarges + * the device tree if necessary. That means it is safe to write any amount + * of data here. + * + * This function can only be called from within struct sandbox_state_io's + * ->write method, i.e. within state I/O drivers. + * + * @param node		Device tree node to write to + * @param prop_name	Property to write + * @param data		Data to write into property + * @param size		Size of data to write into property + */ +int state_setprop(int node, const char *prop_name, const void *data, int size); + +/**   * Initialize the test system state   */  int state_init(void); +/** + * Uninitialize the test system state, writing out state if configured to + * do so. + * + * @return 0 if OK, -ve on error + */ +int state_uninit(void); +  #endif diff --git a/arch/sandbox/include/asm/u-boot-sandbox.h b/arch/sandbox/include/asm/u-boot-sandbox.h index bed720cf8..5707c2710 100644 --- a/arch/sandbox/include/asm/u-boot-sandbox.h +++ b/arch/sandbox/include/asm/u-boot-sandbox.h @@ -23,4 +23,6 @@ int dram_init(void);  int sandbox_early_getopt_check(void);  int sandbox_main_loop_init(void); +int cleanup_before_linux(void); +  #endif	/* _U_BOOT_SANDBOX_H_ */ |