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 .balign 0x10 39 /* 40 * We don't need the return address, so set up the stack so 41 * efi_main() can find its arugments. 42 */ 43 add $0x4, %esp 44 45 call efi_main 46 cmpl $0, %eax 47 movl %eax, %esi 48 jne 2f 491: 50 /* EFI init failed, so hang. */ 51 hlt 52 jmp 1b 532: 54 call 3f 553: 56 popl %eax 57 subl $3b, %eax 58 subl BP_pref_address(%esi), %eax 59 add BP_code32_start(%esi), %eax 60 leal preferred_addr(%eax), %eax 61 jmp *%eax 62 63preferred_addr: 64#endif 65 cld 66 /* 67 * Test KEEP_SEGMENTS flag to see if the bootloader is asking 68 * us to not reload segments 69 */ 70 testb $(1<<6), 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 801: 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 921: 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#else 109 movl $LOAD_PHYSICAL_ADDR, %ebx 110#endif 111 112 /* Target address to relocate to for decompression */ 113 addl $z_extract_offset, %ebx 114 115 /* Set up the stack */ 116 leal boot_stack_end(%ebx), %esp 117 118 /* Zero EFLAGS */ 119 pushl $0 120 popfl 121 122/* 123 * Copy the compressed kernel to the end of our buffer 124 * where decompression in place becomes safe. 125 */ 126 pushl %esi 127 leal (_bss-4)(%ebp), %esi 128 leal (_bss-4)(%ebx), %edi 129 movl $(_bss - startup_32), %ecx 130 shrl $2, %ecx 131 std 132 rep movsl 133 cld 134 popl %esi 135 136/* 137 * Jump to the relocated address. 138 */ 139 leal relocated(%ebx), %eax 140 jmp *%eax 141ENDPROC(startup_32) 142 143 .text 144relocated: 145 146/* 147 * Clear BSS (stack is currently empty) 148 */ 149 xorl %eax, %eax 150 leal _bss(%ebx), %edi 151 leal _ebss(%ebx), %ecx 152 subl %edi, %ecx 153 shrl $2, %ecx 154 rep stosl 155 156/* 157 * Adjust our own GOT 158 */ 159 leal _got(%ebx), %edx 160 leal _egot(%ebx), %ecx 1611: 162 cmpl %ecx, %edx 163 jae 2f 164 addl %ebx, (%edx) 165 addl $4, %edx 166 jmp 1b 1672: 168 169/* 170 * Do the decompression, and jump to the new kernel.. 171 */ 172 leal z_extract_offset_negative(%ebx), %ebp 173 /* push arguments for decompress_kernel: */ 174 pushl %ebp /* output address */ 175 pushl $z_input_len /* input_len */ 176 leal input_data(%ebx), %eax 177 pushl %eax /* input_data */ 178 leal boot_heap(%ebx), %eax 179 pushl %eax /* heap area */ 180 pushl %esi /* real mode pointer */ 181 call decompress_kernel 182 addl $20, %esp 183 184#if CONFIG_RELOCATABLE 185/* 186 * Find the address of the relocations. 187 */ 188 leal z_output_len(%ebp), %edi 189 190/* 191 * Calculate the delta between where vmlinux was compiled to run 192 * and where it was actually loaded. 193 */ 194 movl %ebp, %ebx 195 subl $LOAD_PHYSICAL_ADDR, %ebx 196 jz 2f /* Nothing to be done if loaded at compiled addr. */ 197/* 198 * Process relocations. 199 */ 200 2011: subl $4, %edi 202 movl (%edi), %ecx 203 testl %ecx, %ecx 204 jz 2f 205 addl %ebx, -__PAGE_OFFSET(%ebx, %ecx) 206 jmp 1b 2072: 208#endif 209 210/* 211 * Jump to the decompressed kernel. 212 */ 213 xorl %ebx, %ebx 214 jmp *%ebp 215 216/* 217 * Stack and heap for uncompression 218 */ 219 .bss 220 .balign 4 221boot_heap: 222 .fill BOOT_HEAP_SIZE, 1, 0 223boot_stack: 224 .fill BOOT_STACK_SIZE, 1, 0 225boot_stack_end: 226