misc-common.c 9.7 KB

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