rebootcmd.c 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include "u.h"
  10. #include "../port/lib.h"
  11. #include "mem.h"
  12. #include "dat.h"
  13. #include "fns.h"
  14. #include "../port/error.h"
  15. #include <a.out.h>
  16. static uint32_t
  17. l2be(int32_t l)
  18. {
  19. uint8_t *cp;
  20. cp = (uint8_t*)&l;
  21. return (cp[0]<<24) | (cp[1]<<16) | (cp[2]<<8) | cp[3];
  22. }
  23. static void
  24. readn(Chan *c, void *vp, int32_t n)
  25. {
  26. char *p;
  27. int32_t nn;
  28. p = vp;
  29. while(n > 0) {
  30. nn = c->dev->read(c, p, n, c->offset);
  31. if(nn == 0)
  32. error(Eshort);
  33. c->offset += nn;
  34. p += nn;
  35. n -= nn;
  36. }
  37. }
  38. static void
  39. setbootcmd(int argc, char *argv[])
  40. {
  41. char *buf, *p, *ep;
  42. int i;
  43. buf = malloc(1024);
  44. if(buf == nil)
  45. error(Enomem);
  46. p = buf;
  47. ep = buf + 1024;
  48. for(i=0; i<argc; i++)
  49. p = seprint(p, ep, "%q ", argv[i]);
  50. *p = 0;
  51. ksetenv("bootcmd", buf, 1);
  52. free(buf);
  53. }
  54. void
  55. rebootcmd(int argc, char *argv[])
  56. {
  57. Chan *c;
  58. Exec exec;
  59. uint32_t magic, text, rtext, entry, data, size;
  60. uint8_t *p;
  61. if(argc == 0)
  62. exit(0);
  63. c = namec(argv[0], Aopen, OEXEC, 0);
  64. if(waserror()){
  65. cclose(c);
  66. nexterror();
  67. }
  68. readn(c, &exec, sizeof(Exec));
  69. magic = l2be(exec.magic);
  70. entry = l2be(exec.entry);
  71. text = l2be(exec.text);
  72. data = l2be(exec.data);
  73. if(magic != AOUT_MAGIC)
  74. error(Ebadexec);
  75. /* round text out to page boundary */
  76. rtext = BIGPGROUND(entry+text)-entry;
  77. size = rtext + data;
  78. p = malloc(size);
  79. if(p == nil)
  80. error(Enomem);
  81. if(waserror()){
  82. free(p);
  83. nexterror();
  84. }
  85. memset(p, 0, size);
  86. readn(c, p, text);
  87. readn(c, p + rtext, data);
  88. ksetenv("bootfile", argv[0], 1);
  89. setbootcmd(argc-1, argv+1);
  90. reboot((void*)entry, p, size);
  91. panic("return from reboot!");
  92. }