1 /* 1 /* 2 * Startup glue code to uncompress the kernel !! 2 * linux/boot/head.S 3 * 3 * 4 * (C) 2017 Helge Deller <deller@gmx.de> !! 4 * Copyright (C) 1991, 1992, 1993 Linus Torvalds 5 */ 5 */ 6 6 7 #include <linux/init.h> !! 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 8 #include <linux/linkage.h> 26 #include <linux/linkage.h> 9 #include <asm/asm-offsets.h> !! 27 #include <asm/segment.h> 10 #include <asm/page.h> << 11 #include <asm/psw.h> << 12 #include <asm/pdc.h> << 13 #include <asm/assembly.h> << 14 #include "sizes.h" << 15 << 16 #define BOOTADDR(x) (x) << 17 << 18 #ifndef CONFIG_64BIT << 19 .import $global$ /* for << 20 #endif /*!CONFIG_64BIT*/ << 21 << 22 __HEAD << 23 << 24 ENTRY(startup) << 25 .level PA_ASM_LEVEL << 26 << 27 #define PSW_W_SM 0x200 << 28 #define PSW_W_BIT 36 << 29 << 30 ;! nuke the W bit, saving original val << 31 .level 2.0 << 32 rsm PSW_W_SM, %r1 << 33 << 34 .level 1.1 << 35 extrw,u %r1, PSW_W_BIT-32, 1, %r1 << 36 copy %r1, %arg0 << 37 << 38 /* Make sure sr4-sr7 are set to zero f << 39 mtsp %r0,%sr4 << 40 mtsp %r0,%sr5 << 41 mtsp %r0,%sr6 << 42 mtsp %r0,%sr7 << 43 << 44 /* Clear BSS */ << 45 << 46 .import _bss,data << 47 .import _ebss,data << 48 << 49 load32 BOOTADDR(_bss),%r3 << 50 load32 BOOTADDR(_ebss),%r4 << 51 ldo FRAME_SIZE(%r4),%sp /* sta << 52 $bss_loop: << 53 cmpb,<<,n %r3,%r4,$bss_loop << 54 stw,ma %r0,4(%r3) << 55 << 56 /* Initialize the global data pointer << 57 loadgp << 58 << 59 /* arg0..arg4 were set by palo. */ << 60 copy %arg1, %r6 /* com << 61 copy %arg2, %r7 /* rd- << 62 copy %arg3, %r8 /* rd- << 63 load32 BOOTADDR(decompress_kernel),%r << 64 << 65 #ifdef CONFIG_64BIT << 66 .level PA_ASM_LEVEL << 67 ssm PSW_W_SM, %r0 /* set << 68 depdi 0, 31, 32, %r3 << 69 #endif << 70 load32 BOOTADDR(startup_continue), %r << 71 bv,n 0(%r3) << 72 << 73 startup_continue: << 74 #ifdef CONFIG_64BIT << 75 .level PA_ASM_LEVEL << 76 rsm PSW_W_SM, %r0 /* cle << 77 #endif << 78 << 79 load32 KERNEL_BINARY_TEXT_START, %arg << 80 copy %r6, %arg1 /* com << 81 copy %r7, %arg2 /* rd- << 82 copy %r8, %arg3 /* rd- << 83 28 84 bv,n 0(%ret0) !! 29 .globl startup_32 85 END(startup) !! 30 >> 31 startup_32: >> 32 cld >> 33 cli >> 34 movl $(__KERNEL_DS),%eax >> 35 movl %eax,%ds >> 36 movl %eax,%es >> 37 movl %eax,%fs >> 38 movl %eax,%gs >> 39 >> 40 lss SYMBOL_NAME(stack_start),%esp >> 41 xorl %eax,%eax >> 42 1: incl %eax # check that A20 really IS enabled >> 43 movl %eax,0x000000 # loop forever if it isn't >> 44 cmpl %eax,0x100000 >> 45 je 1b >> 46 >> 47 /* >> 48 * Initialize eflags. Some BIOS's leave bits like NT set. This would >> 49 * confuse the debugger if this code is traced. >> 50 * XXX - best to initialize before switching to protected mode. >> 51 */ >> 52 pushl $0 >> 53 popfl >> 54 /* >> 55 * Clear BSS >> 56 */ >> 57 xorl %eax,%eax >> 58 movl $ SYMBOL_NAME(_edata),%edi >> 59 movl $ SYMBOL_NAME(_end),%ecx >> 60 subl %edi,%ecx >> 61 cld >> 62 rep >> 63 stosb >> 64 /* >> 65 * Do the decompression, and jump to the new kernel.. >> 66 */ >> 67 subl $16,%esp # place for structure on the stack >> 68 movl %esp,%eax >> 69 pushl %esi # real mode pointer as second arg >> 70 pushl %eax # address of structure as first arg >> 71 call SYMBOL_NAME(decompress_kernel) >> 72 orl %eax,%eax >> 73 jnz 3f >> 74 popl %esi # discard address >> 75 popl %esi # real mode pointer >> 76 xorl %ebx,%ebx >> 77 ljmp $(__KERNEL_CS), $0x100000 >> 78 >> 79 /* >> 80 * We come here, if we were loaded high. >> 81 * We need to move the move-in-place routine down to 0x1000 >> 82 * and then start it with the buffer addresses in registers, >> 83 * which we got from the stack. >> 84 */ >> 85 3: >> 86 movl $move_routine_start,%esi >> 87 movl $0x1000,%edi >> 88 movl $move_routine_end,%ecx >> 89 subl %esi,%ecx >> 90 addl $3,%ecx >> 91 shrl $2,%ecx >> 92 cld >> 93 rep >> 94 movsl >> 95 >> 96 popl %esi # discard the address >> 97 popl %ebx # real mode pointer >> 98 popl %esi # low_buffer_start >> 99 popl %ecx # lcount >> 100 popl %edx # high_buffer_start >> 101 popl %eax # hcount >> 102 movl $0x100000,%edi >> 103 cli # make sure we don't get interrupted >> 104 ljmp $(__KERNEL_CS), $0x1000 # and jump to the move routine >> 105 >> 106 /* >> 107 * Routine (template) for moving the decompressed kernel in place, >> 108 * if we were high loaded. This _must_ PIC-code ! >> 109 */ >> 110 move_routine_start: >> 111 movl %ecx,%ebp >> 112 shrl $2,%ecx >> 113 rep >> 114 movsl >> 115 movl %ebp,%ecx >> 116 andl $3,%ecx >> 117 rep >> 118 movsb >> 119 movl %edx,%esi >> 120 movl %eax,%ecx # NOTE: rep movsb won't move if %ecx == 0 >> 121 addl $3,%ecx >> 122 shrl $2,%ecx >> 123 rep >> 124 movsl >> 125 movl %ebx,%esi # Restore setup pointer >> 126 xorl %ebx,%ebx >> 127 ljmp $(__KERNEL_CS), $0x100000 >> 128 move_routine_end:
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.