misc.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  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. extern _sclp_print_early(const char *);
  43. int puts(const char *s)
  44. {
  45. _sclp_print_early(s);
  46. return 0;
  47. }
  48. void *memset(void *s, int c, size_t n)
  49. {
  50. char *xs;
  51. if (c == 0)
  52. return __builtin_memset(s, 0, n);
  53. xs = (char *) s;
  54. if (n > 0)
  55. do {
  56. *xs++ = c;
  57. } while (--n > 0);
  58. return s;
  59. }
  60. void *memcpy(void *__dest, __const void *__src, size_t __n)
  61. {
  62. return __builtin_memcpy(__dest, __src, __n);
  63. }
  64. void *memmove(void *__dest, __const void *__src, size_t __n)
  65. {
  66. char *d;
  67. const char *s;
  68. if (__dest <= __src)
  69. return __builtin_memcpy(__dest, __src, __n);
  70. d = __dest + __n;
  71. s = __src + __n;
  72. while (__n--)
  73. *--d = *--s;
  74. return __dest;
  75. }
  76. static void error(char *x)
  77. {
  78. unsigned long long psw = 0x000a0000deadbeefULL;
  79. puts("\n\n");
  80. puts(x);
  81. puts("\n\n -- System halted");
  82. asm volatile("lpsw %0" : : "Q" (psw));
  83. }
  84. /*
  85. * Safe guard the ipl parameter block against a memory area that will be
  86. * overwritten. The validity check for the ipl parameter block is complex
  87. * (see cio_get_iplinfo and ipl_save_parameters) but if the pointer to
  88. * the ipl parameter block intersects with the passed memory area we can
  89. * safely assume that we can read from that memory. In that case just copy
  90. * the memory to IPL_PARMBLOCK_ORIGIN even if there is no ipl parameter
  91. * block.
  92. */
  93. static void check_ipl_parmblock(void *start, unsigned long size)
  94. {
  95. void *src, *dst;
  96. src = (void *)(unsigned long) S390_lowcore.ipl_parmblock_ptr;
  97. if (src + PAGE_SIZE <= start || src >= start + size)
  98. return;
  99. dst = (void *) IPL_PARMBLOCK_ORIGIN;
  100. memmove(dst, src, PAGE_SIZE);
  101. S390_lowcore.ipl_parmblock_ptr = IPL_PARMBLOCK_ORIGIN;
  102. }
  103. unsigned long decompress_kernel(void)
  104. {
  105. unsigned long output_addr;
  106. unsigned char *output;
  107. check_ipl_parmblock((void *) 0, (unsigned long) output + SZ__bss_start);
  108. memset(&_bss, 0, &_ebss - &_bss);
  109. free_mem_ptr = (unsigned long)&_end;
  110. free_mem_end_ptr = free_mem_ptr + HEAP_SIZE;
  111. output = (unsigned char *) ((free_mem_end_ptr + 4095UL) & -4096UL);
  112. #ifdef CONFIG_BLK_DEV_INITRD
  113. /*
  114. * Move the initrd right behind the end of the decompressed
  115. * kernel image.
  116. */
  117. if (INITRD_START && INITRD_SIZE &&
  118. INITRD_START < (unsigned long) output + SZ__bss_start) {
  119. check_ipl_parmblock(output + SZ__bss_start,
  120. INITRD_START + INITRD_SIZE);
  121. memmove(output + SZ__bss_start,
  122. (void *) INITRD_START, INITRD_SIZE);
  123. INITRD_START = (unsigned long) output + SZ__bss_start;
  124. }
  125. #endif
  126. puts("Uncompressing Linux... ");
  127. decompress(input_data, input_len, NULL, NULL, output, NULL, error);
  128. puts("Ok, booting the kernel.\n");
  129. return (unsigned long) output;
  130. }