diff options
author | Heinrich Schuchardt | 2020-10-27 20:29:25 +0100 |
---|---|---|
committer | Simon Glass | 2020-11-05 09:11:30 -0700 |
commit | 329dccc0675b97d8a1ab9debfb610165262f35c6 (patch) | |
tree | 6f7b32ab18a4807d7967853ff137aa009cb59f73 | |
parent | c0b19f25a1a2ba935333899e5dcbe4429851cb18 (diff) |
sandbox: implement reset
Up to now the sandbox would shutdown upon a cold reset request. Instead it
should be reset.
In our coding we use static variables like LIST_HEAD(efi_obj_list). A reset
can occur at any time, e.g. via an UEFI binary calling the reset service.
The only safe way to return to an initial state is to relaunch the U-Boot
binary.
The reset implementation uses execv() to relaunch U-Boot.
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Reviewed-by: Simon Glass <sjg@chromium.org>
-rw-r--r-- | arch/sandbox/cpu/os.c | 6 | ||||
-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 | ||||
-rw-r--r-- | drivers/sysreset/sysreset_sandbox.c | 3 | ||||
-rw-r--r-- | include/os.h | 15 |
6 files changed, 61 insertions, 0 deletions
diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c index 7e474d63644..0d8efd83f62 100644 --- a/arch/sandbox/cpu/os.c +++ b/arch/sandbox/cpu/os.c @@ -822,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 58ada13fba5..a03e5aa0b30 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 34b6fff7e7a..59f37fab0b8 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 798d0030773..73b1897191d 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); diff --git a/drivers/sysreset/sysreset_sandbox.c b/drivers/sysreset/sysreset_sandbox.c index 71cabd19568..7026a48c4b2 100644 --- a/drivers/sysreset/sysreset_sandbox.c +++ b/drivers/sysreset/sysreset_sandbox.c @@ -56,6 +56,9 @@ static int sandbox_sysreset_request(struct udevice *dev, enum sysreset_t type) switch (type) { case SYSRESET_COLD: state->last_sysreset = type; + if (!state->sysreset_allowed[type]) + return -EACCES; + sandbox_reset(); break; case SYSRESET_POWER_OFF: state->last_sysreset = type; diff --git a/include/os.h b/include/os.h index 1874ae674f2..88dfb71c1a6 100644 --- a/include/os.h +++ b/include/os.h @@ -355,4 +355,19 @@ int os_read_file(const char *name, void **bufp, int *sizep); */ void *os_find_text_base(void); +/** + * os_relaunch() - restart the sandbox + * + * This functions is used to implement the cold reboot of the sand box. + * @argv[0] specifies the binary that is started while the calling process + * stops immediately. If the new binary cannot be started, the process is + * terminated and 1 is set as shell return code. + * + * 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. + * + * @argv: NULL terminated list of command line parameters + */ +void os_relaunch(char *argv[]); + #endif |