xref: /rk3399_rockchip-uboot/arch/sandbox/cpu/os.c (revision d4e33f5a72accc891e3600cb2d2bc579004de9e1)
17a9219c1SSimon Glass /*
27a9219c1SSimon Glass  * Copyright (c) 2011 The Chromium OS Authors.
31a459660SWolfgang Denk  * SPDX-License-Identifier:	GPL-2.0+
47a9219c1SSimon Glass  */
57a9219c1SSimon Glass 
662584db1SSimon Glass #include <dirent.h>
7e1012472SSimon Glass #include <errno.h>
87a9219c1SSimon Glass #include <fcntl.h>
970db4212SSimon Glass #include <getopt.h>
1062584db1SSimon Glass #include <stdio.h>
112a54d159SSimon Glass #include <stdint.h>
127a9219c1SSimon Glass #include <stdlib.h>
1362584db1SSimon Glass #include <string.h>
14ab06a758SMike Frysinger #include <termios.h>
15d99a6874SMatthias Weisser #include <time.h>
16e1012472SSimon Glass #include <unistd.h>
1721899b10SMatthias Weisser #include <sys/mman.h>
18e1012472SSimon Glass #include <sys/stat.h>
193bdf56b7SSimon Glass #include <sys/time.h>
20e1012472SSimon Glass #include <sys/types.h>
21d99a6874SMatthias Weisser #include <linux/types.h>
227a9219c1SSimon Glass 
2370db4212SSimon Glass #include <asm/getopt.h>
2470db4212SSimon Glass #include <asm/sections.h>
2570db4212SSimon Glass #include <asm/state.h>
267a9219c1SSimon Glass #include <os.h>
2794eefdeeSSimon Glass #include <rtc_def.h>
287a9219c1SSimon Glass 
297a9219c1SSimon Glass /* Operating System Interface */
307a9219c1SSimon Glass 
3177595c6dSSimon Glass struct os_mem_hdr {
3277595c6dSSimon Glass 	size_t length;		/* number of bytes in the block */
3377595c6dSSimon Glass };
3477595c6dSSimon Glass 
357a9219c1SSimon Glass ssize_t os_read(int fd, void *buf, size_t count)
367a9219c1SSimon Glass {
377a9219c1SSimon Glass 	return read(fd, buf, count);
387a9219c1SSimon Glass }
397a9219c1SSimon Glass 
40e101550aSTaylor Hutt ssize_t os_read_no_block(int fd, void *buf, size_t count)
41e101550aSTaylor Hutt {
42e101550aSTaylor Hutt 	const int flags = fcntl(fd, F_GETFL, 0);
43e101550aSTaylor Hutt 
44e101550aSTaylor Hutt 	fcntl(fd, F_SETFL, flags | O_NONBLOCK);
45e101550aSTaylor Hutt 	return os_read(fd, buf, count);
46e101550aSTaylor Hutt }
47e101550aSTaylor Hutt 
487a9219c1SSimon Glass ssize_t os_write(int fd, const void *buf, size_t count)
497a9219c1SSimon Glass {
507a9219c1SSimon Glass 	return write(fd, buf, count);
517a9219c1SSimon Glass }
527a9219c1SSimon Glass 
53e2dcefcbSMike Frysinger off_t os_lseek(int fd, off_t offset, int whence)
54e2dcefcbSMike Frysinger {
55e2dcefcbSMike Frysinger 	if (whence == OS_SEEK_SET)
56e2dcefcbSMike Frysinger 		whence = SEEK_SET;
57e2dcefcbSMike Frysinger 	else if (whence == OS_SEEK_CUR)
58e2dcefcbSMike Frysinger 		whence = SEEK_CUR;
59e2dcefcbSMike Frysinger 	else if (whence == OS_SEEK_END)
60e2dcefcbSMike Frysinger 		whence = SEEK_END;
61e2dcefcbSMike Frysinger 	else
62e2dcefcbSMike Frysinger 		os_exit(1);
63e2dcefcbSMike Frysinger 	return lseek(fd, offset, whence);
64e2dcefcbSMike Frysinger }
65e2dcefcbSMike Frysinger 
66d9165153SSimon Glass int os_open(const char *pathname, int os_flags)
677a9219c1SSimon Glass {
68d9165153SSimon Glass 	int flags;
69d9165153SSimon Glass 
70d9165153SSimon Glass 	switch (os_flags & OS_O_MASK) {
71d9165153SSimon Glass 	case OS_O_RDONLY:
72d9165153SSimon Glass 	default:
73d9165153SSimon Glass 		flags = O_RDONLY;
74d9165153SSimon Glass 		break;
75d9165153SSimon Glass 
76d9165153SSimon Glass 	case OS_O_WRONLY:
77d9165153SSimon Glass 		flags = O_WRONLY;
78d9165153SSimon Glass 		break;
79d9165153SSimon Glass 
80d9165153SSimon Glass 	case OS_O_RDWR:
81d9165153SSimon Glass 		flags = O_RDWR;
82d9165153SSimon Glass 		break;
83d9165153SSimon Glass 	}
84d9165153SSimon Glass 
85d9165153SSimon Glass 	if (os_flags & OS_O_CREAT)
86d9165153SSimon Glass 		flags |= O_CREAT;
87d9165153SSimon Glass 
88d9165153SSimon Glass 	return open(pathname, flags, 0777);
897a9219c1SSimon Glass }
907a9219c1SSimon Glass 
917a9219c1SSimon Glass int os_close(int fd)
927a9219c1SSimon Glass {
937a9219c1SSimon Glass 	return close(fd);
947a9219c1SSimon Glass }
957a9219c1SSimon Glass 
96cfd13e8dSStephen Warren int os_unlink(const char *pathname)
97cfd13e8dSStephen Warren {
98cfd13e8dSStephen Warren 	return unlink(pathname);
99cfd13e8dSStephen Warren }
100cfd13e8dSStephen Warren 
1017a9219c1SSimon Glass void os_exit(int exit_code)
1027a9219c1SSimon Glass {
1037a9219c1SSimon Glass 	exit(exit_code);
1047a9219c1SSimon Glass }
105ab06a758SMike Frysinger 
106ab06a758SMike Frysinger /* Restore tty state when we exit */
107ab06a758SMike Frysinger static struct termios orig_term;
108ffb87905SSimon Glass static bool term_setup;
109ab06a758SMike Frysinger 
1108939df09SSimon Glass void os_fd_restore(void)
111ab06a758SMike Frysinger {
1128939df09SSimon Glass 	if (term_setup) {
113ab06a758SMike Frysinger 		tcsetattr(0, TCSANOW, &orig_term);
1148939df09SSimon Glass 		term_setup = false;
1158939df09SSimon Glass 	}
116ab06a758SMike Frysinger }
117ab06a758SMike Frysinger 
118ab06a758SMike Frysinger /* Put tty into raw mode so <tab> and <ctrl+c> work */
119ffb87905SSimon Glass void os_tty_raw(int fd, bool allow_sigs)
120ab06a758SMike Frysinger {
121ab06a758SMike Frysinger 	struct termios term;
122ab06a758SMike Frysinger 
123ffb87905SSimon Glass 	if (term_setup)
124ab06a758SMike Frysinger 		return;
125ab06a758SMike Frysinger 
126ab06a758SMike Frysinger 	/* If not a tty, don't complain */
127ab06a758SMike Frysinger 	if (tcgetattr(fd, &orig_term))
128ab06a758SMike Frysinger 		return;
129ab06a758SMike Frysinger 
130ab06a758SMike Frysinger 	term = orig_term;
131ab06a758SMike Frysinger 	term.c_iflag = IGNBRK | IGNPAR;
132ab06a758SMike Frysinger 	term.c_oflag = OPOST | ONLCR;
133ab06a758SMike Frysinger 	term.c_cflag = CS8 | CREAD | CLOCAL;
134ffb87905SSimon Glass 	term.c_lflag = allow_sigs ? ISIG : 0;
135ab06a758SMike Frysinger 	if (tcsetattr(fd, TCSANOW, &term))
136ab06a758SMike Frysinger 		return;
137ab06a758SMike Frysinger 
1388939df09SSimon Glass 	term_setup = true;
139ab06a758SMike Frysinger 	atexit(os_fd_restore);
140ab06a758SMike Frysinger }
14121899b10SMatthias Weisser 
14221899b10SMatthias Weisser void *os_malloc(size_t length)
14321899b10SMatthias Weisser {
14477595c6dSSimon Glass 	struct os_mem_hdr *hdr;
14577595c6dSSimon Glass 
14677595c6dSSimon Glass 	hdr = mmap(NULL, length + sizeof(*hdr), PROT_READ | PROT_WRITE,
14721899b10SMatthias Weisser 		   MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
14877595c6dSSimon Glass 	if (hdr == MAP_FAILED)
14977595c6dSSimon Glass 		return NULL;
15077595c6dSSimon Glass 	hdr->length = length;
15177595c6dSSimon Glass 
15277595c6dSSimon Glass 	return hdr + 1;
15377595c6dSSimon Glass }
15477595c6dSSimon Glass 
155347d06deSMasahiro Yamada void os_free(void *ptr)
15677595c6dSSimon Glass {
15777595c6dSSimon Glass 	struct os_mem_hdr *hdr = ptr;
15877595c6dSSimon Glass 
15977595c6dSSimon Glass 	hdr--;
16077595c6dSSimon Glass 	if (ptr)
16177595c6dSSimon Glass 		munmap(hdr, hdr->length + sizeof(*hdr));
16277595c6dSSimon Glass }
16377595c6dSSimon Glass 
16477595c6dSSimon Glass void *os_realloc(void *ptr, size_t length)
16577595c6dSSimon Glass {
16677595c6dSSimon Glass 	struct os_mem_hdr *hdr = ptr;
16777595c6dSSimon Glass 	void *buf = NULL;
16877595c6dSSimon Glass 
16977595c6dSSimon Glass 	hdr--;
17077595c6dSSimon Glass 	if (length != 0) {
17177595c6dSSimon Glass 		buf = os_malloc(length);
17277595c6dSSimon Glass 		if (!buf)
17377595c6dSSimon Glass 			return buf;
17477595c6dSSimon Glass 		if (ptr) {
17577595c6dSSimon Glass 			if (length > hdr->length)
17677595c6dSSimon Glass 				length = hdr->length;
17777595c6dSSimon Glass 			memcpy(buf, ptr, length);
17877595c6dSSimon Glass 		}
17977595c6dSSimon Glass 	}
18077595c6dSSimon Glass 	os_free(ptr);
18177595c6dSSimon Glass 
18277595c6dSSimon Glass 	return buf;
18321899b10SMatthias Weisser }
184d99a6874SMatthias Weisser 
185d99a6874SMatthias Weisser void os_usleep(unsigned long usec)
186d99a6874SMatthias Weisser {
187d99a6874SMatthias Weisser 	usleep(usec);
188d99a6874SMatthias Weisser }
189d99a6874SMatthias Weisser 
1902a54d159SSimon Glass uint64_t __attribute__((no_instrument_function)) os_get_nsec(void)
191d99a6874SMatthias Weisser {
192d99a6874SMatthias Weisser #if defined(CLOCK_MONOTONIC) && defined(_POSIX_MONOTONIC_CLOCK)
193d99a6874SMatthias Weisser 	struct timespec tp;
194d99a6874SMatthias Weisser 	if (EINVAL == clock_gettime(CLOCK_MONOTONIC, &tp)) {
195d99a6874SMatthias Weisser 		struct timeval tv;
196d99a6874SMatthias Weisser 
197d99a6874SMatthias Weisser 		gettimeofday(&tv, NULL);
198d99a6874SMatthias Weisser 		tp.tv_sec = tv.tv_sec;
199d99a6874SMatthias Weisser 		tp.tv_nsec = tv.tv_usec * 1000;
200d99a6874SMatthias Weisser 	}
201d99a6874SMatthias Weisser 	return tp.tv_sec * 1000000000ULL + tp.tv_nsec;
202d99a6874SMatthias Weisser #else
203d99a6874SMatthias Weisser 	struct timeval tv;
204d99a6874SMatthias Weisser 	gettimeofday(&tv, NULL);
205d99a6874SMatthias Weisser 	return tv.tv_sec * 1000000000ULL + tv.tv_usec * 1000;
206d99a6874SMatthias Weisser #endif
207d99a6874SMatthias Weisser }
20870db4212SSimon Glass 
20970db4212SSimon Glass static char *short_opts;
21070db4212SSimon Glass static struct option *long_opts;
21170db4212SSimon Glass 
21270db4212SSimon Glass int os_parse_args(struct sandbox_state *state, int argc, char *argv[])
21370db4212SSimon Glass {
2147b3efc66SSimon Glass 	struct sandbox_cmdline_option **sb_opt = __u_boot_sandbox_option_start;
21570db4212SSimon Glass 	size_t num_options = __u_boot_sandbox_option_count();
21670db4212SSimon Glass 	size_t i;
21770db4212SSimon Glass 
21870db4212SSimon Glass 	int hidden_short_opt;
21970db4212SSimon Glass 	size_t si;
22070db4212SSimon Glass 
22170db4212SSimon Glass 	int c;
22270db4212SSimon Glass 
22370db4212SSimon Glass 	if (short_opts || long_opts)
22470db4212SSimon Glass 		return 1;
22570db4212SSimon Glass 
22670db4212SSimon Glass 	state->argc = argc;
22770db4212SSimon Glass 	state->argv = argv;
22870db4212SSimon Glass 
22970db4212SSimon Glass 	/* dynamically construct the arguments to the system getopt_long */
23070db4212SSimon Glass 	short_opts = os_malloc(sizeof(*short_opts) * num_options * 2 + 1);
23170db4212SSimon Glass 	long_opts = os_malloc(sizeof(*long_opts) * num_options);
23270db4212SSimon Glass 	if (!short_opts || !long_opts)
23370db4212SSimon Glass 		return 1;
23470db4212SSimon Glass 
23570db4212SSimon Glass 	/*
23670db4212SSimon Glass 	 * getopt_long requires "val" to be unique (since that is what the
23770db4212SSimon Glass 	 * func returns), so generate unique values automatically for flags
23870db4212SSimon Glass 	 * that don't have a short option.  pick 0x100 as that is above the
23970db4212SSimon Glass 	 * single byte range (where ASCII/ISO-XXXX-X charsets live).
24070db4212SSimon Glass 	 */
24170db4212SSimon Glass 	hidden_short_opt = 0x100;
24270db4212SSimon Glass 	si = 0;
24370db4212SSimon Glass 	for (i = 0; i < num_options; ++i) {
24470db4212SSimon Glass 		long_opts[i].name = sb_opt[i]->flag;
24570db4212SSimon Glass 		long_opts[i].has_arg = sb_opt[i]->has_arg ?
24670db4212SSimon Glass 			required_argument : no_argument;
24770db4212SSimon Glass 		long_opts[i].flag = NULL;
24870db4212SSimon Glass 
24970db4212SSimon Glass 		if (sb_opt[i]->flag_short) {
25070db4212SSimon Glass 			short_opts[si++] = long_opts[i].val = sb_opt[i]->flag_short;
25170db4212SSimon Glass 			if (long_opts[i].has_arg == required_argument)
25270db4212SSimon Glass 				short_opts[si++] = ':';
25370db4212SSimon Glass 		} else
25470db4212SSimon Glass 			long_opts[i].val = sb_opt[i]->flag_short = hidden_short_opt++;
25570db4212SSimon Glass 	}
25670db4212SSimon Glass 	short_opts[si] = '\0';
25770db4212SSimon Glass 
25870db4212SSimon Glass 	/* we need to handle output ourselves since u-boot provides printf */
25970db4212SSimon Glass 	opterr = 0;
26070db4212SSimon Glass 
26170db4212SSimon Glass 	/*
26270db4212SSimon Glass 	 * walk all of the options the user gave us on the command line,
26370db4212SSimon Glass 	 * figure out what u-boot option structure they belong to (via
26470db4212SSimon Glass 	 * the unique short val key), and call the appropriate callback.
26570db4212SSimon Glass 	 */
26670db4212SSimon Glass 	while ((c = getopt_long(argc, argv, short_opts, long_opts, NULL)) != -1) {
26770db4212SSimon Glass 		for (i = 0; i < num_options; ++i) {
26870db4212SSimon Glass 			if (sb_opt[i]->flag_short == c) {
26970db4212SSimon Glass 				if (sb_opt[i]->callback(state, optarg)) {
27070db4212SSimon Glass 					state->parse_err = sb_opt[i]->flag;
27170db4212SSimon Glass 					return 0;
27270db4212SSimon Glass 				}
27370db4212SSimon Glass 				break;
27470db4212SSimon Glass 			}
27570db4212SSimon Glass 		}
27670db4212SSimon Glass 		if (i == num_options) {
27770db4212SSimon Glass 			/*
27870db4212SSimon Glass 			 * store the faulting flag for later display.  we have to
27970db4212SSimon Glass 			 * store the flag itself as the getopt parsing itself is
28070db4212SSimon Glass 			 * tricky: need to handle the following flags (assume all
28170db4212SSimon Glass 			 * of the below are unknown):
28270db4212SSimon Glass 			 *   -a        optopt='a' optind=<next>
28370db4212SSimon Glass 			 *   -abbbb    optopt='a' optind=<this>
28470db4212SSimon Glass 			 *   -aaaaa    optopt='a' optind=<this>
28570db4212SSimon Glass 			 *   --a       optopt=0   optind=<this>
28670db4212SSimon Glass 			 * as you can see, it is impossible to determine the exact
28770db4212SSimon Glass 			 * faulting flag without doing the parsing ourselves, so
28870db4212SSimon Glass 			 * we just report the specific flag that failed.
28970db4212SSimon Glass 			 */
29070db4212SSimon Glass 			if (optopt) {
29170db4212SSimon Glass 				static char parse_err[3] = { '-', 0, '\0', };
29270db4212SSimon Glass 				parse_err[1] = optopt;
29370db4212SSimon Glass 				state->parse_err = parse_err;
29470db4212SSimon Glass 			} else
29570db4212SSimon Glass 				state->parse_err = argv[optind - 1];
29670db4212SSimon Glass 			break;
29770db4212SSimon Glass 		}
29870db4212SSimon Glass 	}
29970db4212SSimon Glass 
30070db4212SSimon Glass 	return 0;
30170db4212SSimon Glass }
30262584db1SSimon Glass 
30362584db1SSimon Glass void os_dirent_free(struct os_dirent_node *node)
30462584db1SSimon Glass {
30562584db1SSimon Glass 	struct os_dirent_node *next;
30662584db1SSimon Glass 
30762584db1SSimon Glass 	while (node) {
30862584db1SSimon Glass 		next = node->next;
30962584db1SSimon Glass 		free(node);
31062584db1SSimon Glass 		node = next;
31162584db1SSimon Glass 	}
31262584db1SSimon Glass }
31362584db1SSimon Glass 
31462584db1SSimon Glass int os_dirent_ls(const char *dirname, struct os_dirent_node **headp)
31562584db1SSimon Glass {
31662584db1SSimon Glass 	struct dirent entry, *result;
31762584db1SSimon Glass 	struct os_dirent_node *head, *node, *next;
31862584db1SSimon Glass 	struct stat buf;
31962584db1SSimon Glass 	DIR *dir;
32062584db1SSimon Glass 	int ret;
32162584db1SSimon Glass 	char *fname;
32262584db1SSimon Glass 	int len;
32362584db1SSimon Glass 
32462584db1SSimon Glass 	*headp = NULL;
32562584db1SSimon Glass 	dir = opendir(dirname);
32662584db1SSimon Glass 	if (!dir)
32762584db1SSimon Glass 		return -1;
32862584db1SSimon Glass 
32962584db1SSimon Glass 	/* Create a buffer for the maximum filename length */
33062584db1SSimon Glass 	len = sizeof(entry.d_name) + strlen(dirname) + 2;
33162584db1SSimon Glass 	fname = malloc(len);
33262584db1SSimon Glass 	if (!fname) {
33362584db1SSimon Glass 		ret = -ENOMEM;
33462584db1SSimon Glass 		goto done;
33562584db1SSimon Glass 	}
33662584db1SSimon Glass 
33762584db1SSimon Glass 	for (node = head = NULL;; node = next) {
33862584db1SSimon Glass 		ret = readdir_r(dir, &entry, &result);
33962584db1SSimon Glass 		if (ret || !result)
34062584db1SSimon Glass 			break;
34162584db1SSimon Glass 		next = malloc(sizeof(*node) + strlen(entry.d_name) + 1);
34262584db1SSimon Glass 		if (!next) {
34362584db1SSimon Glass 			os_dirent_free(head);
34462584db1SSimon Glass 			ret = -ENOMEM;
34562584db1SSimon Glass 			goto done;
34662584db1SSimon Glass 		}
3479c38c070SStephen Warren 		next->next = NULL;
34862584db1SSimon Glass 		strcpy(next->name, entry.d_name);
34962584db1SSimon Glass 		switch (entry.d_type) {
35062584db1SSimon Glass 		case DT_REG:
35162584db1SSimon Glass 			next->type = OS_FILET_REG;
35262584db1SSimon Glass 			break;
35362584db1SSimon Glass 		case DT_DIR:
35462584db1SSimon Glass 			next->type = OS_FILET_DIR;
35562584db1SSimon Glass 			break;
35662584db1SSimon Glass 		case DT_LNK:
35762584db1SSimon Glass 			next->type = OS_FILET_LNK;
35862584db1SSimon Glass 			break;
35962584db1SSimon Glass 		}
36062584db1SSimon Glass 		next->size = 0;
36162584db1SSimon Glass 		snprintf(fname, len, "%s/%s", dirname, next->name);
36262584db1SSimon Glass 		if (!stat(fname, &buf))
36362584db1SSimon Glass 			next->size = buf.st_size;
36462584db1SSimon Glass 		if (node)
36562584db1SSimon Glass 			node->next = next;
36662584db1SSimon Glass 		if (!head)
36762584db1SSimon Glass 			head = node;
36862584db1SSimon Glass 	}
36962584db1SSimon Glass 	*headp = head;
37062584db1SSimon Glass 
37162584db1SSimon Glass done:
37262584db1SSimon Glass 	closedir(dir);
373f80a8bbeSSimon Glass 	free(fname);
37462584db1SSimon Glass 	return ret;
37562584db1SSimon Glass }
37662584db1SSimon Glass 
37762584db1SSimon Glass const char *os_dirent_typename[OS_FILET_COUNT] = {
37862584db1SSimon Glass 	"   ",
37962584db1SSimon Glass 	"SYM",
38062584db1SSimon Glass 	"DIR",
38162584db1SSimon Glass 	"???",
38262584db1SSimon Glass };
38362584db1SSimon Glass 
38462584db1SSimon Glass const char *os_dirent_get_typename(enum os_dirent_t type)
38562584db1SSimon Glass {
38662584db1SSimon Glass 	if (type >= 0 && type < OS_FILET_COUNT)
38762584db1SSimon Glass 		return os_dirent_typename[type];
38862584db1SSimon Glass 
38962584db1SSimon Glass 	return os_dirent_typename[OS_FILET_UNKNOWN];
39062584db1SSimon Glass }
39162584db1SSimon Glass 
39296b1046dSSuriyan Ramasami int os_get_filesize(const char *fname, loff_t *size)
39362584db1SSimon Glass {
39462584db1SSimon Glass 	struct stat buf;
39562584db1SSimon Glass 	int ret;
39662584db1SSimon Glass 
39762584db1SSimon Glass 	ret = stat(fname, &buf);
39862584db1SSimon Glass 	if (ret)
39962584db1SSimon Glass 		return ret;
40096b1046dSSuriyan Ramasami 	*size = buf.st_size;
40196b1046dSSuriyan Ramasami 	return 0;
40262584db1SSimon Glass }
40391b136c7SSimon Glass 
40491b136c7SSimon Glass void os_putc(int ch)
40591b136c7SSimon Glass {
40691b136c7SSimon Glass 	putchar(ch);
40791b136c7SSimon Glass }
40891b136c7SSimon Glass 
40991b136c7SSimon Glass void os_puts(const char *str)
41091b136c7SSimon Glass {
41191b136c7SSimon Glass 	while (*str)
41291b136c7SSimon Glass 		os_putc(*str++);
41391b136c7SSimon Glass }
4145c2859cdSSimon Glass 
4155c2859cdSSimon Glass int os_write_ram_buf(const char *fname)
4165c2859cdSSimon Glass {
4175c2859cdSSimon Glass 	struct sandbox_state *state = state_get_current();
4185c2859cdSSimon Glass 	int fd, ret;
4195c2859cdSSimon Glass 
4205c2859cdSSimon Glass 	fd = open(fname, O_CREAT | O_WRONLY, 0777);
4215c2859cdSSimon Glass 	if (fd < 0)
4225c2859cdSSimon Glass 		return -ENOENT;
4235c2859cdSSimon Glass 	ret = write(fd, state->ram_buf, state->ram_size);
4245c2859cdSSimon Glass 	close(fd);
4255c2859cdSSimon Glass 	if (ret != state->ram_size)
4265c2859cdSSimon Glass 		return -EIO;
4275c2859cdSSimon Glass 
4285c2859cdSSimon Glass 	return 0;
4295c2859cdSSimon Glass }
4305c2859cdSSimon Glass 
4315c2859cdSSimon Glass int os_read_ram_buf(const char *fname)
4325c2859cdSSimon Glass {
4335c2859cdSSimon Glass 	struct sandbox_state *state = state_get_current();
4345c2859cdSSimon Glass 	int fd, ret;
43596b1046dSSuriyan Ramasami 	loff_t size;
4365c2859cdSSimon Glass 
43796b1046dSSuriyan Ramasami 	ret = os_get_filesize(fname, &size);
43896b1046dSSuriyan Ramasami 	if (ret < 0)
43996b1046dSSuriyan Ramasami 		return ret;
4405c2859cdSSimon Glass 	if (size != state->ram_size)
4415c2859cdSSimon Glass 		return -ENOSPC;
4425c2859cdSSimon Glass 	fd = open(fname, O_RDONLY);
4435c2859cdSSimon Glass 	if (fd < 0)
4445c2859cdSSimon Glass 		return -ENOENT;
4455c2859cdSSimon Glass 
4465c2859cdSSimon Glass 	ret = read(fd, state->ram_buf, state->ram_size);
4475c2859cdSSimon Glass 	close(fd);
4485c2859cdSSimon Glass 	if (ret != state->ram_size)
4495c2859cdSSimon Glass 		return -EIO;
4505c2859cdSSimon Glass 
4515c2859cdSSimon Glass 	return 0;
4525c2859cdSSimon Glass }
45347f5fcfbSSimon Glass 
45447f5fcfbSSimon Glass static int make_exec(char *fname, const void *data, int size)
45547f5fcfbSSimon Glass {
45647f5fcfbSSimon Glass 	int fd;
45747f5fcfbSSimon Glass 
45847f5fcfbSSimon Glass 	strcpy(fname, "/tmp/u-boot.jump.XXXXXX");
45947f5fcfbSSimon Glass 	fd = mkstemp(fname);
46047f5fcfbSSimon Glass 	if (fd < 0)
46147f5fcfbSSimon Glass 		return -ENOENT;
46247f5fcfbSSimon Glass 	if (write(fd, data, size) < 0)
46347f5fcfbSSimon Glass 		return -EIO;
46447f5fcfbSSimon Glass 	close(fd);
46547f5fcfbSSimon Glass 	if (chmod(fname, 0777))
46647f5fcfbSSimon Glass 		return -ENOEXEC;
46747f5fcfbSSimon Glass 
46847f5fcfbSSimon Glass 	return 0;
46947f5fcfbSSimon Glass }
47047f5fcfbSSimon Glass 
47147f5fcfbSSimon Glass static int add_args(char ***argvp, const char *add_args[], int count)
47247f5fcfbSSimon Glass {
47347f5fcfbSSimon Glass 	char **argv;
47447f5fcfbSSimon Glass 	int argc;
47547f5fcfbSSimon Glass 
47647f5fcfbSSimon Glass 	for (argv = *argvp, argc = 0; (*argvp)[argc]; argc++)
47747f5fcfbSSimon Glass 		;
47847f5fcfbSSimon Glass 
47947f5fcfbSSimon Glass 	argv = malloc((argc + count + 1) * sizeof(char *));
48047f5fcfbSSimon Glass 	if (!argv) {
48147f5fcfbSSimon Glass 		printf("Out of memory for %d argv\n", count);
48247f5fcfbSSimon Glass 		return -ENOMEM;
48347f5fcfbSSimon Glass 	}
48447f5fcfbSSimon Glass 	memcpy(argv, *argvp, argc * sizeof(char *));
48547f5fcfbSSimon Glass 	memcpy(argv + argc, add_args, count * sizeof(char *));
48647f5fcfbSSimon Glass 	argv[argc + count] = NULL;
48747f5fcfbSSimon Glass 
48847f5fcfbSSimon Glass 	*argvp = argv;
48947f5fcfbSSimon Glass 	return 0;
49047f5fcfbSSimon Glass }
49147f5fcfbSSimon Glass 
49247f5fcfbSSimon Glass int os_jump_to_image(const void *dest, int size)
49347f5fcfbSSimon Glass {
49447f5fcfbSSimon Glass 	struct sandbox_state *state = state_get_current();
49547f5fcfbSSimon Glass 	char fname[30], mem_fname[30];
49647f5fcfbSSimon Glass 	int fd, err;
497ab839dc3SSimon Glass 	const char *extra_args[5];
49847f5fcfbSSimon Glass 	char **argv = state->argv;
49947f5fcfbSSimon Glass #ifdef DEBUG
50047f5fcfbSSimon Glass 	int argc, i;
50147f5fcfbSSimon Glass #endif
50247f5fcfbSSimon Glass 
50347f5fcfbSSimon Glass 	err = make_exec(fname, dest, size);
50447f5fcfbSSimon Glass 	if (err)
50547f5fcfbSSimon Glass 		return err;
50647f5fcfbSSimon Glass 
50747f5fcfbSSimon Glass 	strcpy(mem_fname, "/tmp/u-boot.mem.XXXXXX");
50847f5fcfbSSimon Glass 	fd = mkstemp(mem_fname);
50947f5fcfbSSimon Glass 	if (fd < 0)
51047f5fcfbSSimon Glass 		return -ENOENT;
51147f5fcfbSSimon Glass 	close(fd);
51247f5fcfbSSimon Glass 	err = os_write_ram_buf(mem_fname);
51347f5fcfbSSimon Glass 	if (err)
51447f5fcfbSSimon Glass 		return err;
51547f5fcfbSSimon Glass 
51647f5fcfbSSimon Glass 	os_fd_restore();
51747f5fcfbSSimon Glass 
51847f5fcfbSSimon Glass 	extra_args[0] = "-j";
51947f5fcfbSSimon Glass 	extra_args[1] = fname;
52047f5fcfbSSimon Glass 	extra_args[2] = "-m";
52147f5fcfbSSimon Glass 	extra_args[3] = mem_fname;
522ab839dc3SSimon Glass 	extra_args[4] = "--rm_memory";
52347f5fcfbSSimon Glass 	err = add_args(&argv, extra_args,
52447f5fcfbSSimon Glass 		       sizeof(extra_args) / sizeof(extra_args[0]));
52547f5fcfbSSimon Glass 	if (err)
52647f5fcfbSSimon Glass 		return err;
52747f5fcfbSSimon Glass 
52847f5fcfbSSimon Glass #ifdef DEBUG
52947f5fcfbSSimon Glass 	for (i = 0; argv[i]; i++)
53047f5fcfbSSimon Glass 		printf("%d %s\n", i, argv[i]);
53147f5fcfbSSimon Glass #endif
53247f5fcfbSSimon Glass 
53347f5fcfbSSimon Glass 	if (state_uninit())
53447f5fcfbSSimon Glass 		os_exit(2);
53547f5fcfbSSimon Glass 
53647f5fcfbSSimon Glass 	err = execv(fname, argv);
53747f5fcfbSSimon Glass 	free(argv);
53847f5fcfbSSimon Glass 	if (err)
53947f5fcfbSSimon Glass 		return err;
54047f5fcfbSSimon Glass 
54147f5fcfbSSimon Glass 	return unlink(fname);
54247f5fcfbSSimon Glass }
54394eefdeeSSimon Glass 
544*d4e33f5aSSimon Glass int os_find_u_boot(char *fname, int maxlen)
545*d4e33f5aSSimon Glass {
546*d4e33f5aSSimon Glass 	struct sandbox_state *state = state_get_current();
547*d4e33f5aSSimon Glass 	const char *progname = state->argv[0];
548*d4e33f5aSSimon Glass 	int len = strlen(progname);
549*d4e33f5aSSimon Glass 	char *p;
550*d4e33f5aSSimon Glass 	int fd;
551*d4e33f5aSSimon Glass 
552*d4e33f5aSSimon Glass 	if (len >= maxlen || len < 4)
553*d4e33f5aSSimon Glass 		return -ENOSPC;
554*d4e33f5aSSimon Glass 
555*d4e33f5aSSimon Glass 	/* Look for 'u-boot' in the same directory as 'u-boot-spl' */
556*d4e33f5aSSimon Glass 	strcpy(fname, progname);
557*d4e33f5aSSimon Glass 	if (!strcmp(fname + len - 4, "-spl")) {
558*d4e33f5aSSimon Glass 		fname[len - 4] = '\0';
559*d4e33f5aSSimon Glass 		fd = os_open(fname, O_RDONLY);
560*d4e33f5aSSimon Glass 		if (fd >= 0) {
561*d4e33f5aSSimon Glass 			close(fd);
562*d4e33f5aSSimon Glass 			return 0;
563*d4e33f5aSSimon Glass 		}
564*d4e33f5aSSimon Glass 	}
565*d4e33f5aSSimon Glass 
566*d4e33f5aSSimon Glass 	/* Look for 'u-boot' in the parent directory of spl/ */
567*d4e33f5aSSimon Glass 	p = strstr(fname, "/spl/");
568*d4e33f5aSSimon Glass 	if (p) {
569*d4e33f5aSSimon Glass 		strcpy(p, p + 4);
570*d4e33f5aSSimon Glass 		fd = os_open(fname, O_RDONLY);
571*d4e33f5aSSimon Glass 		if (fd >= 0) {
572*d4e33f5aSSimon Glass 			close(fd);
573*d4e33f5aSSimon Glass 			return 0;
574*d4e33f5aSSimon Glass 		}
575*d4e33f5aSSimon Glass 	}
576*d4e33f5aSSimon Glass 
577*d4e33f5aSSimon Glass 	return -ENOENT;
578*d4e33f5aSSimon Glass }
579*d4e33f5aSSimon Glass 
580*d4e33f5aSSimon Glass int os_spl_to_uboot(const char *fname)
581*d4e33f5aSSimon Glass {
582*d4e33f5aSSimon Glass 	struct sandbox_state *state = state_get_current();
583*d4e33f5aSSimon Glass 	char *argv[state->argc + 1];
584*d4e33f5aSSimon Glass 	int ret;
585*d4e33f5aSSimon Glass 
586*d4e33f5aSSimon Glass 	memcpy(argv, state->argv, sizeof(char *) * (state->argc + 1));
587*d4e33f5aSSimon Glass 	argv[0] = (char *)fname;
588*d4e33f5aSSimon Glass 	ret = execv(fname, argv);
589*d4e33f5aSSimon Glass 	if (ret)
590*d4e33f5aSSimon Glass 		return ret;
591*d4e33f5aSSimon Glass 
592*d4e33f5aSSimon Glass 	return unlink(fname);
593*d4e33f5aSSimon Glass }
594*d4e33f5aSSimon Glass 
59594eefdeeSSimon Glass void os_localtime(struct rtc_time *rt)
59694eefdeeSSimon Glass {
59794eefdeeSSimon Glass 	time_t t = time(NULL);
59894eefdeeSSimon Glass 	struct tm *tm;
59994eefdeeSSimon Glass 
60094eefdeeSSimon Glass 	tm = localtime(&t);
60194eefdeeSSimon Glass 	rt->tm_sec = tm->tm_sec;
60294eefdeeSSimon Glass 	rt->tm_min = tm->tm_min;
60394eefdeeSSimon Glass 	rt->tm_hour = tm->tm_hour;
60494eefdeeSSimon Glass 	rt->tm_mday = tm->tm_mday;
60594eefdeeSSimon Glass 	rt->tm_mon = tm->tm_mon + 1;
60694eefdeeSSimon Glass 	rt->tm_year = tm->tm_year + 1900;
60794eefdeeSSimon Glass 	rt->tm_wday = tm->tm_wday;
60894eefdeeSSimon Glass 	rt->tm_yday = tm->tm_yday;
60994eefdeeSSimon Glass 	rt->tm_isdst = tm->tm_isdst;
61094eefdeeSSimon Glass }
611