sandbox: Add os_jump_to_image() to run another executable
authorSimon Glass <sjg@chromium.org>
Thu, 27 Feb 2014 20:26:15 +0000 (13:26 -0700)
committerSimon Glass <sjg@chromium.org>
Tue, 18 Mar 2014 02:05:48 +0000 (20:05 -0600)
For some tests it is useful to be able to run U-Boot again but pass on the
same memory contents. Add a function to achieve this.

Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Simon Glass <sjg@chromium.org>
arch/sandbox/cpu/os.c
include/os.h

index 98f565eaaf8cfd2d19fb0c011983bb2198d6dce6..52e1096f36ce18d66623db607acd7f8dfd03d79d 100644 (file)
@@ -443,3 +443,92 @@ 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[4];
+       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;
+       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);
+}
index fa4e39fc74c9eb516fa25096cfdfa70c9bfdc8d7..9b5da5c43d5845fe40af9edd6d637e08aaaff91f 100644 (file)
@@ -253,4 +253,23 @@ int os_write_ram_buf(const char *fname);
  */
 int os_read_ram_buf(const char *fname);
 
+/**
+ * Jump to a new executable image
+ *
+ * This uses exec() to run a new executable image, after putting it in a
+ * temporary file. The same arguments and environment are passed to this
+ * new image, with the addition of:
+ *
+ *     -j <filename>   Specifies the filename the image was written to. The
+ *                     calling image may want to delete this at some point.
+ *     -m <filename>   Specifies the file containing the sandbox memory
+ *                     (ram_buf) from this image, so that the new image can
+ *                     have access to this. It also means that the original
+ *                     memory filename passed to U-Boot will be left intact.
+ *
+ * @param dest         Buffer containing executable image
+ * @param size         Size of buffer
+ */
+int os_jump_to_image(const void *dest, int size);
+
 #endif