misc-common.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555
  1. /*
  2. * Misc. bootloader code (almost) all platforms can use
  3. *
  4. * Author: Johnnie Peters <jpeters@mvista.com>
  5. * Editor: Tom Rini <trini@mvista.com>
  6. *
  7. * Derived from arch/ppc/boot/prep/misc.c
  8. *
  9. * 2000-2001 (c) MontaVista, Software, Inc. This file is licensed under
  10. * the terms of the GNU General Public License version 2. This program
  11. * is licensed "as is" without any warranty of any kind, whether express
  12. * or implied.
  13. */
  14. #include <stdarg.h> /* for va_ bits */
  15. #include <linux/string.h>
  16. #include <linux/zlib.h>
  17. #include "nonstdio.h"
  18. /* If we're on a PReP, assume we have a keyboard controller
  19. * Also note, if we're not PReP, we assume you are a serial
  20. * console - Tom */
  21. #if defined(CONFIG_PPC_PREP) && defined(CONFIG_VGA_CONSOLE)
  22. extern void cursor(int x, int y);
  23. extern void scroll(void);
  24. extern char *vidmem;
  25. extern int lines, cols;
  26. extern int orig_x, orig_y;
  27. extern int keyb_present;
  28. extern int CRT_tstc(void);
  29. extern int CRT_getc(void);
  30. #else
  31. int cursor(int x, int y) {return 0;}
  32. void scroll(void) {}
  33. char vidmem[1];
  34. #define lines 0
  35. #define cols 0
  36. int orig_x = 0;
  37. int orig_y = 0;
  38. #define keyb_present 0
  39. int CRT_tstc(void) {return 0;}
  40. int CRT_getc(void) {return 0;}
  41. #endif
  42. extern char *avail_ram;
  43. extern char *end_avail;
  44. extern char _end[];
  45. void puts(const char *);
  46. void putc(const char c);
  47. void puthex(unsigned long val);
  48. void gunzip(void *, int, unsigned char *, int *);
  49. static int _cvt(unsigned long val, char *buf, long radix, char *digits);
  50. void _vprintk(void(*putc)(const char), const char *fmt0, va_list ap);
  51. unsigned char *ISA_io = NULL;
  52. #if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \
  53. || defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \
  54. || defined(CONFIG_SERIAL_MPSC_CONSOLE) \
  55. || defined(CONFIG_SERIAL_UARTLITE_CONSOLE)
  56. extern unsigned long com_port;
  57. extern int serial_tstc(unsigned long com_port);
  58. extern unsigned char serial_getc(unsigned long com_port);
  59. extern void serial_putc(unsigned long com_port, unsigned char c);
  60. #endif
  61. void pause(void)
  62. {
  63. puts("pause\n");
  64. }
  65. void exit(void)
  66. {
  67. puts("exit\n");
  68. while(1);
  69. }
  70. int tstc(void)
  71. {
  72. #if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \
  73. || defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \
  74. || defined(CONFIG_SERIAL_MPSC_CONSOLE) \
  75. || defined(CONFIG_SERIAL_UARTLITE_CONSOLE)
  76. if(keyb_present)
  77. return (CRT_tstc() || serial_tstc(com_port));
  78. else
  79. return (serial_tstc(com_port));
  80. #else
  81. return CRT_tstc();
  82. #endif
  83. }
  84. int getc(void)
  85. {
  86. while (1) {
  87. #if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \
  88. || defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \
  89. || defined(CONFIG_SERIAL_MPSC_CONSOLE) \
  90. || defined(CONFIG_SERIAL_UARTLITE_CONSOLE)
  91. if (serial_tstc(com_port))
  92. return (serial_getc(com_port));
  93. #endif /* serial console */
  94. if (keyb_present)
  95. if(CRT_tstc())
  96. return (CRT_getc());
  97. }
  98. }
  99. void
  100. putc(const char c)
  101. {
  102. int x,y;
  103. #if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \
  104. || defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \
  105. || defined(CONFIG_SERIAL_MPSC_CONSOLE) \
  106. || defined(CONFIG_SERIAL_UARTLITE_CONSOLE)
  107. serial_putc(com_port, c);
  108. if ( c == '\n' )
  109. serial_putc(com_port, '\r');
  110. #endif /* serial console */
  111. x = orig_x;
  112. y = orig_y;
  113. if ( c == '\n' ) {
  114. x = 0;
  115. if ( ++y >= lines ) {
  116. scroll();
  117. y--;
  118. }
  119. } else if (c == '\r') {
  120. x = 0;
  121. } else if (c == '\b') {
  122. if (x > 0) {
  123. x--;
  124. }
  125. } else {
  126. vidmem [ ( x + cols * y ) * 2 ] = c;
  127. if ( ++x >= cols ) {
  128. x = 0;
  129. if ( ++y >= lines ) {
  130. scroll();
  131. y--;
  132. }
  133. }
  134. }
  135. cursor(x, y);
  136. orig_x = x;
  137. orig_y = y;
  138. }
  139. void puts(const char *s)
  140. {
  141. int x,y;
  142. char c;
  143. x = orig_x;
  144. y = orig_y;
  145. while ( ( c = *s++ ) != '\0' ) {
  146. #if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \
  147. || defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \
  148. || defined(CONFIG_SERIAL_MPSC_CONSOLE) \
  149. || defined(CONFIG_SERIAL_UARTLITE_CONSOLE)
  150. serial_putc(com_port, c);
  151. if ( c == '\n' ) serial_putc(com_port, '\r');
  152. #endif /* serial console */
  153. if ( c == '\n' ) {
  154. x = 0;
  155. if ( ++y >= lines ) {
  156. scroll();
  157. y--;
  158. }
  159. } else if (c == '\b') {
  160. if (x > 0) {
  161. x--;
  162. }
  163. } else {
  164. vidmem [ ( x + cols * y ) * 2 ] = c;
  165. if ( ++x >= cols ) {
  166. x = 0;
  167. if ( ++y >= lines ) {
  168. scroll();
  169. y--;
  170. }
  171. }
  172. }
  173. }
  174. cursor(x, y);
  175. orig_x = x;
  176. orig_y = y;
  177. }
  178. void error(char *x)
  179. {
  180. puts("\n\n");
  181. puts(x);
  182. puts("\n\n -- System halted");
  183. while(1); /* Halt */
  184. }
  185. static void *zalloc(unsigned size)
  186. {
  187. void *p = avail_ram;
  188. size = (size + 7) & -8;
  189. avail_ram += size;
  190. if (avail_ram > end_avail) {
  191. puts("oops... out of memory\n");
  192. pause();
  193. }
  194. return p;
  195. }
  196. #define HEAD_CRC 2
  197. #define EXTRA_FIELD 4
  198. #define ORIG_NAME 8
  199. #define COMMENT 0x10
  200. #define RESERVED 0xe0
  201. void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp)
  202. {
  203. z_stream s;
  204. int r, i, flags;
  205. /* skip header */
  206. i = 10;
  207. flags = src[3];
  208. if (src[2] != Z_DEFLATED || (flags & RESERVED) != 0) {
  209. puts("bad gzipped data\n");
  210. exit();
  211. }
  212. if ((flags & EXTRA_FIELD) != 0)
  213. i = 12 + src[10] + (src[11] << 8);
  214. if ((flags & ORIG_NAME) != 0)
  215. while (src[i++] != 0)
  216. ;
  217. if ((flags & COMMENT) != 0)
  218. while (src[i++] != 0)
  219. ;
  220. if ((flags & HEAD_CRC) != 0)
  221. i += 2;
  222. if (i >= *lenp) {
  223. puts("gunzip: ran out of data in header\n");
  224. exit();
  225. }
  226. /* Initialize ourself. */
  227. s.workspace = zalloc(zlib_inflate_workspacesize());
  228. r = zlib_inflateInit2(&s, -MAX_WBITS);
  229. if (r != Z_OK) {
  230. puts("zlib_inflateInit2 returned "); puthex(r); puts("\n");
  231. exit();
  232. }
  233. s.next_in = src + i;
  234. s.avail_in = *lenp - i;
  235. s.next_out = dst;
  236. s.avail_out = dstlen;
  237. r = zlib_inflate(&s, Z_FINISH);
  238. if (r != Z_OK && r != Z_STREAM_END) {
  239. puts("inflate returned "); puthex(r); puts("\n");
  240. exit();
  241. }
  242. *lenp = s.next_out - (unsigned char *) dst;
  243. zlib_inflateEnd(&s);
  244. }
  245. void
  246. puthex(unsigned long val)
  247. {
  248. unsigned char buf[10];
  249. int i;
  250. for (i = 7; i >= 0; i--)
  251. {
  252. buf[i] = "0123456789ABCDEF"[val & 0x0F];
  253. val >>= 4;
  254. }
  255. buf[8] = '\0';
  256. puts(buf);
  257. }
  258. #define FALSE 0
  259. #define TRUE 1
  260. void
  261. _printk(char const *fmt, ...)
  262. {
  263. va_list ap;
  264. va_start(ap, fmt);
  265. _vprintk(putc, fmt, ap);
  266. va_end(ap);
  267. return;
  268. }
  269. #define is_digit(c) ((c >= '0') && (c <= '9'))
  270. void
  271. _vprintk(void(*putc)(const char), const char *fmt0, va_list ap)
  272. {
  273. char c, sign, *cp = 0;
  274. int left_prec, right_prec, zero_fill, length = 0, pad, pad_on_right;
  275. char buf[32];
  276. long val;
  277. while ((c = *fmt0++))
  278. {
  279. if (c == '%')
  280. {
  281. c = *fmt0++;
  282. left_prec = right_prec = pad_on_right = 0;
  283. if (c == '-')
  284. {
  285. c = *fmt0++;
  286. pad_on_right++;
  287. }
  288. if (c == '0')
  289. {
  290. zero_fill = TRUE;
  291. c = *fmt0++;
  292. } else
  293. {
  294. zero_fill = FALSE;
  295. }
  296. while (is_digit(c))
  297. {
  298. left_prec = (left_prec * 10) + (c - '0');
  299. c = *fmt0++;
  300. }
  301. if (c == '.')
  302. {
  303. c = *fmt0++;
  304. zero_fill++;
  305. while (is_digit(c))
  306. {
  307. right_prec = (right_prec * 10) + (c - '0');
  308. c = *fmt0++;
  309. }
  310. } else
  311. {
  312. right_prec = left_prec;
  313. }
  314. sign = '\0';
  315. switch (c)
  316. {
  317. case 'd':
  318. case 'x':
  319. case 'X':
  320. val = va_arg(ap, long);
  321. switch (c)
  322. {
  323. case 'd':
  324. if (val < 0)
  325. {
  326. sign = '-';
  327. val = -val;
  328. }
  329. length = _cvt(val, buf, 10, "0123456789");
  330. break;
  331. case 'x':
  332. length = _cvt(val, buf, 16, "0123456789abcdef");
  333. break;
  334. case 'X':
  335. length = _cvt(val, buf, 16, "0123456789ABCDEF");
  336. break;
  337. }
  338. cp = buf;
  339. break;
  340. case 's':
  341. cp = va_arg(ap, char *);
  342. length = strlen(cp);
  343. break;
  344. case 'c':
  345. c = va_arg(ap, long /*char*/);
  346. (*putc)(c);
  347. continue;
  348. default:
  349. (*putc)('?');
  350. }
  351. pad = left_prec - length;
  352. if (sign != '\0')
  353. {
  354. pad--;
  355. }
  356. if (zero_fill)
  357. {
  358. c = '0';
  359. if (sign != '\0')
  360. {
  361. (*putc)(sign);
  362. sign = '\0';
  363. }
  364. } else
  365. {
  366. c = ' ';
  367. }
  368. if (!pad_on_right)
  369. {
  370. while (pad-- > 0)
  371. {
  372. (*putc)(c);
  373. }
  374. }
  375. if (sign != '\0')
  376. {
  377. (*putc)(sign);
  378. }
  379. while (length-- > 0)
  380. {
  381. (*putc)(c = *cp++);
  382. if (c == '\n')
  383. {
  384. (*putc)('\r');
  385. }
  386. }
  387. if (pad_on_right)
  388. {
  389. while (pad-- > 0)
  390. {
  391. (*putc)(c);
  392. }
  393. }
  394. } else
  395. {
  396. (*putc)(c);
  397. if (c == '\n')
  398. {
  399. (*putc)('\r');
  400. }
  401. }
  402. }
  403. }
  404. int
  405. _cvt(unsigned long val, char *buf, long radix, char *digits)
  406. {
  407. char temp[80];
  408. char *cp = temp;
  409. int length = 0;
  410. if (val == 0)
  411. { /* Special case */
  412. *cp++ = '0';
  413. } else
  414. while (val)
  415. {
  416. *cp++ = digits[val % radix];
  417. val /= radix;
  418. }
  419. while (cp != temp)
  420. {
  421. *buf++ = *--cp;
  422. length++;
  423. }
  424. *buf = '\0';
  425. return (length);
  426. }
  427. void
  428. _dump_buf_with_offset(unsigned char *p, int s, unsigned char *base)
  429. {
  430. int i, c;
  431. if ((unsigned int)s > (unsigned int)p)
  432. {
  433. s = (unsigned int)s - (unsigned int)p;
  434. }
  435. while (s > 0)
  436. {
  437. if (base)
  438. {
  439. _printk("%06X: ", (int)p - (int)base);
  440. } else
  441. {
  442. _printk("%06X: ", p);
  443. }
  444. for (i = 0; i < 16; i++)
  445. {
  446. if (i < s)
  447. {
  448. _printk("%02X", p[i] & 0xFF);
  449. } else
  450. {
  451. _printk(" ");
  452. }
  453. if ((i % 2) == 1) _printk(" ");
  454. if ((i % 8) == 7) _printk(" ");
  455. }
  456. _printk(" |");
  457. for (i = 0; i < 16; i++)
  458. {
  459. if (i < s)
  460. {
  461. c = p[i] & 0xFF;
  462. if ((c < 0x20) || (c >= 0x7F)) c = '.';
  463. } else
  464. {
  465. c = ' ';
  466. }
  467. _printk("%c", c);
  468. }
  469. _printk("|\n");
  470. s -= 16;
  471. p += 16;
  472. }
  473. }
  474. void
  475. _dump_buf(unsigned char *p, int s)
  476. {
  477. _printk("\n");
  478. _dump_buf_with_offset(p, s, 0);
  479. }
  480. /* Very simple inb/outb routines. We declare ISA_io to be 0 above, and
  481. * then modify it on platforms which need to. We do it like this
  482. * because on some platforms we give inb/outb an exact location, and
  483. * on others it's an offset from a given location. -- Tom
  484. */
  485. void ISA_init(unsigned long base)
  486. {
  487. ISA_io = (unsigned char *)base;
  488. }
  489. void
  490. outb(int port, unsigned char val)
  491. {
  492. /* Ensure I/O operations complete */
  493. __asm__ volatile("eieio");
  494. ISA_io[port] = val;
  495. }
  496. unsigned char
  497. inb(int port)
  498. {
  499. /* Ensure I/O operations complete */
  500. __asm__ volatile("eieio");
  501. return (ISA_io[port]);
  502. }
  503. /*
  504. * Local variables:
  505. * c-indent-level: 8
  506. * c-basic-offset: 8
  507. * tab-width: 8
  508. * End:
  509. */