]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - arch/sandbox/cpu/os.c
karo: fdt: fix panel-dpi support
[karo-tx-uboot.git] / arch / sandbox / cpu / os.c
index 725b505177d33938cee5cf4ce8308bb13bf11c9a..8a4d719835ccb88c00b5aa6fd1e37cfdc049e8e8 100644 (file)
@@ -24,6 +24,7 @@
 #include <asm/sections.h>
 #include <asm/state.h>
 #include <os.h>
+#include <rtc_def.h>
 
 /* Operating System Interface */
 
@@ -92,6 +93,11 @@ int os_close(int fd)
        return close(fd);
 }
 
+int os_unlink(const char *pathname)
+{
+       return unlink(pathname);
+}
+
 void os_exit(int exit_code)
 {
        exit(exit_code);
@@ -99,21 +105,23 @@ void os_exit(int exit_code)
 
 /* Restore tty state when we exit */
 static struct termios orig_term;
+static bool term_setup;
 
-static void os_fd_restore(void)
+void os_fd_restore(void)
 {
-       tcsetattr(0, TCSANOW, &orig_term);
+       if (term_setup) {
+               tcsetattr(0, TCSANOW, &orig_term);
+               term_setup = false;
+       }
 }
 
 /* Put tty into raw mode so <tab> and <ctrl+c> work */
-void os_tty_raw(int fd)
+void os_tty_raw(int fd, bool allow_sigs)
 {
-       static int setup = 0;
        struct termios term;
 
-       if (setup)
+       if (term_setup)
                return;
-       setup = 1;
 
        /* If not a tty, don't complain */
        if (tcgetattr(fd, &orig_term))
@@ -123,10 +131,11 @@ void os_tty_raw(int fd)
        term.c_iflag = IGNBRK | IGNPAR;
        term.c_oflag = OPOST | ONLCR;
        term.c_cflag = CS8 | CREAD | CLOCAL;
-       term.c_lflag = 0;
+       term.c_lflag = allow_sigs ? ISIG : 0;
        if (tcsetattr(fd, TCSANOW, &term))
                return;
 
+       term_setup = true;
        atexit(os_fd_restore);
 }
 
@@ -143,7 +152,7 @@ void *os_malloc(size_t length)
        return hdr + 1;
 }
 
-void *os_free(void *ptr)
+void os_free(void *ptr)
 {
        struct os_mem_hdr *hdr = ptr;
 
@@ -335,6 +344,7 @@ int os_dirent_ls(const char *dirname, struct os_dirent_node **headp)
                        ret = -ENOMEM;
                        goto done;
                }
+               next->next = NULL;
                strcpy(next->name, entry.d_name);
                switch (entry.d_type) {
                case DT_REG:
@@ -360,6 +370,7 @@ int os_dirent_ls(const char *dirname, struct os_dirent_node **headp)
 
 done:
        closedir(dir);
+       free(fname);
        return ret;
 }
 
@@ -378,7 +389,7 @@ const char *os_dirent_get_typename(enum os_dirent_t type)
        return os_dirent_typename[OS_FILET_UNKNOWN];
 }
 
-ssize_t os_get_filesize(const char *fname)
+int os_get_filesize(const char *fname, loff_t *size)
 {
        struct stat buf;
        int ret;
@@ -386,7 +397,8 @@ ssize_t os_get_filesize(const char *fname)
        ret = stat(fname, &buf);
        if (ret)
                return ret;
-       return buf.st_size;
+       *size = buf.st_size;
+       return 0;
 }
 
 void os_putc(int ch)
@@ -420,11 +432,11 @@ int os_read_ram_buf(const char *fname)
 {
        struct sandbox_state *state = state_get_current();
        int fd, ret;
-       int size;
+       loff_t size;
 
-       size = os_get_filesize(fname);
-       if (size < 0)
-               return -ENOENT;
+       ret = os_get_filesize(fname, &size);
+       if (ret < 0)
+               return ret;
        if (size != state->ram_size)
                return -ENOSPC;
        fd = open(fname, O_RDONLY);
@@ -438,3 +450,110 @@ int os_read_ram_buf(const char *fname)
 
        return 0;
 }
+
+static int make_exec(char *fname, const void *data, int size)
+{
+       int fd;
+
+       strcpy(fname, "/tmp/u-boot.jump.XXXXXX");
+       fd = mkstemp(fname);
+       if (fd < 0)
+               return -ENOENT;
+       if (write(fd, data, size) < 0)
+               return -EIO;
+       close(fd);
+       if (chmod(fname, 0777))
+               return -ENOEXEC;
+
+       return 0;
+}
+
+static int add_args(char ***argvp, const char *add_args[], int count)
+{
+       char **argv;
+       int argc;
+
+       for (argv = *argvp, argc = 0; (*argvp)[argc]; argc++)
+               ;
+
+       argv = malloc((argc + count + 1) * sizeof(char *));
+       if (!argv) {
+               printf("Out of memory for %d argv\n", count);
+               return -ENOMEM;
+       }
+       memcpy(argv, *argvp, argc * sizeof(char *));
+       memcpy(argv + argc, add_args, count * sizeof(char *));
+       argv[argc + count] = NULL;
+
+       *argvp = argv;
+       return 0;
+}
+
+int os_jump_to_image(const void *dest, int size)
+{
+       struct sandbox_state *state = state_get_current();
+       char fname[30], mem_fname[30];
+       int fd, err;
+       const char *extra_args[5];
+       char **argv = state->argv;
+#ifdef DEBUG
+       int argc, i;
+#endif
+
+       err = make_exec(fname, dest, size);
+       if (err)
+               return err;
+
+       strcpy(mem_fname, "/tmp/u-boot.mem.XXXXXX");
+       fd = mkstemp(mem_fname);
+       if (fd < 0)
+               return -ENOENT;
+       close(fd);
+       err = os_write_ram_buf(mem_fname);
+       if (err)
+               return err;
+
+       os_fd_restore();
+
+       extra_args[0] = "-j";
+       extra_args[1] = fname;
+       extra_args[2] = "-m";
+       extra_args[3] = mem_fname;
+       extra_args[4] = "--rm_memory";
+       err = add_args(&argv, extra_args,
+                      sizeof(extra_args) / sizeof(extra_args[0]));
+       if (err)
+               return err;
+
+#ifdef DEBUG
+       for (i = 0; argv[i]; i++)
+               printf("%d %s\n", i, argv[i]);
+#endif
+
+       if (state_uninit())
+               os_exit(2);
+
+       err = execv(fname, argv);
+       free(argv);
+       if (err)
+               return err;
+
+       return unlink(fname);
+}
+
+void os_localtime(struct rtc_time *rt)
+{
+       time_t t = time(NULL);
+       struct tm *tm;
+
+       tm = localtime(&t);
+       rt->tm_sec = tm->tm_sec;
+       rt->tm_min = tm->tm_min;
+       rt->tm_hour = tm->tm_hour;
+       rt->tm_mday = tm->tm_mday;
+       rt->tm_mon = tm->tm_mon + 1;
+       rt->tm_year = tm->tm_year + 1900;
+       rt->tm_wday = tm->tm_wday;
+       rt->tm_yday = tm->tm_yday;
+       rt->tm_isdst = tm->tm_isdst;
+}