head.S 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  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. .text
  23. #include <linux/linkage.h>
  24. #include <asm/segment.h>
  25. #include <asm/page.h>
  26. .globl startup_32
  27. startup_32:
  28. cld
  29. cli
  30. movl $(__BOOT_DS),%eax
  31. movl %eax,%ds
  32. movl %eax,%es
  33. movl %eax,%fs
  34. movl %eax,%gs
  35. lss stack_start,%esp
  36. xorl %eax,%eax
  37. 1: incl %eax # check that A20 really IS enabled
  38. movl %eax,0x000000 # loop forever if it isn't
  39. cmpl %eax,0x100000
  40. je 1b
  41. /*
  42. * Initialize eflags. Some BIOS's leave bits like NT set. This would
  43. * confuse the debugger if this code is traced.
  44. * XXX - best to initialize before switching to protected mode.
  45. */
  46. pushl $0
  47. popfl
  48. /*
  49. * Clear BSS
  50. */
  51. xorl %eax,%eax
  52. movl $_edata,%edi
  53. movl $_end,%ecx
  54. subl %edi,%ecx
  55. cld
  56. rep
  57. stosb
  58. /*
  59. * Do the decompression, and jump to the new kernel..
  60. */
  61. subl $16,%esp # place for structure on the stack
  62. movl %esp,%eax
  63. pushl %esi # real mode pointer as second arg
  64. pushl %eax # address of structure as first arg
  65. call decompress_kernel
  66. orl %eax,%eax
  67. jnz 3f
  68. popl %esi # discard address
  69. popl %esi # real mode pointer
  70. xorl %ebx,%ebx
  71. ljmp $(__BOOT_CS), $__PHYSICAL_START
  72. /*
  73. * We come here, if we were loaded high.
  74. * We need to move the move-in-place routine down to 0x1000
  75. * and then start it with the buffer addresses in registers,
  76. * which we got from the stack.
  77. */
  78. 3:
  79. movl $move_routine_start,%esi
  80. movl $0x1000,%edi
  81. movl $move_routine_end,%ecx
  82. subl %esi,%ecx
  83. addl $3,%ecx
  84. shrl $2,%ecx
  85. cld
  86. rep
  87. movsl
  88. popl %esi # discard the address
  89. popl %ebx # real mode pointer
  90. popl %esi # low_buffer_start
  91. popl %ecx # lcount
  92. popl %edx # high_buffer_start
  93. popl %eax # hcount
  94. movl $__PHYSICAL_START,%edi
  95. cli # make sure we don't get interrupted
  96. ljmp $(__BOOT_CS), $0x1000 # and jump to the move routine
  97. /*
  98. * Routine (template) for moving the decompressed kernel in place,
  99. * if we were high loaded. This _must_ PIC-code !
  100. */
  101. move_routine_start:
  102. movl %ecx,%ebp
  103. shrl $2,%ecx
  104. rep
  105. movsl
  106. movl %ebp,%ecx
  107. andl $3,%ecx
  108. rep
  109. movsb
  110. movl %edx,%esi
  111. movl %eax,%ecx # NOTE: rep movsb won't move if %ecx == 0
  112. addl $3,%ecx
  113. shrl $2,%ecx
  114. rep
  115. movsl
  116. movl %ebx,%esi # Restore setup pointer
  117. xorl %ebx,%ebx
  118. ljmp $(__BOOT_CS), $__PHYSICAL_START
  119. move_routine_end: