]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/boot/i386/btx/btxldr/btxldr.S
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.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 #include <bootargs.h>
19
20 #define RBX_MUTE        0x10    /* -m */
21 #define OPT_SET(opt)    (1 << (opt))
22
23 /*
24  * Prototype BTX loader program, written in a couple of hours.  The
25  * real thing should probably be more flexible, and in C.
26  */
27
28 /*
29  * Memory locations.
30  */
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
36 /*
37  * Segment selectors.
38  */
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
43 /*
44  * Paging constants.
45  */
46                 .set PAG_SIZ,0x1000             # Page size
47                 .set PAG_ENT,0x4                # Page entry size
48 /*
49  * Screen constants.
50  */
51                 .set SCR_MAT,0x7                # Mode/attribute
52                 .set SCR_COL,0x50               # Columns per row
53                 .set SCR_ROW,0x19               # Rows per screen
54 /*
55  * BIOS Data Area locations.
56  */
57                 .set BDA_MEM,0x413              # Free memory
58                 .set BDA_SCR,0x449              # Video mode
59                 .set BDA_POS,0x450              # Cursor position
60 /*
61  * Required by aout gas inadequacy.
62  */
63                 .set SIZ_STUB,0x1a              # Size of stub
64 /*
65  * We expect to be loaded by boot2 at the origin defined in ./Makefile.
66  */
67                 .globl start
68 /*
69  * BTX program loader for ELF clients.
70  */
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
79 #ifdef BTXLDR_VERBOSE
80                 movl $m_mem,%esi                # Display
81                 call hexout                     #  amount of
82                 call putstr                     #  base memory
83 #endif
84                 lgdt gdtdesc                    # Load new GDT
85 /*
86  * Relocate caller's arguments.
87  */
88 #ifdef BTXLDR_VERBOSE
89                 movl $m_esp,%esi                # Display
90                 movl %esp,%eax                  #  caller
91                 call hexout                     #  stack
92                 call putstr                     #  pointer
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
101 #endif
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
108                 rep                             # Copy
109                 movsb                           #  it
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
117 #endif
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
125                 rep                             # Copy
126                 movsb                           #  them
127 #ifdef BTXLDR_VERBOSE
128                 movl $m_rel_args,%esi           # Display
129                 movl %ebp,%eax                  #  argument
130                 call hexout                     #  relocation
131                 call putstr                     #  message
132 #endif
133 /*
134  * Set up BTX kernel.
135  */
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
142                 call putchr                     #  it
143                 movb $'.',%al                   # And a
144                 call putchr                     #  dot
145                 movb 0x6(%ebx),%al              # Get minor
146                 xorb %ah,%ah                    #  version
147                 movb $0xa,%dl                   # Divide
148                 divb %dl,%al                    #  by 10
149                 addb $'0',%al                   # Display
150                 call putchr                     #  tens
151                 movb %ah,%al                    # Get units
152                 addb $'0',%al                   # Display
153                 call putchr                     #  units
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
158                 incl %edi                       #  BTX
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
165 #endif
166                 rep                             # Relocate
167                 movsb                           #  BTX
168                 movl %esi,%ebx                  # Keep place
169 #ifdef BTXLDR_VERBOSE
170                 movl $m_rel_btx,%esi            # Restore
171                 popl %eax                       #  parameters
172                 call hexout                     #  and
173 #endif
174                 popl %ebp                       #  display
175 #ifdef BTXLDR_VERBOSE
176                 movl %ebp,%eax                  #  the
177                 call hexout                     #  relocation
178                 call putstr                     #  message
179 #endif
180                 addl $PAG_SIZ,%ebp              # Display
181 #ifdef BTXLDR_VERBOSE
182                 movl $m_base,%esi               #  the
183                 movl %ebp,%eax                  #  user
184                 call hexout                     #  base
185                 call putstr                     #  address
186 #endif
187 /*
188  * Set up ELF-format client program.
189  */
190                 cmpl $0x464c457f,(%ebx)         # ELF magic number?
191                 je start.3                      # Yes
192                 movl $e_fmt,%esi                # Display error
193                 call putstr                     #  message
194 start.2:        jmp start.2                     # Hang
195 start.3:
196 #ifdef BTXLDR_VERBOSE
197                 movl $m_elf,%esi                # Display ELF
198                 call putstr                     #  message
199                 movl $m_segs,%esi               # Format string
200 #endif
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?
206                 jne start.6                     # No
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
217 #endif
218                 pushl %esi                      # Save
219                 pushl %edi                      #  working
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
226                 rep                             # Set up
227                 movsb                           #  segment
228                 movl 0x14(%edx),%ecx            # Any bytes
229                 subl 0x10(%edx),%ecx            #  to zero?
230                 jz start.5                      # No
231                 xorb %al,%al                    # Then
232                 rep                             #  zero
233                 stosb                           #  them
234 start.5:        popl %ecx                       # Restore
235                 popl %edi                       #  working
236                 popl %esi                       #  registers
237                 decl %edi                       # Segments to do
238                 je start.7                      # If none
239 start.6:        addl $0x20,%edx                 # To next entry
240                 loop start.4                    # Till done
241 start.7:
242 #ifdef BTXLDR_VERBOSE
243                 movl $m_done,%esi               # Display done
244                 call putstr                     #  message
245 #endif
246                 movl $start.8,%esi              # Real mode stub
247                 movl $MEM_STUB,%edi             # Destination
248                 movl $start.9-start.8,%ecx      # Size
249                 rep                             # Relocate
250                 movsb                           #  it
251                 ljmp $SEL_RCODE,$MEM_STUB       # To 16-bit code
252                 .code16
253 start.8:        xorw %ax,%ax                    # Data
254                 movb $SEL_RDATA,%al             #  selector
255                 movw %ax,%ss                    # Reload SS
256                 movw %ax,%ds                    # Reset
257                 movw %ax,%es                    #  other
258                 movw %ax,%fs                    #  segment
259                 movw %ax,%gs                    #  limits
260                 movl %cr0,%eax                  # Switch to
261                 decw %ax                        #  real
262                 movl %eax,%cr0                  #  mode
263                 ljmp $0,$MEM_ENTRY              # Jump to BTX entry point
264 start.9:
265                 .code32
266 /*
267  * Output message [ESI] followed by EAX in hex.
268  */
269 hexout:         pushl %eax                      # Save
270                 call putstr                     # Display message
271                 popl %eax                       # Restore
272                 pushl %esi                      # Save
273                 pushl %edi                      #  caller's
274                 movl $buf,%edi                  # Buffer
275                 pushl %edi                      # Save
276                 call hex32                      # To hex
277                 xorb %al,%al                    # Terminate
278                 stosb                           #  string
279                 popl %esi                       # Restore
280 hexout.1:       lodsb                           # Get a char
281                 cmpb $'0',%al                   # Leading zero?
282                 je hexout.1                     # Yes
283                 testb %al,%al                   # End of string?
284                 jne hexout.2                    # No
285                 decl %esi                       # Undo
286 hexout.2:       decl %esi                       # Adjust for inc
287                 call putstr                     # Display hex
288                 popl %edi                       # Restore
289                 popl %esi                       #  caller's
290                 ret                             # To caller
291 /*
292  * Output zero-terminated string [ESI] to the console.
293  */
294 putstr.0:       call putchr                     # Output char
295 putstr:         lodsb                           # Load char
296                 testb %al,%al                   # End of string?
297                 jne putstr.0                    # No
298                 ret                             # To caller
299 /*
300  * Output character AL to the console.
301  */
302 putchr:         testb $1,muted                  # Check muted
303                 jnz putchr.5                    #  do a nop
304                 pusha                           # Save
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?
311                 jne putchr.1                    # No
312                 xorw %di,%di                    # Regen buffer (mono)
313 putchr.1:       cmpb $0xa,%al                   # New line?
314                 je putchr.2                     # Yes
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
320                 shll %eax                       #  * 2
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?
325                 jb putchr.3                     # No
326 putchr.2:       xorb %dl,%dl                    # Zero column
327                 incb %dh                        # Bump row
328 putchr.3:       cmpb $SCR_ROW,%dh               # Beyond screen?
329                 jb putchr.4                     # No
330                 leal 2*SCR_COL(%edi),%esi       # New top line
331                 movw $(SCR_ROW-1)*SCR_COL/2,%cx # Words to move
332                 rep                             # Scroll
333                 movsl                           #  screen
334                 movb $' ',%al                   # Space
335                 movb $SCR_COL,%cl               # Columns to clear
336                 rep                             # Clear
337                 stosw                           #  line
338                 movb $SCR_ROW-1,%dh             # Bottom line
339 putchr.4:       movw %dx,(%ebx)                 # Update position
340                 popa                            # Restore
341 putchr.5:       ret                             # To caller
342 /*
343  * Convert EAX, AX, or AL to hex, saving the result to [EDI].
344  */
345 hex32:          pushl %eax                      # Save
346                 shrl $0x10,%eax                 # Do upper
347                 call hex16                      #  16
348                 popl %eax                       # Restore
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
353                 call hex8.1                     #  4
354                 popl %eax                       # Restore
355 hex8.1:         andb $0xf,%al                   # Get lower 4
356                 cmpb $0xa,%al                   # Convert
357                 sbbb $0x69,%al                  #  to hex
358                 das                             #  digit
359                 orb $0x20,%al                   # To lower case
360                 stosb                           # Save char
361                 ret                             # (Recursive)
362
363                 .data
364                 .p2align 4
365 /*
366  * Global descriptor table.
367  */
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
373 gdt.1:
374 gdtdesc:        .word gdt.1-gdt-1               # Limit
375                 .long gdt                       # Base
376 /*
377  * Messages.
378  */
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="
386                 .asciz" bootdev="
387                 .asciz" junk="
388                 .asciz" "
389                 .asciz" "
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="
397                 .asciz " vaddr="
398                 .asciz " filesz="
399                 .asciz " memsz=\0\n"
400                 .asciz "data segment: offset="
401                 .asciz " vaddr="
402                 .asciz " filesz="
403                 .asciz " memsz=\0\n"
404 m_done:         .asciz "Loading complete\n"
405 #endif
406
407 /*
408  * Flags
409  */
410 muted:          .byte 0x0
411
412 /*
413  * Uninitialized data area.
414  */
415 buf:                                            # Scratch buffer