]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/boot/i386/libi386/relocater_tramp.S
MFC Loader Fixes 2017q2: r316437,r316577,r316578,r316585,r316590,r316612,
[FreeBSD/FreeBSD.git] / sys / boot / i386 / libi386 / relocater_tramp.S
1 /*-
2  * Copyright 2015 Toomas Soome <tsoome@me.com>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
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.
13  *
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
24  * SUCH DAMAGE.
25  *
26  * $FreeBSD$
27  */
28
29
30 /*
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.
33  *
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.
39  *
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.
46  *
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.
52  */
53 /*
54  * segment selectors
55  */
56                 .set SEL_SCODE,0x8
57                 .set SEL_SDATA,0x10
58                 .set SEL_RCODE,0x18
59                 .set SEL_RDATA,0x20
60
61                 .p2align        4
62                 .globl relocater
63 relocater:
64                 cli
65                 /*
66                  * set up GDT from new location
67                  */
68                 movl    %eax, %esi              /* our base address */
69                 add     $(relocater.1-relocater), %eax
70                 jmp     *%eax
71 relocater.1:
72                 /* set up jump */
73                 lea     (relocater.2-relocater)(%esi), %eax
74                 movl    %eax, (jump_vector-relocater) (%esi)
75
76                 /* set up gdt */
77                 lea     (gdt-relocater) (%esi), %eax
78                 movl    %eax, (gdtaddr-relocater) (%esi)
79
80                 /* load gdt */
81                 lgdt    (gdtdesc - relocater) (%esi)
82                 lidt    (idt-relocater) (%esi)
83
84                 /* update cs */
85                 ljmp *(jump_vector-relocater) (%esi)
86
87                 .code32
88 relocater.2:
89                 xorl    %eax, %eax
90                 movb    $SEL_SDATA, %al
91                 movw    %ax, %ss
92                 movw    %ax, %ds
93                 movw    %ax, %es
94                 movw    %ax, %fs
95                 movw    %ax, %gs
96                 movl    %cr0, %eax              /* disable paging */
97                 andl    $~0x80000000,%eax
98                 movl    %eax, %cr0
99                 xorl    %ecx, %ecx              /* flush TLB */
100                 movl    %ecx, %cr3
101                 cld
102 /*
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.
106  * %ebx to keep base
107  * %edx for relocater_data offset
108  */
109                 movl    %esi, %ebx              /* base address */
110                 xorl    %edx, %edx
111 loop.1:
112                 movl    (relocater_data-relocater)(%ebx, %edx, 4), %eax
113                 testl   %eax, %eax
114                 jz      loop.2
115                 movl    (relocater_data-relocater)(%ebx, %edx, 4), %esi
116                 inc     %edx
117                 movl    (relocater_data-relocater)(%ebx, %edx, 4), %edi
118                 inc     %edx
119                 movl    (relocater_data-relocater)(%ebx, %edx, 4), %ecx
120                 inc     %edx
121                 rep
122                 movsb
123                 jmp     loop.1
124 loop.2:
125                 movl    %ebx, %esi              /* restore esi */
126                 /*
127                  * data is relocated, switch to 16bit mode
128                  */
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)
133
134                 ljmp *(jump_vector-relocater) (%esi)
135 relocater.3:
136                 .code16
137
138                 movw    $SEL_RDATA, %ax
139                 movw    %ax, %ds
140                 movw    %ax, %es
141                 movw    %ax, %fs
142                 movw    %ax, %gs
143                 movw    %ax, %ss
144                 lidt    (idt-relocater) (%esi)
145                 lea     (relocater.4-relocater)(%esi), %eax
146                 movl    %eax, (jump_vector-relocater) (%esi)
147                 xorl    %eax, %eax
148                 movl    %eax, (jump_vector-relocater+4) (%esi)
149                 /* clear PE */
150                 movl    %cr0, %eax
151                 dec     %al
152                 movl    %eax, %cr0
153                 ljmp *(jump_vector-relocater) (%esi)
154 relocater.4:
155                 xorw    %ax, %ax
156                 movw    %ax, %ds
157                 movw    %ax, %es
158                 movw    %ax, %fs
159                 movw    %ax, %gs
160                 movw    %ax, %ss
161                 /*
162                  * set real mode irq offsets
163                  */
164                 movw    $0x7008,%bx
165                 in $0x21,%al                    # Save master
166                 push %ax                        #  IMR
167                 in $0xa1,%al                    # Save slave
168                 push %ax                        #  IMR
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
184                 outb %al,$0xa1                  #  IMR
185                 pop %ax                         # Restore master
186                 outb %al,$0x21                  #  IMR
187                                                 # done
188                 /*
189                  * Should A20 be left enabled?
190                  */
191                 /* movw imm16, %ax */
192                 .byte   0xb8
193                 .globl  relocator_a20_enabled
194 relocator_a20_enabled:
195                 .word   0
196                 test    %ax, %ax
197                 jnz     a20_done
198
199                 movw    $0xa00, %ax
200                 movw    %ax, %sp
201                 movw    %ax, %bp
202
203                 /* Disable A20 */
204                 movw    $0x2400, %ax
205                 int     $0x15
206 #               jnc     a20_done
207
208                 call    a20_check_state
209                 testb   %al, %al
210                 jz      a20_done
211
212                 inb     $0x92
213                 andb    $(~0x03), %al
214                 outb    $0x92
215                 jmp     a20_done
216
217 a20_check_state:
218                 movw    $100, %cx
219 1:
220                 xorw    %ax, %ax
221                 movw    %ax, %ds
222                 decw    %ax
223                 movw    %ax, %es
224                 xorw    %ax, %ax
225                 movw    $0x8000, %ax
226                 movw    %ax, %si
227                 addw    $0x10, %ax
228                 movw    %ax, %di
229                 movb    %ds:(%si), %dl
230                 movb    %es:(%di), %al
231                 movb    %al, %dh
232                 decb    %dh
233                 movb    %dh, %ds:(%si)
234                 outb    %al, $0x80
235                 outb    %al, $0x80
236                 movb    %es:(%di), %dh
237                 subb    %dh, %al
238                 xorb    $1, %al
239                 movb    %dl, %ds:(%si)
240                 testb   %al, %al
241                 jz      a20_done
242                 loop    1b
243                 ret
244 a20_done:
245                 /*
246                  * set up registers
247                  */
248                 /* movw imm16, %ax. */
249                 .byte   0xb8
250                 .globl  relocator_ds
251 relocator_ds:   .word   0
252                 movw    %ax, %ds
253
254                 /* movw imm16, %ax. */
255                 .byte   0xb8
256                 .globl  relocator_es
257 relocator_es:   .word   0
258                 movw    %ax, %es
259
260                 /* movw imm16, %ax. */
261                 .byte   0xb8
262                 .globl  relocator_fs
263 relocator_fs:   .word   0
264                 movw    %ax, %fs
265
266                 /* movw imm16, %ax. */
267                 .byte   0xb8
268                 .globl  relocator_gs
269 relocator_gs:   .word   0
270                 movw    %ax, %gs
271
272                 /* movw imm16, %ax. */
273                 .byte   0xb8
274                 .globl  relocator_ss
275 relocator_ss:   .word   0
276                 movw    %ax, %ss
277
278                 /* movw imm16, %ax. */
279                 .byte   0xb8
280                 .globl  relocator_sp
281 relocator_sp:   .word   0
282                 movzwl  %ax, %esp
283
284                 /* movw imm32, %eax. */
285                 .byte   0x66, 0xb8
286                 .globl  relocator_esi
287 relocator_esi:  .long   0
288                 movl    %eax, %esi
289
290                 /* movw imm32, %edx. */
291                 .byte   0x66, 0xba
292                 .globl  relocator_edx
293 relocator_edx:  .long   0
294
295                 /* movw imm32, %ebx. */
296                 .byte   0x66, 0xbb
297                 .globl  relocator_ebx
298 relocator_ebx:  .long   0
299
300                 /* movw imm32, %eax. */
301                 .byte   0x66, 0xb8
302                 .globl  relocator_eax
303 relocator_eax:  .long   0
304
305                 /* movw imm32, %ebp. */
306                 .byte   0x66, 0xbd
307                 .globl  relocator_ebp
308 relocator_ebp:  .long   0
309
310                 sti
311                 .byte 0xea                       /* ljmp */
312                 .globl relocator_ip
313 relocator_ip:
314                 .word 0
315                 .globl relocator_cs
316 relocator_cs:
317                 .word 0
318
319 /* GDT to reset BTX */
320                 .code32
321                 .p2align        4
322 jump_vector:    .long   0
323                 .long   SEL_SCODE
324
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
335 gdt.1:
336
337 gdtdesc:        .word gdt.1 - gdt - 1           /* limit */
338 gdtaddr:        .long 0                         /* base */
339
340 idt:            .word 0x3ff
341                 .long 0
342
343                 .globl relocater_data
344 relocater_data:
345                 .long 0                 /* src */
346                 .long 0                 /* dest */
347                 .long 0                 /* size */
348                 .long 0                 /* src */
349                 .long 0                 /* dest */
350                 .long 0                 /* size */
351                 .long 0                 /* src */
352                 .long 0                 /* dest */
353                 .long 0                 /* size */
354                 .long 0
355
356                 .globl relocater_size
357 relocater_size:
358                 .long relocater_size-relocater