Commit 47f5fcfb4169a8ff6e8c81738b77f8572f972e75

Authored by Simon Glass
1 parent b2a668b523

sandbox: Add os_jump_to_image() to run another executable

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>

Showing 2 changed files with 108 additions and 0 deletions Side-by-side Diff

arch/sandbox/cpu/os.c
... ... @@ -443,4 +443,93 @@
443 443  
444 444 return 0;
445 445 }
  446 +
  447 +static int make_exec(char *fname, const void *data, int size)
  448 +{
  449 + int fd;
  450 +
  451 + strcpy(fname, "/tmp/u-boot.jump.XXXXXX");
  452 + fd = mkstemp(fname);
  453 + if (fd < 0)
  454 + return -ENOENT;
  455 + if (write(fd, data, size) < 0)
  456 + return -EIO;
  457 + close(fd);
  458 + if (chmod(fname, 0777))
  459 + return -ENOEXEC;
  460 +
  461 + return 0;
  462 +}
  463 +
  464 +static int add_args(char ***argvp, const char *add_args[], int count)
  465 +{
  466 + char **argv;
  467 + int argc;
  468 +
  469 + for (argv = *argvp, argc = 0; (*argvp)[argc]; argc++)
  470 + ;
  471 +
  472 + argv = malloc((argc + count + 1) * sizeof(char *));
  473 + if (!argv) {
  474 + printf("Out of memory for %d argv\n", count);
  475 + return -ENOMEM;
  476 + }
  477 + memcpy(argv, *argvp, argc * sizeof(char *));
  478 + memcpy(argv + argc, add_args, count * sizeof(char *));
  479 + argv[argc + count] = NULL;
  480 +
  481 + *argvp = argv;
  482 + return 0;
  483 +}
  484 +
  485 +int os_jump_to_image(const void *dest, int size)
  486 +{
  487 + struct sandbox_state *state = state_get_current();
  488 + char fname[30], mem_fname[30];
  489 + int fd, err;
  490 + const char *extra_args[4];
  491 + char **argv = state->argv;
  492 +#ifdef DEBUG
  493 + int argc, i;
  494 +#endif
  495 +
  496 + err = make_exec(fname, dest, size);
  497 + if (err)
  498 + return err;
  499 +
  500 + strcpy(mem_fname, "/tmp/u-boot.mem.XXXXXX");
  501 + fd = mkstemp(mem_fname);
  502 + if (fd < 0)
  503 + return -ENOENT;
  504 + close(fd);
  505 + err = os_write_ram_buf(mem_fname);
  506 + if (err)
  507 + return err;
  508 +
  509 + os_fd_restore();
  510 +
  511 + extra_args[0] = "-j";
  512 + extra_args[1] = fname;
  513 + extra_args[2] = "-m";
  514 + extra_args[3] = mem_fname;
  515 + err = add_args(&argv, extra_args,
  516 + sizeof(extra_args) / sizeof(extra_args[0]));
  517 + if (err)
  518 + return err;
  519 +
  520 +#ifdef DEBUG
  521 + for (i = 0; argv[i]; i++)
  522 + printf("%d %s\n", i, argv[i]);
  523 +#endif
  524 +
  525 + if (state_uninit())
  526 + os_exit(2);
  527 +
  528 + err = execv(fname, argv);
  529 + free(argv);
  530 + if (err)
  531 + return err;
  532 +
  533 + return unlink(fname);
  534 +}
... ... @@ -253,5 +253,24 @@
253 253 */
254 254 int os_read_ram_buf(const char *fname);
255 255  
  256 +/**
  257 + * Jump to a new executable image
  258 + *
  259 + * This uses exec() to run a new executable image, after putting it in a
  260 + * temporary file. The same arguments and environment are passed to this
  261 + * new image, with the addition of:
  262 + *
  263 + * -j <filename> Specifies the filename the image was written to. The
  264 + * calling image may want to delete this at some point.
  265 + * -m <filename> Specifies the file containing the sandbox memory
  266 + * (ram_buf) from this image, so that the new image can
  267 + * have access to this. It also means that the original
  268 + * memory filename passed to U-Boot will be left intact.
  269 + *
  270 + * @param dest Buffer containing executable image
  271 + * @param size Size of buffer
  272 + */
  273 +int os_jump_to_image(const void *dest, int size);
  274 +
256 275 #endif