2 # Copyright (c) 1998 Robert Nordier
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
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
16 # $FreeBSD: src/sys/boot/pc98/btx/btxldr/btxldr.s,v 1.3.2.2 2000/07/06 23:04:33 obrien Exp $
17 # $DragonFly: src/sys/boot/pc98/btx/btxldr/Attic/btxldr.s,v 1.2 2003/06/17 04:28:18 dillon Exp $
20 # Prototype BTX loader program, written in a couple of hours. The
21 # real thing should probably be more flexible, and in C.
27 .set MEM_STUB,0x600 # Real mode stub
28 .set MEM_ESP,0x1000 # New stack pointer
29 .set MEM_TBL,0x5000 # BTX page tables
30 .set MEM_ENTRY,0x9010 # BTX entry point
31 .set MEM_DATA,start+0x1000 # Data segment
35 .set SEL_SCODE,0x8 # 4GB code
36 .set SEL_SDATA,0x10 # 4GB data
37 .set SEL_RCODE,0x18 # 64K code
38 .set SEL_RDATA,0x20 # 64K data
42 .set PAG_SIZ,0x1000 # Page size
43 .set PAG_ENT,0x4 # Page entry size
48 .set SCR_MAT,0xe1 # Mode/attribute
50 .set SCR_MAT,0x7 # Mode/attribute
52 .set SCR_COL,0x50 # Columns per row
53 .set SCR_ROW,0x19 # Rows per screen
55 # BIOS Data Area locations.
58 .set BDA_MEM,0xa1501 # Free memory
59 .set BDA_POS,0xa153e # Cursor position
61 .set BDA_MEM,0x413 # Free memory
62 .set BDA_SCR,0x449 # Video mode
63 .set BDA_POS,0x450 # Cursor position
66 # Required by aout gas inadequacy.
68 .set SIZ_STUB,0x1a # Size of stub
70 # We expect to be loaded by boot2 at the origin defined in ./Makefile.
74 # BTX program loader for ELF clients.
76 start: cld # String ops inc
79 gdcwait.1: inb $0x60,%al
85 gdcwait.2: inb $0x60,%al
99 movl $m_logo,%esi # Identify
100 call putstr # ourselves
101 movzwl BDA_MEM,%eax # Get base memory
105 shll $0x11,%eax # in bytes
107 shll $0xa,%eax # in bytes
109 movl %eax,%ebp # Base of user stack
110 ifdef(`BTXLDR_VERBOSE',`
111 movl $m_mem,%esi # Display
112 call hexout # amount of
113 call putstr # base memory
115 lgdt gdtdesc # Load new GDT
117 # Relocate caller's arguments.
119 ifdef('BTXLDR_VERBOSE',`
120 movl $m_esp,%esi # Display
121 movl %esp,%eax # caller
123 call putstr # pointer
124 movl $m_args,%esi # Format string
125 leal 0x4(%esp,1),%ebx # First argument
126 movl $0x6,%ecx # Count
127 start.1: movl (%ebx),%eax # Get argument and
128 addl $0x4,%ebx # bump pointer
129 call hexout # Display it
130 loop start.1 # Till done
131 call putstr # End message
133 movl $0x48,%ecx # Allocate space
134 subl %ecx,%ebp # for bootinfo
135 movl 0x18(%esp,1),%esi # Source: bootinfo
136 cmpl $0x0, %esi # If the bootinfo pointer
137 je start_null_bi # is null, don't copy it
138 movl %ebp,%edi # Destination
141 movl %ebp,0x18(%esp,1) # Update pointer
142 ifdef(`BTXLDR_VERBOSE',`
143 movl $m_rel_bi,%esi # Display
144 movl %ebp,%eax # bootinfo
145 call hexout # relocation
146 call putstr # message
148 start_null_bi: movl $0x18,%ecx # Allocate space
149 subl %ecx,%ebp # for arguments
150 leal 0x4(%esp,1),%esi # Source
151 movl %ebp,%edi # Destination
154 ifdef(`BTXLDR_VERBOSE',`
155 movl $m_rel_args,%esi # Display
156 movl %ebp,%eax # argument
157 call hexout # relocation
158 call putstr # message
163 movl $MEM_ESP,%esp # Set up new stack
164 movl $MEM_DATA,%ebx # Data segment
165 movl $m_vers,%esi # Display BTX
166 call putstr # version message
167 movb 0x5(%ebx),%al # Get major version
168 addb $'0',%al # Display
170 movb $'.',%al # And a
172 movb 0x6(%ebx),%al # Get minor
173 xorb %ah,%ah # version
174 movb $0xa,%dl # Divide
176 addb $'0',%al # Display
178 movb %ah,%al # Get units
179 addb $'0',%al # Display
181 call putstr # End message
182 movl %ebx,%esi # BTX image
183 movzwl 0x8(%ebx),%edi # Compute
184 orl $PAG_SIZ/PAG_ENT-1,%edi # the
186 shll $0x2,%edi # load
187 addl $MEM_TBL,%edi # address
188 pushl %edi # Save load address
189 movzwl 0xa(%ebx),%ecx # Image size
190 ifdef(`BTXLDR_VERBOSE',`
191 pushl %ecx # Save image size
195 movl %esi,%ebx # Keep place
196 ifdef(`BTXLDR_VERBOSE',`
197 movl $m_rel_btx,%esi # Restore
198 popl %eax # parameters
202 ifdef(`BTXLDR_VERBOSE',`
204 call hexout # relocation
205 call putstr # message
207 addl $PAG_SIZ,%ebp # Display
208 ifdef(`BTXLDR_VERBOSE',`
209 movl $m_base,%esi # the
210 movl %ebp,%eax # user
212 call putstr # address
215 # Set up ELF-format client program.
217 cmpl $0x464c457f,(%ebx) # ELF magic number?
219 movl $e_fmt,%esi # Display error
220 call putstr # message
221 start.2: jmp start.2 # Hang
223 ifdef(`BTXLDR_VERBOSE',`
224 movl $m_elf,%esi # Display ELF
225 call putstr # message
226 movl $m_segs,%esi # Format string
228 movl $0x2,%edi # Segment count
229 movl 0x1c(%ebx),%edx # Get e_phoff
230 addl %ebx,%edx # To pointer
231 movzwl 0x2c(%ebx),%ecx # Get e_phnum
232 start.4: cmpl $0x1,(%edx) # Is p_type PT_LOAD?
234 ifdef(`BTXLDR_VERBOSE',`
235 movl 0x4(%edx),%eax # Display
236 call hexout # p_offset
237 movl 0x8(%edx),%eax # Display
238 call hexout # p_vaddr
239 movl 0x10(%edx),%eax # Display
240 call hexout # p_filesz
241 movl 0x14(%edx),%eax # Display
242 call hexout # p_memsz
243 call putstr # End message
247 pushl %ecx # registers
248 movl 0x4(%edx),%esi # Get p_offset
249 addl %ebx,%esi # as pointer
250 movl 0x8(%edx),%edi # Get p_vaddr
251 addl %ebp,%edi # as pointer
252 movl 0x10(%edx),%ecx # Get p_filesz
255 movl 0x14(%edx),%ecx # Any bytes
256 subl 0x10(%edx),%ecx # to zero?
261 start.5: popl %ecx # Restore
263 popl %esi # registers
264 decl %edi # Segments to do
266 start.6: addl $0x20,%edx # To next entry
267 loop start.4 # Till done
269 ifdef(`BTXLDR_VERBOSE',`
270 movl $m_done,%esi # Display done
271 call putstr # message
273 movl $start.8,%esi # Real mode stub
274 movl $MEM_STUB,%edi # Destination
275 movl $start.9-start.8,%ecx # Size
278 ljmp $SEL_RCODE,$MEM_STUB # To 16-bit code
280 start.8: xorw %ax,%ax # Data
281 movb $SEL_RDATA,%al # selector
282 movw %ax,%ss # Reload SS
285 movw %ax,%fs # segment
286 movw %ax,%gs # limits
287 movl %cr0,%eax # Switch to
289 movl %eax,%cr0 # mode
290 ljmp $0,$MEM_ENTRY # Jump to BTX entry point
294 # Output message [ESI] followed by EAX in hex.
296 hexout: pushl %eax # Save
297 call putstr # Display message
300 pushl %edi # caller's
301 movl $buf,%edi # Buffer
304 xorb %al,%al # Terminate
307 hexout.1: lodsb # Get a char
308 cmpb $'0',%al # Leading zero?
310 testb %al,%al # End of string?
313 hexout.2: decl %esi # Adjust for inc
314 call putstr # Display hex
319 # Output zero-terminated string [ESI] to the console.
321 putstr.0: call putchr # Output char
322 putstr: lodsb # Load char
323 testb %al,%al # End of string?
327 # Output character AL to the console.
330 xorl %ecx,%ecx # Zero for loops
331 movb $SCR_MAT,%ah # Mode/attribute
332 movl $BDA_POS,%ebx # BDA pointer
333 movw (%ebx),%dx # Cursor position
335 movl $0xa0000,%edi # Regen buffer (color)
337 movl $0xb8000,%edi # Regen buffer (color)
338 cmpb %ah,BDA_SCR-BDA_POS(%ebx) # Mono mode?
340 xorw %di,%di # Regen buffer (mono)
342 putchr.1: cmpb $0xa,%al # New line?
346 movb %al,(%edi,%ecx,1) # Write char
348 movb %ah,(%edi,%ecx,1) # Write attr
351 putchr.2: movw %dx,%ax
357 putchr.3: cmpw $SCR_COL*SCR_ROW*2,%dx
359 xchgl %eax,%ecx # Save char
360 movb $SCR_COL,%al # Columns per row
361 mulb %dh # * row position
362 addb %dl,%al # + column
363 adcb $0x0,%ah # position
365 xchgl %eax,%ecx # Swap char, offset
366 movw %ax,(%edi,%ecx,1) # Write attr:char
367 incl %edx # Bump cursor
368 cmpb $SCR_COL,%dl # Beyond row?
370 putchr.2: xorb %dl,%dl # Zero column
372 putchr.3: cmpb $SCR_ROW,%dh # Beyond screen?
375 leal 2*SCR_COL(%edi),%esi # New top line
376 movw $(SCR_ROW-1)*SCR_COL/2,%cx # Words to move
379 movb $' ',%al # Space
383 movb $SCR_COL,%cl # Columns to clear
387 movw $(SCR_ROW-1)*SCR_COL*2,%dx
388 putchr.4: movw %dx,(%ebx) # Update position
390 gdcwait.3: inb $0x60,%al
400 movb $SCR_ROW-1,%dh # Bottom line
401 putchr.4: movw %dx,(%ebx) # Update position
406 # Convert EAX, AX, or AL to hex, saving the result to [EDI].
408 hex32: pushl %eax # Save
409 shrl $0x10,%eax # Do upper
412 hex16: call hex16.1 # Do upper 8
413 hex16.1: xchgb %ah,%al # Save/restore
414 hex8: pushl %eax # Save
415 shrb $0x4,%al # Do upper
418 hex8.1: andb $0xf,%al # Get lower 4
419 cmpb $0xa,%al # Convert
420 sbbb $0x69,%al # to hex
422 orb $0x20,%al # To lower case
429 # Global descriptor table.
431 gdt: .word 0x0,0x0,0x0,0x0 # Null entry
432 .word 0xffff,0x0,0x9a00,0xcf # SEL_SCODE
433 .word 0xffff,0x0,0x9200,0xcf # SEL_SDATA
434 .word 0xffff,0x0,0x9a00,0x0 # SEL_RCODE
435 .word 0xffff,0x0,0x9200,0x0 # SEL_RDATA
437 gdtdesc: .word gdt.1-gdt-1 # Limit
442 m_logo: .asciz " \nBTX loader 1.00 "
443 m_vers: .asciz "BTX version is \0\n"
444 e_fmt: .asciz "Error: Client format not supported\n"
445 ifdef(`BTXLDR_VERBOSE',`
446 m_mem: .asciz "Starting in protected mode (base mem=\0)\n"
447 m_esp: .asciz "Arguments passed (esp=\0):\n"
448 m_args: .asciz"<howto="
453 .asciz" bootinfo=\0>\n"
454 m_rel_bi: .asciz "Relocated bootinfo (size=48) to \0\n"
455 m_rel_args: .asciz "Relocated arguments (size=18) to \0\n"
456 m_rel_btx: .asciz "Relocated kernel (size=\0) to \0\n"
457 m_base: .asciz "Client base address is \0\n"
458 m_elf: .asciz "Client format is ELF\n"
459 m_segs: .asciz "text segment: offset="
463 .asciz "data segment: offset="
467 m_done: .asciz "Loading complete\n"
470 # Uninitialized data area.
472 buf: # Scratch buffer