Merge tag 'dm-9oct18' of git://git.denx.de/u-boot-dm
[platform/kernel/u-boot.git] / arch / sandbox / cpu / os.c
index c524957..07e4647 100644 (file)
@@ -1,12 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 2011 The Chromium OS Authors.
- * SPDX-License-Identifier:    GPL-2.0+
  */
 
 #include <dirent.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <getopt.h>
+#include <setjmp.h>
 #include <stdio.h>
 #include <stdint.h>
 #include <stdlib.h>
@@ -37,14 +38,6 @@ ssize_t os_read(int fd, void *buf, size_t count)
        return read(fd, buf, count);
 }
 
-ssize_t os_read_no_block(int fd, void *buf, size_t count)
-{
-       const int flags = fcntl(fd, F_GETFL, 0);
-
-       fcntl(fd, F_SETFL, flags | O_NONBLOCK);
-       return os_read(fd, buf, count);
-}
-
 ssize_t os_write(int fd, const void *buf, size_t count)
 {
        return write(fd, buf, count);
@@ -84,6 +77,8 @@ int os_open(const char *pathname, int os_flags)
 
        if (os_flags & OS_O_CREAT)
                flags |= O_CREAT;
+       if (os_flags & OS_O_TRUNC)
+               flags |= O_TRUNC;
 
        return open(pathname, flags, 0777);
 }
@@ -103,14 +98,41 @@ void os_exit(int exit_code)
        exit(exit_code);
 }
 
+int os_write_file(const char *name, const void *buf, int size)
+{
+       char fname[256];
+       int fd;
+
+       fd = os_open(fname, OS_O_WRONLY | OS_O_CREAT | OS_O_TRUNC);
+       if (fd < 0) {
+               printf("Cannot open file '%s'\n", fname);
+               return -EIO;
+       }
+       if (os_write(fd, buf, size) != size) {
+               printf("Cannot write to file '%s'\n", fname);
+               return -EIO;
+       }
+       os_close(fd);
+       printf("Write '%s', size %#x (%d)\n", name, size, size);
+
+       return 0;
+}
+
 /* Restore tty state when we exit */
 static struct termios orig_term;
 static bool term_setup;
+static bool term_nonblock;
 
 void os_fd_restore(void)
 {
        if (term_setup) {
+               int flags;
+
                tcsetattr(0, TCSANOW, &orig_term);
+               if (term_nonblock) {
+                       flags = fcntl(0, F_GETFL, 0);
+                       fcntl(0, F_SETFL, flags & ~O_NONBLOCK);
+               }
                term_setup = false;
        }
 }
@@ -119,6 +141,7 @@ void os_fd_restore(void)
 void os_tty_raw(int fd, bool allow_sigs)
 {
        struct termios term;
+       int flags;
 
        if (term_setup)
                return;
@@ -135,6 +158,13 @@ void os_tty_raw(int fd, bool allow_sigs)
        if (tcsetattr(fd, TCSANOW, &term))
                return;
 
+       flags = fcntl(fd, F_GETFL, 0);
+       if (!(flags & O_NONBLOCK)) {
+               if (fcntl(fd, F_SETFL, flags | O_NONBLOCK))
+                       return;
+               term_nonblock = true;
+       }
+
        term_setup = true;
        atexit(os_fd_restore);
 }
@@ -142,14 +172,16 @@ void os_tty_raw(int fd, bool allow_sigs)
 void *os_malloc(size_t length)
 {
        struct os_mem_hdr *hdr;
+       int page_size = getpagesize();
 
-       hdr = mmap(NULL, length + sizeof(*hdr), PROT_READ | PROT_WRITE,
+       hdr = mmap(NULL, length + page_size,
+                  PROT_READ | PROT_WRITE | PROT_EXEC,
                   MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
        if (hdr == MAP_FAILED)
                return NULL;
        hdr->length = length;
 
-       return hdr + 1;
+       return (void *)hdr + page_size;
 }
 
 void os_free(void *ptr)
@@ -421,6 +453,17 @@ int os_get_filesize(const char *fname, loff_t *size)
        return 0;
 }
 
+void os_putc(int ch)
+{
+       putchar(ch);
+}
+
+void os_puts(const char *str)
+{
+       while (*str)
+               os_putc(*str++);
+}
+
 int os_write_ram_buf(const char *fname)
 {
        struct sandbox_state *state = state_get_current();
@@ -555,15 +598,40 @@ int os_find_u_boot(char *fname, int maxlen)
        struct sandbox_state *state = state_get_current();
        const char *progname = state->argv[0];
        int len = strlen(progname);
+       const char *suffix;
        char *p;
        int fd;
 
        if (len >= maxlen || len < 4)
                return -ENOSPC;
 
-       /* Look for 'u-boot' in the same directory as 'u-boot-spl' */
        strcpy(fname, progname);
-       if (!strcmp(fname + len - 4, "-spl")) {
+       suffix = fname + len - 4;
+
+       /* If we are TPL, boot to SPL */
+       if (!strcmp(suffix, "-tpl")) {
+               fname[len - 3] = 's';
+               fd = os_open(fname, O_RDONLY);
+               if (fd >= 0) {
+                       close(fd);
+                       return 0;
+               }
+
+               /* Look for 'u-boot-tpl' in the tpl/ directory */
+               p = strstr(fname, "/tpl/");
+               if (p) {
+                       p[1] = 's';
+                       fd = os_open(fname, O_RDONLY);
+                       if (fd >= 0) {
+                               close(fd);
+                               return 0;
+                       }
+               }
+               return -ENOENT;
+       }
+
+       /* Look for 'u-boot' in the same directory as 'u-boot-spl' */
+       if (!strcmp(suffix, "-spl")) {
                fname[len - 4] = '\0';
                fd = os_open(fname, O_RDONLY);
                if (fd >= 0) {
@@ -617,3 +685,19 @@ void os_localtime(struct rtc_time *rt)
        rt->tm_yday = tm->tm_yday;
        rt->tm_isdst = tm->tm_isdst;
 }
+
+void os_abort(void)
+{
+       abort();
+}
+
+int os_mprotect_allow(void *start, size_t len)
+{
+       int page_size = getpagesize();
+
+       /* Move start to the start of a page, len to the end */
+       start = (void *)(((ulong)start) & ~(page_size - 1));
+       len = (len + page_size * 2) & ~(page_size - 1);
+
+       return mprotect(start, len, PROT_READ | PROT_WRITE);
+}