xref: /rk3399_rockchip-uboot/arch/sandbox/cpu/os.c (revision 47b98ad0f6779485d0f0c14f337c3eece273eb54)
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 
os_read(int fd,void * buf,size_t count)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 
os_read_no_block(int fd,void * buf,size_t count)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 
os_write(int fd,const void * buf,size_t count)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 
os_lseek(int fd,off_t offset,int whence)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 
os_open(const char * pathname,int os_flags)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 
os_close(int fd)917a9219c1SSimon Glass int os_close(int fd)
927a9219c1SSimon Glass {
937a9219c1SSimon Glass 	return close(fd);
947a9219c1SSimon Glass }
957a9219c1SSimon Glass 
os_unlink(const char * pathname)96cfd13e8dSStephen Warren int os_unlink(const char *pathname)
97cfd13e8dSStephen Warren {
98cfd13e8dSStephen Warren 	return unlink(pathname);
99cfd13e8dSStephen Warren }
100cfd13e8dSStephen Warren 
os_exit(int exit_code)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 
os_fd_restore(void)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 */
os_tty_raw(int fd,bool allow_sigs)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 
os_malloc(size_t length)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 
os_free(void * ptr)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 
os_realloc(void * ptr,size_t length)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 
os_usleep(unsigned long usec)185d99a6874SMatthias Weisser void os_usleep(unsigned long usec)
186d99a6874SMatthias Weisser {
187d99a6874SMatthias Weisser 	usleep(usec);
188d99a6874SMatthias Weisser }
189d99a6874SMatthias Weisser 
os_get_nsec(void)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 
os_parse_args(struct sandbox_state * state,int argc,char * argv[])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 
os_dirent_free(struct os_dirent_node * node)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 
os_dirent_ls(const char * dirname,struct os_dirent_node ** headp)31462584db1SSimon Glass int os_dirent_ls(const char *dirname, struct os_dirent_node **headp)
31562584db1SSimon Glass {
316bf635ed0SStefan Brüns 	struct dirent *entry;
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;
323f189899cSStefan Brüns 	int dirlen;
32462584db1SSimon Glass 
32562584db1SSimon Glass 	*headp = NULL;
32662584db1SSimon Glass 	dir = opendir(dirname);
32762584db1SSimon Glass 	if (!dir)
32862584db1SSimon Glass 		return -1;
32962584db1SSimon Glass 
330f189899cSStefan Brüns 	/* Create a buffer upfront, with typically sufficient size */
331f189899cSStefan Brüns 	dirlen = strlen(dirname) + 2;
332f189899cSStefan Brüns 	len = dirlen + 256;
33362584db1SSimon Glass 	fname = malloc(len);
33462584db1SSimon Glass 	if (!fname) {
33562584db1SSimon Glass 		ret = -ENOMEM;
33662584db1SSimon Glass 		goto done;
33762584db1SSimon Glass 	}
33862584db1SSimon Glass 
33962584db1SSimon Glass 	for (node = head = NULL;; node = next) {
340bf635ed0SStefan Brüns 		errno = 0;
341bf635ed0SStefan Brüns 		entry = readdir(dir);
342bf635ed0SStefan Brüns 		if (!entry) {
343bf635ed0SStefan Brüns 			ret = errno;
34462584db1SSimon Glass 			break;
345bf635ed0SStefan Brüns 		}
346bf635ed0SStefan Brüns 		next = malloc(sizeof(*node) + strlen(entry->d_name) + 1);
347bf635ed0SStefan Brüns 		if (dirlen + strlen(entry->d_name) > len) {
348bf635ed0SStefan Brüns 			len = dirlen + strlen(entry->d_name);
349f189899cSStefan Brüns 			fname = realloc(fname, len);
350f189899cSStefan Brüns 		}
351f189899cSStefan Brüns 		if (!next || !fname) {
352f189899cSStefan Brüns 			free(next);
35362584db1SSimon Glass 			os_dirent_free(head);
35462584db1SSimon Glass 			ret = -ENOMEM;
35562584db1SSimon Glass 			goto done;
35662584db1SSimon Glass 		}
3579c38c070SStephen Warren 		next->next = NULL;
358bf635ed0SStefan Brüns 		strcpy(next->name, entry->d_name);
359bf635ed0SStefan Brüns 		switch (entry->d_type) {
36062584db1SSimon Glass 		case DT_REG:
36162584db1SSimon Glass 			next->type = OS_FILET_REG;
36262584db1SSimon Glass 			break;
36362584db1SSimon Glass 		case DT_DIR:
36462584db1SSimon Glass 			next->type = OS_FILET_DIR;
36562584db1SSimon Glass 			break;
36662584db1SSimon Glass 		case DT_LNK:
36762584db1SSimon Glass 			next->type = OS_FILET_LNK;
36862584db1SSimon Glass 			break;
3692f159402SStefan Brüns 		default:
3702f159402SStefan Brüns 			next->type = OS_FILET_UNKNOWN;
37162584db1SSimon Glass 		}
37262584db1SSimon Glass 		next->size = 0;
37362584db1SSimon Glass 		snprintf(fname, len, "%s/%s", dirname, next->name);
37462584db1SSimon Glass 		if (!stat(fname, &buf))
37562584db1SSimon Glass 			next->size = buf.st_size;
37662584db1SSimon Glass 		if (node)
37762584db1SSimon Glass 			node->next = next;
378ce2ec19cSStefan Brüns 		else
379ce2ec19cSStefan Brüns 			head = next;
38062584db1SSimon Glass 	}
38162584db1SSimon Glass 	*headp = head;
38262584db1SSimon Glass 
38362584db1SSimon Glass done:
38462584db1SSimon Glass 	closedir(dir);
385f80a8bbeSSimon Glass 	free(fname);
38662584db1SSimon Glass 	return ret;
38762584db1SSimon Glass }
38862584db1SSimon Glass 
38962584db1SSimon Glass const char *os_dirent_typename[OS_FILET_COUNT] = {
39062584db1SSimon Glass 	"   ",
39162584db1SSimon Glass 	"SYM",
39262584db1SSimon Glass 	"DIR",
39362584db1SSimon Glass 	"???",
39462584db1SSimon Glass };
39562584db1SSimon Glass 
os_dirent_get_typename(enum os_dirent_t type)39662584db1SSimon Glass const char *os_dirent_get_typename(enum os_dirent_t type)
39762584db1SSimon Glass {
398*e2bc87d4STom Rini 	if (type >= OS_FILET_REG && type < OS_FILET_COUNT)
39962584db1SSimon Glass 		return os_dirent_typename[type];
40062584db1SSimon Glass 
40162584db1SSimon Glass 	return os_dirent_typename[OS_FILET_UNKNOWN];
40262584db1SSimon Glass }
40362584db1SSimon Glass 
os_get_filesize(const char * fname,loff_t * size)40496b1046dSSuriyan Ramasami int os_get_filesize(const char *fname, loff_t *size)
40562584db1SSimon Glass {
40662584db1SSimon Glass 	struct stat buf;
40762584db1SSimon Glass 	int ret;
40862584db1SSimon Glass 
40962584db1SSimon Glass 	ret = stat(fname, &buf);
41062584db1SSimon Glass 	if (ret)
41162584db1SSimon Glass 		return ret;
41296b1046dSSuriyan Ramasami 	*size = buf.st_size;
41396b1046dSSuriyan Ramasami 	return 0;
41462584db1SSimon Glass }
41591b136c7SSimon Glass 
os_write_ram_buf(const char * fname)4165c2859cdSSimon Glass int os_write_ram_buf(const char *fname)
4175c2859cdSSimon Glass {
4185c2859cdSSimon Glass 	struct sandbox_state *state = state_get_current();
4195c2859cdSSimon Glass 	int fd, ret;
4205c2859cdSSimon Glass 
4215c2859cdSSimon Glass 	fd = open(fname, O_CREAT | O_WRONLY, 0777);
4225c2859cdSSimon Glass 	if (fd < 0)
4235c2859cdSSimon Glass 		return -ENOENT;
4245c2859cdSSimon Glass 	ret = write(fd, state->ram_buf, state->ram_size);
4255c2859cdSSimon Glass 	close(fd);
4265c2859cdSSimon Glass 	if (ret != state->ram_size)
4275c2859cdSSimon Glass 		return -EIO;
4285c2859cdSSimon Glass 
4295c2859cdSSimon Glass 	return 0;
4305c2859cdSSimon Glass }
4315c2859cdSSimon Glass 
os_read_ram_buf(const char * fname)4325c2859cdSSimon Glass int os_read_ram_buf(const char *fname)
4335c2859cdSSimon Glass {
4345c2859cdSSimon Glass 	struct sandbox_state *state = state_get_current();
4355c2859cdSSimon Glass 	int fd, ret;
43696b1046dSSuriyan Ramasami 	loff_t size;
4375c2859cdSSimon Glass 
43896b1046dSSuriyan Ramasami 	ret = os_get_filesize(fname, &size);
43996b1046dSSuriyan Ramasami 	if (ret < 0)
44096b1046dSSuriyan Ramasami 		return ret;
4415c2859cdSSimon Glass 	if (size != state->ram_size)
4425c2859cdSSimon Glass 		return -ENOSPC;
4435c2859cdSSimon Glass 	fd = open(fname, O_RDONLY);
4445c2859cdSSimon Glass 	if (fd < 0)
4455c2859cdSSimon Glass 		return -ENOENT;
4465c2859cdSSimon Glass 
4475c2859cdSSimon Glass 	ret = read(fd, state->ram_buf, state->ram_size);
4485c2859cdSSimon Glass 	close(fd);
4495c2859cdSSimon Glass 	if (ret != state->ram_size)
4505c2859cdSSimon Glass 		return -EIO;
4515c2859cdSSimon Glass 
4525c2859cdSSimon Glass 	return 0;
4535c2859cdSSimon Glass }
45447f5fcfbSSimon Glass 
make_exec(char * fname,const void * data,int size)45547f5fcfbSSimon Glass static int make_exec(char *fname, const void *data, int size)
45647f5fcfbSSimon Glass {
45747f5fcfbSSimon Glass 	int fd;
45847f5fcfbSSimon Glass 
45947f5fcfbSSimon Glass 	strcpy(fname, "/tmp/u-boot.jump.XXXXXX");
46047f5fcfbSSimon Glass 	fd = mkstemp(fname);
46147f5fcfbSSimon Glass 	if (fd < 0)
46247f5fcfbSSimon Glass 		return -ENOENT;
46347f5fcfbSSimon Glass 	if (write(fd, data, size) < 0)
46447f5fcfbSSimon Glass 		return -EIO;
46547f5fcfbSSimon Glass 	close(fd);
46647f5fcfbSSimon Glass 	if (chmod(fname, 0777))
46747f5fcfbSSimon Glass 		return -ENOEXEC;
46847f5fcfbSSimon Glass 
46947f5fcfbSSimon Glass 	return 0;
47047f5fcfbSSimon Glass }
47147f5fcfbSSimon Glass 
add_args(char *** argvp,const char * add_args[],int count)47247f5fcfbSSimon Glass static int add_args(char ***argvp, const char *add_args[], int count)
47347f5fcfbSSimon Glass {
47447f5fcfbSSimon Glass 	char **argv;
47547f5fcfbSSimon Glass 	int argc;
47647f5fcfbSSimon Glass 
47747f5fcfbSSimon Glass 	for (argv = *argvp, argc = 0; (*argvp)[argc]; argc++)
47847f5fcfbSSimon Glass 		;
47947f5fcfbSSimon Glass 
48047f5fcfbSSimon Glass 	argv = malloc((argc + count + 1) * sizeof(char *));
48147f5fcfbSSimon Glass 	if (!argv) {
48247f5fcfbSSimon Glass 		printf("Out of memory for %d argv\n", count);
48347f5fcfbSSimon Glass 		return -ENOMEM;
48447f5fcfbSSimon Glass 	}
48547f5fcfbSSimon Glass 	memcpy(argv, *argvp, argc * sizeof(char *));
48647f5fcfbSSimon Glass 	memcpy(argv + argc, add_args, count * sizeof(char *));
48747f5fcfbSSimon Glass 	argv[argc + count] = NULL;
48847f5fcfbSSimon Glass 
48947f5fcfbSSimon Glass 	*argvp = argv;
49047f5fcfbSSimon Glass 	return 0;
49147f5fcfbSSimon Glass }
49247f5fcfbSSimon Glass 
os_jump_to_image(const void * dest,int size)49347f5fcfbSSimon Glass int os_jump_to_image(const void *dest, int size)
49447f5fcfbSSimon Glass {
49547f5fcfbSSimon Glass 	struct sandbox_state *state = state_get_current();
49647f5fcfbSSimon Glass 	char fname[30], mem_fname[30];
49747f5fcfbSSimon Glass 	int fd, err;
498ab839dc3SSimon Glass 	const char *extra_args[5];
49947f5fcfbSSimon Glass 	char **argv = state->argv;
50047f5fcfbSSimon Glass #ifdef DEBUG
50147f5fcfbSSimon Glass 	int argc, i;
50247f5fcfbSSimon Glass #endif
50347f5fcfbSSimon Glass 
50447f5fcfbSSimon Glass 	err = make_exec(fname, dest, size);
50547f5fcfbSSimon Glass 	if (err)
50647f5fcfbSSimon Glass 		return err;
50747f5fcfbSSimon Glass 
50847f5fcfbSSimon Glass 	strcpy(mem_fname, "/tmp/u-boot.mem.XXXXXX");
50947f5fcfbSSimon Glass 	fd = mkstemp(mem_fname);
51047f5fcfbSSimon Glass 	if (fd < 0)
51147f5fcfbSSimon Glass 		return -ENOENT;
51247f5fcfbSSimon Glass 	close(fd);
51347f5fcfbSSimon Glass 	err = os_write_ram_buf(mem_fname);
51447f5fcfbSSimon Glass 	if (err)
51547f5fcfbSSimon Glass 		return err;
51647f5fcfbSSimon Glass 
51747f5fcfbSSimon Glass 	os_fd_restore();
51847f5fcfbSSimon Glass 
51947f5fcfbSSimon Glass 	extra_args[0] = "-j";
52047f5fcfbSSimon Glass 	extra_args[1] = fname;
52147f5fcfbSSimon Glass 	extra_args[2] = "-m";
52247f5fcfbSSimon Glass 	extra_args[3] = mem_fname;
523ab839dc3SSimon Glass 	extra_args[4] = "--rm_memory";
52447f5fcfbSSimon Glass 	err = add_args(&argv, extra_args,
52547f5fcfbSSimon Glass 		       sizeof(extra_args) / sizeof(extra_args[0]));
52647f5fcfbSSimon Glass 	if (err)
52747f5fcfbSSimon Glass 		return err;
52847f5fcfbSSimon Glass 
52947f5fcfbSSimon Glass #ifdef DEBUG
53047f5fcfbSSimon Glass 	for (i = 0; argv[i]; i++)
53147f5fcfbSSimon Glass 		printf("%d %s\n", i, argv[i]);
53247f5fcfbSSimon Glass #endif
53347f5fcfbSSimon Glass 
53447f5fcfbSSimon Glass 	if (state_uninit())
53547f5fcfbSSimon Glass 		os_exit(2);
53647f5fcfbSSimon Glass 
53747f5fcfbSSimon Glass 	err = execv(fname, argv);
53847f5fcfbSSimon Glass 	free(argv);
53947f5fcfbSSimon Glass 	if (err)
54047f5fcfbSSimon Glass 		return err;
54147f5fcfbSSimon Glass 
54247f5fcfbSSimon Glass 	return unlink(fname);
54347f5fcfbSSimon Glass }
54494eefdeeSSimon Glass 
os_find_u_boot(char * fname,int maxlen)545d4e33f5aSSimon Glass int os_find_u_boot(char *fname, int maxlen)
546d4e33f5aSSimon Glass {
547d4e33f5aSSimon Glass 	struct sandbox_state *state = state_get_current();
548d4e33f5aSSimon Glass 	const char *progname = state->argv[0];
549d4e33f5aSSimon Glass 	int len = strlen(progname);
550d4e33f5aSSimon Glass 	char *p;
551d4e33f5aSSimon Glass 	int fd;
552d4e33f5aSSimon Glass 
553d4e33f5aSSimon Glass 	if (len >= maxlen || len < 4)
554d4e33f5aSSimon Glass 		return -ENOSPC;
555d4e33f5aSSimon Glass 
556d4e33f5aSSimon Glass 	/* Look for 'u-boot' in the same directory as 'u-boot-spl' */
557d4e33f5aSSimon Glass 	strcpy(fname, progname);
558d4e33f5aSSimon Glass 	if (!strcmp(fname + len - 4, "-spl")) {
559d4e33f5aSSimon Glass 		fname[len - 4] = '\0';
560d4e33f5aSSimon Glass 		fd = os_open(fname, O_RDONLY);
561d4e33f5aSSimon Glass 		if (fd >= 0) {
562d4e33f5aSSimon Glass 			close(fd);
563d4e33f5aSSimon Glass 			return 0;
564d4e33f5aSSimon Glass 		}
565d4e33f5aSSimon Glass 	}
566d4e33f5aSSimon Glass 
567d4e33f5aSSimon Glass 	/* Look for 'u-boot' in the parent directory of spl/ */
568d4e33f5aSSimon Glass 	p = strstr(fname, "/spl/");
569d4e33f5aSSimon Glass 	if (p) {
570d4e33f5aSSimon Glass 		strcpy(p, p + 4);
571d4e33f5aSSimon Glass 		fd = os_open(fname, O_RDONLY);
572d4e33f5aSSimon Glass 		if (fd >= 0) {
573d4e33f5aSSimon Glass 			close(fd);
574d4e33f5aSSimon Glass 			return 0;
575d4e33f5aSSimon Glass 		}
576d4e33f5aSSimon Glass 	}
577d4e33f5aSSimon Glass 
578d4e33f5aSSimon Glass 	return -ENOENT;
579d4e33f5aSSimon Glass }
580d4e33f5aSSimon Glass 
os_spl_to_uboot(const char * fname)581d4e33f5aSSimon Glass int os_spl_to_uboot(const char *fname)
582d4e33f5aSSimon Glass {
583d4e33f5aSSimon Glass 	struct sandbox_state *state = state_get_current();
584d4e33f5aSSimon Glass 	char *argv[state->argc + 1];
585d4e33f5aSSimon Glass 	int ret;
586d4e33f5aSSimon Glass 
587d4e33f5aSSimon Glass 	memcpy(argv, state->argv, sizeof(char *) * (state->argc + 1));
588d4e33f5aSSimon Glass 	argv[0] = (char *)fname;
589d4e33f5aSSimon Glass 	ret = execv(fname, argv);
590d4e33f5aSSimon Glass 	if (ret)
591d4e33f5aSSimon Glass 		return ret;
592d4e33f5aSSimon Glass 
593d4e33f5aSSimon Glass 	return unlink(fname);
594d4e33f5aSSimon Glass }
595d4e33f5aSSimon Glass 
os_localtime(struct rtc_time * rt)59694eefdeeSSimon Glass void os_localtime(struct rtc_time *rt)
59794eefdeeSSimon Glass {
59894eefdeeSSimon Glass 	time_t t = time(NULL);
59994eefdeeSSimon Glass 	struct tm *tm;
60094eefdeeSSimon Glass 
60194eefdeeSSimon Glass 	tm = localtime(&t);
60294eefdeeSSimon Glass 	rt->tm_sec = tm->tm_sec;
60394eefdeeSSimon Glass 	rt->tm_min = tm->tm_min;
60494eefdeeSSimon Glass 	rt->tm_hour = tm->tm_hour;
60594eefdeeSSimon Glass 	rt->tm_mday = tm->tm_mday;
60694eefdeeSSimon Glass 	rt->tm_mon = tm->tm_mon + 1;
60794eefdeeSSimon Glass 	rt->tm_year = tm->tm_year + 1900;
60894eefdeeSSimon Glass 	rt->tm_wday = tm->tm_wday;
60994eefdeeSSimon Glass 	rt->tm_yday = tm->tm_yday;
61094eefdeeSSimon Glass 	rt->tm_isdst = tm->tm_isdst;
61194eefdeeSSimon Glass }
612