2 * Copyright 2015 Toomas Soome <tsoome@me.com>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * relocate is needed to support loading code which has to be located
32 * below 1MB, as both BTX and loader are using low memory area.
34 * relocate and start loaded code. Since loaded code may need to be
35 * placed to already occupied memory area, this code is moved to safe
36 * memory area and then btx __exec will be called with physical pointer
37 * to this area. __exec will set pointer to %eax and use call *%eax,
38 * so on entry, we have new "base" address in %eax.
40 * Relocate will first set up and load new safe GDT to shut down BTX,
41 * then loaded code will be relocated to final memory location,
42 * then machine will be switched from 32bit protected mode to 16bit
43 * protected mode following by switch to real mode with A20 enabled or
44 * disabled. Finally the loaded code will be started and it will take
45 * over the whole system.
47 * For now, the known "safe" memory area for relocate is 0x600,
48 * the actual "free" memory is supposed to start from 0x500, leaving
49 * first 0x100 bytes in reserve. As relocate code+data is very small,
50 * it will leave enough space to set up boot blocks to 0:7c00 or load
51 * linux kernel below 1MB space.
66 * set up GDT from new location
68 movl %eax, %esi /* our base address */
69 add $(relocater.1-relocater), %eax
73 lea (relocater.2-relocater)(%esi), %eax
74 movl %eax, (jump_vector-relocater) (%esi)
77 lea (gdt-relocater) (%esi), %eax
78 movl %eax, (gdtaddr-relocater) (%esi)
81 lgdt (gdtdesc - relocater) (%esi)
82 lidt (idt-relocater) (%esi)
85 ljmp *(jump_vector-relocater) (%esi)
96 movl %cr0, %eax /* disable paging */
97 andl $~0x80000000,%eax
99 xorl %ecx, %ecx /* flush TLB */
103 * relocate data loop. load source, dest and size from
104 * relocater_data[i], 0 value will stop the loop.
105 * registers used for move: %esi, %edi, %ecx.
107 * %edx for relocater_data offset
109 movl %esi, %ebx /* base address */
112 movl (relocater_data-relocater)(%ebx, %edx, 4), %eax
115 movl (relocater_data-relocater)(%ebx, %edx, 4), %esi
117 movl (relocater_data-relocater)(%ebx, %edx, 4), %edi
119 movl (relocater_data-relocater)(%ebx, %edx, 4), %ecx
125 movl %ebx, %esi /* restore esi */
127 * data is relocated, switch to 16bit mode
129 lea (relocater.3-relocater)(%esi), %eax
130 movl %eax, (jump_vector-relocater) (%esi)
131 movl $SEL_RCODE, %eax
132 movl %eax, (jump_vector-relocater+4) (%esi)
134 ljmp *(jump_vector-relocater) (%esi)
144 lidt (idt-relocater) (%esi)
145 lea (relocater.4-relocater)(%esi), %eax
146 movl %eax, (jump_vector-relocater) (%esi)
148 movl %eax, (jump_vector-relocater+4) (%esi)
153 ljmp *(jump_vector-relocater) (%esi)
162 * set real mode irq offsets
165 in $0x21,%al # Save master
167 in $0xa1,%al # Save slave
169 movb $0x11,%al # ICW1 to
170 outb %al,$0x20 # master,
171 outb %al,$0xa0 # slave
172 movb %bl,%al # ICW2 to
173 outb %al,$0x21 # master
174 movb %bh,%al # ICW2 to
175 outb %al,$0xa1 # slave
176 movb $0x4,%al # ICW3 to
177 outb %al,$0x21 # master
178 movb $0x2,%al # ICW3 to
179 outb %al,$0xa1 # slave
180 movb $0x1,%al # ICW4 to
181 outb %al,$0x21 # master,
182 outb %al,$0xa1 # slave
183 pop %ax # Restore slave
185 pop %ax # Restore master
189 * Should A20 be left enabled?
191 /* movw imm16, %ax */
193 .globl relocator_a20_enabled
194 relocator_a20_enabled:
248 /* movw imm16, %ax. */
251 relocator_ds: .word 0
254 /* movw imm16, %ax. */
257 relocator_es: .word 0
260 /* movw imm16, %ax. */
263 relocator_fs: .word 0
266 /* movw imm16, %ax. */
269 relocator_gs: .word 0
272 /* movw imm16, %ax. */
275 relocator_ss: .word 0
278 /* movw imm16, %ax. */
281 relocator_sp: .word 0
284 /* movw imm32, %eax. */
287 relocator_esi: .long 0
290 /* movw imm32, %edx. */
293 relocator_edx: .long 0
295 /* movw imm32, %ebx. */
298 relocator_ebx: .long 0
300 /* movw imm32, %eax. */
303 relocator_eax: .long 0
305 /* movw imm32, %ebp. */
308 relocator_ebp: .long 0
311 .byte 0xea /* ljmp */
319 /* GDT to reset BTX */
325 gdt: .word 0x0, 0x0 /* null entry */
326 .byte 0x0, 0x0, 0x0, 0x0
327 .word 0xffff, 0x0 /* SEL_SCODE */
328 .byte 0x0, 0x9a, 0xcf, 0x0
329 .word 0xffff, 0x0 /* SEL_SDATA */
330 .byte 0x0, 0x92, 0xcf, 0x0
331 .word 0xffff, 0x0 /* SEL_RCODE */
332 .byte 0x0, 0x9a, 0x0f, 0x0
333 .word 0xffff, 0x0 /* SEL_RDATA */
334 .byte 0x0, 0x92, 0x0f, 0x0
337 gdtdesc: .word gdt.1 - gdt - 1 /* limit */
338 gdtaddr: .long 0 /* base */
343 .globl relocater_data
356 .globl relocater_size
358 .long relocater_size-relocater