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/linkage.h>
  27#include <asm/segment.h>
  28#include <asm/page.h>
  29#include <asm/boot.h>
  30#include <asm/asm-offsets.h>
  31
  32.section ".text.head","ax",@progbits
  33        .globl startup_32
  34
  35startup_32:
  36        cld
  37        /* test KEEP_SEGMENTS flag to see if the bootloader is asking
  38         * us to not reload segments */
  39        testb $(1<<6), BP_loadflags(%esi)
  40        jnz 1f
  41
  42        cli
  43        movl $(__BOOT_DS),%eax
  44        movl %eax,%ds
  45        movl %eax,%es
  46        movl %eax,%fs
  47        movl %eax,%gs
  48        movl %eax,%ss
  491:
  50
  51/* Calculate the delta between where we were compiled to run
  52 * at and where we were actually loaded at.  This can only be done
  53 * with a short local call on x86.  Nothing  else will tell us what
  54 * address we are running at.  The reserved chunk of the real-mode
  55 * data at 0x1e4 (defined as a scratch field) are used as the stack
  56 * for this calculation. Only 4 bytes are needed.
  57 */
  58        leal (0x1e4+4)(%esi), %esp
  59        call 1f
  601:      popl %ebp
  61        subl $1b, %ebp
  62
  63/* %ebp contains the address we are loaded at by the boot loader and %ebx
  64 * contains the address where we should move the kernel image temporarily
  65 * for safe in-place decompression.
  66 */
  67
  68#ifdef CONFIG_RELOCATABLE
  69        movl    %ebp, %ebx
  70        addl    $(CONFIG_PHYSICAL_ALIGN - 1), %ebx
  71        andl    $(~(CONFIG_PHYSICAL_ALIGN - 1)), %ebx
  72#else
  73        movl $LOAD_PHYSICAL_ADDR, %ebx
  74#endif
  75
  76        /* Replace the compressed data size with the uncompressed size */
  77        subl input_len(%ebp), %ebx
  78        movl output_len(%ebp), %eax
  79        addl %eax, %ebx
  80        /* Add 8 bytes for every 32K input block */
  81        shrl $12, %eax
  82        addl %eax, %ebx
  83        /* Add 32K + 18 bytes of extra slack */
  84        addl $(32768 + 18), %ebx
  85        /* Align on a 4K boundary */
  86        addl $4095, %ebx
  87        andl $~4095, %ebx
  88
  89/* Copy the compressed kernel to the end of our buffer
  90 * where decompression in place becomes safe.
  91 */
  92        pushl %esi
  93        leal _end(%ebp), %esi
  94        leal _end(%ebx), %edi
  95        movl $(_end - startup_32), %ecx
  96        std
  97        rep
  98        movsb
  99        cld
 100        popl %esi
 101
 102/* Compute the kernel start address.
 103 */
 104#ifdef CONFIG_RELOCATABLE
 105        addl    $(CONFIG_PHYSICAL_ALIGN - 1), %ebp
 106        andl    $(~(CONFIG_PHYSICAL_ALIGN - 1)), %ebp
 107#else
 108        movl    $LOAD_PHYSICAL_ADDR, %ebp
 109#endif
 110
 111/*
 112 * Jump to the relocated address.
 113 */
 114        leal relocated(%ebx), %eax
 115        jmp *%eax
 116.section ".text"
 117relocated:
 118
 119/*
 120 * Clear BSS
 121 */
 122        xorl %eax,%eax
 123        leal _edata(%ebx),%edi
 124        leal _end(%ebx), %ecx
 125        subl %edi,%ecx
 126        cld
 127        rep
 128        stosb
 129
 130/*
 131 * Setup the stack for the decompressor
 132 */
 133        leal stack_end(%ebx), %esp
 134
 135/*
 136 * Do the decompression, and jump to the new kernel..
 137 */
 138        movl output_len(%ebx), %eax
 139        pushl %eax
 140        pushl %ebp      # output address
 141        movl input_len(%ebx), %eax
 142        pushl %eax      # input_len
 143        leal input_data(%ebx), %eax
 144        pushl %eax      # input_data
 145        leal _end(%ebx), %eax
 146        pushl %eax      # end of the image as third argument
 147        pushl %esi      # real mode pointer as second arg
 148        call decompress_kernel
 149        addl $20, %esp
 150        popl %ecx
 151
 152#if CONFIG_RELOCATABLE
 153/* Find the address of the relocations.
 154 */
 155        movl %ebp, %edi
 156        addl %ecx, %edi
 157
 158/* Calculate the delta between where vmlinux was compiled to run
 159 * and where it was actually loaded.
 160 */
 161        movl %ebp, %ebx
 162        subl $LOAD_PHYSICAL_ADDR, %ebx
 163        jz   2f         /* Nothing to be done if loaded at compiled addr. */
 164/*
 165 * Process relocations.
 166 */
 167
 1681:      subl $4, %edi
 169        movl 0(%edi), %ecx
 170        testl %ecx, %ecx
 171        jz 2f
 172        addl %ebx, -__PAGE_OFFSET(%ebx, %ecx)
 173        jmp 1b
 1742:
 175#endif
 176
 177/*
 178 * Jump to the decompressed kernel.
 179 */
 180        xorl %ebx,%ebx
 181        jmp *%ebp
 182
 183.bss
 184.balign 4
 185stack:
 186        .fill 4096, 1, 0
 187stack_end:
 188
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.