diff options
53 files changed, 1314 insertions, 96 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_ */ diff --git a/arch/sh/cpu/sh2/config.mk b/arch/sh/cpu/sh2/config.mk index 8a0de9671..69273b4f3 100644 --- a/arch/sh/cpu/sh2/config.mk +++ b/arch/sh/cpu/sh2/config.mk @@ -12,7 +12,7 @@ PLATFORM_CPPFLAGS += -m2a -m2a-nofpu -mb -ffreestanding  else # SH2  PLATFORM_CPPFLAGS += -m3e -mb  endif -PLATFORM_CPPFLAGS += $(call cc-option,-mno-fdpic) +PLATFORM_CPPFLAGS += -DCONFIG_SH2 $(call cc-option,-mno-fdpic)  PLATFORM_RELFLAGS += -ffixed-r13  PLATFORM_LDFLAGS += $(ENDIANNESS) diff --git a/arch/sh/cpu/sh2/cpu.c b/arch/sh/cpu/sh2/cpu.c index 18479a4c4..a2f856f45 100644 --- a/arch/sh/cpu/sh2/cpu.c +++ b/arch/sh/cpu/sh2/cpu.c @@ -23,11 +23,7 @@  int checkcpu(void)  { -#if defined(CONFIG_SH2A) -	puts("CPU: SH2A\n"); -#else  	puts("CPU: SH2\n"); -#endif  	return 0;  } diff --git a/arch/sh/cpu/sh3/config.mk b/arch/sh/cpu/sh3/config.mk index 5c77e5c32..abd4b8d2b 100644 --- a/arch/sh/cpu/sh3/config.mk +++ b/arch/sh/cpu/sh3/config.mk @@ -11,5 +11,5 @@  # SPDX-License-Identifier:	GPL-2.0+  #  # -PLATFORM_CPPFLAGS += -m3 +PLATFORM_CPPFLAGS += -DCONFIG_SH3 -m3  PLATFORM_RELFLAGS += -ffixed-r13 diff --git a/arch/sh/cpu/sh4/config.mk b/arch/sh/cpu/sh4/config.mk index c3575570e..753580beb 100644 --- a/arch/sh/cpu/sh4/config.mk +++ b/arch/sh/cpu/sh4/config.mk @@ -8,5 +8,5 @@  # SPDX-License-Identifier:	GPL-2.0+  #  # -PLATFORM_CPPFLAGS += -m4-nofpu +PLATFORM_CPPFLAGS += -DCONFIG_SH4 -m4-nofpu  PLATFORM_RELFLAGS += -ffixed-r13 diff --git a/arch/sh/cpu/sh4/cpu.c b/arch/sh/cpu/sh4/cpu.c index 91133a38a..e8ee0a45a 100644 --- a/arch/sh/cpu/sh4/cpu.c +++ b/arch/sh/cpu/sh4/cpu.c @@ -13,11 +13,7 @@  int checkcpu(void)  { -#ifdef CONFIG_SH4A -	puts("CPU: SH-4A\n"); -#else  	puts("CPU: SH4\n"); -#endif  	return 0;  } diff --git a/arch/sh/include/asm/cache.h b/arch/sh/include/asm/cache.h index b21dc4422..0698a3775 100644 --- a/arch/sh/include/asm/cache.h +++ b/arch/sh/include/asm/cache.h @@ -1,7 +1,7 @@  #ifndef __ASM_SH_CACHE_H  #define __ASM_SH_CACHE_H -#if defined(CONFIG_SH4) || defined(CONFIG_SH4A) +#if defined(CONFIG_SH4)  int cache_control(unsigned int cmd); @@ -18,7 +18,7 @@ struct __large_struct { unsigned long buf[100]; };   */  #define ARCH_DMA_MINALIGN	32 -#endif /* CONFIG_SH4 || CONFIG_SH4A */ +#endif /* CONFIG_SH4 */  /*   * Use the L1 data cache line size value for the minimum DMA buffer alignment diff --git a/arch/sh/include/asm/processor.h b/arch/sh/include/asm/processor.h index 938a89cff..b8677da95 100644 --- a/arch/sh/include/asm/processor.h +++ b/arch/sh/include/asm/processor.h @@ -1,12 +1,10 @@  #ifndef _ASM_SH_PROCESSOR_H_  #define _ASM_SH_PROCESSOR_H_ -#if defined(CONFIG_SH2) || \ -	defined (CONFIG_SH2A) +#if defined(CONFIG_SH2)  # include <asm/cpu_sh2.h> -#elif defined (CONFIG_SH3) +#elif defined(CONFIG_SH3)  # include <asm/cpu_sh3.h> -#elif defined (CONFIG_SH4) || \ -	defined (CONFIG_SH4A) +#elif defined(CONFIG_SH4)  # include <asm/cpu_sh4.h>  #endif  #endif diff --git a/arch/sh/lib/time_sh2.c b/arch/sh/lib/time_sh2.c index be3896c3e..4b1f47b6a 100644 --- a/arch/sh/lib/time_sh2.c +++ b/arch/sh/lib/time_sh2.c @@ -84,5 +84,5 @@ void __udelay(unsigned long usec)  unsigned long get_tbclk(void)  { -	return CONFIG_SYS_HZ; +	return CONFIG_SH_CMT_CLK_FREQ;  } diff --git a/common/board_f.c b/common/board_f.c index fcfd713b0..c2f47bc18 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -347,9 +347,10 @@ done:  #ifdef CONFIG_SANDBOX  static int setup_ram_buf(void)  { -	gd->arch.ram_buf = os_malloc(CONFIG_SYS_SDRAM_SIZE); -	assert(gd->arch.ram_buf); -	gd->ram_size = CONFIG_SYS_SDRAM_SIZE; +	struct sandbox_state *state = state_get_current(); + +	gd->arch.ram_buf = state->ram_buf; +	gd->ram_size = state->ram_size;  	return 0;  } @@ -772,7 +773,7 @@ static int setup_reloc(void)  }  /* ARM calls relocate_code from its crt0.S */ -#if !defined(CONFIG_ARM) +#if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX)  static int jump_to_copy(void)  { @@ -792,8 +793,6 @@ static int jump_to_copy(void)  	 * (CPU cache)  	 */  	board_init_f_r_trampoline(gd->start_addr_sp); -#elif defined(CONFIG_SANDBOX) -	board_init_r(gd->new_gd, 0);  #else  	relocate_code(gd->start_addr_sp, gd->new_gd, gd->relocaddr);  #endif @@ -995,7 +994,7 @@ static init_fnc_t init_sequence_f[] = {  	INIT_FUNC_WATCHDOG_RESET  	reloc_fdt,  	setup_reloc, -#ifndef CONFIG_ARM +#if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX)  	jump_to_copy,  #endif  	NULL, @@ -1015,7 +1014,7 @@ void board_init_f(ulong boot_flags)  	if (initcall_run_list(init_sequence_f))  		hang(); -#ifndef CONFIG_ARM +#if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX)  	/* NOTREACHED - jump_to_copy() does not return */  	hang();  #endif diff --git a/common/cmd_sandbox.c b/common/cmd_sandbox.c index 8d59364b6..00982b164 100644 --- a/common/cmd_sandbox.c +++ b/common/cmd_sandbox.c @@ -6,6 +6,9 @@  #include <common.h>  #include <fs.h> +#include <part.h> +#include <sandboxblockdev.h> +#include <asm/errno.h>  static int do_sandbox_load(cmd_tbl_t *cmdtp, int flag, int argc,  			   char * const argv[]) @@ -25,10 +28,69 @@ static int do_sandbox_save(cmd_tbl_t *cmdtp, int flag, int argc,  	return do_save(cmdtp, flag, argc, argv, FS_TYPE_SANDBOX);  } +static int do_sandbox_bind(cmd_tbl_t *cmdtp, int flag, int argc, +			   char * const argv[]) +{ +	if (argc < 2 || argc > 3) +		return CMD_RET_USAGE; +	char *ep; +	char *dev_str = argv[1]; +	char *file = argc >= 3 ? argv[2] : NULL; +	int dev = simple_strtoul(dev_str, &ep, 16); +	if (*ep) { +		printf("** Bad device specification %s **\n", dev_str); +		return CMD_RET_USAGE; +	} +	return host_dev_bind(dev, file); +} + +static int do_sandbox_info(cmd_tbl_t *cmdtp, int flag, int argc, +			   char * const argv[]) +{ +	if (argc < 1 || argc > 2) +		return CMD_RET_USAGE; +	int min_dev = 0; +	int max_dev = CONFIG_HOST_MAX_DEVICES - 1; +	if (argc >= 2) { +		char *ep; +		char *dev_str = argv[1]; +		int dev = simple_strtoul(dev_str, &ep, 16); +		if (*ep) { +			printf("** Bad device specification %s **\n", dev_str); +			return CMD_RET_USAGE; +		} +		min_dev = dev; +		max_dev = dev; +	} +	int dev; +	printf("%3s %12s %s\n", "dev", "blocks", "path"); +	for (dev = min_dev; dev <= max_dev; dev++) { +		block_dev_desc_t *blk_dev; +		int ret; + +		printf("%3d ", dev); +		ret = host_get_dev_err(dev, &blk_dev); +		if (ret) { +			if (ret == -ENOENT) +				puts("Not bound to a backing file\n"); +			else if (ret == -ENODEV) +				puts("Invalid host device number\n"); + +			continue; +		} +		struct host_block_dev *host_dev = blk_dev->priv; +		printf("%12lu %s\n", (unsigned long)blk_dev->lba, +		       host_dev->filename); +	} +	return 0; +} +  static cmd_tbl_t cmd_sandbox_sub[] = {  	U_BOOT_CMD_MKENT(load, 7, 0, do_sandbox_load, "", ""),  	U_BOOT_CMD_MKENT(ls, 3, 0, do_sandbox_ls, "", ""),  	U_BOOT_CMD_MKENT(save, 6, 0, do_sandbox_save, "", ""), +	U_BOOT_CMD_MKENT(bind, 3, 0, do_sandbox_bind, "", ""), +	U_BOOT_CMD_MKENT(info, 3, 0, do_sandbox_info, "", ""),  };  static int do_sandbox(cmd_tbl_t *cmdtp, int flag, int argc, @@ -57,4 +119,6 @@ U_BOOT_CMD(  	"sb ls host <filename>                      - list files on host\n"  	"sb save host <dev> <filename> <addr> <bytes> [<offset>] - "  		"save a file to host\n" +	"sb bind <dev> [<filename>] - bind \"host\" device to file\n" +	"sb info [<dev>]            - show device binding & info"  ); diff --git a/common/console.c b/common/console.c index cc55068c7..2dfb78888 100644 --- a/common/console.c +++ b/common/console.c @@ -8,6 +8,7 @@  #include <common.h>  #include <stdarg.h>  #include <malloc.h> +#include <os.h>  #include <serial.h>  #include <stdio_dev.h>  #include <exports.h> @@ -415,6 +416,12 @@ static inline void print_pre_console_buffer(void) {}  void putc(const char c)  { +#ifdef CONFIG_SANDBOX +	if (!gd) { +		os_putc(c); +		return; +	} +#endif  #ifdef CONFIG_SILENT_CONSOLE  	if (gd->flags & GD_FLG_SILENT)  		return; @@ -439,6 +446,13 @@ void putc(const char c)  void puts(const char *s)  { +#ifdef CONFIG_SANDBOX +	if (!gd) { +		os_puts(s); +		return; +	} +#endif +  #ifdef CONFIG_SILENT_CONSOLE  	if (gd->flags & GD_FLG_SILENT)  		return; @@ -467,7 +481,7 @@ int printf(const char *fmt, ...)  	uint i;  	char printbuffer[CONFIG_SYS_PBSIZE]; -#ifndef CONFIG_PRE_CONSOLE_BUFFER +#if !defined(CONFIG_SANDBOX) && !defined(CONFIG_PRE_CONSOLE_BUFFER)  	if (!gd->have_console)  		return 0;  #endif diff --git a/disk/part.c b/disk/part.c index d2e34cfcf..6941033d8 100644 --- a/disk/part.c +++ b/disk/part.c @@ -43,6 +43,9 @@ static const struct block_drvr block_drvr[] = {  #if defined(CONFIG_SYSTEMACE)  	{ .name = "ace", .get_dev = systemace_get_dev, },  #endif +#if defined(CONFIG_SANDBOX) +	{ .name = "host", .get_dev = host_get_dev, }, +#endif  	{ },  }; @@ -286,6 +289,9 @@ static void print_part_header (const char *type, block_dev_desc_t * dev_desc)  	case IF_TYPE_MMC:  		puts ("MMC");  		break; +	case IF_TYPE_HOST: +		puts("HOST"); +		break;  	default:  		puts ("UNKNOWN");  		break; diff --git a/drivers/block/Makefile b/drivers/block/Makefile index 4e9437838..8697da426 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -18,5 +18,6 @@ obj-$(CONFIG_SATA_DWC) += sata_dwc.o  obj-$(CONFIG_SATA_SIL3114) += sata_sil3114.o  obj-$(CONFIG_SATA_SIL) += sata_sil.o  obj-$(CONFIG_IDE_SIL680) += sil680.o +obj-$(CONFIG_SANDBOX) += sandbox.o  obj-$(CONFIG_SCSI_SYM53C8XX) += sym53c8xx.o  obj-$(CONFIG_SYSTEMACE) += systemace.o diff --git a/drivers/block/sandbox.c b/drivers/block/sandbox.c new file mode 100644 index 000000000..73f4c4a9e --- /dev/null +++ b/drivers/block/sandbox.c @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2013 Henrik Nordstrom <henrik@henriknordstrom.net> + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <config.h> +#include <common.h> +#include <part.h> +#include <os.h> +#include <malloc.h> +#include <sandboxblockdev.h> +#include <asm/errno.h> + +static struct host_block_dev host_devices[CONFIG_HOST_MAX_DEVICES]; + +static struct host_block_dev *find_host_device(int dev) +{ +	if (dev >= 0 && dev < CONFIG_HOST_MAX_DEVICES) +		return &host_devices[dev]; + +	return NULL; +} + +static unsigned long host_block_read(int dev, unsigned long start, +				     lbaint_t blkcnt, void *buffer) +{ +	struct host_block_dev *host_dev = find_host_device(dev); + +	if (!host_dev) +		return -1; +	if (os_lseek(host_dev->fd, +		     start * host_dev->blk_dev.blksz, +		     OS_SEEK_SET) == -1) { +		printf("ERROR: Invalid position\n"); +		return -1; +	} +	ssize_t len = os_read(host_dev->fd, buffer, +			      blkcnt * host_dev->blk_dev.blksz); +	if (len >= 0) +		return len / host_dev->blk_dev.blksz; +	return -1; +} + +static unsigned long host_block_write(int dev, unsigned long start, +				      lbaint_t blkcnt, const void *buffer) +{ +	struct host_block_dev *host_dev = find_host_device(dev); +	if (os_lseek(host_dev->fd, +		     start * host_dev->blk_dev.blksz, +		     OS_SEEK_SET) == -1) { +		printf("ERROR: Invalid position\n"); +		return -1; +	} +	ssize_t len = os_write(host_dev->fd, buffer, blkcnt * +			       host_dev->blk_dev.blksz); +	if (len >= 0) +		return len / host_dev->blk_dev.blksz; +	return -1; +} + +int host_dev_bind(int dev, char *filename) +{ +	struct host_block_dev *host_dev = find_host_device(dev); + +	if (!host_dev) +		return -1; +	if (host_dev->blk_dev.priv) { +		os_close(host_dev->fd); +		host_dev->blk_dev.priv = NULL; +	} +	if (host_dev->filename) +		free(host_dev->filename); +	if (filename && *filename) { +		host_dev->filename = strdup(filename); +	} else { +		host_dev->filename = NULL; +		return 0; +	} + +	host_dev->fd = os_open(host_dev->filename, OS_O_RDWR); +	if (host_dev->fd == -1) { +		printf("Failed to access host backing file '%s'\n", +		       host_dev->filename); +		return 1; +	} + +	block_dev_desc_t *blk_dev = &host_dev->blk_dev; +	blk_dev->if_type = IF_TYPE_HOST; +	blk_dev->priv = host_dev; +	blk_dev->blksz = 512; +	blk_dev->lba = os_lseek(host_dev->fd, 0, OS_SEEK_END) / blk_dev->blksz; +	blk_dev->block_read = host_block_read; +	blk_dev->block_write = host_block_write; +	blk_dev->dev = dev; +	blk_dev->part_type = PART_TYPE_UNKNOWN; +	init_part(blk_dev); + +	return 0; +} + +int host_get_dev_err(int dev, block_dev_desc_t **blk_devp) +{ +	struct host_block_dev *host_dev = find_host_device(dev); + +	if (!host_dev) +		return -ENODEV; + +	if (!host_dev->blk_dev.priv) +		return -ENOENT; + +	*blk_devp = &host_dev->blk_dev; +	return 0; +} + +block_dev_desc_t *host_get_dev(int dev) +{ +	block_dev_desc_t *blk_dev; + +	if (host_get_dev_err(dev, &blk_dev)) +		return NULL; + +	return blk_dev; +} diff --git a/drivers/tpm/Makefile b/drivers/tpm/Makefile index 2f2353f80..150570ee7 100644 --- a/drivers/tpm/Makefile +++ b/drivers/tpm/Makefile @@ -8,3 +8,4 @@ obj-$(CONFIG_TPM_ATMEL_TWI) += tpm_atmel_twi.o  obj-$(CONFIG_TPM_TIS_I2C) += tpm.o  obj-$(CONFIG_TPM_TIS_I2C) += tpm_tis_i2c.o  obj-$(CONFIG_TPM_TIS_LPC) += tpm_tis_lpc.o +obj-$(CONFIG_TPM_TIS_SANDBOX) += tpm_tis_sandbox.o diff --git a/drivers/tpm/tpm_tis_sandbox.c b/drivers/tpm/tpm_tis_sandbox.c new file mode 100644 index 000000000..ed4b03912 --- /dev/null +++ b/drivers/tpm/tpm_tis_sandbox.c @@ -0,0 +1,260 @@ +/* + * Copyright (c) 2013 Google, Inc + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> +#include <asm/state.h> +#include <asm/unaligned.h> +#include <linux/crc8.h> + +/* TPM NVRAM location indices. */ +#define FIRMWARE_NV_INDEX		0x1007 +#define KERNEL_NV_INDEX			0x1008 + +#define NV_DATA_PUBLIC_PERMISSIONS_OFFSET	60 + +/* Kernel TPM space - KERNEL_NV_INDEX, locked with physical presence */ +#define ROLLBACK_SPACE_KERNEL_VERSION	2 +#define ROLLBACK_SPACE_KERNEL_UID	0x4752574C  /* 'GRWL' */ + +struct rollback_space_kernel { +	/* Struct version, for backwards compatibility */ +	uint8_t struct_version; +	/* Unique ID to detect space redefinition */ +	uint32_t uid; +	/* Kernel versions */ +	uint32_t kernel_versions; +	/* Reserved for future expansion */ +	uint8_t reserved[3]; +	/* Checksum (v2 and later only) */ +	uint8_t crc8; +} __packed rollback_space_kernel; + +/* + * These numbers derive from adding the sizes of command fields as shown in + * the TPM commands manual. + */ +#define TPM_REQUEST_HEADER_LENGTH	10 +#define TPM_RESPONSE_HEADER_LENGTH	10 + +/* These are the different non-volatile spaces that we emulate */ +enum { +	NV_GLOBAL_LOCK, +	NV_SEQ_FIRMWARE, +	NV_SEQ_KERNEL, +	NV_SEQ_COUNT, +}; + +/* Size of each non-volatile space */ +#define NV_DATA_SIZE		0x20 + +/* + * Information about our TPM emulation. This is preserved in the sandbox + * state file if enabled. + */ +static struct tpm_state { +	uint8_t nvdata[NV_SEQ_COUNT][NV_DATA_SIZE]; +} state; + +/** + * sandbox_tpm_read_state() - read the sandbox EC state from the state file + * + * If data is available, then blob and node will provide access to it. If + * not this function sets up an empty TPM. + * + * @blob: Pointer to device tree blob, or NULL if no data to read + * @node: Node offset to read from + */ +static int sandbox_tpm_read_state(const void *blob, int node) +{ +	const char *prop; +	int len; +	int i; + +	if (!blob) +		return 0; + +	for (i = 0; i < NV_SEQ_COUNT; i++) { +		char prop_name[20]; + +		sprintf(prop_name, "nvdata%d", i); +		prop = fdt_getprop(blob, node, prop_name, &len); +		if (prop && len == NV_DATA_SIZE) +			memcpy(state.nvdata[i], prop, NV_DATA_SIZE); +	} + +	return 0; +} + +/** + * cros_ec_write_state() - Write out our state to the state file + * + * 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 is overridden. + * + * @blob: Device tree blob holding state + * @node: Node to write our state into + */ +static int sandbox_tpm_write_state(void *blob, int node) +{ +	int i; + +	/* +	 * We are guaranteed enough space to write basic properties. +	 * We could use fdt_add_subnode() to put each set of data in its +	 * own node - perhaps useful if we add access informaiton to each. +	 */ +	for (i = 0; i < NV_SEQ_COUNT; i++) { +		char prop_name[20]; + +		sprintf(prop_name, "nvdata%d", i); +		fdt_setprop(blob, node, prop_name, state.nvdata[i], +			    NV_DATA_SIZE); +	} + +	return 0; +} + +SANDBOX_STATE_IO(sandbox_tpm, "google,sandbox-tpm", sandbox_tpm_read_state, +		 sandbox_tpm_write_state); + +static int index_to_seq(uint32_t index) +{ +	switch (index) { +	case FIRMWARE_NV_INDEX: +		return NV_SEQ_FIRMWARE; +	case KERNEL_NV_INDEX: +		return NV_SEQ_KERNEL; +	case 0: +		return NV_GLOBAL_LOCK; +	} + +	printf("Invalid nv index %#x\n", index); +	return -1; +} + +int tis_sendrecv(const u8 *sendbuf, size_t send_size, +		 u8 *recvbuf, size_t *recv_len) +{ +	struct tpm_state *tpm = &state; +	uint32_t code, index, length, type; +	uint8_t *data; +	int seq; + +	code = get_unaligned_be32(sendbuf + sizeof(uint16_t) + +				  sizeof(uint32_t)); +	printf("tpm: %zd bytes, recv_len %zd, cmd = %x\n", send_size, +	       *recv_len, code); +	print_buffer(0, sendbuf, 1, send_size, 0); +	switch (code) { +	case 0x65: /* get flags */ +		type = get_unaligned_be32(sendbuf + 14); +		switch (type) { +		case 4: +			index = get_unaligned_be32(sendbuf + 18); +			printf("Get flags index %#02x\n", index); +			*recv_len = 22; +			memset(recvbuf, '\0', *recv_len); +			put_unaligned_be32(22, recvbuf + +					   TPM_RESPONSE_HEADER_LENGTH); +			data = recvbuf + TPM_RESPONSE_HEADER_LENGTH + +					sizeof(uint32_t); +			switch (index) { +			case FIRMWARE_NV_INDEX: +				break; +			case KERNEL_NV_INDEX: +				/* TPM_NV_PER_PPWRITE */ +				put_unaligned_be32(1, data + +					NV_DATA_PUBLIC_PERMISSIONS_OFFSET); +				break; +			} +			break; +		case 0x11: /* TPM_CAP_NV_INDEX */ +			index = get_unaligned_be32(sendbuf + 18); +			printf("Get cap nv index %#02x\n", index); +			put_unaligned_be32(22, recvbuf + +					   TPM_RESPONSE_HEADER_LENGTH); +			break; +		default: +			printf("   ** Unknown 0x65 command type %#02x\n", +			       type); +			return -1; +		} +		break; +	case 0xcd: /* nvwrite */ +		index = get_unaligned_be32(sendbuf + 10); +		length = get_unaligned_be32(sendbuf + 18); +		seq = index_to_seq(index); +		if (seq < 0) +			return -1; +		printf("tpm: nvwrite index=%#02x, len=%#02x\n", index, length); +		memcpy(&tpm->nvdata[seq], sendbuf + 22, length); +		*recv_len = 12; +		memset(recvbuf, '\0', *recv_len); +		break; +	case 0xcf: /* nvread */ +		index = get_unaligned_be32(sendbuf + 10); +		length = get_unaligned_be32(sendbuf + 18); +		seq = index_to_seq(index); +		if (seq < 0) +			return -1; +		printf("tpm: nvread index=%#02x, len=%#02x\n", index, length); +		*recv_len = TPM_RESPONSE_HEADER_LENGTH + sizeof(uint32_t) + +					length; +		memset(recvbuf, '\0', *recv_len); +		put_unaligned_be32(length, recvbuf + +				   TPM_RESPONSE_HEADER_LENGTH); +		if (seq == NV_SEQ_KERNEL) { +			struct rollback_space_kernel rsk; + +			data = recvbuf + TPM_RESPONSE_HEADER_LENGTH + +					sizeof(uint32_t); +			rsk.struct_version = 2; +			rsk.uid = ROLLBACK_SPACE_KERNEL_UID; +			rsk.kernel_versions = 0; +			rsk.crc8 = crc8((unsigned char *)&rsk, +					offsetof(struct rollback_space_kernel, +						 crc8)); +			memcpy(data, &rsk, sizeof(rsk)); +		} else { +			memcpy(recvbuf + TPM_RESPONSE_HEADER_LENGTH + +			       sizeof(uint32_t), &tpm->nvdata[seq], length); +		} +		break; +	case 0x14: /* tpm extend */ +	case 0x15: /* pcr read */ +	case 0x5d: /* force clear */ +	case 0x6f: /* physical enable */ +	case 0x72: /* physical set deactivated */ +	case 0x99: /* startup */ +	case 0x4000000a:  /* assert physical presence */ +		*recv_len = 12; +		memset(recvbuf, '\0', *recv_len); +		break; +	default: +		printf("Unknown tpm command %02x\n", code); +		return -1; +	} + +	return 0; +} + +int tis_open(void) +{ +	printf("%s\n", __func__); +	return 0; +} + +int tis_close(void) +{ +	printf("%s\n", __func__); +	return 0; +} + +int tis_init(void) +{ +	printf("%s\n", __func__); +	return 0; +} diff --git a/include/config_fallbacks.h b/include/config_fallbacks.h index 3633b09aa..d8339b26c 100644 --- a/include/config_fallbacks.h +++ b/include/config_fallbacks.h @@ -50,7 +50,8 @@  	defined(CONFIG_CMD_PART) || \  	defined(CONFIG_CMD_GPT) || \  	defined(CONFIG_MMC) || \ -	defined(CONFIG_SYSTEMACE) +	defined(CONFIG_SYSTEMACE) || \ +	defined(CONFIG_SANDBOX)  #define HAVE_BLOCK_DEVICE  #endif diff --git a/include/configs/MigoR.h b/include/configs/MigoR.h index 9fd455142..88df94f11 100644 --- a/include/configs/MigoR.h +++ b/include/configs/MigoR.h @@ -10,8 +10,6 @@  #define __MIGO_R_H  #undef DEBUG -#define CONFIG_SH		1 -#define CONFIG_SH4		1  #define CONFIG_CPU_SH7722	1  #define CONFIG_MIGO_R		1 diff --git a/include/configs/ap325rxa.h b/include/configs/ap325rxa.h index 933de52c5..462b2e291 100644 --- a/include/configs/ap325rxa.h +++ b/include/configs/ap325rxa.h @@ -11,8 +11,6 @@  #define __AP325RXA_H  #undef DEBUG -#define CONFIG_SH		1 -#define CONFIG_SH4		1  #define CONFIG_CPU_SH7723	1  #define CONFIG_AP325RXA	1 diff --git a/include/configs/ap_sh4a_4a.h b/include/configs/ap_sh4a_4a.h index 83a5c37e4..bb39491f8 100644 --- a/include/configs/ap_sh4a_4a.h +++ b/include/configs/ap_sh4a_4a.h @@ -10,9 +10,6 @@  #define __AP_SH4A_4A_H  #undef DEBUG -#define CONFIG_SH		1 -#define CONFIG_SH4		1 -#define CONFIG_SH4A		1  #define CONFIG_CPU_SH7734	1  #define CONFIG_AP_SH4A_4A	1  #define CONFIG_400MHZ_MODE	1 diff --git a/include/configs/ecovec.h b/include/configs/ecovec.h index 3483cf1f5..3a5cc7482 100644 --- a/include/configs/ecovec.h +++ b/include/configs/ecovec.h @@ -23,9 +23,6 @@   */  #undef DEBUG -#define CONFIG_SH		1 -#define CONFIG_SH4		1 -#define CONFIG_SH4A		1  #define CONFIG_CPU_SH7724	1  #define CONFIG_BOARD_LATE_INIT		1  #define CONFIG_ECOVEC		1 diff --git a/include/configs/espt.h b/include/configs/espt.h index 1bd7eeceb..de16be70b 100644 --- a/include/configs/espt.h +++ b/include/configs/espt.h @@ -10,8 +10,6 @@  #ifndef __ESPT_H  #define __ESPT_H -#define CONFIG_SH		1 -#define CONFIG_SH4		1  #define CONFIG_CPU_SH7763	1  #define CONFIG_ESPT	1  #define __LITTLE_ENDIAN		1 diff --git a/include/configs/mpr2.h b/include/configs/mpr2.h index fcf237edb..8ae497c6d 100644 --- a/include/configs/mpr2.h +++ b/include/configs/mpr2.h @@ -24,8 +24,6 @@  #define CONFIG_VERSION_VARIABLE  /* CPU and platform */ -#define CONFIG_SH		1 -#define CONFIG_SH3		1  #define CONFIG_CPU_SH7720	1  #define CONFIG_MPR2		1 diff --git a/include/configs/ms7720se.h b/include/configs/ms7720se.h index ec8523eb9..585d68f20 100644 --- a/include/configs/ms7720se.h +++ b/include/configs/ms7720se.h @@ -9,8 +9,6 @@  #ifndef __MS7720SE_H  #define __MS7720SE_H -#define CONFIG_SH		1 -#define CONFIG_SH3		1  #define CONFIG_CPU_SH7720	1  #define CONFIG_MS7720SE		1 diff --git a/include/configs/ms7722se.h b/include/configs/ms7722se.h index 54fb7c3e8..1c8ada6c0 100644 --- a/include/configs/ms7722se.h +++ b/include/configs/ms7722se.h @@ -9,8 +9,6 @@  #ifndef __MS7722SE_H  #define __MS7722SE_H -#define CONFIG_SH		1 -#define CONFIG_SH4		1  #define CONFIG_CPU_SH7722	1  #define CONFIG_MS7722SE		1 diff --git a/include/configs/ms7750se.h b/include/configs/ms7750se.h index eea3bd1f2..4cf8efeca 100644 --- a/include/configs/ms7750se.h +++ b/include/configs/ms7750se.h @@ -9,8 +9,6 @@  #ifndef __MS7750SE_H  #define __MS7750SE_H -#define CONFIG_SH		1 -#define CONFIG_SH4		1  #define CONFIG_CPU_SH7750	1  /* #define CONFIG_CPU_SH7751	1 */  /* #define CONFIG_CPU_TYPE_R	1 */ diff --git a/include/configs/r0p7734.h b/include/configs/r0p7734.h index dd26a71bc..53128ecc1 100644 --- a/include/configs/r0p7734.h +++ b/include/configs/r0p7734.h @@ -10,9 +10,6 @@  #define __R0P7734_H  #undef DEBUG -#define CONFIG_SH		1 -#define CONFIG_SH4		1 -#define CONFIG_SH4A		1  #define CONFIG_CPU_SH7734	1  #define CONFIG_R0P7734		1  #define CONFIG_400MHZ_MODE	1 diff --git a/include/configs/r2dplus.h b/include/configs/r2dplus.h index ddcc97587..24d0c34db 100644 --- a/include/configs/r2dplus.h +++ b/include/configs/r2dplus.h @@ -3,8 +3,6 @@  #undef DEBUG -#define CONFIG_SH		1 -#define CONFIG_SH4		1  #define CONFIG_CPU_SH7751	1  #define CONFIG_CPU_SH_TYPE_R	1  #define CONFIG_R2DPLUS		1 diff --git a/include/configs/r7780mp.h b/include/configs/r7780mp.h index f5e4daab8..8156724f7 100644 --- a/include/configs/r7780mp.h +++ b/include/configs/r7780mp.h @@ -11,8 +11,6 @@  #define __R7780RP_H  #undef DEBUG -#define CONFIG_SH		1 -#define CONFIG_SH4A		1  #define CONFIG_CPU_SH7780	1  #define CONFIG_R7780MP		1  #define CONFIG_SYS_R7780MP_OLD_FLASH	1 diff --git a/include/configs/rsk7203.h b/include/configs/rsk7203.h index acee4e898..543632458 100644 --- a/include/configs/rsk7203.h +++ b/include/configs/rsk7203.h @@ -11,8 +11,6 @@  #define __RSK7203_H  #undef DEBUG -#define CONFIG_SH		1 -#define CONFIG_SH2		1  #define CONFIG_SH2A		1  #define CONFIG_CPU_SH7203	1  #define CONFIG_RSK7203	1 @@ -87,7 +85,7 @@  #define CONFIG_SH_TMU_CLK_FREQ CONFIG_SYS_CLK_FREQ  #define CONFIG_SH_SCIF_CLK_FREQ CONFIG_SYS_CLK_FREQ  #define CMT_CLK_DIVIDER	32	/* 8 (default), 32, 128 or 512 */ -#define CONFIG_SYS_HZ			(CONFIG_SYS_CLK_FREQ / CMT_CLK_DIVIDER) +#define CONFIG_SH_CMT_CLK_FREQ (CONFIG_SYS_CLK_FREQ / CMT_CLK_DIVIDER)  /* Network interface */  #define CONFIG_SMC911X diff --git a/include/configs/rsk7264.h b/include/configs/rsk7264.h index a5dbb64f4..4aaa3ef74 100644 --- a/include/configs/rsk7264.h +++ b/include/configs/rsk7264.h @@ -12,8 +12,6 @@  #define __RSK7264_H  #undef DEBUG -#define CONFIG_SH		1 -#define CONFIG_SH2		1  #define CONFIG_SH2A		1  #define CONFIG_CPU_SH7264	1  #define CONFIG_RSK7264		1 @@ -67,7 +65,7 @@  #define CONFIG_SH_TMU_CLK_FREQ CONFIG_SYS_CLK_FREQ  #define CONFIG_SH_SCIF_CLK_FREQ CONFIG_SYS_CLK_FREQ  #define CMT_CLK_DIVIDER		32	/* 8 (default), 32, 128 or 512 */ -#define CONFIG_SYS_HZ		(CONFIG_SYS_CLK_FREQ / CMT_CLK_DIVIDER) +#define CONFIG_SH_CMT_CLK_FREQ (CONFIG_SYS_CLK_FREQ / CMT_CLK_DIVIDER)  /* Network interface */  #define CONFIG_SMC911X diff --git a/include/configs/rsk7269.h b/include/configs/rsk7269.h index 9f54160af..11fc231fa 100644 --- a/include/configs/rsk7269.h +++ b/include/configs/rsk7269.h @@ -11,8 +11,6 @@  #define __RSK7269_H  #undef DEBUG -#define CONFIG_SH		1 -#define CONFIG_SH2		1  #define CONFIG_SH2A		1  #define CONFIG_CPU_SH7269	1  #define CONFIG_RSK7269		1 @@ -66,7 +64,7 @@  #define CONFIG_SH_TMU_CLK_FREQ CONFIG_SYS_CLK_FREQ  #define CONFIG_SH_SCIF_CLK_FREQ CONFIG_SYS_CLK_FREQ  #define CMT_CLK_DIVIDER		32	/* 8 (default), 32, 128 or 512 */ -#define CONFIG_SYS_HZ		(CONFIG_SYS_CLK_FREQ / CMT_CLK_DIVIDER) +#define CONFIG_SH_CMT_CLK_FREQ (CONFIG_SYS_CLK_FREQ / CMT_CLK_DIVIDER)  /* Network interface */  #define CONFIG_SMC911X diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h index 7e78a231d..a6d55822b 100644 --- a/include/configs/sandbox.h +++ b/include/configs/sandbox.h @@ -39,6 +39,9 @@  #define CONFIG_CMD_FAT  #define CONFIG_CMD_EXT4  #define CONFIG_CMD_EXT4_WRITE +#define CONFIG_CMD_PART +#define CONFIG_DOS_PARTITION +#define CONFIG_HOST_MAX_DEVICES 4  #define CONFIG_SYS_VSNPRINTF @@ -126,4 +129,6 @@  #define CONFIG_LZO  #define CONFIG_LZMA +#define CONFIG_TPM_TIS_SANDBOX +  #endif diff --git a/include/configs/sh7752evb.h b/include/configs/sh7752evb.h index ebdc5c8b0..f06abbca0 100644 --- a/include/configs/sh7752evb.h +++ b/include/configs/sh7752evb.h @@ -10,8 +10,6 @@  #define __SH7752EVB_H  #undef DEBUG -#define CONFIG_SH		1 -#define CONFIG_SH4A		1  #define CONFIG_SH_32BIT		1  #define CONFIG_CPU_SH7752	1  #define CONFIG_SH7752EVB	1 diff --git a/include/configs/sh7753evb.h b/include/configs/sh7753evb.h index f7eb86d1d..e400db08a 100644 --- a/include/configs/sh7753evb.h +++ b/include/configs/sh7753evb.h @@ -10,8 +10,6 @@  #define __SH7753EVB_H  #undef DEBUG -#define CONFIG_SH		1 -#define CONFIG_SH4A		1  #define CONFIG_SH_32BIT		1  #define CONFIG_CPU_SH7753	1  #define CONFIG_SH7753EVB	1 diff --git a/include/configs/sh7757lcr.h b/include/configs/sh7757lcr.h index ce1add268..08bff1da3 100644 --- a/include/configs/sh7757lcr.h +++ b/include/configs/sh7757lcr.h @@ -10,8 +10,6 @@  #define __SH7757LCR_H  #undef DEBUG -#define CONFIG_SH		1 -#define CONFIG_SH4A		1  #define CONFIG_SH_32BIT		1  #define CONFIG_CPU_SH7757	1  #define CONFIG_SH7757LCR	1 diff --git a/include/configs/sh7763rdp.h b/include/configs/sh7763rdp.h index a13778830..2438318fc 100644 --- a/include/configs/sh7763rdp.h +++ b/include/configs/sh7763rdp.h @@ -10,8 +10,6 @@  #ifndef __SH7763RDP_H  #define __SH7763RDP_H -#define CONFIG_SH		1 -#define CONFIG_SH4		1  #define CONFIG_CPU_SH7763	1  #define CONFIG_SH7763RDP	1  #define __LITTLE_ENDIAN		1 diff --git a/include/configs/sh7785lcr.h b/include/configs/sh7785lcr.h index 4acbcab1b..2723eaf2d 100644 --- a/include/configs/sh7785lcr.h +++ b/include/configs/sh7785lcr.h @@ -10,8 +10,6 @@  #define __SH7785LCR_H  #undef DEBUG -#define CONFIG_SH		1 -#define CONFIG_SH4A		1  #define CONFIG_CPU_SH7785	1  #define CONFIG_SH7785LCR	1 diff --git a/include/configs/shmin.h b/include/configs/shmin.h index 5c990fc96..f8155efbc 100644 --- a/include/configs/shmin.h +++ b/include/configs/shmin.h @@ -9,8 +9,6 @@  #ifndef __SHMIN_H  #define __SHMIN_H -#define CONFIG_SH		1 -#define CONFIG_SH3		1  #define CONFIG_CPU_SH7706	1  /* T-SH7706LAN */  #define CONFIG_SHMIN		1 diff --git a/include/linux/crc8.h b/include/linux/crc8.h new file mode 100644 index 000000000..b5fd2ac9d --- /dev/null +++ b/include/linux/crc8.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2013 Google, Inc + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + + +#ifndef __linux_crc8_h +#define __linux_crc8_h + +/** + * crc8() - Calculate and return CRC-8 of the data + * + * This uses an x^8 + x^2 + x + 1 polynomial.  A table-based algorithm would + * be faster, but for only a few bytes it isn't worth the code size + * + * @vptr: Buffer to checksum + * @len: Length of buffer in bytes + * @return CRC8 checksum + */ +unsigned int crc8(const unsigned char *vptr, int len); + +#endif diff --git a/include/os.h b/include/os.h index 950433daa..b65fba430 100644 --- a/include/os.h +++ b/include/os.h @@ -107,6 +107,35 @@ void os_tty_raw(int fd);  void *os_malloc(size_t length);  /** + * Free memory previous allocated with os_malloc()/os_realloc() + * + * This returns the memory to the OS. + * + * \param ptr		Pointer to memory block to free + */ +void *os_free(void *ptr); + +/** + * Reallocate previously-allocated memory to increase/decrease space + * + * This works in a similar way to the C library realloc() function. If + * length is 0, then ptr is freed. Otherwise the space used by ptr is + * expanded or reduced depending on whether length is larger or smaller + * than before. + * + * If ptr is NULL, then this is similar to calling os_malloc(). + * + * This function may need to move the memory block to make room for any + * extra space, in which case the new pointer is returned. + * + * \param ptr		Pointer to memory block to reallocate + * \param length	New length for memory block + * \return pointer to new memory block, or NULL on failure or if length + *	is 0. + */ +void *os_realloc(void *ptr, size_t length); + +/**   * Access to the usleep function of the os   *   * \param usec Time to sleep in micro seconds @@ -180,4 +209,40 @@ const char *os_dirent_get_typename(enum os_dirent_t type);   */  ssize_t os_get_filesize(const char *fname); +/** + * Write a character to the controlling OS terminal + * + * This bypasses the U-Boot console support and writes directly to the OS + * stdout file descriptor. + * + * @param ch	Character to write + */ +void os_putc(int ch); + +/** + * Write a string to the controlling OS terminal + * + * This bypasses the U-Boot console support and writes directly to the OS + * stdout file descriptor. + * + * @param str	String to write (note that \n is not appended) + */ +void os_puts(const char *str); + +/** + * Write the sandbox RAM buffer to a existing file + * + * @param fname		Filename to write memory to (simple binary format) + * @return 0 if OK, -ve on error + */ +int os_write_ram_buf(const char *fname); + +/** + * Read the sandbox RAM buffer from an existing file + * + * @param fname		Filename containing memory (simple binary format) + * @return 0 if OK, -ve on error + */ +int os_read_ram_buf(const char *fname); +  #endif diff --git a/include/part.h b/include/part.h index ce840bd84..4beb6db89 100644 --- a/include/part.h +++ b/include/part.h @@ -58,6 +58,8 @@ typedef struct block_dev_desc {  #define IF_TYPE_MMC		6  #define IF_TYPE_SD		7  #define IF_TYPE_SATA		8 +#define IF_TYPE_HOST		9 +#define IF_TYPE_MAX		10	/* Max number of IF_TYPE_* supported */  /* Part types */  #define PART_TYPE_UNKNOWN	0x00 @@ -102,6 +104,8 @@ block_dev_desc_t* usb_stor_get_dev(int dev);  block_dev_desc_t* mmc_get_dev(int dev);  block_dev_desc_t* systemace_get_dev(int dev);  block_dev_desc_t* mg_disk_get_dev(int dev); +block_dev_desc_t *host_get_dev(int dev); +int host_get_dev_err(int dev, block_dev_desc_t **blk_devp);  /* disk/part.c */  int get_partition_info (block_dev_desc_t * dev_desc, int part, disk_partition_t *info); @@ -123,6 +127,7 @@ static inline block_dev_desc_t* usb_stor_get_dev(int dev) { return NULL; }  static inline block_dev_desc_t* mmc_get_dev(int dev) { return NULL; }  static inline block_dev_desc_t* systemace_get_dev(int dev) { return NULL; }  static inline block_dev_desc_t* mg_disk_get_dev(int dev) { return NULL; } +static inline block_dev_desc_t *host_get_dev(int dev) { return NULL; }  static inline int get_partition_info (block_dev_desc_t * dev_desc, int part,  	disk_partition_t *info) { return -1; } diff --git a/include/sandboxblockdev.h b/include/sandboxblockdev.h new file mode 100644 index 000000000..627787aa3 --- /dev/null +++ b/include/sandboxblockdev.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2013, Henrik Nordstrom <henrik@henriknordstrom.net> + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#ifndef __SANDBOX_BLOCK_DEV__ +#define __SANDBOX_BLOCK_DEV__ + +struct host_block_dev { +	block_dev_desc_t blk_dev; +	char *filename; +	int fd; +}; + +int host_dev_bind(int dev, char *filename); + +#endif diff --git a/include/sh_tmu.h b/include/sh_tmu.h index f5b42faea..61afc7136 100644 --- a/include/sh_tmu.h +++ b/include/sh_tmu.h @@ -47,7 +47,7 @@ struct tmu_regs {  };  #endif /* CONFIG_SH3 */ -#if defined(CONFIG_SH4) || defined(CONFIG_SH4A) || defined(CONFIG_RMOBILE) +#if defined(CONFIG_SH4) || defined(CONFIG_RMOBILE)  struct tmu_regs {  	u32 reserved;  	u8  tstr; diff --git a/lib/Makefile b/lib/Makefile index e787f77be..760340fbd 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -21,6 +21,7 @@ obj-$(CONFIG_BZIP2) += bzlib_randtable.o  obj-$(CONFIG_BZIP2) += bzlib_huffman.o  obj-$(CONFIG_USB_TTY) += circbuf.o  obj-y += crc7.o +obj-y += crc8.o  obj-y += crc16.o  obj-$(CONFIG_OF_CONTROL) += fdtdec.o  obj-$(CONFIG_TEST_FDTDEC) += fdtdec_test.o diff --git a/lib/crc8.c b/lib/crc8.c new file mode 100644 index 000000000..8b68a29e4 --- /dev/null +++ b/lib/crc8.c @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2013 Google, Inc + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include "linux/crc8.h" + +unsigned int crc8(const unsigned char *vptr, int len) +{ +	const unsigned char *data = vptr; +	unsigned int crc = 0; +	int i, j; + +	for (j = len; j; j--, data++) { +		crc ^= (*data << 8); +		for (i = 8; i; i--) { +			if (crc & 0x8000) +				crc ^= (0x1070 << 3); +			crc <<= 1; +		} +	} + +	return (crc >> 8) & 0xff; +} |