2 * Copyright (c) 2003,2004 The DragonFly Project. All rights reserved.
4 * This code is derived from software contributed to The DragonFly Project
5 * by Matthew Dillon <dillon@backplane.com>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * 3. Neither the name of The DragonFly Project nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific, prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * Copyright (c) 1998 Robert Nordier
35 * All rights reserved.
37 * Redistribution and use in source and binary forms are freely
38 * permitted provided that the above copyright notice and this
39 * paragraph and the following disclaimer are duplicated in all
42 * This software is provided "AS IS" and without any express or
43 * implied warranties, including, without limitation, the implied
44 * warranties of merchantability and fitness for a particular
47 * $FreeBSD: src/sys/boot/i386/btx/btxldr/Makefile,v 1.17 2004/04/27 19:45:16 ru Exp $
48 * $DragonFly: src/sys/boot/pc32/btx/btxldr/btxldr.S,v 1.3 2004/07/19 23:30:34 dillon Exp $
52 * Prototype BTX loader program, written in a couple of hours. The
53 * real thing should probably be more flexible, and in C.
56 #include "../../bootasm.h"
60 .set MEM_DATA,start+0x1000 # Data segment
64 .set SEL_SCODE,0x8 # 4GB code
65 .set SEL_SDATA,0x10 # 4GB data
66 .set SEL_RCODE,0x18 # 64K code
67 .set SEL_RDATA,0x20 # 64K data
71 .set PAG_SIZ,0x1000 # Page size
72 .set PAG_ENT,0x4 # Page entry size
76 .set SCR_MAT,0x7 # Mode/attribute
77 .set SCR_COL,0x50 # Columns per row
78 .set SCR_ROW,0x19 # Rows per screen
80 * Required by aout gas inadequacy.
82 .set SIZ_STUB,0x1a # Size of stub
84 * We expect to be loaded by boot2 at the origin defined in ./Makefile.
85 * This is typically 0x200000.
87 * I *THINK* (not sure) that execution begins with us in 'virtual mode',
88 * meaning everything is offset by MEM_BTX_USR. We will load a gdt to
89 * set the base offsets back to 0.
93 * BTX program loader for ELF clients.
95 start: cld # String ops inc
96 movl $m_logo,%esi # Identify
97 call putstr # ourselves
98 #if !defined(MEM_BTX_USR_STK)
99 movzwl BDA_MEM,%eax # Get base memory
100 shll $0xa,%eax # Convert to bytes
102 movl $MEM_BTX_USR_STK,%eax
104 movl %eax,%ebp # Base of user stack
105 #ifdef BTXLDR_VERBOSE
106 movl $m_mem,%esi # Display
107 call hexout # amount of
108 call putstr # base memory
112 * Load a new GDT. XXX what does this do to running code
113 * segments? What if an interrupt occurs? What if the
114 * segment registers are reloaded?
119 * Relocate caller's arguments.
121 #ifdef BTXLDR_VERBOSE
122 movl $m_esp,%esi # Display
123 movl %esp,%eax # caller
125 call putstr # pointer
126 movl $m_args,%esi # Format string
127 leal 0x4(%esp,1),%ebx # First argument
128 movl $0x6,%ecx # Count
129 start.1: movl (%ebx),%eax # Get argument and
130 addl $0x4,%ebx # bump pointer
131 call hexout # Display it
132 loop start.1 # Till done
133 call putstr # End message
136 * Arguments: (entry, boothowto, bootdev, 0, 0, 0, bootinfo)
137 * 0x00, 0x04, 0x08, 0x18
139 * sizeof(bootinfo) == 0x48 (BOOTINFO_SIZE)
140 * sizeof arguments == 0x18 (MEM_ARG_SIZE)
141 * total arguments == 0x60 bytes (USR_ARGOFFSET)
144 movl $BOOTINFO_SIZE,%ecx # Allocate space
145 subl %ecx,%ebp # for bootinfo
146 movl 0x18(%esp,1),%esi # Source: bootinfo
147 cmpl $0x0, %esi # If the bootinfo pointer
148 je start_null_bi # is null, do not copy it
149 movl %ebp,%edi # Destination
152 movl %ebp,0x18(%esp,1) # Update pointer
153 #ifdef BTXLDR_VERBOSE
154 movl $m_rel_bi,%esi # Display
155 movl %ebp,%eax # bootinfo
156 call hexout # relocation
157 call putstr # message
159 start_null_bi: movl $0x18,%ecx # Allocate space
160 subl %ecx,%ebp # for arguments
161 leal 0x4(%esp,1),%esi # Source
162 movl %ebp,%edi # Destination
165 #ifdef BTXLDR_VERBOSE
166 movl $m_rel_args,%esi # Display
167 movl %ebp,%eax # argument
168 call hexout # relocation
169 call putstr # message
174 movl $MEM_BTX_ESP,%esp # Set up new stack
175 movl $MEM_DATA,%ebx # Data segment
176 movl $m_vers,%esi # Display BTX
177 call putstr # version message
178 movb 0x5(%ebx),%al # Get major version
179 addb $'0',%al # Display
181 movb $'.',%al # And a
183 movb 0x6(%ebx),%al # Get minor
184 xorb %ah,%ah # version
185 movb $0xa,%dl # Divide
187 addb $'0',%al # Display
189 movb %ah,%al # Get units
190 addb $'0',%al # Display
192 call putstr # End message
194 # Relocate the BTX image from wherever it was loaded (%ebx),
195 # which is typically offset 0x1000 in the load data, to
196 # MEM_BTX_ORG (typically 0x9000).
198 # MEM_BTX_TBL + ((mappages | 0x3ff) + 1) * 4
199 # mappages is typically 0x0ffn so we get 0x1000*4 = 0x4000
200 # MEM_BTX_TBL is traditionally mapped at 0x5000 so the
201 # whole calculation translated to MEM_BTX_ORG (0x9000).
203 /* XXX what is all of this junk? */
204 movzwl 0x8(%ebx),%edi # Compute the BTX load address
205 orl $PAG_SIZ/PAG_ENT-1,%edi # (by skipping the page table)
208 addl $MEM_BTX_TBL,%edi
210 movl $MEM_BTX_ORG,%edi
212 movl %ebx,%esi # %esi = BTX image source
213 pushl %edi # Save load address
214 movzwl 0xa(%ebx),%ecx # Image size (bytes)
215 #ifdef BTXLDR_VERBOSE
216 pushl %ecx # Save image size
220 movl %esi,%ebx # Keep place
221 #ifdef BTXLDR_VERBOSE
222 movl $m_rel_btx,%esi # Restore
223 popl %eax # parameters
227 #ifdef BTXLDR_VERBOSE
229 call hexout # relocation
230 call putstr # message
233 * ADJUST EBP FOR USER BASE ADDRESS
235 * XXX why not just move MEM_BTX_USR into %ebp ?
237 addl $MEM_BTX_USR-MEM_BTX_ORG,%ebp
238 #ifdef BTXLDR_VERBOSE
239 movl $m_base,%esi # the
240 movl %ebp,%eax # user
242 call putstr # address
245 * Set up ELF-format client program.
247 cmpl $0x464c457f,(%ebx) # ELF magic number?
249 movl $e_fmt,%esi # Display error
250 call putstr # message
251 start.2: jmp start.2 # Hang
253 #ifdef BTXLDR_VERBOSE
254 movl $m_elf,%esi # Display ELF
255 call putstr # message
256 movl $m_segs,%esi # Format string
258 movl $0x2,%edi # Segment count
259 movl 0x1c(%ebx),%edx # Get e_phoff
260 addl %ebx,%edx # To pointer
261 movzwl 0x2c(%ebx),%ecx # Get e_phnum
262 start.4: cmpl $0x1,(%edx) # Is p_type PT_LOAD?
264 #ifdef BTXLDR_VERBOSE
265 movl 0x4(%edx),%eax # Display
266 call hexout # p_offset
267 movl 0x8(%edx),%eax # Display
268 call hexout # p_vaddr
269 movl 0x10(%edx),%eax # Display
270 call hexout # p_filesz
271 movl 0x14(%edx),%eax # Display
272 call hexout # p_memsz
273 call putstr # End message
277 pushl %ecx # registers
278 movl 0x4(%edx),%esi # Get p_offset
279 addl %ebx,%esi # as pointer
280 movl 0x8(%edx),%edi # Get p_vaddr
281 addl %ebp,%edi # as pointer
282 movl 0x10(%edx),%ecx # Get p_filesz
285 movl 0x14(%edx),%ecx # Any bytes
286 subl 0x10(%edx),%ecx # to zero?
291 start.5: popl %ecx # Restore
293 popl %esi # registers
294 decl %edi # Segments to do
296 start.6: addl $0x20,%edx # To next entry
297 loop start.4 # Till done
299 #ifdef BTXLDR_VERBOSE
300 movl $m_done,%esi # Display done
301 call putstr # message
303 movl $start.8,%esi # Real mode stub
304 movl $BOOT0_ORIGIN,%edi # Destination
305 movl $start.9-start.8,%ecx # Size
308 ljmp $SEL_RCODE,$BOOT0_ORIGIN # To 16-bit code
310 start.8: xorw %ax,%ax # Data
311 movb $SEL_RDATA,%al # selector
312 movw %ax,%ss # Reload SS
315 movw %ax,%fs # segment
316 movw %ax,%gs # limits
317 movl %cr0,%eax # Switch to
319 movl %eax,%cr0 # mode
320 ljmp $0,$MEM_BTX_ENTRY # Jump to BTX entry point
324 * Output message [ESI] followed by EAX in hex.
326 hexout: pushl %eax # Save
327 call putstr # Display message
331 movl $buf,%edi # Buffer
334 xorb %al,%al # Terminate
337 hexout.1: lodsb # Get a char
338 cmpb $'0',%al # Leading zero?
340 testb %al,%al # End of string?
343 hexout.2: decl %esi # Adjust for inc
344 call putstr # Display hex
349 * Output zero-terminated string [ESI] to the console.
351 putstr.0: call putchr # Output char
352 putstr: lodsb # Load char
353 testb %al,%al # End of string?
357 * Output character AL to the console.
360 xorl %ecx,%ecx # Zero for loops
361 movb $SCR_MAT,%ah # Mode/attribute
362 movl $BDA_POS,%ebx # BDA pointer
363 movw (%ebx),%dx # Cursor position
364 movl $0xb8000,%edi # Regen buffer (color)
365 cmpb %ah,BDA_SCR-BDA_POS(%ebx) # Mono mode?
367 xorw %di,%di # Regen buffer (mono)
368 putchr.1: cmpb $0xa,%al # New line?
370 xchgl %eax,%ecx # Save char
371 movb $SCR_COL,%al # Columns per row
372 mulb %dh # * row position
373 addb %dl,%al # + column
374 adcb $0x0,%ah # position
376 xchgl %eax,%ecx # Swap char, offset
377 movw %ax,(%edi,%ecx,1) # Write attr:char
378 incl %edx # Bump cursor
379 cmpb $SCR_COL,%dl # Beyond row?
381 putchr.2: xorb %dl,%dl # Zero column
383 putchr.3: cmpb $SCR_ROW,%dh # Beyond screen?
385 leal 2*SCR_COL(%edi),%esi # New top line
386 movw $(SCR_ROW-1)*SCR_COL/2,%cx # Words to move
389 movb $' ',%al # Space
390 movb $SCR_COL,%cl # Columns to clear
393 movb $SCR_ROW-1,%dh # Bottom line
394 putchr.4: movw %dx,(%ebx) # Update position
398 * Convert EAX, AX, or AL to hex, saving the result to [EDI].
400 hex32: pushl %eax # Save
401 shrl $0x10,%eax # Do upper
404 hex16: call hex16.1 # Do upper 8
405 hex16.1: xchgb %ah,%al # Save/restore
406 hex8: pushl %eax # Save
407 shrb $0x4,%al # Do upper
410 hex8.1: andb $0xf,%al # Get lower 4
411 cmpb $0xa,%al # Convert
412 sbbb $0x69,%al # to hex
414 orb $0x20,%al # To lower case
421 * Global descriptor table.
423 gdt: .word 0x0,0x0,0x0,0x0 # Null entry
424 .word 0xffff,0x0,0x9a00,0xcf # SEL_SCODE
425 .word 0xffff,0x0,0x9200,0xcf # SEL_SDATA
426 .word 0xffff,0x0,0x9a00,0x0 # SEL_RCODE
427 .word 0xffff,0x0,0x9200,0x0 # SEL_RDATA
429 gdtdesc: .word gdt.1-gdt-1 # Limit
434 m_logo: .asciz " \nBTX loader 1.00 "
435 m_vers: .asciz "BTX version is \0\n"
436 e_fmt: .asciz "Error: Client format not supported\n"
437 #ifdef BTXLDR_VERBOSE
438 m_mem: .asciz "Starting in protected mode (base mem=\0)\n"
439 m_esp: .asciz "Arguments passed (esp=\0):\n"
440 m_args: .asciz"<howto="
445 .asciz" bootinfo=\0>\n"
446 m_rel_bi: .asciz "Relocated bootinfo (size=48) to \0\n"
447 m_rel_args: .asciz "Relocated arguments (size=18) to \0\n"
448 m_rel_btx: .asciz "Relocated kernel (size=\0) to \0\n"
449 m_base: .asciz "Client base address is \0\n"
450 m_elf: .asciz "Client format is ELF\n"
451 m_segs: .asciz "text segment: offset="
455 .asciz "data segment: offset="
459 m_done: .asciz "Loading complete\n"
462 * Uninitialized data area.
464 buf: # Scratch buffer