Undo some of the previously made changes to deal with cross build issues
[dragonfly.git] / sys / boot / i386 / pxeldr / pxeldr.s
1 #
2 # Copyright (c) 2000 John Baldwin
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/i386/pxeldr/pxeldr.s,v 1.9 2003/09/03 08:12:20 phk Exp $
17 # $DragonFly: src/sys/boot/i386/pxeldr/Attic/pxeldr.s,v 1.3 2003/11/10 06:08:37 dillon Exp $
18
19 #
20 # This simple program is a preloader for the normal boot3 loader.  It is simply
21 # prepended to the beginning of a fully built and btxld'd loader.  It then
22 # copies the loader to the address boot2 normally loads it, emulates the
23 # boot[12] environment (protected mode, a bootinfo struct, etc.), and then jumps
24 # to the start of btxldr to start the boot process.  This method allows a stock
25 # /boot/loader to be booted over the network via PXE w/o having to write a
26 # separate PXE-aware client just to load the loader.
27 #
28
29 #
30 # Memory locations.
31 #
32                 .set MEM_PAGE_SIZE,0x1000       # memory page size, 4k
33                 .set MEM_ARG,0x900              # Arguments at start
34                 .set MEM_ARG_BTX,0xa100         # Where we move them to so the
35                                                 #  BTX client can see them
36                 .set MEM_ARG_SIZE,0x18          # Size of the arguments
37                 .set MEM_BTX_ADDRESS,0x9000     # where BTX lives
38                 .set MEM_BTX_ENTRY,0x9010       # where BTX starts to execute
39                 .set MEM_BTX_OFFSET,MEM_PAGE_SIZE # offset of BTX in the loader
40                 .set MEM_BTX_CLIENT,0xa000      # where BTX clients live
41                 .set MEM_BIOS_KEYBOARD,0x496    # BDA byte with keyboard bit
42 #
43 # a.out header fields
44 #
45                 .set AOUT_TEXT,0x04             # text segment size
46                 .set AOUT_DATA,0x08             # data segment size
47                 .set AOUT_BSS,0x0c              # zero'd BSS size
48                 .set AOUT_SYMBOLS,0x10          # symbol table
49                 .set AOUT_ENTRY,0x14            # entry point
50                 .set AOUT_HEADER,MEM_PAGE_SIZE  # size of the a.out header
51 #
52 # Flags for kargs->bootflags
53 #
54                 .set KARGS_FLAGS_PXE,0x2        # flag to indicate booting from
55                                                 #  PXE loader
56 #
57 # Boot howto bits
58 #
59                 .set RB_SERIAL,0x1000           # serial console
60 #
61 # Segment selectors.
62 #
63                 .set SEL_SDATA,0x8              # Supervisor data
64                 .set SEL_RDATA,0x10             # Real mode data
65                 .set SEL_SCODE,0x18             # PM-32 code
66                 .set SEL_SCODE16,0x20           # PM-16 code
67 #
68 # BTX constants
69 #
70                 .set INT_SYS,0x30               # BTX syscall interrupt
71 #
72 # Bit in MEM_BIOS_KEYBOARD that is set if an enhanced keyboard is present
73 #
74                 .set KEYBOARD_BIT,0x10
75 #
76 # We expect to be loaded by the BIOS at 0x7c00 (standard boot loader entry
77 # point)
78 #
79                 .code16
80                 .globl start
81                 .org 0x0, 0x0
82 #
83 # BTX program loader for PXE network booting
84 #
85 start:          cld                             # string ops inc
86                 xorw %ax, %ax                   # zero %ax
87                 movw %ax, %ss                   # setup the
88                 movw $start, %sp                #  stack
89                 movw %es, %cx                   # save PXENV+ segment
90                 movw %ax, %ds                   # setup the
91                 movw %ax, %es                   #  data segments
92                 andl $0xffff, %ecx              # clear upper words
93                 andl $0xffff, %ebx              #  of %ebx and %ecx
94                 shll $4, %ecx                   # calculate the offset of
95                 addl %ebx, %ecx                 #  the PXENV+ struct and
96                 pushl %ecx                      #  save it on the stack
97                 movw $welcome_msg, %si          # %ds:(%si) -> welcome message
98                 callw putstr                    # display the welcome message
99 #
100 # Setup the arguments that the loader is expecting from boot[12]
101 #
102                 movw $bootinfo_msg, %si         # %ds:(%si) -> boot args message
103                 callw putstr                    # display the message
104                 movw $MEM_ARG, %bx              # %ds:(%bx) -> boot args
105                 movw %bx, %di                   # %es:(%di) -> boot args
106                 xorl %eax, %eax                 # zero %eax
107                 movw $(MEM_ARG_SIZE/4), %cx     # Size of arguments in 32-bit
108                                                 #  dwords
109                 rep                             # Clear the arguments
110                 stosl                           #  to zero
111                 orb $KARGS_FLAGS_PXE, 0x8(%bx)  # kargs->bootflags |=
112                                                 #  KARGS_FLAGS_PXE
113                 popl 0xc(%bx)                   # kargs->pxeinfo = *PXENV+
114 ifdef(`ALWAYS_SERIAL',`
115 #
116 # set the RBX_SERIAL bit in the howto byte.
117                 orl $RB_SERIAL, (%bx)           # enable serial console
118 ')
119 ifdef(`PROBE_KEYBOARD',`
120 #
121 # Look at the BIOS data area to see if we have an enhanced keyboard.  If not,
122 # set the RBX_SERIAL bit in the howto byte.
123                 testb $KEYBOARD_BIT, MEM_BIOS_KEYBOARD # keyboard present?
124                 jnz keyb                        # yes, so skip
125                 orl $RB_SERIAL, (%bx)           # enable serial console
126 keyb:
127 ')
128 #
129 # Turn on the A20 address line
130 #
131                 callw seta20                    # Turn A20 on
132 #
133 # Relocate the loader and BTX using a very lazy protected mode
134 #
135                 movw $relocate_msg, %si         # Display the
136                 callw putstr                    #  relocation message
137                 movl end+AOUT_ENTRY, %edi       # %edi is the destination
138                 movl $(end+AOUT_HEADER), %esi   # %esi is
139                                                 #  the start of the text
140                                                 #  segment
141                 movl end+AOUT_TEXT, %ecx        # %ecx = length of the text
142                                                 #  segment
143                 lgdt gdtdesc                    # setup our own gdt
144                 cli                             # turn off interrupts
145                 movl %cr0, %eax                 # Turn on
146                 orb $0x1, %al                   #  protected
147                 movl %eax, %cr0                 #  mode
148                 ljmp $SEL_SCODE,$pm_start       # long jump to clear the
149                                                 #  instruction pre-fetch queue
150                 .code32
151 pm_start:       movw $SEL_SDATA, %ax            # Initialize
152                 movw %ax, %ds                   #  %ds and
153                 movw %ax, %es                   #  %es to a flat selector
154                 rep                             # Relocate the
155                 movsb                           #  text segment
156                 addl $(MEM_PAGE_SIZE - 1), %edi # pad %edi out to a new page
157                 andl $~(MEM_PAGE_SIZE - 1), %edi #  for the data segment
158                 movl end+AOUT_DATA, %ecx        # size of the data segment
159                 rep                             # Relocate the
160                 movsb                           #  data segment
161                 movl end+AOUT_BSS, %ecx         # size of the bss
162                 xorl %eax, %eax                 # zero %eax
163                 addb $3, %cl                    # round %ecx up to
164                 shrl $2, %ecx                   #  a multiple of 4
165                 rep                             # zero the
166                 stosl                           #  bss
167                 movl end+AOUT_ENTRY, %esi       # %esi -> relocated loader
168                 addl $MEM_BTX_OFFSET, %esi      # %esi -> BTX in the loader
169                 movl $MEM_BTX_ADDRESS, %edi     # %edi -> where BTX needs to go
170                 movzwl 0xa(%esi), %ecx          # %ecx -> length of BTX
171                 rep                             # Relocate
172                 movsb                           #  BTX
173                 ljmp $SEL_SCODE16,$pm_16        # Jump to 16-bit PM
174                 .code16
175 pm_16:          movw $SEL_RDATA, %ax            # Initialize
176                 movw %ax, %ds                   #  %ds and
177                 movw %ax, %es                   #  %es to a real mode selector
178                 movl %cr0, %eax                 # Turn off
179                 andb $~0x1, %al                 #  protected
180                 movl %eax, %cr0                 #  mode
181                 ljmp $0,$pm_end                 # Long jump to clear the
182                                                 #  instruction pre-fetch queue
183 pm_end:         sti                             # Turn interrupts back on now
184 #
185 # Copy the BTX client to MEM_BTX_CLIENT
186 #
187                 xorw %ax, %ax                   # zero %ax and set
188                 movw %ax, %ds                   #  %ds and %es
189                 movw %ax, %es                   #  to segment 0
190                 movw $MEM_BTX_CLIENT, %di       # Prepare to relocate
191                 movw $btx_client, %si           #  the simple btx client
192                 movw $(btx_client_end-btx_client), %cx # length of btx client
193                 rep                             # Relocate the
194                 movsb                           #  simple BTX client
195 #
196 # Copy the boot[12] args to where the BTX client can see them
197 #
198                 movw $MEM_ARG, %si              # where the args are at now
199                 movw $MEM_ARG_BTX, %di          # where the args are moving to
200                 movw $(MEM_ARG_SIZE/4), %cx     # size of the arguments in longs
201                 rep                             # Relocate
202                 movsl                           #  the words
203 #
204 # Save the entry point so the client can get to it later on
205 #
206                 movl end+AOUT_ENTRY, %eax       # load the entry point
207                 stosl                           # add it to the end of the
208                                                 #  arguments
209 #
210 # Now we just start up BTX and let it do the rest
211 #
212                 movw $jump_message, %si         # Display the
213                 callw putstr                    #  jump message
214                 ljmp $0,$MEM_BTX_ENTRY          # Jump to the BTX entry point
215
216 #
217 # Display a null-terminated string
218 #
219 putstr:         lodsb                           # load %al from %ds:(%si)
220                 testb %al,%al                   # stop at null
221                 jnz putc                        # if the char != null, output it
222                 retw                            # return when null is hit
223 putc:           movw $0x7,%bx                   # attribute for output
224                 movb $0xe,%ah                   # BIOS: put_char
225                 int $0x10                       # call BIOS, print char in %al
226                 jmp putstr                      # keep looping
227
228 #
229 # Enable A20
230 #
231 seta20:         cli                             # Disable interrupts
232 seta20.1:       inb $0x64,%al                   # Get status
233                 testb $0x2,%al                  # Busy?
234                 jnz seta20.1                    # Yes
235                 movb $0xd1,%al                  # Command: Write
236                 outb %al,$0x64                  #  output port
237 seta20.2:       inb $0x64,%al                   # Get status
238                 testb $0x2,%al                  # Busy?
239                 jnz seta20.2                    # Yes
240                 movb $0xdf,%al                  # Enable
241                 outb %al,$0x60                  #  A20
242                 sti                             # Enable interrupts
243                 retw                            # To caller
244
245 #
246 # BTX client to start btxldr
247 #
248                 .code32
249 btx_client:     movl $(MEM_ARG_BTX-MEM_BTX_CLIENT+MEM_ARG_SIZE-4), %esi
250                                                 # %ds:(%esi) -> end
251                                                 #  of boot[12] args
252                 movl $(MEM_ARG_SIZE/4), %ecx    # Number of words to push
253                 std                             # Go backwards
254 push_arg:       lodsl                           # Read argument
255                 pushl %eax                      # Push it onto the stack
256                 loop push_arg                   # Push all of the arguments
257                 cld                             # In case anyone depends on this
258                 pushl MEM_ARG_BTX-MEM_BTX_CLIENT+MEM_ARG_SIZE # Entry point of
259                                                 #  the loader
260                 pushl %eax                      # Emulate a near call
261                 movl $0x1, %eax                 # 'exec' system call
262                 int $INT_SYS                    # BTX system call
263 btx_client_end:
264                 .code16
265
266                 .p2align 4
267 #
268 # Global descriptor table.
269 #
270 gdt:            .word 0x0,0x0,0x0,0x0           # Null entry
271                 .word 0xffff,0x0,0x9200,0xcf    # SEL_SDATA
272                 .word 0xffff,0x0,0x9200,0x0     # SEL_RDATA
273                 .word 0xffff,0x0,0x9a00,0xcf    # SEL_SCODE (32-bit)
274                 .word 0xffff,0x0,0x9a00,0x8f    # SEL_SCODE16 (16-bit)
275 gdt.1:
276 #
277 # Pseudo-descriptors.
278 #
279 gdtdesc:        .word gdt.1-gdt-1               # Limit
280                 .long gdt                       # Base
281
282 welcome_msg:    .asciz  "PXE Loader 1.00\r\n\n"
283 bootinfo_msg:   .asciz  "Building the boot loader arguments\r\n"
284 relocate_msg:   .asciz  "Relocating the loader and the BTX\r\n"
285 jump_message:   .asciz  "Starting the BTX loader\r\n"
286
287                 .p2align 4
288 end: