2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
12 * Copyright 2016 Toomas Soome <tsoome@me.com>
16 * Relocate is needed to support loading code which has to be located
17 * below 1MB, as both BTX and loader are using low memory area.
19 * Relocate and start loaded code. Since loaded code may need to be
20 * placed in an already occupied memory area, the code is moved to a safe
21 * memory area and then btx __exec will be called with physical pointer
22 * to this area. __exec will set the pointer to %eax and call *%eax,
23 * so that on entry, we have the new "base" address in %eax.
25 * Relocate will first set up and load new safe GDT to shut down BTX,
26 * then loaded code will be relocated to final memory location,
27 * then machine will be switched from 32-bit protected mode to 16-bit
28 * protected mode following by switch to real mode with A20 enabled or
29 * disabled. Finally the loaded code will be started and it will take
30 * over the whole system.
32 * For now, the known "safe" memory area for relocate is 0x600,
33 * the actual "free" memory is supposed to start from 0x500, leaving
34 * first 0x100 bytes in reserve. As relocate code+data is very small,
35 * it will leave enough space to set up boot blocks to 0:7c00 or load
36 * linux kernel below 1MB space.
51 * set up GDT from new location
53 movl %eax, %esi /* our base address */
54 add $(relocater.1-relocater), %eax
58 lea (relocater.2-relocater)(%esi), %eax
59 movl %eax, (jump_vector-relocater) (%esi)
62 lea (gdt-relocater) (%esi), %eax
63 movl %eax, (gdtaddr-relocater) (%esi)
66 lgdt (gdtdesc - relocater) (%esi)
67 lidt (idt-relocater) (%esi)
70 ljmp *(jump_vector-relocater) (%esi)
81 movl %cr0, %eax /* disable paging */
82 andl $~0x80000000,%eax
84 xorl %ecx, %ecx /* flush TLB */
88 * relocate data loop. load source, dest and size from
89 * relocater_data[i], 0 value will stop the loop.
90 * registers used for move: %esi, %edi, %ecx.
92 * %edx for relocater_data offset
94 movl %esi, %ebx /* base address */
97 movl (relocater_data-relocater)(%ebx, %edx, 4), %eax
100 movl (relocater_data-relocater)(%ebx, %edx, 4), %esi
102 movl (relocater_data-relocater)(%ebx, %edx, 4), %edi
104 movl (relocater_data-relocater)(%ebx, %edx, 4), %ecx
110 movl %ebx, %esi /* restore esi */
112 * data is relocated, switch to 16-bit mode
114 lea (relocater.3-relocater)(%esi), %eax
115 movl %eax, (jump_vector-relocater) (%esi)
116 movl $SEL_RCODE, %eax
117 movl %eax, (jump_vector-relocater+4) (%esi)
119 ljmp *(jump_vector-relocater) (%esi)
129 lidt (idt-relocater) (%esi)
130 lea (relocater.4-relocater)(%esi), %eax
131 movl %eax, (jump_vector-relocater) (%esi)
133 movl %eax, (jump_vector-relocater+4) (%esi)
138 ljmp *(jump_vector-relocater) (%esi)
147 * set real mode irq offsets
150 in $0x21,%al # Save master
152 in $0xa1,%al # Save slave
154 movb $0x11,%al # ICW1 to
155 outb %al,$0x20 # master,
156 outb %al,$0xa0 # slave
157 movb %bl,%al # ICW2 to
158 outb %al,$0x21 # master
159 movb %bh,%al # ICW2 to
160 outb %al,$0xa1 # slave
161 movb $0x4,%al # ICW3 to
162 outb %al,$0x21 # master
163 movb $0x2,%al # ICW3 to
164 outb %al,$0xa1 # slave
165 movb $0x1,%al # ICW4 to
166 outb %al,$0x21 # master,
167 outb %al,$0xa1 # slave
168 pop %ax # Restore slave
170 pop %ax # Restore master
174 * Should A20 be left enabled?
176 /* movw imm16, %ax */
178 .globl relocator_a20_enabled
179 relocator_a20_enabled:
233 /* movw imm16, %ax. */
236 relocator_ds: .word 0
239 /* movw imm16, %ax. */
242 relocator_es: .word 0
245 /* movw imm16, %ax. */
248 relocator_fs: .word 0
251 /* movw imm16, %ax. */
254 relocator_gs: .word 0
257 /* movw imm16, %ax. */
260 relocator_ss: .word 0
263 /* movw imm16, %ax. */
266 relocator_sp: .word 0
269 /* movw imm32, %eax. */
272 relocator_esi: .long 0
275 /* movw imm32, %edx. */
278 relocator_edx: .long 0
280 /* movw imm32, %ebx. */
283 relocator_ebx: .long 0
285 /* movw imm32, %eax. */
288 relocator_eax: .long 0
290 /* movw imm32, %ebp. */
293 relocator_ebp: .long 0
296 .byte 0xea /* ljmp */
304 /* GDT to reset BTX */
310 gdt: .word 0x0, 0x0 /* null entry */
311 .byte 0x0, 0x0, 0x0, 0x0
312 .word 0xffff, 0x0 /* SEL_SCODE */
313 .byte 0x0, 0x9a, 0xcf, 0x0
314 .word 0xffff, 0x0 /* SEL_SDATA */
315 .byte 0x0, 0x92, 0xcf, 0x0
316 .word 0xffff, 0x0 /* SEL_RCODE */
317 .byte 0x0, 0x9a, 0x0f, 0x0
318 .word 0xffff, 0x0 /* SEL_RDATA */
319 .byte 0x0, 0x92, 0x0f, 0x0
322 gdtdesc: .word gdt.1 - gdt - 1 /* limit */
323 gdtaddr: .long 0 /* base */
328 .globl relocater_data
330 /* reserve space for 3 entries */
343 .globl relocater_size
345 .long relocater_size-relocater