Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/stand/i386/libi386/relocater_tramp.S
34860 views
1
/*-
2
* Copyright 2015 Toomas Soome <[email protected]>
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
27
28
/*
29
* relocate is needed to support loading code which has to be located
30
* below 1MB, as both BTX and loader are using low memory area.
31
*
32
* relocate and start loaded code. Since loaded code may need to be
33
* placed to already occupied memory area, this code is moved to safe
34
* memory area and then btx __exec will be called with physical pointer
35
* to this area. __exec will set pointer to %eax and use call *%eax,
36
* so on entry, we have new "base" address in %eax.
37
*
38
* Relocate will first set up and load new safe GDT to shut down BTX,
39
* then loaded code will be relocated to final memory location,
40
* then machine will be switched from 32bit protected mode to 16bit
41
* protected mode following by switch to real mode with A20 enabled or
42
* disabled. Finally the loaded code will be started and it will take
43
* over the whole system.
44
*
45
* For now, the known "safe" memory area for relocate is 0x600,
46
* the actual "free" memory is supposed to start from 0x500, leaving
47
* first 0x100 bytes in reserve. As relocate code+data is very small,
48
* it will leave enough space to set up boot blocks to 0:7c00 or load
49
* linux kernel below 1MB space.
50
*/
51
/*
52
* segment selectors
53
*/
54
.set SEL_SCODE,0x8
55
.set SEL_SDATA,0x10
56
.set SEL_RCODE,0x18
57
.set SEL_RDATA,0x20
58
59
.p2align 4
60
.globl relocater
61
relocater:
62
cli
63
/*
64
* set up GDT from new location
65
*/
66
movl %eax, %esi /* our base address */
67
add $(relocater.1-relocater), %eax
68
jmp *%eax
69
relocater.1:
70
/* set up jump */
71
lea (relocater.2-relocater)(%esi), %eax
72
movl %eax, (jump_vector-relocater) (%esi)
73
74
/* set up gdt */
75
lea (gdt-relocater) (%esi), %eax
76
movl %eax, (gdtaddr-relocater) (%esi)
77
78
/* load gdt */
79
lgdt (gdtdesc - relocater) (%esi)
80
lidt (idt-relocater) (%esi)
81
82
/* update cs */
83
ljmp *(jump_vector-relocater) (%esi)
84
85
.code32
86
relocater.2:
87
xorl %eax, %eax
88
movb $SEL_SDATA, %al
89
movw %ax, %ss
90
movw %ax, %ds
91
movw %ax, %es
92
movw %ax, %fs
93
movw %ax, %gs
94
movl %cr0, %eax /* disable paging */
95
andl $~0x80000000,%eax
96
movl %eax, %cr0
97
xorl %ecx, %ecx /* flush TLB */
98
movl %ecx, %cr3
99
cld
100
/*
101
* relocate data loop. load source, dest and size from
102
* relocater_data[i], 0 value will stop the loop.
103
* registers used for move: %esi, %edi, %ecx.
104
* %ebx to keep base
105
* %edx for relocater_data offset
106
*/
107
movl %esi, %ebx /* base address */
108
xorl %edx, %edx
109
loop.1:
110
movl (relocater_data-relocater)(%ebx, %edx, 4), %eax
111
testl %eax, %eax
112
jz loop.2
113
movl (relocater_data-relocater)(%ebx, %edx, 4), %esi
114
inc %edx
115
movl (relocater_data-relocater)(%ebx, %edx, 4), %edi
116
inc %edx
117
movl (relocater_data-relocater)(%ebx, %edx, 4), %ecx
118
inc %edx
119
rep
120
movsb
121
jmp loop.1
122
loop.2:
123
movl %ebx, %esi /* restore esi */
124
/*
125
* data is relocated, switch to 16bit mode
126
*/
127
lea (relocater.3-relocater)(%esi), %eax
128
movl %eax, (jump_vector-relocater) (%esi)
129
movl $SEL_RCODE, %eax
130
movl %eax, (jump_vector-relocater+4) (%esi)
131
132
ljmp *(jump_vector-relocater) (%esi)
133
relocater.3:
134
.code16
135
136
movw $SEL_RDATA, %ax
137
movw %ax, %ds
138
movw %ax, %es
139
movw %ax, %fs
140
movw %ax, %gs
141
movw %ax, %ss
142
lidt (idt-relocater) (%esi)
143
lea (relocater.4-relocater)(%esi), %eax
144
movl %eax, (jump_vector-relocater) (%esi)
145
xorl %eax, %eax
146
movl %eax, (jump_vector-relocater+4) (%esi)
147
/* clear PE */
148
movl %cr0, %eax
149
dec %al
150
movl %eax, %cr0
151
ljmp *(jump_vector-relocater) (%esi)
152
relocater.4:
153
xorw %ax, %ax
154
movw %ax, %ds
155
movw %ax, %es
156
movw %ax, %fs
157
movw %ax, %gs
158
movw %ax, %ss
159
/*
160
* set real mode irq offsets
161
*/
162
movw $0x7008,%bx
163
in $0x21,%al # Save master
164
push %ax # IMR
165
in $0xa1,%al # Save slave
166
push %ax # IMR
167
movb $0x11,%al # ICW1 to
168
outb %al,$0x20 # master,
169
outb %al,$0xa0 # slave
170
movb %bl,%al # ICW2 to
171
outb %al,$0x21 # master
172
movb %bh,%al # ICW2 to
173
outb %al,$0xa1 # slave
174
movb $0x4,%al # ICW3 to
175
outb %al,$0x21 # master
176
movb $0x2,%al # ICW3 to
177
outb %al,$0xa1 # slave
178
movb $0x1,%al # ICW4 to
179
outb %al,$0x21 # master,
180
outb %al,$0xa1 # slave
181
pop %ax # Restore slave
182
outb %al,$0xa1 # IMR
183
pop %ax # Restore master
184
outb %al,$0x21 # IMR
185
# done
186
/*
187
* Should A20 be left enabled?
188
*/
189
/* movw imm16, %ax */
190
.byte 0xb8
191
.globl relocator_a20_enabled
192
relocator_a20_enabled:
193
.word 0
194
test %ax, %ax
195
jnz a20_done
196
197
movw $0xa00, %ax
198
movw %ax, %sp
199
movw %ax, %bp
200
201
/* Disable A20 */
202
movw $0x2400, %ax
203
int $0x15
204
# jnc a20_done
205
206
call a20_check_state
207
testb %al, %al
208
jz a20_done
209
210
inb $0x92
211
andb $(~0x03), %al
212
outb $0x92
213
jmp a20_done
214
215
a20_check_state:
216
movw $100, %cx
217
1:
218
xorw %ax, %ax
219
movw %ax, %ds
220
decw %ax
221
movw %ax, %es
222
xorw %ax, %ax
223
movw $0x8000, %ax
224
movw %ax, %si
225
addw $0x10, %ax
226
movw %ax, %di
227
movb %ds:(%si), %dl
228
movb %es:(%di), %al
229
movb %al, %dh
230
decb %dh
231
movb %dh, %ds:(%si)
232
outb %al, $0x80
233
outb %al, $0x80
234
movb %es:(%di), %dh
235
subb %dh, %al
236
xorb $1, %al
237
movb %dl, %ds:(%si)
238
testb %al, %al
239
jz a20_done
240
loop 1b
241
ret
242
a20_done:
243
/*
244
* set up registers
245
*/
246
/* movw imm16, %ax. */
247
.byte 0xb8
248
.globl relocator_ds
249
relocator_ds: .word 0
250
movw %ax, %ds
251
252
/* movw imm16, %ax. */
253
.byte 0xb8
254
.globl relocator_es
255
relocator_es: .word 0
256
movw %ax, %es
257
258
/* movw imm16, %ax. */
259
.byte 0xb8
260
.globl relocator_fs
261
relocator_fs: .word 0
262
movw %ax, %fs
263
264
/* movw imm16, %ax. */
265
.byte 0xb8
266
.globl relocator_gs
267
relocator_gs: .word 0
268
movw %ax, %gs
269
270
/* movw imm16, %ax. */
271
.byte 0xb8
272
.globl relocator_ss
273
relocator_ss: .word 0
274
movw %ax, %ss
275
276
/* movw imm16, %ax. */
277
.byte 0xb8
278
.globl relocator_sp
279
relocator_sp: .word 0
280
movzwl %ax, %esp
281
282
/* movw imm32, %eax. */
283
.byte 0x66, 0xb8
284
.globl relocator_esi
285
relocator_esi: .long 0
286
movl %eax, %esi
287
288
/* movw imm32, %edx. */
289
.byte 0x66, 0xba
290
.globl relocator_edx
291
relocator_edx: .long 0
292
293
/* movw imm32, %ebx. */
294
.byte 0x66, 0xbb
295
.globl relocator_ebx
296
relocator_ebx: .long 0
297
298
/* movw imm32, %eax. */
299
.byte 0x66, 0xb8
300
.globl relocator_eax
301
relocator_eax: .long 0
302
303
/* movw imm32, %ebp. */
304
.byte 0x66, 0xbd
305
.globl relocator_ebp
306
relocator_ebp: .long 0
307
308
sti
309
.byte 0xea /* ljmp */
310
.globl relocator_ip
311
relocator_ip:
312
.word 0
313
.globl relocator_cs
314
relocator_cs:
315
.word 0
316
317
/* GDT to reset BTX */
318
.code32
319
.p2align 4
320
jump_vector: .long 0
321
.long SEL_SCODE
322
323
gdt: .word 0x0, 0x0 /* null entry */
324
.byte 0x0, 0x0, 0x0, 0x0
325
.word 0xffff, 0x0 /* SEL_SCODE */
326
.byte 0x0, 0x9a, 0xcf, 0x0
327
.word 0xffff, 0x0 /* SEL_SDATA */
328
.byte 0x0, 0x92, 0xcf, 0x0
329
.word 0xffff, 0x0 /* SEL_RCODE */
330
.byte 0x0, 0x9a, 0x0f, 0x0
331
.word 0xffff, 0x0 /* SEL_RDATA */
332
.byte 0x0, 0x92, 0x0f, 0x0
333
gdt.1:
334
335
gdtdesc: .word gdt.1 - gdt - 1 /* limit */
336
gdtaddr: .long 0 /* base */
337
338
idt: .word 0x3ff
339
.long 0
340
341
.globl relocater_data
342
relocater_data:
343
.long 0 /* src */
344
.long 0 /* dest */
345
.long 0 /* size */
346
.long 0 /* src */
347
.long 0 /* dest */
348
.long 0 /* size */
349
.long 0 /* src */
350
.long 0 /* dest */
351
.long 0 /* size */
352
.long 0
353
354
.globl relocater_size
355
relocater_size:
356
.long relocater_size-relocater
357
358