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