rebootcmd.c 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. #include "u.h"
  2. #include "../port/lib.h"
  3. #include "mem.h"
  4. #include "dat.h"
  5. #include "fns.h"
  6. #include "../port/error.h"
  7. #include "a.out.h"
  8. static ulong
  9. l2be(long l)
  10. {
  11. uchar *cp;
  12. cp = (uchar*)&l;
  13. return (cp[0]<<24) | (cp[1]<<16) | (cp[2]<<8) | cp[3];
  14. }
  15. static void
  16. readn(Chan *c, void *vp, long n)
  17. {
  18. char *p = vp;
  19. long nn;
  20. while(n > 0) {
  21. nn = devtab[c->type]->read(c, p, n, c->offset);
  22. if(nn == 0)
  23. error(Eshort);
  24. c->offset += nn;
  25. p += nn;
  26. n -= nn;
  27. }
  28. }
  29. static void
  30. setbootcmd(int argc, char *argv[])
  31. {
  32. char *buf, *p, *ep;
  33. int i;
  34. buf = malloc(1024);
  35. if(buf == nil)
  36. error(Enomem);
  37. p = buf;
  38. ep = buf + 1024;
  39. for(i=0; i<argc; i++)
  40. p = seprint(p, ep, "%q ", argv[i]);
  41. *p = 0;
  42. ksetenv("bootcmd", buf, 1);
  43. free(buf);
  44. }
  45. void
  46. rebootcmd(int argc, char *argv[])
  47. {
  48. Chan *c;
  49. Exec exec;
  50. ulong magic, text, rtext, entry, data, size;
  51. uchar *p;
  52. if(argc == 0)
  53. exit(0);
  54. c = namec(argv[0], Aopen, OEXEC, 0);
  55. if(waserror()){
  56. cclose(c);
  57. nexterror();
  58. }
  59. readn(c, &exec, sizeof(Exec));
  60. magic = l2be(exec.magic);
  61. entry = l2be(exec.entry);
  62. text = l2be(exec.text);
  63. data = l2be(exec.data);
  64. if(magic != AOUT_MAGIC)
  65. error(Ebadexec);
  66. /* round text out to page boundary */
  67. rtext = PGROUND(entry+text)-entry;
  68. size = rtext + data;
  69. p = malloc(size);
  70. if(p == nil)
  71. error(Enomem);
  72. if(waserror()){
  73. free(p);
  74. nexterror();
  75. }
  76. memset(p, 0, size);
  77. readn(c, p, text);
  78. readn(c, p + rtext, data);
  79. ksetenv("bootfile", argv[0], 1);
  80. setbootcmd(argc-1, argv+1);
  81. reboot((void*)entry, p, size);
  82. panic("return from reboot!");
  83. }