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