misc.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  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 unsigned long free_mem_ptr = (unsigned long) &end;
  133. static unsigned long free_mem_end_ptr = (unsigned long) &end + 0x90000;
  134. #define INPLACE_MOVE_ROUTINE 0x1000
  135. #define LOW_BUFFER_START 0x2000
  136. #define LOW_BUFFER_END 0x90000
  137. #define LOW_BUFFER_SIZE (LOW_BUFFER_END - LOW_BUFFER_START)
  138. #define HEAP_SIZE 0x3000
  139. static int high_loaded;
  140. static uch *high_buffer_start /* = (uch *)(((ulg)&end) + HEAP_SIZE)*/;
  141. static char *vidmem = (char *)0xb8000;
  142. static int lines, cols;
  143. #include "../../../../lib/inflate.c"
  144. static inline void scroll(void)
  145. {
  146. int i;
  147. memcpy(vidmem, vidmem + cols * 2, (lines - 1) * cols * 2);
  148. for (i = (lines - 1) * cols * 2; i < lines * cols * 2; i += 2)
  149. vidmem[i] = ' ';
  150. }
  151. static inline void kputchar(unsigned char ch)
  152. {
  153. #ifdef CONFIG_MN10300_UNIT_ASB2305
  154. while (SC0STR & SC01STR_TBF)
  155. continue;
  156. if (ch == 0x0a) {
  157. SC0TXB = 0x0d;
  158. while (SC0STR & SC01STR_TBF)
  159. continue;
  160. }
  161. SC0TXB = ch;
  162. #else
  163. while (SC1STR & SC01STR_TBF)
  164. continue;
  165. if (ch == 0x0a) {
  166. SC1TXB = 0x0d;
  167. while (SC1STR & SC01STR_TBF)
  168. continue;
  169. }
  170. SC1TXB = ch;
  171. #endif
  172. }
  173. static void kputs(const char *s)
  174. {
  175. #ifdef CONFIG_DEBUG_DECOMPRESS_KERNEL
  176. #ifndef CONFIG_GDBSTUB_ON_TTYSx
  177. char ch;
  178. FLOWCTL_SET(DTR);
  179. while (*s) {
  180. LSR_WAIT_FOR(THRE);
  181. ch = *s++;
  182. if (ch == 0x0a) {
  183. CYG_DEV_THR = 0x0d;
  184. LSR_WAIT_FOR(THRE);
  185. }
  186. CYG_DEV_THR = ch;
  187. }
  188. FLOWCTL_CLEAR(DTR);
  189. #else
  190. for (; *s; s++)
  191. kputchar(*s);
  192. #endif
  193. #endif /* CONFIG_DEBUG_DECOMPRESS_KERNEL */
  194. }
  195. /* ===========================================================================
  196. * Fill the input buffer. This is called only when the buffer is empty
  197. * and at least one byte is really needed.
  198. */
  199. static int fill_inbuf()
  200. {
  201. if (insize != 0)
  202. error("ran out of input data\n");
  203. inbuf = input_data;
  204. insize = input_len;
  205. inptr = 1;
  206. return inbuf[0];
  207. }
  208. /* ===========================================================================
  209. * Write the output window window[0..outcnt-1] and update crc and bytes_out.
  210. * (Used for the decompressed data only.)
  211. */
  212. static void flush_window_low(void)
  213. {
  214. ulg c = crc; /* temporary variable */
  215. unsigned n;
  216. uch *in, *out, ch;
  217. in = window;
  218. out = &output_data[output_ptr];
  219. for (n = 0; n < outcnt; n++) {
  220. ch = *out++ = *in++;
  221. c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
  222. }
  223. crc = c;
  224. bytes_out += (ulg)outcnt;
  225. output_ptr += (ulg)outcnt;
  226. outcnt = 0;
  227. }
  228. static void flush_window_high(void)
  229. {
  230. ulg c = crc; /* temporary variable */
  231. unsigned n;
  232. uch *in, ch;
  233. in = window;
  234. for (n = 0; n < outcnt; n++) {
  235. ch = *output_data++ = *in++;
  236. if ((ulg) output_data == LOW_BUFFER_END)
  237. output_data = high_buffer_start;
  238. c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
  239. }
  240. crc = c;
  241. bytes_out += (ulg)outcnt;
  242. outcnt = 0;
  243. }
  244. static void flush_window(void)
  245. {
  246. if (high_loaded)
  247. flush_window_high();
  248. else
  249. flush_window_low();
  250. }
  251. static void error(const char *x)
  252. {
  253. kputs("\n\n");
  254. kputs(x);
  255. kputs("\n\n -- System halted");
  256. while (1)
  257. /* Halt */;
  258. }
  259. #define STACK_SIZE (4096)
  260. long user_stack[STACK_SIZE];
  261. struct {
  262. long *a;
  263. short b;
  264. } stack_start = { &user_stack[STACK_SIZE], 0 };
  265. void setup_normal_output_buffer(void)
  266. {
  267. #ifdef STANDARD_MEMORY_BIOS_CALL
  268. if (EXT_MEM_K < 1024)
  269. error("Less than 2MB of memory.\n");
  270. #else
  271. if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < 1024)
  272. error("Less than 2MB of memory.\n");
  273. #endif
  274. output_data = (char *) 0x100000; /* Points to 1M */
  275. }
  276. struct moveparams {
  277. uch *low_buffer_start;
  278. int lcount;
  279. uch *high_buffer_start;
  280. int hcount;
  281. };
  282. void setup_output_buffer_if_we_run_high(struct moveparams *mv)
  283. {
  284. high_buffer_start = (uch *)(((ulg) &end) + HEAP_SIZE);
  285. #ifdef STANDARD_MEMORY_BIOS_CALL
  286. if (EXT_MEM_K < (3 * 1024))
  287. error("Less than 4MB of memory.\n");
  288. #else
  289. if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < (3 * 1024))
  290. error("Less than 4MB of memory.\n");
  291. #endif
  292. mv->low_buffer_start = output_data = (char *) LOW_BUFFER_START;
  293. high_loaded = 1;
  294. free_mem_end_ptr = (long) high_buffer_start;
  295. if (0x100000 + LOW_BUFFER_SIZE > (ulg) high_buffer_start) {
  296. high_buffer_start = (uch *)(0x100000 + LOW_BUFFER_SIZE);
  297. mv->hcount = 0; /* say: we need not to move high_buffer */
  298. } else {
  299. mv->hcount = -1;
  300. }
  301. mv->high_buffer_start = high_buffer_start;
  302. }
  303. void close_output_buffer_if_we_run_high(struct moveparams *mv)
  304. {
  305. mv->lcount = bytes_out;
  306. if (bytes_out > LOW_BUFFER_SIZE) {
  307. mv->lcount = LOW_BUFFER_SIZE;
  308. if (mv->hcount)
  309. mv->hcount = bytes_out - LOW_BUFFER_SIZE;
  310. } else {
  311. mv->hcount = 0;
  312. }
  313. }
  314. #undef DEBUGFLAG
  315. #ifdef DEBUGFLAG
  316. int debugflag;
  317. #endif
  318. int decompress_kernel(struct moveparams *mv)
  319. {
  320. #ifdef DEBUGFLAG
  321. while (!debugflag)
  322. barrier();
  323. #endif
  324. output_data = (char *) CONFIG_KERNEL_TEXT_ADDRESS;
  325. makecrc();
  326. kputs("Uncompressing Linux... ");
  327. gunzip();
  328. kputs("Ok, booting the kernel.\n");
  329. return 0;
  330. }