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#ifdef CONFIG_EFI_STUB 36 jmp preferred_addr 37 38 /* 39 * We don't need the return address, so set up the stack so 40 * efi_main() can find its arguments. 41 */ 42ENTRY(efi_pe_entry) 43 add $0x4, %esp 44 45 call 1f 461: popl %esi 47 subl $1b, %esi 48 49 popl %ecx 50 movl %ecx, efi32_config(%esi) /* Handle */ 51 popl %ecx 52 movl %ecx, efi32_config+8(%esi) /* EFI System table pointer */ 53 54 /* Relocate efi_config->call() */ 55 leal efi32_config(%esi), %eax 56 add %esi, 88(%eax) 57 pushl %eax 58 59 call make_boot_params 60 cmpl $0, %eax 61 je fail 62 movl %esi, BP_code32_start(%eax) 63 popl %ecx 64 pushl %eax 65 pushl %ecx 66 jmp 2f /* Skip efi_config initialization */ 67 68ENTRY(efi32_stub_entry) 69 add $0x4, %esp 70 popl %ecx 71 popl %edx 72 73 call 1f 741: popl %esi 75 subl $1b, %esi 76 77 movl %ecx, efi32_config(%esi) /* Handle */ 78 movl %edx, efi32_config+8(%esi) /* EFI System table pointer */ 79 80 /* Relocate efi_config->call() */ 81 leal efi32_config(%esi), %eax 82 add %esi, 88(%eax) 83 pushl %eax 842: 85 call efi_main 86 cmpl $0, %eax 87 movl %eax, %esi 88 jne 2f 89fail: 90 /* EFI init failed, so hang. */ 91 hlt 92 jmp fail 932: 94 movl BP_code32_start(%esi), %eax 95 leal preferred_addr(%eax), %eax 96 jmp *%eax 97 98preferred_addr: 99#endif 100 cld 101 /* 102 * Test KEEP_SEGMENTS flag to see if the bootloader is asking 103 * us to not reload segments 104 */ 105 testb $(1<<6), BP_loadflags(%esi) 106 jnz 1f 107 108 cli 109 movl $__BOOT_DS, %eax 110 movl %eax, %ds 111 movl %eax, %es 112 movl %eax, %fs 113 movl %eax, %gs 114 movl %eax, %ss 1151: 116 117/* 118 * Calculate the delta between where we were compiled to run 119 * at and where we were actually loaded at. This can only be done 120 * with a short local call on x86. Nothing else will tell us what 121 * address we are running at. The reserved chunk of the real-mode 122 * data at 0x1e4 (defined as a scratch field) are used as the stack 123 * for this calculation. Only 4 bytes are needed. 124 */ 125 leal (BP_scratch+4)(%esi), %esp 126 call 1f 1271: popl %ebp 128 subl $1b, %ebp 129 130/* 131 * %ebp contains the address we are loaded at by the boot loader and %ebx 132 * contains the address where we should move the kernel image temporarily 133 * for safe in-place decompression. 134 */ 135 136#ifdef CONFIG_RELOCATABLE 137 movl %ebp, %ebx 138 movl BP_kernel_alignment(%esi), %eax 139 decl %eax 140 addl %eax, %ebx 141 notl %eax 142 andl %eax, %ebx 143 cmpl $LOAD_PHYSICAL_ADDR, %ebx 144 jge 1f 145#endif 146 movl $LOAD_PHYSICAL_ADDR, %ebx 1471: 148 149 /* Target address to relocate to for decompression */ 150 addl $z_extract_offset, %ebx 151 152 /* Set up the stack */ 153 leal boot_stack_end(%ebx), %esp 154 155 /* Zero EFLAGS */ 156 pushl $0 157 popfl 158 159/* 160 * Copy the compressed kernel to the end of our buffer 161 * where decompression in place becomes safe. 162 */ 163 pushl %esi 164 leal (_bss-4)(%ebp), %esi 165 leal (_bss-4)(%ebx), %edi 166 movl $(_bss - startup_32), %ecx 167 shrl $2, %ecx 168 std 169 rep movsl 170 cld 171 popl %esi 172 173/* 174 * Jump to the relocated address. 175 */ 176 leal relocated(%ebx), %eax 177 jmp *%eax 178ENDPROC(startup_32) 179 180 .text 181relocated: 182 183/* 184 * Clear BSS (stack is currently empty) 185 */ 186 xorl %eax, %eax 187 leal _bss(%ebx), %edi 188 leal _ebss(%ebx), %ecx 189 subl %edi, %ecx 190 shrl $2, %ecx 191 rep stosl 192 193/* 194 * Adjust our own GOT 195 */ 196 leal _got(%ebx), %edx 197 leal _egot(%ebx), %ecx 1981: 199 cmpl %ecx, %edx 200 jae 2f 201 addl %ebx, (%edx) 202 addl $4, %edx 203 jmp 1b 2042: 205 206/* 207 * Do the decompression, and jump to the new kernel.. 208 */ 209 /* push arguments for decompress_kernel: */ 210 pushl $z_output_len /* decompressed length */ 211 leal z_extract_offset_negative(%ebx), %ebp 212 pushl %ebp /* output address */ 213 pushl $z_input_len /* input_len */ 214 leal input_data(%ebx), %eax 215 pushl %eax /* input_data */ 216 leal boot_heap(%ebx), %eax 217 pushl %eax /* heap area */ 218 pushl %esi /* real mode pointer */ 219 call decompress_kernel /* returns kernel location in %eax */ 220 addl $24, %esp 221 222/* 223 * Jump to the decompressed kernel. 224 */ 225 xorl %ebx, %ebx 226 jmp *%eax 227 228#ifdef CONFIG_EFI_STUB 229 .data 230efi32_config: 231 .fill 11,8,0 232 .long efi_call_phys 233 .long 0 234 .byte 0 235#endif 236 237/* 238 * Stack and heap for uncompression 239 */ 240 .bss 241 .balign 4 242boot_heap: 243 .fill BOOT_HEAP_SIZE, 1, 0 244boot_stack: 245 .fill BOOT_STACK_SIZE, 1, 0 246boot_stack_end: 247