head.S 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. /*
  2. * linux/boot/head.S
  3. *
  4. * Copyright (C) 1991, 1992, 1993 Linus Torvalds
  5. */
  6. /*
  7. * head.S contains the 32-bit startup code.
  8. *
  9. * NOTE!!! Startup happens at absolute address 0x00001000, which is also where
  10. * the page directory will exist. The startup code will be overwritten by
  11. * the page directory. [According to comments etc elsewhere on a compressed
  12. * 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 in
  15. * laptops may need to access the BIOS data stored there. This is also
  16. * useful for future device drivers that either access the BIOS via VM86
  17. * mode.
  18. */
  19. /*
  20. * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
  21. */
  22. .code32
  23. .text
  24. #include <linux/linkage.h>
  25. #include <asm/segment.h>
  26. #include <asm/page.h>
  27. .code32
  28. .globl startup_32
  29. startup_32:
  30. cld
  31. cli
  32. movl $(__KERNEL_DS),%eax
  33. movl %eax,%ds
  34. movl %eax,%es
  35. movl %eax,%fs
  36. movl %eax,%gs
  37. lss stack_start,%esp
  38. xorl %eax,%eax
  39. 1: incl %eax # check that A20 really IS enabled
  40. movl %eax,0x000000 # loop forever if it isn't
  41. cmpl %eax,0x100000
  42. je 1b
  43. /*
  44. * Initialize eflags. Some BIOS's leave bits like NT set. This would
  45. * confuse the debugger if this code is traced.
  46. * XXX - best to initialize before switching to protected mode.
  47. */
  48. pushl $0
  49. popfl
  50. /*
  51. * Clear BSS
  52. */
  53. xorl %eax,%eax
  54. movl $_edata,%edi
  55. movl $_end,%ecx
  56. subl %edi,%ecx
  57. cld
  58. rep
  59. stosb
  60. /*
  61. * Do the decompression, and jump to the new kernel..
  62. */
  63. subl $16,%esp # place for structure on the stack
  64. movl %esp,%eax
  65. pushl %esi # real mode pointer as second arg
  66. pushl %eax # address of structure as first arg
  67. call decompress_kernel
  68. orl %eax,%eax
  69. jnz 3f
  70. addl $8,%esp
  71. xorl %ebx,%ebx
  72. ljmp $(__KERNEL_CS), $__PHYSICAL_START
  73. /*
  74. * We come here, if we were loaded high.
  75. * We need to move the move-in-place routine down to 0x1000
  76. * and then start it with the buffer addresses in registers,
  77. * which we got from the stack.
  78. */
  79. 3:
  80. movl %esi,%ebx
  81. movl $move_routine_start,%esi
  82. movl $0x1000,%edi
  83. movl $move_routine_end,%ecx
  84. subl %esi,%ecx
  85. addl $3,%ecx
  86. shrl $2,%ecx
  87. cld
  88. rep
  89. movsl
  90. popl %esi # discard the address
  91. addl $4,%esp # real mode pointer
  92. popl %esi # low_buffer_start
  93. popl %ecx # lcount
  94. popl %edx # high_buffer_start
  95. popl %eax # hcount
  96. movl $__PHYSICAL_START,%edi
  97. cli # make sure we don't get interrupted
  98. ljmp $(__KERNEL_CS), $0x1000 # and jump to the move routine
  99. /*
  100. * Routine (template) for moving the decompressed kernel in place,
  101. * if we were high loaded. This _must_ PIC-code !
  102. */
  103. move_routine_start:
  104. movl %ecx,%ebp
  105. shrl $2,%ecx
  106. rep
  107. movsl
  108. movl %ebp,%ecx
  109. andl $3,%ecx
  110. rep
  111. movsb
  112. movl %edx,%esi
  113. movl %eax,%ecx # NOTE: rep movsb won't move if %ecx == 0
  114. addl $3,%ecx
  115. shrl $2,%ecx
  116. rep
  117. movsl
  118. movl %ebx,%esi # Restore setup pointer
  119. xorl %ebx,%ebx
  120. ljmp $(__KERNEL_CS), $__PHYSICAL_START
  121. move_routine_end:
  122. /* Stack for uncompression */
  123. .align 32
  124. user_stack:
  125. .fill 4096,4,0
  126. stack_start:
  127. .long user_stack+4096
  128. .word __KERNEL_DS