]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - sys/boot/i386/btx/btxldr/btxldr.S
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / sys / boot / i386 / btx / btxldr / btxldr.S
1 /*
2  * Copyright (c) 1998 Robert Nordier
3  * All rights reserved.
4  *
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
8  * such forms.
9  *
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
13  * purpose.
14  *
15  * $FreeBSD$
16  */
17
18 #define RBX_MUTE        0x10    /* -m */
19 #define OPT_SET(opt)    (1 << (opt))
20
21 /*
22  * Prototype BTX loader program, written in a couple of hours.  The
23  * real thing should probably be more flexible, and in C.
24  */
25
26 /*
27  * Memory locations.
28  */
29                 .set MEM_STUB,0x600             # Real mode stub
30                 .set MEM_ESP,0x1000             # New stack pointer
31                 .set MEM_TBL,0x5000             # BTX page tables
32                 .set MEM_ENTRY,0x9010           # BTX entry point
33                 .set MEM_DATA,start+0x1000      # Data segment
34 /*
35  * Segment selectors.
36  */
37                 .set SEL_SCODE,0x8              # 4GB code
38                 .set SEL_SDATA,0x10             # 4GB data
39                 .set SEL_RCODE,0x18             # 64K code
40                 .set SEL_RDATA,0x20             # 64K data
41 /*
42  * Paging constants.
43  */
44                 .set PAG_SIZ,0x1000             # Page size
45                 .set PAG_ENT,0x4                # Page entry size
46 /*
47  * Screen constants.
48  */
49                 .set SCR_MAT,0x7                # Mode/attribute
50                 .set SCR_COL,0x50               # Columns per row
51                 .set SCR_ROW,0x19               # Rows per screen
52 /*
53  * BIOS Data Area locations.
54  */
55                 .set BDA_MEM,0x413              # Free memory
56                 .set BDA_SCR,0x449              # Video mode
57                 .set BDA_POS,0x450              # Cursor position
58 /*
59  * Required by aout gas inadequacy.
60  */
61                 .set SIZ_STUB,0x1a              # Size of stub
62 /*
63  * We expect to be loaded by boot2 at the origin defined in ./Makefile.
64  */
65                 .globl start
66 /*
67  * BTX program loader for ELF clients.
68  */
69 start:          cld                             # String ops inc
70                 testl $OPT_SET(RBX_MUTE), 4(%esp) # Check first argument
71                 setnz muted                     #  for RBX_MUTE, set flag
72                 movl $m_logo,%esi               # Identify
73                 call putstr                     #  ourselves
74                 movzwl BDA_MEM,%eax             # Get base memory
75                 shll $0xa,%eax                  #  in bytes
76                 movl %eax,%ebp                  # Base of user stack
77 #ifdef BTXLDR_VERBOSE
78                 movl $m_mem,%esi                # Display
79                 call hexout                     #  amount of
80                 call putstr                     #  base memory
81 #endif
82                 lgdt gdtdesc                    # Load new GDT
83 /*
84  * Relocate caller's arguments.
85  */
86 #ifdef BTXLDR_VERBOSE
87                 movl $m_esp,%esi                # Display
88                 movl %esp,%eax                  #  caller
89                 call hexout                     #  stack
90                 call putstr                     #  pointer
91                 movl $m_args,%esi               # Format string
92                 leal 0x4(%esp,1),%ebx           # First argument
93                 movl $0x6,%ecx                  # Count
94 start.1:        movl (%ebx),%eax                # Get argument and
95                 addl $0x4,%ebx                  #  bump pointer
96                 call hexout                     # Display it
97                 loop start.1                    # Till done
98                 call putstr                     # End message
99 #endif
100                 movl $0x48,%ecx                 # Allocate space
101                 subl %ecx,%ebp                  #  for bootinfo
102                 movl 0x18(%esp,1),%esi          # Source: bootinfo
103                 cmpl $0x0, %esi                 # If the bootinfo pointer
104                 je start_null_bi                #  is null, don't copy it
105                 movl %ebp,%edi                  # Destination
106                 rep                             # Copy
107                 movsb                           #  it
108                 movl %ebp,0x18(%esp,1)          # Update pointer
109 #ifdef BTXLDR_VERBOSE
110                 movl $m_rel_bi,%esi             # Display
111                 movl %ebp,%eax                  #  bootinfo
112                 call hexout                     #  relocation
113                 call putstr                     #  message
114 #endif
115 start_null_bi:  movl $0x18,%ecx                 # Allocate space
116                 subl %ecx,%ebp                  #  for arguments
117                 leal 0x4(%esp,1),%esi           # Source
118                 movl %ebp,%edi                  # Destination
119                 rep                             # Copy
120                 movsb                           #  them
121 #ifdef BTXLDR_VERBOSE
122                 movl $m_rel_args,%esi           # Display
123                 movl %ebp,%eax                  #  argument
124                 call hexout                     #  relocation
125                 call putstr                     #  message
126 #endif
127 /*
128  * Set up BTX kernel.
129  */
130                 movl $MEM_ESP,%esp              # Set up new stack
131                 movl $MEM_DATA,%ebx             # Data segment
132                 movl $m_vers,%esi               # Display BTX
133                 call putstr                     #  version message
134                 movb 0x5(%ebx),%al              # Get major version
135                 addb $'0',%al                   # Display
136                 call putchr                     #  it
137                 movb $'.',%al                   # And a
138                 call putchr                     #  dot
139                 movb 0x6(%ebx),%al              # Get minor
140                 xorb %ah,%ah                    #  version
141                 movb $0xa,%dl                   # Divide
142                 divb %dl,%al                    #  by 10
143                 addb $'0',%al                   # Display
144                 call putchr                     #  tens
145                 movb %ah,%al                    # Get units
146                 addb $'0',%al                   # Display
147                 call putchr                     #  units
148                 call putstr                     # End message
149                 movl %ebx,%esi                  # BTX image
150                 movzwl 0x8(%ebx),%edi           # Compute
151                 orl $PAG_SIZ/PAG_ENT-1,%edi     #  the
152                 incl %edi                       #  BTX
153                 shll $0x2,%edi                  #  load
154                 addl $MEM_TBL,%edi              #  address
155                 pushl %edi                      # Save load address
156                 movzwl 0xa(%ebx),%ecx           # Image size
157 #ifdef BTXLDR_VERBOSE
158                 pushl %ecx                      # Save image size
159 #endif
160                 rep                             # Relocate
161                 movsb                           #  BTX
162                 movl %esi,%ebx                  # Keep place
163 #ifdef BTXLDR_VERBOSE
164                 movl $m_rel_btx,%esi            # Restore
165                 popl %eax                       #  parameters
166                 call hexout                     #  and
167 #endif
168                 popl %ebp                       #  display
169 #ifdef BTXLDR_VERBOSE
170                 movl %ebp,%eax                  #  the
171                 call hexout                     #  relocation
172                 call putstr                     #  message
173 #endif
174                 addl $PAG_SIZ,%ebp              # Display
175 #ifdef BTXLDR_VERBOSE
176                 movl $m_base,%esi               #  the
177                 movl %ebp,%eax                  #  user
178                 call hexout                     #  base
179                 call putstr                     #  address
180 #endif
181 /*
182  * Set up ELF-format client program.
183  */
184                 cmpl $0x464c457f,(%ebx)         # ELF magic number?
185                 je start.3                      # Yes
186                 movl $e_fmt,%esi                # Display error
187                 call putstr                     #  message
188 start.2:        jmp start.2                     # Hang
189 start.3:
190 #ifdef BTXLDR_VERBOSE
191                 movl $m_elf,%esi                # Display ELF
192                 call putstr                     #  message
193                 movl $m_segs,%esi               # Format string
194 #endif
195                 movl $0x2,%edi                  # Segment count
196                 movl 0x1c(%ebx),%edx            # Get e_phoff
197                 addl %ebx,%edx                  # To pointer
198                 movzwl 0x2c(%ebx),%ecx          # Get e_phnum
199 start.4:        cmpl $0x1,(%edx)                # Is p_type PT_LOAD?
200                 jne start.6                     # No
201 #ifdef BTXLDR_VERBOSE
202                 movl 0x4(%edx),%eax             # Display
203                 call hexout                     #  p_offset
204                 movl 0x8(%edx),%eax             # Display
205                 call hexout                     #  p_vaddr
206                 movl 0x10(%edx),%eax            # Display
207                 call hexout                     #  p_filesz
208                 movl 0x14(%edx),%eax            # Display
209                 call hexout                     #  p_memsz
210                 call putstr                     # End message
211 #endif
212                 pushl %esi                      # Save
213                 pushl %edi                      #  working
214                 pushl %ecx                      #  registers
215                 movl 0x4(%edx),%esi             # Get p_offset
216                 addl %ebx,%esi                  #  as pointer
217                 movl 0x8(%edx),%edi             # Get p_vaddr
218                 addl %ebp,%edi                  #  as pointer
219                 movl 0x10(%edx),%ecx            # Get p_filesz
220                 rep                             # Set up
221                 movsb                           #  segment
222                 movl 0x14(%edx),%ecx            # Any bytes
223                 subl 0x10(%edx),%ecx            #  to zero?
224                 jz start.5                      # No
225                 xorb %al,%al                    # Then
226                 rep                             #  zero
227                 stosb                           #  them
228 start.5:        popl %ecx                       # Restore
229                 popl %edi                       #  working
230                 popl %esi                       #  registers
231                 decl %edi                       # Segments to do
232                 je start.7                      # If none
233 start.6:        addl $0x20,%edx                 # To next entry
234                 loop start.4                    # Till done
235 start.7:
236 #ifdef BTXLDR_VERBOSE
237                 movl $m_done,%esi               # Display done
238                 call putstr                     #  message
239 #endif
240                 movl $start.8,%esi              # Real mode stub
241                 movl $MEM_STUB,%edi             # Destination
242                 movl $start.9-start.8,%ecx      # Size
243                 rep                             # Relocate
244                 movsb                           #  it
245                 ljmp $SEL_RCODE,$MEM_STUB       # To 16-bit code
246                 .code16
247 start.8:        xorw %ax,%ax                    # Data
248                 movb $SEL_RDATA,%al             #  selector
249                 movw %ax,%ss                    # Reload SS
250                 movw %ax,%ds                    # Reset
251                 movw %ax,%es                    #  other
252                 movw %ax,%fs                    #  segment
253                 movw %ax,%gs                    #  limits
254                 movl %cr0,%eax                  # Switch to
255                 decw %ax                        #  real
256                 movl %eax,%cr0                  #  mode
257                 ljmp $0,$MEM_ENTRY              # Jump to BTX entry point
258 start.9:
259                 .code32
260 /*
261  * Output message [ESI] followed by EAX in hex.
262  */
263 hexout:         pushl %eax                      # Save
264                 call putstr                     # Display message
265                 popl %eax                       # Restore
266                 pushl %esi                      # Save
267                 pushl %edi                      #  caller's
268                 movl $buf,%edi                  # Buffer
269                 pushl %edi                      # Save
270                 call hex32                      # To hex
271                 xorb %al,%al                    # Terminate
272                 stosb                           #  string
273                 popl %esi                       # Restore
274 hexout.1:       lodsb                           # Get a char
275                 cmpb $'0',%al                   # Leading zero?
276                 je hexout.1                     # Yes
277                 testb %al,%al                   # End of string?
278                 jne hexout.2                    # No
279                 decl %esi                       # Undo
280 hexout.2:       decl %esi                       # Adjust for inc
281                 call putstr                     # Display hex
282                 popl %edi                       # Restore
283                 popl %esi                       #  caller's
284                 ret                             # To caller
285 /*
286  * Output zero-terminated string [ESI] to the console.
287  */
288 putstr.0:       call putchr                     # Output char
289 putstr:         lodsb                           # Load char
290                 testb %al,%al                   # End of string?
291                 jne putstr.0                    # No
292                 ret                             # To caller
293 /*
294  * Output character AL to the console.
295  */
296 putchr:         testb $1,muted                  # Check muted
297                 jnz putchr.5                    #  do a nop
298                 pusha                           # Save
299                 xorl %ecx,%ecx                  # Zero for loops
300                 movb $SCR_MAT,%ah               # Mode/attribute
301                 movl $BDA_POS,%ebx              # BDA pointer
302                 movw (%ebx),%dx                 # Cursor position
303                 movl $0xb8000,%edi              # Regen buffer (color)
304                 cmpb %ah,BDA_SCR-BDA_POS(%ebx)  # Mono mode?
305                 jne putchr.1                    # No
306                 xorw %di,%di                    # Regen buffer (mono)
307 putchr.1:       cmpb $0xa,%al                   # New line?
308                 je putchr.2                     # Yes
309                 xchgl %eax,%ecx                 # Save char
310                 movb $SCR_COL,%al               # Columns per row
311                 mulb %dh                        #  * row position
312                 addb %dl,%al                    #  + column
313                 adcb $0x0,%ah                   #  position
314                 shll %eax                       #  * 2
315                 xchgl %eax,%ecx                 # Swap char, offset
316                 movw %ax,(%edi,%ecx,1)          # Write attr:char
317                 incl %edx                       # Bump cursor
318                 cmpb $SCR_COL,%dl               # Beyond row?
319                 jb putchr.3                     # No
320 putchr.2:       xorb %dl,%dl                    # Zero column
321                 incb %dh                        # Bump row
322 putchr.3:       cmpb $SCR_ROW,%dh               # Beyond screen?
323                 jb putchr.4                     # No
324                 leal 2*SCR_COL(%edi),%esi       # New top line
325                 movw $(SCR_ROW-1)*SCR_COL/2,%cx # Words to move
326                 rep                             # Scroll
327                 movsl                           #  screen
328                 movb $' ',%al                   # Space
329                 movb $SCR_COL,%cl               # Columns to clear
330                 rep                             # Clear
331                 stosw                           #  line
332                 movb $SCR_ROW-1,%dh             # Bottom line
333 putchr.4:       movw %dx,(%ebx)                 # Update position
334                 popa                            # Restore
335 putchr.5:       ret                             # To caller
336 /*
337  * Convert EAX, AX, or AL to hex, saving the result to [EDI].
338  */
339 hex32:          pushl %eax                      # Save
340                 shrl $0x10,%eax                 # Do upper
341                 call hex16                      #  16
342                 popl %eax                       # Restore
343 hex16:          call hex16.1                    # Do upper 8
344 hex16.1:        xchgb %ah,%al                   # Save/restore
345 hex8:           pushl %eax                      # Save
346                 shrb $0x4,%al                   # Do upper
347                 call hex8.1                     #  4
348                 popl %eax                       # Restore
349 hex8.1:         andb $0xf,%al                   # Get lower 4
350                 cmpb $0xa,%al                   # Convert
351                 sbbb $0x69,%al                  #  to hex
352                 das                             #  digit
353                 orb $0x20,%al                   # To lower case
354                 stosb                           # Save char
355                 ret                             # (Recursive)
356
357                 .data
358                 .p2align 4
359 /*
360  * Global descriptor table.
361  */
362 gdt:            .word 0x0,0x0,0x0,0x0           # Null entry
363                 .word 0xffff,0x0,0x9a00,0xcf    # SEL_SCODE
364                 .word 0xffff,0x0,0x9200,0xcf    # SEL_SDATA
365                 .word 0xffff,0x0,0x9a00,0x0     # SEL_RCODE
366                 .word 0xffff,0x0,0x9200,0x0     # SEL_RDATA
367 gdt.1:
368 gdtdesc:        .word gdt.1-gdt-1               # Limit
369                 .long gdt                       # Base
370 /*
371  * Messages.
372  */
373 m_logo:         .asciz " \nBTX loader 1.00  "
374 m_vers:         .asciz "BTX version is \0\n"
375 e_fmt:          .asciz "Error: Client format not supported\n"
376 #ifdef BTXLDR_VERBOSE
377 m_mem:          .asciz "Starting in protected mode (base mem=\0)\n"
378 m_esp:          .asciz "Arguments passed (esp=\0):\n"
379 m_args:         .asciz"<howto="
380                 .asciz" bootdev="
381                 .asciz" junk="
382                 .asciz" "
383                 .asciz" "
384                 .asciz" bootinfo=\0>\n"
385 m_rel_bi:       .asciz "Relocated bootinfo (size=48) to \0\n"
386 m_rel_args:     .asciz "Relocated arguments (size=18) to \0\n"
387 m_rel_btx:      .asciz "Relocated kernel (size=\0) to \0\n"
388 m_base:         .asciz "Client base address is \0\n"
389 m_elf:          .asciz "Client format is ELF\n"
390 m_segs:         .asciz "text segment: offset="
391                 .asciz " vaddr="
392                 .asciz " filesz="
393                 .asciz " memsz=\0\n"
394                 .asciz "data segment: offset="
395                 .asciz " vaddr="
396                 .asciz " filesz="
397                 .asciz " memsz=\0\n"
398 m_done:         .asciz "Loading complete\n"
399 #endif
400
401 /*
402  * Flags
403  */
404 muted:          .byte 0x0
405
406 /*
407  * Uninitialized data area.
408  */
409 buf:                                            # Scratch buffer