root/arch/x86/boot/compressed/head_32.S

/* [<][>][^][v][top][bottom][index][help] */
   1 /* SPDX-License-Identifier: GPL-2.0 */
   2 /*
   3  *  linux/boot/head.S
   4  *
   5  *  Copyright (C) 1991, 1992, 1993  Linus Torvalds
   6  */
   7 
   8 /*
   9  *  head.S contains the 32-bit startup code.
  10  *
  11  * NOTE!!! Startup happens at absolute address 0x00001000, which is also where
  12  * the page directory will exist. The startup code will be overwritten by
  13  * the page directory. [According to comments etc elsewhere on a compressed
  14  * kernel it will end up at 0x1000 + 1Mb I hope so as I assume this. - AC]
  15  *
  16  * Page 0 is deliberately kept safe, since System Management Mode code in
  17  * laptops may need to access the BIOS data stored there.  This is also
  18  * useful for future device drivers that either access the BIOS via VM86
  19  * mode.
  20  */
  21 
  22 /*
  23  * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
  24  */
  25         .text
  26 
  27 #include <linux/init.h>
  28 #include <linux/linkage.h>
  29 #include <asm/segment.h>
  30 #include <asm/page_types.h>
  31 #include <asm/boot.h>
  32 #include <asm/asm-offsets.h>
  33 #include <asm/bootparam.h>
  34 
  35 /*
  36  * The 32-bit x86 assembler in binutils 2.26 will generate R_386_GOT32X
  37  * relocation to get the symbol address in PIC.  When the compressed x86
  38  * kernel isn't built as PIC, the linker optimizes R_386_GOT32X
  39  * relocations to their fixed symbol addresses.  However, when the
  40  * compressed x86 kernel is loaded at a different address, it leads
  41  * to the following load failure:
  42  *
  43  *   Failed to allocate space for phdrs
  44  *
  45  * during the decompression stage.
  46  *
  47  * If the compressed x86 kernel is relocatable at run-time, it should be
  48  * compiled with -fPIE, instead of -fPIC, if possible and should be built as
  49  * Position Independent Executable (PIE) so that linker won't optimize
  50  * R_386_GOT32X relocation to its fixed symbol address.  Older
  51  * linkers generate R_386_32 relocations against locally defined symbols,
  52  * _bss, _ebss, _got and _egot, in PIE.  It isn't wrong, just less
  53  * optimal than R_386_RELATIVE.  But the x86 kernel fails to properly handle
  54  * R_386_32 relocations when relocating the kernel.  To generate
  55  * R_386_RELATIVE relocations, we mark _bss, _ebss, _got and _egot as
  56  * hidden:
  57  */
  58         .hidden _bss
  59         .hidden _ebss
  60         .hidden _got
  61         .hidden _egot
  62 
  63         __HEAD
  64 ENTRY(startup_32)
  65         cld
  66         /*
  67          * Test KEEP_SEGMENTS flag to see if the bootloader is asking
  68          * us to not reload segments
  69          */
  70         testb   $KEEP_SEGMENTS, BP_loadflags(%esi)
  71         jnz     1f
  72 
  73         cli
  74         movl    $__BOOT_DS, %eax
  75         movl    %eax, %ds
  76         movl    %eax, %es
  77         movl    %eax, %fs
  78         movl    %eax, %gs
  79         movl    %eax, %ss
  80 1:
  81 
  82 /*
  83  * Calculate the delta between where we were compiled to run
  84  * at and where we were actually loaded at.  This can only be done
  85  * with a short local call on x86.  Nothing  else will tell us what
  86  * address we are running at.  The reserved chunk of the real-mode
  87  * data at 0x1e4 (defined as a scratch field) are used as the stack
  88  * for this calculation. Only 4 bytes are needed.
  89  */
  90         leal    (BP_scratch+4)(%esi), %esp
  91         call    1f
  92 1:      popl    %ebp
  93         subl    $1b, %ebp
  94 
  95 /*
  96  * %ebp contains the address we are loaded at by the boot loader and %ebx
  97  * contains the address where we should move the kernel image temporarily
  98  * for safe in-place decompression.
  99  */
 100 
 101 #ifdef CONFIG_RELOCATABLE
 102         movl    %ebp, %ebx
 103         movl    BP_kernel_alignment(%esi), %eax
 104         decl    %eax
 105         addl    %eax, %ebx
 106         notl    %eax
 107         andl    %eax, %ebx
 108         cmpl    $LOAD_PHYSICAL_ADDR, %ebx
 109         jae     1f
 110 #endif
 111         movl    $LOAD_PHYSICAL_ADDR, %ebx
 112 1:
 113 
 114         /* Target address to relocate to for decompression */
 115         movl    BP_init_size(%esi), %eax
 116         subl    $_end, %eax
 117         addl    %eax, %ebx
 118 
 119         /* Set up the stack */
 120         leal    boot_stack_end(%ebx), %esp
 121 
 122         /* Zero EFLAGS */
 123         pushl   $0
 124         popfl
 125 
 126 /*
 127  * Copy the compressed kernel to the end of our buffer
 128  * where decompression in place becomes safe.
 129  */
 130         pushl   %esi
 131         leal    (_bss-4)(%ebp), %esi
 132         leal    (_bss-4)(%ebx), %edi
 133         movl    $(_bss - startup_32), %ecx
 134         shrl    $2, %ecx
 135         std
 136         rep     movsl
 137         cld
 138         popl    %esi
 139 
 140 /*
 141  * Jump to the relocated address.
 142  */
 143         leal    .Lrelocated(%ebx), %eax
 144         jmp     *%eax
 145 ENDPROC(startup_32)
 146 
 147 #ifdef CONFIG_EFI_STUB
 148 /*
 149  * We don't need the return address, so set up the stack so efi_main() can find
 150  * its arguments.
 151  */
 152 ENTRY(efi_pe_entry)
 153         add     $0x4, %esp
 154 
 155         call    1f
 156 1:      popl    %esi
 157         subl    $1b, %esi
 158 
 159         popl    %ecx
 160         movl    %ecx, efi32_config(%esi)        /* Handle */
 161         popl    %ecx
 162         movl    %ecx, efi32_config+8(%esi)      /* EFI System table pointer */
 163 
 164         /* Relocate efi_config->call() */
 165         leal    efi32_config(%esi), %eax
 166         add     %esi, 40(%eax)
 167         pushl   %eax
 168 
 169         call    make_boot_params
 170         cmpl    $0, %eax
 171         je      fail
 172         movl    %esi, BP_code32_start(%eax)
 173         popl    %ecx
 174         pushl   %eax
 175         pushl   %ecx
 176         jmp     2f              /* Skip efi_config initialization */
 177 ENDPROC(efi_pe_entry)
 178 
 179 ENTRY(efi32_stub_entry)
 180         add     $0x4, %esp
 181         popl    %ecx
 182         popl    %edx
 183 
 184         call    1f
 185 1:      popl    %esi
 186         subl    $1b, %esi
 187 
 188         movl    %ecx, efi32_config(%esi)        /* Handle */
 189         movl    %edx, efi32_config+8(%esi)      /* EFI System table pointer */
 190 
 191         /* Relocate efi_config->call() */
 192         leal    efi32_config(%esi), %eax
 193         add     %esi, 40(%eax)
 194         pushl   %eax
 195 2:
 196         call    efi_main
 197         cmpl    $0, %eax
 198         movl    %eax, %esi
 199         jne     2f
 200 fail:
 201         /* EFI init failed, so hang. */
 202         hlt
 203         jmp     fail
 204 2:
 205         movl    BP_code32_start(%esi), %eax
 206         leal    startup_32(%eax), %eax
 207         jmp     *%eax
 208 ENDPROC(efi32_stub_entry)
 209 #endif
 210 
 211         .text
 212 .Lrelocated:
 213 
 214 /*
 215  * Clear BSS (stack is currently empty)
 216  */
 217         xorl    %eax, %eax
 218         leal    _bss(%ebx), %edi
 219         leal    _ebss(%ebx), %ecx
 220         subl    %edi, %ecx
 221         shrl    $2, %ecx
 222         rep     stosl
 223 
 224 /*
 225  * Adjust our own GOT
 226  */
 227         leal    _got(%ebx), %edx
 228         leal    _egot(%ebx), %ecx
 229 1:
 230         cmpl    %ecx, %edx
 231         jae     2f
 232         addl    %ebx, (%edx)
 233         addl    $4, %edx
 234         jmp     1b
 235 2:
 236 
 237 /*
 238  * Do the extraction, and jump to the new kernel..
 239  */
 240                                 /* push arguments for extract_kernel: */
 241         pushl   $z_output_len   /* decompressed length, end of relocs */
 242 
 243         movl    BP_init_size(%esi), %eax
 244         subl    $_end, %eax
 245         movl    %ebx, %ebp
 246         subl    %eax, %ebp
 247         pushl   %ebp            /* output address */
 248 
 249         pushl   $z_input_len    /* input_len */
 250         leal    input_data(%ebx), %eax
 251         pushl   %eax            /* input_data */
 252         leal    boot_heap(%ebx), %eax
 253         pushl   %eax            /* heap area */
 254         pushl   %esi            /* real mode pointer */
 255         call    extract_kernel  /* returns kernel location in %eax */
 256         addl    $24, %esp
 257 
 258 /*
 259  * Jump to the extracted kernel.
 260  */
 261         xorl    %ebx, %ebx
 262         jmp     *%eax
 263 
 264 #ifdef CONFIG_EFI_STUB
 265         .data
 266 efi32_config:
 267         .fill 5,8,0
 268         .long efi_call_phys
 269         .long 0
 270         .byte 0
 271 #endif
 272 
 273 /*
 274  * Stack and heap for uncompression
 275  */
 276         .bss
 277         .balign 4
 278 boot_heap:
 279         .fill BOOT_HEAP_SIZE, 1, 0
 280 boot_stack:
 281         .fill BOOT_STACK_SIZE, 1, 0
 282 boot_stack_end:

/* [<][>][^][v][top][bottom][index][help] */