Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/stand/i386/btx/btxldr/btxldr.S
34869 views
1
/*
2
* Copyright (c) 1998 Robert Nordier
3
* All rights reserved.
4
*
5
* Redistribution and use in source and binary forms are freely
6
* permitted provided that the above copyright notice and this
7
* paragraph and the following disclaimer are duplicated in all
8
* such forms.
9
*
10
* This software is provided "AS IS" and without any express or
11
* implied warranties, including, without limitation, the implied
12
* warranties of merchantability and fitness for a particular
13
* purpose.
14
*/
15
16
#include <bootargs.h>
17
18
#define RBX_MUTE 0x10 /* -m */
19
#define OPT_SET(opt) (1 << (opt))
20
21
/*
22
* Prototype BTX loader program, written in a couple of hours. The
23
* real thing should probably be more flexible, and in C.
24
*/
25
26
/*
27
* Memory locations.
28
*/
29
.set MEM_STUB,0x600 # Real mode stub
30
.set MEM_ESP,0x1000 # New stack pointer
31
.set MEM_TBL,0x5000 # BTX page tables
32
.set MEM_ENTRY,0x9010 # BTX entry point
33
.set MEM_DATA,start+0x1000 # Data segment
34
/*
35
* Segment selectors.
36
*/
37
.set SEL_SCODE,0x8 # 4GB code
38
.set SEL_SDATA,0x10 # 4GB data
39
.set SEL_RCODE,0x18 # 64K code
40
.set SEL_RDATA,0x20 # 64K data
41
/*
42
* Paging constants.
43
*/
44
.set PAG_SIZ,0x1000 # Page size
45
.set PAG_ENT,0x4 # Page entry size
46
/*
47
* Screen constants.
48
*/
49
.set SCR_MAT,0x7 # Mode/attribute
50
.set SCR_COL,0x50 # Columns per row
51
.set SCR_ROW,0x19 # Rows per screen
52
/*
53
* BIOS Data Area locations.
54
*/
55
.set BDA_MEM,0x413 # Free memory
56
.set BDA_SCR,0x449 # Video mode
57
.set BDA_POS,0x450 # Cursor position
58
/*
59
* Required by aout gas inadequacy.
60
*/
61
.set SIZ_STUB,0x1a # Size of stub
62
/*
63
* We expect to be loaded by boot2 at the origin defined in ./Makefile.
64
*/
65
.globl start
66
/*
67
* BTX program loader for ELF clients.
68
*/
69
start: cld # String ops inc
70
testl $OPT_SET(RBX_MUTE), 4(%esp) # Check first argument
71
setnz muted # for RBX_MUTE, set flag
72
movl $m_logo,%esi # Identify
73
call putstr # ourselves
74
movzwl BDA_MEM,%eax # Get base memory
75
shll $0xa,%eax # in bytes
76
movl %eax,%ebp # Base of user stack
77
#ifdef BTXLDR_VERBOSE
78
movl $m_mem,%esi # Display
79
call hexout # amount of
80
call putstr # base memory
81
#endif
82
lgdt gdtdesc # Load new GDT
83
/*
84
* Relocate caller's arguments.
85
*/
86
#ifdef BTXLDR_VERBOSE
87
movl $m_esp,%esi # Display
88
movl %esp,%eax # caller
89
call hexout # stack
90
call putstr # pointer
91
movl $m_args,%esi # Format string
92
leal 0x4(%esp),%ebx # First argument
93
movl $0x6,%ecx # Count
94
start.1: movl (%ebx),%eax # Get argument and
95
addl $0x4,%ebx # bump pointer
96
call hexout # Display it
97
loop start.1 # Till done
98
call putstr # End message
99
#endif
100
movl BA_BOOTINFO+4(%esp),%esi # Source: bootinfo
101
cmpl $0x0, %esi # If the bootinfo pointer
102
je start_null_bi # is null, don't copy it
103
movl BI_SIZE(%esi),%ecx # Allocate space
104
subl %ecx,%ebp # for bootinfo
105
movl %ebp,%edi # Destination
106
rep # Copy
107
movsb # it
108
movl %ebp,BA_BOOTINFO+4(%esp) # Update pointer
109
movl %edi,%ebp # Restore base pointer
110
#ifdef BTXLDR_VERBOSE
111
movl $m_rel_bi,%esi # Display
112
movl %ebp,%eax # bootinfo
113
call hexout # relocation
114
call putstr # message
115
#endif
116
start_null_bi: movl $BOOTARGS_SIZE,%ecx # Fixed size of arguments
117
testl $KARGS_FLAGS_EXTARG, BA_BOOTFLAGS+4(%esp) # Check for extra data
118
jz start_fixed # Skip if the flag is not set
119
addl BOOTARGS_SIZE+4(%esp),%ecx # Add size of variable args
120
start_fixed: subl $ARGOFF,%ebp # Place args at fixed offset
121
leal 0x4(%esp),%esi # Source
122
movl %ebp,%edi # Destination
123
rep # Copy
124
movsb # them
125
#ifdef BTXLDR_VERBOSE
126
movl $m_rel_args,%esi # Display
127
movl %ebp,%eax # argument
128
call hexout # relocation
129
call putstr # message
130
#endif
131
/*
132
* Set up BTX kernel.
133
*/
134
movl $MEM_ESP,%esp # Set up new stack
135
movl $MEM_DATA,%ebx # Data segment
136
movl $m_vers,%esi # Display BTX
137
call putstr # version message
138
movb 0x5(%ebx),%al # Get major version
139
addb $'0',%al # Display
140
call putchr # it
141
movb $'.',%al # And a
142
call putchr # dot
143
movb 0x6(%ebx),%al # Get minor
144
xorb %ah,%ah # version
145
movb $0xa,%dl # Divide
146
divb %dl,%al # by 10
147
addb $'0',%al # Display
148
call putchr # tens
149
movb %ah,%al # Get units
150
addb $'0',%al # Display
151
call putchr # units
152
call putstr # End message
153
movl %ebx,%esi # BTX image
154
movzwl 0x8(%ebx),%edi # Compute
155
orl $PAG_SIZ/PAG_ENT-1,%edi # the
156
incl %edi # BTX
157
shll $0x2,%edi # load
158
addl $MEM_TBL,%edi # address
159
pushl %edi # Save load address
160
movzwl 0xa(%ebx),%ecx # Image size
161
#ifdef BTXLDR_VERBOSE
162
pushl %ecx # Save image size
163
#endif
164
rep # Relocate
165
movsb # BTX
166
movl %esi,%ebx # Keep place
167
#ifdef BTXLDR_VERBOSE
168
movl $m_rel_btx,%esi # Restore
169
popl %eax # parameters
170
call hexout # and
171
#endif
172
popl %ebp # display
173
#ifdef BTXLDR_VERBOSE
174
movl %ebp,%eax # the
175
call hexout # relocation
176
call putstr # message
177
#endif
178
addl $PAG_SIZ,%ebp # Display
179
#ifdef BTXLDR_VERBOSE
180
movl $m_base,%esi # the
181
movl %ebp,%eax # user
182
call hexout # base
183
call putstr # address
184
#endif
185
/*
186
* Set up ELF-format client program.
187
*/
188
cmpl $0x464c457f,(%ebx) # ELF magic number?
189
je start.3 # Yes
190
movl $e_fmt,%esi # Display error
191
call putstr # message
192
start.2: jmp start.2 # Hang
193
start.3:
194
#ifdef BTXLDR_VERBOSE
195
movl $m_elf,%esi # Display ELF
196
call putstr # message
197
movl $m_segs,%esi # Format string
198
#endif
199
movl 0x1c(%ebx),%edx # Get e_phoff
200
addl %ebx,%edx # To pointer
201
movzwl 0x2c(%ebx),%ecx # Get e_phnum
202
start.4: cmpl $0x1,(%edx) # Is p_type PT_LOAD?
203
jne start.6 # No
204
#ifdef BTXLDR_VERBOSE
205
movl 0x4(%edx),%eax # Display
206
call hexout # p_offset
207
movl 0x8(%edx),%eax # Display
208
call hexout # p_vaddr
209
movl 0x10(%edx),%eax # Display
210
call hexout # p_filesz
211
movl 0x14(%edx),%eax # Display
212
call hexout # p_memsz
213
call putstr # End message
214
#endif
215
pushl %esi # Save
216
pushl %ecx # working registers
217
movl 0x4(%edx),%esi # Get p_offset
218
addl %ebx,%esi # as pointer
219
movl 0x8(%edx),%edi # Get p_vaddr
220
addl %ebp,%edi # as pointer
221
movl 0x10(%edx),%ecx # Get p_filesz
222
rep # Set up
223
movsb # segment
224
movl 0x14(%edx),%ecx # Any bytes
225
subl 0x10(%edx),%ecx # to zero?
226
jz start.5 # No
227
xorb %al,%al # Then
228
rep # zero
229
stosb # them
230
start.5: popl %ecx # Restore
231
popl %esi # registers
232
start.6: addl $0x20,%edx # To next entry
233
loop start.4 # Till done
234
#ifdef BTXLDR_VERBOSE
235
movl $m_done,%esi # Display done
236
call putstr # message
237
#endif
238
movl $start.8,%esi # Real mode stub
239
movl $MEM_STUB,%edi # Destination
240
movl $start.9-start.8,%ecx # Size
241
rep # Relocate
242
movsb # it
243
ljmp $SEL_RCODE,$MEM_STUB # To 16-bit code
244
.code16
245
start.8: xorw %ax,%ax # Data
246
movb $SEL_RDATA,%al # selector
247
movw %ax,%ss # Reload SS
248
movw %ax,%ds # Reset
249
movw %ax,%es # other
250
movw %ax,%fs # segment
251
movw %ax,%gs # limits
252
movl %cr0,%eax # Switch to
253
decw %ax # real
254
movl %eax,%cr0 # mode
255
ljmp $0,$MEM_ENTRY # Jump to BTX entry point
256
start.9:
257
.code32
258
/*
259
* Output message [ESI] followed by EAX in hex.
260
*/
261
hexout: pushl %eax # Save
262
call putstr # Display message
263
popl %eax # Restore
264
pushl %esi # Save
265
pushl %edi # caller's
266
movl $buf,%edi # Buffer
267
pushl %edi # Save
268
call hex32 # To hex
269
xorb %al,%al # Terminate
270
stosb # string
271
popl %esi # Restore
272
hexout.1: lodsb # Get a char
273
cmpb $'0',%al # Leading zero?
274
je hexout.1 # Yes
275
testb %al,%al # End of string?
276
jne hexout.2 # No
277
decl %esi # Undo
278
hexout.2: decl %esi # Adjust for inc
279
call putstr # Display hex
280
popl %edi # Restore
281
popl %esi # caller's
282
ret # To caller
283
/*
284
* Output zero-terminated string [ESI] to the console.
285
*/
286
putstr.0: call putchr # Output char
287
putstr: lodsb # Load char
288
testb %al,%al # End of string?
289
jne putstr.0 # No
290
ret # To caller
291
/*
292
* Output character AL to the console.
293
*/
294
putchr: testb $1,muted # Check muted
295
jnz putchr.5 # do a nop
296
pusha # Save
297
xorl %ecx,%ecx # Zero for loops
298
movb $SCR_MAT,%ah # Mode/attribute
299
movl $BDA_POS,%ebx # BDA pointer
300
movw (%ebx),%dx # Cursor position
301
movl $0xb8000,%edi # Regen buffer (color)
302
cmpb %ah,BDA_SCR-BDA_POS(%ebx) # Mono mode?
303
jne putchr.1 # No
304
xorw %di,%di # Regen buffer (mono)
305
putchr.1: cmpb $0xa,%al # New line?
306
je putchr.2 # Yes
307
xchgl %eax,%ecx # Save char
308
movb $SCR_COL,%al # Columns per row
309
mulb %dh # * row position
310
addb %dl,%al # + column
311
adcb $0x0,%ah # position
312
shll %eax # * 2
313
xchgl %eax,%ecx # Swap char, offset
314
movw %ax,(%edi,%ecx,1) # Write attr:char
315
incl %edx # Bump cursor
316
cmpb $SCR_COL,%dl # Beyond row?
317
jb putchr.3 # No
318
putchr.2: xorb %dl,%dl # Zero column
319
incb %dh # Bump row
320
putchr.3: cmpb $SCR_ROW,%dh # Beyond screen?
321
jb putchr.4 # No
322
leal 2*SCR_COL(%edi),%esi # New top line
323
movw $(SCR_ROW-1)*SCR_COL/2,%cx # Words to move
324
rep # Scroll
325
movsl # screen
326
movb $' ',%al # Space
327
movb $SCR_COL,%cl # Columns to clear
328
rep # Clear
329
stosw # line
330
movb $SCR_ROW-1,%dh # Bottom line
331
putchr.4: movw %dx,(%ebx) # Update position
332
popa # Restore
333
putchr.5: ret # To caller
334
/*
335
* Convert EAX, AX, or AL to hex, saving the result to [EDI].
336
*/
337
hex32: pushl %eax # Save
338
shrl $0x10,%eax # Do upper
339
call hex16 # 16
340
popl %eax # Restore
341
hex16: call hex16.1 # Do upper 8
342
hex16.1: xchgb %ah,%al # Save/restore
343
hex8: pushl %eax # Save
344
shrb $0x4,%al # Do upper
345
call hex8.1 # 4
346
popl %eax # Restore
347
hex8.1: andb $0xf,%al # Get lower 4
348
cmpb $0xa,%al # Convert
349
sbbb $0x69,%al # to hex
350
das # digit
351
orb $0x20,%al # To lower case
352
stosb # Save char
353
ret # (Recursive)
354
355
.data
356
.p2align 4
357
/*
358
* Global descriptor table.
359
*/
360
gdt: .word 0x0,0x0,0x0,0x0 # Null entry
361
.word 0xffff,0x0,0x9a00,0xcf # SEL_SCODE
362
.word 0xffff,0x0,0x9200,0xcf # SEL_SDATA
363
.word 0xffff,0x0,0x9a00,0x0 # SEL_RCODE
364
.word 0xffff,0x0,0x9200,0x0 # SEL_RDATA
365
gdt.1:
366
gdtdesc: .word gdt.1-gdt-1 # Limit
367
.long gdt # Base
368
/*
369
* Messages.
370
*/
371
m_logo: .asciz " \nBTX loader 1.00 "
372
m_vers: .asciz "BTX version is \0\n"
373
e_fmt: .asciz "Error: Client format not supported\n"
374
#ifdef BTXLDR_VERBOSE
375
m_mem: .asciz "Starting in protected mode (base mem=\0)\n"
376
m_esp: .asciz "Arguments passed (esp=\0):\n"
377
m_args: .asciz "<howto="
378
.asciz " bootdev="
379
.asciz " junk="
380
.asciz " "
381
.asciz " "
382
.asciz " bootinfo=\0>\n"
383
m_rel_bi: .asciz "Relocated bootinfo (size=48) to \0\n"
384
m_rel_args: .asciz "Relocated arguments (size=18) to \0\n"
385
m_rel_btx: .asciz "Relocated kernel (size=\0) to \0\n"
386
m_base: .asciz "Client base address is \0\n"
387
m_elf: .asciz "Client format is ELF\n"
388
m_segs: .asciz "text segment: offset="
389
.asciz " vaddr="
390
.asciz " filesz="
391
.asciz " memsz=\0\n"
392
.asciz "data segment: offset="
393
.asciz " vaddr="
394
.asciz " filesz="
395
.asciz " memsz=\0\n"
396
m_done: .asciz "Loading complete\n"
397
#endif
398
399
/*
400
* Flags
401
*/
402
muted: .byte 0x0
403
404
/*
405
* Uninitialized data area.
406
*/
407
buf: # Scratch buffer
408
409