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
20 #define RBX_MUTE 0x10 /* -m */
21 #define OPT_SET(opt) (1 << (opt))
24 * Prototype BTX loader program, written in a couple of hours. The
25 * real thing should probably be more flexible, and in C.
31 .set MEM_STUB,0x600 # Real mode stub
32 .set MEM_ESP,0x1000 # New stack pointer
33 .set MEM_TBL,0x5000 # BTX page tables
34 .set MEM_ENTRY,0x9010 # BTX entry point
35 .set MEM_DATA,start+0x1000 # Data segment
39 .set SEL_SCODE,0x8 # 4GB code
40 .set SEL_SDATA,0x10 # 4GB data
41 .set SEL_RCODE,0x18 # 64K code
42 .set SEL_RDATA,0x20 # 64K data
46 .set PAG_SIZ,0x1000 # Page size
47 .set PAG_ENT,0x4 # Page entry size
51 .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.
57 .set BDA_MEM,0x413 # Free memory
58 .set BDA_SCR,0x449 # Video mode
59 .set BDA_POS,0x450 # Cursor position
61 * Required by aout gas inadequacy.
63 .set SIZ_STUB,0x1a # Size of stub
65 * We expect to be loaded by boot2 at the origin defined in ./Makefile.
69 * BTX program loader for ELF clients.
71 start: cld # String ops inc
72 testl $OPT_SET(RBX_MUTE), 4(%esp) # Check first argument
73 setnz muted # for RBX_MUTE, set flag
74 movl $m_logo,%esi # Identify
75 call putstr # ourselves
76 movzwl BDA_MEM,%eax # Get base memory
77 shll $0xa,%eax # in bytes
78 movl %eax,%ebp # Base of user stack
80 movl $m_mem,%esi # Display
81 call hexout # amount of
82 call putstr # base memory
84 lgdt gdtdesc # Load new GDT
86 * Relocate caller's arguments.
89 movl $m_esp,%esi # Display
90 movl %esp,%eax # caller
93 movl $m_args,%esi # Format string
94 leal 0x4(%esp),%ebx # First argument
95 movl $0x6,%ecx # Count
96 start.1: movl (%ebx),%eax # Get argument and
97 addl $0x4,%ebx # bump pointer
98 call hexout # Display it
99 loop start.1 # Till done
100 call putstr # End message
102 movl BA_BOOTINFO+4(%esp),%esi # Source: bootinfo
103 cmpl $0x0, %esi # If the bootinfo pointer
104 je start_null_bi # is null, don't copy it
105 movl BI_SIZE(%esi),%ecx # Allocate space
106 subl %ecx,%ebp # for bootinfo
107 movl %ebp,%edi # Destination
110 movl %ebp,BA_BOOTINFO+4(%esp) # Update pointer
111 movl %edi,%ebp # Restore base pointer
112 #ifdef BTXLDR_VERBOSE
113 movl $m_rel_bi,%esi # Display
114 movl %ebp,%eax # bootinfo
115 call hexout # relocation
116 call putstr # message
118 start_null_bi: movl $BOOTARGS_SIZE,%ecx # Fixed size of arguments
119 testl $KARGS_FLAGS_EXTARG, BA_BOOTFLAGS+4(%esp) # Check for extra data
120 jz start_fixed # Skip if the flag is not set
121 addl BOOTARGS_SIZE+4(%esp),%ecx # Add size of variable args
122 start_fixed: subl $ARGOFF,%ebp # Place args at fixed offset
123 leal 0x4(%esp),%esi # Source
124 movl %ebp,%edi # Destination
127 #ifdef BTXLDR_VERBOSE
128 movl $m_rel_args,%esi # Display
129 movl %ebp,%eax # argument
130 call hexout # relocation
131 call putstr # message
136 movl $MEM_ESP,%esp # Set up new stack
137 movl $MEM_DATA,%ebx # Data segment
138 movl $m_vers,%esi # Display BTX
139 call putstr # version message
140 movb 0x5(%ebx),%al # Get major version
141 addb $'0',%al # Display
143 movb $'.',%al # And a
145 movb 0x6(%ebx),%al # Get minor
146 xorb %ah,%ah # version
147 movb $0xa,%dl # Divide
149 addb $'0',%al # Display
151 movb %ah,%al # Get units
152 addb $'0',%al # Display
154 call putstr # End message
155 movl %ebx,%esi # BTX image
156 movzwl 0x8(%ebx),%edi # Compute
157 orl $PAG_SIZ/PAG_ENT-1,%edi # the
159 shll $0x2,%edi # load
160 addl $MEM_TBL,%edi # address
161 pushl %edi # Save load address
162 movzwl 0xa(%ebx),%ecx # Image size
163 #ifdef BTXLDR_VERBOSE
164 pushl %ecx # Save image size
168 movl %esi,%ebx # Keep place
169 #ifdef BTXLDR_VERBOSE
170 movl $m_rel_btx,%esi # Restore
171 popl %eax # parameters
175 #ifdef BTXLDR_VERBOSE
177 call hexout # relocation
178 call putstr # message
180 addl $PAG_SIZ,%ebp # Display
181 #ifdef BTXLDR_VERBOSE
182 movl $m_base,%esi # the
183 movl %ebp,%eax # user
185 call putstr # address
188 * Set up ELF-format client program.
190 cmpl $0x464c457f,(%ebx) # ELF magic number?
192 movl $e_fmt,%esi # Display error
193 call putstr # message
194 start.2: jmp start.2 # Hang
196 #ifdef BTXLDR_VERBOSE
197 movl $m_elf,%esi # Display ELF
198 call putstr # message
199 movl $m_segs,%esi # Format string
201 movl $0x2,%edi # Segment count
202 movl 0x1c(%ebx),%edx # Get e_phoff
203 addl %ebx,%edx # To pointer
204 movzwl 0x2c(%ebx),%ecx # Get e_phnum
205 start.4: cmpl $0x1,(%edx) # Is p_type PT_LOAD?
207 #ifdef BTXLDR_VERBOSE
208 movl 0x4(%edx),%eax # Display
209 call hexout # p_offset
210 movl 0x8(%edx),%eax # Display
211 call hexout # p_vaddr
212 movl 0x10(%edx),%eax # Display
213 call hexout # p_filesz
214 movl 0x14(%edx),%eax # Display
215 call hexout # p_memsz
216 call putstr # End message
220 pushl %ecx # registers
221 movl 0x4(%edx),%esi # Get p_offset
222 addl %ebx,%esi # as pointer
223 movl 0x8(%edx),%edi # Get p_vaddr
224 addl %ebp,%edi # as pointer
225 movl 0x10(%edx),%ecx # Get p_filesz
228 movl 0x14(%edx),%ecx # Any bytes
229 subl 0x10(%edx),%ecx # to zero?
234 start.5: popl %ecx # Restore
236 popl %esi # registers
237 decl %edi # Segments to do
239 start.6: addl $0x20,%edx # To next entry
240 loop start.4 # Till done
242 #ifdef BTXLDR_VERBOSE
243 movl $m_done,%esi # Display done
244 call putstr # message
246 movl $start.8,%esi # Real mode stub
247 movl $MEM_STUB,%edi # Destination
248 movl $start.9-start.8,%ecx # Size
251 ljmp $SEL_RCODE,$MEM_STUB # To 16-bit code
253 start.8: xorw %ax,%ax # Data
254 movb $SEL_RDATA,%al # selector
255 movw %ax,%ss # Reload SS
258 movw %ax,%fs # segment
259 movw %ax,%gs # limits
260 movl %cr0,%eax # Switch to
262 movl %eax,%cr0 # mode
263 ljmp $0,$MEM_ENTRY # Jump to BTX entry point
267 * Output message [ESI] followed by EAX in hex.
269 hexout: pushl %eax # Save
270 call putstr # Display message
273 pushl %edi # caller's
274 movl $buf,%edi # Buffer
277 xorb %al,%al # Terminate
280 hexout.1: lodsb # Get a char
281 cmpb $'0',%al # Leading zero?
283 testb %al,%al # End of string?
286 hexout.2: decl %esi # Adjust for inc
287 call putstr # Display hex
292 * Output zero-terminated string [ESI] to the console.
294 putstr.0: call putchr # Output char
295 putstr: lodsb # Load char
296 testb %al,%al # End of string?
300 * Output character AL to the console.
302 putchr: testb $1,muted # Check muted
303 jnz putchr.5 # do a nop
305 xorl %ecx,%ecx # Zero for loops
306 movb $SCR_MAT,%ah # Mode/attribute
307 movl $BDA_POS,%ebx # BDA pointer
308 movw (%ebx),%dx # Cursor position
309 movl $0xb8000,%edi # Regen buffer (color)
310 cmpb %ah,BDA_SCR-BDA_POS(%ebx) # Mono mode?
312 xorw %di,%di # Regen buffer (mono)
313 putchr.1: cmpb $0xa,%al # New line?
315 xchgl %eax,%ecx # Save char
316 movb $SCR_COL,%al # Columns per row
317 mulb %dh # * row position
318 addb %dl,%al # + column
319 adcb $0x0,%ah # position
321 xchgl %eax,%ecx # Swap char, offset
322 movw %ax,(%edi,%ecx,1) # Write attr:char
323 incl %edx # Bump cursor
324 cmpb $SCR_COL,%dl # Beyond row?
326 putchr.2: xorb %dl,%dl # Zero column
328 putchr.3: cmpb $SCR_ROW,%dh # Beyond screen?
330 leal 2*SCR_COL(%edi),%esi # New top line
331 movw $(SCR_ROW-1)*SCR_COL/2,%cx # Words to move
334 movb $' ',%al # Space
335 movb $SCR_COL,%cl # Columns to clear
338 movb $SCR_ROW-1,%dh # Bottom line
339 putchr.4: movw %dx,(%ebx) # Update position
341 putchr.5: ret # To caller
343 * Convert EAX, AX, or AL to hex, saving the result to [EDI].
345 hex32: pushl %eax # Save
346 shrl $0x10,%eax # Do upper
349 hex16: call hex16.1 # Do upper 8
350 hex16.1: xchgb %ah,%al # Save/restore
351 hex8: pushl %eax # Save
352 shrb $0x4,%al # Do upper
355 hex8.1: andb $0xf,%al # Get lower 4
356 cmpb $0xa,%al # Convert
357 sbbb $0x69,%al # to hex
359 orb $0x20,%al # To lower case
366 * Global descriptor table.
368 gdt: .word 0x0,0x0,0x0,0x0 # Null entry
369 .word 0xffff,0x0,0x9a00,0xcf # SEL_SCODE
370 .word 0xffff,0x0,0x9200,0xcf # SEL_SDATA
371 .word 0xffff,0x0,0x9a00,0x0 # SEL_RCODE
372 .word 0xffff,0x0,0x9200,0x0 # SEL_RDATA
374 gdtdesc: .word gdt.1-gdt-1 # Limit
379 m_logo: .asciz " \nBTX loader 1.00 "
380 m_vers: .asciz "BTX version is \0\n"
381 e_fmt: .asciz "Error: Client format not supported\n"
382 #ifdef BTXLDR_VERBOSE
383 m_mem: .asciz "Starting in protected mode (base mem=\0)\n"
384 m_esp: .asciz "Arguments passed (esp=\0):\n"
385 m_args: .asciz"<howto="
390 .asciz" bootinfo=\0>\n"
391 m_rel_bi: .asciz "Relocated bootinfo (size=48) to \0\n"
392 m_rel_args: .asciz "Relocated arguments (size=18) to \0\n"
393 m_rel_btx: .asciz "Relocated kernel (size=\0) to \0\n"
394 m_base: .asciz "Client base address is \0\n"
395 m_elf: .asciz "Client format is ELF\n"
396 m_segs: .asciz "text segment: offset="
400 .asciz "data segment: offset="
404 m_done: .asciz "Loading complete\n"
413 * Uninitialized data area.
415 buf: # Scratch buffer