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