diff options
Diffstat (limited to 'roms/u-boot/arch/sandbox/cpu')
| -rw-r--r-- | roms/u-boot/arch/sandbox/cpu/Makefile | 22 | ||||
| -rw-r--r-- | roms/u-boot/arch/sandbox/cpu/cpu.c | 68 | ||||
| -rw-r--r-- | roms/u-boot/arch/sandbox/cpu/os.c | 536 | ||||
| -rw-r--r-- | roms/u-boot/arch/sandbox/cpu/sdl.c | 341 | ||||
| -rw-r--r-- | roms/u-boot/arch/sandbox/cpu/start.c | 250 | ||||
| -rw-r--r-- | roms/u-boot/arch/sandbox/cpu/state.c | 392 | ||||
| -rw-r--r-- | roms/u-boot/arch/sandbox/cpu/u-boot.lds | 24 | 
7 files changed, 1633 insertions, 0 deletions
diff --git a/roms/u-boot/arch/sandbox/cpu/Makefile b/roms/u-boot/arch/sandbox/cpu/Makefile new file mode 100644 index 00000000..7d4410c4 --- /dev/null +++ b/roms/u-boot/arch/sandbox/cpu/Makefile @@ -0,0 +1,22 @@ +# +# Copyright (c) 2011 The Chromium OS Authors. +# +# (C) Copyright 2000-2003 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier:	GPL-2.0+ +# + +obj-y	:= cpu.o os.o start.o state.o +obj-$(CONFIG_SANDBOX_SDL)	+= sdl.o + +# os.c is build in the system environment, so needs standard includes +# CFLAGS_REMOVE_os.o cannot be used to drop header include path +quiet_cmd_cc_os.o = CC $(quiet_modtag)  $@ +cmd_cc_os.o = $(CC) $(filter-out -nostdinc, \ +	$(patsubst -I%,-idirafter%,$(c_flags))) -c -o $@ $< + +$(obj)/os.o: $(src)/os.c FORCE +	$(call if_changed_dep,cc_os.o) +$(obj)/sdl.o: $(src)/sdl.c FORCE +	$(call if_changed_dep,cc_os.o) diff --git a/roms/u-boot/arch/sandbox/cpu/cpu.c b/roms/u-boot/arch/sandbox/cpu/cpu.c new file mode 100644 index 00000000..3f4005b5 --- /dev/null +++ b/roms/u-boot/arch/sandbox/cpu/cpu.c @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2011 The Chromium OS Authors. + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> +#include <os.h> +#include <asm/state.h> + +DECLARE_GLOBAL_DATA_PTR; + +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; +} + +/* delay x useconds */ +void __udelay(unsigned long usec) +{ +	os_usleep(usec); +} + +unsigned long __attribute__((no_instrument_function)) timer_get_us(void) +{ +	return os_get_nsec() / 1000; +} + +int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images) +{ +	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) +{ +	return 0; +} + +void *map_physmem(phys_addr_t paddr, unsigned long len, unsigned long flags) +{ +	return (void *)(gd->arch.ram_buf + paddr); +} + +phys_addr_t map_to_sysmem(const void *ptr) +{ +	return (u8 *)ptr - gd->arch.ram_buf; +} + +void flush_dcache_range(unsigned long start, unsigned long stop) +{ +} diff --git a/roms/u-boot/arch/sandbox/cpu/os.c b/roms/u-boot/arch/sandbox/cpu/os.c new file mode 100644 index 00000000..57d04a45 --- /dev/null +++ b/roms/u-boot/arch/sandbox/cpu/os.c @@ -0,0 +1,536 @@ +/* + * Copyright (c) 2011 The Chromium OS Authors. + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <dirent.h> +#include <errno.h> +#include <fcntl.h> +#include <getopt.h> +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <termios.h> +#include <time.h> +#include <unistd.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <sys/time.h> +#include <sys/types.h> +#include <linux/types.h> + +#include <asm/getopt.h> +#include <asm/sections.h> +#include <asm/state.h> +#include <os.h> + +/* 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); +} + +ssize_t os_read_no_block(int fd, void *buf, size_t count) +{ +	const int flags = fcntl(fd, F_GETFL, 0); + +	fcntl(fd, F_SETFL, flags | O_NONBLOCK); +	return os_read(fd, buf, count); +} + +ssize_t os_write(int fd, const void *buf, size_t count) +{ +	return write(fd, buf, count); +} + +off_t os_lseek(int fd, off_t offset, int whence) +{ +	if (whence == OS_SEEK_SET) +		whence = SEEK_SET; +	else if (whence == OS_SEEK_CUR) +		whence = SEEK_CUR; +	else if (whence == OS_SEEK_END) +		whence = SEEK_END; +	else +		os_exit(1); +	return lseek(fd, offset, whence); +} + +int os_open(const char *pathname, int os_flags) +{ +	int flags; + +	switch (os_flags & OS_O_MASK) { +	case OS_O_RDONLY: +	default: +		flags = O_RDONLY; +		break; + +	case OS_O_WRONLY: +		flags = O_WRONLY; +		break; + +	case OS_O_RDWR: +		flags = O_RDWR; +		break; +	} + +	if (os_flags & OS_O_CREAT) +		flags |= O_CREAT; + +	return open(pathname, flags, 0777); +} + +int os_close(int fd) +{ +	return close(fd); +} + +int os_unlink(const char *pathname) +{ +	return unlink(pathname); +} + +void os_exit(int exit_code) +{ +	exit(exit_code); +} + +/* Restore tty state when we exit */ +static struct termios orig_term; +static bool term_setup; + +static void os_fd_restore(void) +{ +	if (term_setup) +		tcsetattr(0, TCSANOW, &orig_term); +} + +/* Put tty into raw mode so <tab> and <ctrl+c> work */ +void os_tty_raw(int fd, bool allow_sigs) +{ +	struct termios term; + +	if (term_setup) +		return; +	term_setup = true; + +	/* If not a tty, don't complain */ +	if (tcgetattr(fd, &orig_term)) +		return; + +	term = orig_term; +	term.c_iflag = IGNBRK | IGNPAR; +	term.c_oflag = OPOST | ONLCR; +	term.c_cflag = CS8 | CREAD | CLOCAL; +	term.c_lflag = allow_sigs ? ISIG : 0; +	if (tcsetattr(fd, TCSANOW, &term)) +		return; + +	atexit(os_fd_restore); +} + +void *os_malloc(size_t length) +{ +	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) +{ +	usleep(usec); +} + +uint64_t __attribute__((no_instrument_function)) os_get_nsec(void) +{ +#if defined(CLOCK_MONOTONIC) && defined(_POSIX_MONOTONIC_CLOCK) +	struct timespec tp; +	if (EINVAL == clock_gettime(CLOCK_MONOTONIC, &tp)) { +		struct timeval tv; + +		gettimeofday(&tv, NULL); +		tp.tv_sec = tv.tv_sec; +		tp.tv_nsec = tv.tv_usec * 1000; +	} +	return tp.tv_sec * 1000000000ULL + tp.tv_nsec; +#else +	struct timeval tv; +	gettimeofday(&tv, NULL); +	return tv.tv_sec * 1000000000ULL + tv.tv_usec * 1000; +#endif +} + +static char *short_opts; +static struct option *long_opts; + +int os_parse_args(struct sandbox_state *state, int argc, char *argv[]) +{ +	struct sandbox_cmdline_option **sb_opt = __u_boot_sandbox_option_start; +	size_t num_options = __u_boot_sandbox_option_count(); +	size_t i; + +	int hidden_short_opt; +	size_t si; + +	int c; + +	if (short_opts || long_opts) +		return 1; + +	state->argc = argc; +	state->argv = argv; + +	/* dynamically construct the arguments to the system getopt_long */ +	short_opts = os_malloc(sizeof(*short_opts) * num_options * 2 + 1); +	long_opts = os_malloc(sizeof(*long_opts) * num_options); +	if (!short_opts || !long_opts) +		return 1; + +	/* +	 * getopt_long requires "val" to be unique (since that is what the +	 * func returns), so generate unique values automatically for flags +	 * that don't have a short option.  pick 0x100 as that is above the +	 * single byte range (where ASCII/ISO-XXXX-X charsets live). +	 */ +	hidden_short_opt = 0x100; +	si = 0; +	for (i = 0; i < num_options; ++i) { +		long_opts[i].name = sb_opt[i]->flag; +		long_opts[i].has_arg = sb_opt[i]->has_arg ? +			required_argument : no_argument; +		long_opts[i].flag = NULL; + +		if (sb_opt[i]->flag_short) { +			short_opts[si++] = long_opts[i].val = sb_opt[i]->flag_short; +			if (long_opts[i].has_arg == required_argument) +				short_opts[si++] = ':'; +		} else +			long_opts[i].val = sb_opt[i]->flag_short = hidden_short_opt++; +	} +	short_opts[si] = '\0'; + +	/* we need to handle output ourselves since u-boot provides printf */ +	opterr = 0; + +	/* +	 * walk all of the options the user gave us on the command line, +	 * figure out what u-boot option structure they belong to (via +	 * the unique short val key), and call the appropriate callback. +	 */ +	while ((c = getopt_long(argc, argv, short_opts, long_opts, NULL)) != -1) { +		for (i = 0; i < num_options; ++i) { +			if (sb_opt[i]->flag_short == c) { +				if (sb_opt[i]->callback(state, optarg)) { +					state->parse_err = sb_opt[i]->flag; +					return 0; +				} +				break; +			} +		} +		if (i == num_options) { +			/* +			 * store the faulting flag for later display.  we have to +			 * store the flag itself as the getopt parsing itself is +			 * tricky: need to handle the following flags (assume all +			 * of the below are unknown): +			 *   -a        optopt='a' optind=<next> +			 *   -abbbb    optopt='a' optind=<this> +			 *   -aaaaa    optopt='a' optind=<this> +			 *   --a       optopt=0   optind=<this> +			 * as you can see, it is impossible to determine the exact +			 * faulting flag without doing the parsing ourselves, so +			 * we just report the specific flag that failed. +			 */ +			if (optopt) { +				static char parse_err[3] = { '-', 0, '\0', }; +				parse_err[1] = optopt; +				state->parse_err = parse_err; +			} else +				state->parse_err = argv[optind - 1]; +			break; +		} +	} + +	return 0; +} + +void os_dirent_free(struct os_dirent_node *node) +{ +	struct os_dirent_node *next; + +	while (node) { +		next = node->next; +		free(node); +		node = next; +	} +} + +int os_dirent_ls(const char *dirname, struct os_dirent_node **headp) +{ +	struct dirent entry, *result; +	struct os_dirent_node *head, *node, *next; +	struct stat buf; +	DIR *dir; +	int ret; +	char *fname; +	int len; + +	*headp = NULL; +	dir = opendir(dirname); +	if (!dir) +		return -1; + +	/* Create a buffer for the maximum filename length */ +	len = sizeof(entry.d_name) + strlen(dirname) + 2; +	fname = malloc(len); +	if (!fname) { +		ret = -ENOMEM; +		goto done; +	} + +	for (node = head = NULL;; node = next) { +		ret = readdir_r(dir, &entry, &result); +		if (ret || !result) +			break; +		next = malloc(sizeof(*node) + strlen(entry.d_name) + 1); +		if (!next) { +			os_dirent_free(head); +			ret = -ENOMEM; +			goto done; +		} +		strcpy(next->name, entry.d_name); +		switch (entry.d_type) { +		case DT_REG: +			next->type = OS_FILET_REG; +			break; +		case DT_DIR: +			next->type = OS_FILET_DIR; +			break; +		case DT_LNK: +			next->type = OS_FILET_LNK; +			break; +		} +		next->size = 0; +		snprintf(fname, len, "%s/%s", dirname, next->name); +		if (!stat(fname, &buf)) +			next->size = buf.st_size; +		if (node) +			node->next = next; +		if (!head) +			head = node; +	} +	*headp = head; + +done: +	closedir(dir); +	return ret; +} + +const char *os_dirent_typename[OS_FILET_COUNT] = { +	"   ", +	"SYM", +	"DIR", +	"???", +}; + +const char *os_dirent_get_typename(enum os_dirent_t type) +{ +	if (type >= 0 && type < OS_FILET_COUNT) +		return os_dirent_typename[type]; + +	return os_dirent_typename[OS_FILET_UNKNOWN]; +} + +ssize_t os_get_filesize(const char *fname) +{ +	struct stat buf; +	int ret; + +	ret = stat(fname, &buf); +	if (ret) +		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; +} + +static int make_exec(char *fname, const void *data, int size) +{ +	int fd; + +	strcpy(fname, "/tmp/u-boot.jump.XXXXXX"); +	fd = mkstemp(fname); +	if (fd < 0) +		return -ENOENT; +	if (write(fd, data, size) < 0) +		return -EIO; +	close(fd); +	if (chmod(fname, 0777)) +		return -ENOEXEC; + +	return 0; +} + +static int add_args(char ***argvp, const char *add_args[], int count) +{ +	char **argv; +	int argc; + +	for (argv = *argvp, argc = 0; (*argvp)[argc]; argc++) +		; + +	argv = malloc((argc + count + 1) * sizeof(char *)); +	if (!argv) { +		printf("Out of memory for %d argv\n", count); +		return -ENOMEM; +	} +	memcpy(argv, *argvp, argc * sizeof(char *)); +	memcpy(argv + argc, add_args, count * sizeof(char *)); +	argv[argc + count] = NULL; + +	*argvp = argv; +	return 0; +} + +int os_jump_to_image(const void *dest, int size) +{ +	struct sandbox_state *state = state_get_current(); +	char fname[30], mem_fname[30]; +	int fd, err; +	const char *extra_args[5]; +	char **argv = state->argv; +#ifdef DEBUG +	int argc, i; +#endif + +	err = make_exec(fname, dest, size); +	if (err) +		return err; + +	strcpy(mem_fname, "/tmp/u-boot.mem.XXXXXX"); +	fd = mkstemp(mem_fname); +	if (fd < 0) +		return -ENOENT; +	close(fd); +	err = os_write_ram_buf(mem_fname); +	if (err) +		return err; + +	os_fd_restore(); + +	extra_args[0] = "-j"; +	extra_args[1] = fname; +	extra_args[2] = "-m"; +	extra_args[3] = mem_fname; +	extra_args[4] = "--rm_memory"; +	err = add_args(&argv, extra_args, +		       sizeof(extra_args) / sizeof(extra_args[0])); +	if (err) +		return err; + +#ifdef DEBUG +	for (i = 0; argv[i]; i++) +		printf("%d %s\n", i, argv[i]); +#endif + +	if (state_uninit()) +		os_exit(2); + +	err = execv(fname, argv); +	free(argv); +	if (err) +		return err; + +	return unlink(fname); +} diff --git a/roms/u-boot/arch/sandbox/cpu/sdl.c b/roms/u-boot/arch/sandbox/cpu/sdl.c new file mode 100644 index 00000000..18dc7edf --- /dev/null +++ b/roms/u-boot/arch/sandbox/cpu/sdl.c @@ -0,0 +1,341 @@ +/* + * Copyright (c) 2013 Google, Inc + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <errno.h> +#include <linux/input.h> +#include <SDL/SDL.h> +#include <sound.h> +#include <asm/state.h> + +static struct sdl_info { +	SDL_Surface *screen; +	int width; +	int height; +	int depth; +	int pitch; +	uint frequency; +	uint audio_pos; +	uint audio_size; +	uint8_t *audio_data; +	bool audio_active; +	bool inited; +} sdl; + +static void sandbox_sdl_poll_events(void) +{ +	/* +	 * We don't want to include common.h in this file since it uses +	 * system headers. So add a declation here. +	 */ +	extern void reset_cpu(unsigned long addr); +	SDL_Event event; + +	while (SDL_PollEvent(&event)) { +		switch (event.type) { +		case SDL_QUIT: +			puts("LCD window closed - quitting\n"); +			reset_cpu(1); +			break; +		} +	} +} + +static int sandbox_sdl_ensure_init(void) +{ +	if (!sdl.inited) { +		if (SDL_Init(0) < 0) { +			printf("Unable to initialize SDL: %s\n", +			       SDL_GetError()); +			return -EIO; +		} + +		atexit(SDL_Quit); + +		sdl.inited = true; +	} +	return 0; +} + +int sandbox_sdl_init_display(int width, int height, int log2_bpp) +{ +	struct sandbox_state *state = state_get_current(); +	int err; + +	if (!width || !state->show_lcd) +		return 0; +	err = sandbox_sdl_ensure_init(); +	if (err) +		return err; +	if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0) { +		printf("Unable to initialize SDL LCD: %s\n", SDL_GetError()); +		return -EPERM; +	} +	SDL_WM_SetCaption("U-Boot", "U-Boot"); + +	sdl.width = width; +	sdl.height = height; +	sdl.depth = 1 << log2_bpp; +	sdl.pitch = sdl.width * sdl.depth / 8; +	sdl.screen = SDL_SetVideoMode(width, height, 0, 0); +	sandbox_sdl_poll_events(); + +	return 0; +} + +int sandbox_sdl_sync(void *lcd_base) +{ +	SDL_Surface *frame; + +	frame = SDL_CreateRGBSurfaceFrom(lcd_base, sdl.width, sdl.height, +			sdl.depth, sdl.pitch, +			0x1f << 11, 0x3f << 5, 0x1f << 0, 0); +	SDL_BlitSurface(frame, NULL, sdl.screen, NULL); +	SDL_FreeSurface(frame); +	SDL_UpdateRect(sdl.screen, 0, 0, 0, 0); +	sandbox_sdl_poll_events(); + +	return 0; +} + +#define NONE (-1) +#define NUM_SDL_CODES	(SDLK_UNDO + 1) + +static int16_t sdl_to_keycode[NUM_SDL_CODES] = { +	/* 0 */ +	NONE, NONE, NONE, NONE, NONE, +	NONE, NONE, NONE, KEY_BACKSPACE, KEY_TAB, +	NONE, NONE, NONE, KEY_ENTER, NONE, +	NONE, NONE, NONE, NONE, KEY_POWER,	/* use PAUSE as POWER */ + +	/* 20 */ +	NONE, NONE, NONE, NONE, NONE, +	NONE, NONE, KEY_ESC, NONE, NONE, +	NONE, NONE, KEY_SPACE, NONE, NONE, +	NONE, NONE, NONE, NONE, NONE, + +	/* 40 */ +	NONE, NONE, NONE, NONE, KEY_COMMA, +	KEY_MINUS, KEY_DOT, KEY_SLASH, KEY_0, KEY_1, +	KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, +	KEY_7, KEY_8, KEY_9, NONE, KEY_SEMICOLON, + +	/* 60 */ +	NONE, KEY_EQUAL, NONE, NONE, NONE, +	NONE, NONE, NONE, NONE, NONE, +	NONE, NONE, NONE, NONE, NONE, +	NONE, NONE, NONE, NONE, NONE, + +	/* 80 */ +	NONE, NONE, NONE, NONE, NONE, +	NONE, NONE, NONE, NONE, NONE, +	NONE, NONE, KEY_BACKSLASH, NONE, NONE, +	NONE, KEY_GRAVE, KEY_A, KEY_B, KEY_C, + +	/* 100 */ +	KEY_D, KEY_E, KEY_F, KEY_G, KEY_H, +	KEY_I, KEY_J, KEY_K, KEY_L, KEY_M, +	KEY_N, KEY_O, KEY_P, KEY_Q, KEY_R, +	KEY_S, KEY_T, KEY_U, KEY_V, KEY_W, + +	/* 120 */ +	KEY_X, KEY_Y, KEY_Z, NONE, NONE, +	NONE, NONE, KEY_DELETE, NONE, NONE, +	NONE, NONE, NONE, NONE, NONE, +	NONE, NONE, NONE, NONE, NONE, + +	/* 140 */ +	NONE, NONE, NONE, NONE, NONE, +	NONE, NONE, NONE, NONE, NONE, +	NONE, NONE, NONE, NONE, NONE, +	NONE, NONE, NONE, NONE, NONE, + +	/* 160 */ +	NONE, NONE, NONE, NONE, NONE, +	NONE, NONE, NONE, NONE, NONE, +	NONE, NONE, NONE, NONE, NONE, +	NONE, NONE, NONE, NONE, NONE, + +	/* 180 */ +	NONE, NONE, NONE, NONE, NONE, +	NONE, NONE, NONE, NONE, NONE, +	NONE, NONE, NONE, NONE, NONE, +	NONE, NONE, NONE, NONE, NONE, + +	/* 200 */ +	NONE, NONE, NONE, NONE, NONE, +	NONE, NONE, NONE, NONE, NONE, +	NONE, NONE, NONE, NONE, NONE, +	NONE, NONE, NONE, NONE, NONE, + +	/* 220 */ +	NONE, NONE, NONE, NONE, NONE, +	NONE, NONE, NONE, NONE, NONE, +	NONE, NONE, NONE, NONE, NONE, +	NONE, NONE, NONE, NONE, NONE, + +	/* 240 */ +	NONE, NONE, NONE, NONE, NONE, +	NONE, NONE, NONE, NONE, NONE, +	NONE, NONE, NONE, NONE, NONE, +	NONE, KEY_KP0, KEY_KP1, KEY_KP2, KEY_KP3, + +	/* 260 */ +	KEY_KP4, KEY_KP5, KEY_KP6, KEY_KP7, KEY_KP8, +	KEY_KP9, KEY_KPDOT, KEY_KPSLASH, KEY_KPASTERISK, KEY_KPMINUS, +	KEY_KPPLUS, KEY_KPENTER, KEY_KPEQUAL, KEY_UP, KEY_DOWN, +	KEY_RIGHT, KEY_LEFT, KEY_INSERT, KEY_HOME, KEY_END, + +	/* 280 */ +	KEY_PAGEUP, KEY_PAGEDOWN, KEY_F1, KEY_F2, KEY_F3, +	KEY_F4, KEY_F5, KEY_F6, KEY_F7, KEY_F8, +	KEY_F9, KEY_F10, KEY_F11, KEY_F12, NONE, +	NONE, NONE, NONE, NONE, NONE, + +	/* 300 */ +	KEY_NUMLOCK, KEY_CAPSLOCK, KEY_SCROLLLOCK, KEY_RIGHTSHIFT, +		KEY_LEFTSHIFT, +	KEY_RIGHTCTRL, KEY_LEFTCTRL, KEY_RIGHTALT, KEY_LEFTALT, KEY_RIGHTMETA, +	KEY_LEFTMETA, NONE, KEY_FN, NONE, KEY_COMPOSE, +	NONE, KEY_PRINT, KEY_SYSRQ, KEY_PAUSE, NONE, + +	/* 320 */ +	NONE, NONE, NONE, +}; + +int sandbox_sdl_scan_keys(int key[], int max_keys) +{ +	Uint8 *keystate; +	int i, count; + +	sandbox_sdl_poll_events(); +	keystate = SDL_GetKeyState(NULL); +	for (i = count = 0; i < NUM_SDL_CODES; i++) { +		if (count >= max_keys) +			break; +		else if (keystate[i]) +			key[count++] = sdl_to_keycode[i]; +	} + +	return count; +} + +int sandbox_sdl_key_pressed(int keycode) +{ +	int key[8];	/* allow up to 8 keys to be pressed at once */ +	int count; +	int i; + +	count = sandbox_sdl_scan_keys(key, sizeof(key) / sizeof(key[0])); +	for (i = 0; i < count; i++) { +		if (key[i] == keycode) +			return 0; +	} + +	return -ENOENT; +} + +void sandbox_sdl_fill_audio(void *udata, Uint8 *stream, int len) +{ +	int avail; + +	avail = sdl.audio_size - sdl.audio_pos; +	if (avail < len) +		len = avail; + +	SDL_MixAudio(stream, sdl.audio_data + sdl.audio_pos, len, +		     SDL_MIX_MAXVOLUME); +	sdl.audio_pos += len; + +	/* Loop if we are at the end */ +	if (sdl.audio_pos == sdl.audio_size) +		sdl.audio_pos = 0; +} + +int sandbox_sdl_sound_init(void) +{ +	SDL_AudioSpec wanted; + +	if (sandbox_sdl_ensure_init()) +		return -1; + +	if (sdl.audio_active) +		return 0; + +	/* +	 * At present all sandbox sounds crash. This is probably due to +	 * symbol name conflicts with U-Boot. We can remove the malloc() +	 * probles with: +	 * +	 * #define USE_DL_PREFIX +	 * +	 * and get this: +	 * +	 * Assertion 'e->pollfd->fd == e->fd' failed at pulse/mainloop.c:676, +	 *		function dispatch_pollfds(). Aborting. +	 * +	 * The right solution is probably to make U-Boot's names private or +	 * link os.c and sdl.c against their libraries before liking with +	 * U-Boot. TBD. For now sound is disabled. +	 */ +	printf("(Warning: sandbox sound disabled)\n"); +	return 0; + +	/* Set the audio format */ +	wanted.freq = 22050; +	wanted.format = AUDIO_S16; +	wanted.channels = 1;    /* 1 = mono, 2 = stereo */ +	wanted.samples = 1024;  /* Good low-latency value for callback */ +	wanted.callback = sandbox_sdl_fill_audio; +	wanted.userdata = NULL; + +	sdl.audio_size = sizeof(uint16_t) * wanted.freq; +	sdl.audio_data = malloc(sdl.audio_size); +	if (!sdl.audio_data) { +		printf("%s: Out of memory\n", __func__); +		return -1; +	} +	sdl.audio_pos = 0; + +	if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) { +		printf("Unable to initialize SDL audio: %s\n", SDL_GetError()); +		goto err; +	} + +	/* Open the audio device, forcing the desired format */ +	if (SDL_OpenAudio(&wanted, NULL) < 0) { +		printf("Couldn't open audio: %s\n", SDL_GetError()); +		goto err; +	} +	sdl.audio_active = true; + +	return 0; + +err: +	free(sdl.audio_data); +	return -1; +} + +int sandbox_sdl_sound_start(uint frequency) +{ +	if (!sdl.audio_active) +		return -1; +	sdl.frequency = frequency; +	sound_create_square_wave((unsigned short *)sdl.audio_data, +				 sdl.audio_size, frequency); +	sdl.audio_pos = 0; +	SDL_PauseAudio(0); + +	return 0; +} + +int sandbox_sdl_sound_stop(void) +{ +	if (!sdl.audio_active) +		return -1; +	SDL_PauseAudio(1); + +	return 0; +} diff --git a/roms/u-boot/arch/sandbox/cpu/start.c b/roms/u-boot/arch/sandbox/cpu/start.c new file mode 100644 index 00000000..aad3b8b1 --- /dev/null +++ b/roms/u-boot/arch/sandbox/cpu/start.c @@ -0,0 +1,250 @@ +/* + * Copyright (c) 2011-2012 The Chromium OS Authors. + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> +#include <os.h> +#include <asm/getopt.h> +#include <asm/sections.h> +#include <asm/state.h> + +DECLARE_GLOBAL_DATA_PTR; + +int sandbox_early_getopt_check(void) +{ +	struct sandbox_state *state = state_get_current(); +	struct sandbox_cmdline_option **sb_opt = __u_boot_sandbox_option_start; +	size_t num_options = __u_boot_sandbox_option_count(); +	size_t i; +	int max_arg_len, max_noarg_len; + +	/* parse_err will be a string of the faulting option */ +	if (!state->parse_err) +		return 0; + +	if (strcmp(state->parse_err, "help")) { +		printf("u-boot: error: failed while parsing option: %s\n" +			"\ttry running with --help for more information.\n", +			state->parse_err); +		os_exit(1); +	} + +	printf( +		"u-boot, a command line test interface to U-Boot\n\n" +		"Usage: u-boot [options]\n" +		"Options:\n"); + +	max_arg_len = 0; +	for (i = 0; i < num_options; ++i) +		max_arg_len = max(strlen(sb_opt[i]->flag), max_arg_len); +	max_noarg_len = max_arg_len + 7; + +	for (i = 0; i < num_options; ++i) { +		struct sandbox_cmdline_option *opt = sb_opt[i]; + +		/* first output the short flag if it has one */ +		if (opt->flag_short >= 0x100) +			printf("      "); +		else +			printf("  -%c, ", opt->flag_short); + +		/* then the long flag */ +		if (opt->has_arg) +			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); +	} + +	os_exit(0); +} + +static int sandbox_cmdline_cb_help(struct sandbox_state *state, const char *arg) +{ +	/* just flag to sandbox_early_getopt_check to show usage */ +	return 1; +} +SANDBOX_CMDLINE_OPT_SHORT(help, 'h', 0, "Display help"); + +int sandbox_main_loop_init(void) +{ +	struct sandbox_state *state = state_get_current(); + +	/* Execute command if required */ +	if (state->cmd) { +		run_command_list(state->cmd, -1, 0); +		if (!state->interactive) +			os_exit(state->exit_type); +	} + +	return 0; +} + +static int sandbox_cmdline_cb_command(struct sandbox_state *state, +				      const char *arg) +{ +	state->cmd = arg; +	return 0; +} +SANDBOX_CMDLINE_OPT_SHORT(command, 'c', 1, "Execute U-Boot command"); + +static int sandbox_cmdline_cb_fdt(struct sandbox_state *state, const char *arg) +{ +	state->fdt_fname = arg; +	return 0; +} +SANDBOX_CMDLINE_OPT_SHORT(fdt, 'd', 1, "Specify U-Boot's control FDT"); + +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_jump(struct sandbox_state *state, +				   const char *arg) +{ +	/* Remember to delete this U-Boot image later */ +	state->jumped_fname = arg; + +	return 0; +} +SANDBOX_CMDLINE_OPT_SHORT(jump, 'j', 1, "Jumped from previous U-Boot"); + +static int sandbox_cmdline_cb_memory(struct sandbox_state *state, +				     const char *arg) +{ +	int 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_rm_memory(struct sandbox_state *state, +					const char *arg) +{ +	state->ram_buf_rm = true; + +	return 0; +} +SANDBOX_CMDLINE_OPT(rm_memory, 0, "Remove memory file after reading"); + +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"); + +static int sandbox_cmdline_cb_show_lcd(struct sandbox_state *state, +				       const char *arg) +{ +	state->show_lcd = true; +	return 0; +} +SANDBOX_CMDLINE_OPT_SHORT(show_lcd, 'l', 0, +			  "Show the sandbox LCD display"); + +static const char *term_args[STATE_TERM_COUNT] = { +	"raw-with-sigs", +	"raw", +	"cooked", +}; + +static int sandbox_cmdline_cb_terminal(struct sandbox_state *state, +				       const char *arg) +{ +	int i; + +	for (i = 0; i < STATE_TERM_COUNT; i++) { +		if (!strcmp(arg, term_args[i])) { +			state->term_raw = i; +			return 0; +		} +	} + +	printf("Unknown terminal setting '%s' (", arg); +	for (i = 0; i < STATE_TERM_COUNT; i++) +		printf("%s%s", i ? ", " : "", term_args[i]); +	puts(")\n"); + +	return 1; +} +SANDBOX_CMDLINE_OPT_SHORT(terminal, 't', 1, +			  "Set terminal to raw/cooked mode"); + +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; + +	ret = sandbox_read_state(state, state->state_fname); +	if (ret) +		goto err; + +	/* Remove old memory file if required */ +	if (state->ram_buf_rm && state->ram_buf_fname) +		os_unlink(state->ram_buf_fname); + +	/* Do pre- and post-relocation init */ +	board_init_f(0); + +	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/roms/u-boot/arch/sandbox/cpu/state.c b/roms/u-boot/arch/sandbox/cpu/state.c new file mode 100644 index 00000000..59adad65 --- /dev/null +++ b/roms/u-boot/arch/sandbox/cpu/state.c @@ -0,0 +1,392 @@ +/* + * Copyright (c) 2011-2012 The Chromium OS Authors. + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> +#include <errno.h> +#include <fdtdec.h> +#include <os.h> +#include <asm/state.h> + +/* Main state record for the sandbox */ +static struct sandbox_state main_state; +static struct sandbox_state *state;	/* Pointer to current state record */ + +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); +	return state; +} + +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: +	 * +	 * sandbox_gpio_set_direction(170, 0); +	 * sandbox_gpio_set_value(170, 0); +	 */ +	return 0; +} + +int state_uninit(void) +{ +	int err; + +	state = &main_state; + +	if (state->write_ram_buf && !state->ram_buf_rm) { +		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; +		} +	} + +	/* Delete this at the last moment so as not to upset gdb too much */ +	if (state->jumped_fname) +		os_unlink(state->jumped_fname); + +	if (state->state_fdt) +		os_free(state->state_fdt); +	memset(state, '\0', sizeof(*state)); + +	return 0; +} diff --git a/roms/u-boot/arch/sandbox/cpu/u-boot.lds b/roms/u-boot/arch/sandbox/cpu/u-boot.lds new file mode 100644 index 00000000..7e92b4ac --- /dev/null +++ b/roms/u-boot/arch/sandbox/cpu/u-boot.lds @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2011-2012 The Chromium OS Authors. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +SECTIONS +{ + +	. = ALIGN(4); +	.u_boot_list : { +		KEEP(*(SORT(.u_boot_list*))); +	} + +	__u_boot_sandbox_option_start = .; +	_u_boot_sandbox_getopt : { *(.u_boot_sandbox_getopt) } +	__u_boot_sandbox_option_end = .; + +	__bss_start = .; +} + +INSERT BEFORE .data;  | 
