xref: /rk3399_rockchip-uboot/arch/sandbox/cpu/os.c (revision 94eefdee2f5db36d52e817a01b07c8255527e193)
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>
27*94eefdeeSSimon 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 
110ab06a758SMike Frysinger static void os_fd_restore(void)
111ab06a758SMike Frysinger {
112ffb87905SSimon Glass 	if (term_setup)
113ab06a758SMike Frysinger 		tcsetattr(0, TCSANOW, &orig_term);
114ab06a758SMike Frysinger }
115ab06a758SMike Frysinger 
116ab06a758SMike Frysinger /* Put tty into raw mode so <tab> and <ctrl+c> work */
117ffb87905SSimon Glass void os_tty_raw(int fd, bool allow_sigs)
118ab06a758SMike Frysinger {
119ab06a758SMike Frysinger 	struct termios term;
120ab06a758SMike Frysinger 
121ffb87905SSimon Glass 	if (term_setup)
122ab06a758SMike Frysinger 		return;
123ffb87905SSimon Glass 	term_setup = true;
124ab06a758SMike Frysinger 
125ab06a758SMike Frysinger 	/* If not a tty, don't complain */
126ab06a758SMike Frysinger 	if (tcgetattr(fd, &orig_term))
127ab06a758SMike Frysinger 		return;
128ab06a758SMike Frysinger 
129ab06a758SMike Frysinger 	term = orig_term;
130ab06a758SMike Frysinger 	term.c_iflag = IGNBRK | IGNPAR;
131ab06a758SMike Frysinger 	term.c_oflag = OPOST | ONLCR;
132ab06a758SMike Frysinger 	term.c_cflag = CS8 | CREAD | CLOCAL;
133ffb87905SSimon Glass 	term.c_lflag = allow_sigs ? ISIG : 0;
134ab06a758SMike Frysinger 	if (tcsetattr(fd, TCSANOW, &term))
135ab06a758SMike Frysinger 		return;
136ab06a758SMike Frysinger 
137ab06a758SMike Frysinger 	atexit(os_fd_restore);
138ab06a758SMike Frysinger }
13921899b10SMatthias Weisser 
14021899b10SMatthias Weisser void *os_malloc(size_t length)
14121899b10SMatthias Weisser {
14277595c6dSSimon Glass 	struct os_mem_hdr *hdr;
14377595c6dSSimon Glass 
14477595c6dSSimon Glass 	hdr = mmap(NULL, length + sizeof(*hdr), PROT_READ | PROT_WRITE,
14521899b10SMatthias Weisser 		   MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
14677595c6dSSimon Glass 	if (hdr == MAP_FAILED)
14777595c6dSSimon Glass 		return NULL;
14877595c6dSSimon Glass 	hdr->length = length;
14977595c6dSSimon Glass 
15077595c6dSSimon Glass 	return hdr + 1;
15177595c6dSSimon Glass }
15277595c6dSSimon Glass 
153347d06deSMasahiro Yamada void os_free(void *ptr)
15477595c6dSSimon Glass {
15577595c6dSSimon Glass 	struct os_mem_hdr *hdr = ptr;
15677595c6dSSimon Glass 
15777595c6dSSimon Glass 	hdr--;
15877595c6dSSimon Glass 	if (ptr)
15977595c6dSSimon Glass 		munmap(hdr, hdr->length + sizeof(*hdr));
16077595c6dSSimon Glass }
16177595c6dSSimon Glass 
16277595c6dSSimon Glass void *os_realloc(void *ptr, size_t length)
16377595c6dSSimon Glass {
16477595c6dSSimon Glass 	struct os_mem_hdr *hdr = ptr;
16577595c6dSSimon Glass 	void *buf = NULL;
16677595c6dSSimon Glass 
16777595c6dSSimon Glass 	hdr--;
16877595c6dSSimon Glass 	if (length != 0) {
16977595c6dSSimon Glass 		buf = os_malloc(length);
17077595c6dSSimon Glass 		if (!buf)
17177595c6dSSimon Glass 			return buf;
17277595c6dSSimon Glass 		if (ptr) {
17377595c6dSSimon Glass 			if (length > hdr->length)
17477595c6dSSimon Glass 				length = hdr->length;
17577595c6dSSimon Glass 			memcpy(buf, ptr, length);
17677595c6dSSimon Glass 		}
17777595c6dSSimon Glass 	}
17877595c6dSSimon Glass 	os_free(ptr);
17977595c6dSSimon Glass 
18077595c6dSSimon Glass 	return buf;
18121899b10SMatthias Weisser }
182d99a6874SMatthias Weisser 
183d99a6874SMatthias Weisser void os_usleep(unsigned long usec)
184d99a6874SMatthias Weisser {
185d99a6874SMatthias Weisser 	usleep(usec);
186d99a6874SMatthias Weisser }
187d99a6874SMatthias Weisser 
1882a54d159SSimon Glass uint64_t __attribute__((no_instrument_function)) os_get_nsec(void)
189d99a6874SMatthias Weisser {
190d99a6874SMatthias Weisser #if defined(CLOCK_MONOTONIC) && defined(_POSIX_MONOTONIC_CLOCK)
191d99a6874SMatthias Weisser 	struct timespec tp;
192d99a6874SMatthias Weisser 	if (EINVAL == clock_gettime(CLOCK_MONOTONIC, &tp)) {
193d99a6874SMatthias Weisser 		struct timeval tv;
194d99a6874SMatthias Weisser 
195d99a6874SMatthias Weisser 		gettimeofday(&tv, NULL);
196d99a6874SMatthias Weisser 		tp.tv_sec = tv.tv_sec;
197d99a6874SMatthias Weisser 		tp.tv_nsec = tv.tv_usec * 1000;
198d99a6874SMatthias Weisser 	}
199d99a6874SMatthias Weisser 	return tp.tv_sec * 1000000000ULL + tp.tv_nsec;
200d99a6874SMatthias Weisser #else
201d99a6874SMatthias Weisser 	struct timeval tv;
202d99a6874SMatthias Weisser 	gettimeofday(&tv, NULL);
203d99a6874SMatthias Weisser 	return tv.tv_sec * 1000000000ULL + tv.tv_usec * 1000;
204d99a6874SMatthias Weisser #endif
205d99a6874SMatthias Weisser }
20670db4212SSimon Glass 
20770db4212SSimon Glass static char *short_opts;
20870db4212SSimon Glass static struct option *long_opts;
20970db4212SSimon Glass 
21070db4212SSimon Glass int os_parse_args(struct sandbox_state *state, int argc, char *argv[])
21170db4212SSimon Glass {
2127b3efc66SSimon Glass 	struct sandbox_cmdline_option **sb_opt = __u_boot_sandbox_option_start;
21370db4212SSimon Glass 	size_t num_options = __u_boot_sandbox_option_count();
21470db4212SSimon Glass 	size_t i;
21570db4212SSimon Glass 
21670db4212SSimon Glass 	int hidden_short_opt;
21770db4212SSimon Glass 	size_t si;
21870db4212SSimon Glass 
21970db4212SSimon Glass 	int c;
22070db4212SSimon Glass 
22170db4212SSimon Glass 	if (short_opts || long_opts)
22270db4212SSimon Glass 		return 1;
22370db4212SSimon Glass 
22470db4212SSimon Glass 	state->argc = argc;
22570db4212SSimon Glass 	state->argv = argv;
22670db4212SSimon Glass 
22770db4212SSimon Glass 	/* dynamically construct the arguments to the system getopt_long */
22870db4212SSimon Glass 	short_opts = os_malloc(sizeof(*short_opts) * num_options * 2 + 1);
22970db4212SSimon Glass 	long_opts = os_malloc(sizeof(*long_opts) * num_options);
23070db4212SSimon Glass 	if (!short_opts || !long_opts)
23170db4212SSimon Glass 		return 1;
23270db4212SSimon Glass 
23370db4212SSimon Glass 	/*
23470db4212SSimon Glass 	 * getopt_long requires "val" to be unique (since that is what the
23570db4212SSimon Glass 	 * func returns), so generate unique values automatically for flags
23670db4212SSimon Glass 	 * that don't have a short option.  pick 0x100 as that is above the
23770db4212SSimon Glass 	 * single byte range (where ASCII/ISO-XXXX-X charsets live).
23870db4212SSimon Glass 	 */
23970db4212SSimon Glass 	hidden_short_opt = 0x100;
24070db4212SSimon Glass 	si = 0;
24170db4212SSimon Glass 	for (i = 0; i < num_options; ++i) {
24270db4212SSimon Glass 		long_opts[i].name = sb_opt[i]->flag;
24370db4212SSimon Glass 		long_opts[i].has_arg = sb_opt[i]->has_arg ?
24470db4212SSimon Glass 			required_argument : no_argument;
24570db4212SSimon Glass 		long_opts[i].flag = NULL;
24670db4212SSimon Glass 
24770db4212SSimon Glass 		if (sb_opt[i]->flag_short) {
24870db4212SSimon Glass 			short_opts[si++] = long_opts[i].val = sb_opt[i]->flag_short;
24970db4212SSimon Glass 			if (long_opts[i].has_arg == required_argument)
25070db4212SSimon Glass 				short_opts[si++] = ':';
25170db4212SSimon Glass 		} else
25270db4212SSimon Glass 			long_opts[i].val = sb_opt[i]->flag_short = hidden_short_opt++;
25370db4212SSimon Glass 	}
25470db4212SSimon Glass 	short_opts[si] = '\0';
25570db4212SSimon Glass 
25670db4212SSimon Glass 	/* we need to handle output ourselves since u-boot provides printf */
25770db4212SSimon Glass 	opterr = 0;
25870db4212SSimon Glass 
25970db4212SSimon Glass 	/*
26070db4212SSimon Glass 	 * walk all of the options the user gave us on the command line,
26170db4212SSimon Glass 	 * figure out what u-boot option structure they belong to (via
26270db4212SSimon Glass 	 * the unique short val key), and call the appropriate callback.
26370db4212SSimon Glass 	 */
26470db4212SSimon Glass 	while ((c = getopt_long(argc, argv, short_opts, long_opts, NULL)) != -1) {
26570db4212SSimon Glass 		for (i = 0; i < num_options; ++i) {
26670db4212SSimon Glass 			if (sb_opt[i]->flag_short == c) {
26770db4212SSimon Glass 				if (sb_opt[i]->callback(state, optarg)) {
26870db4212SSimon Glass 					state->parse_err = sb_opt[i]->flag;
26970db4212SSimon Glass 					return 0;
27070db4212SSimon Glass 				}
27170db4212SSimon Glass 				break;
27270db4212SSimon Glass 			}
27370db4212SSimon Glass 		}
27470db4212SSimon Glass 		if (i == num_options) {
27570db4212SSimon Glass 			/*
27670db4212SSimon Glass 			 * store the faulting flag for later display.  we have to
27770db4212SSimon Glass 			 * store the flag itself as the getopt parsing itself is
27870db4212SSimon Glass 			 * tricky: need to handle the following flags (assume all
27970db4212SSimon Glass 			 * of the below are unknown):
28070db4212SSimon Glass 			 *   -a        optopt='a' optind=<next>
28170db4212SSimon Glass 			 *   -abbbb    optopt='a' optind=<this>
28270db4212SSimon Glass 			 *   -aaaaa    optopt='a' optind=<this>
28370db4212SSimon Glass 			 *   --a       optopt=0   optind=<this>
28470db4212SSimon Glass 			 * as you can see, it is impossible to determine the exact
28570db4212SSimon Glass 			 * faulting flag without doing the parsing ourselves, so
28670db4212SSimon Glass 			 * we just report the specific flag that failed.
28770db4212SSimon Glass 			 */
28870db4212SSimon Glass 			if (optopt) {
28970db4212SSimon Glass 				static char parse_err[3] = { '-', 0, '\0', };
29070db4212SSimon Glass 				parse_err[1] = optopt;
29170db4212SSimon Glass 				state->parse_err = parse_err;
29270db4212SSimon Glass 			} else
29370db4212SSimon Glass 				state->parse_err = argv[optind - 1];
29470db4212SSimon Glass 			break;
29570db4212SSimon Glass 		}
29670db4212SSimon Glass 	}
29770db4212SSimon Glass 
29870db4212SSimon Glass 	return 0;
29970db4212SSimon Glass }
30062584db1SSimon Glass 
30162584db1SSimon Glass void os_dirent_free(struct os_dirent_node *node)
30262584db1SSimon Glass {
30362584db1SSimon Glass 	struct os_dirent_node *next;
30462584db1SSimon Glass 
30562584db1SSimon Glass 	while (node) {
30662584db1SSimon Glass 		next = node->next;
30762584db1SSimon Glass 		free(node);
30862584db1SSimon Glass 		node = next;
30962584db1SSimon Glass 	}
31062584db1SSimon Glass }
31162584db1SSimon Glass 
31262584db1SSimon Glass int os_dirent_ls(const char *dirname, struct os_dirent_node **headp)
31362584db1SSimon Glass {
31462584db1SSimon Glass 	struct dirent entry, *result;
31562584db1SSimon Glass 	struct os_dirent_node *head, *node, *next;
31662584db1SSimon Glass 	struct stat buf;
31762584db1SSimon Glass 	DIR *dir;
31862584db1SSimon Glass 	int ret;
31962584db1SSimon Glass 	char *fname;
32062584db1SSimon Glass 	int len;
32162584db1SSimon Glass 
32262584db1SSimon Glass 	*headp = NULL;
32362584db1SSimon Glass 	dir = opendir(dirname);
32462584db1SSimon Glass 	if (!dir)
32562584db1SSimon Glass 		return -1;
32662584db1SSimon Glass 
32762584db1SSimon Glass 	/* Create a buffer for the maximum filename length */
32862584db1SSimon Glass 	len = sizeof(entry.d_name) + strlen(dirname) + 2;
32962584db1SSimon Glass 	fname = malloc(len);
33062584db1SSimon Glass 	if (!fname) {
33162584db1SSimon Glass 		ret = -ENOMEM;
33262584db1SSimon Glass 		goto done;
33362584db1SSimon Glass 	}
33462584db1SSimon Glass 
33562584db1SSimon Glass 	for (node = head = NULL;; node = next) {
33662584db1SSimon Glass 		ret = readdir_r(dir, &entry, &result);
33762584db1SSimon Glass 		if (ret || !result)
33862584db1SSimon Glass 			break;
33962584db1SSimon Glass 		next = malloc(sizeof(*node) + strlen(entry.d_name) + 1);
34062584db1SSimon Glass 		if (!next) {
34162584db1SSimon Glass 			os_dirent_free(head);
34262584db1SSimon Glass 			ret = -ENOMEM;
34362584db1SSimon Glass 			goto done;
34462584db1SSimon Glass 		}
3459c38c070SStephen Warren 		next->next = NULL;
34662584db1SSimon Glass 		strcpy(next->name, entry.d_name);
34762584db1SSimon Glass 		switch (entry.d_type) {
34862584db1SSimon Glass 		case DT_REG:
34962584db1SSimon Glass 			next->type = OS_FILET_REG;
35062584db1SSimon Glass 			break;
35162584db1SSimon Glass 		case DT_DIR:
35262584db1SSimon Glass 			next->type = OS_FILET_DIR;
35362584db1SSimon Glass 			break;
35462584db1SSimon Glass 		case DT_LNK:
35562584db1SSimon Glass 			next->type = OS_FILET_LNK;
35662584db1SSimon Glass 			break;
35762584db1SSimon Glass 		}
35862584db1SSimon Glass 		next->size = 0;
35962584db1SSimon Glass 		snprintf(fname, len, "%s/%s", dirname, next->name);
36062584db1SSimon Glass 		if (!stat(fname, &buf))
36162584db1SSimon Glass 			next->size = buf.st_size;
36262584db1SSimon Glass 		if (node)
36362584db1SSimon Glass 			node->next = next;
36462584db1SSimon Glass 		if (!head)
36562584db1SSimon Glass 			head = node;
36662584db1SSimon Glass 	}
36762584db1SSimon Glass 	*headp = head;
36862584db1SSimon Glass 
36962584db1SSimon Glass done:
37062584db1SSimon Glass 	closedir(dir);
371f80a8bbeSSimon Glass 	free(fname);
37262584db1SSimon Glass 	return ret;
37362584db1SSimon Glass }
37462584db1SSimon Glass 
37562584db1SSimon Glass const char *os_dirent_typename[OS_FILET_COUNT] = {
37662584db1SSimon Glass 	"   ",
37762584db1SSimon Glass 	"SYM",
37862584db1SSimon Glass 	"DIR",
37962584db1SSimon Glass 	"???",
38062584db1SSimon Glass };
38162584db1SSimon Glass 
38262584db1SSimon Glass const char *os_dirent_get_typename(enum os_dirent_t type)
38362584db1SSimon Glass {
38462584db1SSimon Glass 	if (type >= 0 && type < OS_FILET_COUNT)
38562584db1SSimon Glass 		return os_dirent_typename[type];
38662584db1SSimon Glass 
38762584db1SSimon Glass 	return os_dirent_typename[OS_FILET_UNKNOWN];
38862584db1SSimon Glass }
38962584db1SSimon Glass 
39096b1046dSSuriyan Ramasami int os_get_filesize(const char *fname, loff_t *size)
39162584db1SSimon Glass {
39262584db1SSimon Glass 	struct stat buf;
39362584db1SSimon Glass 	int ret;
39462584db1SSimon Glass 
39562584db1SSimon Glass 	ret = stat(fname, &buf);
39662584db1SSimon Glass 	if (ret)
39762584db1SSimon Glass 		return ret;
39896b1046dSSuriyan Ramasami 	*size = buf.st_size;
39996b1046dSSuriyan Ramasami 	return 0;
40062584db1SSimon Glass }
40191b136c7SSimon Glass 
40291b136c7SSimon Glass void os_putc(int ch)
40391b136c7SSimon Glass {
40491b136c7SSimon Glass 	putchar(ch);
40591b136c7SSimon Glass }
40691b136c7SSimon Glass 
40791b136c7SSimon Glass void os_puts(const char *str)
40891b136c7SSimon Glass {
40991b136c7SSimon Glass 	while (*str)
41091b136c7SSimon Glass 		os_putc(*str++);
41191b136c7SSimon Glass }
4125c2859cdSSimon Glass 
4135c2859cdSSimon Glass int os_write_ram_buf(const char *fname)
4145c2859cdSSimon Glass {
4155c2859cdSSimon Glass 	struct sandbox_state *state = state_get_current();
4165c2859cdSSimon Glass 	int fd, ret;
4175c2859cdSSimon Glass 
4185c2859cdSSimon Glass 	fd = open(fname, O_CREAT | O_WRONLY, 0777);
4195c2859cdSSimon Glass 	if (fd < 0)
4205c2859cdSSimon Glass 		return -ENOENT;
4215c2859cdSSimon Glass 	ret = write(fd, state->ram_buf, state->ram_size);
4225c2859cdSSimon Glass 	close(fd);
4235c2859cdSSimon Glass 	if (ret != state->ram_size)
4245c2859cdSSimon Glass 		return -EIO;
4255c2859cdSSimon Glass 
4265c2859cdSSimon Glass 	return 0;
4275c2859cdSSimon Glass }
4285c2859cdSSimon Glass 
4295c2859cdSSimon Glass int os_read_ram_buf(const char *fname)
4305c2859cdSSimon Glass {
4315c2859cdSSimon Glass 	struct sandbox_state *state = state_get_current();
4325c2859cdSSimon Glass 	int fd, ret;
43396b1046dSSuriyan Ramasami 	loff_t size;
4345c2859cdSSimon Glass 
43596b1046dSSuriyan Ramasami 	ret = os_get_filesize(fname, &size);
43696b1046dSSuriyan Ramasami 	if (ret < 0)
43796b1046dSSuriyan Ramasami 		return ret;
4385c2859cdSSimon Glass 	if (size != state->ram_size)
4395c2859cdSSimon Glass 		return -ENOSPC;
4405c2859cdSSimon Glass 	fd = open(fname, O_RDONLY);
4415c2859cdSSimon Glass 	if (fd < 0)
4425c2859cdSSimon Glass 		return -ENOENT;
4435c2859cdSSimon Glass 
4445c2859cdSSimon Glass 	ret = read(fd, state->ram_buf, state->ram_size);
4455c2859cdSSimon Glass 	close(fd);
4465c2859cdSSimon Glass 	if (ret != state->ram_size)
4475c2859cdSSimon Glass 		return -EIO;
4485c2859cdSSimon Glass 
4495c2859cdSSimon Glass 	return 0;
4505c2859cdSSimon Glass }
45147f5fcfbSSimon Glass 
45247f5fcfbSSimon Glass static int make_exec(char *fname, const void *data, int size)
45347f5fcfbSSimon Glass {
45447f5fcfbSSimon Glass 	int fd;
45547f5fcfbSSimon Glass 
45647f5fcfbSSimon Glass 	strcpy(fname, "/tmp/u-boot.jump.XXXXXX");
45747f5fcfbSSimon Glass 	fd = mkstemp(fname);
45847f5fcfbSSimon Glass 	if (fd < 0)
45947f5fcfbSSimon Glass 		return -ENOENT;
46047f5fcfbSSimon Glass 	if (write(fd, data, size) < 0)
46147f5fcfbSSimon Glass 		return -EIO;
46247f5fcfbSSimon Glass 	close(fd);
46347f5fcfbSSimon Glass 	if (chmod(fname, 0777))
46447f5fcfbSSimon Glass 		return -ENOEXEC;
46547f5fcfbSSimon Glass 
46647f5fcfbSSimon Glass 	return 0;
46747f5fcfbSSimon Glass }
46847f5fcfbSSimon Glass 
46947f5fcfbSSimon Glass static int add_args(char ***argvp, const char *add_args[], int count)
47047f5fcfbSSimon Glass {
47147f5fcfbSSimon Glass 	char **argv;
47247f5fcfbSSimon Glass 	int argc;
47347f5fcfbSSimon Glass 
47447f5fcfbSSimon Glass 	for (argv = *argvp, argc = 0; (*argvp)[argc]; argc++)
47547f5fcfbSSimon Glass 		;
47647f5fcfbSSimon Glass 
47747f5fcfbSSimon Glass 	argv = malloc((argc + count + 1) * sizeof(char *));
47847f5fcfbSSimon Glass 	if (!argv) {
47947f5fcfbSSimon Glass 		printf("Out of memory for %d argv\n", count);
48047f5fcfbSSimon Glass 		return -ENOMEM;
48147f5fcfbSSimon Glass 	}
48247f5fcfbSSimon Glass 	memcpy(argv, *argvp, argc * sizeof(char *));
48347f5fcfbSSimon Glass 	memcpy(argv + argc, add_args, count * sizeof(char *));
48447f5fcfbSSimon Glass 	argv[argc + count] = NULL;
48547f5fcfbSSimon Glass 
48647f5fcfbSSimon Glass 	*argvp = argv;
48747f5fcfbSSimon Glass 	return 0;
48847f5fcfbSSimon Glass }
48947f5fcfbSSimon Glass 
49047f5fcfbSSimon Glass int os_jump_to_image(const void *dest, int size)
49147f5fcfbSSimon Glass {
49247f5fcfbSSimon Glass 	struct sandbox_state *state = state_get_current();
49347f5fcfbSSimon Glass 	char fname[30], mem_fname[30];
49447f5fcfbSSimon Glass 	int fd, err;
495ab839dc3SSimon Glass 	const char *extra_args[5];
49647f5fcfbSSimon Glass 	char **argv = state->argv;
49747f5fcfbSSimon Glass #ifdef DEBUG
49847f5fcfbSSimon Glass 	int argc, i;
49947f5fcfbSSimon Glass #endif
50047f5fcfbSSimon Glass 
50147f5fcfbSSimon Glass 	err = make_exec(fname, dest, size);
50247f5fcfbSSimon Glass 	if (err)
50347f5fcfbSSimon Glass 		return err;
50447f5fcfbSSimon Glass 
50547f5fcfbSSimon Glass 	strcpy(mem_fname, "/tmp/u-boot.mem.XXXXXX");
50647f5fcfbSSimon Glass 	fd = mkstemp(mem_fname);
50747f5fcfbSSimon Glass 	if (fd < 0)
50847f5fcfbSSimon Glass 		return -ENOENT;
50947f5fcfbSSimon Glass 	close(fd);
51047f5fcfbSSimon Glass 	err = os_write_ram_buf(mem_fname);
51147f5fcfbSSimon Glass 	if (err)
51247f5fcfbSSimon Glass 		return err;
51347f5fcfbSSimon Glass 
51447f5fcfbSSimon Glass 	os_fd_restore();
51547f5fcfbSSimon Glass 
51647f5fcfbSSimon Glass 	extra_args[0] = "-j";
51747f5fcfbSSimon Glass 	extra_args[1] = fname;
51847f5fcfbSSimon Glass 	extra_args[2] = "-m";
51947f5fcfbSSimon Glass 	extra_args[3] = mem_fname;
520ab839dc3SSimon Glass 	extra_args[4] = "--rm_memory";
52147f5fcfbSSimon Glass 	err = add_args(&argv, extra_args,
52247f5fcfbSSimon Glass 		       sizeof(extra_args) / sizeof(extra_args[0]));
52347f5fcfbSSimon Glass 	if (err)
52447f5fcfbSSimon Glass 		return err;
52547f5fcfbSSimon Glass 
52647f5fcfbSSimon Glass #ifdef DEBUG
52747f5fcfbSSimon Glass 	for (i = 0; argv[i]; i++)
52847f5fcfbSSimon Glass 		printf("%d %s\n", i, argv[i]);
52947f5fcfbSSimon Glass #endif
53047f5fcfbSSimon Glass 
53147f5fcfbSSimon Glass 	if (state_uninit())
53247f5fcfbSSimon Glass 		os_exit(2);
53347f5fcfbSSimon Glass 
53447f5fcfbSSimon Glass 	err = execv(fname, argv);
53547f5fcfbSSimon Glass 	free(argv);
53647f5fcfbSSimon Glass 	if (err)
53747f5fcfbSSimon Glass 		return err;
53847f5fcfbSSimon Glass 
53947f5fcfbSSimon Glass 	return unlink(fname);
54047f5fcfbSSimon Glass }
541*94eefdeeSSimon Glass 
542*94eefdeeSSimon Glass void os_localtime(struct rtc_time *rt)
543*94eefdeeSSimon Glass {
544*94eefdeeSSimon Glass 	time_t t = time(NULL);
545*94eefdeeSSimon Glass 	struct tm *tm;
546*94eefdeeSSimon Glass 
547*94eefdeeSSimon Glass 	tm = localtime(&t);
548*94eefdeeSSimon Glass 	rt->tm_sec = tm->tm_sec;
549*94eefdeeSSimon Glass 	rt->tm_min = tm->tm_min;
550*94eefdeeSSimon Glass 	rt->tm_hour = tm->tm_hour;
551*94eefdeeSSimon Glass 	rt->tm_mday = tm->tm_mday;
552*94eefdeeSSimon Glass 	rt->tm_mon = tm->tm_mon + 1;
553*94eefdeeSSimon Glass 	rt->tm_year = tm->tm_year + 1900;
554*94eefdeeSSimon Glass 	rt->tm_wday = tm->tm_wday;
555*94eefdeeSSimon Glass 	rt->tm_yday = tm->tm_yday;
556*94eefdeeSSimon Glass 	rt->tm_isdst = tm->tm_isdst;
557*94eefdeeSSimon Glass }
558