Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 | /* * linux/boot/head.S * * Copyright (C) 1991, 1992, 1993 Linus Torvalds * * $Id: head.S,v 1.3 2001/04/20 00:59:28 ak Exp $ */ /* * 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] * * 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 */ .code32 .text #include <linux/linkage.h> #include <asm/segment.h> .code32 .globl startup_32 startup_32: cld cli movl $(__KERNEL_DS),%eax movl %eax,%ds movl %eax,%es movl %eax,%fs movl %eax,%gs 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 movl %esp,%eax pushl %esi # real mode pointer as second arg pushl %eax # address of structure as first arg call SYMBOL_NAME(decompress_kernel) orl %eax,%eax jnz 3f addl $8,%esp 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 %esi,%ebx movl $move_routine_start,%esi movl $0x1000,%edi movl $move_routine_end,%ecx subl %esi,%ecx addl $3,%ecx shrl $2,%ecx cld rep movsl popl %esi # discard the address addl $4,%esp # real mode pointer 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: movl %ecx,%ebp shrl $2,%ecx rep movsl movl %ebp,%ecx andl $3,%ecx rep movsb movl %edx,%esi movl %eax,%ecx # NOTE: rep movsb won't move if %ecx == 0 addl $3,%ecx shrl $2,%ecx rep movsl movl %ebx,%esi # Restore setup pointer xorl %ebx,%ebx ljmp $(__KERNEL_CS), $0x100000 move_routine_end: /* Stack for uncompression */ .align 32 user_stack: .fill 4096,4,0 stack_start: .long user_stack+4096 .word __KERNEL_DS |