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#ifdef CONFIG_ARCH_MULTIPLATFORM
  29static inline void putc(int c) {}
  30static inline void flush(void) {}
  31static inline void arch_decomp_setup(void) {}
  32#else
  33#include <mach/uncompress.h>
  34#endif
  35
  36#ifdef CONFIG_DEBUG_ICEDCC
  37
  38#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K) || defined(CONFIG_CPU_V7)
  39
  40static void icedcc_putc(int ch)
  41{
  42        int status, i = 0x4000000;
  43
  44        do {
  45                if (--i < 0)
  46                        return;
  47
  48                asm volatile ("mrc p14, 0, %0, c0, c1, 0" : "=r" (status));
  49        } while (status & (1 << 29));
  50
  51        asm("mcr p14, 0, %0, c0, c5, 0" : : "r" (ch));
  52}
  53
  54
  55#elif defined(CONFIG_CPU_XSCALE)
  56
  57static void icedcc_putc(int ch)
  58{
  59        int status, i = 0x4000000;
  60
  61        do {
  62                if (--i < 0)
  63                        return;
  64
  65                asm volatile ("mrc p14, 0, %0, c14, c0, 0" : "=r" (status));
  66        } while (status & (1 << 28));
  67
  68        asm("mcr p14, 0, %0, c8, c0, 0" : : "r" (ch));
  69}
  70
  71#else
  72
  73static void icedcc_putc(int ch)
  74{
  75        int status, i = 0x4000000;
  76
  77        do {
  78                if (--i < 0)
  79                        return;
  80
  81                asm volatile ("mrc p14, 0, %0, c0, c0, 0" : "=r" (status));
  82        } while (status & 2);
  83
  84        asm("mcr p14, 0, %0, c1, c0, 0" : : "r" (ch));
  85}
  86
  87#endif
  88
  89#define putc(ch)        icedcc_putc(ch)
  90#endif
  91
  92static void putstr(const char *ptr)
  93{
  94        char c;
  95
  96        while ((c = *ptr++) != '\0') {
  97                if (c == '\n')
  98                        putc('\r');
  99                putc(c);
 100        }
 101
 102        flush();
 103}
 104
 105/*
 106 * gzip declarations
 107 */
 108extern char input_data[];
 109extern char input_data_end[];
 110
 111unsigned char *output_data;
 112
 113unsigned long free_mem_ptr;
 114unsigned long free_mem_end_ptr;
 115
 116#ifndef arch_error
 117#define arch_error(x)
 118#endif
 119
 120void error(char *x)
 121{
 122        arch_error(x);
 123
 124        putstr("\n\n");
 125        putstr(x);
 126        putstr("\n\n -- System halted");
 127
 128        while(1);       /* Halt */
 129}
 130
 131asmlinkage void __div0(void)
 132{
 133        error("Attempting division by 0!");
 134}
 135
 136extern int do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x));
 137
 138
 139void
 140decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p,
 141                unsigned long free_mem_ptr_end_p,
 142                int arch_id)
 143{
 144        int ret;
 145
 146        output_data             = (unsigned char *)output_start;
 147        free_mem_ptr            = free_mem_ptr_p;
 148        free_mem_end_ptr        = free_mem_ptr_end_p;
 149        __machine_arch_type     = arch_id;
 150
 151        arch_decomp_setup();
 152
 153        putstr("Uncompressing Linux...");
 154        ret = do_decompress(input_data, input_data_end - input_data,
 155                            output_data, error);
 156        if (ret)
 157                error("decompressor returned an error");
 158        else
 159                putstr(" done, booting the kernel.\n");
 160}
 161