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