X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=arch%2Fsandbox%2Fcpu%2Fos.c;h=8a4d719835ccb88c00b5aa6fd1e37cfdc049e8e8;hb=c1924d85af4a07dc70aef1ef95c48b54a136733f;hp=d07540776cc6a8d32fb58a18e752c738c761a06d;hpb=76b40ab41eff1f402ee52ba768b09daad293b9bb;p=u-boot diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c index d07540776c..8a4d719835 100644 --- a/arch/sandbox/cpu/os.c +++ b/arch/sandbox/cpu/os.c @@ -1,22 +1,6 @@ /* * Copyright (c) 2011 The Chromium OS Authors. - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA + * SPDX-License-Identifier: GPL-2.0+ */ #include @@ -24,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -39,9 +24,14 @@ #include #include #include +#include /* Operating System Interface */ +struct os_mem_hdr { + size_t length; /* number of bytes in the block */ +}; + ssize_t os_read(int fd, void *buf, size_t count) { return read(fd, buf, count); @@ -103,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); @@ -110,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 and 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)) @@ -134,17 +131,55 @@ 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); } void *os_malloc(size_t length) { - return mmap(NULL, length, PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + struct os_mem_hdr *hdr; + + hdr = mmap(NULL, length + sizeof(*hdr), PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (hdr == MAP_FAILED) + return NULL; + hdr->length = length; + + return hdr + 1; +} + +void os_free(void *ptr) +{ + struct os_mem_hdr *hdr = ptr; + + hdr--; + if (ptr) + munmap(hdr, hdr->length + sizeof(*hdr)); +} + +void *os_realloc(void *ptr, size_t length) +{ + struct os_mem_hdr *hdr = ptr; + void *buf = NULL; + + hdr--; + if (length != 0) { + buf = os_malloc(length); + if (!buf) + return buf; + if (ptr) { + if (length > hdr->length) + length = hdr->length; + memcpy(buf, ptr, length); + } + } + os_free(ptr); + + return buf; } void os_usleep(unsigned long usec) @@ -152,7 +187,7 @@ void os_usleep(unsigned long usec) usleep(usec); } -u64 os_get_nsec(void) +uint64_t __attribute__((no_instrument_function)) os_get_nsec(void) { #if defined(CLOCK_MONOTONIC) && defined(_POSIX_MONOTONIC_CLOCK) struct timespec tp; @@ -176,7 +211,7 @@ static struct option *long_opts; int os_parse_args(struct sandbox_state *state, int argc, char *argv[]) { - struct sb_cmdline_option **sb_opt = __u_boot_sandbox_option_start; + struct sandbox_cmdline_option **sb_opt = __u_boot_sandbox_option_start; size_t num_options = __u_boot_sandbox_option_count(); size_t i; @@ -309,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: @@ -334,6 +370,7 @@ int os_dirent_ls(const char *dirname, struct os_dirent_node **headp) done: closedir(dir); + free(fname); return ret; } @@ -352,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; @@ -360,5 +397,163 @@ 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) +{ + 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(); + int fd, ret; + + fd = open(fname, O_CREAT | O_WRONLY, 0777); + if (fd < 0) + return -ENOENT; + ret = write(fd, state->ram_buf, state->ram_size); + close(fd); + if (ret != state->ram_size) + return -EIO; + + return 0; +} + +int os_read_ram_buf(const char *fname) +{ + struct sandbox_state *state = state_get_current(); + int fd, ret; + loff_t size; + + ret = os_get_filesize(fname, &size); + if (ret < 0) + return ret; + if (size != state->ram_size) + return -ENOSPC; + fd = open(fname, O_RDONLY); + if (fd < 0) + return -ENOENT; + + ret = read(fd, state->ram_buf, state->ram_size); + close(fd); + if (ret != state->ram_size) + return -EIO; + + 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; }