boot.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. #include "u.h"
  2. #include "lib.h"
  3. #include "mem.h"
  4. #include "dat.h"
  5. #include "fns.h"
  6. #include "io.h"
  7. static int
  8. addbytes(char **dbuf, char *edbuf, char **sbuf, char *esbuf)
  9. {
  10. int n;
  11. n = edbuf - *dbuf;
  12. if(n <= 0)
  13. return 0;
  14. if(n > esbuf - *sbuf)
  15. n = esbuf - *sbuf;
  16. if(n <= 0)
  17. return -1;
  18. memmove(*dbuf, *sbuf, n);
  19. *sbuf += n;
  20. *dbuf += n;
  21. return edbuf - *dbuf;
  22. }
  23. int
  24. bootpass(Boot *b, void *vbuf, int nbuf)
  25. {
  26. char *buf, *ebuf;
  27. Exec *ep;
  28. ulong entry, data, text, bss;
  29. if(b->state == FAILED)
  30. return FAIL;
  31. if(nbuf == 0)
  32. goto Endofinput;
  33. buf = vbuf;
  34. ebuf = buf+nbuf;
  35. while(addbytes(&b->wp, b->ep, &buf, ebuf) == 0) {
  36. switch(b->state) {
  37. case INITKERNEL:
  38. b->state = READEXEC;
  39. b->bp = (char*)&b->exec;
  40. b->wp = b->bp;
  41. b->ep = b->bp+sizeof(Exec);
  42. break;
  43. case READEXEC:
  44. ep = &b->exec;
  45. if(GLLONG(ep->magic) == I_MAGIC) {
  46. b->state = READTEXT;
  47. b->bp = (char*)PADDR(GLLONG(ep->entry));
  48. b->wp = b->bp;
  49. b->ep = b->wp+GLLONG(ep->text);
  50. print("%lud", GLLONG(ep->text));
  51. break;
  52. }
  53. /* check for gzipped kernel */
  54. if(b->bp[0] == 0x1F && (uchar)b->bp[1] == 0x8B && b->bp[2] == 0x08) {
  55. b->state = READGZIP;
  56. b->bp = (char*)malloc(1440*1024);
  57. b->wp = b->bp;
  58. b->ep = b->wp + 1440*1024;
  59. memmove(b->bp, &b->exec, sizeof(Exec));
  60. b->wp += sizeof(Exec);
  61. print("gz...");
  62. break;
  63. }
  64. print("bad kernel format\n");
  65. b->state = FAILED;
  66. return FAIL;
  67. case READTEXT:
  68. ep = &b->exec;
  69. b->state = READDATA;
  70. b->bp = (char*)PGROUND(GLLONG(ep->entry)+GLLONG(ep->text));
  71. b->wp = b->bp;
  72. b->ep = b->wp + GLLONG(ep->data);
  73. print("+%ld", GLLONG(ep->data));
  74. break;
  75. case READDATA:
  76. ep = &b->exec;
  77. bss = GLLONG(ep->bss);
  78. print("+%ld=%ld\n",
  79. bss, GLLONG(ep->text)+GLLONG(ep->data)+bss);
  80. b->state = TRYBOOT;
  81. return ENOUGH;
  82. case TRYBOOT:
  83. case READGZIP:
  84. return ENOUGH;
  85. case READ9LOAD:
  86. case INIT9LOAD:
  87. panic("9load");
  88. default:
  89. panic("bootstate");
  90. }
  91. }
  92. return MORE;
  93. Endofinput:
  94. /* end of input */
  95. switch(b->state) {
  96. case INITKERNEL:
  97. case READEXEC:
  98. case READDATA:
  99. case READTEXT:
  100. print("premature EOF\n");
  101. b->state = FAILED;
  102. return FAIL;
  103. case TRYBOOT:
  104. entry = GLLONG(b->exec.entry);
  105. print("entry: 0x%lux\n", entry);
  106. warp9(PADDR(entry));
  107. b->state = FAILED;
  108. return FAIL;
  109. case READGZIP:
  110. ep = &b->exec;
  111. if(b->bp[0] != 0x1F || (uchar)b->bp[1] != 0x8B || b->bp[2] != 0x08)
  112. print("lost magic\n");
  113. print("%ld => ", b->wp - b->bp);
  114. if(gunzip((uchar*)ep, sizeof(*ep), (uchar*)b->bp, b->wp - b->bp) < sizeof(*ep)) {
  115. print("badly compressed kernel\n");
  116. return FAIL;
  117. }
  118. entry = GLLONG(ep->entry);
  119. text = GLLONG(ep->text);
  120. data = GLLONG(ep->data);
  121. bss = GLLONG(ep->bss);
  122. print("%lud+%lud+%lud=%lud\n", text, data, bss, text+data+bss);
  123. if(gunzip((uchar*)PADDR(entry)-sizeof(Exec), sizeof(Exec)+text+data,
  124. (uchar*)b->bp, b->wp-b->bp) < sizeof(Exec)+text+data) {
  125. print("error uncompressing kernel\n");
  126. return FAIL;
  127. }
  128. /* relocate data to start at page boundary */
  129. memmove((void*)PGROUND(entry+text), (void*)(entry+text), data);
  130. print("entry: %lux\n", entry);
  131. warp9(PADDR(entry));
  132. b->state = FAILED;
  133. return FAIL;
  134. case INIT9LOAD:
  135. case READ9LOAD:
  136. panic("end 9load");
  137. default:
  138. panic("bootdone");
  139. }
  140. b->state = FAILED;
  141. return FAIL;
  142. }