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/i386/btx/btxldr/btxldr.s,v 1.8.2.2 2000/07/06 23:04:29 obrien Exp $
19 # Prototype BTX loader program, written in a couple of hours. The
20 # real thing should probably be more flexible, and in C.
26 .set MEM_STUB,0x600 # Real mode stub
27 .set MEM_ESP,0x1000 # New stack pointer
28 .set MEM_TBL,0x5000 # BTX page tables
29 .set MEM_ENTRY,0x9010 # BTX entry point
30 .set MEM_DATA,start+0x1000 # Data segment
34 .set SEL_SCODE,0x8 # 4GB code
35 .set SEL_SDATA,0x10 # 4GB data
36 .set SEL_RCODE,0x18 # 64K code
37 .set SEL_RDATA,0x20 # 64K data
41 .set PAG_SIZ,0x1000 # Page size
42 .set PAG_ENT,0x4 # Page entry size
46 .set SCR_MAT,0x7 # Mode/attribute
47 .set SCR_COL,0x50 # Columns per row
48 .set SCR_ROW,0x19 # Rows per screen
50 # BIOS Data Area locations.
52 .set BDA_MEM,0x413 # Free memory
53 .set BDA_SCR,0x449 # Video mode
54 .set BDA_POS,0x450 # Cursor position
56 # Required by aout gas inadequacy.
58 .set SIZ_STUB,0x1a # Size of stub
60 # We expect to be loaded by boot2 at the origin defined in ./Makefile.
64 # BTX program loader for ELF clients.
66 start: cld # String ops inc
67 movl $m_logo,%esi # Identify
68 call putstr # ourselves
69 movzwl BDA_MEM,%eax # Get base memory
70 shll $0xa,%eax # in bytes
71 movl %eax,%ebp # Base of user stack
72 ifdef(`BTXLDR_VERBOSE',`
73 movl $m_mem,%esi # Display
74 call hexout # amount of
75 call putstr # base memory
77 lgdt gdtdesc # Load new GDT
79 # Relocate caller's arguments.
81 ifdef('BTXLDR_VERBOSE',`
82 movl $m_esp,%esi # Display
83 movl %esp,%eax # caller
86 movl $m_args,%esi # Format string
87 leal 0x4(%esp,1),%ebx # First argument
88 movl $0x6,%ecx # Count
89 start.1: movl (%ebx),%eax # Get argument and
90 addl $0x4,%ebx # bump pointer
91 call hexout # Display it
92 loop start.1 # Till done
93 call putstr # End message
95 movl $0x48,%ecx # Allocate space
96 subl %ecx,%ebp # for bootinfo
97 movl 0x18(%esp,1),%esi # Source: bootinfo
98 cmpl $0x0, %esi # If the bootinfo pointer
99 je start_null_bi # is null, don't copy it
100 movl %ebp,%edi # Destination
103 movl %ebp,0x18(%esp,1) # Update pointer
104 ifdef(`BTXLDR_VERBOSE',`
105 movl $m_rel_bi,%esi # Display
106 movl %ebp,%eax # bootinfo
107 call hexout # relocation
108 call putstr # message
110 start_null_bi: movl $0x18,%ecx # Allocate space
111 subl %ecx,%ebp # for arguments
112 leal 0x4(%esp,1),%esi # Source
113 movl %ebp,%edi # Destination
116 ifdef(`BTXLDR_VERBOSE',`
117 movl $m_rel_args,%esi # Display
118 movl %ebp,%eax # argument
119 call hexout # relocation
120 call putstr # message
125 movl $MEM_ESP,%esp # Set up new stack
126 movl $MEM_DATA,%ebx # Data segment
127 movl $m_vers,%esi # Display BTX
128 call putstr # version message
129 movb 0x5(%ebx),%al # Get major version
130 addb $'0',%al # Display
132 movb $'.',%al # And a
134 movb 0x6(%ebx),%al # Get minor
135 xorb %ah,%ah # version
136 movb $0xa,%dl # Divide
138 addb $'0',%al # Display
140 movb %ah,%al # Get units
141 addb $'0',%al # Display
143 call putstr # End message
144 movl %ebx,%esi # BTX image
145 movzwl 0x8(%ebx),%edi # Compute
146 orl $PAG_SIZ/PAG_ENT-1,%edi # the
148 shll $0x2,%edi # load
149 addl $MEM_TBL,%edi # address
150 pushl %edi # Save load address
151 movzwl 0xa(%ebx),%ecx # Image size
152 ifdef(`BTXLDR_VERBOSE',`
153 pushl %ecx # Save image size
157 movl %esi,%ebx # Keep place
158 ifdef(`BTXLDR_VERBOSE',`
159 movl $m_rel_btx,%esi # Restore
160 popl %eax # parameters
164 ifdef(`BTXLDR_VERBOSE',`
166 call hexout # relocation
167 call putstr # message
169 addl $PAG_SIZ,%ebp # Display
170 ifdef(`BTXLDR_VERBOSE',`
171 movl $m_base,%esi # the
172 movl %ebp,%eax # user
174 call putstr # address
177 # Set up ELF-format client program.
179 cmpl $0x464c457f,(%ebx) # ELF magic number?
181 movl $e_fmt,%esi # Display error
182 call putstr # message
183 start.2: jmp start.2 # Hang
185 ifdef(`BTXLDR_VERBOSE',`
186 movl $m_elf,%esi # Display ELF
187 call putstr # message
188 movl $m_segs,%esi # Format string
190 movl $0x2,%edi # Segment count
191 movl 0x1c(%ebx),%edx # Get e_phoff
192 addl %ebx,%edx # To pointer
193 movzwl 0x2c(%ebx),%ecx # Get e_phnum
194 start.4: cmpl $0x1,(%edx) # Is p_type PT_LOAD?
196 ifdef(`BTXLDR_VERBOSE',`
197 movl 0x4(%edx),%eax # Display
198 call hexout # p_offset
199 movl 0x8(%edx),%eax # Display
200 call hexout # p_vaddr
201 movl 0x10(%edx),%eax # Display
202 call hexout # p_filesz
203 movl 0x14(%edx),%eax # Display
204 call hexout # p_memsz
205 call putstr # End message
209 pushl %ecx # registers
210 movl 0x4(%edx),%esi # Get p_offset
211 addl %ebx,%esi # as pointer
212 movl 0x8(%edx),%edi # Get p_vaddr
213 addl %ebp,%edi # as pointer
214 movl 0x10(%edx),%ecx # Get p_filesz
217 movl 0x14(%edx),%ecx # Any bytes
218 subl 0x10(%edx),%ecx # to zero?
223 start.5: popl %ecx # Restore
225 popl %esi # registers
226 decl %edi # Segments to do
228 start.6: addl $0x20,%edx # To next entry
229 loop start.4 # Till done
231 ifdef(`BTXLDR_VERBOSE',`
232 movl $m_done,%esi # Display done
233 call putstr # message
235 movl $start.8,%esi # Real mode stub
236 movl $MEM_STUB,%edi # Destination
237 movl $start.9-start.8,%ecx # Size
240 ljmp $SEL_RCODE,$MEM_STUB # To 16-bit code
242 start.8: xorw %ax,%ax # Data
243 movb $SEL_RDATA,%al # selector
244 movw %ax,%ss # Reload SS
247 movw %ax,%fs # segment
248 movw %ax,%gs # limits
249 movl %cr0,%eax # Switch to
251 movl %eax,%cr0 # mode
252 ljmp $0,$MEM_ENTRY # Jump to BTX entry point
256 # Output message [ESI] followed by EAX in hex.
258 hexout: pushl %eax # Save
259 call putstr # Display message
262 pushl %edi # caller's
263 movl $buf,%edi # Buffer
266 xorb %al,%al # Terminate
269 hexout.1: lodsb # Get a char
270 cmpb $'0',%al # Leading zero?
272 testb %al,%al # End of string?
275 hexout.2: decl %esi # Adjust for inc
276 call putstr # Display hex
281 # Output zero-terminated string [ESI] to the console.
283 putstr.0: call putchr # Output char
284 putstr: lodsb # Load char
285 testb %al,%al # End of string?
289 # Output character AL to the console.
292 xorl %ecx,%ecx # Zero for loops
293 movb $SCR_MAT,%ah # Mode/attribute
294 movl $BDA_POS,%ebx # BDA pointer
295 movw (%ebx),%dx # Cursor position
296 movl $0xb8000,%edi # Regen buffer (color)
297 cmpb %ah,BDA_SCR-BDA_POS(%ebx) # Mono mode?
299 xorw %di,%di # Regen buffer (mono)
300 putchr.1: cmpb $0xa,%al # New line?
302 xchgl %eax,%ecx # Save char
303 movb $SCR_COL,%al # Columns per row
304 mulb %dh # * row position
305 addb %dl,%al # + column
306 adcb $0x0,%ah # position
308 xchgl %eax,%ecx # Swap char, offset
309 movw %ax,(%edi,%ecx,1) # Write attr:char
310 incl %edx # Bump cursor
311 cmpb $SCR_COL,%dl # Beyond row?
313 putchr.2: xorb %dl,%dl # Zero column
315 putchr.3: cmpb $SCR_ROW,%dh # Beyond screen?
317 leal 2*SCR_COL(%edi),%esi # New top line
318 movw $(SCR_ROW-1)*SCR_COL/2,%cx # Words to move
321 movb $' ',%al # Space
322 movb $SCR_COL,%cl # Columns to clear
325 movb $SCR_ROW-1,%dh # Bottom line
326 putchr.4: movw %dx,(%ebx) # Update position
330 # Convert EAX, AX, or AL to hex, saving the result to [EDI].
332 hex32: pushl %eax # Save
333 shrl $0x10,%eax # Do upper
336 hex16: call hex16.1 # Do upper 8
337 hex16.1: xchgb %ah,%al # Save/restore
338 hex8: pushl %eax # Save
339 shrb $0x4,%al # Do upper
342 hex8.1: andb $0xf,%al # Get lower 4
343 cmpb $0xa,%al # Convert
344 sbbb $0x69,%al # to hex
346 orb $0x20,%al # To lower case
353 # Global descriptor table.
355 gdt: .word 0x0,0x0,0x0,0x0 # Null entry
356 .word 0xffff,0x0,0x9a00,0xcf # SEL_SCODE
357 .word 0xffff,0x0,0x9200,0xcf # SEL_SDATA
358 .word 0xffff,0x0,0x9a00,0x0 # SEL_RCODE
359 .word 0xffff,0x0,0x9200,0x0 # SEL_RDATA
361 gdtdesc: .word gdt.1-gdt-1 # Limit
366 m_logo: .asciz " \nBTX loader 1.00 "
367 m_vers: .asciz "BTX version is \0\n"
368 e_fmt: .asciz "Error: Client format not supported\n"
369 ifdef(`BTXLDR_VERBOSE',`
370 m_mem: .asciz "Starting in protected mode (base mem=\0)\n"
371 m_esp: .asciz "Arguments passed (esp=\0):\n"
372 m_args: .asciz"<howto="
377 .asciz" bootinfo=\0>\n"
378 m_rel_bi: .asciz "Relocated bootinfo (size=48) to \0\n"
379 m_rel_args: .asciz "Relocated arguments (size=18) to \0\n"
380 m_rel_btx: .asciz "Relocated kernel (size=\0) to \0\n"
381 m_base: .asciz "Client base address is \0\n"
382 m_elf: .asciz "Client format is ELF\n"
383 m_segs: .asciz "text segment: offset="
387 .asciz "data segment: offset="
391 m_done: .asciz "Loading complete\n"
394 # Uninitialized data area.
396 buf: # Scratch buffer