1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 21da177e4SLinus Torvalds /* 31da177e4SLinus Torvalds * misc.c 41da177e4SLinus Torvalds * 51da177e4SLinus Torvalds * This is a collection of several routines from gzip-1.0.3 61da177e4SLinus Torvalds * adapted for Linux. 71da177e4SLinus Torvalds * 81da177e4SLinus Torvalds * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994 91da177e4SLinus Torvalds * 101da177e4SLinus Torvalds * Modified for ARM Linux by Russell King 111da177e4SLinus Torvalds * 121da177e4SLinus Torvalds * Nicolas Pitre <nico@visuaide.com> 1999/04/14 : 131da177e4SLinus Torvalds * For this code to run directly from Flash, all constant variables must 141da177e4SLinus Torvalds * be marked with 'const' and all other variables initialized at run-time 151da177e4SLinus Torvalds * only. This way all non constant variables will end up in the bss segment, 161da177e4SLinus Torvalds * which should point to addresses in RAM and cleared to 0 on start. 171da177e4SLinus Torvalds * This allows for a much quicker boot time. 181da177e4SLinus Torvalds */ 191da177e4SLinus Torvalds 201da177e4SLinus Torvalds unsigned int __machine_arch_type; 211da177e4SLinus Torvalds 22aa0d3bb7SRusty Russell #include <linux/compiler.h> /* for inline */ 23df4879faSNicolas Pitre #include <linux/types.h> 24e7db7b42SAlbin Tonnerre #include <linux/linkage.h> 25a081568dSRussell King 26a081568dSRussell King static void putstr(const char *ptr); 27a2302b45SMark Brown extern void error(char *x); 28a081568dSRussell King 29615967b0SShawn Guo #include CONFIG_UNCOMPRESS_INCLUDE 301da177e4SLinus Torvalds 311da177e4SLinus Torvalds #ifdef CONFIG_DEBUG_ICEDCC 327d95ded9STony Lindgren 33dfad549dSStephen Boyd #if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K) || defined(CONFIG_CPU_V7) 347d95ded9STony Lindgren 357d95ded9STony Lindgren static void icedcc_putc(int ch) 367d95ded9STony Lindgren { 377d95ded9STony Lindgren int status, i = 0x4000000; 387d95ded9STony Lindgren 397d95ded9STony Lindgren do { 407d95ded9STony Lindgren if (--i < 0) 417d95ded9STony Lindgren return; 427d95ded9STony Lindgren 437d95ded9STony Lindgren asm volatile ("mrc p14, 0, %0, c0, c1, 0" : "=r" (status)); 447d95ded9STony Lindgren } while (status & (1 << 29)); 457d95ded9STony Lindgren 467d95ded9STony Lindgren asm("mcr p14, 0, %0, c0, c5, 0" : : "r" (ch)); 477d95ded9STony Lindgren } 48200b7a8dSTony Lindgren 49200b7a8dSTony Lindgren 50c633c3cfSJean-Christop PLAGNIOL-VILLARD #elif defined(CONFIG_CPU_XSCALE) 51c633c3cfSJean-Christop PLAGNIOL-VILLARD 52c633c3cfSJean-Christop PLAGNIOL-VILLARD static void icedcc_putc(int ch) 53c633c3cfSJean-Christop PLAGNIOL-VILLARD { 54c633c3cfSJean-Christop PLAGNIOL-VILLARD int status, i = 0x4000000; 55c633c3cfSJean-Christop PLAGNIOL-VILLARD 56c633c3cfSJean-Christop PLAGNIOL-VILLARD do { 57c633c3cfSJean-Christop PLAGNIOL-VILLARD if (--i < 0) 58c633c3cfSJean-Christop PLAGNIOL-VILLARD return; 59c633c3cfSJean-Christop PLAGNIOL-VILLARD 60c633c3cfSJean-Christop PLAGNIOL-VILLARD asm volatile ("mrc p14, 0, %0, c14, c0, 0" : "=r" (status)); 61c633c3cfSJean-Christop PLAGNIOL-VILLARD } while (status & (1 << 28)); 62c633c3cfSJean-Christop PLAGNIOL-VILLARD 63c633c3cfSJean-Christop PLAGNIOL-VILLARD asm("mcr p14, 0, %0, c8, c0, 0" : : "r" (ch)); 64c633c3cfSJean-Christop PLAGNIOL-VILLARD } 657d95ded9STony Lindgren 667d95ded9STony Lindgren #else 677d95ded9STony Lindgren 68de4533a0SRussell King static void icedcc_putc(int ch) 69de4533a0SRussell King { 70de4533a0SRussell King int status, i = 0x4000000; 71de4533a0SRussell King 72de4533a0SRussell King do { 73de4533a0SRussell King if (--i < 0) 74de4533a0SRussell King return; 75de4533a0SRussell King 76b2556da5SUwe Zeisberger asm volatile ("mrc p14, 0, %0, c0, c0, 0" : "=r" (status)); 77de4533a0SRussell King } while (status & 2); 78de4533a0SRussell King 79b2556da5SUwe Zeisberger asm("mcr p14, 0, %0, c1, c0, 0" : : "r" (ch)); 80de4533a0SRussell King } 81de4533a0SRussell King 827d95ded9STony Lindgren #endif 837d95ded9STony Lindgren 84a081568dSRussell King #define putc(ch) icedcc_putc(ch) 85a081568dSRussell King #endif 861da177e4SLinus Torvalds 87a081568dSRussell King static void putstr(const char *ptr) 881da177e4SLinus Torvalds { 89a081568dSRussell King char c; 90a081568dSRussell King 91a081568dSRussell King while ((c = *ptr++) != '\0') { 92a081568dSRussell King if (c == '\n') 93a081568dSRussell King putc('\r'); 94a081568dSRussell King putc(c); 951da177e4SLinus Torvalds } 96a081568dSRussell King 97a081568dSRussell King flush(); 981da177e4SLinus Torvalds } 991da177e4SLinus Torvalds 1001da177e4SLinus Torvalds /* 101e40f1e9fSNicolas Pitre * gzip declarations 1021da177e4SLinus Torvalds */ 1031da177e4SLinus Torvalds extern char input_data[]; 1041da177e4SLinus Torvalds extern char input_data_end[]; 1051da177e4SLinus Torvalds 1065de813b6SRussell King unsigned char *output_data; 1071da177e4SLinus Torvalds 1085de813b6SRussell King unsigned long free_mem_ptr; 1095de813b6SRussell King unsigned long free_mem_end_ptr; 1101da177e4SLinus Torvalds 111f8c905d3SBen Dooks #ifndef arch_error 112f8c905d3SBen Dooks #define arch_error(x) 113f8c905d3SBen Dooks #endif 114f8c905d3SBen Dooks 1155de813b6SRussell King void error(char *x) 1161da177e4SLinus Torvalds { 117f8c905d3SBen Dooks arch_error(x); 118f8c905d3SBen Dooks 1191da177e4SLinus Torvalds putstr("\n\n"); 1201da177e4SLinus Torvalds putstr(x); 1211da177e4SLinus Torvalds putstr("\n\n -- System halted"); 1221da177e4SLinus Torvalds 1231da177e4SLinus Torvalds while(1); /* Halt */ 1241da177e4SLinus Torvalds } 1251da177e4SLinus Torvalds 126e7db7b42SAlbin Tonnerre asmlinkage void __div0(void) 127e7db7b42SAlbin Tonnerre { 128e7db7b42SAlbin Tonnerre error("Attempting division by 0!"); 129e7db7b42SAlbin Tonnerre } 130e7db7b42SAlbin Tonnerre 1318779657dSKees Cook unsigned long __stack_chk_guard; 1328779657dSKees Cook 1338779657dSKees Cook void __stack_chk_guard_setup(void) 1348779657dSKees Cook { 1358779657dSKees Cook __stack_chk_guard = 0x000a0dff; 1368779657dSKees Cook } 1378779657dSKees Cook 1388779657dSKees Cook void __stack_chk_fail(void) 1398779657dSKees Cook { 1408779657dSKees Cook error("stack-protector: Kernel stack is corrupted\n"); 1418779657dSKees Cook } 1428779657dSKees Cook 143ccc1c7c6SNicolas Pitre extern int do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x)); 1445de813b6SRussell King 1451da177e4SLinus Torvalds 146e40f1e9fSNicolas Pitre void 147e7db7b42SAlbin Tonnerre decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p, 148e7db7b42SAlbin Tonnerre unsigned long free_mem_ptr_end_p, 1491da177e4SLinus Torvalds int arch_id) 1501da177e4SLinus Torvalds { 151ccc1c7c6SNicolas Pitre int ret; 152e7db7b42SAlbin Tonnerre 1538779657dSKees Cook __stack_chk_guard_setup(); 1548779657dSKees Cook 155e7db7b42SAlbin Tonnerre output_data = (unsigned char *)output_start; 1561da177e4SLinus Torvalds free_mem_ptr = free_mem_ptr_p; 1572d6ffccaSThomas Petazzoni free_mem_end_ptr = free_mem_ptr_end_p; 1581da177e4SLinus Torvalds __machine_arch_type = arch_id; 1591da177e4SLinus Torvalds 1601da177e4SLinus Torvalds arch_decomp_setup(); 1611da177e4SLinus Torvalds 1621da177e4SLinus Torvalds putstr("Uncompressing Linux..."); 163ccc1c7c6SNicolas Pitre ret = do_decompress(input_data, input_data_end - input_data, 1645de813b6SRussell King output_data, error); 165ccc1c7c6SNicolas Pitre if (ret) 166ccc1c7c6SNicolas Pitre error("decompressor returned an error"); 167ccc1c7c6SNicolas Pitre else 1681da177e4SLinus Torvalds putstr(" done, booting the kernel.\n"); 1691da177e4SLinus Torvalds } 170*ee333554SJinbum Park 171*ee333554SJinbum Park void fortify_panic(const char *name) 172*ee333554SJinbum Park { 173*ee333554SJinbum Park error("detected buffer overflow"); 174*ee333554SJinbum Park } 175