linux/arch/arm/boot/compressed/misc.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * misc.c
   4 * 
   5 * This is a collection of several routines from gzip-1.0.3 
   6 * adapted for Linux.
   7 *
   8 * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
   9 *
  10 * Modified for ARM Linux by Russell King
  11 *
  12 * Nicolas Pitre <nico@visuaide.com>  1999/04/14 :
  13 *  For this code to run directly from Flash, all constant variables must
  14 *  be marked with 'const' and all other variables initialized at run-time 
  15 *  only.  This way all non constant variables will end up in the bss segment,
  16 *  which should point to addresses in RAM and cleared to 0 on start.
  17 *  This allows for a much quicker boot time.
  18 */
  19
  20unsigned int __machine_arch_type;
  21
  22#include <linux/compiler.h>     /* for inline */
  23#include <linux/types.h>
  24#include <linux/linkage.h>
  25#include "misc.h"
  26
  27static void putstr(const char *ptr);
  28
  29#include CONFIG_UNCOMPRESS_INCLUDE
  30
  31#ifdef CONFIG_DEBUG_ICEDCC
  32
  33#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K) || defined(CONFIG_CPU_V7)
  34
  35static void icedcc_putc(int ch)
  36{
  37        int status, i = 0x4000000;
  38
  39        do {
  40                if (--i < 0)
  41                        return;
  42
  43                asm volatile ("mrc p14, 0, %0, c0, c1, 0" : "=r" (status));
  44        } while (status & (1 << 29));
  45
  46        asm("mcr p14, 0, %0, c0, c5, 0" : : "r" (ch));
  47}
  48
  49
  50#elif defined(CONFIG_CPU_XSCALE)
  51
  52static void icedcc_putc(int ch)
  53{
  54        int status, i = 0x4000000;
  55
  56        do {
  57                if (--i < 0)
  58                        return;
  59
  60                asm volatile ("mrc p14, 0, %0, c14, c0, 0" : "=r" (status));
  61        } while (status & (1 << 28));
  62
  63        asm("mcr p14, 0, %0, c8, c0, 0" : : "r" (ch));
  64}
  65
  66#else
  67
  68static void icedcc_putc(int ch)
  69{
  70        int status, i = 0x4000000;
  71
  72        do {
  73                if (--i < 0)
  74                        return;
  75
  76                asm volatile ("mrc p14, 0, %0, c0, c0, 0" : "=r" (status));
  77        } while (status & 2);
  78
  79        asm("mcr p14, 0, %0, c1, c0, 0" : : "r" (ch));
  80}
  81
  82#endif
  83
  84#define putc(ch)        icedcc_putc(ch)
  85#endif
  86
  87static void putstr(const char *ptr)
  88{
  89        char c;
  90
  91        while ((c = *ptr++) != '\0') {
  92                if (c == '\n')
  93                        putc('\r');
  94                putc(c);
  95        }
  96
  97        flush();
  98}
  99
 100/*
 101 * gzip declarations
 102 */
 103extern char input_data[];
 104extern char input_data_end[];
 105
 106unsigned char *output_data;
 107
 108unsigned long free_mem_ptr;
 109unsigned long free_mem_end_ptr;
 110
 111#ifndef arch_error
 112#define arch_error(x)
 113#endif
 114
 115void error(char *x)
 116{
 117        arch_error(x);
 118
 119        putstr("\n\n");
 120        putstr(x);
 121        putstr("\n\n -- System halted");
 122
 123        while(1);       /* Halt */
 124}
 125
 126asmlinkage void __div0(void)
 127{
 128        error("Attempting division by 0!");
 129}
 130
 131const unsigned long __stack_chk_guard = 0x000a0dff;
 132
 133void __stack_chk_fail(void)
 134{
 135        error("stack-protector: Kernel stack is corrupted\n");
 136}
 137
 138extern int do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x));
 139
 140
 141void
 142decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p,
 143                unsigned long free_mem_ptr_end_p,
 144                int arch_id)
 145{
 146        int ret;
 147
 148        output_data             = (unsigned char *)output_start;
 149        free_mem_ptr            = free_mem_ptr_p;
 150        free_mem_end_ptr        = free_mem_ptr_end_p;
 151        __machine_arch_type     = arch_id;
 152
 153        arch_decomp_setup();
 154
 155        putstr("Uncompressing Linux...");
 156        ret = do_decompress(input_data, input_data_end - input_data,
 157                            output_data, error);
 158        if (ret)
 159                error("decompressor returned an error");
 160        else
 161                putstr(" done, booting the kernel.\n");
 162}
 163
 164void fortify_panic(const char *name)
 165{
 166        error("detected buffer overflow");
 167}
 168