Merge branch 'for-2023.07' of https://source.denx.de/u-boot/custodians/u-boot-mpc8xx
[platform/kernel/u-boot.git] / arch / sandbox / cpu / os.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2011 The Chromium OS Authors.
4  */
5
6 #define _GNU_SOURCE
7
8 #include <dirent.h>
9 #include <errno.h>
10 #include <fcntl.h>
11 #include <pthread.h>
12 #include <getopt.h>
13 #include <setjmp.h>
14 #include <signal.h>
15 #include <stdarg.h>
16 #include <stdio.h>
17 #include <stdint.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <termios.h>
21 #include <time.h>
22 #include <ucontext.h>
23 #include <unistd.h>
24 #include <sys/mman.h>
25 #include <sys/stat.h>
26 #include <sys/time.h>
27 #include <sys/types.h>
28 #include <linux/compiler_attributes.h>
29 #include <linux/types.h>
30
31 #include <asm/fuzzing_engine.h>
32 #include <asm/getopt.h>
33 #include <asm/main.h>
34 #include <asm/sections.h>
35 #include <asm/state.h>
36 #include <os.h>
37 #include <rtc_def.h>
38
39 /* Environment variable for time offset */
40 #define ENV_TIME_OFFSET "UBOOT_SB_TIME_OFFSET"
41
42 /* Operating System Interface */
43
44 struct os_mem_hdr {
45         size_t length;          /* number of bytes in the block */
46 };
47
48 ssize_t os_read(int fd, void *buf, size_t count)
49 {
50         return read(fd, buf, count);
51 }
52
53 ssize_t os_write(int fd, const void *buf, size_t count)
54 {
55         return write(fd, buf, count);
56 }
57
58 int os_printf(const char *fmt, ...)
59 {
60         va_list args;
61         int i;
62
63         va_start(args, fmt);
64         i = vfprintf(stdout, fmt, args);
65         va_end(args);
66
67         return i;
68 }
69
70 off_t os_lseek(int fd, off_t offset, int whence)
71 {
72         if (whence == OS_SEEK_SET)
73                 whence = SEEK_SET;
74         else if (whence == OS_SEEK_CUR)
75                 whence = SEEK_CUR;
76         else if (whence == OS_SEEK_END)
77                 whence = SEEK_END;
78         else
79                 os_exit(1);
80         return lseek(fd, offset, whence);
81 }
82
83 int os_open(const char *pathname, int os_flags)
84 {
85         int flags;
86
87         switch (os_flags & OS_O_MASK) {
88         case OS_O_RDONLY:
89         default:
90                 flags = O_RDONLY;
91                 break;
92
93         case OS_O_WRONLY:
94                 flags = O_WRONLY;
95                 break;
96
97         case OS_O_RDWR:
98                 flags = O_RDWR;
99                 break;
100         }
101
102         if (os_flags & OS_O_CREAT)
103                 flags |= O_CREAT;
104         if (os_flags & OS_O_TRUNC)
105                 flags |= O_TRUNC;
106         /*
107          * During a cold reset execv() is used to relaunch the U-Boot binary.
108          * We must ensure that all files are closed in this case.
109          */
110         flags |= O_CLOEXEC;
111
112         return open(pathname, flags, 0777);
113 }
114
115 int os_close(int fd)
116 {
117         /* Do not close the console input */
118         if (fd)
119                 return close(fd);
120         return -1;
121 }
122
123 int os_unlink(const char *pathname)
124 {
125         return unlink(pathname);
126 }
127
128 void os_exit(int exit_code)
129 {
130         exit(exit_code);
131 }
132
133 unsigned int os_alarm(unsigned int seconds)
134 {
135         return alarm(seconds);
136 }
137
138 void os_set_alarm_handler(void (*handler)(int))
139 {
140         if (!handler)
141                 handler = SIG_DFL;
142         signal(SIGALRM, handler);
143 }
144
145 void os_raise_sigalrm(void)
146 {
147         raise(SIGALRM);
148 }
149
150 int os_write_file(const char *fname, const void *buf, int size)
151 {
152         int fd;
153
154         fd = os_open(fname, OS_O_WRONLY | OS_O_CREAT | OS_O_TRUNC);
155         if (fd < 0) {
156                 printf("Cannot open file '%s'\n", fname);
157                 return -EIO;
158         }
159         if (os_write(fd, buf, size) != size) {
160                 printf("Cannot write to file '%s'\n", fname);
161                 os_close(fd);
162                 return -EIO;
163         }
164         os_close(fd);
165
166         return 0;
167 }
168
169 off_t os_filesize(int fd)
170 {
171         off_t size;
172
173         size = os_lseek(fd, 0, OS_SEEK_END);
174         if (size < 0)
175                 return -errno;
176         if (os_lseek(fd, 0, OS_SEEK_SET) < 0)
177                 return -errno;
178
179         return size;
180 }
181
182 int os_read_file(const char *fname, void **bufp, int *sizep)
183 {
184         off_t size;
185         int ret = -EIO;
186         int fd;
187
188         fd = os_open(fname, OS_O_RDONLY);
189         if (fd < 0) {
190                 printf("Cannot open file '%s'\n", fname);
191                 goto err;
192         }
193         size = os_filesize(fd);
194         if (size < 0) {
195                 printf("Cannot get file size of '%s'\n", fname);
196                 goto err;
197         }
198
199         *bufp = os_malloc(size);
200         if (!*bufp) {
201                 printf("Not enough memory to read file '%s'\n", fname);
202                 ret = -ENOMEM;
203                 goto err;
204         }
205         if (os_read(fd, *bufp, size) != size) {
206                 printf("Cannot read from file '%s'\n", fname);
207                 goto err;
208         }
209         os_close(fd);
210         *sizep = size;
211
212         return 0;
213 err:
214         os_close(fd);
215         return ret;
216 }
217
218 int os_map_file(const char *pathname, int os_flags, void **bufp, int *sizep)
219 {
220         void *ptr;
221         off_t size;
222         int ifd;
223
224         ifd = os_open(pathname, os_flags);
225         if (ifd < 0) {
226                 printf("Cannot open file '%s'\n", pathname);
227                 return -EIO;
228         }
229         size = os_filesize(ifd);
230         if (size < 0) {
231                 printf("Cannot get file size of '%s'\n", pathname);
232                 return -EIO;
233         }
234         if ((unsigned long long)size > (unsigned long long)SIZE_MAX) {
235                 printf("File '%s' too large to map\n", pathname);
236                 return -EIO;
237         }
238
239         ptr = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, ifd, 0);
240         if (ptr == MAP_FAILED) {
241                 printf("Can't map file '%s': %s\n", pathname, strerror(errno));
242                 return -EPERM;
243         }
244
245         *bufp = ptr;
246         *sizep = size;
247
248         return 0;
249 }
250
251 int os_unmap(void *buf, int size)
252 {
253         if (munmap(buf, size)) {
254                 printf("Can't unmap %p %x\n", buf, size);
255                 return -EIO;
256         }
257
258         return 0;
259 }
260
261 /* Restore tty state when we exit */
262 static struct termios orig_term;
263 static bool term_setup;
264 static bool term_nonblock;
265
266 void os_fd_restore(void)
267 {
268         if (term_setup) {
269                 int flags;
270
271                 tcsetattr(0, TCSANOW, &orig_term);
272                 if (term_nonblock) {
273                         flags = fcntl(0, F_GETFL, 0);
274                         fcntl(0, F_SETFL, flags & ~O_NONBLOCK);
275                 }
276                 term_setup = false;
277         }
278 }
279
280 static void os_sigint_handler(int sig)
281 {
282         os_fd_restore();
283         signal(SIGINT, SIG_DFL);
284         raise(SIGINT);
285 }
286
287 static void os_signal_handler(int sig, siginfo_t *info, void *con)
288 {
289         ucontext_t __maybe_unused *context = con;
290         unsigned long pc;
291
292 #if defined(__x86_64__)
293         pc = context->uc_mcontext.gregs[REG_RIP];
294 #elif defined(__aarch64__)
295         pc = context->uc_mcontext.pc;
296 #elif defined(__riscv)
297         pc = context->uc_mcontext.__gregs[REG_PC];
298 #else
299         const char msg[] =
300                 "\nUnsupported architecture, cannot read program counter\n";
301
302         os_write(1, msg, sizeof(msg));
303         pc = 0;
304 #endif
305
306         os_signal_action(sig, pc);
307 }
308
309 int os_setup_signal_handlers(void)
310 {
311         struct sigaction act;
312
313         act.sa_sigaction = os_signal_handler;
314         sigemptyset(&act.sa_mask);
315         act.sa_flags = SA_SIGINFO;
316         if (sigaction(SIGILL, &act, NULL) ||
317             sigaction(SIGBUS, &act, NULL) ||
318             sigaction(SIGSEGV, &act, NULL))
319                 return -1;
320         return 0;
321 }
322
323 /* Put tty into raw mode so <tab> and <ctrl+c> work */
324 void os_tty_raw(int fd, bool allow_sigs)
325 {
326         struct termios term;
327         int flags;
328
329         if (term_setup)
330                 return;
331
332         /* If not a tty, don't complain */
333         if (tcgetattr(fd, &orig_term))
334                 return;
335
336         term = orig_term;
337         term.c_iflag = IGNBRK | IGNPAR;
338         term.c_oflag = OPOST | ONLCR;
339         term.c_cflag = CS8 | CREAD | CLOCAL;
340         term.c_lflag = allow_sigs ? ISIG : 0;
341         if (tcsetattr(fd, TCSANOW, &term))
342                 return;
343
344         flags = fcntl(fd, F_GETFL, 0);
345         if (!(flags & O_NONBLOCK)) {
346                 if (fcntl(fd, F_SETFL, flags | O_NONBLOCK))
347                         return;
348                 term_nonblock = true;
349         }
350
351         term_setup = true;
352         atexit(os_fd_restore);
353         signal(SIGINT, os_sigint_handler);
354 }
355
356 /*
357  * Provide our own malloc so we don't use space in the sandbox ram_buf for
358  * allocations that are internal to sandbox, or need to be done before U-Boot's
359  * malloc() is ready.
360  */
361 void *os_malloc(size_t length)
362 {
363         int page_size = getpagesize();
364         struct os_mem_hdr *hdr;
365
366         if (!length)
367                 return NULL;
368         /*
369          * Use an address that is hopefully available to us so that pointers
370          * to this memory are fairly obvious. If we end up with a different
371          * address, that's fine too.
372          */
373         hdr = mmap((void *)0x10000000, length + page_size,
374                    PROT_READ | PROT_WRITE | PROT_EXEC,
375                    MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
376         if (hdr == MAP_FAILED)
377                 return NULL;
378         hdr->length = length;
379
380         return (void *)hdr + page_size;
381 }
382
383 void os_free(void *ptr)
384 {
385         int page_size = getpagesize();
386         struct os_mem_hdr *hdr;
387
388         if (ptr) {
389                 hdr = ptr - page_size;
390                 munmap(hdr, hdr->length + page_size);
391         }
392 }
393
394 /* These macros are from kernel.h but not accessible in this file */
395 #define ALIGN(x, a)             __ALIGN_MASK((x), (typeof(x))(a) - 1)
396 #define __ALIGN_MASK(x, mask)   (((x) + (mask)) & ~(mask))
397
398 /*
399  * Provide our own malloc so we don't use space in the sandbox ram_buf for
400  * allocations that are internal to sandbox, or need to be done before U-Boot's
401  * malloc() is ready.
402  */
403 void *os_realloc(void *ptr, size_t length)
404 {
405         int page_size = getpagesize();
406         struct os_mem_hdr *hdr;
407         void *new_ptr;
408
409         /* Reallocating a NULL pointer is just an alloc */
410         if (!ptr)
411                 return os_malloc(length);
412
413         /* Changing a length to 0 is just a free */
414         if (length) {
415                 os_free(ptr);
416                 return NULL;
417         }
418
419         /*
420          * If the new size is the same number of pages as the old, nothing to
421          * do. There isn't much point in shrinking things
422          */
423         hdr = ptr - page_size;
424         if (ALIGN(length, page_size) <= ALIGN(hdr->length, page_size))
425                 return ptr;
426
427         /* We have to grow it, so allocate something new */
428         new_ptr = os_malloc(length);
429         memcpy(new_ptr, ptr, hdr->length);
430         os_free(ptr);
431
432         return new_ptr;
433 }
434
435 void os_usleep(unsigned long usec)
436 {
437         usleep(usec);
438 }
439
440 uint64_t __attribute__((no_instrument_function)) os_get_nsec(void)
441 {
442 #if defined(CLOCK_MONOTONIC) && defined(_POSIX_MONOTONIC_CLOCK)
443         struct timespec tp;
444         if (EINVAL == clock_gettime(CLOCK_MONOTONIC, &tp)) {
445                 struct timeval tv;
446
447                 gettimeofday(&tv, NULL);
448                 tp.tv_sec = tv.tv_sec;
449                 tp.tv_nsec = tv.tv_usec * 1000;
450         }
451         return tp.tv_sec * 1000000000ULL + tp.tv_nsec;
452 #else
453         struct timeval tv;
454         gettimeofday(&tv, NULL);
455         return tv.tv_sec * 1000000000ULL + tv.tv_usec * 1000;
456 #endif
457 }
458
459 static char *short_opts;
460 static struct option *long_opts;
461
462 int os_parse_args(struct sandbox_state *state, int argc, char *argv[])
463 {
464         struct sandbox_cmdline_option **sb_opt =
465                 __u_boot_sandbox_option_start();
466         size_t num_options = __u_boot_sandbox_option_count();
467         size_t i;
468
469         int hidden_short_opt;
470         size_t si;
471
472         int c;
473
474         if (short_opts || long_opts)
475                 return 1;
476
477         state->argc = argc;
478         state->argv = argv;
479
480         /* dynamically construct the arguments to the system getopt_long */
481         short_opts = os_malloc(sizeof(*short_opts) * num_options * 2 + 1);
482         long_opts = os_malloc(sizeof(*long_opts) * (num_options + 1));
483         if (!short_opts || !long_opts)
484                 return 1;
485
486         /*
487          * getopt_long requires "val" to be unique (since that is what the
488          * func returns), so generate unique values automatically for flags
489          * that don't have a short option.  pick 0x100 as that is above the
490          * single byte range (where ASCII/ISO-XXXX-X charsets live).
491          */
492         hidden_short_opt = 0x100;
493         si = 0;
494         for (i = 0; i < num_options; ++i) {
495                 long_opts[i].name = sb_opt[i]->flag;
496                 long_opts[i].has_arg = sb_opt[i]->has_arg ?
497                         required_argument : no_argument;
498                 long_opts[i].flag = NULL;
499
500                 if (sb_opt[i]->flag_short) {
501                         short_opts[si++] = long_opts[i].val = sb_opt[i]->flag_short;
502                         if (long_opts[i].has_arg == required_argument)
503                                 short_opts[si++] = ':';
504                 } else
505                         long_opts[i].val = sb_opt[i]->flag_short = hidden_short_opt++;
506         }
507         short_opts[si] = '\0';
508
509         /* we need to handle output ourselves since u-boot provides printf */
510         opterr = 0;
511
512         memset(&long_opts[num_options], '\0', sizeof(*long_opts));
513         /*
514          * walk all of the options the user gave us on the command line,
515          * figure out what u-boot option structure they belong to (via
516          * the unique short val key), and call the appropriate callback.
517          */
518         while ((c = getopt_long(argc, argv, short_opts, long_opts, NULL)) != -1) {
519                 for (i = 0; i < num_options; ++i) {
520                         if (sb_opt[i]->flag_short == c) {
521                                 if (sb_opt[i]->callback(state, optarg)) {
522                                         state->parse_err = sb_opt[i]->flag;
523                                         return 0;
524                                 }
525                                 break;
526                         }
527                 }
528                 if (i == num_options) {
529                         /*
530                          * store the faulting flag for later display.  we have to
531                          * store the flag itself as the getopt parsing itself is
532                          * tricky: need to handle the following flags (assume all
533                          * of the below are unknown):
534                          *   -a        optopt='a' optind=<next>
535                          *   -abbbb    optopt='a' optind=<this>
536                          *   -aaaaa    optopt='a' optind=<this>
537                          *   --a       optopt=0   optind=<this>
538                          * as you can see, it is impossible to determine the exact
539                          * faulting flag without doing the parsing ourselves, so
540                          * we just report the specific flag that failed.
541                          */
542                         if (optopt) {
543                                 static char parse_err[3] = { '-', 0, '\0', };
544                                 parse_err[1] = optopt;
545                                 state->parse_err = parse_err;
546                         } else
547                                 state->parse_err = argv[optind - 1];
548                         break;
549                 }
550         }
551
552         return 0;
553 }
554
555 void os_dirent_free(struct os_dirent_node *node)
556 {
557         struct os_dirent_node *next;
558
559         while (node) {
560                 next = node->next;
561                 os_free(node);
562                 node = next;
563         }
564 }
565
566 int os_dirent_ls(const char *dirname, struct os_dirent_node **headp)
567 {
568         struct dirent *entry;
569         struct os_dirent_node *head, *node, *next;
570         struct stat buf;
571         DIR *dir;
572         int ret;
573         char *fname;
574         char *old_fname;
575         int len;
576         int dirlen;
577
578         *headp = NULL;
579         dir = opendir(dirname);
580         if (!dir)
581                 return -1;
582
583         /* Create a buffer upfront, with typically sufficient size */
584         dirlen = strlen(dirname) + 2;
585         len = dirlen + 256;
586         fname = os_malloc(len);
587         if (!fname) {
588                 ret = -ENOMEM;
589                 goto done;
590         }
591
592         for (node = head = NULL;; node = next) {
593                 errno = 0;
594                 entry = readdir(dir);
595                 if (!entry) {
596                         ret = errno;
597                         break;
598                 }
599                 next = os_malloc(sizeof(*node) + strlen(entry->d_name) + 1);
600                 if (!next) {
601                         os_dirent_free(head);
602                         ret = -ENOMEM;
603                         goto done;
604                 }
605                 if (dirlen + strlen(entry->d_name) > len) {
606                         len = dirlen + strlen(entry->d_name);
607                         old_fname = fname;
608                         fname = os_realloc(fname, len);
609                         if (!fname) {
610                                 os_free(old_fname);
611                                 os_free(next);
612                                 os_dirent_free(head);
613                                 ret = -ENOMEM;
614                                 goto done;
615                         }
616                 }
617                 next->next = NULL;
618                 strcpy(next->name, entry->d_name);
619                 switch (entry->d_type) {
620                 case DT_REG:
621                         next->type = OS_FILET_REG;
622                         break;
623                 case DT_DIR:
624                         next->type = OS_FILET_DIR;
625                         break;
626                 case DT_LNK:
627                         next->type = OS_FILET_LNK;
628                         break;
629                 default:
630                         next->type = OS_FILET_UNKNOWN;
631                 }
632                 next->size = 0;
633                 snprintf(fname, len, "%s/%s", dirname, next->name);
634                 if (!stat(fname, &buf))
635                         next->size = buf.st_size;
636                 if (node)
637                         node->next = next;
638                 else
639                         head = next;
640         }
641         *headp = head;
642
643 done:
644         closedir(dir);
645         os_free(fname);
646         return ret;
647 }
648
649 const char *os_dirent_typename[OS_FILET_COUNT] = {
650         "   ",
651         "SYM",
652         "DIR",
653         "???",
654 };
655
656 const char *os_dirent_get_typename(enum os_dirent_t type)
657 {
658         if (type >= OS_FILET_REG && type < OS_FILET_COUNT)
659                 return os_dirent_typename[type];
660
661         return os_dirent_typename[OS_FILET_UNKNOWN];
662 }
663
664 /*
665  * For compatibility reasons avoid loff_t here.
666  * U-Boot defines loff_t as long long.
667  * But /usr/include/linux/types.h may not define it at all.
668  * Alpine Linux being one example.
669  */
670 int os_get_filesize(const char *fname, long long *size)
671 {
672         struct stat buf;
673         int ret;
674
675         ret = stat(fname, &buf);
676         if (ret)
677                 return ret;
678         *size = buf.st_size;
679         return 0;
680 }
681
682 void os_putc(int ch)
683 {
684         os_write(1, &ch, 1);
685 }
686
687 void os_puts(const char *str)
688 {
689         while (*str)
690                 os_putc(*str++);
691 }
692
693 void os_flush(void)
694 {
695         fflush(stdout);
696 }
697
698 int os_write_ram_buf(const char *fname)
699 {
700         struct sandbox_state *state = state_get_current();
701         int fd, ret;
702
703         fd = open(fname, O_CREAT | O_WRONLY, 0777);
704         if (fd < 0)
705                 return -ENOENT;
706         ret = write(fd, state->ram_buf, state->ram_size);
707         close(fd);
708         if (ret != state->ram_size)
709                 return -EIO;
710
711         return 0;
712 }
713
714 int os_read_ram_buf(const char *fname)
715 {
716         struct sandbox_state *state = state_get_current();
717         int fd, ret;
718         long long size;
719
720         ret = os_get_filesize(fname, &size);
721         if (ret < 0)
722                 return ret;
723         if (size != state->ram_size)
724                 return -ENOSPC;
725         fd = open(fname, O_RDONLY);
726         if (fd < 0)
727                 return -ENOENT;
728
729         ret = read(fd, state->ram_buf, state->ram_size);
730         close(fd);
731         if (ret != state->ram_size)
732                 return -EIO;
733
734         return 0;
735 }
736
737 static int make_exec(char *fname, const void *data, int size)
738 {
739         int fd;
740
741         strcpy(fname, "/tmp/u-boot.jump.XXXXXX");
742         fd = mkstemp(fname);
743         if (fd < 0)
744                 return -ENOENT;
745         if (write(fd, data, size) < 0)
746                 return -EIO;
747         close(fd);
748         if (chmod(fname, 0777))
749                 return -ENOEXEC;
750
751         return 0;
752 }
753
754 /**
755  * add_args() - Allocate a new argv with the given args
756  *
757  * This is used to create a new argv array with all the old arguments and some
758  * new ones that are passed in
759  *
760  * @argvp:  Returns newly allocated args list
761  * @add_args: Arguments to add, each a string
762  * @count: Number of arguments in @add_args
763  * Return: 0 if OK, -ENOMEM if out of memory
764  */
765 static int add_args(char ***argvp, char *add_args[], int count)
766 {
767         char **argv, **ap;
768         int argc;
769
770         for (argc = 0; (*argvp)[argc]; argc++)
771                 ;
772
773         argv = os_malloc((argc + count + 1) * sizeof(char *));
774         if (!argv) {
775                 printf("Out of memory for %d argv\n", count);
776                 return -ENOMEM;
777         }
778         for (ap = *argvp, argc = 0; *ap; ap++) {
779                 char *arg = *ap;
780
781                 /* Drop args that we don't want to propagate */
782                 if (*arg == '-' && strlen(arg) == 2) {
783                         switch (arg[1]) {
784                         case 'j':
785                         case 'm':
786                                 ap++;
787                                 continue;
788                         }
789                 } else if (!strcmp(arg, "--rm_memory")) {
790                         continue;
791                 }
792                 argv[argc++] = arg;
793         }
794
795         memcpy(argv + argc, add_args, count * sizeof(char *));
796         argv[argc + count] = NULL;
797
798         *argvp = argv;
799         return 0;
800 }
801
802 /**
803  * os_jump_to_file() - Jump to a new program
804  *
805  * This saves the memory buffer, sets up arguments to the new process, then
806  * execs it.
807  *
808  * @fname: Filename to exec
809  * Return: does not return on success, any return value is an error
810  */
811 static int os_jump_to_file(const char *fname, bool delete_it)
812 {
813         struct sandbox_state *state = state_get_current();
814         char mem_fname[30];
815         int fd, err;
816         char *extra_args[5];
817         char **argv = state->argv;
818         int argc;
819 #ifdef DEBUG
820         int i;
821 #endif
822
823         strcpy(mem_fname, "/tmp/u-boot.mem.XXXXXX");
824         fd = mkstemp(mem_fname);
825         if (fd < 0)
826                 return -ENOENT;
827         close(fd);
828         err = os_write_ram_buf(mem_fname);
829         if (err)
830                 return err;
831
832         os_fd_restore();
833
834         argc = 0;
835         if (delete_it) {
836                 extra_args[argc++] = "-j";
837                 extra_args[argc++] = (char *)fname;
838         }
839         extra_args[argc++] = "-m";
840         extra_args[argc++] = mem_fname;
841         if (state->ram_buf_rm)
842                 extra_args[argc++] = "--rm_memory";
843         err = add_args(&argv, extra_args, argc);
844         if (err)
845                 return err;
846         argv[0] = (char *)fname;
847
848 #ifdef DEBUG
849         for (i = 0; argv[i]; i++)
850                 printf("%d %s\n", i, argv[i]);
851 #endif
852
853         if (state_uninit())
854                 os_exit(2);
855
856         err = execv(fname, argv);
857         os_free(argv);
858         if (err) {
859                 perror("Unable to run image");
860                 printf("Image filename '%s'\n", fname);
861                 return err;
862         }
863
864         if (delete_it)
865                 return unlink(fname);
866
867         return -EFAULT;
868 }
869
870 int os_jump_to_image(const void *dest, int size)
871 {
872         char fname[30];
873         int err;
874
875         err = make_exec(fname, dest, size);
876         if (err)
877                 return err;
878
879         return os_jump_to_file(fname, true);
880 }
881
882 int os_find_u_boot(char *fname, int maxlen, bool use_img,
883                    const char *cur_prefix, const char *next_prefix)
884 {
885         struct sandbox_state *state = state_get_current();
886         const char *progname = state->argv[0];
887         int len = strlen(progname);
888         char subdir[10];
889         char *suffix;
890         char *p;
891         int fd;
892
893         if (len >= maxlen || len < 4)
894                 return -ENOSPC;
895
896         strcpy(fname, progname);
897         suffix = fname + len - 4;
898
899         /* Change the existing suffix to the new one */
900         if (*suffix != '-')
901                 return -EINVAL;
902
903         if (*next_prefix)
904                 strcpy(suffix + 1, next_prefix);  /* e.g. "-tpl" to "-spl" */
905         else
906                 *suffix = '\0';  /* e.g. "-spl" to "" */
907         fd = os_open(fname, O_RDONLY);
908         if (fd >= 0) {
909                 close(fd);
910                 return 0;
911         }
912
913         /*
914          * We didn't find it, so try looking for 'u-boot-xxx' in the xxx/
915          * directory. Replace the old dirname with the new one.
916          */
917         snprintf(subdir, sizeof(subdir), "/%s/", cur_prefix);
918         p = strstr(fname, subdir);
919         if (p) {
920                 if (*next_prefix)
921                         /* e.g. ".../tpl/u-boot-spl"  to "../spl/u-boot-spl" */
922                         memcpy(p + 1, next_prefix, strlen(next_prefix));
923                 else
924                         /* e.g. ".../spl/u-boot" to ".../u-boot" */
925                         strcpy(p, p + 1 + strlen(cur_prefix));
926                 if (use_img)
927                         strcat(p, ".img");
928
929                 fd = os_open(fname, O_RDONLY);
930                 if (fd >= 0) {
931                         close(fd);
932                         return 0;
933                 }
934         }
935
936         return -ENOENT;
937 }
938
939 int os_spl_to_uboot(const char *fname)
940 {
941         struct sandbox_state *state = state_get_current();
942
943         /* U-Boot will delete ram buffer after read: "--rm_memory"*/
944         state->ram_buf_rm = true;
945
946         return os_jump_to_file(fname, false);
947 }
948
949 long os_get_time_offset(void)
950 {
951         const char *offset;
952
953         offset = getenv(ENV_TIME_OFFSET);
954         if (offset)
955                 return strtol(offset, NULL, 0);
956         return 0;
957 }
958
959 void os_set_time_offset(long offset)
960 {
961         char buf[21];
962         int ret;
963
964         snprintf(buf, sizeof(buf), "%ld", offset);
965         ret = setenv(ENV_TIME_OFFSET, buf, true);
966         if (ret)
967                 printf("Could not set environment variable %s\n",
968                        ENV_TIME_OFFSET);
969 }
970
971 void os_localtime(struct rtc_time *rt)
972 {
973         time_t t = time(NULL);
974         struct tm *tm;
975
976         tm = localtime(&t);
977         rt->tm_sec = tm->tm_sec;
978         rt->tm_min = tm->tm_min;
979         rt->tm_hour = tm->tm_hour;
980         rt->tm_mday = tm->tm_mday;
981         rt->tm_mon = tm->tm_mon + 1;
982         rt->tm_year = tm->tm_year + 1900;
983         rt->tm_wday = tm->tm_wday;
984         rt->tm_yday = tm->tm_yday;
985         rt->tm_isdst = tm->tm_isdst;
986 }
987
988 void os_abort(void)
989 {
990         abort();
991 }
992
993 int os_mprotect_allow(void *start, size_t len)
994 {
995         int page_size = getpagesize();
996
997         /* Move start to the start of a page, len to the end */
998         start = (void *)(((ulong)start) & ~(page_size - 1));
999         len = (len + page_size * 2) & ~(page_size - 1);
1000
1001         return mprotect(start, len, PROT_READ | PROT_WRITE);
1002 }
1003
1004 void *os_find_text_base(void)
1005 {
1006         char line[500];
1007         void *base = NULL;
1008         int len;
1009         int fd;
1010
1011         /*
1012          * This code assumes that the first line of /proc/self/maps holds
1013          * information about the text, for example:
1014          *
1015          * 5622d9907000-5622d9a55000 r-xp 00000000 08:01 15067168   u-boot
1016          *
1017          * The first hex value is assumed to be the address.
1018          *
1019          * This is tested in Linux 4.15.
1020          */
1021         fd = open("/proc/self/maps", O_RDONLY);
1022         if (fd == -1)
1023                 return NULL;
1024         len = read(fd, line, sizeof(line));
1025         if (len > 0) {
1026                 char *end = memchr(line, '-', len);
1027
1028                 if (end) {
1029                         uintptr_t addr;
1030
1031                         *end = '\0';
1032                         if (sscanf(line, "%zx", &addr) == 1)
1033                                 base = (void *)addr;
1034                 }
1035         }
1036         close(fd);
1037
1038         return base;
1039 }
1040
1041 /**
1042  * os_unblock_signals() - unblock all signals
1043  *
1044  * If we are relaunching the sandbox in a signal handler, we have to unblock
1045  * the respective signal before calling execv(). See signal(7) man-page.
1046  */
1047 static void os_unblock_signals(void)
1048 {
1049         sigset_t sigs;
1050
1051         sigfillset(&sigs);
1052         sigprocmask(SIG_UNBLOCK, &sigs, NULL);
1053 }
1054
1055 void os_relaunch(char *argv[])
1056 {
1057         os_unblock_signals();
1058
1059         execv(argv[0], argv);
1060         os_exit(1);
1061 }
1062
1063
1064 #ifdef CONFIG_FUZZ
1065 static void *fuzzer_thread(void * ptr)
1066 {
1067         char cmd[64];
1068         char *argv[5] = {"./u-boot", "-T", "-c", cmd, NULL};
1069         const char *fuzz_test;
1070
1071         /* Find which test to run from an environment variable. */
1072         fuzz_test = getenv("UBOOT_SB_FUZZ_TEST");
1073         if (!fuzz_test)
1074                 os_abort();
1075
1076         snprintf(cmd, sizeof(cmd), "fuzz %s", fuzz_test);
1077
1078         sandbox_main(4, argv);
1079         os_abort();
1080         return NULL;
1081 }
1082
1083 static bool fuzzer_initialized = false;
1084 static pthread_mutex_t fuzzer_mutex = PTHREAD_MUTEX_INITIALIZER;
1085 static pthread_cond_t fuzzer_cond = PTHREAD_COND_INITIALIZER;
1086 static const uint8_t *fuzzer_data;
1087 static size_t fuzzer_size;
1088
1089 int sandbox_fuzzing_engine_get_input(const uint8_t **data, size_t *size)
1090 {
1091         if (!fuzzer_initialized)
1092                 return -ENOSYS;
1093
1094         /* Tell the main thread we need new inputs then wait for them. */
1095         pthread_mutex_lock(&fuzzer_mutex);
1096         pthread_cond_signal(&fuzzer_cond);
1097         pthread_cond_wait(&fuzzer_cond, &fuzzer_mutex);
1098         *data = fuzzer_data;
1099         *size = fuzzer_size;
1100         pthread_mutex_unlock(&fuzzer_mutex);
1101         return 0;
1102 }
1103
1104 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
1105 {
1106         static pthread_t tid;
1107
1108         pthread_mutex_lock(&fuzzer_mutex);
1109
1110         /* Initialize the sandbox on another thread. */
1111         if (!fuzzer_initialized) {
1112                 fuzzer_initialized = true;
1113                 if (pthread_create(&tid, NULL, fuzzer_thread, NULL))
1114                         os_abort();
1115                 pthread_cond_wait(&fuzzer_cond, &fuzzer_mutex);
1116         }
1117
1118         /* Hand over the input. */
1119         fuzzer_data = data;
1120         fuzzer_size = size;
1121         pthread_cond_signal(&fuzzer_cond);
1122
1123         /* Wait for the inputs to be finished with. */
1124         pthread_cond_wait(&fuzzer_cond, &fuzzer_mutex);
1125         pthread_mutex_unlock(&fuzzer_mutex);
1126
1127         return 0;
1128 }
1129 #else
1130 int main(int argc, char *argv[])
1131 {
1132         return sandbox_main(argc, argv);
1133 }
1134 #endif