misc-common.c 9.7 KB

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