/* * linux/boot/head.S * * Copyright (C) 1991, 1992, 1993 Linus Torvalds */ /* * head.S contains the 32-bit startup code. * * NOTE!!! Startup happens at absolute address 0x00001000, which is also where * the page directory will exist. The startup code will be overwritten by * the page directory. [According to comments etc elsewhere on a compressed * kernel it will end up at 0x1000 + 1Mb I hope so as I assume this. - AC] * * In SMP mode we keep this page safe. Really we ought to shuffle things and * put the trampoline here. - AC. An SMP trampoline enters with %cx holding * the stack base. * * Page 0 is deliberately kept safe, since System Management Mode code in * laptops may need to access the BIOS data stored there. This is also * useful for future device drivers that either access the BIOS via VM86 * mode. */ /* * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996 */ .text #define __ASSEMBLY__ #include #include #include .globl startup_32 startup_32: cld cli movl $(__KERNEL_DS),%eax mov %ax,%ds mov %ax,%es mov %ax,%fs mov %ax,%gs #ifdef __SMP__ orw %bx,%bx # What state are we in BX=1 for SMP # 0 for boot jz 2f # Initial boot /* * We are trampolining an SMP processor */ mov %ax,%ss xorl %eax,%eax # Back to 0 mov %cx,%ax # SP low 16 bits movl %eax,%esp pushl 0 # Clear NT popfl ljmp $(__KERNEL_CS), $0x100000 # Into C and sanity 2: #endif lss SYMBOL_NAME(stack_start),%esp xorl %eax,%eax 1: incl %eax # check that A20 really IS enabled movl %eax,0x000000 # loop forever if it isn't cmpl %eax,0x100000 je 1b /* * Initialize eflags. Some BIOS's leave bits like NT set. This would * confuse the debugger if this code is traced. * XXX - best to initialize before switching to protected mode. */ pushl $0 popfl /* * Clear BSS */ xorl %eax,%eax movl $ SYMBOL_NAME(_edata),%edi movl $ SYMBOL_NAME(_end),%ecx subl %edi,%ecx cld rep stosb /* * Do the decompression, and jump to the new kernel.. */ subl $16,%esp # place for structure on the stack pushl %esp # address of structure as first arg call SYMBOL_NAME(decompress_kernel) orl %eax,%eax jnz 3f xorl %ebx,%ebx ljmp $(__KERNEL_CS), $0x100000 /* * We come here, if we were loaded high. * We need to move the move-in-place routine down to 0x1000 * and then start it with the buffer addresses in registers, * which we got from the stack. */ 3: movl $move_routine_start,%esi movl $0x1000,%edi movl $move_routine_end,%ecx subl %esi,%ecx cld rep movsb popl %esi # discard the address popl %esi # low_buffer_start popl %ecx # lcount popl %edx # high_buffer_start popl %eax # hcount movl $0x100000,%edi cli # make sure we don't get interrupted ljmp $(__KERNEL_CS), $0x1000 # and jump to the move routine /* * Routine (template) for moving the decompressed kernel in place, * if we were high loaded. This _must_ PIC-code ! */ move_routine_start: rep movsb movl %edx,%esi movl %eax,%ecx # NOTE: rep movsb won't move if %ecx == 0 rep movsb xorl %ebx,%ebx /* * Well, the kernel relies on %esp pointing into low mem, * with the decompressor loaded high this is no longer true, * so we set esp here. */ mov $0x90000,%esp ljmp $(__KERNEL_CS), $0x100000 move_routine_end: