misc.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. /*
  2. * Definitions and wrapper functions for kernel decompressor
  3. *
  4. * Copyright IBM Corp. 2010
  5. *
  6. * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
  7. */
  8. #include <asm/uaccess.h>
  9. #include <asm/page.h>
  10. #include <asm/ipl.h>
  11. #include "sizes.h"
  12. /*
  13. * gzip declarations
  14. */
  15. #define STATIC static
  16. #undef memset
  17. #undef memcpy
  18. #undef memmove
  19. #define memzero(s, n) memset((s), 0, (n))
  20. /* Symbols defined by linker scripts */
  21. extern char input_data[];
  22. extern int input_len;
  23. extern char _text, _end;
  24. extern char _bss, _ebss;
  25. static void error(char *m);
  26. static unsigned long free_mem_ptr;
  27. static unsigned long free_mem_end_ptr;
  28. #ifdef CONFIG_HAVE_KERNEL_BZIP2
  29. #define HEAP_SIZE 0x400000
  30. #else
  31. #define HEAP_SIZE 0x10000
  32. #endif
  33. #ifdef CONFIG_KERNEL_GZIP
  34. #include "../../../../lib/decompress_inflate.c"
  35. #endif
  36. #ifdef CONFIG_KERNEL_BZIP2
  37. #include "../../../../lib/decompress_bunzip2.c"
  38. #endif
  39. #ifdef CONFIG_KERNEL_LZMA
  40. #include "../../../../lib/decompress_unlzma.c"
  41. #endif
  42. #ifdef CONFIG_KERNEL_LZO
  43. #include "../../../../lib/decompress_unlzo.c"
  44. #endif
  45. extern _sclp_print_early(const char *);
  46. int puts(const char *s)
  47. {
  48. _sclp_print_early(s);
  49. return 0;
  50. }
  51. void *memset(void *s, int c, size_t n)
  52. {
  53. char *xs;
  54. if (c == 0)
  55. return __builtin_memset(s, 0, n);
  56. xs = (char *) s;
  57. if (n > 0)
  58. do {
  59. *xs++ = c;
  60. } while (--n > 0);
  61. return s;
  62. }
  63. void *memcpy(void *__dest, __const void *__src, size_t __n)
  64. {
  65. return __builtin_memcpy(__dest, __src, __n);
  66. }
  67. void *memmove(void *__dest, __const void *__src, size_t __n)
  68. {
  69. char *d;
  70. const char *s;
  71. if (__dest <= __src)
  72. return __builtin_memcpy(__dest, __src, __n);
  73. d = __dest + __n;
  74. s = __src + __n;
  75. while (__n--)
  76. *--d = *--s;
  77. return __dest;
  78. }
  79. static void error(char *x)
  80. {
  81. unsigned long long psw = 0x000a0000deadbeefULL;
  82. puts("\n\n");
  83. puts(x);
  84. puts("\n\n -- System halted");
  85. asm volatile("lpsw %0" : : "Q" (psw));
  86. }
  87. /*
  88. * Safe guard the ipl parameter block against a memory area that will be
  89. * overwritten. The validity check for the ipl parameter block is complex
  90. * (see cio_get_iplinfo and ipl_save_parameters) but if the pointer to
  91. * the ipl parameter block intersects with the passed memory area we can
  92. * safely assume that we can read from that memory. In that case just copy
  93. * the memory to IPL_PARMBLOCK_ORIGIN even if there is no ipl parameter
  94. * block.
  95. */
  96. static void check_ipl_parmblock(void *start, unsigned long size)
  97. {
  98. void *src, *dst;
  99. src = (void *)(unsigned long) S390_lowcore.ipl_parmblock_ptr;
  100. if (src + PAGE_SIZE <= start || src >= start + size)
  101. return;
  102. dst = (void *) IPL_PARMBLOCK_ORIGIN;
  103. memmove(dst, src, PAGE_SIZE);
  104. S390_lowcore.ipl_parmblock_ptr = IPL_PARMBLOCK_ORIGIN;
  105. }
  106. unsigned long decompress_kernel(void)
  107. {
  108. unsigned long output_addr;
  109. unsigned char *output;
  110. check_ipl_parmblock((void *) 0, (unsigned long) output + SZ__bss_start);
  111. memset(&_bss, 0, &_ebss - &_bss);
  112. free_mem_ptr = (unsigned long)&_end;
  113. free_mem_end_ptr = free_mem_ptr + HEAP_SIZE;
  114. output = (unsigned char *) ((free_mem_end_ptr + 4095UL) & -4096UL);
  115. #ifdef CONFIG_BLK_DEV_INITRD
  116. /*
  117. * Move the initrd right behind the end of the decompressed
  118. * kernel image.
  119. */
  120. if (INITRD_START && INITRD_SIZE &&
  121. INITRD_START < (unsigned long) output + SZ__bss_start) {
  122. check_ipl_parmblock(output + SZ__bss_start,
  123. INITRD_START + INITRD_SIZE);
  124. memmove(output + SZ__bss_start,
  125. (void *) INITRD_START, INITRD_SIZE);
  126. INITRD_START = (unsigned long) output + SZ__bss_start;
  127. }
  128. #endif
  129. puts("Uncompressing Linux... ");
  130. decompress(input_data, input_len, NULL, NULL, output, NULL, error);
  131. puts("Ok, booting the kernel.\n");
  132. return (unsigned long) output;
  133. }