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#define _LINUX_STRING_H_
  22
  23#include <linux/compiler.h>     /* for inline */
  24#include <linux/types.h>        /* for size_t */
  25#include <linux/stddef.h>       /* for NULL */
  26#include <linux/linkage.h>
  27#include <asm/string.h>
  28
  29#include <asm/unaligned.h>
  30
  31
  32static void putstr(const char *ptr);
  33extern void error(char *x);
  34
  35#include <mach/uncompress.h>
  36
  37#ifdef CONFIG_DEBUG_ICEDCC
  38
  39#ifdef CONFIG_CPU_V6
  40
  41static void icedcc_putc(int ch)
  42{
  43        int status, i = 0x4000000;
  44
  45        do {
  46                if (--i < 0)
  47                        return;
  48
  49                asm volatile ("mrc p14, 0, %0, c0, c1, 0" : "=r" (status));
  50        } while (status & (1 << 29));
  51
  52        asm("mcr p14, 0, %0, c0, c5, 0" : : "r" (ch));
  53}
  54
  55#elif defined(CONFIG_CPU_V7)
  56
  57static void icedcc_putc(int ch)
  58{
  59        asm(
  60        "wait:  mrc     p14, 0, pc, c0, c1, 0                   \n\
  61                bcs     wait                                    \n\
  62                mcr     p14, 0, %0, c0, c5, 0                   "
  63        : : "r" (ch));
  64}
  65
  66#elif defined(CONFIG_CPU_XSCALE)
  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, c14, c0, 0" : "=r" (status));
  77        } while (status & (1 << 28));
  78
  79        asm("mcr p14, 0, %0, c8, c0, 0" : : "r" (ch));
  80}
  81
  82#else
  83
  84static void icedcc_putc(int ch)
  85{
  86        int status, i = 0x4000000;
  87
  88        do {
  89                if (--i < 0)
  90                        return;
  91
  92                asm volatile ("mrc p14, 0, %0, c0, c0, 0" : "=r" (status));
  93        } while (status & 2);
  94
  95        asm("mcr p14, 0, %0, c1, c0, 0" : : "r" (ch));
  96}
  97
  98#endif
  99
 100#define putc(ch)        icedcc_putc(ch)
 101#endif
 102
 103static void putstr(const char *ptr)
 104{
 105        char c;
 106
 107        while ((c = *ptr++) != '\0') {
 108                if (c == '\n')
 109                        putc('\r');
 110                putc(c);
 111        }
 112
 113        flush();
 114}
 115
 116
 117void *memcpy(void *__dest, __const void *__src, size_t __n)
 118{
 119        int i = 0;
 120        unsigned char *d = (unsigned char *)__dest, *s = (unsigned char *)__src;
 121
 122        for (i = __n >> 3; i > 0; i--) {
 123                *d++ = *s++;
 124                *d++ = *s++;
 125                *d++ = *s++;
 126                *d++ = *s++;
 127                *d++ = *s++;
 128                *d++ = *s++;
 129                *d++ = *s++;
 130                *d++ = *s++;
 131        }
 132
 133        if (__n & 1 << 2) {
 134                *d++ = *s++;
 135                *d++ = *s++;
 136                *d++ = *s++;
 137                *d++ = *s++;
 138        }
 139
 140        if (__n & 1 << 1) {
 141                *d++ = *s++;
 142                *d++ = *s++;
 143        }
 144
 145        if (__n & 1)
 146                *d++ = *s++;
 147
 148        return __dest;
 149}
 150
 151/*
 152 * gzip delarations
 153 */
 154extern char input_data[];
 155extern char input_data_end[];
 156
 157unsigned char *output_data;
 158unsigned long output_ptr;
 159
 160unsigned long free_mem_ptr;
 161unsigned long free_mem_end_ptr;
 162
 163#ifndef arch_error
 164#define arch_error(x)
 165#endif
 166
 167void error(char *x)
 168{
 169        arch_error(x);
 170
 171        putstr("\n\n");
 172        putstr(x);
 173        putstr("\n\n -- System halted");
 174
 175        while(1);       /* Halt */
 176}
 177
 178asmlinkage void __div0(void)
 179{
 180        error("Attempting division by 0!");
 181}
 182
 183extern void do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x));
 184
 185
 186unsigned long
 187decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p,
 188                unsigned long free_mem_ptr_end_p,
 189                int arch_id)
 190{
 191        unsigned char *tmp;
 192
 193        output_data             = (unsigned char *)output_start;
 194        free_mem_ptr            = free_mem_ptr_p;
 195        free_mem_end_ptr        = free_mem_ptr_end_p;
 196        __machine_arch_type     = arch_id;
 197
 198        arch_decomp_setup();
 199
 200        tmp = (unsigned char *) (((unsigned long)input_data_end) - 4);
 201        output_ptr = get_unaligned_le32(tmp);
 202
 203        putstr("Uncompressing Linux...");
 204        do_decompress(input_data, input_data_end - input_data,
 205                        output_data, error);
 206        putstr(" done, booting the kernel.\n");
 207        return output_ptr;
 208}
 209