linux/arch/x86/boot/compressed/head_32.S
<<
>>
Prefs
   1/*
   2 *  linux/boot/head.S
   3 *
   4 *  Copyright (C) 1991, 1992, 1993  Linus Torvalds
   5 */
   6
   7/*
   8 *  head.S contains the 32-bit startup code.
   9 *
  10 * NOTE!!! Startup happens at absolute address 0x00001000, which is also where
  11 * the page directory will exist. The startup code will be overwritten by
  12 * the page directory. [According to comments etc elsewhere on a compressed
  13 * kernel it will end up at 0x1000 + 1Mb I hope so as I assume this. - AC]
  14 *
  15 * Page 0 is deliberately kept safe, since System Management Mode code in
  16 * laptops may need to access the BIOS data stored there.  This is also
  17 * useful for future device drivers that either access the BIOS via VM86
  18 * mode.
  19 */
  20
  21/*
  22 * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
  23 */
  24        .text
  25
  26#include <linux/init.h>
  27#include <linux/linkage.h>
  28#include <asm/segment.h>
  29#include <asm/page_types.h>
  30#include <asm/boot.h>
  31#include <asm/asm-offsets.h>
  32
  33        __HEAD
  34ENTRY(startup_32)
  35        cld
  36        /*
  37         * Test KEEP_SEGMENTS flag to see if the bootloader is asking
  38         * us to not reload segments
  39         */
  40        testb   $(1<<6), BP_loadflags(%esi)
  41        jnz     1f
  42
  43        cli
  44        movl    $__BOOT_DS, %eax
  45        movl    %eax, %ds
  46        movl    %eax, %es
  47        movl    %eax, %fs
  48        movl    %eax, %gs
  49        movl    %eax, %ss
  501:
  51
  52/*
  53 * Calculate the delta between where we were compiled to run
  54 * at and where we were actually loaded at.  This can only be done
  55 * with a short local call on x86.  Nothing  else will tell us what
  56 * address we are running at.  The reserved chunk of the real-mode
  57 * data at 0x1e4 (defined as a scratch field) are used as the stack
  58 * for this calculation. Only 4 bytes are needed.
  59 */
  60        leal    (BP_scratch+4)(%esi), %esp
  61        call    1f
  621:      popl    %ebp
  63        subl    $1b, %ebp
  64
  65/*
  66 * %ebp contains the address we are loaded at by the boot loader and %ebx
  67 * contains the address where we should move the kernel image temporarily
  68 * for safe in-place decompression.
  69 */
  70
  71#ifdef CONFIG_RELOCATABLE
  72        movl    %ebp, %ebx
  73        movl    BP_kernel_alignment(%esi), %eax
  74        decl    %eax
  75        addl    %eax, %ebx
  76        notl    %eax
  77        andl    %eax, %ebx
  78#else
  79        movl    $LOAD_PHYSICAL_ADDR, %ebx
  80#endif
  81
  82        /* Target address to relocate to for decompression */
  83        addl    $z_extract_offset, %ebx
  84
  85        /* Set up the stack */
  86        leal    boot_stack_end(%ebx), %esp
  87
  88        /* Zero EFLAGS */
  89        pushl   $0
  90        popfl
  91
  92/*
  93 * Copy the compressed kernel to the end of our buffer
  94 * where decompression in place becomes safe.
  95 */
  96        pushl   %esi
  97        leal    (_bss-4)(%ebp), %esi
  98        leal    (_bss-4)(%ebx), %edi
  99        movl    $(_bss - startup_32), %ecx
 100        shrl    $2, %ecx
 101        std
 102        rep     movsl
 103        cld
 104        popl    %esi
 105
 106/*
 107 * Jump to the relocated address.
 108 */
 109        leal    relocated(%ebx), %eax
 110        jmp     *%eax
 111ENDPROC(startup_32)
 112
 113        .text
 114relocated:
 115
 116/*
 117 * Clear BSS (stack is currently empty)
 118 */
 119        xorl    %eax, %eax
 120        leal    _bss(%ebx), %edi
 121        leal    _ebss(%ebx), %ecx
 122        subl    %edi, %ecx
 123        shrl    $2, %ecx
 124        rep     stosl
 125
 126/*
 127 * Do the decompression, and jump to the new kernel..
 128 */
 129        leal    z_extract_offset_negative(%ebx), %ebp
 130                                /* push arguments for decompress_kernel: */
 131        pushl   %ebp            /* output address */
 132        pushl   $z_input_len    /* input_len */
 133        leal    input_data(%ebx), %eax
 134        pushl   %eax            /* input_data */
 135        leal    boot_heap(%ebx), %eax
 136        pushl   %eax            /* heap area */
 137        pushl   %esi            /* real mode pointer */
 138        call    decompress_kernel
 139        addl    $20, %esp
 140
 141#if CONFIG_RELOCATABLE
 142/*
 143 * Find the address of the relocations.
 144 */
 145        leal    z_output_len(%ebp), %edi
 146
 147/*
 148 * Calculate the delta between where vmlinux was compiled to run
 149 * and where it was actually loaded.
 150 */
 151        movl    %ebp, %ebx
 152        subl    $LOAD_PHYSICAL_ADDR, %ebx
 153        jz      2f      /* Nothing to be done if loaded at compiled addr. */
 154/*
 155 * Process relocations.
 156 */
 157
 1581:      subl    $4, %edi
 159        movl    (%edi), %ecx
 160        testl   %ecx, %ecx
 161        jz      2f
 162        addl    %ebx, -__PAGE_OFFSET(%ebx, %ecx)
 163        jmp     1b
 1642:
 165#endif
 166
 167/*
 168 * Jump to the decompressed kernel.
 169 */
 170        xorl    %ebx, %ebx
 171        jmp     *%ebp
 172
 173/*
 174 * Stack and heap for uncompression
 175 */
 176        .bss
 177        .balign 4
 178boot_heap:
 179        .fill BOOT_HEAP_SIZE, 1, 0
 180boot_stack:
 181        .fill BOOT_STACK_SIZE, 1, 0
 182boot_stack_end:
 183