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