misc.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. /*
  2. * Definitions and wrapper functions for kernel decompressor
  3. *
  4. * (C) 2017 Helge Deller <deller@gmx.de>
  5. */
  6. #include <linux/uaccess.h>
  7. #include <asm/unaligned.h>
  8. #include <asm/page.h>
  9. #include "sizes.h"
  10. /*
  11. * gzip declarations
  12. */
  13. #define STATIC static
  14. #undef memmove
  15. #define memmove memmove
  16. #define memzero(s, n) memset((s), 0, (n))
  17. #define malloc malloc_gzip
  18. #define free free_gzip
  19. /* Symbols defined by linker scripts */
  20. extern char input_data[];
  21. extern int input_len;
  22. /* output_len is inserted by the linker possibly at an unaligned address */
  23. extern __le32 output_len __aligned(1);
  24. extern char _text, _end;
  25. extern char _bss, _ebss;
  26. extern char _startcode_end;
  27. extern void startup_continue(void *entry, unsigned long cmdline,
  28. unsigned long rd_start, unsigned long rd_end) __noreturn;
  29. void error(char *m) __noreturn;
  30. static unsigned long free_mem_ptr;
  31. static unsigned long free_mem_end_ptr;
  32. #ifdef CONFIG_KERNEL_GZIP
  33. #include "../../../../lib/decompress_inflate.c"
  34. #endif
  35. #ifdef CONFIG_KERNEL_BZIP2
  36. #include "../../../../lib/decompress_bunzip2.c"
  37. #endif
  38. #ifdef CONFIG_KERNEL_LZ4
  39. #include "../../../../lib/decompress_unlz4.c"
  40. #endif
  41. #ifdef CONFIG_KERNEL_LZMA
  42. #include "../../../../lib/decompress_unlzma.c"
  43. #endif
  44. #ifdef CONFIG_KERNEL_LZO
  45. #include "../../../../lib/decompress_unlzo.c"
  46. #endif
  47. #ifdef CONFIG_KERNEL_XZ
  48. #include "../../../../lib/decompress_unxz.c"
  49. #endif
  50. void *memmove(void *dest, const void *src, size_t n)
  51. {
  52. const char *s = src;
  53. char *d = dest;
  54. if (d <= s) {
  55. while (n--)
  56. *d++ = *s++;
  57. } else {
  58. d += n;
  59. s += n;
  60. while (n--)
  61. *--d = *--s;
  62. }
  63. return dest;
  64. }
  65. void *memset(void *s, int c, size_t count)
  66. {
  67. char *xs = (char *)s;
  68. while (count--)
  69. *xs++ = c;
  70. return s;
  71. }
  72. void *memcpy(void *d, const void *s, size_t len)
  73. {
  74. char *dest = (char *)d;
  75. const char *source = (const char *)s;
  76. while (len--)
  77. *dest++ = *source++;
  78. return d;
  79. }
  80. size_t strlen(const char *s)
  81. {
  82. const char *sc;
  83. for (sc = s; *sc != '\0'; ++sc)
  84. ;
  85. return sc - s;
  86. }
  87. char *strchr(const char *s, int c)
  88. {
  89. while (*s) {
  90. if (*s == (char)c)
  91. return (char *)s;
  92. ++s;
  93. }
  94. return NULL;
  95. }
  96. int puts(const char *s)
  97. {
  98. const char *nuline = s;
  99. while ((nuline = strchr(s, '\n')) != NULL) {
  100. if (nuline != s)
  101. pdc_iodc_print(s, nuline - s);
  102. pdc_iodc_print("\r\n", 2);
  103. s = nuline + 1;
  104. }
  105. if (*s != '\0')
  106. pdc_iodc_print(s, strlen(s));
  107. return 0;
  108. }
  109. static int putchar(int c)
  110. {
  111. char buf[2];
  112. buf[0] = c;
  113. buf[1] = '\0';
  114. puts(buf);
  115. return c;
  116. }
  117. void __noreturn error(char *x)
  118. {
  119. puts("\n\n");
  120. puts(x);
  121. puts("\n\n -- System halted");
  122. while (1) /* wait forever */
  123. ;
  124. }
  125. static int print_hex(unsigned long num)
  126. {
  127. const char hex[] = "0123456789abcdef";
  128. char str[40];
  129. int i = sizeof(str)-1;
  130. str[i--] = '\0';
  131. do {
  132. str[i--] = hex[num & 0x0f];
  133. num >>= 4;
  134. } while (num);
  135. str[i--] = 'x';
  136. str[i] = '0';
  137. puts(&str[i]);
  138. return 0;
  139. }
  140. int printf(const char *fmt, ...)
  141. {
  142. va_list args;
  143. int i = 0;
  144. va_start(args, fmt);
  145. while (fmt[i]) {
  146. if (fmt[i] != '%') {
  147. put:
  148. putchar(fmt[i++]);
  149. continue;
  150. }
  151. if (fmt[++i] == '%')
  152. goto put;
  153. ++i;
  154. print_hex(va_arg(args, unsigned long));
  155. }
  156. va_end(args);
  157. return 0;
  158. }
  159. /* helper functions for libgcc */
  160. void abort(void)
  161. {
  162. error("aborted.");
  163. }
  164. #undef malloc
  165. void *malloc(size_t size)
  166. {
  167. return malloc_gzip(size);
  168. }
  169. #undef free
  170. void free(void *ptr)
  171. {
  172. return free_gzip(ptr);
  173. }
  174. static void flush_data_cache(char *start, unsigned long length)
  175. {
  176. char *end = start + length;
  177. do {
  178. asm volatile("fdc 0(%0)" : : "r" (start));
  179. asm volatile("fic 0(%%sr0,%0)" : : "r" (start));
  180. start += 16;
  181. } while (start < end);
  182. asm volatile("fdc 0(%0)" : : "r" (end));
  183. asm ("sync");
  184. }
  185. unsigned long decompress_kernel(unsigned int started_wide,
  186. unsigned int command_line,
  187. const unsigned int rd_start,
  188. const unsigned int rd_end)
  189. {
  190. char *output;
  191. unsigned long len, len_all;
  192. #ifdef CONFIG_64BIT
  193. parisc_narrow_firmware = 0;
  194. #endif
  195. set_firmware_width_unlocked();
  196. putchar('U'); /* if you get this p and no more, string storage */
  197. /* in $GLOBAL$ is wrong or %dp is wrong */
  198. puts("ncompressing ...\n");
  199. output = (char *) KERNEL_BINARY_TEXT_START;
  200. len_all = __pa(SZ_end) - __pa(SZparisc_kernel_start);
  201. if ((unsigned long) &_startcode_end > (unsigned long) output)
  202. error("Bootcode overlaps kernel code");
  203. len = get_unaligned_le32(&output_len);
  204. if (len > len_all)
  205. error("Output len too big.");
  206. else
  207. memset(&output[len], 0, len_all - len);
  208. /*
  209. * Initialize free_mem_ptr and free_mem_end_ptr.
  210. */
  211. free_mem_ptr = (unsigned long) &_ebss;
  212. free_mem_ptr += 2*1024*1024; /* leave 2 MB for stack */
  213. /* Limit memory for bootoader to 1GB */
  214. #define ARTIFICIAL_LIMIT (1*1024*1024*1024)
  215. free_mem_end_ptr = PAGE0->imm_max_mem;
  216. if (free_mem_end_ptr > ARTIFICIAL_LIMIT)
  217. free_mem_end_ptr = ARTIFICIAL_LIMIT;
  218. #ifdef CONFIG_BLK_DEV_INITRD
  219. /* if we have ramdisk this is at end of memory */
  220. if (rd_start && rd_start < free_mem_end_ptr)
  221. free_mem_end_ptr = rd_start;
  222. #endif
  223. #ifdef DEBUG
  224. printf("startcode_end = %x\n", &_startcode_end);
  225. printf("commandline = %x\n", command_line);
  226. printf("rd_start = %x\n", rd_start);
  227. printf("rd_end = %x\n", rd_end);
  228. printf("free_ptr = %x\n", free_mem_ptr);
  229. printf("free_ptr_end = %x\n", free_mem_end_ptr);
  230. printf("input_data = %x\n", input_data);
  231. printf("input_len = %x\n", input_len);
  232. printf("output = %x\n", output);
  233. printf("output_len = %x\n", len);
  234. printf("output_max = %x\n", len_all);
  235. #endif
  236. __decompress(input_data, input_len, NULL, NULL,
  237. output, 0, NULL, error);
  238. flush_data_cache(output, len);
  239. printf("Booting kernel ...\n\n");
  240. return (unsigned long) output;
  241. }