diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/Kconfig | 3 | ||||
-rw-r--r-- | arch/sandbox/cpu/eth-raw-os.c | 8 | ||||
-rw-r--r-- | arch/sandbox/cpu/os.c | 16 | ||||
-rw-r--r-- | arch/sandbox/cpu/start.c | 26 | ||||
-rw-r--r-- | arch/sandbox/cpu/state.c | 1 | ||||
-rw-r--r-- | arch/sandbox/include/asm/u-boot-sandbox.h | 10 |
6 files changed, 58 insertions, 6 deletions
diff --git a/arch/Kconfig b/arch/Kconfig index 041e179256..3aa99e08fc 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -92,6 +92,7 @@ config SANDBOX bool "Sandbox" select BOARD_LATE_INIT select BZIP2 + select CMD_POWEROFF select DM select DM_GPIO select DM_I2C @@ -107,7 +108,7 @@ config SANDBOX select PCI_ENDPOINT select SPI select SUPPORT_OF_CONTROL - select SYSRESET_CMD_POWEROFF if CMD_POWEROFF + select SYSRESET_CMD_POWEROFF imply BITREVERSE select BLOBLIST imply CMD_DM diff --git a/arch/sandbox/cpu/eth-raw-os.c b/arch/sandbox/cpu/eth-raw-os.c index da01d1addf..6a8d809756 100644 --- a/arch/sandbox/cpu/eth-raw-os.c +++ b/arch/sandbox/cpu/eth-raw-os.c @@ -53,7 +53,7 @@ int sandbox_eth_raw_os_is_local(const char *ifname) } ret = !!(ifr.ifr_flags & IFF_LOOPBACK); out: - close(fd); + os_close(fd); return ret; } @@ -220,7 +220,7 @@ int sandbox_eth_raw_os_send(void *packet, int length, struct sockaddr_in addr; if (priv->local_bind_sd != -1) - close(priv->local_bind_sd); + os_close(priv->local_bind_sd); /* A normal UDP socket is required to bind */ priv->local_bind_sd = socket(AF_INET, SOCK_DGRAM, 0); @@ -284,11 +284,11 @@ void sandbox_eth_raw_os_stop(struct eth_sandbox_raw_priv *priv) { free(priv->device); priv->device = NULL; - close(priv->sd); + os_close(priv->sd); priv->sd = -1; if (priv->local) { if (priv->local_bind_sd != -1) - close(priv->local_bind_sd); + os_close(priv->local_bind_sd); priv->local_bind_sd = -1; priv->local_bind_udp_port = 0; } diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c index e7ec892bdf..0d8efd83f6 100644 --- a/arch/sandbox/cpu/os.c +++ b/arch/sandbox/cpu/os.c @@ -80,13 +80,21 @@ int os_open(const char *pathname, int os_flags) flags |= O_CREAT; if (os_flags & OS_O_TRUNC) flags |= O_TRUNC; + /* + * During a cold reset execv() is used to relaunch the U-Boot binary. + * We must ensure that all files are closed in this case. + */ + flags |= O_CLOEXEC; return open(pathname, flags, 0777); } int os_close(int fd) { - return close(fd); + /* Do not close the console input */ + if (fd) + return close(fd); + return -1; } int os_unlink(const char *pathname) @@ -814,3 +822,9 @@ void *os_find_text_base(void) return base; } + +void os_relaunch(char *argv[]) +{ + execv(argv[0], argv); + os_exit(1); +} diff --git a/arch/sandbox/cpu/start.c b/arch/sandbox/cpu/start.c index 58ada13fba..a03e5aa0b3 100644 --- a/arch/sandbox/cpu/start.c +++ b/arch/sandbox/cpu/start.c @@ -5,6 +5,7 @@ #include <common.h> #include <command.h> +#include <dm/root.h> #include <errno.h> #include <init.h> #include <os.h> @@ -19,6 +20,8 @@ DECLARE_GLOBAL_DATA_PTR; +static char **os_argv; + /* Compare two options so that they can be sorted into alphabetical order */ static int h_compare_opt(const void *p1, const void *p2) { @@ -403,12 +406,35 @@ void state_show(struct sandbox_state *state) printf("\n"); } +void sandbox_reset(void) +{ + /* Do this here while it still has an effect */ + os_fd_restore(); + if (state_uninit()) + os_exit(2); + + if (dm_uninit()) + os_exit(2); + + /* Restart U-Boot */ + os_relaunch(os_argv); +} + int main(int argc, char *argv[]) { struct sandbox_state *state; gd_t data; int ret; + /* + * Copy argv[] so that we can pass the arguments in the original + * sequence when resetting the sandbox. + */ + os_argv = calloc(argc + 1, sizeof(char *)); + if (!os_argv) + os_exit(1); + memcpy(os_argv, argv, sizeof(char *) * (argc + 1)); + memset(&data, '\0', sizeof(data)); gd = &data; gd->arch.text_base = os_find_text_base(); diff --git a/arch/sandbox/cpu/state.c b/arch/sandbox/cpu/state.c index 34b6fff7e7..59f37fab0b 100644 --- a/arch/sandbox/cpu/state.c +++ b/arch/sandbox/cpu/state.c @@ -358,6 +358,7 @@ void state_reset_for_test(struct sandbox_state *state) /* No reset yet, so mark it as such. Always allow power reset */ state->last_sysreset = SYSRESET_COUNT; state->sysreset_allowed[SYSRESET_POWER_OFF] = true; + state->sysreset_allowed[SYSRESET_COLD] = true; state->allow_memio = false; memset(&state->wdt, '\0', sizeof(state->wdt)); diff --git a/arch/sandbox/include/asm/u-boot-sandbox.h b/arch/sandbox/include/asm/u-boot-sandbox.h index 798d003077..73b1897191 100644 --- a/arch/sandbox/include/asm/u-boot-sandbox.h +++ b/arch/sandbox/include/asm/u-boot-sandbox.h @@ -84,6 +84,16 @@ void sandbox_set_enable_pci_map(int enable); */ int sandbox_read_fdt_from_file(void); +/** + * sandbox_reset() - reset sandbox + * + * This functions implements the cold reboot of the sandbox. It relaunches the + * U-Boot binary with the same command line parameters as the original call. + * The PID of the process stays the same. All file descriptors that have not + * been opened with O_CLOEXEC stay open including stdin, stdout, stderr. + */ +void sandbox_reset(void); + /* Exit sandbox (quit U-Boot) */ void sandbox_exit(void); |