head.S 2.8 KB

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