Path: blob/master/arch/x86/boot/compressed/head_32.S
10820 views
/*1* linux/boot/head.S2*3* Copyright (C) 1991, 1992, 1993 Linus Torvalds4*/56/*7* head.S contains the 32-bit startup code.8*9* NOTE!!! Startup happens at absolute address 0x00001000, which is also where10* the page directory will exist. The startup code will be overwritten by11* the page directory. [According to comments etc elsewhere on a compressed12* kernel it will end up at 0x1000 + 1Mb I hope so as I assume this. - AC]13*14* Page 0 is deliberately kept safe, since System Management Mode code in15* laptops may need to access the BIOS data stored there. This is also16* useful for future device drivers that either access the BIOS via VM8617* mode.18*/1920/*21* High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 199622*/23.text2425#include <linux/init.h>26#include <linux/linkage.h>27#include <asm/segment.h>28#include <asm/page_types.h>29#include <asm/boot.h>30#include <asm/asm-offsets.h>3132__HEAD33ENTRY(startup_32)34cld35/*36* Test KEEP_SEGMENTS flag to see if the bootloader is asking37* us to not reload segments38*/39testb $(1<<6), BP_loadflags(%esi)40jnz 1f4142cli43movl $__BOOT_DS, %eax44movl %eax, %ds45movl %eax, %es46movl %eax, %fs47movl %eax, %gs48movl %eax, %ss491:5051/*52* Calculate the delta between where we were compiled to run53* at and where we were actually loaded at. This can only be done54* with a short local call on x86. Nothing else will tell us what55* address we are running at. The reserved chunk of the real-mode56* data at 0x1e4 (defined as a scratch field) are used as the stack57* for this calculation. Only 4 bytes are needed.58*/59leal (BP_scratch+4)(%esi), %esp60call 1f611: popl %ebp62subl $1b, %ebp6364/*65* %ebp contains the address we are loaded at by the boot loader and %ebx66* contains the address where we should move the kernel image temporarily67* for safe in-place decompression.68*/6970#ifdef CONFIG_RELOCATABLE71movl %ebp, %ebx72movl BP_kernel_alignment(%esi), %eax73decl %eax74addl %eax, %ebx75notl %eax76andl %eax, %ebx77#else78movl $LOAD_PHYSICAL_ADDR, %ebx79#endif8081/* Target address to relocate to for decompression */82addl $z_extract_offset, %ebx8384/* Set up the stack */85leal boot_stack_end(%ebx), %esp8687/* Zero EFLAGS */88pushl $089popfl9091/*92* Copy the compressed kernel to the end of our buffer93* where decompression in place becomes safe.94*/95pushl %esi96leal (_bss-4)(%ebp), %esi97leal (_bss-4)(%ebx), %edi98movl $(_bss - startup_32), %ecx99shrl $2, %ecx100std101rep movsl102cld103popl %esi104105/*106* Jump to the relocated address.107*/108leal relocated(%ebx), %eax109jmp *%eax110ENDPROC(startup_32)111112.text113relocated:114115/*116* Clear BSS (stack is currently empty)117*/118xorl %eax, %eax119leal _bss(%ebx), %edi120leal _ebss(%ebx), %ecx121subl %edi, %ecx122shrl $2, %ecx123rep stosl124125/*126* Adjust our own GOT127*/128leal _got(%ebx), %edx129leal _egot(%ebx), %ecx1301:131cmpl %ecx, %edx132jae 2f133addl %ebx, (%edx)134addl $4, %edx135jmp 1b1362:137138/*139* Do the decompression, and jump to the new kernel..140*/141leal z_extract_offset_negative(%ebx), %ebp142/* push arguments for decompress_kernel: */143pushl %ebp /* output address */144pushl $z_input_len /* input_len */145leal input_data(%ebx), %eax146pushl %eax /* input_data */147leal boot_heap(%ebx), %eax148pushl %eax /* heap area */149pushl %esi /* real mode pointer */150call decompress_kernel151addl $20, %esp152153#if CONFIG_RELOCATABLE154/*155* Find the address of the relocations.156*/157leal z_output_len(%ebp), %edi158159/*160* Calculate the delta between where vmlinux was compiled to run161* and where it was actually loaded.162*/163movl %ebp, %ebx164subl $LOAD_PHYSICAL_ADDR, %ebx165jz 2f /* Nothing to be done if loaded at compiled addr. */166/*167* Process relocations.168*/1691701: subl $4, %edi171movl (%edi), %ecx172testl %ecx, %ecx173jz 2f174addl %ebx, -__PAGE_OFFSET(%ebx, %ecx)175jmp 1b1762:177#endif178179/*180* Jump to the decompressed kernel.181*/182xorl %ebx, %ebx183jmp *%ebp184185/*186* Stack and heap for uncompression187*/188.bss189.balign 4190boot_heap:191.fill BOOT_HEAP_SIZE, 1, 0192boot_stack:193.fill BOOT_STACK_SIZE, 1, 0194boot_stack_end:195196197