PageRenderTime 44ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/sub.c

https://bitbucket.org/mveety/9boot
C | 426 lines | 361 code | 64 blank | 1 comment | 80 complexity | c846c324b3d1ffb4f9ecc619941fd3ff MD5 | raw file
  1. #include <u.h>
  2. #include <a.out.h>
  3. #include "fns.h"
  4. #include "mem.h"
  5. void
  6. memset(void *dst, int v, int n)
  7. {
  8. uchar *d = dst;
  9. while(n > 0){
  10. *d++ = v;
  11. n--;
  12. }
  13. }
  14. void
  15. memmove(void *dst, void *src, int n)
  16. {
  17. uchar *d = dst;
  18. uchar *s = src;
  19. if(d < s){
  20. while(n-- > 0)
  21. *d++ = *s++;
  22. } else if(d > s){
  23. s += n;
  24. d += n;
  25. while(n-- > 0)
  26. *--d = *--s;
  27. }
  28. }
  29. int
  30. memcmp(void *src, void *dst, int n)
  31. {
  32. uchar *d = dst;
  33. uchar *s = src;
  34. int r = 0;
  35. while(n-- > 0)
  36. if(r = (*d++ - *s++))
  37. break;
  38. return r;
  39. }
  40. int
  41. strlen(char *s)
  42. {
  43. char *p = s;
  44. while(*p)
  45. p++;
  46. return p - s;
  47. }
  48. char*
  49. strchr(char *s, int c)
  50. {
  51. for(; *s; s++)
  52. if(*s == c)
  53. return s;
  54. return 0;
  55. }
  56. void
  57. print(char *s)
  58. {
  59. while(*s)
  60. putc(*s++);
  61. }
  62. int
  63. readn(void *f, void *data, int len)
  64. {
  65. uchar *p, *e;
  66. putc(' ');
  67. p = data;
  68. e = p + len;
  69. while(p < e){
  70. if(((ulong)p & 0xF000) == 0){
  71. putc('\b');
  72. putc(hex[((ulong)p>>16)&0xF]);
  73. }
  74. if((len = read(f, p, e - p)) <= 0)
  75. break;
  76. p += len;
  77. }
  78. putc('\b');
  79. return p - (uchar*)data;
  80. }
  81. static int
  82. readline(void *f, char buf[64])
  83. {
  84. static char white[] = "\t ";
  85. char *p;
  86. p = buf;
  87. do{
  88. if(!f)
  89. putc('>');
  90. for(;;){
  91. if(!f){
  92. putc(*p = getc());
  93. if(*p == '\r')
  94. putc('\n');
  95. else if(*p == '\b' && p > buf){
  96. p--;
  97. continue;
  98. }
  99. }else if(read(f, p, 1) <= 0)
  100. return 0;
  101. if(strchr(crnl, *p))
  102. break;
  103. if(p == buf && strchr(white, *p))
  104. continue; /* whitespace on start of line */
  105. if(p >= buf + 64-1){
  106. if(!f){
  107. putc('\b');
  108. putc(' ');
  109. putc('\b');
  110. }
  111. continue; /* line full do not advance */
  112. }
  113. p++;
  114. }
  115. while(p > buf && strchr(white, p[-1]))
  116. p--;
  117. }while(p == buf);
  118. *p = 0;
  119. return p - buf;
  120. }
  121. static int
  122. timeout(int ms)
  123. {
  124. while(ms > 0){
  125. if(gotc())
  126. return 1;
  127. usleep(100000);
  128. ms -= 100;
  129. }
  130. return 0;
  131. }
  132. #define BOOTLINE ((char*)CONFADDR)
  133. #define BOOTLINELEN 64
  134. #define BOOTARGS ((char*)(CONFADDR+BOOTLINELEN))
  135. #define BOOTARGSLEN (4096-0x200-BOOTLINELEN)
  136. char *confend;
  137. static void apmconf(int);
  138. static void e820conf(void);
  139. static int
  140. delconf(char *s)
  141. {
  142. char *p, *e;
  143. for(p = BOOTARGS; p < confend; p = e){
  144. for(e = p+1; e < confend; e++){
  145. if(*e == '\n'){
  146. e++;
  147. break;
  148. }
  149. }
  150. if(!memcmp(p, s, strlen(s))){
  151. memmove(p, e, confend - e);
  152. confend -= e - p;
  153. *confend = 0;
  154. return 1;
  155. }
  156. }
  157. return 0;
  158. }
  159. char*
  160. configure(void *f, char *path)
  161. {
  162. char line[64], *kern, *s, *p;
  163. int inblock, nowait, n;
  164. Clear:
  165. kern = 0;
  166. nowait = 1;
  167. inblock = 0;
  168. memset(BOOTLINE, 0, BOOTLINELEN);
  169. confend = BOOTARGS;
  170. memset(confend, 0, BOOTARGSLEN);
  171. e820conf();
  172. Loop:
  173. while(readline(f, line) > 0){
  174. if(*line == 0 || strchr("#;=", *line))
  175. continue;
  176. if(*line == '['){
  177. inblock = memcmp("[common]", line, 8);
  178. continue;
  179. }
  180. if(!memcmp("boot", line, 5)){
  181. nowait=1;
  182. break;
  183. }
  184. if(!memcmp("wait", line, 5)){
  185. nowait=0;
  186. continue;
  187. }
  188. if(!memcmp("clear", line, 5)){
  189. if(line[5] == 0){
  190. print("ok");
  191. print(crnl);
  192. goto Clear;
  193. } else if(line[5] == ' ' && delconf(line+6)){
  194. print("ok");
  195. print(crnl);
  196. }
  197. continue;
  198. }
  199. if(inblock || (p = strchr(line, '=')) == nil)
  200. continue;
  201. *p++ = 0;
  202. delconf(line);
  203. if(!memcmp("apm", line, 3)){
  204. apmconf('0' - line[3]);
  205. continue;
  206. }
  207. if(!memcmp("bootfile", line, 8))
  208. memmove(kern = path, p, strlen(p)+1);
  209. s = confend;
  210. memmove(confend, line, n = strlen(line)); confend += n;
  211. *confend++ = '=';
  212. memmove(confend, p, n = strlen(p)); confend += n;
  213. *confend = 0;
  214. print(s); print(crnl);
  215. *confend++ = '\n';
  216. *confend = 0;
  217. }
  218. if(f){
  219. close(f);
  220. f = 0;
  221. if(kern && (nowait==0 || timeout(1000)))
  222. goto Loop;
  223. }
  224. if(!kern){
  225. print("no bootfile\r\n");
  226. goto Loop;
  227. }
  228. while(p = strchr(kern, '!'))
  229. kern = p+1;
  230. return kern;
  231. }
  232. static void
  233. hexfmt(char *s, int i, ulong a)
  234. {
  235. s += i;
  236. while(i > 0){
  237. *--s = hex[a&15];
  238. a >>= 4;
  239. i--;
  240. }
  241. }
  242. static void
  243. addconfx(char *s, int w, ulong v)
  244. {
  245. int n;
  246. n = strlen(s);
  247. memmove(confend, s, n);
  248. hexfmt(confend+n, w, v);
  249. confend += n+w;
  250. *confend = 0;
  251. }
  252. static void
  253. apmconf(int id)
  254. {
  255. uchar *a;
  256. char *s;
  257. a = (uchar*)CONFADDR;
  258. memset(a, 0, 20);
  259. apm(id);
  260. if(memcmp(a, "APM", 4))
  261. return;
  262. s = confend;
  263. addconfx("apm", 1, id);
  264. addconfx("=ax=", 4, *((ushort*)(a+4)));
  265. addconfx(" ebx=", 8, *((ulong*)(a+12)));
  266. addconfx(" cx=", 4, *((ushort*)(a+6)));
  267. addconfx(" dx=", 4, *((ushort*)(a+8)));
  268. addconfx(" di=", 4, *((ushort*)(a+10)));
  269. addconfx(" esi=", 8, *((ulong*)(a+16)));
  270. print(s); print(crnl);
  271. *confend++ = '\n';
  272. *confend = 0;
  273. }
  274. static void
  275. e820conf(void)
  276. {
  277. struct {
  278. uvlong base;
  279. uvlong len;
  280. ulong typ;
  281. ulong ext;
  282. } e;
  283. uvlong v;
  284. ulong bx;
  285. char *s;
  286. bx=0;
  287. s = confend;
  288. do{
  289. bx = e820(bx, &e);
  290. if(e.len != 0 && (e.ext & 3) == 1){
  291. if(confend == s){
  292. /* single entry <= 1MB is useless */
  293. if(bx == 0 && e.typ == 1 && e.len <= 0x100000)
  294. break;
  295. memmove(confend, "*e820=", 6);
  296. confend += 6;
  297. }
  298. addconfx("", 1, e.typ);
  299. v = e.base;
  300. addconfx(" 0x", 8, v>>32);
  301. addconfx("", 8, v&0xffffffff);
  302. v += e.len;
  303. addconfx(" 0x", 8, v>>32);
  304. addconfx("", 8, v&0xffffffff);
  305. *confend++ = ' ';
  306. }
  307. } while(bx);
  308. if(confend == s)
  309. return;
  310. *confend = 0;
  311. print(s); print(crnl);
  312. *confend++ = '\n';
  313. *confend = 0;
  314. }
  315. static ulong
  316. beswal(ulong l)
  317. {
  318. uchar *p = (uchar*)&l;
  319. return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
  320. }
  321. char*
  322. bootkern(void *f)
  323. {
  324. uchar *e, *d, *t;
  325. ulong n;
  326. Exec ex;
  327. while(a20() < 0)
  328. print("a20 enable failed\r\n");
  329. if(readn(f, &ex, sizeof(ex)) != sizeof(ex))
  330. return "bad header";
  331. e = (uchar*)(beswal(ex.entry) & ~0xF0000000UL);
  332. switch(beswal(ex.magic)){
  333. case S_MAGIC:
  334. if(readn(f, e, 8) != 8)
  335. goto Error;
  336. case I_MAGIC:
  337. break;
  338. default:
  339. return "bad magic";
  340. }
  341. t = e;
  342. n = beswal(ex.text);
  343. if(readn(f, t, n) != n)
  344. goto Error;
  345. t += n;
  346. d = (uchar*)PGROUND((ulong)t);
  347. memset(t, 0, d - t);
  348. n = beswal(ex.data);
  349. if(readn(f, d, n) != n)
  350. goto Error;
  351. d += n;
  352. t = (uchar*)PGROUND((ulong)d);
  353. t += PGROUND(beswal(ex.bss));
  354. memset(d, 0, t - d);
  355. close(f);
  356. unload();
  357. print("boot");
  358. print(crnl);
  359. jump(e);
  360. Error:
  361. return "i/o error";
  362. }