misc.c 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  1. /* MN10300 Miscellaneous helper routines for kernel decompressor
  2. *
  3. * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
  4. * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
  5. * Modified by David Howells (dhowells@redhat.com)
  6. * - Derived from arch/x86/boot/compressed/misc_32.c
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public Licence
  10. * as published by the Free Software Foundation; either version
  11. * 2 of the Licence, or (at your option) any later version.
  12. */
  13. #include <linux/compiler.h>
  14. #include <asm/serial-regs.h>
  15. #include "misc.h"
  16. #ifndef CONFIG_GDBSTUB_ON_TTYSx
  17. /* display 'Uncompressing Linux... ' messages on ttyS0 or ttyS1 */
  18. #if 1 /* ttyS0 */
  19. #define CYG_DEV_BASE 0xA6FB0000
  20. #else /* ttyS1 */
  21. #define CYG_DEV_BASE 0xA6FC0000
  22. #endif
  23. #define CYG_DEV_THR (*((volatile __u8*)(CYG_DEV_BASE + 0x00)))
  24. #define CYG_DEV_MCR (*((volatile __u8*)(CYG_DEV_BASE + 0x10)))
  25. #define SIO_MCR_DTR 0x01
  26. #define SIO_MCR_RTS 0x02
  27. #define CYG_DEV_LSR (*((volatile __u8*)(CYG_DEV_BASE + 0x14)))
  28. #define SIO_LSR_THRE 0x20 /* transmitter holding register empty */
  29. #define SIO_LSR_TEMT 0x40 /* transmitter register empty */
  30. #define CYG_DEV_MSR (*((volatile __u8*)(CYG_DEV_BASE + 0x18)))
  31. #define SIO_MSR_CTS 0x10 /* clear to send */
  32. #define SIO_MSR_DSR 0x20 /* data set ready */
  33. #define LSR_WAIT_FOR(STATE) \
  34. do { while (!(CYG_DEV_LSR & SIO_LSR_##STATE)) {} } while (0)
  35. #define FLOWCTL_QUERY(LINE) \
  36. ({ CYG_DEV_MSR & SIO_MSR_##LINE; })
  37. #define FLOWCTL_WAIT_FOR(LINE) \
  38. do { while (!(CYG_DEV_MSR & SIO_MSR_##LINE)) {} } while (0)
  39. #define FLOWCTL_CLEAR(LINE) \
  40. do { CYG_DEV_MCR &= ~SIO_MCR_##LINE; } while (0)
  41. #define FLOWCTL_SET(LINE) \
  42. do { CYG_DEV_MCR |= SIO_MCR_##LINE; } while (0)
  43. #endif
  44. /*
  45. * gzip declarations
  46. */
  47. #define OF(args) args
  48. #define STATIC static
  49. #undef memset
  50. #undef memcpy
  51. static inline void *memset(const void *s, int c, size_t n)
  52. {
  53. int i;
  54. char *ss = (char *) s;
  55. for (i = 0; i < n; i++)
  56. ss[i] = c;
  57. return (void *)s;
  58. }
  59. #define memzero(s, n) memset((s), 0, (n))
  60. static inline void *memcpy(void *__dest, const void *__src, size_t __n)
  61. {
  62. int i;
  63. const char *s = __src;
  64. char *d = __dest;
  65. for (i = 0; i < __n; i++)
  66. d[i] = s[i];
  67. return __dest;
  68. }
  69. typedef unsigned char uch;
  70. typedef unsigned short ush;
  71. typedef unsigned long ulg;
  72. #define WSIZE 0x8000 /* Window size must be at least 32k, and a power of
  73. * two */
  74. static uch *inbuf; /* input buffer */
  75. static uch window[WSIZE]; /* sliding window buffer */
  76. static unsigned insize; /* valid bytes in inbuf */
  77. static unsigned inptr; /* index of next byte to be processed in inbuf */
  78. static unsigned outcnt; /* bytes in output buffer */
  79. /* gzip flag byte */
  80. #define ASCII_FLAG 0x01 /* bit 0 set: file probably ASCII text */
  81. #define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
  82. #define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
  83. #define ORIG_NAME 0x08 /* bit 3 set: original file name present */
  84. #define COMMENT 0x10 /* bit 4 set: file comment present */
  85. #define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */
  86. #define RESERVED 0xC0 /* bit 6,7: reserved */
  87. /* Diagnostic functions */
  88. #ifdef DEBUG
  89. # define Assert(cond, msg) { if (!(cond)) error(msg); }
  90. # define Trace(x) fprintf x
  91. # define Tracev(x) { if (verbose) fprintf x ; }
  92. # define Tracevv(x) { if (verbose > 1) fprintf x ; }
  93. # define Tracec(c, x) { if (verbose && (c)) fprintf x ; }
  94. # define Tracecv(c, x) { if (verbose > 1 && (c)) fprintf x ; }
  95. #else
  96. # define Assert(cond, msg)
  97. # define Trace(x)
  98. # define Tracev(x)
  99. # define Tracevv(x)
  100. # define Tracec(c, x)
  101. # define Tracecv(c, x)
  102. #endif
  103. static int fill_inbuf(void);
  104. static void flush_window(void);
  105. static void error(const char *) __attribute__((noreturn));
  106. static void kputs(const char *);
  107. static inline unsigned char get_byte(void)
  108. {
  109. unsigned char ch = inptr < insize ? inbuf[inptr++] : fill_inbuf();
  110. #if 0
  111. char hex[3];
  112. hex[0] = ((ch & 0x0f) > 9) ?
  113. ((ch & 0x0f) + 'A' - 0xa) : ((ch & 0x0f) + '0');
  114. hex[1] = ((ch >> 4) > 9) ?
  115. ((ch >> 4) + 'A' - 0xa) : ((ch >> 4) + '0');
  116. hex[2] = 0;
  117. kputs(hex);
  118. #endif
  119. return ch;
  120. }
  121. /*
  122. * This is set up by the setup-routine at boot-time
  123. */
  124. #define EXT_MEM_K (*(unsigned short *)0x90002)
  125. #ifndef STANDARD_MEMORY_BIOS_CALL
  126. #define ALT_MEM_K (*(unsigned long *) 0x901e0)
  127. #endif
  128. #define SCREEN_INFO (*(struct screen_info *)0x90000)
  129. static long bytes_out;
  130. static uch *output_data;
  131. static unsigned long output_ptr;
  132. static void *malloc(int size);
  133. static inline void free(void *where)
  134. { /* Don't care */
  135. }
  136. static unsigned long free_mem_ptr = (unsigned long) &end;
  137. static unsigned long free_mem_end_ptr = (unsigned long) &end + 0x90000;
  138. static inline void gzip_mark(void **ptr)
  139. {
  140. kputs(".");
  141. *ptr = (void *) free_mem_ptr;
  142. }
  143. static inline void gzip_release(void **ptr)
  144. {
  145. free_mem_ptr = (unsigned long) *ptr;
  146. }
  147. #define INPLACE_MOVE_ROUTINE 0x1000
  148. #define LOW_BUFFER_START 0x2000
  149. #define LOW_BUFFER_END 0x90000
  150. #define LOW_BUFFER_SIZE (LOW_BUFFER_END - LOW_BUFFER_START)
  151. #define HEAP_SIZE 0x3000
  152. static int high_loaded;
  153. static uch *high_buffer_start /* = (uch *)(((ulg)&end) + HEAP_SIZE)*/;
  154. static char *vidmem = (char *)0xb8000;
  155. static int lines, cols;
  156. #include "../../../../lib/inflate.c"
  157. static void *malloc(int size)
  158. {
  159. void *p;
  160. if (size < 0)
  161. error("Malloc error\n");
  162. if (!free_mem_ptr)
  163. error("Memory error\n");
  164. free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */
  165. p = (void *) free_mem_ptr;
  166. free_mem_ptr += size;
  167. if (free_mem_ptr >= free_mem_end_ptr)
  168. error("\nOut of memory\n");
  169. return p;
  170. }
  171. static inline void scroll(void)
  172. {
  173. int i;
  174. memcpy(vidmem, vidmem + cols * 2, (lines - 1) * cols * 2);
  175. for (i = (lines - 1) * cols * 2; i < lines * cols * 2; i += 2)
  176. vidmem[i] = ' ';
  177. }
  178. static inline void kputchar(unsigned char ch)
  179. {
  180. #ifdef CONFIG_MN10300_UNIT_ASB2305
  181. while (SC0STR & SC01STR_TBF)
  182. continue;
  183. if (ch == 0x0a) {
  184. SC0TXB = 0x0d;
  185. while (SC0STR & SC01STR_TBF)
  186. continue;
  187. }
  188. SC0TXB = ch;
  189. #else
  190. while (SC1STR & SC01STR_TBF)
  191. continue;
  192. if (ch == 0x0a) {
  193. SC1TXB = 0x0d;
  194. while (SC1STR & SC01STR_TBF)
  195. continue;
  196. }
  197. SC1TXB = ch;
  198. #endif
  199. }
  200. static void kputs(const char *s)
  201. {
  202. #ifdef CONFIG_DEBUG_DECOMPRESS_KERNEL
  203. #ifndef CONFIG_GDBSTUB_ON_TTYSx
  204. char ch;
  205. FLOWCTL_SET(DTR);
  206. while (*s) {
  207. LSR_WAIT_FOR(THRE);
  208. ch = *s++;
  209. if (ch == 0x0a) {
  210. CYG_DEV_THR = 0x0d;
  211. LSR_WAIT_FOR(THRE);
  212. }
  213. CYG_DEV_THR = ch;
  214. }
  215. FLOWCTL_CLEAR(DTR);
  216. #else
  217. for (; *s; s++)
  218. kputchar(*s);
  219. #endif
  220. #endif /* CONFIG_DEBUG_DECOMPRESS_KERNEL */
  221. }
  222. /* ===========================================================================
  223. * Fill the input buffer. This is called only when the buffer is empty
  224. * and at least one byte is really needed.
  225. */
  226. static int fill_inbuf()
  227. {
  228. if (insize != 0)
  229. error("ran out of input data\n");
  230. inbuf = input_data;
  231. insize = input_len;
  232. inptr = 1;
  233. return inbuf[0];
  234. }
  235. /* ===========================================================================
  236. * Write the output window window[0..outcnt-1] and update crc and bytes_out.
  237. * (Used for the decompressed data only.)
  238. */
  239. static void flush_window_low(void)
  240. {
  241. ulg c = crc; /* temporary variable */
  242. unsigned n;
  243. uch *in, *out, ch;
  244. in = window;
  245. out = &output_data[output_ptr];
  246. for (n = 0; n < outcnt; n++) {
  247. ch = *out++ = *in++;
  248. c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
  249. }
  250. crc = c;
  251. bytes_out += (ulg)outcnt;
  252. output_ptr += (ulg)outcnt;
  253. outcnt = 0;
  254. }
  255. static void flush_window_high(void)
  256. {
  257. ulg c = crc; /* temporary variable */
  258. unsigned n;
  259. uch *in, ch;
  260. in = window;
  261. for (n = 0; n < outcnt; n++) {
  262. ch = *output_data++ = *in++;
  263. if ((ulg) output_data == LOW_BUFFER_END)
  264. output_data = high_buffer_start;
  265. c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
  266. }
  267. crc = c;
  268. bytes_out += (ulg)outcnt;
  269. outcnt = 0;
  270. }
  271. static void flush_window(void)
  272. {
  273. if (high_loaded)
  274. flush_window_high();
  275. else
  276. flush_window_low();
  277. }
  278. static void error(const char *x)
  279. {
  280. kputs("\n\n");
  281. kputs(x);
  282. kputs("\n\n -- System halted");
  283. while (1)
  284. /* Halt */;
  285. }
  286. #define STACK_SIZE (4096)
  287. long user_stack[STACK_SIZE];
  288. struct {
  289. long *a;
  290. short b;
  291. } stack_start = { &user_stack[STACK_SIZE], 0 };
  292. void setup_normal_output_buffer(void)
  293. {
  294. #ifdef STANDARD_MEMORY_BIOS_CALL
  295. if (EXT_MEM_K < 1024)
  296. error("Less than 2MB of memory.\n");
  297. #else
  298. if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < 1024)
  299. error("Less than 2MB of memory.\n");
  300. #endif
  301. output_data = (char *) 0x100000; /* Points to 1M */
  302. }
  303. struct moveparams {
  304. uch *low_buffer_start;
  305. int lcount;
  306. uch *high_buffer_start;
  307. int hcount;
  308. };
  309. void setup_output_buffer_if_we_run_high(struct moveparams *mv)
  310. {
  311. high_buffer_start = (uch *)(((ulg) &end) + HEAP_SIZE);
  312. #ifdef STANDARD_MEMORY_BIOS_CALL
  313. if (EXT_MEM_K < (3 * 1024))
  314. error("Less than 4MB of memory.\n");
  315. #else
  316. if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < (3 * 1024))
  317. error("Less than 4MB of memory.\n");
  318. #endif
  319. mv->low_buffer_start = output_data = (char *) LOW_BUFFER_START;
  320. high_loaded = 1;
  321. free_mem_end_ptr = (long) high_buffer_start;
  322. if (0x100000 + LOW_BUFFER_SIZE > (ulg) high_buffer_start) {
  323. high_buffer_start = (uch *)(0x100000 + LOW_BUFFER_SIZE);
  324. mv->hcount = 0; /* say: we need not to move high_buffer */
  325. } else {
  326. mv->hcount = -1;
  327. }
  328. mv->high_buffer_start = high_buffer_start;
  329. }
  330. void close_output_buffer_if_we_run_high(struct moveparams *mv)
  331. {
  332. mv->lcount = bytes_out;
  333. if (bytes_out > LOW_BUFFER_SIZE) {
  334. mv->lcount = LOW_BUFFER_SIZE;
  335. if (mv->hcount)
  336. mv->hcount = bytes_out - LOW_BUFFER_SIZE;
  337. } else {
  338. mv->hcount = 0;
  339. }
  340. }
  341. #undef DEBUGFLAG
  342. #ifdef DEBUGFLAG
  343. int debugflag;
  344. #endif
  345. int decompress_kernel(struct moveparams *mv)
  346. {
  347. #ifdef DEBUGFLAG
  348. while (!debugflag)
  349. barrier();
  350. #endif
  351. output_data = (char *) CONFIG_KERNEL_TEXT_ADDRESS;
  352. makecrc();
  353. kputs("Uncompressing Linux... ");
  354. gunzip();
  355. kputs("Ok, booting the kernel.\n");
  356. return 0;
  357. }