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