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
21 * Prototype BTX loader program, written in a couple of hours. The
22 * real thing should probably be more flexible, and in C.
28 .set MEM_STUB,0x600 # Real mode stub
29 .set MEM_ESP,0x1000 # New stack pointer
30 .set MEM_TBL,0x5000 # BTX page tables
31 .set MEM_ENTRY,0x9010 # BTX entry point
32 .set MEM_DATA,start+0x1000 # Data segment
36 .set SEL_SCODE,0x8 # 4GB code
37 .set SEL_SDATA,0x10 # 4GB data
38 .set SEL_RCODE,0x18 # 64K code
39 .set SEL_RDATA,0x20 # 64K data
43 .set PAG_SIZ,0x1000 # Page size
44 .set PAG_ENT,0x4 # Page entry size
48 .set SCR_MAT,0xe1 # Mode/attribute
49 .set SCR_COL,0x50 # Columns per row
50 .set SCR_ROW,0x19 # Rows per screen
52 * BIOS Data Area locations.
54 .set BDA_MEM,0xa1501 # Free memory
55 .set BDA_POS,0xa153e # Cursor position
57 * Required by aout gas inadequacy.
59 .set SIZ_STUB,0x1a # Size of stub
61 * We expect to be loaded by boot2 at the origin defined in ./Makefile.
65 * BTX program loader for ELF clients.
67 start: cld # String ops inc
69 gdcwait.1: inb $0x60,%al
75 gdcwait.2: inb $0x60,%al
88 movl $m_logo,%esi # Identify
89 call putstr # ourselves
90 movzwl BDA_MEM,%eax # Get base memory
93 shll $0x11,%eax # in bytes
94 movl %eax,%ebp # Base of user stack
96 movl $m_mem,%esi # Display
97 call hexout # amount of
98 call putstr # base memory
100 lgdt gdtdesc # Load new GDT
102 * Relocate caller's arguments.
104 #ifdef BTXLDR_VERBOSE
105 movl $m_esp,%esi # Display
106 movl %esp,%eax # caller
108 call putstr # pointer
109 movl $m_args,%esi # Format string
110 leal 0x4(%esp),%ebx # First argument
111 movl $0x6,%ecx # Count
112 start.1: movl (%ebx),%eax # Get argument and
113 addl $0x4,%ebx # bump pointer
114 call hexout # Display it
115 loop start.1 # Till done
116 call putstr # End message
118 movl BA_BOOTINFO+4(%esp),%esi # Source: bootinfo
119 cmpl $0x0, %esi # If the bootinfo pointer
120 je start_null_bi # is null, don't copy it
121 movl BI_SIZE(%esi),%ecx # Allocate space
122 subl %ecx,%ebp # for bootinfo
123 movl %ebp,%edi # Destination
126 movl %ebp,BA_BOOTINFO+4(%esp) # Update pointer
127 movl %edi,%ebp # Restore base pointer
128 #ifdef BTXLDR_VERBOSE
129 movl $m_rel_bi,%esi # Display
130 movl %ebp,%eax # bootinfo
131 call hexout # relocation
132 call putstr # message
134 start_null_bi: movl $BOOTARGS_SIZE,%ecx # Fixed size of arguments
135 testl $KARGS_FLAGS_EXTARG, BA_BOOTFLAGS+4(%esp) # Check for extra data
136 jz start_fixed # Skip if the flag is not set
137 addl BOOTARGS_SIZE+4(%esp),%ecx # Add size of variable args
138 start_fixed: subl $ARGOFF,%ebp # Place args at fixed offset
139 leal 0x4(%esp),%esi # Source
140 movl %ebp,%edi # Destination
143 #ifdef BTXLDR_VERBOSE
144 movl $m_rel_args,%esi # Display
145 movl %ebp,%eax # argument
146 call hexout # relocation
147 call putstr # message
152 movl $MEM_ESP,%esp # Set up new stack
153 movl $MEM_DATA,%ebx # Data segment
154 movl $m_vers,%esi # Display BTX
155 call putstr # version message
156 movb 0x5(%ebx),%al # Get major version
157 addb $'0',%al # Display
159 movb $'.',%al # And a
161 movb 0x6(%ebx),%al # Get minor
162 xorb %ah,%ah # version
163 movb $0xa,%dl # Divide
165 addb $'0',%al # Display
167 movb %ah,%al # Get units
168 addb $'0',%al # Display
170 call putstr # End message
171 movl %ebx,%esi # BTX image
172 movzwl 0x8(%ebx),%edi # Compute
173 orl $PAG_SIZ/PAG_ENT-1,%edi # the
175 shll $0x2,%edi # load
176 addl $MEM_TBL,%edi # address
177 pushl %edi # Save load address
178 movzwl 0xa(%ebx),%ecx # Image size
179 #ifdef BTXLDR_VERBOSE
180 pushl %ecx # Save image size
184 movl %esi,%ebx # Keep place
185 #ifdef BTXLDR_VERBOSE
186 movl $m_rel_btx,%esi # Restore
187 popl %eax # parameters
191 #ifdef BTXLDR_VERBOSE
193 call hexout # relocation
194 call putstr # message
196 addl $PAG_SIZ,%ebp # Display
197 #ifdef BTXLDR_VERBOSE
198 movl $m_base,%esi # the
199 movl %ebp,%eax # user
201 call putstr # address
204 * Set up ELF-format client program.
206 cmpl $0x464c457f,(%ebx) # ELF magic number?
208 movl $e_fmt,%esi # Display error
209 call putstr # message
210 start.2: jmp start.2 # Hang
212 #ifdef BTXLDR_VERBOSE
213 movl $m_elf,%esi # Display ELF
214 call putstr # message
215 movl $m_segs,%esi # Format string
217 movl $0x2,%edi # Segment count
218 movl 0x1c(%ebx),%edx # Get e_phoff
219 addl %ebx,%edx # To pointer
220 movzwl 0x2c(%ebx),%ecx # Get e_phnum
221 start.4: cmpl $0x1,(%edx) # Is p_type PT_LOAD?
223 #ifdef BTXLDR_VERBOSE
224 movl 0x4(%edx),%eax # Display
225 call hexout # p_offset
226 movl 0x8(%edx),%eax # Display
227 call hexout # p_vaddr
228 movl 0x10(%edx),%eax # Display
229 call hexout # p_filesz
230 movl 0x14(%edx),%eax # Display
231 call hexout # p_memsz
232 call putstr # End message
236 pushl %ecx # registers
237 movl 0x4(%edx),%esi # Get p_offset
238 addl %ebx,%esi # as pointer
239 movl 0x8(%edx),%edi # Get p_vaddr
240 addl %ebp,%edi # as pointer
241 movl 0x10(%edx),%ecx # Get p_filesz
244 movl 0x14(%edx),%ecx # Any bytes
245 subl 0x10(%edx),%ecx # to zero?
250 start.5: popl %ecx # Restore
252 popl %esi # registers
253 decl %edi # Segments to do
255 start.6: addl $0x20,%edx # To next entry
256 loop start.4 # Till done
258 #ifdef BTXLDR_VERBOSE
259 movl $m_done,%esi # Display done
260 call putstr # message
262 movl $start.8,%esi # Real mode stub
263 movl $MEM_STUB,%edi # Destination
264 movl $start.9-start.8,%ecx # Size
267 ljmp $SEL_RCODE,$MEM_STUB # To 16-bit code
269 start.8: xorw %ax,%ax # Data
270 movb $SEL_RDATA,%al # selector
271 movw %ax,%ss # Reload SS
274 movw %ax,%fs # segment
275 movw %ax,%gs # limits
276 movl %cr0,%eax # Switch to
278 movl %eax,%cr0 # mode
279 ljmp $0,$MEM_ENTRY # Jump to BTX entry point
283 * Output message [ESI] followed by EAX in hex.
285 hexout: pushl %eax # Save
286 call putstr # Display message
289 pushl %edi # caller's
290 movl $buf,%edi # Buffer
293 xorb %al,%al # Terminate
296 hexout.1: lodsb # Get a char
297 cmpb $'0',%al # Leading zero?
299 testb %al,%al # End of string?
302 hexout.2: decl %esi # Adjust for inc
303 call putstr # Display hex
308 * Output zero-terminated string [ESI] to the console.
310 putstr.0: call putchr # Output char
311 putstr: lodsb # Load char
312 testb %al,%al # End of string?
316 * Output character AL to the console.
319 xorl %ecx,%ecx # Zero for loops
320 movb $SCR_MAT,%ah # Mode/attribute
321 movl $BDA_POS,%ebx # BDA pointer
322 movw (%ebx),%dx # Cursor position
323 movl $0xa0000,%edi # Regen buffer (color)
324 putchr.1: cmpb $0xa,%al # New line?
327 movb %al,(%edi,%ecx,1) # Write char
329 movb %ah,(%edi,%ecx,1) # Write attr
332 putchr.2: movw %dx,%ax
338 putchr.3: cmpw $SCR_COL*SCR_ROW*2,%dx
340 leal 2*SCR_COL(%edi),%esi # New top line
341 movw $(SCR_ROW-1)*SCR_COL/2,%cx # Words to move
344 movb $' ',%al # Space
346 movb $SCR_COL,%cl # Columns to clear
349 movw $(SCR_ROW-1)*SCR_COL*2,%dx
350 putchr.4: movw %dx,(%ebx) # Update position
352 gdcwait.3: inb $0x60,%al
364 * Convert EAX, AX, or AL to hex, saving the result to [EDI].
366 hex32: pushl %eax # Save
367 shrl $0x10,%eax # Do upper
370 hex16: call hex16.1 # Do upper 8
371 hex16.1: xchgb %ah,%al # Save/restore
372 hex8: pushl %eax # Save
373 shrb $0x4,%al # Do upper
376 hex8.1: andb $0xf,%al # Get lower 4
377 cmpb $0xa,%al # Convert
378 sbbb $0x69,%al # to hex
380 orb $0x20,%al # To lower case
387 * Global descriptor table.
389 gdt: .word 0x0,0x0,0x0,0x0 # Null entry
390 .word 0xffff,0x0,0x9a00,0xcf # SEL_SCODE
391 .word 0xffff,0x0,0x9200,0xcf # SEL_SDATA
392 .word 0xffff,0x0,0x9a00,0x0 # SEL_RCODE
393 .word 0xffff,0x0,0x9200,0x0 # SEL_RDATA
395 gdtdesc: .word gdt.1-gdt-1 # Limit
400 m_logo: .asciz " \nBTX loader 1.00 "
401 m_vers: .asciz "BTX version is \0\n"
402 e_fmt: .asciz "Error: Client format not supported\n"
403 #ifdef BTXLDR_VERBOSE
404 m_mem: .asciz "Starting in protected mode (base mem=\0)\n"
405 m_esp: .asciz "Arguments passed (esp=\0):\n"
406 m_args: .asciz"<howto="
411 .asciz" bootinfo=\0>\n"
412 m_rel_bi: .asciz "Relocated bootinfo (size=48) to \0\n"
413 m_rel_args: .asciz "Relocated arguments (size=18) to \0\n"
414 m_rel_btx: .asciz "Relocated kernel (size=\0) to \0\n"
415 m_base: .asciz "Client base address is \0\n"
416 m_elf: .asciz "Client format is ELF\n"
417 m_segs: .asciz "text segment: offset="
421 .asciz "data segment: offset="
425 m_done: .asciz "Loading complete\n"
428 * Uninitialized data area.
430 buf: # Scratch buffer