decompress_kernel - notro/rpi-firmware GitHub Wiki

Kernel decompression on Raspberry Pi

arch/arm/boot/compressed/head.S

/*
 * The C runtime environment should now be setup sufficiently.
 * Set up some pointers, and start decompressing.
 *   r4  = kernel execution address
 *   r7  = architecture ID
 *   r8  = atags pointer
 */
                mov     r0, r4
                mov     r1, sp                  @ malloc space above stack
                add     r2, sp, #0x10000        @ 64k max
                mov     r3, r7
                bl      decompress_kernel
                bl      cache_clean_flush
                bl      cache_off
                mov     r1, r7                  @ restore architecture number
                mov     r2, r8                  @ restore atags pointer

arch/arm/boot/compressed/misc.c

#include CONFIG_UNCOMPRESS_INCLUDE

static void putstr(const char *ptr)
{
        char c;

        while ((c = *ptr++) != '\0') {
                if (c == '\n')
                        putc('\r');
                putc(c);
        }

        flush();
}

void
decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p,
                unsigned long free_mem_ptr_end_p,
                int arch_id)
{
        int ret;

        __stack_chk_guard_setup();

        output_data             = (unsigned char *)output_start;
        free_mem_ptr            = free_mem_ptr_p;
        free_mem_end_ptr        = free_mem_ptr_end_p;
        __machine_arch_type     = arch_id;

        arch_decomp_setup();

        putstr("Uncompressing Linux...");
        ret = do_decompress(input_data, input_data_end - input_data,
                            output_data, error);
        if (ret)
                error("decompressor returned an error");
        else
                putstr(" done, booting the kernel.\n");
}

For gzip: lib/decompress_inflate.c

/* Included from initramfs et al code */
STATIC int INIT gunzip(unsigned char *buf, long len,
[...]

#define decompress gunzip

arch/arm/boot/compressed/decompress.c

#ifdef CONFIG_KERNEL_GZIP
#include "../../../../lib/decompress_inflate.c"
#endif

int do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x))
{
        return decompress(input, len, NULL, NULL, output, NULL, error);
}

Kernel low-level startup

arch/arm/kernel/head.S

 *  Kernel startup code for all 32-bit CPUs

#include "head-common.S"

arch/arm/kernel/head-common.S

        str     r9, [r4]                        @ Save processor ID
        str     r1, [r5]                        @ Save machine type
        str     r2, [r6]                        @ Save atags pointer
        cmp     r7, #0
        strne   r0, [r7]                        @ Save control register values
        b       start_kernel

start_kernel