9128 lines
562 KiB
Plaintext
9128 lines
562 KiB
Plaintext
1 ; -*- fundamental -*- (asm-mode sucks)
|
|
2 ; $Id: pxelinux.asm,v 1.168 2005/01/20 18:43:22 hpa Exp $
|
|
3 ; ****************************************************************************
|
|
4 ;
|
|
5 ; pxelinux.asm
|
|
6 ;
|
|
7 ; A program to boot Linux kernels off a TFTP server using the Intel PXE
|
|
8 ; network booting API. It is based on the SYSLINUX boot loader for
|
|
9 ; MS-DOS floppies.
|
|
10 ;
|
|
11 ; Copyright (C) 1994-2005 H. Peter Anvin
|
|
12 ;
|
|
13 ; This program is free software; you can redistribute it and/or modify
|
|
14 ; it under the terms of the GNU General Public License as published by
|
|
15 ; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
|
|
16 ; Boston MA 02111-1307, USA; either version 2 of the License, or
|
|
17 ; (at your option) any later version; incorporated herein by reference.
|
|
18 ;
|
|
19 ; ****************************************************************************
|
|
20
|
|
21 %define IS_PXELINUX 1
|
|
22 %include "macros.inc"
|
|
23 <1> ;; $Id: macros.inc,v 1.9 2004/12/14 22:46:25 hpa Exp $
|
|
24 <1> ;; -----------------------------------------------------------------------
|
|
25 <1> ;;
|
|
26 <1> ;; Copyright 1994-2004 H. Peter Anvin - All Rights Reserved
|
|
27 <1> ;;
|
|
28 <1> ;; This program is free software; you can redistribute it and/or modify
|
|
29 <1> ;; it under the terms of the GNU General Public License as published by
|
|
30 <1> ;; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
|
|
31 <1> ;; Boston MA 02111-1307, USA; either version 2 of the License, or
|
|
32 <1> ;; (at your option) any later version; incorporated herein by reference.
|
|
33 <1> ;;
|
|
34 <1> ;; -----------------------------------------------------------------------
|
|
35 <1>
|
|
36 <1> ;;
|
|
37 <1> ;; macros.inc
|
|
38 <1> ;;
|
|
39 <1> ;; Convenient macros
|
|
40 <1> ;;
|
|
41 <1>
|
|
42 <1> %ifndef _MACROS_INC
|
|
43 <1> %define _MACROS_INC
|
|
44 <1>
|
|
45 <1> ;
|
|
46 <1> ; Identify the module we're compiling; the "correct" should be defined
|
|
47 <1> ; in the module itself to 1
|
|
48 <1> ;
|
|
49 <1> %ifndef IS_SYSLINUX
|
|
50 <1> %define IS_SYSLINUX 0
|
|
51 <1> %endif
|
|
52 <1> %ifndef IS_MDSLINUX
|
|
53 <1> %define IS_MDSLINUX 0
|
|
54 <1> %endif
|
|
55 <1> %ifndef IS_PXELINUX
|
|
56 <1> %define IS_PXELINUX 0
|
|
57 <1> %endif
|
|
58 <1> %ifndef IS_ISOLINUX
|
|
59 <1> %define IS_ISOLINUX 0
|
|
60 <1> %endif
|
|
61 <1> %ifndef IS_EXTLINUX
|
|
62 <1> %define IS_EXTLINUX 0
|
|
63 <1> %endif
|
|
64 <1>
|
|
65 <1> ;
|
|
66 <1> ; Macros similar to res[bwd], but which works in the code segment (after
|
|
67 <1> ; section .text) or the data segment (section .data)
|
|
68 <1> ;
|
|
69 <1> %macro zb 1.nolist
|
|
70 <1> times %1 db 0
|
|
71 <1> %endmacro
|
|
72 <1>
|
|
73 <1> %macro zw 1.nolist
|
|
74 <1> times %1 dw 0
|
|
75 <1> %endmacro
|
|
76 <1>
|
|
77 <1> %macro zd 1.nolist
|
|
78 <1> times %1 dd 0
|
|
79 <1> %endmacro
|
|
80 <1>
|
|
81 <1> ;
|
|
82 <1> ; Macro to emit an unsigned decimal number as a string
|
|
83 <1> ;
|
|
84 <1> %macro asciidec 1.nolist
|
|
85 <1> %ifndef DEPEND ; Not safe for "depend"
|
|
86 <1> %if %1 >= 1000000000
|
|
87 <1> db ((%1/1000000000) % 10) + '0'
|
|
88 <1> %endif
|
|
89 <1> %if %1 >= 100000000
|
|
90 <1> db ((%1/100000000) % 10) + '0'
|
|
91 <1> %endif
|
|
92 <1> %if %1 >= 10000000
|
|
93 <1> db ((%1/10000000) % 10) + '0'
|
|
94 <1> %endif
|
|
95 <1> %if %1 >= 1000000
|
|
96 <1> db ((%1/1000000) % 10) + '0'
|
|
97 <1> %endif
|
|
98 <1> %if %1 >= 100000
|
|
99 <1> db ((%1/100000) % 10) + '0'
|
|
100 <1> %endif
|
|
101 <1> %if %1 >= 10000
|
|
102 <1> db ((%1/10000) % 10) + '0'
|
|
103 <1> %endif
|
|
104 <1> %if %1 >= 1000
|
|
105 <1> db ((%1/1000) % 10) + '0'
|
|
106 <1> %endif
|
|
107 <1> %if %1 >= 100
|
|
108 <1> db ((%1/100) % 10) + '0'
|
|
109 <1> %endif
|
|
110 <1> %if %1 >= 10
|
|
111 <1> db ((%1/10) % 10) + '0'
|
|
112 <1> %endif
|
|
113 <1> db (%1 % 10) + '0'
|
|
114 <1> %endif
|
|
115 <1> %endmacro
|
|
116 <1>
|
|
117 <1> ;
|
|
118 <1> ; Macros for network byte order of constants
|
|
119 <1> ;
|
|
120 <1> %define htons(x) ( ( ((x) & 0FFh) << 8 ) + ( ((x) & 0FF00h) >> 8 ) )
|
|
121 <1> %define ntohs(x) htons(x)
|
|
122 <1> %define htonl(x) ( ( ((x) & 0FFh) << 24) + ( ((x) & 0FF00h) << 8 ) + ( ((x) & 0FF0000h) >> 8 ) + ( ((x) & 0FF000000h) >> 24) )
|
|
123 <1> %define ntohl(x) htonl(x)
|
|
124 <1>
|
|
125 <1> ;
|
|
126 <1> ; ASCII
|
|
127 <1> ;
|
|
128 <1> CR equ 13 ; Carriage Return
|
|
129 <1> LF equ 10 ; Line Feed
|
|
130 <1> FF equ 12 ; Form Feed
|
|
131 <1> BS equ 8 ; Backspace
|
|
132 <1>
|
|
133 <1> %endif ; _MACROS_INC
|
|
134 %include "config.inc"
|
|
135 <1> ;; $Id: config.inc,v 1.9 2005/06/16 05:52:44 hpa Exp $
|
|
136 <1> ;; -----------------------------------------------------------------------
|
|
137 <1> ;;
|
|
138 <1> ;; Copyright 2002-2005 H. Peter Anvin - All Rights Reserved
|
|
139 <1> ;;
|
|
140 <1> ;; This program is free software; you can redistribute it and/or modify
|
|
141 <1> ;; it under the terms of the GNU General Public License as published by
|
|
142 <1> ;; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
|
|
143 <1> ;; Boston MA 02111-1307, USA; either version 2 of the License, or
|
|
144 <1> ;; (at your option) any later version; incorporated herein by reference.
|
|
145 <1> ;;
|
|
146 <1> ;; -----------------------------------------------------------------------
|
|
147 <1>
|
|
148 <1> ;;
|
|
149 <1> ;; config.inc
|
|
150 <1> ;;
|
|
151 <1> ;; Common configuration options. Some of these are imposed by the kernel.
|
|
152 <1> ;;
|
|
153 <1>
|
|
154 <1> %ifndef _CONFIG_INC
|
|
155 <1> %define _CONFIG_INC
|
|
156 <1>
|
|
157 <1> max_cmd_len equ 511 ; Must be &3; 255 is the kernel limit
|
|
158 <1> HIGHMEM_MAX equ 037FFFFFFh ; DEFAULT highest address for an initrd
|
|
159 <1> DEFAULT_BAUD equ 9600 ; Default baud rate for serial port
|
|
160 <1> BAUD_DIVISOR equ 115200 ; Serial port parameter
|
|
161 <1>
|
|
162 <1> %assign DO_WBINVD 0 ; Should we use WBINVD or not?
|
|
163 <1>
|
|
164 <1> ;
|
|
165 <1> ; Version number definitinons
|
|
166 <1> ;
|
|
167 <1> %ifndef DEPEND ; Generated file
|
|
168 <1> %include "version.gen"
|
|
169 <2> %define VERSION "3.09"
|
|
170 <2> %define VER_MAJOR 3
|
|
171 <2> %define VER_MINOR 9
|
|
172 <1> %endif
|
|
173 <1>
|
|
174 <1> ;
|
|
175 <1> ; Should be updated with every release to avoid bootsector/SYS file mismatch
|
|
176 <1> ;
|
|
177 <1> %define version_str VERSION ; Must be 4 characters long!
|
|
178 <1> %define date DATE_STR ; Defined from the Makefile
|
|
179 <1> %define year '2005'
|
|
180 <1>
|
|
181 <1> %endif ; _CONFIG_INC
|
|
182 %include "kernel.inc"
|
|
183 <1> ;; $Id: kernel.inc,v 1.5 2005/01/10 02:41:31 hpa Exp $
|
|
184 <1> ;; -----------------------------------------------------------------------
|
|
185 <1> ;;
|
|
186 <1> ;; Copyright 1994-2002 H. Peter Anvin - All Rights Reserved
|
|
187 <1> ;;
|
|
188 <1> ;; This program is free software; you can redistribute it and/or modify
|
|
189 <1> ;; it under the terms of the GNU General Public License as published by
|
|
190 <1> ;; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
|
|
191 <1> ;; Boston MA 02111-1307, USA; either version 2 of the License, or
|
|
192 <1> ;; (at your option) any later version; incorporated herein by reference.
|
|
193 <1> ;;
|
|
194 <1> ;; -----------------------------------------------------------------------
|
|
195 <1>
|
|
196 <1> ;;
|
|
197 <1> ;; kernel.inc
|
|
198 <1> ;;
|
|
199 <1> ;; Header file for the kernel interface definitions
|
|
200 <1> ;;
|
|
201 <1>
|
|
202 <1> %ifndef _KERNEL_INC
|
|
203 <1> %define _KERNEL_INC
|
|
204 <1>
|
|
205 <1> ;;
|
|
206 <1> ;; Structure of the real_mode_seg
|
|
207 <1> ;;
|
|
208 <1>
|
|
209 <1> struc real_mode_seg_t
|
|
210 00000000 <res 00000020> <1> resb 20h-($-$$) ; org 20h
|
|
211 00000020 <res 00000002> <1> kern_cmd_magic resw 1 ; 0020 Magic # for command line
|
|
212 00000022 <res 00000002> <1> kern_cmd_offset resw 1 ; 0022 Offset for kernel command line
|
|
213 00000024 <res 000001CD> <1> resb 497-($-$$) ; org 497d
|
|
214 000001F1 <res 00000001> <1> bs_setupsecs resb 1 ; 01F1 Sectors for setup code (0 -> 4)
|
|
215 000001F2 <res 00000002> <1> bs_rootflags resw 1 ; 01F2 Root readonly flag
|
|
216 000001F4 <res 00000002> <1> bs_syssize resw 1 ; 01F4
|
|
217 000001F6 <res 00000002> <1> bs_swapdev resw 1 ; 01F6 Swap device (obsolete)
|
|
218 000001F8 <res 00000002> <1> bs_ramsize resw 1 ; 01F8 Ramdisk flags, formerly ramdisk size
|
|
219 000001FA <res 00000002> <1> bs_vidmode resw 1 ; 01FA Video mode
|
|
220 000001FC <res 00000002> <1> bs_rootdev resw 1 ; 01FC Root device
|
|
221 000001FE <res 00000002> <1> bs_bootsign resw 1 ; 01FE Boot sector signature (0AA55h)
|
|
222 00000200 <res 00000001> <1> su_jump resb 1 ; 0200 0EBh
|
|
223 00000201 <res 00000001> <1> su_jump2 resb 1 ; 0201 Size of following header
|
|
224 00000202 <res 00000004> <1> su_header resd 1 ; 0202 New setup code: header
|
|
225 00000206 <res 00000002> <1> su_version resw 1 ; 0206 See linux/arch/i386/boot/setup.S
|
|
226 00000208 <res 00000002> <1> su_switch resw 1 ; 0208
|
|
227 0000020A <res 00000002> <1> su_setupseg resw 1 ; 020A
|
|
228 0000020C <res 00000002> <1> su_startsys resw 1 ; 020C
|
|
229 0000020E <res 00000002> <1> su_kver resw 1 ; 020E Kernel version pointer
|
|
230 00000210 <res 00000001> <1> su_loader resb 1 ; 0210 Loader ID
|
|
231 00000211 <res 00000001> <1> su_loadflags resb 1 ; 0211 Load high flag
|
|
232 00000212 <res 00000002> <1> su_movesize resw 1 ; 0212
|
|
233 00000214 <res 00000004> <1> su_code32start resd 1 ; 0214 Start of code loaded high
|
|
234 00000218 <res 00000004> <1> su_ramdiskat resd 1 ; 0218 Start of initial ramdisk
|
|
235 0000021C <res 00000004> <1> su_ramdisklen resd 1 ; 021C Length of initial ramdisk
|
|
236 00000220 <res 00000002> <1> su_bsklugeoffs resw 1 ; 0220
|
|
237 00000222 <res 00000002> <1> su_bsklugeseg resw 1 ; 0222
|
|
238 00000224 <res 00000002> <1> su_heapend resw 1 ; 0224
|
|
239 00000226 <res 00000002> <1> su_pad1 resw 1 ; 0226
|
|
240 00000228 <res 00000004> <1> su_cmd_line_ptr resd 1 ; 0228
|
|
241 0000022C <res 00000004> <1> su_ramdisk_max resd 1 ; 022C
|
|
242 00000230 <res 00008DC4> <1> resb (9000h-12)-($-$$) ; Were bootsect.S puts it...
|
|
243 <1> linux_stack equ $ ; 8FF4
|
|
244 <1> linux_fdctab equ $
|
|
245 00008FF4 <res 0000000C> <1> resb 9000h-($-$$)
|
|
246 <1> cmd_line_here equ $ ; 9000 Should be out of the way
|
|
247 <1> endstruc
|
|
248 <1>
|
|
249 <1> ;
|
|
250 <1> ; Kernel command line signature
|
|
251 <1> ;
|
|
252 <1> CMD_MAGIC equ 0A33Fh ; Command line magic
|
|
253 <1>
|
|
254 <1> ;
|
|
255 <1> ; Magic number of su_header field
|
|
256 <1> ;
|
|
257 <1> HEADER_ID equ 'HdrS' ; HdrS (in littleendian hex)
|
|
258 <1>
|
|
259 <1> ;
|
|
260 <1> ; Flags for the su_loadflags field
|
|
261 <1> ;
|
|
262 <1> LOAD_HIGH equ 01h ; Large kernel, load high
|
|
263 <1> CAN_USE_HEAP equ 80h ; Boot loader reports heap size
|
|
264 <1>
|
|
265 <1> ;
|
|
266 <1> ; ID codes for various modules
|
|
267 <1> ;
|
|
268 <1> syslinux_id equ 031h ; 3 = SYSLINUX family; 1 = SYSLINUX
|
|
269 <1> pxelinux_id equ 032h ; 3 = SYSLINUX family; 2 = PXELINUX
|
|
270 <1> isolinux_id equ 033h ; 3 = SYSLINUX family; 3 = ISOLINUX
|
|
271 <1> extlinux_id equ 034h ; 3 = SYSLINUX family; 4 = EXTLINUX
|
|
272 <1>
|
|
273 <1> %endif ; _KERNEL_INC
|
|
274 %include "bios.inc"
|
|
275 <1> ;; $Id: bios.inc,v 1.3 2004/12/14 22:46:24 hpa Exp $
|
|
276 <1> ;; -----------------------------------------------------------------------
|
|
277 <1> ;;
|
|
278 <1> ;; Copyright 1994-2004 H. Peter Anvin - All Rights Reserved
|
|
279 <1> ;;
|
|
280 <1> ;; This program is free software; you can redistribute it and/or modify
|
|
281 <1> ;; it under the terms of the GNU General Public License as published by
|
|
282 <1> ;; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
|
|
283 <1> ;; Boston MA 02111-1307, USA; either version 2 of the License, or
|
|
284 <1> ;; (at your option) any later version; incorporated herein by reference.
|
|
285 <1> ;;
|
|
286 <1> ;; -----------------------------------------------------------------------
|
|
287 <1>
|
|
288 <1> ;;
|
|
289 <1> ;; bios.inc
|
|
290 <1> ;;
|
|
291 <1> ;; Header file for the BIOS data structures etc.
|
|
292 <1> ;;
|
|
293 <1>
|
|
294 <1> %ifndef _BIOS_INC
|
|
295 <1> %define _BIOS_INC
|
|
296 <1>
|
|
297 <1> absolute 4*1Eh ; In the interrupt table
|
|
298 <1> fdctab equ $
|
|
299 00000078 <res 00000002> <1> fdctab1 resw 1
|
|
300 0000007A <res 00000002> <1> fdctab2 resw 1
|
|
301 <1> absolute 0400h
|
|
302 00000400 <res 00000008> <1> serial_base resw 4 ; Base addresses for 4 serial ports
|
|
303 <1> absolute 0413h
|
|
304 00000413 <res 00000002> <1> BIOS_fbm resw 1 ; Free Base Memory (kilobytes)
|
|
305 <1> absolute 0462h
|
|
306 00000462 <res 00000001> <1> BIOS_page resb 1 ; Current video page
|
|
307 <1> absolute 046Ch
|
|
308 0000046C <res 00000002> <1> BIOS_timer resw 1 ; Timer ticks
|
|
309 <1> absolute 0472h
|
|
310 00000472 <res 00000002> <1> BIOS_magic resw 1 ; BIOS reset magic
|
|
311 <1> absolute 0484h
|
|
312 00000484 <res 00000001> <1> BIOS_vidrows resb 1 ; Number of screen rows
|
|
313 <1>
|
|
314 <1> %endif ; _BIOS_INC
|
|
315 %include "tracers.inc"
|
|
316 <1> ;; $Id: tracers.inc,v 1.6 2005/01/12 00:35:13 hpa Exp $
|
|
317 <1> ;; -----------------------------------------------------------------------
|
|
318 <1> ;;
|
|
319 <1> ;; Copyright 1994-2002 H. Peter Anvin - All Rights Reserved
|
|
320 <1> ;;
|
|
321 <1> ;; This program is free software; you can redistribute it and/or modify
|
|
322 <1> ;; it under the terms of the GNU General Public License as published by
|
|
323 <1> ;; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
|
|
324 <1> ;; Boston MA 02111-1307, USA; either version 2 of the License, or
|
|
325 <1> ;; (at your option) any later version; incorporated herein by reference.
|
|
326 <1> ;;
|
|
327 <1> ;; -----------------------------------------------------------------------
|
|
328 <1>
|
|
329 <1> ;;
|
|
330 <1> ;; tracers.inc
|
|
331 <1> ;;
|
|
332 <1> ;; Debugging tracers
|
|
333 <1> ;;
|
|
334 <1>
|
|
335 <1> %ifndef _TRACERS_INC
|
|
336 <1> %define _TRACERS_INC
|
|
337 <1>
|
|
338 <1> ; Note: The Makefile builds one version with DEBUG_MESSAGES automatically.
|
|
339 <1> ; %define DEBUG_TRACERS 1 ; Uncomment to get debugging tracers
|
|
340 <1> ; %define DEBUG_MESSAGES ; Uncomment to get debugging messages
|
|
341 <1>
|
|
342 <1> %ifdef DEBUG_TRACERS
|
|
343 <1>
|
|
344 <1> %macro TRACER 1
|
|
345 <1> call debug_tracer
|
|
346 <1> db %1
|
|
347 <1> %endmacro
|
|
348 <1>
|
|
349 <1> %else ; DEBUG_TRACERS
|
|
350 <1>
|
|
351 <1> %macro TRACER 1
|
|
352 <1> %endmacro
|
|
353 <1>
|
|
354 <1> %endif ; DEBUG_TRACERS
|
|
355 <1>
|
|
356 <1> %endif ; _TRACERS_INC
|
|
357 %include "pxe.inc"
|
|
358 <1> ;; -----------------------------------------------------------------------
|
|
359 <1> ;;
|
|
360 <1> ;; Copyright 1999-2004 H. Peter Anvin - All Rights Reserved
|
|
361 <1> ;;
|
|
362 <1> ;; This program is free software; you can redistribute it and/or modify
|
|
363 <1> ;; it under the terms of the GNU General Public License as published by
|
|
364 <1> ;; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
|
|
365 <1> ;; Boston MA 02111-1307, USA; either version 2 of the License, or
|
|
366 <1> ;; (at your option) any later version; incorporated herein by reference.
|
|
367 <1> ;;
|
|
368 <1> ;; -----------------------------------------------------------------------
|
|
369 <1> ;; $Id: pxe.inc,v 1.5 2004/12/14 23:03:28 hpa Exp $
|
|
370 <1>
|
|
371 <1> ;;
|
|
372 <1> ;; pxe.inc
|
|
373 <1> ;;
|
|
374 <1> ;; PXE opcodes
|
|
375 <1> ;;
|
|
376 <1>
|
|
377 <1> %ifndef _PXE_INC
|
|
378 <1> %define _PXE_INC 1
|
|
379 <1>
|
|
380 <1> %define PXENV_TFTP_OPEN 0020h
|
|
381 <1> %define PXENV_TFTP_CLOSE 0021h
|
|
382 <1> %define PXENV_TFTP_READ 0022h
|
|
383 <1> %define PXENV_TFTP_READ_FILE 0023h
|
|
384 <1> %define PXENV_TFTP_READ_FILE_PMODE 0024h
|
|
385 <1> %define PXENV_TFTP_GET_FSIZE 0025h
|
|
386 <1>
|
|
387 <1> %define PXENV_UDP_OPEN 0030h
|
|
388 <1> %define PXENV_UDP_CLOSE 0031h
|
|
389 <1> %define PXENV_UDP_READ 0032h
|
|
390 <1> %define PXENV_UDP_WRITE 0033h
|
|
391 <1>
|
|
392 <1> %define PXENV_START_UNDI 0000h
|
|
393 <1> %define PXENV_UNDI_STARTUP 0001h
|
|
394 <1> %define PXENV_UNDI_CLEANUP 0002h
|
|
395 <1> %define PXENV_UNDI_INITIALIZE 0003h
|
|
396 <1> %define PXENV_UNDI_RESET_NIC 0004h
|
|
397 <1> %define PXENV_UNDI_SHUTDOWN 0005h
|
|
398 <1> %define PXENV_UNDI_OPEN 0006h
|
|
399 <1> %define PXENV_UNDI_CLOSE 0007h
|
|
400 <1> %define PXENV_UNDI_TRANSMIT 0008h
|
|
401 <1> %define PXENV_UNDI_SET_MCAST_ADDR 0009h
|
|
402 <1> %define PXENV_UNDI_SET_STATION_ADDR 000Ah
|
|
403 <1> %define PXENV_UNDI_SET_PACKET_FILTER 000Bh
|
|
404 <1> %define PXENV_UNDI_GET_INFORMATION 000Ch
|
|
405 <1> %define PXENV_UNDI_GET_STATISTICS 000Dh
|
|
406 <1> %define PXENV_UNDI_CLEAR_STATISTICS 000Eh
|
|
407 <1> %define PXENV_UNDI_INITIATE_DIAGS 000Fh
|
|
408 <1> %define PXENV_UNDI_FORCE_INTERRUPT 0010h
|
|
409 <1> %define PXENV_UNDI_GET_MCAST_ADDR 0011h
|
|
410 <1> %define PXENV_UNDI_GET_NIC_TYPE 0012h
|
|
411 <1> %define PXENV_UNDI_GET_IFACE_INFO 0013h
|
|
412 <1> %define PXENV_UNDI_ISR 0014h
|
|
413 <1> %define PXENV_STOP_UNDI 0015h ; Overlap...?
|
|
414 <1> %define PXENV_UNDI_GET_STATE 0015h ; Overlap...?
|
|
415 <1>
|
|
416 <1> %define PXENV_UNLOAD_STACK 0070h
|
|
417 <1> %define PXENV_GET_CACHED_INFO 0071h
|
|
418 <1> %define PXENV_RESTART_DHCP 0072h
|
|
419 <1> %define PXENV_RESTART_TFTP 0073h
|
|
420 <1> %define PXENV_MODE_SWITCH 0074h
|
|
421 <1> %define PXENV_START_BASE 0075h
|
|
422 <1> %define PXENV_STOP_BASE 0076h
|
|
423 <1>
|
|
424 <1> %define PXENV_EXIT_SUCCESS 0x0000
|
|
425 <1> %define PXENV_EXIT_FAILURE 0x0001
|
|
426 <1>
|
|
427 <1> %define PXENV_STATUS_SUCCESS 0x00
|
|
428 <1> %define PXENV_STATUS_FAILURE 0x01
|
|
429 <1> %define PXENV_STATUS_BAD_FUNC 0x02
|
|
430 <1> %define PXENV_STATUS_UNSUPPORTED 0x03
|
|
431 <1> %define PXENV_STATUS_KEEP_UNDI 0x04
|
|
432 <1> %define PXENV_STATUS_KEEP_ALL 0x05
|
|
433 <1> %define PXENV_STATUS_OUT_OF_RESOURCES 0x06
|
|
434 <1> %define PXENV_STATUS_ARP_TIMEOUT 0x11
|
|
435 <1> %define PXENV_STATUS_UDP_CLOSED 0x18
|
|
436 <1> %define PXENV_STATUS_UDP_OPEN 0x19
|
|
437 <1> %define PXENV_STATUS_TFTP_CLOSED 0x1A
|
|
438 <1> %define PXENV_STATUS_TFTP_OPEN 0x1B
|
|
439 <1> %define PXENV_STATUS_MCOPY_PROBLEM 0x20
|
|
440 <1> %define PXENV_STATUS_BIS_INTEGRITY_FAILURE 0x21
|
|
441 <1> %define PXENV_STATUS_BIS_VALIDATE_FAILURE 0x22
|
|
442 <1> %define PXENV_STATUS_BIS_INIT_FAILURE 0x23
|
|
443 <1> %define PXENV_STATUS_BIS_SHUTDOWN_FAILURE 0x24
|
|
444 <1> %define PXENV_STATUS_BIS_GBOA_FAILURE 0x25
|
|
445 <1> %define PXENV_STATUS_BIS_FREE_FAILURE 0x26
|
|
446 <1> %define PXENV_STATUS_BIS_GSI_FAILURE 0x27
|
|
447 <1> %define PXENV_STATUS_BIS_BAD_CKSUM 0x28
|
|
448 <1> %define PXENV_STATUS_TFTP_CANNOT_ARP_ADDRESS 0x30
|
|
449 <1> %define PXENV_STATUS_TFTP_OPEN_TIMEOUT 0x32
|
|
450 <1>
|
|
451 <1> %define PXENV_STATUS_TFTP_UNKNOWN_OPCODE 0x33
|
|
452 <1> %define PXENV_STATUS_TFTP_READ_TIMEOUT 0x35
|
|
453 <1> %define PXENV_STATUS_TFTP_ERROR_OPCODE 0x36
|
|
454 <1> %define PXENV_STATUS_TFTP_CANNOT_OPEN_CONNECTION 0x38
|
|
455 <1> %define PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION 0x39
|
|
456 <1> %define PXENV_STATUS_TFTP_TOO_MANY_PACKAGES 0x3A
|
|
457 <1> %define PXENV_STATUS_TFTP_FILE_NOT_FOUND 0x3B
|
|
458 <1> %define PXENV_STATUS_TFTP_ACCESS_VIOLATION 0x3C
|
|
459 <1> %define PXENV_STATUS_TFTP_NO_MCAST_ADDRESS 0x3D
|
|
460 <1> %define PXENV_STATUS_TFTP_NO_FILESIZE 0x3E
|
|
461 <1> %define PXENV_STATUS_TFTP_INVALID_PACKET_SIZE 0x3F
|
|
462 <1> %define PXENV_STATUS_DHCP_TIMEOUT 0x51
|
|
463 <1> %define PXENV_STATUS_DHCP_NO_IP_ADDRESS 0x52
|
|
464 <1> %define PXENV_STATUS_DHCP_NO_BOOTFILE_NAME 0x53
|
|
465 <1> %define PXENV_STATUS_DHCP_BAD_IP_ADDRESS 0x54
|
|
466 <1> %define PXENV_STATUS_UNDI_INVALID_FUNCTION 0x60
|
|
467 <1> %define PXENV_STATUS_UNDI_MEDIATEST_FAILED 0x61
|
|
468 <1> %define PXENV_STATUS_UNDI_CANNOT_INIT_NIC_FOR_MCAST 0x62
|
|
469 <1> %define PXENV_STATUS_UNDI_CANNOT_INITIALIZE_NIC 0x63
|
|
470 <1> %define PXENV_STATUS_UNDI_CANNOT_INITIALIZE_PHY 0x64
|
|
471 <1> %define PXENV_STATUS_UNDI_CANNOT_READ_CONFIG_DATA 0x65
|
|
472 <1> %define PXENV_STATUS_UNDI_CANNOT_READ_INIT_DATA 0x66
|
|
473 <1> %define PXENV_STATUS_UNDI_BAD_MAC_ADDRESS 0x67
|
|
474 <1> %define PXENV_STATUS_UNDI_BAD_EEPROM_CHECKSUM 0x68
|
|
475 <1> %define PXENV_STATUS_UNDI_ERROR_SETTING_ISR 0x69
|
|
476 <1> %define PXENV_STATUS_UNDI_INVALID_STATE 0x6A
|
|
477 <1> %define PXENV_STATUS_UNDI_TRANSMIT_ERROR 0x6B
|
|
478 <1> %define PXENV_STATUS_UNDI_INVALID_PARAMETER 0x6C
|
|
479 <1> %define PXENV_STATUS_BSTRAP_PROMPT_MENU 0x74
|
|
480 <1> %define PXENV_STATUS_BSTRAP_MCAST_ADDR 0x76
|
|
481 <1> %define PXENV_STATUS_BSTRAP_MISSING_LIST 0x77
|
|
482 <1> %define PXENV_STATUS_BSTRAP_NO_RESPONSE 0x78
|
|
483 <1> %define PXENV_STATUS_BSTRAP_FILE_TOO_BIG 0x79
|
|
484 <1> %define PXENV_STATUS_BINL_CANCELED_BY_KEYSTROKE 0xA0
|
|
485 <1> %define PXENV_STATUS_BINL_NO_PXE_SERVER 0xA1
|
|
486 <1> %define PXENV_STATUS_NOT_AVAILABLE_IN_PMODE 0xA2
|
|
487 <1> %define PXENV_STATUS_NOT_AVAILABLE_IN_RMODE 0xA3
|
|
488 <1> %define PXENV_STATUS_BUSD_DEVICE_NOT_SUPPORTED 0xB0
|
|
489 <1> %define PXENV_STATUS_LOADER_NO_FREE_BASE_MEMORY 0xC0
|
|
490 <1> %define PXENV_STATUS_LOADER_NO_BC_ROMID 0xC1
|
|
491 <1> %define PXENV_STATUS_LOADER_BAD_BC_ROMID 0xC2
|
|
492 <1> %define PXENV_STATUS_LOADER_BAD_BC_RUNTIME_IMAGE 0xC3
|
|
493 <1> %define PXENV_STATUS_LOADER_NO_UNDI_ROMID 0xC4
|
|
494 <1> %define PXENV_STATUS_LOADER_BAD_UNDI_ROMID 0xC5
|
|
495 <1> %define PXENV_STATUS_LOADER_BAD_UNDI_DRIVER_IMAGE 0xC6
|
|
496 <1> %define PXENV_STATUS_LOADER_NO_PXE_STRUCT 0xC8
|
|
497 <1> %define PXENV_STATUS_LOADER_NO_PXENV_STRUCT 0xC9
|
|
498 <1> %define PXENV_STATUS_LOADER_UNDI_START 0xCA
|
|
499 <1> %define PXENV_STATUS_LOADER_BC_START 0xCB
|
|
500 <1>
|
|
501 <1> %endif ; _PXE_INC
|
|
502 <1>
|
|
503 %include "layout.inc"
|
|
504 <1> ; $Id: layout.inc,v 1.1 2004/12/28 06:05:14 hpa Exp $
|
|
505 <1> ; -----------------------------------------------------------------------
|
|
506 <1> ;
|
|
507 <1> ; Copyright 1994-2004 H. Peter Anvin - All Rights Reserved
|
|
508 <1> ;
|
|
509 <1> ; This program is free software; you can redistribute it and/or modify
|
|
510 <1> ; it under the terms of the GNU General Public License as published by
|
|
511 <1> ; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
|
|
512 <1> ; Bostom MA 02111-1307, USA; either version 2 of the License, or
|
|
513 <1> ; (at your option) any later version; incorporated herein by reference.
|
|
514 <1> ;
|
|
515 <1> ; -----------------------------------------------------------------------
|
|
516 <1>
|
|
517 <1> ;
|
|
518 <1> ; layout.inc
|
|
519 <1> ;
|
|
520 <1> ; Memory layout of segments
|
|
521 <1> ;
|
|
522 <1>
|
|
523 <1>
|
|
524 <1> ; Memory below 0800h is reserved for the BIOS and the MBR
|
|
525 <1> BSS_START equ 0800h
|
|
526 <1>
|
|
527 <1> ; PXELINUX needs lots of BSS, so it relocates itself on startup
|
|
528 <1> %if IS_PXELINUX
|
|
529 <1> TEXT_START equ 9000h
|
|
530 <1> %else
|
|
531 <1> TEXT_START equ 7C00h
|
|
532 <1> %endif
|
|
533 <1>
|
|
534 <1> %ifdef MAP
|
|
535 <1> [map all MAP]
|
|
536 <1> %endif
|
|
537 <1>
|
|
538 <1> ;
|
|
539 <1> ; The various sections and their relationship
|
|
540 <1> ;
|
|
541 <1> org TEXT_START
|
|
542 <1>
|
|
543 <1> ; NASM BUG: refers to hacks to handle NASM 0.98.38 bugs; might need
|
|
544 <1> ; conditional compilation
|
|
545 <1>
|
|
546 <1> section .earlybss nobits start=BSS_START
|
|
547 <1> section .bcopy32 align=4 valign=16 follows=.data vfollows=.earlybss
|
|
548 <1> ; NASM BUG: follows= here should be vfollows=
|
|
549 <1> section .bss nobits align=256 follows=.bcopy32
|
|
550 <1>
|
|
551 <1> section .text start=TEXT_START
|
|
552 <1> ; NASM BUG: follows=.text not accepted here
|
|
553 <1> section .data align=16 ; follows=.text
|
|
554 <1>
|
|
555 <1> ; NASM BUG: We would like to do follows=.bcopy32
|
|
556 <1> section .latebss nobits align=16 start=0E000h
|
|
557 <1>
|
|
558 <1>
|
|
559
|
|
560 ;
|
|
561 ; Some semi-configurable constants... change on your own risk.
|
|
562 ;
|
|
563 my_id equ pxelinux_id
|
|
564 FILENAME_MAX_LG2 equ 7 ; log2(Max filename size Including final null)
|
|
565 FILENAME_MAX equ (1 << FILENAME_MAX_LG2)
|
|
566 NULLFILE equ 0 ; Zero byte == null file name
|
|
567 NULLOFFSET equ 4 ; Position in which to look
|
|
568 REBOOT_TIME equ 5*60 ; If failure, time until full reset
|
|
569 %assign HIGHMEM_SLOP 128*1024 ; Avoid this much memory near the top
|
|
570 MAX_OPEN_LG2 equ 5 ; log2(Max number of open sockets)
|
|
571 MAX_OPEN equ (1 << MAX_OPEN_LG2)
|
|
572 PKTBUF_SIZE equ (65536/MAX_OPEN) ; Per-socket packet buffer size
|
|
573 TFTP_PORT equ htons(69) ; Default TFTP port
|
|
574 PKT_RETRY equ 6 ; Packet transmit retry count
|
|
575 PKT_TIMEOUT equ 12 ; Initial timeout, timer ticks @ 55 ms
|
|
576 ; Desired TFTP block size
|
|
577 ; For Ethernet MTU is normally 1500. Unfortunately there seems to
|
|
578 ; be a fair number of networks with "substandard" MTUs which break.
|
|
579 ; The code assumes TFTP_LARGEBLK <= 2K.
|
|
580 TFTP_MTU equ 1472
|
|
581 TFTP_LARGEBLK equ (TFTP_MTU-20-8-4) ; MTU - IP hdr - UDP hdr - TFTP hdr
|
|
582 ; Standard TFTP block size
|
|
583 TFTP_BLOCKSIZE_LG2 equ 9 ; log2(bytes/block)
|
|
584 TFTP_BLOCKSIZE equ (1 << TFTP_BLOCKSIZE_LG2)
|
|
585 %assign USE_PXE_PROVIDED_STACK 1 ; Use stack provided by PXE?
|
|
586
|
|
587 SECTOR_SHIFT equ TFTP_BLOCKSIZE_LG2
|
|
588 SECTOR_SIZE equ TFTP_BLOCKSIZE
|
|
589
|
|
590 ;
|
|
591 ; This is what we need to do when idle
|
|
592 ;
|
|
593 %macro RESET_IDLE 0
|
|
594 call reset_idle
|
|
595 %endmacro
|
|
596 %macro DO_IDLE 0
|
|
597 call check_for_arp
|
|
598 %endmacro
|
|
599
|
|
600 ;
|
|
601 ; TFTP operation codes
|
|
602 ;
|
|
603 TFTP_RRQ equ htons(1) ; Read request
|
|
604 TFTP_WRQ equ htons(2) ; Write request
|
|
605 TFTP_DATA equ htons(3) ; Data packet
|
|
606 TFTP_ACK equ htons(4) ; ACK packet
|
|
607 TFTP_ERROR equ htons(5) ; ERROR packet
|
|
608 TFTP_OACK equ htons(6) ; OACK packet
|
|
609
|
|
610 ;
|
|
611 ; TFTP error codes
|
|
612 ;
|
|
613 TFTP_EUNDEF equ htons(0) ; Unspecified error
|
|
614 TFTP_ENOTFOUND equ htons(1) ; File not found
|
|
615 TFTP_EACCESS equ htons(2) ; Access violation
|
|
616 TFTP_ENOSPACE equ htons(3) ; Disk full
|
|
617 TFTP_EBADOP equ htons(4) ; Invalid TFTP operation
|
|
618 TFTP_EBADID equ htons(5) ; Unknown transfer
|
|
619 TFTP_EEXISTS equ htons(6) ; File exists
|
|
620 TFTP_ENOUSER equ htons(7) ; No such user
|
|
621 TFTP_EOPTNEG equ htons(8) ; Option negotiation failure
|
|
622
|
|
623 ;
|
|
624 ; The following structure is used for "virtual kernels"; i.e. LILO-style
|
|
625 ; option labels. The options we permit here are `kernel' and `append
|
|
626 ; Since there is no room in the bottom 64K for all of these, we
|
|
627 ; stick them at vk_seg:0000 and copy them down before we need them.
|
|
628 ;
|
|
629 struc vkernel
|
|
630 00000000 <res 00000080> vk_vname: resb FILENAME_MAX ; Virtual name **MUST BE FIRST!**
|
|
631 00000080 <res 00000080> vk_rname: resb FILENAME_MAX ; Real name
|
|
632 00000100 <res 00000001> vk_ipappend: resb 1 ; "IPAPPEND" flag
|
|
633 00000101 <res 00000001> resb 1 ; Pad
|
|
634 00000102 <res 00000002> vk_appendlen: resw 1
|
|
635 alignb 4
|
|
636 00000104 <res 00000200> vk_append: resb max_cmd_len+1 ; Command line
|
|
637 alignb 4
|
|
638 vk_end: equ $ ; Should be <= vk_size
|
|
639 endstruc
|
|
640
|
|
641 ;
|
|
642 ; Segment assignments in the bottom 640K
|
|
643 ; 0000h - main code/data segment (and BIOS segment)
|
|
644 ;
|
|
645 real_mode_seg equ 4000h
|
|
646 vk_seg equ 3000h ; Virtual kernels
|
|
647 xfer_buf_seg equ 2000h ; Bounce buffer for I/O to high mem
|
|
648 pktbuf_seg equ 1000h ; Packet buffers segments
|
|
649 comboot_seg equ real_mode_seg ; COMBOOT image loading zone
|
|
650
|
|
651 ;
|
|
652 ; BOOTP/DHCP packet pattern
|
|
653 ;
|
|
654 struc bootp_t
|
|
655 bootp:
|
|
656 00000000 <res 00000001> .opcode resb 1 ; BOOTP/DHCP "opcode"
|
|
657 00000001 <res 00000001> .hardware resb 1 ; ARP hardware type
|
|
658 00000002 <res 00000001> .hardlen resb 1 ; Hardware address length
|
|
659 00000003 <res 00000001> .gatehops resb 1 ; Used by forwarders
|
|
660 00000004 <res 00000004> .ident resd 1 ; Transaction ID
|
|
661 00000008 <res 00000002> .seconds resw 1 ; Seconds elapsed
|
|
662 0000000A <res 00000002> .flags resw 1 ; Broadcast flags
|
|
663 0000000C <res 00000004> .cip resd 1 ; Client IP
|
|
664 00000010 <res 00000004> .yip resd 1 ; "Your" IP
|
|
665 00000014 <res 00000004> .sip resd 1 ; Next server IP
|
|
666 00000018 <res 00000004> .gip resd 1 ; Relay agent IP
|
|
667 0000001C <res 00000010> .macaddr resb 16 ; Client MAC address
|
|
668 0000002C <res 00000040> .sname resb 64 ; Server name (optional)
|
|
669 0000006C <res 00000080> .bootfile resb 128 ; Boot file name
|
|
670 000000EC <res 00000004> .option_magic resd 1 ; Vendor option magic cookie
|
|
671 000000F0 <res 000004EC> .options resb 1260 ; Vendor options
|
|
672 endstruc
|
|
673
|
|
674 BOOTP_OPTION_MAGIC equ htonl(0x63825363) ; See RFC 2132
|
|
675
|
|
676 ;
|
|
677 ; TFTP connection data structure. Each one of these corresponds to a local
|
|
678 ; UDP port. The size of this structure must be a power of 2.
|
|
679 ; HBO = host byte order; NBO = network byte order
|
|
680 ; (*) = written by options negotiation code, must be dword sized
|
|
681 ;
|
|
682 struc open_file_t
|
|
683 00000000 <res 00000002> tftp_localport resw 1 ; Local port number (0 = not in use)
|
|
684 00000002 <res 00000002> tftp_remoteport resw 1 ; Remote port number
|
|
685 00000004 <res 00000004> tftp_remoteip resd 1 ; Remote IP address
|
|
686 00000008 <res 00000004> tftp_filepos resd 1 ; Bytes downloaded (including buffer)
|
|
687 0000000C <res 00000004> tftp_filesize resd 1 ; Total file size(*)
|
|
688 00000010 <res 00000004> tftp_blksize resd 1 ; Block size for this connection(*)
|
|
689 00000014 <res 00000002> tftp_bytesleft resw 1 ; Unclaimed data bytes
|
|
690 00000016 <res 00000002> tftp_lastpkt resw 1 ; Sequence number of last packet (NBO)
|
|
691 00000018 <res 00000002> tftp_dataptr resw 1 ; Pointer to available data
|
|
692 0000001A <res 00000004> resw 2 ; Currently unusued
|
|
693 ; At end since it should not be zeroed on socked close
|
|
694 0000001E <res 00000002> tftp_pktbuf resw 1 ; Packet buffer offset
|
|
695 endstruc
|
|
696 %ifndef DEPEND
|
|
697 %if (open_file_t_size & (open_file_t_size-1))
|
|
698 %error "open_file_t is not a power of 2"
|
|
699 %endif
|
|
700 %endif
|
|
701
|
|
702 ; ---------------------------------------------------------------------------
|
|
703 ; BEGIN CODE
|
|
704 ; ---------------------------------------------------------------------------
|
|
705
|
|
706 ;
|
|
707 ; Memory below this point is reserved for the BIOS and the MBR
|
|
708 ;
|
|
709 section .earlybss
|
|
710 trackbufsize equ 8192
|
|
711 00000000 <res 00002000> trackbuf resb trackbufsize ; Track buffer goes here
|
|
712 00002000 <res 00002000> getcbuf resb trackbufsize
|
|
713 ; ends at 4800h
|
|
714
|
|
715 ; Put some large buffers here, before RBFG_brainfuck,
|
|
716 ; where we can still carefully control the address
|
|
717 ; assignments...
|
|
718
|
|
719 alignb open_file_t_size
|
|
720 00004000 <res 00000400> Files resb MAX_OPEN*open_file_t_size
|
|
721
|
|
722 alignb FILENAME_MAX
|
|
723 00004400 <res 00000100> BootFile resb 256 ; Boot file from DHCP packet
|
|
724 00004500 <res 00000004> ConfigServer resd 1 ; Null prefix for mangled config name
|
|
725 00004504 <res 000000FC> ConfigName resb 256-4 ; Configuration file from DHCP option
|
|
726 00004600 <res 00000100> PathPrefix resb 256 ; Path prefix derived from boot file
|
|
727 00004700 <res 00000010> DotQuadBuf resb 16 ; Buffer for dotted-quad IP address
|
|
728 00004710 <res 00000050> IPOption resb 80 ; ip= option buffer
|
|
729 00004760 <res 00000004> InitStack resd 1 ; Pointer to reset stack
|
|
730
|
|
731 ; Warning here: RBFG build 22 randomly overwrites memory location
|
|
732 ; [0x5680,0x576c), possibly more. It seems that it gets confused and
|
|
733 ; screws up the pointer to its own internal packet buffer and starts
|
|
734 ; writing a received ARP packet into low memory.
|
|
735 00004764 <res 00000E00> RBFG_brainfuck resb 0E00h
|
|
736
|
|
737 section .bss
|
|
738 alignb 4
|
|
739 00000000 <res 00000004> RebootTime resd 1 ; Reboot timeout, if set by option
|
|
740 00000004 <res 00000004> StrucPtr resd 1 ; Pointer to PXENV+ or !PXE structure
|
|
741 00000008 <res 00000002> APIVer resw 1 ; PXE API version found
|
|
742 0000000A <res 00000002> IPOptionLen resw 1 ; Length of IPOption
|
|
743 0000000C <res 00000002> IdleTimer resw 1 ; Time to check for ARP?
|
|
744 0000000E <res 00000002> LocalBootType resw 1 ; Local boot return code
|
|
745 00000010 <res 00000002> PktTimeout resw 1 ; Timeout for current packet
|
|
746 00000012 <res 00000002> RealBaseMem resw 1 ; Amount of DOS memory after freeing
|
|
747 00000014 <res 00000001> OverLoad resb 1 ; Set if DHCP packet uses "overloading"
|
|
748
|
|
749 ; The relative position of these fields matter!
|
|
750 00000015 <res 00000001> MACLen resb 1 ; MAC address len
|
|
751 00000016 <res 00000001> MACType resb 1 ; MAC address type
|
|
752 00000017 <res 00000010> MAC resb 16 ; Actual MAC address
|
|
753 00000027 <res 00000007> BOOTIFStr resb 7 ; Space for "BOOTIF="
|
|
754 0000002E <res 00000033> MACStr resb 3*17 ; MAC address as a string
|
|
755
|
|
756 ;
|
|
757 ; PXE packets which don't need static initialization
|
|
758 ;
|
|
759 00000061 <res 00000001>- alignb 4
|
|
760 00000061 <rept>
|
|
761 pxe_unload_stack_pkt:
|
|
762 00000064 <res 00000002> .status: resw 1 ; Status
|
|
763 00000066 <res 00000014> .reserved: resw 10 ; Reserved
|
|
764 pxe_unload_stack_pkt_len equ $-pxe_unload_stack_pkt
|
|
765
|
|
766 0000007A <res 00000001>- alignb 16
|
|
767 0000007A <rept>
|
|
768 ; BOOTP/DHCP packet buffer
|
|
769
|
|
770 alignb 16
|
|
771 00000080 <res 00000800> packet_buf resb 2048 ; Transfer packet
|
|
772 packet_buf_size equ $-packet_buf
|
|
773
|
|
774 ;
|
|
775 ; Constants for the xfer_buf_seg
|
|
776 ;
|
|
777 ; The xfer_buf_seg is also used to store message file buffers. We
|
|
778 ; need two trackbuffers (text and graphics), plus a work buffer
|
|
779 ; for the graphics decompressor.
|
|
780 ;
|
|
781 xbs_textbuf equ 0 ; Also hard-coded, do not change
|
|
782 xbs_vgabuf equ trackbufsize
|
|
783 xbs_vgatmpbuf equ 2*trackbufsize
|
|
784
|
|
785 section .text
|
|
786 ;
|
|
787 ; PXELINUX needs more BSS than the other derivatives;
|
|
788 ; therefore we relocate it from 7C00h on startup.
|
|
789 ;
|
|
790 StackBuf equ $ ; Base of stack if we use our own
|
|
791
|
|
792 ;
|
|
793 ; Primary entry point.
|
|
794 ;
|
|
795 bootsec equ $
|
|
796 _start:
|
|
797 00000000 669C pushfd ; Paranoia... in case of return to PXE
|
|
798 00000002 6660 pushad ; ... save as much state as possible
|
|
799 00000004 1E push ds
|
|
800 00000005 06 push es
|
|
801 00000006 0FA0 push fs
|
|
802 00000008 0FA8 push gs
|
|
803
|
|
804 0000000A 31C0 xor ax,ax
|
|
805 0000000C 8ED8 mov ds,ax
|
|
806 0000000E 8EC0 mov es,ax
|
|
807
|
|
808 ; This is uglier than it should be, but works around
|
|
809 ; some NASM 0.98.38 bugs.
|
|
810 00000010 BF[0000] mov di,section..bcopy32.start
|
|
811 00000013 81C70802 add di,__bcopy_size-4
|
|
812 00000017 8DB500EC lea si,[di-(TEXT_START-7C00h)]
|
|
813 0000001B 8D8D0470 lea cx,[di-(TEXT_START-4)]
|
|
814 0000001F C1E902 shr cx,2
|
|
815 00000022 FD std ; Overlapping areas, copy backwards
|
|
816 00000023 F366A5 rep movsd
|
|
817
|
|
818 00000026 EA[2B00]0000 jmp 0:_start1 ; Canonicalize address
|
|
819 _start1:
|
|
820 0000002B 89E5 mov bp,sp
|
|
821 0000002D C45E30 les bx,[bp+48] ; ES:BX -> !PXE or PXENV+ structure
|
|
822
|
|
823 ; That is all pushed onto the PXE stack. Save the pointer
|
|
824 ; to it and switch to an internal stack.
|
|
825 00000030 8926[6047] mov [InitStack],sp
|
|
826 00000034 8C16[6247] mov [InitStack+2],ss
|
|
827
|
|
828 %if USE_PXE_PROVIDED_STACK
|
|
829 ; Apparently some platforms go bonkers if we
|
|
830 ; set up our own stack...
|
|
831 00000038 8926[A008] mov [BaseStack],sp
|
|
832 0000003C 8C16[A408] mov [BaseStack+4],ss
|
|
833 %endif
|
|
834
|
|
835 00000040 FA cli ; Paranoia
|
|
836 00000041 660FB226[A008] lss esp,[BaseStack]
|
|
837
|
|
838 00000047 FB sti ; Stack set up and ready
|
|
839 00000048 FC cld ; Copy upwards
|
|
840
|
|
841 ;
|
|
842 ; Initialize screen (if we're using one)
|
|
843 ;
|
|
844 ; Now set up screen parameters
|
|
845 00000049 E85A22 call adjust_screen
|
|
846
|
|
847 ; Wipe the F-key area
|
|
848 0000004C B000 mov al,NULLFILE
|
|
849 0000004E BF[DC16] mov di,FKeyName
|
|
850 00000051 B90005 mov cx,10*(1 << FILENAME_MAX_LG2)
|
|
851 00000054 06 push es ; Save ES -> PXE structure
|
|
852 00000055 1E push ds ; ES <- DS
|
|
853 00000056 07 pop es
|
|
854 00000057 F3AA rep stosb
|
|
855 00000059 07 pop es ; Restore ES
|
|
856
|
|
857 ;
|
|
858 ; Tell the user we got this far
|
|
859 ;
|
|
860 0000005A BE[EE06] mov si,syslinux_banner
|
|
861 0000005D E8F41D call writestr
|
|
862
|
|
863 00000060 BE[4B01] mov si,copyright_str
|
|
864 00000063 E8EE1D call writestr
|
|
865
|
|
866 ;
|
|
867 ; Assume API version 2.1, in case we find the !PXE structure without
|
|
868 ; finding the PXENV+ structure. This should really look at the Base
|
|
869 ; Code ROM ID structure in have_pxe, but this is adequate for now --
|
|
870 ; if we have !PXE, we have to be 2.1 or higher, and we don't care
|
|
871 ; about higher versions than that.
|
|
872 ;
|
|
873 00000066 C706[0800]0102 mov word [APIVer],0201h
|
|
874
|
|
875 ;
|
|
876 ; Now we need to find the !PXE structure. It's *supposed* to be pointed
|
|
877 ; to by SS:[SP+4], but support INT 1Ah, AX=5650h method as well.
|
|
878 ; FIX: ES:BX should point to the PXENV+ structure on entry as well.
|
|
879 ; We should make that the second test, and not trash ES:BX...
|
|
880 ;
|
|
881 0000006C 2666813F21505845 cmp dword [es:bx], '!PXE'
|
|
882 00000074 0F840F01 je have_pxe
|
|
883
|
|
884 ; Uh-oh, not there... try plan B
|
|
885 00000078 B85056 mov ax, 5650h
|
|
886 0000007B CD1A int 1Ah ; May trash regs
|
|
887 0000007D 7223 jc no_pxe
|
|
888 0000007F 3D4E56 cmp ax,564Eh
|
|
889 00000082 751E jne no_pxe
|
|
890
|
|
891 ; Okay, that gave us the PXENV+ structure, find !PXE
|
|
892 ; structure from that (if available)
|
|
893 00000084 2666813F5058454E cmp dword [es:bx], 'PXEN'
|
|
894 0000008C 7514 jne no_pxe
|
|
895 0000008E 26817F04562B cmp word [es:bx+4], 'V+'
|
|
896 00000094 7415 je have_pxenv
|
|
897
|
|
898 ; Nothing there either. Last-ditch: scan memory
|
|
899 00000096 E87C11 call memory_scan_for_pxe_struct ; !PXE scan
|
|
900 00000099 0F83EA00 jnc have_pxe
|
|
901 0000009D E8DE11 call memory_scan_for_pxenv_struct ; PXENV+ scan
|
|
902 000000A0 7309 jnc have_pxenv
|
|
903
|
|
904 000000A2 BE[3004] no_pxe: mov si,err_nopxe
|
|
905 000000A5 E8AC1D call writestr
|
|
906 000000A8 E90A11 jmp kaboom
|
|
907
|
|
908 have_pxenv:
|
|
909 000000AB 891E[0400] mov [StrucPtr],bx
|
|
910 000000AF 8C06[0600] mov [StrucPtr+2],es
|
|
911
|
|
912 000000B3 BE[CA04] mov si,found_pxenv
|
|
913 000000B6 E89B1D call writestr
|
|
914
|
|
915 000000B9 BE[1205] mov si,apiver_str
|
|
916 000000BC E8951D call writestr
|
|
917 000000BF 268B4706 mov ax,[es:bx+6]
|
|
918 000000C3 A3[0800] mov [APIVer],ax
|
|
919 000000C6 E8AB1D call writehex4
|
|
920 000000C9 E87B1D call crlf
|
|
921
|
|
922 000000CC 3D0102 cmp ax,0201h ; API version 2.1 or higher
|
|
923 000000CF 721F jb old_api
|
|
924 000000D1 89DE mov si,bx
|
|
925 000000D3 8CC0 mov ax,es
|
|
926 000000D5 26C45F28 les bx,[es:bx+28h] ; !PXE structure pointer
|
|
927 000000D9 2666813F21505845 cmp dword [es:bx],'!PXE'
|
|
928 000000E1 0F84A200 je have_pxe
|
|
929
|
|
930 ; Nope, !PXE structure missing despite API 2.1+, or at least
|
|
931 ; the pointer is missing. Do a last-ditch attempt to find it.
|
|
932 000000E5 E82D11 call memory_scan_for_pxe_struct
|
|
933 000000E8 0F839B00 jnc have_pxe
|
|
934
|
|
935 ; Otherwise, no dice, use PXENV+ structure
|
|
936 000000EC 89F3 mov bx,si
|
|
937 000000EE 8EC0 mov es,ax
|
|
938
|
|
939 old_api: ; Need to use a PXENV+ structure
|
|
940 000000F0 BE[E304] mov si,using_pxenv_msg
|
|
941 000000F3 E85E1D call writestr
|
|
942
|
|
943 000000F6 26668B470A mov eax,[es:bx+0Ah] ; PXE RM API
|
|
944 000000FB 66A3[A815] mov [PXENVEntry],eax
|
|
945
|
|
946 000000FF BE[C005] mov si,undi_data_msg
|
|
947 00000102 E84F1D call writestr
|
|
948 00000105 268B4720 mov ax,[es:bx+20h]
|
|
949 00000109 E8681D call writehex4
|
|
950 0000010C E8381D call crlf
|
|
951 0000010F BE[D905] mov si,undi_data_len_msg
|
|
952 00000112 E83F1D call writestr
|
|
953 00000115 268B4722 mov ax,[es:bx+22h]
|
|
954 00000119 E8581D call writehex4
|
|
955 0000011C E8281D call crlf
|
|
956 0000011F BE[F205] mov si,undi_code_msg
|
|
957 00000122 E82F1D call writestr
|
|
958 00000125 268B4724 mov ax,[es:bx+24h]
|
|
959 00000129 E8481D call writehex4
|
|
960 0000012C E8181D call crlf
|
|
961 0000012F BE[0B06] mov si,undi_code_len_msg
|
|
962 00000132 E81F1D call writestr
|
|
963 00000135 268B4726 mov ax,[es:bx+26h]
|
|
964 00000139 E8381D call writehex4
|
|
965 0000013C E8081D call crlf
|
|
966
|
|
967 ; Compute base memory size from PXENV+ structure
|
|
968 0000013F 6631F6 xor esi,esi
|
|
969 00000142 26660FB74720 movzx eax,word [es:bx+20h] ; UNDI data seg
|
|
970 00000148 263B4724 cmp ax,[es:bx+24h] ; UNDI code seg
|
|
971 0000014C 770A ja .use_data
|
|
972 0000014E 268B4724 mov ax,[es:bx+24h]
|
|
973 00000152 268B7726 mov si,[es:bx+26h]
|
|
974 00000156 EB04 jmp short .combine
|
|
975 .use_data:
|
|
976 00000158 268B7722 mov si,[es:bx+22h]
|
|
977 .combine:
|
|
978 0000015C 66C1E004 shl eax,4
|
|
979 00000160 6601F0 add eax,esi
|
|
980 00000163 66C1E80A shr eax,10 ; Convert to kilobytes
|
|
981 00000167 A3[1200] mov [RealBaseMem],ax
|
|
982
|
|
983 0000016A BE[4A05] mov si,pxenventry_msg
|
|
984 0000016D E8E41C call writestr
|
|
985 00000170 A1[AA15] mov ax,[PXENVEntry+2]
|
|
986 00000173 E8FE1C call writehex4
|
|
987 00000176 B03A mov al,':'
|
|
988 00000178 E80A24 call writechr
|
|
989 0000017B A1[A815] mov ax,[PXENVEntry]
|
|
990 0000017E E8F31C call writehex4
|
|
991 00000181 E8C31C call crlf
|
|
992 00000184 E99400 jmp have_entrypoint
|
|
993
|
|
994 have_pxe:
|
|
995 00000187 891E[0400] mov [StrucPtr],bx
|
|
996 0000018B 8C06[0600] mov [StrucPtr+2],es
|
|
997
|
|
998 0000018F 26668B4710 mov eax,[es:bx+10h]
|
|
999 00000194 66A3[B215] mov [PXEEntry],eax
|
|
1000
|
|
1001 00000198 BE[C005] mov si,undi_data_msg
|
|
1002 0000019B E8B61C call writestr
|
|
1003 0000019E 26668B472A mov eax,[es:bx+2Ah]
|
|
1004 000001A3 E8DB1C call writehex8
|
|
1005 000001A6 E89E1C call crlf
|
|
1006 000001A9 BE[D905] mov si,undi_data_len_msg
|
|
1007 000001AC E8A51C call writestr
|
|
1008 000001AF 268B472E mov ax,[es:bx+2Eh]
|
|
1009 000001B3 E8BE1C call writehex4
|
|
1010 000001B6 E88E1C call crlf
|
|
1011 000001B9 BE[F205] mov si,undi_code_msg
|
|
1012 000001BC E8951C call writestr
|
|
1013 000001BF 268B4732 mov ax,[es:bx+32h]
|
|
1014 000001C3 E8BB1C call writehex8
|
|
1015 000001C6 E87E1C call crlf
|
|
1016 000001C9 BE[0B06] mov si,undi_code_len_msg
|
|
1017 000001CC E8851C call writestr
|
|
1018 000001CF 268B4736 mov ax,[es:bx+36h]
|
|
1019 000001D3 E89E1C call writehex4
|
|
1020 000001D6 E86E1C call crlf
|
|
1021
|
|
1022 ; Compute base memory size from !PXE structure
|
|
1023 000001D9 6631F6 xor esi,esi
|
|
1024 000001DC 26668B472A mov eax,[es:bx+2Ah]
|
|
1025 000001E1 26663B4732 cmp eax,[es:bx+32h]
|
|
1026 000001E6 770B ja .use_data
|
|
1027 000001E8 26668B4732 mov eax,[es:bx+32h]
|
|
1028 000001ED 268B7736 mov si,[es:bx+36h]
|
|
1029 000001F1 EB04 jmp short .combine
|
|
1030 .use_data:
|
|
1031 000001F3 268B772E mov si,[es:bx+2Eh]
|
|
1032 .combine:
|
|
1033 000001F7 6601F0 add eax,esi
|
|
1034 000001FA 66C1E80A shr eax,10
|
|
1035 000001FE A3[1200] mov [RealBaseMem],ax
|
|
1036
|
|
1037 00000201 BE[2605] mov si,pxeentry_msg
|
|
1038 00000204 E84D1C call writestr
|
|
1039 00000207 A1[B415] mov ax,[PXEEntry+2]
|
|
1040 0000020A E8671C call writehex4
|
|
1041 0000020D B03A mov al,':'
|
|
1042 0000020F E87323 call writechr
|
|
1043 00000212 A1[B215] mov ax,[PXEEntry]
|
|
1044 00000215 E85C1C call writehex4
|
|
1045 00000218 E82C1C call crlf
|
|
1046
|
|
1047 have_entrypoint:
|
|
1048 0000021B 0E push cs
|
|
1049 0000021C 07 pop es ; Restore CS == DS == ES
|
|
1050
|
|
1051 ;
|
|
1052 ; Network-specific initialization
|
|
1053 ;
|
|
1054 0000021D 31C0 xor ax,ax
|
|
1055 0000021F A2[9C23] mov [LocalDomain],al ; No LocalDomain received
|
|
1056
|
|
1057 ;
|
|
1058 ; Now attempt to get the BOOTP/DHCP packet that brought us life (and an IP
|
|
1059 ; address). This lives in the DHCPACK packet (query info 2).
|
|
1060 ;
|
|
1061 query_bootp:
|
|
1062 00000222 BF[4A08] mov di,pxe_bootp_query_pkt_2
|
|
1063 00000225 BB7100 mov bx,PXENV_GET_CACHED_INFO
|
|
1064
|
|
1065 00000228 E87C13 call pxenv
|
|
1066 0000022B FF36[4A08] push word [pxe_bootp_query_pkt_2.status]
|
|
1067 0000022F 7205 jc .pxe_err1
|
|
1068 00000231 83F800 cmp ax,byte 0
|
|
1069 00000234 742C je .pxe_ok
|
|
1070 .pxe_err1:
|
|
1071 00000236 BF[6208] mov di,pxe_bootp_size_query_pkt
|
|
1072 00000239 BB7100 mov bx,PXENV_GET_CACHED_INFO
|
|
1073
|
|
1074 0000023C E86813 call pxenv
|
|
1075 0000023F 7209 jc .pxe_err
|
|
1076 .pxe_size:
|
|
1077 00000241 A1[6608] mov ax,[pxe_bootp_size_query_pkt.buffersize]
|
|
1078 00000244 E82D1C call writehex4
|
|
1079 00000247 E8FD1B call crlf
|
|
1080
|
|
1081 .pxe_err:
|
|
1082 0000024A BE[5D04] mov si,err_pxefailed
|
|
1083 0000024D E8041C call writestr
|
|
1084 00000250 E8211C call writehex4
|
|
1085 00000253 B020 mov al, ' '
|
|
1086 00000255 E82D23 call writechr
|
|
1087 00000258 58 pop ax ; Status
|
|
1088 00000259 E8181C call writehex4
|
|
1089 0000025C E8E81B call crlf
|
|
1090 0000025F E9530F jmp kaboom ; We're dead
|
|
1091
|
|
1092 .pxe_ok:
|
|
1093 00000262 59 pop cx ; Forget status
|
|
1094 00000263 8B0E[4E08] mov cx,[pxe_bootp_query_pkt_2.buffersize]
|
|
1095 00000267 E8C215 call parse_dhcp ; Parse DHCP packet
|
|
1096 ;
|
|
1097 ; Save away MAC address (assume this is in query info 2. If this
|
|
1098 ; turns out to be problematic it might be better getting it from
|
|
1099 ; the query info 1 packet.)
|
|
1100 ;
|
|
1101 .save_mac:
|
|
1102 0000026A 0FB60E[0200] movzx cx,byte [trackbuf+bootp.hardlen]
|
|
1103 0000026F 880E[1500] mov [MACLen],cl
|
|
1104 00000273 A0[0100] mov al,[trackbuf+bootp.hardware]
|
|
1105 00000276 A2[1600] mov [MACType],al
|
|
1106 00000279 BE[1C00] mov si,trackbuf+bootp.macaddr
|
|
1107 0000027C BF[1700] mov di,MAC
|
|
1108 0000027F 51 push cx
|
|
1109 00000280 F3A4 rep movsb
|
|
1110 00000282 B9[2700] mov cx,MAC+16
|
|
1111 00000285 29F9 sub cx,di
|
|
1112 00000287 31C0 xor ax,ax
|
|
1113 00000289 F3AA rep stosb
|
|
1114
|
|
1115 0000028B BE[1E07] mov si,bootif_str
|
|
1116 0000028E BF[2700] mov di,BOOTIFStr
|
|
1117 00000291 B90700 mov cx,bootif_str_len
|
|
1118 00000294 F3A4 rep movsb
|
|
1119
|
|
1120 00000296 59 pop cx
|
|
1121 00000297 BE[1600] mov si,MACType
|
|
1122 0000029A 41 inc cx
|
|
1123 0000029B BB[3B01] mov bx,hextbl_lower
|
|
1124 .hexify_mac:
|
|
1125 0000029E AC lodsb
|
|
1126 0000029F 88C4 mov ah,al
|
|
1127 000002A1 C0E804 shr al,4
|
|
1128 000002A4 D7 xlatb
|
|
1129 000002A5 AA stosb
|
|
1130 000002A6 88E0 mov al,ah
|
|
1131 000002A8 240F and al,0Fh
|
|
1132 000002AA D7 xlatb
|
|
1133 000002AB AA stosb
|
|
1134 000002AC B02D mov al,'-'
|
|
1135 000002AE AA stosb
|
|
1136 000002AF E2ED loop .hexify_mac
|
|
1137 000002B1 C645FF00 mov [di-1],byte 0 ; Null-terminate and strip final colon
|
|
1138
|
|
1139 ;
|
|
1140 ; Now, get the boot file and other info. This lives in the CACHED_REPLY
|
|
1141 ; packet (query info 3).
|
|
1142 ;
|
|
1143 000002B5 C606[6408]03 mov [pxe_bootp_size_query_pkt.packettype], byte 3
|
|
1144
|
|
1145 000002BA BF[5608] mov di,pxe_bootp_query_pkt_3
|
|
1146 000002BD BB7100 mov bx,PXENV_GET_CACHED_INFO
|
|
1147
|
|
1148 000002C0 E8E412 call pxenv
|
|
1149 000002C3 FF36[5608] push word [pxe_bootp_query_pkt_3.status]
|
|
1150 000002C7 0F826BFF jc .pxe_err1
|
|
1151 000002CB 83F800 cmp ax,byte 0
|
|
1152 000002CE 0F8564FF jne .pxe_err1
|
|
1153
|
|
1154 ; Packet loaded OK...
|
|
1155 000002D2 59 pop cx ; Forget status
|
|
1156 000002D3 8B0E[5A08] mov cx,[pxe_bootp_query_pkt_3.buffersize]
|
|
1157 000002D7 E85215 call parse_dhcp ; Parse DHCP packet
|
|
1158 ;
|
|
1159 ; Generate ip= option
|
|
1160 ;
|
|
1161 000002DA E8CC16 call genipopt
|
|
1162
|
|
1163 ;
|
|
1164 ; Print IP address
|
|
1165 ;
|
|
1166 000002DD 66A1[EC08] mov eax,[MyIP]
|
|
1167 000002E1 BF[0047] mov di,DotQuadBuf
|
|
1168 000002E4 57 push di
|
|
1169 000002E5 E80B15 call gendotquad ; This takes network byte order input
|
|
1170
|
|
1171 000002E8 86E0 xchg ah,al ; Convert to host byte order
|
|
1172 000002EA 66C1C810 ror eax,16 ; (BSWAP doesn't work on 386)
|
|
1173 000002EE 86E0 xchg ah,al
|
|
1174
|
|
1175 000002F0 BE[5306] mov si,myipaddr_msg
|
|
1176 000002F3 E85E1B call writestr
|
|
1177 000002F6 E8881B call writehex8
|
|
1178 000002F9 B020 mov al,' '
|
|
1179 000002FB E88722 call writechr
|
|
1180 000002FE 5E pop si ; DotQuadBuf
|
|
1181 000002FF E8521B call writestr
|
|
1182 00000302 E8421B call crlf
|
|
1183
|
|
1184 00000305 BE[1047] mov si,IPOption
|
|
1185 00000308 E8491B call writestr
|
|
1186 0000030B E8391B call crlf
|
|
1187
|
|
1188 ;
|
|
1189 ; Check to see if we got any PXELINUX-specific DHCP options; in particular,
|
|
1190 ; if we didn't get the magic enable, do not recognize any other options.
|
|
1191 ;
|
|
1192 check_dhcp_magic:
|
|
1193 0000030E F606[0909]01 test byte [DHCPMagic], 1 ; If we didn't get the magic enable...
|
|
1194 00000313 7505 jnz .got_magic
|
|
1195 00000315 C606[0909]00 mov byte [DHCPMagic], 0 ; If not, kill all other options
|
|
1196 .got_magic:
|
|
1197
|
|
1198
|
|
1199 ;
|
|
1200 ; Initialize UDP stack
|
|
1201 ;
|
|
1202 udp_init:
|
|
1203 0000031A 66A1[EC08] mov eax,[MyIP]
|
|
1204 0000031E 66A3[7008] mov [pxe_udp_open_pkt.sip],eax
|
|
1205 00000322 BF[6E08] mov di,pxe_udp_open_pkt
|
|
1206 00000325 BB3000 mov bx,PXENV_UDP_OPEN
|
|
1207 00000328 E87C12 call pxenv
|
|
1208 0000032B 7207 jc .failed
|
|
1209 0000032D 833E[6E08]00 cmp word [pxe_udp_open_pkt.status], byte 0
|
|
1210 00000332 7409 je .success
|
|
1211 00000334 BE[7904] .failed: mov si,err_udpinit
|
|
1212 00000337 E81A1B call writestr
|
|
1213 0000033A E9780E jmp kaboom
|
|
1214 .success:
|
|
1215
|
|
1216 ;
|
|
1217 ; Common initialization code
|
|
1218 ;
|
|
1219 %include "init.inc"
|
|
1220 <1> ; -*- fundamental -*-
|
|
1221 <1> ; -----------------------------------------------------------------------
|
|
1222 <1> ;
|
|
1223 <1> ; Copyright 2004 H. Peter Anvin - All Rights Reserved
|
|
1224 <1> ;
|
|
1225 <1> ; This program is free software; you can redistribute it and/or modify
|
|
1226 <1> ; it under the terms of the GNU General Public License as published by
|
|
1227 <1> ; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
|
|
1228 <1> ; Boston MA 02111-1307, USA; either version 2 of the License, or
|
|
1229 <1> ; (at your option) any later version; incorporated herein by reference.
|
|
1230 <1> ;
|
|
1231 <1> ; -----------------------------------------------------------------------
|
|
1232 <1> ; $Id: init.inc,v 1.1 2004/12/19 07:08:48 hpa Exp $
|
|
1233 <1>
|
|
1234 <1> ;
|
|
1235 <1> ; init.inc
|
|
1236 <1> ;
|
|
1237 <1> ; Common initialization code (inline)
|
|
1238 <1> ;
|
|
1239 <1>
|
|
1240 <1> section .text
|
|
1241 <1> common_init:
|
|
1242 <1> ; Now set up screen parameters
|
|
1243 0000033D E8661F <1> call adjust_screen
|
|
1244 <1>
|
|
1245 <1> ; Wipe the F-key area
|
|
1246 00000340 B000 <1> mov al,NULLFILE
|
|
1247 00000342 BF[DC16] <1> mov di,FKeyName
|
|
1248 00000345 B90005 <1> mov cx,10*(1 << FILENAME_MAX_LG2)
|
|
1249 00000348 F3AA <1> rep stosb
|
|
1250 <1>
|
|
1251 0000034A BE[0000] <1> mov si,linuxauto_cmd ; Default command: "linux auto"
|
|
1252 0000034D BF[D80A] <1> mov di,default_cmd
|
|
1253 00000350 B90B00 <1> mov cx,linuxauto_len
|
|
1254 00000353 F3A4 <1> rep movsb
|
|
1255 <1>
|
|
1256 00000355 BF[DC15] <1> mov di,KbdMap ; Default keymap 1:1
|
|
1257 00000358 30C0 <1> xor al,al
|
|
1258 0000035A FEC5 <1> inc ch ; CX <- 256
|
|
1259 0000035C AA <1> mkkeymap: stosb
|
|
1260 0000035D FEC0 <1> inc al
|
|
1261 0000035F E2FB <1> loop mkkeymap
|
|
1262 <1>
|
|
1263 <1> ;
|
|
1264 <1> ; Clear Files structures
|
|
1265 <1> ;
|
|
1266 00000361 BF[0040] <1> mov di,Files
|
|
1267 00000364 B90001 <1> mov cx,(MAX_OPEN*open_file_t_size)/4
|
|
1268 00000367 6631C0 <1> xor eax,eax
|
|
1269 0000036A F366AB <1> rep stosd
|
|
1270 <1>
|
|
1271 <1> %if IS_PXELINUX
|
|
1272 0000036D BF[1E40] <1> mov di,Files+tftp_pktbuf
|
|
1273 00000370 B92000 <1> mov cx,MAX_OPEN
|
|
1274 <1> .setbufptr:
|
|
1275 00000373 8905 <1> mov [di],ax
|
|
1276 00000375 83C720 <1> add di,open_file_t_size
|
|
1277 00000378 050008 <1> add ax,PKTBUF_SIZE
|
|
1278 0000037B E2F6 <1> loop .setbufptr
|
|
1279 <1> %endif
|
|
1280 <1>
|
|
1281 <1> section .data
|
|
1282 00000000 6C696E757820617574- <1> linuxauto_cmd db 'linux auto',0
|
|
1283 00000009 6F00 <1>
|
|
1284 <1> linuxauto_len equ $-linuxauto_cmd
|
|
1285 <1>
|
|
1286 <1> section .text ; This is an inline file...
|
|
1287 <1>
|
|
1288 %include "cpuinit.inc"
|
|
1289 <1> ;; $Id: cpuinit.inc,v 1.5 2004/12/27 07:04:08 hpa Exp $
|
|
1290 <1> ;; -----------------------------------------------------------------------
|
|
1291 <1> ;;
|
|
1292 <1> ;; Copyright 1994-2002 H. Peter Anvin - All Rights Reserved
|
|
1293 <1> ;;
|
|
1294 <1> ;; This program is free software; you can redistribute it and/or modify
|
|
1295 <1> ;; it under the terms of the GNU General Public License as published by
|
|
1296 <1> ;; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
|
|
1297 <1> ;; Boston MA 02111-1307, USA; either version 2 of the License, or
|
|
1298 <1> ;; (at your option) any later version; incorporated herein by reference.
|
|
1299 <1> ;;
|
|
1300 <1> ;; -----------------------------------------------------------------------
|
|
1301 <1>
|
|
1302 <1> ;;
|
|
1303 <1> ;; cpuinit.inc
|
|
1304 <1> ;;
|
|
1305 <1> ;; CPU-dependent initialization and related checks.
|
|
1306 <1> ;;
|
|
1307 <1>
|
|
1308 <1> check_escapes:
|
|
1309 0000037D B402 <1> mov ah,02h ; Check keyboard flags
|
|
1310 0000037F CD16 <1> int 16h
|
|
1311 00000381 A2[8408] <1> mov [KbdFlags],al ; Save for boot prompt check
|
|
1312 00000384 A804 <1> test al,04h ; Ctrl->skip 386 check
|
|
1313 00000386 7510 <1> jnz skip_checks
|
|
1314 <1>
|
|
1315 <1> ;
|
|
1316 <1> ; Now check that there is sufficient low (DOS) memory
|
|
1317 <1> ;
|
|
1318 <1> ; NOTE: Linux doesn't use all of real_mode_seg, but we use the same
|
|
1319 <1> ; segment for COMBOOT images, which can use all 64K
|
|
1320 <1> ;
|
|
1321 <1> dosram_k equ (real_mode_seg+0x1000) >> 6 ; Minimum DOS memory (K)
|
|
1322 00000388 CD12 <1> int 12h
|
|
1323 0000038A 3D4001 <1> cmp ax,dosram_k
|
|
1324 0000038D 7309 <1> jae enough_ram
|
|
1325 0000038F BE[C301] <1> mov si,err_noram
|
|
1326 00000392 E8BF1A <1> call writestr
|
|
1327 00000395 E91D0E <1> jmp kaboom
|
|
1328 <1> enough_ram:
|
|
1329 <1> skip_checks:
|
|
1330 <1>
|
|
1331 <1> ;
|
|
1332 <1> ; Initialize the bcopy32 code in low memory
|
|
1333 <1> ;
|
|
1334 00000398 BE[0000] <1> mov si,section..bcopy32.start
|
|
1335 0000039B BF[0000] <1> mov di,__bcopy_start
|
|
1336 0000039E B98300 <1> mov cx,__bcopy_size >> 2
|
|
1337 000003A1 F366A5 <1> rep movsd
|
|
1338 <1>
|
|
1339 <1> ;
|
|
1340 <1> ; Check if we're 386 (as opposed to 486+); if so we need to blank out
|
|
1341 <1> ; the WBINVD instruction
|
|
1342 <1> ;
|
|
1343 <1> ; We check for 486 by setting EFLAGS.AC
|
|
1344 <1> ;
|
|
1345 <1> %if DO_WBINVD
|
|
1346 <1> pushfd ; Save the good flags
|
|
1347 <1> pushfd
|
|
1348 <1> pop eax
|
|
1349 <1> mov ebx,eax
|
|
1350 <1> xor eax,(1 << 18) ; AC bit
|
|
1351 <1> push eax
|
|
1352 <1> popfd
|
|
1353 <1> pushfd
|
|
1354 <1> pop eax
|
|
1355 <1> popfd ; Restore the original flags
|
|
1356 <1> xor eax,ebx
|
|
1357 <1> jnz is_486
|
|
1358 <1> ;
|
|
1359 <1> ; 386 - Looks like we better blot out the WBINVD instruction
|
|
1360 <1> ;
|
|
1361 <1> mov byte [try_wbinvd],0c3h ; Near RET
|
|
1362 <1> is_486:
|
|
1363 <1> %endif ; DO_WBINVD
|
|
1364 <1>
|
|
1365
|
|
1366 ;
|
|
1367 ; Now we're all set to start with our *real* business. First load the
|
|
1368 ; configuration file (if any) and parse it.
|
|
1369 ;
|
|
1370 ; In previous versions I avoided using 32-bit registers because of a
|
|
1371 ; rumour some BIOSes clobbered the upper half of 32-bit registers at
|
|
1372 ; random. I figure, though, that if there are any of those still left
|
|
1373 ; they probably won't be trying to install Linux on them...
|
|
1374 ;
|
|
1375 ; The code is still ripe with 16-bitisms, though. Not worth the hassle
|
|
1376 ; to take'm out. In fact, we may want to put them back if we're going
|
|
1377 ; to boot ELKS at some point.
|
|
1378 ;
|
|
1379
|
|
1380 ;
|
|
1381 ; Store standard filename prefix
|
|
1382 ;
|
|
1383 000003A4 F606[0909]04 prefix: test byte [DHCPMagic], 04h ; Did we get a path prefix option
|
|
1384 000003A9 7537 jnz .got_prefix
|
|
1385 000003AB BE[0044] mov si,BootFile
|
|
1386 000003AE BF[0046] mov di,PathPrefix
|
|
1387 000003B1 FC cld
|
|
1388 000003B2 E8C721 call strcpy
|
|
1389 000003B5 89F9 mov cx,di
|
|
1390 000003B7 81E9[0146] sub cx,PathPrefix+1
|
|
1391 000003BB FD std
|
|
1392 000003BC 8D75FE lea si,[di-2] ; Skip final null!
|
|
1393 000003BF AC .find_alnum: lodsb
|
|
1394 000003C0 0C20 or al,20h
|
|
1395 000003C2 3C2E cmp al,'.' ; Count . or - as alphanum
|
|
1396 000003C4 7414 je .alnum
|
|
1397 000003C6 3C2D cmp al,'-'
|
|
1398 000003C8 7410 je .alnum
|
|
1399 000003CA 3C30 cmp al,'0'
|
|
1400 000003CC 720F jb .notalnum
|
|
1401 000003CE 3C39 cmp al,'9'
|
|
1402 000003D0 7608 jbe .alnum
|
|
1403 000003D2 3C61 cmp al,'a'
|
|
1404 000003D4 7207 jb .notalnum
|
|
1405 000003D6 3C7A cmp al,'z'
|
|
1406 000003D8 7703 ja .notalnum
|
|
1407 000003DA E2E3 .alnum: loop .find_alnum
|
|
1408 000003DC 4E dec si
|
|
1409 000003DD C6440200 .notalnum: mov byte [si+2],0 ; Zero-terminate after delimiter
|
|
1410 000003E1 FC cld
|
|
1411 .got_prefix:
|
|
1412 000003E2 BE[6E06] mov si,tftpprefix_msg
|
|
1413 000003E5 E86C1A call writestr
|
|
1414 000003E8 BE[0046] mov si,PathPrefix
|
|
1415 000003EB E8661A call writestr
|
|
1416 000003EE E8561A call crlf
|
|
1417
|
|
1418 ;
|
|
1419 ; Load configuration file
|
|
1420 ;
|
|
1421 find_config:
|
|
1422
|
|
1423 ;
|
|
1424 ; Begin looking for configuration file
|
|
1425 ;
|
|
1426 config_scan:
|
|
1427 000003F1 BF[0045] mov di,ConfigServer
|
|
1428 000003F4 6631C0 xor eax,eax
|
|
1429 000003F7 66AB stosd ; The config file is always from the server
|
|
1430
|
|
1431 000003F9 F606[0909]02 test byte [DHCPMagic], 02h
|
|
1432 000003FE 7418 jz .no_option
|
|
1433
|
|
1434 ; We got a DHCP option, try it first
|
|
1435 00000400 BE[B306] mov si,trying_msg
|
|
1436 00000403 E84E1A call writestr
|
|
1437 ; mov di,ConfigName ; - already the case
|
|
1438 00000406 89FE mov si,di
|
|
1439 00000408 E8491A call writestr
|
|
1440 0000040B E8391A call crlf
|
|
1441 0000040E BF[0045] mov di,ConfigServer
|
|
1442 00000411 E82C16 call open
|
|
1443 00000414 0F858900 jnz .success
|
|
1444
|
|
1445 .no_option:
|
|
1446 00000418 BF[0445] mov di,ConfigName
|
|
1447 0000041B BE[0A07] mov si,cfgprefix
|
|
1448 0000041E B90D00 mov cx,cfgprefix_len
|
|
1449 00000421 F3A4 rep movsb
|
|
1450
|
|
1451 ; Try loading by MAC address
|
|
1452 ; Have to guess config file name
|
|
1453 00000423 57 push di
|
|
1454 00000424 BE[2E00] mov si,MACStr
|
|
1455 00000427 B91A00 mov cx,(3*17+1)/2
|
|
1456 0000042A F3A5 rep movsw
|
|
1457 0000042C BE[B306] mov si,trying_msg
|
|
1458 0000042F E8221A call writestr
|
|
1459 00000432 BF[0445] mov di,ConfigName
|
|
1460 00000435 89FE mov si,di
|
|
1461 00000437 E81A1A call writestr
|
|
1462 0000043A E80A1A call crlf
|
|
1463 0000043D BF[0045] mov di,ConfigServer
|
|
1464 00000440 E8FD15 call open
|
|
1465 00000443 5F pop di
|
|
1466 00000444 755B jnz .success
|
|
1467
|
|
1468 .scan_ip:
|
|
1469 00000446 B90800 mov cx,8
|
|
1470 00000449 66A1[EC08] mov eax,[MyIP]
|
|
1471 0000044D 86E0 xchg ah,al ; Convert to host byte order
|
|
1472 0000044F 66C1C810 ror eax,16
|
|
1473 00000453 86E0 xchg ah,al
|
|
1474 00000455 66C1C004 .hexify_loop: rol eax,4
|
|
1475 00000459 6650 push eax
|
|
1476 0000045B 240F and al,0Fh
|
|
1477 0000045D 3C0A cmp al,10
|
|
1478 0000045F 7304 jae .high
|
|
1479 00000461 0430 .low: add al,'0'
|
|
1480 00000463 EB02 jmp short .char
|
|
1481 00000465 0437 .high: add al,'A'-10
|
|
1482 00000467 AA .char: stosb
|
|
1483 00000468 6658 pop eax
|
|
1484 0000046A E2E9 loop .hexify_loop
|
|
1485
|
|
1486 0000046C B90900 mov cx,9 ; Up to 9 attempts
|
|
1487
|
|
1488 0000046F C60500 .tryagain: mov byte [di],0
|
|
1489 00000472 83F901 cmp cx,byte 1
|
|
1490 00000475 750A jne .not_default
|
|
1491 00000477 60 pusha
|
|
1492 00000478 BE[E606] mov si,default_str
|
|
1493 0000047B B90800 mov cx,default_len
|
|
1494 0000047E F3A4 rep movsb ; Copy "default" string
|
|
1495 00000480 61 popa
|
|
1496 00000481 60 .not_default: pusha
|
|
1497 00000482 BE[B306] mov si,trying_msg
|
|
1498 00000485 E8CC19 call writestr
|
|
1499 00000488 BF[0445] mov di,ConfigName
|
|
1500 0000048B 89FE mov si,di
|
|
1501 0000048D E8C419 call writestr
|
|
1502 00000490 E8B419 call crlf
|
|
1503 00000493 BF[0045] mov di,ConfigServer
|
|
1504 00000496 E8A715 call open
|
|
1505 00000499 61 popa
|
|
1506 0000049A 7505 jnz .success
|
|
1507 0000049C 4F dec di
|
|
1508 0000049D E2D0 loop .tryagain
|
|
1509
|
|
1510 0000049F EB03 jmp no_config_file
|
|
1511
|
|
1512 .success:
|
|
1513
|
|
1514 ;
|
|
1515 ; Now we have the config file open. Parse the config file and
|
|
1516 ; run the user interface.
|
|
1517 ;
|
|
1518 %include "ui.inc"
|
|
1519 <1> ;; $Id: ui.inc,v 1.20 2005/04/08 16:33:32 hpa Exp $
|
|
1520 <1> ;; -----------------------------------------------------------------------
|
|
1521 <1> ;;
|
|
1522 <1> ;; Copyright 1994-2002 H. Peter Anvin - All Rights Reserved
|
|
1523 <1> ;;
|
|
1524 <1> ;; This program is free software; you can redistribute it and/or modify
|
|
1525 <1> ;; it under the terms of the GNU General Public License as published by
|
|
1526 <1> ;; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
|
|
1527 <1> ;; Boston MA 02111-1307, USA; either version 2 of the License, or
|
|
1528 <1> ;; (at your option) any later version; incorporated herein by reference.
|
|
1529 <1> ;;
|
|
1530 <1> ;; -----------------------------------------------------------------------
|
|
1531 <1>
|
|
1532 <1> ;
|
|
1533 <1> ; This file should be entered with the config file open (for getc)
|
|
1534 <1> ;
|
|
1535 000004A1 E8E31B <1> call parse_config ; Parse configuration file
|
|
1536 <1> no_config_file:
|
|
1537 <1> ;
|
|
1538 <1> ; Check whether or not we are supposed to display the boot prompt.
|
|
1539 <1> ;
|
|
1540 <1> check_for_key:
|
|
1541 000004A4 833E[F000]00 <1> cmp word [ForcePrompt],byte 0 ; Force prompt?
|
|
1542 000004A9 7509 <1> jnz enter_command
|
|
1543 000004AB F606[8408]5B <1> test byte [KbdFlags],5Bh ; Caps, Scroll, Shift, Alt
|
|
1544 000004B0 0F842001 <1> jz auto_boot ; If neither, default boot
|
|
1545 <1>
|
|
1546 <1> enter_command:
|
|
1547 000004B4 BE[7501] <1> mov si,boot_prompt
|
|
1548 000004B7 E89A19 <1> call cwritestr
|
|
1549 <1>
|
|
1550 000004BA C606[8508]00 <1> mov byte [FuncFlag],0 ; <Ctrl-F> not pressed
|
|
1551 000004BF BF[D408] <1> mov di,command_line
|
|
1552 <1> ;
|
|
1553 <1> ; get the very first character -- we can either time
|
|
1554 <1> ; out, or receive a character press at this time. Some dorky BIOSes stuff
|
|
1555 <1> ; a return in the buffer on bootup, so wipe the keyboard buffer first.
|
|
1556 <1> ;
|
|
1557 000004C2 B411 <1> clear_buffer: mov ah,11h ; Check for pending char
|
|
1558 000004C4 CD16 <1> int 16h
|
|
1559 000004C6 7406 <1> jz get_char_time
|
|
1560 000004C8 B410 <1> mov ah,10h ; Get char
|
|
1561 000004CA CD16 <1> int 16h
|
|
1562 000004CC EBF4 <1> jmp short clear_buffer
|
|
1563 <1> get_char_time:
|
|
1564 000004CE E89C1F <1> call vgashowcursor
|
|
1565 <1> RESET_IDLE
|
|
1566 000004D1 E81315 <2> call reset_idle
|
|
1567 000004D4 8B0E[EC00] <1> mov cx,[KbdTimeOut]
|
|
1568 000004D8 21C9 <1> and cx,cx
|
|
1569 000004DA 7428 <1> jz get_char ; Timeout == 0 -> no timeout
|
|
1570 000004DC 41 <1> inc cx ; The first loop will happen
|
|
1571 <1> ; immediately as we don't
|
|
1572 <1> ; know the appropriate DX value
|
|
1573 000004DD 51 <1> time_loop: push cx
|
|
1574 000004DE 52 <1> tick_loop: push dx
|
|
1575 000004DF E8FA18 <1> call pollchar
|
|
1576 000004E2 751E <1> jnz get_char_pop
|
|
1577 000004E4 8B166C04 <1> mov dx,[BIOS_timer] ; Get time "of day"
|
|
1578 000004E8 58 <1> pop ax
|
|
1579 000004E9 39C2 <1> cmp dx,ax ; Has the timer advanced?
|
|
1580 000004EB 74F1 <1> je tick_loop
|
|
1581 000004ED 59 <1> pop cx
|
|
1582 <1> DO_IDLE
|
|
1583 000004EE E80115 <2> call check_for_arp
|
|
1584 000004F1 E2EA <1> loop time_loop ; If so, decrement counter
|
|
1585 <1>
|
|
1586 <1> ; Timeout!!!!
|
|
1587 000004F3 E87D1F <1> call vgahidecursor
|
|
1588 000004F6 BE[DC11] <1> mov si,Ontimeout ; Copy ontimeout command
|
|
1589 000004F9 8B0E[E800] <1> mov cx,[OntimeoutLen] ; if we have one...
|
|
1590 000004FD F3A4 <1> rep movsb
|
|
1591 <1> .stddefault:
|
|
1592 000004FF E9E000 <1> jmp command_done
|
|
1593 <1>
|
|
1594 00000502 6658 <1> get_char_pop: pop eax ; Clear stack
|
|
1595 <1> get_char:
|
|
1596 00000504 E8661F <1> call vgashowcursor
|
|
1597 00000507 E8FC18 <1> call getchar
|
|
1598 0000050A E8661F <1> call vgahidecursor
|
|
1599 0000050D 20C0 <1> and al,al
|
|
1600 0000050F 747B <1> jz func_key
|
|
1601 <1>
|
|
1602 00000511 3C7F <1> got_ascii: cmp al,7Fh ; <DEL> == <BS>
|
|
1603 00000513 744D <1> je backspace
|
|
1604 00000515 3C20 <1> cmp al,' ' ; ASCII?
|
|
1605 00000517 722A <1> jb not_ascii
|
|
1606 00000519 7706 <1> ja enter_char
|
|
1607 0000051B 81FF[D408] <1> cmp di,command_line ; Space must not be first
|
|
1608 0000051F 74E3 <1> je short get_char
|
|
1609 00000521 F606[8508]01 <1> enter_char: test byte [FuncFlag],1
|
|
1610 00000526 740F <1> jz .not_ctrl_f
|
|
1611 00000528 C606[8508]00 <1> mov byte [FuncFlag],0
|
|
1612 0000052D 3C30 <1> cmp al,'0'
|
|
1613 0000052F 7206 <1> jb .not_ctrl_f
|
|
1614 00000531 7451 <1> je ctrl_f_0
|
|
1615 00000533 3C39 <1> cmp al,'9'
|
|
1616 00000535 764F <1> jbe ctrl_f
|
|
1617 00000537 81FF[D30A] <1> .not_ctrl_f: cmp di,max_cmd_len+command_line ; Check there's space
|
|
1618 0000053B 73C7 <1> jnb short get_char
|
|
1619 0000053D AA <1> stosb ; Save it
|
|
1620 0000053E E84420 <1> call writechr ; Echo to screen
|
|
1621 00000541 EBC1 <1> jmp short get_char
|
|
1622 00000543 C606[8508]00 <1> not_ascii: mov byte [FuncFlag],0
|
|
1623 00000548 3C0D <1> cmp al,0Dh ; Enter
|
|
1624 0000054A 0F849400 <1> je command_done
|
|
1625 0000054E 3C06 <1> cmp al,'F' & 1Fh ; <Ctrl-F>
|
|
1626 00000550 742B <1> je set_func_flag
|
|
1627 00000552 3C15 <1> cmp al,'U' & 1Fh ; <Ctrl-U>
|
|
1628 00000554 741B <1> je kill_command ; Kill input line
|
|
1629 00000556 3C16 <1> cmp al,'V' & 1Fh ; <Ctrl-V>
|
|
1630 00000558 7459 <1> je print_version
|
|
1631 0000055A 3C18 <1> cmp al,'X' & 1Fh ; <Ctrl-X>
|
|
1632 0000055C 7419 <1> je force_text_mode
|
|
1633 0000055E 3C08 <1> cmp al,08h ; Backspace
|
|
1634 00000560 75A2 <1> jne get_char
|
|
1635 00000562 81FF[D408] <1> backspace: cmp di,command_line ; Make sure there is anything
|
|
1636 00000566 749C <1> je get_char ; to erase
|
|
1637 00000568 4F <1> dec di ; Unstore one character
|
|
1638 00000569 BE[7C01] <1> mov si,wipe_char ; and erase it from the screen
|
|
1639 0000056C E8E518 <1> call cwritestr
|
|
1640 0000056F EB11 <1> jmp short get_char_2
|
|
1641 <1>
|
|
1642 <1> kill_command:
|
|
1643 00000571 E8D318 <1> call crlf
|
|
1644 00000574 E93DFF <1> jmp enter_command
|
|
1645 <1>
|
|
1646 <1> force_text_mode:
|
|
1647 00000577 E8CB1E <1> call vgaclearmode
|
|
1648 0000057A E937FF <1> jmp enter_command
|
|
1649 <1>
|
|
1650 <1> set_func_flag:
|
|
1651 0000057D C606[8508]01 <1> mov byte [FuncFlag],1
|
|
1652 <1> get_char_2:
|
|
1653 00000582 EB80 <1> jmp short get_char
|
|
1654 <1>
|
|
1655 00000584 040A <1> ctrl_f_0: add al,10 ; <Ctrl-F>0 == F10
|
|
1656 00000586 2C31 <1> ctrl_f: sub al,'1'
|
|
1657 00000588 30E4 <1> xor ah,ah
|
|
1658 0000058A EB0A <1> jmp short show_help
|
|
1659 <1>
|
|
1660 <1> func_key:
|
|
1661 <1> ; AL = 0 if we get here
|
|
1662 0000058C 86C4 <1> xchg al,ah
|
|
1663 0000058E 3C44 <1> cmp al,68 ; F10
|
|
1664 00000590 77F0 <1> ja short get_char_2
|
|
1665 00000592 2C3B <1> sub al,59 ; F1
|
|
1666 00000594 72EC <1> jb short get_char_2
|
|
1667 <1> show_help: ; AX = func key # (0 = F1, 9 = F10)
|
|
1668 00000596 57 <1> push di ; Save end-of-cmdline pointer
|
|
1669 00000597 C1E007 <1> shl ax,FILENAME_MAX_LG2 ; Convert to pointer
|
|
1670 0000059A 05[DC16] <1> add ax,FKeyName
|
|
1671 0000059D 97 <1> xchg di,ax
|
|
1672 0000059E 807D0400 <1> cmp byte [di+NULLOFFSET],NULLFILE
|
|
1673 000005A2 742D <1> je short fk_nofile ; Undefined F-key
|
|
1674 000005A4 E8360D <1> call searchdir
|
|
1675 000005A7 7428 <1> jz short fk_nofile ; File not found
|
|
1676 000005A9 56 <1> push si
|
|
1677 000005AA E89A18 <1> call crlf
|
|
1678 000005AD 5E <1> pop si
|
|
1679 000005AE E83D16 <1> call get_msg_file
|
|
1680 000005B1 EB0D <1> jmp short fk_wrcmd
|
|
1681 <1>
|
|
1682 <1> print_version:
|
|
1683 000005B3 57 <1> push di ; Command line write pointer
|
|
1684 000005B4 BE[EE06] <1> mov si,syslinux_banner
|
|
1685 000005B7 E89A18 <1> call cwritestr
|
|
1686 000005BA BE[4B01] <1> mov si,copyright_str
|
|
1687 000005BD E89418 <1> call cwritestr
|
|
1688 <1>
|
|
1689 <1> ; ... fall through ...
|
|
1690 <1>
|
|
1691 <1> ; Write the boot prompt and command line again and
|
|
1692 <1> ; wait for input. Note that this expects the cursor
|
|
1693 <1> ; to already have been CRLF'd, and that the old value
|
|
1694 <1> ; of DI (the command line write pointer) is on the stack.
|
|
1695 <1> fk_wrcmd:
|
|
1696 000005C0 BE[7501] <1> mov si,boot_prompt
|
|
1697 000005C3 E88E18 <1> call cwritestr
|
|
1698 000005C6 5F <1> pop di ; Command line write pointer
|
|
1699 000005C7 57 <1> push di
|
|
1700 000005C8 C60500 <1> mov byte [di],0 ; Null-terminate command line
|
|
1701 000005CB BE[D408] <1> mov si,command_line
|
|
1702 000005CE E88318 <1> call cwritestr ; Write command line so far
|
|
1703 000005D1 5F <1> fk_nofile: pop di
|
|
1704 000005D2 EBAE <1> jmp short get_char_2
|
|
1705 <1> auto_boot:
|
|
1706 000005D4 BE[D80A] <1> mov si,default_cmd
|
|
1707 000005D7 BF[D408] <1> mov di,command_line
|
|
1708 000005DA B98000 <1> mov cx,(max_cmd_len+4) >> 2
|
|
1709 000005DD F366A5 <1> rep movsd
|
|
1710 000005E0 EB0C <1> jmp short load_kernel
|
|
1711 <1> command_done:
|
|
1712 000005E2 E86218 <1> call crlf
|
|
1713 000005E5 81FF[D408] <1> cmp di,command_line ; Did we just hit return?
|
|
1714 000005E9 74E9 <1> je auto_boot
|
|
1715 000005EB 30C0 <1> xor al,al ; Store a final null
|
|
1716 000005ED AA <1> stosb
|
|
1717 <1>
|
|
1718 <1> load_kernel: ; Load the kernel now
|
|
1719 <1> ;
|
|
1720 <1> ; First we need to mangle the kernel name the way DOS would...
|
|
1721 <1> ;
|
|
1722 000005EE BE[D408] <1> mov si,command_line
|
|
1723 000005F1 BF[E01B] <1> mov di,KernelName
|
|
1724 000005F4 56 <1> push si
|
|
1725 000005F5 57 <1> push di
|
|
1726 000005F6 E8420F <1> call mangle_name
|
|
1727 000005F9 5F <1> pop di
|
|
1728 000005FA 5E <1> pop si
|
|
1729 <1> ;
|
|
1730 <1> ; Fast-forward to first option (we start over from the beginning, since
|
|
1731 <1> ; mangle_name doesn't necessarily return a consistent ending state.)
|
|
1732 <1> ;
|
|
1733 000005FB AC <1> clin_non_wsp: lodsb
|
|
1734 000005FC 3C20 <1> cmp al,' '
|
|
1735 000005FE 77FB <1> ja clin_non_wsp
|
|
1736 00000600 20C0 <1> clin_is_wsp: and al,al
|
|
1737 00000602 7405 <1> jz clin_opt_ptr
|
|
1738 00000604 AC <1> lodsb
|
|
1739 00000605 3C20 <1> cmp al,' '
|
|
1740 00000607 76F7 <1> jbe clin_is_wsp
|
|
1741 00000609 4E <1> clin_opt_ptr: dec si ; Point to first nonblank
|
|
1742 0000060A 8936[8208] <1> mov [CmdOptPtr],si ; Save ptr to first option
|
|
1743 <1> ;
|
|
1744 <1> ; If "allowoptions 0", put a null character here in order to ignore any
|
|
1745 <1> ; user-specified options.
|
|
1746 <1> ;
|
|
1747 0000060E A1[F400] <1> mov ax,[AllowOptions]
|
|
1748 00000611 21C0 <1> and ax,ax
|
|
1749 00000613 7502 <1> jnz clin_opt_ok
|
|
1750 00000615 8804 <1> mov [si],al
|
|
1751 <1> clin_opt_ok:
|
|
1752 <1>
|
|
1753 <1> ;
|
|
1754 <1> ; Now check if it is a "virtual kernel"
|
|
1755 <1> ;
|
|
1756 <1> vk_check:
|
|
1757 00000617 31F6 <1> xor si,si ; Beginning of vk_seg
|
|
1758 <1> .scan:
|
|
1759 00000619 3B36[F800] <1> cmp si,[VKernelBytes]
|
|
1760 0000061D 7355 <1> jae .not_vk
|
|
1761 <1>
|
|
1762 0000061F 1E <1> push ds
|
|
1763 00000620 680030 <1> push word vk_seg
|
|
1764 00000623 1F <1> pop ds
|
|
1765 <1>
|
|
1766 00000624 BF[D80C] <1> mov di,VKernelBuf
|
|
1767 00000627 E80B1B <1> call rllunpack
|
|
1768 0000062A 1F <1> pop ds
|
|
1769 <1> ; SI updated on return
|
|
1770 <1>
|
|
1771 0000062B 29CF <1> sub di,cx ; Return to beginning of buf
|
|
1772 0000062D 56 <1> push si
|
|
1773 0000062E BE[E01B] <1> mov si,KernelName
|
|
1774 00000631 B98000 <1> mov cx,FILENAME_MAX
|
|
1775 00000634 26F3A6 <1> es repe cmpsb
|
|
1776 00000637 5E <1> pop si
|
|
1777 00000638 7402 <1> je .found
|
|
1778 0000063A EBDD <1> jmp .scan
|
|
1779 <1>
|
|
1780 <1> ;
|
|
1781 <1> ; We *are* using a "virtual kernel"
|
|
1782 <1> ;
|
|
1783 <1> .found:
|
|
1784 0000063C 06 <1> push es
|
|
1785 0000063D 680040 <1> push word real_mode_seg
|
|
1786 00000640 07 <1> pop es
|
|
1787 00000641 BF0090 <1> mov di,cmd_line_here
|
|
1788 00000644 BE[DC0D] <1> mov si,VKernelBuf+vk_append
|
|
1789 00000647 8B0E[DA0D] <1> mov cx,[VKernelBuf+vk_appendlen]
|
|
1790 0000064B F3A4 <1> rep movsb
|
|
1791 0000064D 893E[EE00] <1> mov [CmdLinePtr],di ; Where to add rest of cmd
|
|
1792 00000651 07 <1> pop es
|
|
1793 00000652 BF[E01B] <1> mov di,KernelName
|
|
1794 00000655 57 <1> push di
|
|
1795 00000656 BE[580D] <1> mov si,VKernelBuf+vk_rname
|
|
1796 00000659 B98000 <1> mov cx,FILENAME_MAX ; We need ECX == CX later
|
|
1797 0000065C F3A4 <1> rep movsb
|
|
1798 0000065E 5F <1> pop di
|
|
1799 <1> %if IS_PXELINUX
|
|
1800 0000065F A0[D80D] <1> mov al,[VKernelBuf+vk_ipappend]
|
|
1801 00000662 A2[0809] <1> mov [IPAppend],al
|
|
1802 <1> %endif
|
|
1803 00000665 31DB <1> xor bx,bx ; Try only one version
|
|
1804 <1>
|
|
1805 <1> %if IS_PXELINUX || IS_ISOLINUX
|
|
1806 <1> ; Is this a "localboot" pseudo-kernel?
|
|
1807 <1> %if IS_PXELINUX
|
|
1808 00000667 803E[5C0D]00 <1> cmp byte [VKernelBuf+vk_rname+4], 0
|
|
1809 <1> %else
|
|
1810 <1> cmp byte [VKernelBuf+vk_rname], 0
|
|
1811 <1> %endif
|
|
1812 0000066C 7528 <1> jne get_kernel ; No, it's real, go get it
|
|
1813 <1>
|
|
1814 0000066E A1[590D] <1> mov ax, [VKernelBuf+vk_rname+1]
|
|
1815 00000671 E9EE0A <1> jmp local_boot
|
|
1816 <1> %else
|
|
1817 <1> jmp get_kernel
|
|
1818 <1> %endif
|
|
1819 <1>
|
|
1820 <1> .not_vk:
|
|
1821 <1>
|
|
1822 <1> ;
|
|
1823 <1> ; Not a "virtual kernel" - check that's OK and construct the command line
|
|
1824 <1> ;
|
|
1825 00000674 833E[F200]00 <1> cmp word [AllowImplicit],byte 0
|
|
1826 00000679 7455 <1> je bad_implicit
|
|
1827 0000067B 06 <1> push es
|
|
1828 0000067C 56 <1> push si
|
|
1829 0000067D 57 <1> push di
|
|
1830 0000067E BF0040 <1> mov di,real_mode_seg
|
|
1831 00000681 8EC7 <1> mov es,di
|
|
1832 00000683 BE[DC0F] <1> mov si,AppendBuf
|
|
1833 00000686 BF0090 <1> mov di,cmd_line_here
|
|
1834 00000689 8B0E[E600] <1> mov cx,[AppendLen]
|
|
1835 0000068D F3A4 <1> rep movsb
|
|
1836 0000068F 893E[EE00] <1> mov [CmdLinePtr],di
|
|
1837 00000693 5F <1> pop di
|
|
1838 00000694 5E <1> pop si
|
|
1839 00000695 07 <1> pop es
|
|
1840 <1> ;
|
|
1841 <1> ; Find the kernel on disk
|
|
1842 <1> ;
|
|
1843 00000696 C606[601C]00 <1> get_kernel: mov byte [KernelName+FILENAME_MAX],0 ; Zero-terminate filename/extension
|
|
1844 <1> %if IS_SYSLINUX || IS_MDSLINUX ; SYSLINUX has to deal with DOS mangled names...
|
|
1845 <1> mov eax,[KernelName+8] ; Save initial extension
|
|
1846 <1> mov [exten_table_end],eax ; Last case == initial ext.
|
|
1847 <1> %else
|
|
1848 0000069B BF[E41B] <1> mov di,KernelName+4*IS_PXELINUX
|
|
1849 0000069E 30C0 <1> xor al,al
|
|
1850 000006A0 B97B00 <1> mov cx,FILENAME_MAX-5 ; Need 4 chars + null
|
|
1851 000006A3 F2AE <1> repne scasb ; Scan for final null
|
|
1852 000006A5 7501 <1> jne .no_skip
|
|
1853 000006A7 4F <1> dec di ; Point to final null
|
|
1854 000006A8 893E[8008] <1> .no_skip: mov [KernelExtPtr],di
|
|
1855 <1> %endif
|
|
1856 000006AC BB[2808] <1> mov bx,exten_table
|
|
1857 000006AF 53 <1> .search_loop: push bx
|
|
1858 000006B0 BF[E01B] <1> mov di,KernelName ; Search on disk
|
|
1859 000006B3 E8270C <1> call searchdir
|
|
1860 000006B6 5B <1> pop bx
|
|
1861 000006B7 756B <1> jnz kernel_good
|
|
1862 000006B9 668B07 <1> mov eax,[bx] ; Try a different extension
|
|
1863 <1> %if IS_SYSLINUX || IS_MDSLINUX
|
|
1864 <1> mov [KernelName+8],eax
|
|
1865 <1> %else
|
|
1866 000006BC 8B36[8008] <1> mov si,[KernelExtPtr]
|
|
1867 000006C0 668904 <1> mov [si],eax
|
|
1868 000006C3 C6440400 <1> mov byte [si+4],0
|
|
1869 <1> %endif
|
|
1870 000006C7 83C304 <1> add bx,byte 4
|
|
1871 000006CA 81FB[3808] <1> cmp bx,exten_table_end
|
|
1872 000006CE 76DF <1> jna .search_loop ; allow == case (final case)
|
|
1873 <1> ; Fall into bad_kernel
|
|
1874 <1> ;
|
|
1875 <1> ; bad_kernel: Kernel image not found
|
|
1876 <1> ; bad_implicit: The user entered a nonvirtual kernel name, with "implicit 0"
|
|
1877 <1> ;
|
|
1878 <1> bad_implicit:
|
|
1879 <1> bad_kernel:
|
|
1880 000006D0 8B0E[EA00] <1> mov cx,[OnerrorLen]
|
|
1881 000006D4 21C9 <1> and cx,cx
|
|
1882 000006D6 751A <1> jnz on_error
|
|
1883 <1> .really:
|
|
1884 000006D8 BE[E01B] <1> mov si,KernelName
|
|
1885 000006DB BF[601C] <1> mov di,KernelCName
|
|
1886 000006DE 57 <1> push di
|
|
1887 000006DF E8AE0E <1> call unmangle_name ; Get human form
|
|
1888 000006E2 BE[8001] <1> mov si,err_notfound ; Complain about missing kernel
|
|
1889 000006E5 E86C17 <1> call cwritestr
|
|
1890 000006E8 5E <1> pop si ; KernelCName
|
|
1891 000006E9 E86817 <1> call cwritestr
|
|
1892 000006EC BE[E006] <1> mov si,crlf_msg
|
|
1893 000006EF E9AE0A <1> jmp abort_load ; Ask user for clue
|
|
1894 <1>
|
|
1895 <1> ;
|
|
1896 <1> ; on_error: bad kernel, but we have onerror set
|
|
1897 <1> ;
|
|
1898 <1> on_error:
|
|
1899 000006F2 BE[DC13] <1> mov si,Onerror
|
|
1900 000006F5 BF[D408] <1> mov di,command_line
|
|
1901 000006F8 56 <1> push si ; <A>
|
|
1902 000006F9 57 <1> push di ; <B>
|
|
1903 000006FA 51 <1> push cx ; <C>
|
|
1904 000006FB 51 <1> push cx ; <D>
|
|
1905 000006FC 57 <1> push di ; <E>
|
|
1906 000006FD F3A6 <1> repe cmpsb
|
|
1907 000006FF 5F <1> pop di ; <E> di == command_line
|
|
1908 00000700 5B <1> pop bx ; <D> bx == [OnerrorLen]
|
|
1909 00000701 74D5 <1> je bad_kernel.really ; Onerror matches command_line already
|
|
1910 00000703 F7DB <1> neg bx ; bx == -[OnerrorLen]
|
|
1911 00000705 8D8FFF01 <1> lea cx,[max_cmd_len+bx]
|
|
1912 <1> ; CX == max_cmd_len-[OnerrorLen]
|
|
1913 00000709 BF[D20A] <1> mov di,command_line+max_cmd_len-1
|
|
1914 0000070C C6450100 <1> mov byte [di+1],0 ; Enforce null-termination
|
|
1915 00000710 8D31 <1> lea si,[di+bx]
|
|
1916 00000712 FD <1> std
|
|
1917 00000713 F3A4 <1> rep movsb ; Make space in command_line
|
|
1918 00000715 FC <1> cld
|
|
1919 00000716 59 <1> pop cx ; <C> cx == [OnerrorLen]
|
|
1920 00000717 5F <1> pop di ; <B> di == command_line
|
|
1921 00000718 5E <1> pop si ; <A> si == Onerror
|
|
1922 00000719 F3A4 <1> rep movsb
|
|
1923 0000071B E9D0FE <1> jmp load_kernel
|
|
1924 <1>
|
|
1925 <1> ;
|
|
1926 <1> ; kernel_corrupt: Called if the kernel file does not seem healthy
|
|
1927 <1> ;
|
|
1928 0000071E BE[9E01] <1> kernel_corrupt: mov si,err_notkernel
|
|
1929 00000721 E97C0A <1> jmp abort_load
|
|
1930 <1> ;
|
|
1931 <1> ; This is it! We have a name (and location on the disk)... let's load
|
|
1932 <1> ; that sucker!! First we have to decide what kind of file this is; base
|
|
1933 <1> ; that decision on the file extension. The following extensions are
|
|
1934 <1> ; recognized; case insensitive:
|
|
1935 <1> ;
|
|
1936 <1> ; .com - COMBOOT image
|
|
1937 <1> ; .cbt - COMBOOT image
|
|
1938 <1> ; .c32 - COM32 image
|
|
1939 <1> ; .bs - Boot sector
|
|
1940 <1> ; .0 - PXE bootstrap program (PXELINUX only)
|
|
1941 <1> ; .bin - Boot sector
|
|
1942 <1> ; .bss - Boot sector, but transfer over DOS superblock (SYSLINUX only)
|
|
1943 <1> ; .img - Floppy image (ISOLINUX only)
|
|
1944 <1> ;
|
|
1945 <1> ; Anything else is assumed to be a Linux kernel.
|
|
1946 <1> ;
|
|
1947 <1> kernel_good:
|
|
1948 00000724 60 <1> pusha
|
|
1949 00000725 BE[E01B] <1> mov si,KernelName
|
|
1950 00000728 BF[601C] <1> mov di,KernelCName
|
|
1951 0000072B E8620E <1> call unmangle_name
|
|
1952 0000072E 81EF[601C] <1> sub di,KernelCName
|
|
1953 00000732 893E[DC1B] <1> mov [KernelCNameLen],di
|
|
1954 00000736 61 <1> popa
|
|
1955 <1>
|
|
1956 <1> %if IS_SYSLINUX || IS_MDSLINUX
|
|
1957 <1> mov ecx,[KernelName+7]
|
|
1958 <1> mov cl,'.'
|
|
1959 <1> %else
|
|
1960 00000737 57 <1> push di
|
|
1961 00000738 50 <1> push ax
|
|
1962 00000739 BF[E41B] <1> mov di,KernelName+4*IS_PXELINUX
|
|
1963 0000073C 30C0 <1> xor al,al
|
|
1964 0000073E B98000 <1> mov cx,FILENAME_MAX
|
|
1965 00000741 F2AE <1> repne scasb
|
|
1966 00000743 7501 <1> jne .one_step
|
|
1967 00000745 4F <1> dec di
|
|
1968 00000746 668B4DFC <1> .one_step: mov ecx,[di-4] ; 4 bytes before end
|
|
1969 0000074A 58 <1> pop ax
|
|
1970 0000074B 5F <1> pop di
|
|
1971 <1> %endif
|
|
1972 <1>
|
|
1973 <1> ;
|
|
1974 <1> ; At this point, DX:AX contains the size of the kernel, and SI contains
|
|
1975 <1> ; the file handle/cluster pointer.
|
|
1976 <1> ;
|
|
1977 0000074C 6681C900202020 <1> or ecx,20202000h ; Force lower case
|
|
1978 <1>
|
|
1979 00000753 6681F92E636F6D <1> cmp ecx,'.com'
|
|
1980 0000075A 0F848104 <1> je is_comboot_image
|
|
1981 0000075E 6681F92E636274 <1> cmp ecx,'.cbt'
|
|
1982 00000765 0F847604 <1> je is_comboot_image
|
|
1983 00000769 6681F92E633332 <1> cmp ecx,'.c32'
|
|
1984 00000770 0F845507 <1> je is_com32_image
|
|
1985 <1> %if IS_ISOLINUX
|
|
1986 <1> cmp ecx,'.img'
|
|
1987 <1> je is_disk_image
|
|
1988 <1> %endif
|
|
1989 00000774 6681F92E627373 <1> cmp ecx,'.bss'
|
|
1990 0000077B 0F84DA09 <1> je is_bss_sector
|
|
1991 0000077F 6681F92E62696E <1> cmp ecx,'.bin'
|
|
1992 00000786 0F844909 <1> je is_bootsector
|
|
1993 <1> %if IS_SYSLINUX || IS_MDSLINUX
|
|
1994 <1> cmp ecx,'.bs '
|
|
1995 <1> je is_bootsector
|
|
1996 <1> cmp ecx,'.0 '
|
|
1997 <1> je is_bootsector
|
|
1998 <1> %else
|
|
1999 0000078A 66C1E908 <1> shr ecx,8
|
|
2000 0000078E 6681F92E627300 <1> cmp ecx,'.bs'
|
|
2001 00000795 0F843A09 <1> je is_bootsector
|
|
2002 00000799 66C1E908 <1> shr ecx,8
|
|
2003 0000079D 81F92E30 <1> cmp cx,'.0'
|
|
2004 000007A1 0F842E09 <1> je is_bootsector
|
|
2005 <1> %endif
|
|
2006 <1> ; Otherwise Linux kernel
|
|
2007 <1>
|
|
2008 <1> section .bss
|
|
2009 <1> alignb 2
|
|
2010 00000880 <res 00000002> <1> KernelExtPtr resw 1 ; During search, final null pointer
|
|
2011 00000882 <res 00000002> <1> CmdOptPtr resw 1 ; Pointer to first option on cmd line
|
|
2012 00000884 <res 00000001> <1> KbdFlags resb 1 ; Check for keyboard escapes
|
|
2013 00000885 <res 00000001> <1> FuncFlag resb 1 ; Escape sequences received from keyboard
|
|
2014 <1>
|
|
2015 <1> section .text
|
|
2016
|
|
2017 ;
|
|
2018 ; Linux kernel loading code is common. However, we need to define
|
|
2019 ; a couple of helper macros...
|
|
2020 ;
|
|
2021
|
|
2022 ; Handle "ipappend" option
|
|
2023 %define HAVE_SPECIAL_APPEND
|
|
2024 %macro SPECIAL_APPEND 0
|
|
2025 test byte [IPAppend],01h ; ip=
|
|
2026 jz .noipappend1
|
|
2027 mov si,IPOption
|
|
2028 mov cx,[IPOptionLen]
|
|
2029 rep movsb
|
|
2030 mov al,' '
|
|
2031 stosb
|
|
2032 .noipappend1:
|
|
2033 test byte [IPAppend],02h
|
|
2034 jz .noipappend2
|
|
2035 mov si,BOOTIFStr
|
|
2036 call strcpy
|
|
2037 mov byte [es:di-1],' ' ; Replace null with space
|
|
2038 .noipappend2:
|
|
2039 %endmacro
|
|
2040
|
|
2041 ; Unload PXE stack
|
|
2042 %define HAVE_UNLOAD_PREP
|
|
2043 %macro UNLOAD_PREP 0
|
|
2044 call unload_pxe
|
|
2045 %endmacro
|
|
2046
|
|
2047 %include "runkernel.inc"
|
|
2048 <1> ;; $Id: runkernel.inc,v 1.21 2005/06/16 05:52:44 hpa Exp $
|
|
2049 <1> ;; -----------------------------------------------------------------------
|
|
2050 <1> ;;
|
|
2051 <1> ;; Copyright 1994-2005 H. Peter Anvin - All Rights Reserved
|
|
2052 <1> ;;
|
|
2053 <1> ;; This program is free software; you can redistribute it and/or modify
|
|
2054 <1> ;; it under the terms of the GNU General Public License as published by
|
|
2055 <1> ;; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
|
|
2056 <1> ;; Boston MA 02111-1307, USA; either version 2 of the License, or
|
|
2057 <1> ;; (at your option) any later version; incorporated herein by reference.
|
|
2058 <1> ;;
|
|
2059 <1> ;; -----------------------------------------------------------------------
|
|
2060 <1>
|
|
2061 <1> ;;
|
|
2062 <1> ;; runkernel.inc
|
|
2063 <1> ;;
|
|
2064 <1> ;; Common code for running a Linux kernel
|
|
2065 <1> ;;
|
|
2066 <1>
|
|
2067 <1> ;
|
|
2068 <1> ; Hook macros, that may or may not be defined
|
|
2069 <1> ;
|
|
2070 <1> %ifndef HAVE_SPECIAL_APPEND
|
|
2071 <1> %macro SPECIAL_APPEND 0
|
|
2072 <1> %endmacro
|
|
2073 <1> %endif
|
|
2074 <1>
|
|
2075 <1> %ifndef HAVE_UNLOAD_PREP
|
|
2076 <1> %macro UNLOAD_PREP 0
|
|
2077 <1> %endmacro
|
|
2078 <1> %endif
|
|
2079 <1>
|
|
2080 <1> ;
|
|
2081 <1> ; A Linux kernel consists of three parts: boot sector, setup code, and
|
|
2082 <1> ; kernel code. The boot sector is never executed when using an external
|
|
2083 <1> ; booting utility, but it contains some status bytes that are necessary.
|
|
2084 <1> ;
|
|
2085 <1> ; First check that our kernel is at least 1K and less than 8M (if it is
|
|
2086 <1> ; more than 8M, we need to change the logic for loading it anyway...)
|
|
2087 <1> ;
|
|
2088 <1> ; We used to require the kernel to be 64K or larger, but it has gotten
|
|
2089 <1> ; popular to use the Linux kernel format for other things, which may
|
|
2090 <1> ; not be so large.
|
|
2091 <1> ;
|
|
2092 <1> is_linux_kernel:
|
|
2093 000007A5 81FA8000 <1> cmp dx,80h ; 8 megs
|
|
2094 000007A9 0F8771FF <1> ja kernel_corrupt
|
|
2095 000007AD 21D2 <1> and dx,dx
|
|
2096 000007AF 7507 <1> jnz kernel_sane
|
|
2097 000007B1 3D0004 <1> cmp ax,1024 ; Bootsect + 1 setup sect
|
|
2098 000007B4 0F8266FF <1> jb kernel_corrupt
|
|
2099 000007B8 50 <1> kernel_sane: push ax
|
|
2100 000007B9 52 <1> push dx
|
|
2101 000007BA 56 <1> push si
|
|
2102 000007BB BE[C606] <1> mov si,loading_msg
|
|
2103 000007BE E89316 <1> call cwritestr
|
|
2104 <1> ;
|
|
2105 <1> ; Now start transferring the kernel
|
|
2106 <1> ;
|
|
2107 000007C1 680040 <1> push word real_mode_seg
|
|
2108 000007C4 07 <1> pop es
|
|
2109 <1>
|
|
2110 000007C5 660FB7C0 <1> movzx eax,ax ; Fix this by using a 32-bit
|
|
2111 000007C9 66C1E210 <1> shl edx,16 ; register for the kernel size
|
|
2112 000007CD 6609D0 <1> or eax,edx
|
|
2113 000007D0 66A3[8C08] <1> mov [KernelSize],eax
|
|
2114 000007D4 6605FF010000 <1> add eax,SECTOR_SIZE-1
|
|
2115 000007DA 66C1E809 <1> shr eax,SECTOR_SHIFT
|
|
2116 000007DE 66A3[9008] <1> mov [KernelSects],eax ; Total sectors in kernel
|
|
2117 <1>
|
|
2118 <1> ;
|
|
2119 <1> ; Now, if we transfer these straight, we'll hit 64K boundaries. Hence we
|
|
2120 <1> ; have to see if we're loading more than 64K, and if so, load it step by
|
|
2121 <1> ; step.
|
|
2122 <1> ;
|
|
2123 <1>
|
|
2124 <1> ;
|
|
2125 <1> ; Start by loading the bootsector/setup code, to see if we need to
|
|
2126 <1> ; do something funky. It should fit in the first 32K (loading 64K won't
|
|
2127 <1> ; work since we might have funny stuff up near the end of memory).
|
|
2128 <1> ; If we have larger than 32K clusters, yes, we're hosed.
|
|
2129 <1> ;
|
|
2130 000007E2 E8A709 <1> call abort_check ; Check for abort key
|
|
2131 000007E5 66B940000000 <1> mov ecx,8000h >> SECTOR_SHIFT ; Half a moby (32K)
|
|
2132 000007EB 663B0E[9008] <1> cmp ecx,[KernelSects]
|
|
2133 000007F0 7605 <1> jna .normalkernel
|
|
2134 000007F2 668B0E[9008] <1> mov ecx,[KernelSects]
|
|
2135 <1> .normalkernel:
|
|
2136 000007F7 66290E[9008] <1> sub [KernelSects],ecx
|
|
2137 000007FC 31DB <1> xor bx,bx
|
|
2138 000007FE 5E <1> pop si ; Cluster pointer on stack
|
|
2139 000007FF E8BC0D <1> call getfssec
|
|
2140 00000802 26813EFE0155AA <1> cmp word [es:bs_bootsign],0AA55h
|
|
2141 00000809 0F8511FF <1> jne kernel_corrupt ; Boot sec signature missing
|
|
2142 <1>
|
|
2143 <1> ;
|
|
2144 <1> ; Save the cluster pointer for later...
|
|
2145 <1> ;
|
|
2146 0000080D 56 <1> push si
|
|
2147 <1> ;
|
|
2148 <1> ; Get the BIOS' idea of what the size of high memory is.
|
|
2149 <1> ;
|
|
2150 0000080E E87A1C <1> call highmemsize
|
|
2151 <1> ;
|
|
2152 <1> ; Construct the command line (append options have already been copied)
|
|
2153 <1> ;
|
|
2154 <1> construct_cmdline:
|
|
2155 00000811 8B3E[EE00] <1> mov di,[CmdLinePtr]
|
|
2156 00000815 BE[0B00] <1> mov si,boot_image ; BOOT_IMAGE=
|
|
2157 00000818 B90B00 <1> mov cx,boot_image_len
|
|
2158 0000081B F3A4 <1> rep movsb
|
|
2159 0000081D BE[601C] <1> mov si,KernelCName ; Unmangled kernel name
|
|
2160 00000820 8B0E[DC1B] <1> mov cx,[KernelCNameLen]
|
|
2161 00000824 F3A4 <1> rep movsb
|
|
2162 00000826 B020 <1> mov al,' ' ; Space
|
|
2163 00000828 AA <1> stosb
|
|
2164 <1>
|
|
2165 <1> SPECIAL_APPEND ; Module-specific hook
|
|
2166 00000829 F606[0809]01 <2> test byte [IPAppend],01h
|
|
2167 0000082E 740C <2> jz .noipappend1
|
|
2168 00000830 BE[1047] <2> mov si,IPOption
|
|
2169 00000833 8B0E[0A00] <2> mov cx,[IPOptionLen]
|
|
2170 00000837 F3A4 <2> rep movsb
|
|
2171 00000839 B020 <2> mov al,' '
|
|
2172 0000083B AA <2> stosb
|
|
2173 <2> .noipappend1:
|
|
2174 0000083C F606[0809]02 <2> test byte [IPAppend],02h
|
|
2175 00000841 740B <2> jz .noipappend2
|
|
2176 00000843 BE[2700] <2> mov si,BOOTIFStr
|
|
2177 00000846 E8331D <2> call strcpy
|
|
2178 00000849 26C645FF20 <2> mov byte [es:di-1],' '
|
|
2179 <2> .noipappend2:
|
|
2180 <1>
|
|
2181 0000084E 8B36[8208] <1> mov si,[CmdOptPtr] ; Options from user input
|
|
2182 00000852 E8271D <1> call strcpy
|
|
2183 <1>
|
|
2184 <1> ;
|
|
2185 <1> ; Scan through the command line for anything that looks like we might be
|
|
2186 <1> ; interested in. The original version of this code automatically assumed
|
|
2187 <1> ; the first option was BOOT_IMAGE=, but that is no longer certain.
|
|
2188 <1> ;
|
|
2189 00000855 BE0090 <1> mov si,cmd_line_here
|
|
2190 00000858 31C0 <1> xor ax,ax
|
|
2191 0000085A A3[9C08] <1> mov [InitRDPtr],ax ; No initrd= option (yet)
|
|
2192 0000085D 06 <1> push es ; Set DS <- real_mode_seg
|
|
2193 0000085E 1F <1> pop ds
|
|
2194 0000085F AC <1> get_next_opt: lodsb
|
|
2195 00000860 20C0 <1> and al,al
|
|
2196 00000862 0F84A300 <1> jz cmdline_end
|
|
2197 00000866 3C20 <1> cmp al,' '
|
|
2198 00000868 76F5 <1> jbe get_next_opt
|
|
2199 0000086A 4E <1> dec si
|
|
2200 0000086B 668B04 <1> mov eax,[si]
|
|
2201 0000086E 663D7667613D <1> cmp eax,'vga='
|
|
2202 00000874 744D <1> je is_vga_cmd
|
|
2203 00000876 663D6D656D3D <1> cmp eax,'mem='
|
|
2204 0000087C 7474 <1> je is_mem_cmd
|
|
2205 <1> %if IS_PXELINUX
|
|
2206 0000087E 663D6B656570 <1> cmp eax,'keep' ; Is it "keeppxe"?
|
|
2207 00000884 7516 <1> jne .notkeep
|
|
2208 00000886 66817C0370707865 <1> cmp dword [si+3],'ppxe'
|
|
2209 0000088E 750C <1> jne .notkeep
|
|
2210 00000890 807C0720 <1> cmp byte [si+7],' ' ; Must be whitespace or EOS
|
|
2211 00000894 7706 <1> ja .notkeep
|
|
2212 00000896 2E800E[A608]01 <1> or byte [cs:KeepPXE],1
|
|
2213 <1> .notkeep:
|
|
2214 <1> %endif
|
|
2215 0000089C 06 <1> push es ; Save ES -> real_mode_seg
|
|
2216 0000089D 0E <1> push cs
|
|
2217 0000089E 07 <1> pop es ; Set ES <- normal DS
|
|
2218 0000089F BF[1707] <1> mov di,initrd_cmd
|
|
2219 000008A2 B90700 <1> mov cx,initrd_cmd_len
|
|
2220 000008A5 F3A6 <1> repe cmpsb
|
|
2221 000008A7 7511 <1> jne .not_initrd
|
|
2222 <1>
|
|
2223 000008A9 3C20 <1> cmp al,' '
|
|
2224 000008AB 7607 <1> jbe .noramdisk
|
|
2225 000008AD 2E8936[9C08] <1> mov [cs:InitRDPtr],si
|
|
2226 000008B2 EB06 <1> jmp .not_initrd
|
|
2227 <1> .noramdisk:
|
|
2228 000008B4 31C0 <1> xor ax,ax
|
|
2229 000008B6 2EA3[9C08] <1> mov [cs:InitRDPtr],ax
|
|
2230 000008BA 07 <1> .not_initrd: pop es ; Restore ES -> real_mode_seg
|
|
2231 000008BB AC <1> skip_this_opt: lodsb ; Load from command line
|
|
2232 000008BC 3C20 <1> cmp al,' '
|
|
2233 000008BE 77FB <1> ja skip_this_opt
|
|
2234 000008C0 4E <1> dec si
|
|
2235 000008C1 EB9C <1> jmp short get_next_opt
|
|
2236 <1> is_vga_cmd:
|
|
2237 000008C3 83C604 <1> add si,4
|
|
2238 000008C6 668B44FF <1> mov eax,[si-1]
|
|
2239 000008CA BBFFFF <1> mov bx,-1
|
|
2240 000008CD 663D3D6E6F72 <1> cmp eax,'=nor' ; vga=normal
|
|
2241 000008D3 7417 <1> je vc0
|
|
2242 000008D5 4B <1> dec bx ; bx <- -2
|
|
2243 000008D6 663D3D657874 <1> cmp eax,'=ext' ; vga=ext
|
|
2244 000008DC 740E <1> je vc0
|
|
2245 000008DE 4B <1> dec bx ; bx <- -3
|
|
2246 000008DF 663D3D61736B <1> cmp eax,'=ask' ; vga=ask
|
|
2247 000008E5 7405 <1> je vc0
|
|
2248 000008E7 E81212 <1> call parseint ; vga=<number>
|
|
2249 000008EA 72CF <1> jc skip_this_opt ; Not an integer
|
|
2250 000008EC 891EFA01 <1> vc0: mov [bs_vidmode],bx ; Set video mode
|
|
2251 000008F0 EBC9 <1> jmp short skip_this_opt
|
|
2252 <1> is_mem_cmd:
|
|
2253 000008F2 83C604 <1> add si,4
|
|
2254 000008F5 E80412 <1> call parseint
|
|
2255 000008F8 72C1 <1> jc skip_this_opt ; Not an integer
|
|
2256 <1> %if HIGHMEM_SLOP != 0
|
|
2257 000008FA 6681EB00000200 <1> sub ebx,HIGHMEM_SLOP
|
|
2258 <1> %endif
|
|
2259 00000901 2E66891E[981F] <1> mov [cs:HighMemSize],ebx
|
|
2260 00000907 EBB2 <1> jmp short skip_this_opt
|
|
2261 <1> cmdline_end:
|
|
2262 00000909 0E <1> push cs ; Restore standard DS
|
|
2263 0000090A 1F <1> pop ds
|
|
2264 0000090B 81EE0090 <1> sub si,cmd_line_here
|
|
2265 0000090F 8936[9808] <1> mov [CmdLineLen],si ; Length including final null
|
|
2266 <1> ;
|
|
2267 <1> ; Now check if we have a large kernel, which needs to be loaded high
|
|
2268 <1> ;
|
|
2269 00000913 66C706[8808]FFFFFF- <1> mov dword [RamdiskMax], HIGHMEM_MAX ; Default initrd limit
|
|
2270 0000091B 37 <1>
|
|
2271 0000091C 2666813E0202486472- <1> cmp dword [es:su_header],HEADER_ID ; New setup code ID
|
|
2272 00000925 53 <1>
|
|
2273 00000926 0F859701 <1> jne old_kernel ; Old kernel, load low
|
|
2274 0000092A 26813E06020002 <1> cmp word [es:su_version],0200h ; Setup code version 2.0
|
|
2275 00000931 0F828C01 <1> jb old_kernel ; Old kernel, load low
|
|
2276 00000935 26813E06020102 <1> cmp word [es:su_version],0201h ; Version 2.01+?
|
|
2277 0000093C 721F <1> jb new_kernel ; If 2.00, skip this step
|
|
2278 0000093E 26C7062402F48F <1> mov word [es:su_heapend],linux_stack ; Set up the heap
|
|
2279 00000945 26800E110280 <1> or byte [es:su_loadflags],80h ; Let the kernel know we care
|
|
2280 0000094B 26813E06020302 <1> cmp word [es:su_version],0203h ; Version 2.03+?
|
|
2281 00000952 7209 <1> jb new_kernel ; Not 2.03+
|
|
2282 00000954 2666A12C02 <1> mov eax,[es:su_ramdisk_max]
|
|
2283 00000959 66A3[8808] <1> mov [RamdiskMax],eax ; Set the ramdisk limit
|
|
2284 <1>
|
|
2285 <1> ;
|
|
2286 <1> ; We definitely have a new-style kernel. Let the kernel know who we are,
|
|
2287 <1> ; and that we are clueful
|
|
2288 <1> ;
|
|
2289 <1> new_kernel:
|
|
2290 0000095D 26C606100232 <1> mov byte [es:su_loader],my_id ; Show some ID
|
|
2291 00000963 260FB606F101 <1> movzx ax,byte [es:bs_setupsecs] ; Variable # of setup sectors
|
|
2292 00000969 A3[9A08] <1> mov [SetupSecs],ax
|
|
2293 0000096C 6631C0 <1> xor eax,eax
|
|
2294 0000096F 2666A31C02 <1> mov [es:su_ramdisklen],eax ; No initrd loaded yet
|
|
2295 <1>
|
|
2296 <1> ;
|
|
2297 <1> ; About to load the kernel. This is a modern kernel, so use the boot flags
|
|
2298 <1> ; we were provided.
|
|
2299 <1> ;
|
|
2300 00000974 26A01102 <1> mov al,[es:su_loadflags]
|
|
2301 00000978 A2[9E08] <1> mov [LoadFlags],al
|
|
2302 <1> ;
|
|
2303 <1> ; Load the kernel. We always load it at 100000h even if we're supposed to
|
|
2304 <1> ; load it "low"; for a "low" load we copy it down to low memory right before
|
|
2305 <1> ; jumping to it.
|
|
2306 <1> ;
|
|
2307 <1> read_kernel:
|
|
2308 0000097B BE[601C] <1> mov si,KernelCName ; Print kernel name part of
|
|
2309 0000097E E8D314 <1> call cwritestr ; "Loading" message
|
|
2310 00000981 BE[CF06] <1> mov si,dotdot_msg ; Print dots
|
|
2311 00000984 E8CD14 <1> call cwritestr
|
|
2312 <1>
|
|
2313 00000987 66A1[981F] <1> mov eax,[HighMemSize]
|
|
2314 0000098B 662D00001000 <1> sub eax,100000h ; Load address
|
|
2315 00000991 663B06[8C08] <1> cmp eax,[KernelSize]
|
|
2316 00000996 0F823502 <1> jb no_high_mem ; Not enough high memory
|
|
2317 <1> ;
|
|
2318 <1> ; Move the stuff beyond the setup code to high memory at 100000h
|
|
2319 <1> ;
|
|
2320 0000099A 660FB736[9A08] <1> movzx esi,word [SetupSecs] ; Setup sectors
|
|
2321 000009A0 46 <1> inc si ; plus 1 boot sector
|
|
2322 000009A1 C1E609 <1> shl si,9 ; Convert to bytes
|
|
2323 000009A4 66B900800000 <1> mov ecx,8000h ; 32K
|
|
2324 000009AA 6629F1 <1> sub ecx,esi ; Number of bytes to copy
|
|
2325 000009AD 6651 <1> push ecx
|
|
2326 000009AF 6681C600000400 <1> add esi,(real_mode_seg << 4) ; Pointer to source
|
|
2327 000009B6 66BF00001000 <1> mov edi,100000h ; Copy to address 100000h
|
|
2328 <1>
|
|
2329 000009BC E8(3000) <1> call bcopy ; Transfer to high memory
|
|
2330 <1>
|
|
2331 <1> ; On exit EDI -> where to load the rest
|
|
2332 <1>
|
|
2333 000009BF BE[D006] <1> mov si,dot_msg ; Progress report
|
|
2334 000009C2 E88F14 <1> call cwritestr
|
|
2335 000009C5 E8C407 <1> call abort_check
|
|
2336 <1>
|
|
2337 000009C8 6659 <1> pop ecx ; Number of bytes in the initial portion
|
|
2338 000009CA 5E <1> pop si ; Restore file handle/cluster pointer
|
|
2339 000009CB 66A1[8C08] <1> mov eax,[KernelSize]
|
|
2340 000009CF 662D00800000 <1> sub eax,8000h ; Amount of kernel not yet loaded
|
|
2341 000009D5 7605 <1> jbe high_load_done ; Zero left (tiny kernel)
|
|
2342 <1>
|
|
2343 000009D7 31D2 <1> xor dx,dx ; No padding needed
|
|
2344 000009D9 E8DF17 <1> call load_high ; Copy the file
|
|
2345 <1>
|
|
2346 <1> high_load_done:
|
|
2347 000009DC 66893E[9408] <1> mov [KernelEnd],edi
|
|
2348 000009E1 B80040 <1> mov ax,real_mode_seg ; Set to real mode seg
|
|
2349 000009E4 8EC0 <1> mov es,ax
|
|
2350 <1>
|
|
2351 000009E6 BE[D006] <1> mov si,dot_msg
|
|
2352 000009E9 E86814 <1> call cwritestr
|
|
2353 <1>
|
|
2354 <1> ;
|
|
2355 <1> ; Now see if we have an initial RAMdisk; if so, do requisite computation
|
|
2356 <1> ; We know we have a new kernel; the old_kernel code already will have objected
|
|
2357 <1> ; if we tried to load initrd using an old kernel
|
|
2358 <1> ;
|
|
2359 <1> load_initrd:
|
|
2360 000009EC 833E[9C08]00 <1> cmp word [InitRDPtr],0
|
|
2361 000009F1 7403 <1> jz nk_noinitrd
|
|
2362 000009F3 E8E600 <1> call parse_load_initrd
|
|
2363 <1> nk_noinitrd:
|
|
2364 <1> ;
|
|
2365 <1> ; Abandon hope, ye that enter here! We do no longer permit aborts.
|
|
2366 <1> ;
|
|
2367 000009F6 E89307 <1> call abort_check ; Last chance!!
|
|
2368 <1>
|
|
2369 000009F9 BE[AA06] <1> mov si,ready_msg
|
|
2370 000009FC E85514 <1> call cwritestr
|
|
2371 <1>
|
|
2372 000009FF E8431A <1> call vgaclearmode ; We can't trust ourselves after this
|
|
2373 <1>
|
|
2374 <1> UNLOAD_PREP ; Module-specific hook
|
|
2375 00000A02 E8440D <2> call unload_pxe
|
|
2376 <1>
|
|
2377 <1> ;
|
|
2378 <1> ; Now, if we were supposed to load "low", copy the kernel down to 10000h
|
|
2379 <1> ; and the real mode stuff to 90000h. We assume that all bzImage kernels are
|
|
2380 <1> ; capable of starting their setup from a different address.
|
|
2381 <1> ;
|
|
2382 00000A05 B80040 <1> mov ax,real_mode_seg
|
|
2383 00000A08 8EE0 <1> mov fs,ax
|
|
2384 <1>
|
|
2385 <1> ;
|
|
2386 <1> ; Copy command line. Unfortunately, the kernel boot protocol requires
|
|
2387 <1> ; the command line to exist in the 9xxxxh range even if the rest of the
|
|
2388 <1> ; setup doesn't.
|
|
2389 <1> ;
|
|
2390 00000A0A FA <1> cli ; In case of hooked interrupts
|
|
2391 00000A0B F606[9E08]01 <1> test byte [LoadFlags],LOAD_HIGH
|
|
2392 00000A10 7415 <1> jz need_high_cmdline
|
|
2393 00000A12 64813E06020202 <1> cmp word [fs:su_version],0202h ; Support new cmdline protocol?
|
|
2394 00000A19 720C <1> jb need_high_cmdline
|
|
2395 <1> ; New cmdline protocol
|
|
2396 <1> ; Store 32-bit (flat) pointer to command line
|
|
2397 00000A1B 6466C7062802009004- <1> mov dword [fs:su_cmd_line_ptr],(real_mode_seg << 4) + cmd_line_here
|
|
2398 00000A24 00 <1>
|
|
2399 00000A25 EB70 <1> jmp short in_proper_place
|
|
2400 <1>
|
|
2401 <1> need_high_cmdline:
|
|
2402 <1> ;
|
|
2403 <1> ; Copy command line up to 90000h
|
|
2404 <1> ;
|
|
2405 00000A27 B80090 <1> mov ax,9000h ; Note AL <- 0
|
|
2406 00000A2A 8EC0 <1> mov es,ax
|
|
2407 00000A2C BE0090 <1> mov si,cmd_line_here
|
|
2408 00000A2F 89F7 <1> mov di,si
|
|
2409 00000A31 64C70620003FA3 <1> mov [fs:kern_cmd_magic],word CMD_MAGIC ; Store magic
|
|
2410 00000A38 64893E2200 <1> mov [fs:kern_cmd_offset],di ; Store pointer
|
|
2411 <1>
|
|
2412 00000A3D 8B0E[9808] <1> mov cx,[CmdLineLen]
|
|
2413 00000A41 81F9FF00 <1> cmp cx,255
|
|
2414 00000A45 7603 <1> jna .len_ok
|
|
2415 00000A47 B9FF00 <1> mov cx,255 ; Protocol < 0x202 has 255 as hard limit
|
|
2416 <1> .len_ok:
|
|
2417 00000A4A 64F3A4 <1> fs rep movsb
|
|
2418 00000A4D AA <1> stosb ; Final null, note AL == 0 already
|
|
2419 <1>
|
|
2420 00000A4E 0FA0 <1> push fs
|
|
2421 00000A50 07 <1> pop es
|
|
2422 <1>
|
|
2423 00000A51 F606[9E08]01 <1> test byte [LoadFlags],LOAD_HIGH
|
|
2424 00000A56 753F <1> jnz in_proper_place ; If high load, we're done
|
|
2425 <1>
|
|
2426 <1> ;
|
|
2427 <1> ; Loading low; we can't assume it's safe to run in place.
|
|
2428 <1> ;
|
|
2429 <1> ; Copy real_mode stuff up to 90000h
|
|
2430 <1> ;
|
|
2431 00000A58 B80090 <1> mov ax,9000h
|
|
2432 00000A5B 8EC0 <1> mov es,ax
|
|
2433 00000A5D 8B0E[9A08] <1> mov cx,[SetupSecs]
|
|
2434 00000A61 41 <1> inc cx ; Setup + boot sector
|
|
2435 00000A62 C1E107 <1> shl cx,7 ; Sectors -> dwords
|
|
2436 00000A65 31F6 <1> xor si,si
|
|
2437 00000A67 31FF <1> xor di,di
|
|
2438 00000A69 64F366A5 <1> fs rep movsd ; Copy setup + boot sector
|
|
2439 <1> ;
|
|
2440 <1> ; Some kernels in the 1.2 ballpark but pre-bzImage have more than 4
|
|
2441 <1> ; setup sectors, but the boot protocol had not yet been defined. They
|
|
2442 <1> ; rely on a signature to figure out if they need to copy stuff from
|
|
2443 <1> ; the "protected mode" kernel area. Unfortunately, we used that area
|
|
2444 <1> ; as a transfer buffer, so it's going to find the signature there.
|
|
2445 <1> ; Hence, zero the low 32K beyond the setup area.
|
|
2446 <1> ;
|
|
2447 00000A6D 8B3E[9A08] <1> mov di,[SetupSecs]
|
|
2448 00000A71 47 <1> inc di ; Setup + boot sector
|
|
2449 00000A72 B94000 <1> mov cx,32768/512 ; Sectors/32K
|
|
2450 00000A75 29F9 <1> sub cx,di ; Remaining sectors
|
|
2451 00000A77 C1E709 <1> shl di,9 ; Sectors -> bytes
|
|
2452 00000A7A C1E107 <1> shl cx,7 ; Sectors -> dwords
|
|
2453 00000A7D 6631C0 <1> xor eax,eax
|
|
2454 00000A80 F366AB <1> rep stosd ; Clear region
|
|
2455 <1> ;
|
|
2456 <1> ; Copy the kernel down to the "low" location
|
|
2457 <1> ;
|
|
2458 00000A83 668B0E[8C08] <1> mov ecx,[KernelSize]
|
|
2459 00000A88 66BE00001000 <1> mov esi,100000h
|
|
2460 00000A8E 66BF00000100 <1> mov edi,10000h
|
|
2461 00000A94 E8(3000) <1> call bcopy
|
|
2462 <1>
|
|
2463 <1> ;
|
|
2464 <1> ; Now everything is where it needs to be...
|
|
2465 <1> ;
|
|
2466 <1> ; When we get here, es points to the final segment, either
|
|
2467 <1> ; 9000h or real_mode_seg
|
|
2468 <1> ;
|
|
2469 <1> in_proper_place:
|
|
2470 <1>
|
|
2471 <1> ;
|
|
2472 <1> ; If the default root device is set to FLOPPY (0000h), change to
|
|
2473 <1> ; /dev/fd0 (0200h)
|
|
2474 <1> ;
|
|
2475 00000A97 26833EFC0100 <1> cmp word [es:bs_rootdev],byte 0
|
|
2476 00000A9D 7507 <1> jne root_not_floppy
|
|
2477 00000A9F 26C706FC010002 <1> mov word [es:bs_rootdev],0200h
|
|
2478 <1> root_not_floppy:
|
|
2479 <1>
|
|
2480 <1> ;
|
|
2481 <1> ; Copy the disk table to high memory, then re-initialize the floppy
|
|
2482 <1> ; controller
|
|
2483 <1> ;
|
|
2484 <1> %if IS_SYSLINUX || IS_MDSLINUX
|
|
2485 <1> lgs si,[cs:fdctab]
|
|
2486 <1> mov di,linux_fdctab
|
|
2487 <1> mov cx,6 ; 12 bytes
|
|
2488 <1> gs rep movsw
|
|
2489 <1> mov [cs:fdctab],word linux_fdctab ; Save new floppy tab pos
|
|
2490 <1> mov [cs:fdctab+2],es
|
|
2491 <1> %endif
|
|
2492 <1> ;
|
|
2493 <1> ; Linux wants the floppy motor shut off before starting the kernel,
|
|
2494 <1> ; at least bootsect.S seems to imply so.
|
|
2495 <1> ;
|
|
2496 <1> kill_motor:
|
|
2497 00000AA6 31C0 <1> xor ax,ax
|
|
2498 00000AA8 31D2 <1> xor dx,dx
|
|
2499 00000AAA CD13 <1> int 13h
|
|
2500 <1>
|
|
2501 <1> ;
|
|
2502 <1> ; If we're debugging, wait for a keypress so we can read any debug messages
|
|
2503 <1> ;
|
|
2504 <1> %ifdef debug
|
|
2505 <1> xor ax,ax
|
|
2506 <1> int 16h
|
|
2507 <1> %endif
|
|
2508 <1> ;
|
|
2509 <1> ; Set up segment registers and the Linux real-mode stack
|
|
2510 <1> ; Note: es == the real mode segment
|
|
2511 <1> ;
|
|
2512 00000AAC FA <1> cli
|
|
2513 00000AAD 8CC3 <1> mov bx,es
|
|
2514 00000AAF 8EDB <1> mov ds,bx
|
|
2515 00000AB1 8EE3 <1> mov fs,bx
|
|
2516 00000AB3 8EEB <1> mov gs,bx
|
|
2517 00000AB5 8ED3 <1> mov ss,bx
|
|
2518 00000AB7 BCF48F <1> mov sp,linux_stack
|
|
2519 <1> ;
|
|
2520 <1> ; We're done... now RUN THAT KERNEL!!!!
|
|
2521 <1> ; Setup segment == real mode segment + 020h; we need to jump to offset
|
|
2522 <1> ; zero in the real mode segment.
|
|
2523 <1> ;
|
|
2524 00000ABA 83C320 <1> add bx,020h
|
|
2525 00000ABD 53 <1> push bx
|
|
2526 00000ABE 6A00 <1> push word 0h
|
|
2527 00000AC0 CB <1> retf
|
|
2528 <1>
|
|
2529 <1> ;
|
|
2530 <1> ; Load an older kernel. Older kernels always have 4 setup sectors, can't have
|
|
2531 <1> ; initrd, and are always loaded low.
|
|
2532 <1> ;
|
|
2533 <1> old_kernel:
|
|
2534 00000AC1 833E[9C08]00 <1> cmp word [InitRDPtr],0 ; Old kernel can't have initrd
|
|
2535 00000AC6 7406 <1> je load_old_kernel
|
|
2536 00000AC8 BE[5003] <1> mov si,err_oldkernel
|
|
2537 00000ACB E9D206 <1> jmp abort_load
|
|
2538 <1> load_old_kernel:
|
|
2539 00000ACE C706[9A08]0400 <1> mov word [SetupSecs],4 ; Always 4 setup sectors
|
|
2540 00000AD4 C606[9E08]00 <1> mov byte [LoadFlags],0 ; Always low
|
|
2541 00000AD9 E99FFE <1> jmp read_kernel
|
|
2542 <1>
|
|
2543 <1> ;
|
|
2544 <1> ; parse_load_initrd
|
|
2545 <1> ;
|
|
2546 <1> ; Parse an initrd= option and load the initrds. Note that we load
|
|
2547 <1> ; from the high end of memory first, so we parse this option from
|
|
2548 <1> ; left to right.
|
|
2549 <1> ;
|
|
2550 <1> parse_load_initrd:
|
|
2551 00000ADC 06 <1> push es
|
|
2552 00000ADD 1E <1> push ds
|
|
2553 00000ADE B80040 <1> mov ax,real_mode_seg
|
|
2554 00000AE1 8ED8 <1> mov ds,ax
|
|
2555 00000AE3 0E <1> push cs
|
|
2556 00000AE4 07 <1> pop es ; DS == real_mode_seg, ES == CS
|
|
2557 <1>
|
|
2558 00000AE5 2E8B36[9C08] <1> mov si,[cs:InitRDPtr]
|
|
2559 <1> .find_end:
|
|
2560 00000AEA AC <1> lodsb
|
|
2561 00000AEB 3C20 <1> cmp al,' '
|
|
2562 00000AED 77FB <1> ja .find_end
|
|
2563 <1> ; Now SI points to one character beyond the
|
|
2564 <1> ; byte that ended this option.
|
|
2565 <1>
|
|
2566 <1> .get_chunk:
|
|
2567 00000AEF 4E <1> dec si
|
|
2568 <1>
|
|
2569 <1> ; DS:SI points to a termination byte
|
|
2570 <1>
|
|
2571 00000AF0 31C0 <1> xor ax,ax
|
|
2572 00000AF2 8604 <1> xchg al,[si] ; Zero-terminate
|
|
2573 00000AF4 56 <1> push si ; Save ending byte address
|
|
2574 00000AF5 50 <1> push ax ; Save ending byte
|
|
2575 <1>
|
|
2576 <1> .find_start:
|
|
2577 00000AF6 4E <1> dec si
|
|
2578 00000AF7 2E3B36[9C08] <1> cmp si,[cs:InitRDPtr]
|
|
2579 00000AFC 7406 <1> je .got_start
|
|
2580 00000AFE 803C2C <1> cmp byte [si],','
|
|
2581 00000B01 75F3 <1> jne .find_start
|
|
2582 <1>
|
|
2583 <1> ; It's a comma byte
|
|
2584 00000B03 46 <1> inc si
|
|
2585 <1>
|
|
2586 <1> .got_start:
|
|
2587 00000B04 56 <1> push si
|
|
2588 00000B05 BF[E01D] <1> mov di,InitRD ; Target buffer for mangled name
|
|
2589 00000B08 E8300A <1> call mangle_name
|
|
2590 00000B0B E80F00 <1> call loadinitrd
|
|
2591 00000B0E 5E <1> pop si
|
|
2592 <1>
|
|
2593 00000B0F 58 <1> pop ax
|
|
2594 00000B10 5F <1> pop di
|
|
2595 00000B11 8805 <1> mov [di],al ; Restore ending byte
|
|
2596 <1>
|
|
2597 00000B13 2E3B36[9C08] <1> cmp si,[cs:InitRDPtr]
|
|
2598 00000B18 77D5 <1> ja .get_chunk
|
|
2599 <1>
|
|
2600 00000B1A 1F <1> pop ds
|
|
2601 00000B1B 07 <1> pop es
|
|
2602 00000B1C C3 <1> ret
|
|
2603 <1>
|
|
2604 <1> ;
|
|
2605 <1> ; Load RAM disk into high memory
|
|
2606 <1> ;
|
|
2607 <1> ; Input: InitRD - set to the mangled name of the initrd
|
|
2608 <1> ;
|
|
2609 <1> loadinitrd:
|
|
2610 00000B1D 1E <1> push ds
|
|
2611 00000B1E 06 <1> push es
|
|
2612 00000B1F 8CC8 <1> mov ax,cs ; CS == DS == ES
|
|
2613 00000B21 8ED8 <1> mov ds,ax
|
|
2614 00000B23 8EC0 <1> mov es,ax
|
|
2615 00000B25 BE[E01D] <1> mov si,InitRD
|
|
2616 00000B28 BF[E01C] <1> mov di,InitRDCName
|
|
2617 00000B2B E8620A <1> call unmangle_name ; Create human-readable name
|
|
2618 00000B2E 81EF[E01C] <1> sub di,InitRDCName
|
|
2619 00000B32 893E[DE1B] <1> mov [InitRDCNameLen],di
|
|
2620 00000B36 BF[E01D] <1> mov di,InitRD
|
|
2621 00000B39 E8A107 <1> call searchdir ; Look for it in directory
|
|
2622 00000B3C 747F <1> jz .notthere
|
|
2623 <1>
|
|
2624 00000B3E 89D1 <1> mov cx,dx
|
|
2625 00000B40 66C1E110 <1> shl ecx,16
|
|
2626 00000B44 89C1 <1> mov cx,ax ; ECX <- ram disk length
|
|
2627 <1>
|
|
2628 00000B46 B80040 <1> mov ax,real_mode_seg
|
|
2629 00000B49 8EC0 <1> mov es,ax
|
|
2630 <1>
|
|
2631 00000B4B 6651 <1> push ecx ; Bytes to load
|
|
2632 00000B4D 2666833E1C0200 <1> cmp dword [es:su_ramdisklen],0
|
|
2633 00000B54 740B <1> je .nopadding ; Don't pad the last initrd
|
|
2634 00000B56 6681C1FF0F0000 <1> add ecx,4095
|
|
2635 00000B5D 81E100F0 <1> and cx,0F000h
|
|
2636 <1> .nopadding:
|
|
2637 00000B61 2666010E1C02 <1> add [es:su_ramdisklen],ecx
|
|
2638 00000B67 668B16[981F] <1> mov edx,[HighMemSize] ; End of memory
|
|
2639 00000B6C 664A <1> dec edx
|
|
2640 00000B6E 66A1[8808] <1> mov eax,[RamdiskMax] ; Highest address allowed by kernel
|
|
2641 00000B72 6639C2 <1> cmp edx,eax
|
|
2642 00000B75 7603 <1> jna .memsize_ok
|
|
2643 00000B77 6689C2 <1> mov edx,eax ; Adjust to fit inside limit
|
|
2644 <1> .memsize_ok:
|
|
2645 00000B7A 6642 <1> inc edx
|
|
2646 00000B7C 81E200F0 <1> and dx,0F000h ; Round down to 4K boundary
|
|
2647 00000B80 6629CA <1> sub edx,ecx ; Subtract size of ramdisk
|
|
2648 00000B83 81E200F0 <1> and dx,0F000h ; Round down to 4K boundary
|
|
2649 00000B87 663B16[9408] <1> cmp edx,[KernelEnd] ; Are we hitting the kernel image?
|
|
2650 00000B8C 7241 <1> jb no_high_mem
|
|
2651 <1>
|
|
2652 00000B8E 266689161802 <1> mov [es:su_ramdiskat],edx ; Load address
|
|
2653 00000B94 668916[8808] <1> mov [RamdiskMax],edx ; Next initrd loaded here
|
|
2654 <1>
|
|
2655 00000B99 6689D7 <1> mov edi,edx ; initrd load address
|
|
2656 00000B9C 56 <1> push si
|
|
2657 00000B9D BE[C406] <1> mov si,crlfloading_msg ; Write "Loading "
|
|
2658 00000BA0 E8B112 <1> call cwritestr
|
|
2659 00000BA3 BE[E01C] <1> mov si,InitRDCName ; Write ramdisk name
|
|
2660 00000BA6 E8AB12 <1> call cwritestr
|
|
2661 00000BA9 BE[CF06] <1> mov si,dotdot_msg ; Write dots
|
|
2662 00000BAC E8A512 <1> call cwritestr
|
|
2663 00000BAF 5E <1> pop si
|
|
2664 <1>
|
|
2665 00000BB0 6658 <1> pop eax ; Bytes to load
|
|
2666 00000BB2 BAFF0F <1> mov dx,0FFFh ; Pad to page
|
|
2667 00000BB5 E80316 <1> call load_high ; Load the file
|
|
2668 <1>
|
|
2669 00000BB8 07 <1> pop es
|
|
2670 00000BB9 1F <1> pop ds
|
|
2671 00000BBA E98A12 <1> jmp crlf ; Print carriage return and return
|
|
2672 <1>
|
|
2673 <1> .notthere:
|
|
2674 00000BBD BE[E402] <1> mov si,err_noinitrd
|
|
2675 00000BC0 E89112 <1> call cwritestr
|
|
2676 00000BC3 BE[E01C] <1> mov si,InitRDCName
|
|
2677 00000BC6 E88B12 <1> call cwritestr
|
|
2678 00000BC9 BE[E006] <1> mov si,crlf_msg
|
|
2679 00000BCC E9D105 <1> jmp abort_load
|
|
2680 <1>
|
|
2681 <1> no_high_mem: ; Error routine
|
|
2682 00000BCF BE[0503] <1> mov si,err_nohighmem
|
|
2683 00000BD2 E9CB05 <1> jmp abort_load
|
|
2684 <1>
|
|
2685 00000BD5 C3 <1> ret
|
|
2686 <1>
|
|
2687 <1> section .data
|
|
2688 0000000B 424F4F545F494D4147- <1> boot_image db 'BOOT_IMAGE='
|
|
2689 00000014 453D <1>
|
|
2690 <1> boot_image_len equ $-boot_image
|
|
2691 <1>
|
|
2692 <1> section .bss
|
|
2693 00000886 <res 00000001>- <1> alignb 4
|
|
2694 00000886 <rept> <1>
|
|
2695 00000888 <res 00000004> <1> RamdiskMax resd 1 ; Highest address for ramdisk
|
|
2696 0000088C <res 00000004> <1> KernelSize resd 1 ; Size of kernel in bytes
|
|
2697 00000890 <res 00000004> <1> KernelSects resd 1 ; Size of kernel in sectors
|
|
2698 00000894 <res 00000004> <1> KernelEnd resd 1 ; Ending address of the kernel image
|
|
2699 00000898 <res 00000002> <1> CmdLineLen resw 1 ; Length of command line including null
|
|
2700 0000089A <res 00000002> <1> SetupSecs resw 1 ; Number of setup sectors
|
|
2701 0000089C <res 00000002> <1> InitRDPtr resw 1 ; Pointer to initrd= option in command line
|
|
2702 0000089E <res 00000001> <1> LoadFlags resb 1 ; Loadflags from kernel
|
|
2703
|
|
2704 ;
|
|
2705 ; COMBOOT-loading code
|
|
2706 ;
|
|
2707 %include "comboot.inc"
|
|
2708 <1> ;; $Id: comboot.inc,v 1.39 2005/01/20 18:43:22 hpa Exp $
|
|
2709 <1> ;; -----------------------------------------------------------------------
|
|
2710 <1> ;;
|
|
2711 <1> ;; Copyright 1994-2005 H. Peter Anvin - All Rights Reserved
|
|
2712 <1> ;;
|
|
2713 <1> ;; This program is free software; you can redistribute it and/or modify
|
|
2714 <1> ;; it under the terms of the GNU General Public License as published by
|
|
2715 <1> ;; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
|
|
2716 <1> ;; Boston MA 02111-1307, USA; either version 2 of the License, or
|
|
2717 <1> ;; (at your option) any later version; incorporated herein by reference.
|
|
2718 <1> ;;
|
|
2719 <1> ;; -----------------------------------------------------------------------
|
|
2720 <1>
|
|
2721 <1> ;;
|
|
2722 <1> ;; comboot.inc
|
|
2723 <1> ;;
|
|
2724 <1> ;; Common code for running a COMBOOT image
|
|
2725 <1> ;;
|
|
2726 <1>
|
|
2727 <1> section .text
|
|
2728 <1>
|
|
2729 <1> ; Parameter registers definition; this is the definition
|
|
2730 <1> ; of the stack frame used by INT 21h and INT 22h.
|
|
2731 <1> %define P_FLAGS word [bp+44]
|
|
2732 <1> %define P_FLAGSL byte [bp+44]
|
|
2733 <1> %define P_FLAGSH byte [bp+45]
|
|
2734 <1> %define P_CS word [bp+42]
|
|
2735 <1> %define P_IP word [bp+40]
|
|
2736 <1> %define P_DS word [bp+38]
|
|
2737 <1> %define P_ES word [bp+36]
|
|
2738 <1> %define P_FS word [bp+34]
|
|
2739 <1> %define P_GS word [bp+32]
|
|
2740 <1> %define P_EAX dword [bp+28]
|
|
2741 <1> %define P_AX word [bp+28]
|
|
2742 <1> %define P_HAX word [bp+30]
|
|
2743 <1> %define P_AL byte [bp+28]
|
|
2744 <1> %define P_AH byte [bp+29]
|
|
2745 <1> %define P_ECX dword [bp+24]
|
|
2746 <1> %define P_CX word [bp+24]
|
|
2747 <1> %define P_HCX word [bp+26]
|
|
2748 <1> %define P_CL byte [bp+24]
|
|
2749 <1> %define P_CH byte [bp+25]
|
|
2750 <1> %define P_EDX dword [bp+20]
|
|
2751 <1> %define P_DX word [bp+20]
|
|
2752 <1> %define P_HDX word [bp+22]
|
|
2753 <1> %define P_DL byte [bp+20]
|
|
2754 <1> %define P_DH byte [bp+21]
|
|
2755 <1> %define P_EBX dword [bp+16]
|
|
2756 <1> %define P_BX word [bp+16]
|
|
2757 <1> %define P_HBX word [bp+18]
|
|
2758 <1> %define P_BL byte [bp+16]
|
|
2759 <1> %define P_BH byte [bp+17]
|
|
2760 <1> %define P_EBP dword [bp+8]
|
|
2761 <1> %define P_BP word [bp+8]
|
|
2762 <1> %define P_HBP word [bp+10]
|
|
2763 <1> %define P_ESI dword [bp+4]
|
|
2764 <1> %define P_SI word [bp+4]
|
|
2765 <1> %define P_HSI word [bp+6]
|
|
2766 <1> %define P_EDI dword [bp]
|
|
2767 <1> %define P_DI word [bp]
|
|
2768 <1> %define P_HDI word [bp+2]
|
|
2769 <1>
|
|
2770 <1> ; Looks like a COMBOOT image but too large
|
|
2771 <1> comboot_too_large:
|
|
2772 00000BD6 BE[A003] <1> mov si,err_comlarge
|
|
2773 00000BD9 E87812 <1> call cwritestr
|
|
2774 00000BDC E9D5F8 <1> jmp enter_command
|
|
2775 <1>
|
|
2776 <1> ;
|
|
2777 <1> ; Load a COMBOOT image. A COMBOOT image is basically a DOS .COM file,
|
|
2778 <1> ; except that it may, of course, not contain any DOS system calls. We
|
|
2779 <1> ; do, however, allow the execution of INT 20h to return to SYSLINUX.
|
|
2780 <1> ;
|
|
2781 <1> is_comboot_image:
|
|
2782 00000BDF 21D2 <1> and dx,dx
|
|
2783 00000BE1 75F3 <1> jnz comboot_too_large
|
|
2784 00000BE3 3D00FF <1> cmp ax,0ff00h ; Max size in bytes
|
|
2785 00000BE6 73EE <1> jae comboot_too_large
|
|
2786 <1>
|
|
2787 00000BE8 56 <1> push si ; Save file handle
|
|
2788 <1>
|
|
2789 00000BE9 E8CC04 <1> call make_plain_cmdline
|
|
2790 <1>
|
|
2791 00000BEC E86600 <1> call comboot_setup_api
|
|
2792 <1>
|
|
2793 00000BEF B90040 <1> mov cx,comboot_seg
|
|
2794 00000BF2 8EC1 <1> mov es,cx
|
|
2795 <1>
|
|
2796 00000BF4 31FF <1> xor di,di
|
|
2797 00000BF6 B94000 <1> mov cx,64 ; 256 bytes (size of PSP)
|
|
2798 00000BF9 6631C0 <1> xor eax,eax ; Clear PSP
|
|
2799 00000BFC F366AB <1> rep stosd
|
|
2800 <1>
|
|
2801 00000BFF 26C7060000CD20 <1> mov word [es:0], 020CDh ; INT 20h instruction
|
|
2802 <1> ; First non-free paragraph
|
|
2803 <1> ; This is valid because comboot_seg == real_mode_seg
|
|
2804 <1> ; == the highest segment used by all derivatives
|
|
2805 00000C06 CD12 <1> int 12h ; Get DOS memory size
|
|
2806 00000C08 C1E006 <1> shl ax,6 ; Kilobytes -> paragraphs
|
|
2807 00000C0B 26A30200 <1> mov word [es:02h],ax
|
|
2808 <1>
|
|
2809 <1> %ifndef DEPEND
|
|
2810 <1> %if real_mode_seg != comboot_seg
|
|
2811 <1> %error "This code assumes real_mode_seg == comboot_seg"
|
|
2812 <1> %endif
|
|
2813 <1> %endif
|
|
2814 <1> ; Copy the command line from high memory
|
|
2815 00000C0F BE0090 <1> mov si,cmd_line_here
|
|
2816 00000C12 B97D00 <1> mov cx,125 ; Max cmdline len (minus space and CR)
|
|
2817 00000C15 BF8100 <1> mov di,081h ; Offset in PSP for command line
|
|
2818 00000C18 B020 <1> mov al,' ' ; DOS command lines begin with a space
|
|
2819 00000C1A AA <1> stosb
|
|
2820 <1>
|
|
2821 00000C1B 26AC <1> .loop: es lodsb
|
|
2822 00000C1D 20C0 <1> and al,al
|
|
2823 00000C1F 7403 <1> jz .done
|
|
2824 00000C21 AA <1> stosb
|
|
2825 00000C22 E2F7 <1> loop .loop
|
|
2826 <1> .done:
|
|
2827 <1>
|
|
2828 00000C24 B00D <1> mov al,0Dh ; CR after last character
|
|
2829 00000C26 AA <1> stosb
|
|
2830 00000C27 89F8 <1> mov ax,di
|
|
2831 00000C29 2C82 <1> sub al,82h ; Include space but not CR
|
|
2832 00000C2B 26A28000 <1> mov [es:80h],al ; Store command line length
|
|
2833 <1>
|
|
2834 <1> ; Now actually load the file...
|
|
2835 00000C2F 5E <1> pop si ; File handle
|
|
2836 00000C30 BB0001 <1> mov bx,100h ; Load at <seg>:0100h
|
|
2837 00000C33 B97F00 <1> mov cx,0FF00h >> SECTOR_SHIFT
|
|
2838 <1> ; Absolute maximum # of sectors
|
|
2839 00000C36 E88509 <1> call getfssec
|
|
2840 <1>
|
|
2841 <1> ; And invoke the program...
|
|
2842 00000C39 8926[6855] <1> mov [SavedSSSP],sp
|
|
2843 00000C3D 8C16[6A55] <1> mov [SavedSSSP+2],ss ; Save away SS:SP
|
|
2844 <1>
|
|
2845 00000C41 8CC0 <1> mov ax,es
|
|
2846 00000C43 8ED8 <1> mov ds,ax
|
|
2847 00000C45 8ED0 <1> mov ss,ax
|
|
2848 00000C47 31E4 <1> xor sp,sp
|
|
2849 00000C49 6A00 <1> push word 0 ; Return to address 0 -> exit
|
|
2850 <1>
|
|
2851 00000C4B EA00010040 <1> jmp comboot_seg:100h ; Run it
|
|
2852 <1>
|
|
2853 <1> ; Proper return vector
|
|
2854 00000C50 FA <1> comboot_return: cli ; Don't trust anyone
|
|
2855 00000C51 31C0 <1> xor ax,ax
|
|
2856 00000C53 EB55 <1> jmp comboot_exit
|
|
2857 <1>
|
|
2858 <1> ;
|
|
2859 <1> ; Set up the COMBOOT API interrupt vectors. This is also used
|
|
2860 <1> ; by the COM32 code.
|
|
2861 <1> ;
|
|
2862 <1> comboot_setup_api:
|
|
2863 00000C55 BF8000 <1> mov di,4*0x20 ; DOS interrupt vectors
|
|
2864 00000C58 66B8[500C0000] <1> mov eax,comboot_return ; INT 20h = exit
|
|
2865 00000C5E 66AB <1> stosd
|
|
2866 00000C60 B8[740C] <1> mov ax,comboot_int21 ; INT 21h = DOS-compatible syscalls
|
|
2867 00000C63 66AB <1> stosd
|
|
2868 00000C65 B8[5B0D] <1> mov ax,comboot_int22 ; INT 22h = proprietary syscalls
|
|
2869 00000C68 66AB <1> stosd
|
|
2870 00000C6A B8[A60C] <1> mov ax,comboot_bogus
|
|
2871 00000C6D B91D00 <1> mov cx,29 ; All remaining DOS vectors
|
|
2872 00000C70 F366AB <1> rep stosd
|
|
2873 00000C73 C3 <1> ret
|
|
2874 <1>
|
|
2875 <1> ; INT 21h: generic DOS system call
|
|
2876 00000C74 FA <1> comboot_int21: cli
|
|
2877 00000C75 1E <1> push ds
|
|
2878 00000C76 06 <1> push es
|
|
2879 00000C77 0FA0 <1> push fs
|
|
2880 00000C79 0FA8 <1> push gs
|
|
2881 00000C7B 6660 <1> pushad
|
|
2882 00000C7D FC <1> cld
|
|
2883 00000C7E 8CCD <1> mov bp,cs
|
|
2884 00000C80 8EDD <1> mov ds,bp
|
|
2885 00000C82 8EC5 <1> mov es,bp
|
|
2886 00000C84 89E5 <1> mov bp,sp ; Set up stack frame
|
|
2887 <1>
|
|
2888 00000C86 E81D16 <1> call adjust_screen ; The COMBOOT program might have changed the screen
|
|
2889 <1>
|
|
2890 00000C89 B90A00 <1> mov cx,int21_count
|
|
2891 00000C8C BE[6A00] <1> mov si,int21_table
|
|
2892 00000C8F AC <1> .again: lodsb
|
|
2893 00000C90 3A461D <1> cmp al,P_AH
|
|
2894 00000C93 AD <1> lodsw
|
|
2895 00000C94 E0F9 <1> loopne .again
|
|
2896 <1> ; The last function in the list is the
|
|
2897 <1> ; "no such function" function
|
|
2898 00000C96 F8 <1> clc
|
|
2899 00000C97 FFD0 <1> call ax ; Call the invoked function
|
|
2900 <1> comboot_resume:
|
|
2901 00000C99 0F92462C <1> setc P_FLAGSL ; Propagate CF->error
|
|
2902 00000C9D 6661 <1> popad
|
|
2903 00000C9F 0FA9 <1> pop gs
|
|
2904 00000CA1 0FA1 <1> pop fs
|
|
2905 00000CA3 07 <1> pop es
|
|
2906 00000CA4 1F <1> pop ds
|
|
2907 00000CA5 CF <1> iret
|
|
2908 <1>
|
|
2909 <1> ; Attempted to execute non-21h DOS system call
|
|
2910 00000CA6 FA <1> comboot_bogus: cli ; Don't trust anyone
|
|
2911 00000CA7 B8[8203] <1> mov ax,err_notdos
|
|
2912 <1> ;
|
|
2913 <1> ; Generic COMBOOT return to command line code
|
|
2914 <1> ; AX -> message (if any)
|
|
2915 <1> ; BX -> where to go next
|
|
2916 <1> ;
|
|
2917 <1> comboot_exit:
|
|
2918 00000CAA BB[B404] <1> mov bx,enter_command ; Normal return to command prompt
|
|
2919 <1> comboot_exit_special:
|
|
2920 00000CAD 31D2 <1> xor dx,dx
|
|
2921 00000CAF 8EDA <1> mov ds,dx
|
|
2922 00000CB1 8EC2 <1> mov es,dx
|
|
2923 00000CB3 0FB226[6855] <1> lss sp,[SavedSSSP]
|
|
2924 00000CB8 FB <1> sti
|
|
2925 00000CB9 FC <1> cld
|
|
2926 00000CBA E8E915 <1> call adjust_screen ; The COMBOOT program might have changed the screen
|
|
2927 00000CBD 21C0 <1> and ax,ax
|
|
2928 00000CBF 740A <1> je .nomsg
|
|
2929 00000CC1 BE[601C] <1> mov si,KernelCName
|
|
2930 00000CC4 E88D11 <1> call cwritestr
|
|
2931 00000CC7 96 <1> xchg si,ax
|
|
2932 00000CC8 E88911 <1> call cwritestr
|
|
2933 00000CCB FFE3 <1> .nomsg: jmp bx
|
|
2934 <1>
|
|
2935 <1> ;
|
|
2936 <1> ; INT 21h system calls
|
|
2937 <1> ;
|
|
2938 <1> comboot_getkey: ; 01 = get key with echo
|
|
2939 00000CCD E89D17 <1> call vgashowcursor
|
|
2940 00000CD0 E86500 <1> call comboot_getchar
|
|
2941 00000CD3 E89D17 <1> call vgahidecursor
|
|
2942 00000CD6 E8AC18 <1> call writechr
|
|
2943 00000CD9 F8 <1> clc
|
|
2944 00000CDA C3 <1> ret
|
|
2945 <1>
|
|
2946 <1> comboot_writechr: ; 02 = writechr
|
|
2947 00000CDB 8A4614 <1> mov al,P_DL
|
|
2948 00000CDE E8A418 <1> call writechr
|
|
2949 00000CE1 F8 <1> clc
|
|
2950 00000CE2 C3 <1> ret
|
|
2951 <1>
|
|
2952 <1> comboot_writeserial: ; 04 = write serial port
|
|
2953 00000CE3 8A4614 <1> mov al,P_DL
|
|
2954 00000CE6 E8B510 <1> call write_serial
|
|
2955 00000CE9 F8 <1> clc
|
|
2956 00000CEA C3 <1> ret
|
|
2957 <1>
|
|
2958 <1> comboot_getkeynoecho: ; 08 = get key w/o echo
|
|
2959 00000CEB E84A00 <1> call comboot_getchar
|
|
2960 00000CEE F8 <1> clc
|
|
2961 00000CEF C3 <1> ret
|
|
2962 <1>
|
|
2963 <1> comboot_writestr: ; 09 = write DOS string
|
|
2964 00000CF0 8E4626 <1> mov es,P_DS
|
|
2965 00000CF3 8B7614 <1> mov si,P_DX
|
|
2966 00000CF6 26AC <1> .loop: es lodsb
|
|
2967 00000CF8 3C24 <1> cmp al,'$' ; End string with $ - bizarre
|
|
2968 00000CFA 7405 <1> je .done
|
|
2969 00000CFC E88618 <1> call writechr
|
|
2970 00000CFF EBF5 <1> jmp short .loop
|
|
2971 00000D01 F8 <1> .done: clc
|
|
2972 00000D02 C3 <1> ret
|
|
2973 <1>
|
|
2974 <1> comboot_checkkey: ; 0B = check keyboard status
|
|
2975 00000D03 803E[B100]00 <1> cmp byte [APIKeyFlag],00h
|
|
2976 00000D08 7503 <1> jnz .waiting
|
|
2977 00000D0A E8CF10 <1> call pollchar
|
|
2978 00000D0D 0F94C0 <1> .waiting: setz al
|
|
2979 00000D10 FEC8 <1> dec al ; AL = 0FFh if present, 0 if not
|
|
2980 00000D12 88461C <1> mov P_AL,al
|
|
2981 00000D15 F8 <1> clc
|
|
2982 00000D16 C3 <1> ret
|
|
2983 <1>
|
|
2984 <1> comboot_checkver: ; 30 = check DOS version
|
|
2985 <1> ; We return 0 in all DOS-compatible version registers,
|
|
2986 <1> ; but the high part of eax-ebx-ecx-edx spell "SYSLINUX"
|
|
2987 00000D17 66C7461C00005359 <1> mov P_EAX,'SY' << 16
|
|
2988 00000D1F 66C746100000534C <1> mov P_EBX,'SL' << 16
|
|
2989 00000D27 66C746180000494E <1> mov P_ECX,'IN' << 16
|
|
2990 00000D2F 66C7461400005558 <1> mov P_EDX,'UX' << 16
|
|
2991 00000D37 C3 <1> ret
|
|
2992 <1>
|
|
2993 <1> comboot_getchar:
|
|
2994 00000D38 803E[B100]00 <1> cmp byte [APIKeyFlag],00h
|
|
2995 00000D3D 7513 <1> jne .queued
|
|
2996 00000D3F E8C410 <1> call getchar ; If not queued get input
|
|
2997 00000D42 20C0 <1> and al,al ; Function key? (CF <- 0)
|
|
2998 00000D44 7508 <1> jnz .done
|
|
2999 00000D46 8826[B000] <1> mov [APIKeyWait],ah ; High part of key
|
|
3000 00000D4A FE06[B100] <1> inc byte [APIKeyFlag] ; Set flag
|
|
3001 00000D4E 88461C <1> .done: mov P_AL,al
|
|
3002 00000D51 C3 <1> ret
|
|
3003 00000D52 A0[B000] <1> .queued: mov al,[APIKeyWait]
|
|
3004 00000D55 FE0E[B100] <1> dec byte [APIKeyFlag]
|
|
3005 00000D59 EBF3 <1> jmp .done
|
|
3006 <1>
|
|
3007 <1> ;
|
|
3008 <1> ; INT 22h - SYSLINUX-specific system calls
|
|
3009 <1> ; System call number in ax
|
|
3010 <1> ;
|
|
3011 <1> comboot_int22:
|
|
3012 00000D5B FA <1> cli
|
|
3013 00000D5C 1E <1> push ds
|
|
3014 00000D5D 06 <1> push es
|
|
3015 00000D5E 0FA0 <1> push fs
|
|
3016 00000D60 0FA8 <1> push gs
|
|
3017 00000D62 6660 <1> pushad
|
|
3018 00000D64 FC <1> cld
|
|
3019 00000D65 8CCD <1> mov bp,cs
|
|
3020 00000D67 8EDD <1> mov ds,bp
|
|
3021 00000D69 8EC5 <1> mov es,bp
|
|
3022 00000D6B 89E5 <1> mov bp,sp ; Set up stack frame
|
|
3023 <1>
|
|
3024 00000D6D E83615 <1> call adjust_screen ; The COMBOOT program might have changed the screen
|
|
3025 <1>
|
|
3026 00000D70 83F814 <1> cmp ax,int22_count
|
|
3027 00000D73 7202 <1> jb .ok
|
|
3028 00000D75 31C0 <1> xor ax,ax ; Function 0 -> unimplemented
|
|
3029 <1> .ok:
|
|
3030 00000D77 93 <1> xchg ax,bx
|
|
3031 00000D78 01DB <1> add bx,bx ; CF <- 0
|
|
3032 00000D7A FF97[8800] <1> call [bx+int22_table]
|
|
3033 00000D7E E918FF <1> jmp comboot_resume ; On return
|
|
3034 <1>
|
|
3035 <1> ;
|
|
3036 <1> ; INT 22h AX=0000h Unimplemented call
|
|
3037 <1> ;
|
|
3038 <1> comapi_err:
|
|
3039 00000D81 F9 <1> stc
|
|
3040 00000D82 C3 <1> ret
|
|
3041 <1>
|
|
3042 <1> ;
|
|
3043 <1> ; INT 22h AX=0001h Get SYSLINUX version
|
|
3044 <1> ;
|
|
3045 <1> comapi_get_version:
|
|
3046 <1> ; Number of API functions supported
|
|
3047 00000D83 C7461C1400 <1> mov P_AX,int22_count
|
|
3048 <1> ; SYSLINUX version
|
|
3049 00000D88 C746180903 <1> mov P_CX,(VER_MAJOR << 8)+VER_MINOR
|
|
3050 <1> ; SYSLINUX derivative ID byte
|
|
3051 00000D8D C746143200 <1> mov P_DX,my_id
|
|
3052 <1> ; For future use
|
|
3053 00000D92 8C4E10 <1> mov P_BX,cs ; cs == 0
|
|
3054 <1>
|
|
3055 00000D95 8C5E24 <1> mov P_ES,ds
|
|
3056 <1> ; ES:SI -> version banner
|
|
3057 00000D98 C74604[EE06] <1> mov P_SI,syslinux_banner
|
|
3058 <1> ; ES:DI -> copyright string
|
|
3059 00000D9D C74600[4B01] <1> mov P_DI,copyright_str
|
|
3060 <1>
|
|
3061 <1> comapi_nop:
|
|
3062 00000DA2 F8 <1> clc
|
|
3063 00000DA3 C3 <1> ret
|
|
3064 <1>
|
|
3065 <1> ;
|
|
3066 <1> ; INT 22h AX=0002h Write string
|
|
3067 <1> ;
|
|
3068 <1> ; Write null-terminated string in ES:BX
|
|
3069 <1> ;
|
|
3070 <1> comapi_writestr:
|
|
3071 00000DA4 8E5E24 <1> mov ds,P_ES
|
|
3072 00000DA7 8B7610 <1> mov si,P_BX
|
|
3073 00000DAA E8A710 <1> call writestr
|
|
3074 00000DAD F8 <1> clc
|
|
3075 00000DAE C3 <1> ret
|
|
3076 <1>
|
|
3077 <1> ;
|
|
3078 <1> ; INT 22h AX=0003h Run command
|
|
3079 <1> ;
|
|
3080 <1> ; Terminates the COMBOOT program and executes the command line in
|
|
3081 <1> ; ES:BX as if it had been entered by the user.
|
|
3082 <1> ;
|
|
3083 <1> comapi_run:
|
|
3084 00000DAF 8E5E24 <1> mov ds,P_ES
|
|
3085 00000DB2 8B7610 <1> mov si,P_BX
|
|
3086 00000DB5 BF[D408] <1> mov di,command_line
|
|
3087 00000DB8 E8C117 <1> call strcpy
|
|
3088 00000DBB 31C0 <1> xor ax,ax
|
|
3089 00000DBD BB[EE05] <1> mov bx,load_kernel ; Run a new kernel
|
|
3090 00000DC0 E9EAFE <1> jmp comboot_exit_special ; Terminate task, clean up
|
|
3091 <1>
|
|
3092 <1> ;
|
|
3093 <1> ; INT 22h AX=0004h Run default command
|
|
3094 <1> ;
|
|
3095 <1> ; Terminates the COMBOOT program and executes the default command line
|
|
3096 <1> ; as if a timeout had happened or the user pressed <Enter>.
|
|
3097 <1> ;
|
|
3098 <1> comapi_run_default:
|
|
3099 00000DC3 BB[D405] <1> mov bx,auto_boot
|
|
3100 00000DC6 E9E4FE <1> jmp comboot_exit_special
|
|
3101 <1>
|
|
3102 <1> ;
|
|
3103 <1> ; INT 22h AX=0005h Force text mode
|
|
3104 <1> ;
|
|
3105 <1> ; Puts the video in standard text mode
|
|
3106 <1> ;
|
|
3107 <1> comapi_textmode:
|
|
3108 00000DC9 E87916 <1> call vgaclearmode
|
|
3109 00000DCC F8 <1> clc
|
|
3110 00000DCD C3 <1> ret
|
|
3111 <1>
|
|
3112 <1> ;
|
|
3113 <1> ; INT 22h AX=0006h Open file
|
|
3114 <1> ;
|
|
3115 <1> comapi_open:
|
|
3116 00000DCE 1E <1> push ds
|
|
3117 00000DCF 8E5E24 <1> mov ds,P_ES
|
|
3118 00000DD2 8B7604 <1> mov si,P_SI
|
|
3119 00000DD5 BF[E01D] <1> mov di,InitRD
|
|
3120 00000DD8 57 <1> push di
|
|
3121 00000DD9 E85F07 <1> call mangle_name
|
|
3122 00000DDC 5F <1> pop di
|
|
3123 00000DDD 1F <1> pop ds
|
|
3124 00000DDE E8FC04 <1> call searchdir
|
|
3125 00000DE1 7410 <1> jz .err
|
|
3126 00000DE3 89461C <1> mov P_AX,ax
|
|
3127 00000DE6 89561E <1> mov P_HAX,dx
|
|
3128 00000DE9 C746180002 <1> mov P_CX,SECTOR_SIZE
|
|
3129 00000DEE 897604 <1> mov P_SI,si
|
|
3130 00000DF1 F8 <1> clc
|
|
3131 00000DF2 C3 <1> ret
|
|
3132 <1> .err:
|
|
3133 00000DF3 F9 <1> stc
|
|
3134 00000DF4 C3 <1> ret
|
|
3135 <1>
|
|
3136 <1>
|
|
3137 <1> ;
|
|
3138 <1> ; INT 22h AX=0007h Read file
|
|
3139 <1> ;
|
|
3140 <1> comapi_read:
|
|
3141 00000DF5 8E4624 <1> mov es,P_ES
|
|
3142 00000DF8 8B5E10 <1> mov bx,P_BX
|
|
3143 00000DFB 8B7604 <1> mov si,P_SI
|
|
3144 00000DFE 8B4E18 <1> mov cx,P_CX
|
|
3145 00000E01 E8BA07 <1> call getfssec
|
|
3146 00000E04 7302 <1> jnc .noteof
|
|
3147 00000E06 31F6 <1> xor si,si ; SI <- 0 on EOF, CF <- 0
|
|
3148 00000E08 897604 <1> .noteof: mov P_SI,si
|
|
3149 00000E0B C3 <1> ret
|
|
3150 <1>
|
|
3151 <1> ;
|
|
3152 <1> ; INT 22h AX=0008h Close file
|
|
3153 <1> ;
|
|
3154 <1> comapi_close:
|
|
3155 <1> ; Do nothing for now. Eventually implement
|
|
3156 <1> ; an internal API for this.
|
|
3157 00000E0C F8 <1> clc
|
|
3158 00000E0D C3 <1> ret
|
|
3159 <1>
|
|
3160 <1> ;
|
|
3161 <1> ; INT 22h AX=0009h Call PXE stack
|
|
3162 <1> ;
|
|
3163 <1> %if IS_PXELINUX
|
|
3164 <1> comapi_pxecall:
|
|
3165 00000E0E 8B5E10 <1> mov bx,P_BX
|
|
3166 00000E11 8E4624 <1> mov es,P_ES
|
|
3167 00000E14 8B7E00 <1> mov di,P_DI
|
|
3168 00000E17 E88D07 <1> call pxenv
|
|
3169 00000E1A 89461C <1> mov P_AX,ax
|
|
3170 00000E1D F8 <1> clc
|
|
3171 00000E1E C3 <1> ret
|
|
3172 <1> %else
|
|
3173 <1> comapi_pxecall equ comapi_err ; Not available
|
|
3174 <1> %endif
|
|
3175 <1>
|
|
3176 <1> ;
|
|
3177 <1> ; INT 22h AX=000Ah Get Derivative-Specific Info
|
|
3178 <1> ;
|
|
3179 <1> comapi_derinfo:
|
|
3180 00000E1F C6461C32 <1> mov P_AL,my_id
|
|
3181 <1> %if IS_SYSLINUX || IS_MDSLINUX || IS_EXTLINUX
|
|
3182 <1> mov al,[DriveNumber]
|
|
3183 <1> mov P_DL,al
|
|
3184 <1> mov P_ES,cs
|
|
3185 <1> mov P_BX,PartInfo
|
|
3186 <1> %elif IS_PXELINUX
|
|
3187 00000E23 A1[0800] <1> mov ax,[APIVer]
|
|
3188 00000E26 894614 <1> mov P_DX,ax
|
|
3189 00000E29 A1[0400] <1> mov ax,[StrucPtr]
|
|
3190 00000E2C 894610 <1> mov P_BX,ax
|
|
3191 00000E2F A1[0600] <1> mov ax,[StrucPtr+2]
|
|
3192 00000E32 894624 <1> mov P_ES,ax
|
|
3193 00000E35 A1[6047] <1> mov ax,[InitStack]
|
|
3194 00000E38 894604 <1> mov P_SI,ax
|
|
3195 00000E3B A1[6247] <1> mov ax,[InitStack+2]
|
|
3196 00000E3E 894622 <1> mov P_FS,ax
|
|
3197 <1> %elif IS_ISOLINUX
|
|
3198 <1> mov al,[DriveNo]
|
|
3199 <1> mov P_DL,al
|
|
3200 <1> mov P_ES,cs
|
|
3201 <1> mov P_BX,spec_packet
|
|
3202 <1> %endif
|
|
3203 00000E41 F8 <1> clc
|
|
3204 00000E42 C3 <1> ret
|
|
3205 <1>
|
|
3206 <1> ;
|
|
3207 <1> ; INT 22h AX=000Bh Get Serial Console Configuration
|
|
3208 <1> ;
|
|
3209 <1> comapi_serialcfg:
|
|
3210 00000E43 A1[F600] <1> mov ax,[SerialPort]
|
|
3211 00000E46 894614 <1> mov P_DX,ax
|
|
3212 00000E49 A1[CA08] <1> mov ax,[BaudDivisor]
|
|
3213 00000E4C 894618 <1> mov P_CX,ax
|
|
3214 00000E4F A1[CC08] <1> mov ax,[FlowControl]
|
|
3215 00000E52 08E0 <1> or al,ah
|
|
3216 00000E54 8A26[CE08] <1> mov ah,[FlowIgnore]
|
|
3217 00000E58 C0EC04 <1> shr ah,4
|
|
3218 00000E5B F606[BE00]01 <1> test byte [DisplayCon],01h
|
|
3219 00000E60 7503 <1> jnz .normalconsole
|
|
3220 00000E62 80CC80 <1> or ah,80h
|
|
3221 <1> .normalconsole:
|
|
3222 00000E65 894610 <1> mov P_BX,ax
|
|
3223 00000E68 F8 <1> clc
|
|
3224 00000E69 C3 <1> ret
|
|
3225 <1>
|
|
3226 <1> ;
|
|
3227 <1> ; INT 22h AX=000Ch Perform final cleanup
|
|
3228 <1> ;
|
|
3229 <1> comapi_cleanup:
|
|
3230 <1> %if IS_PXELINUX
|
|
3231 <1> ; Unload PXE if requested
|
|
3232 00000E6A F6C203 <1> test dl,3
|
|
3233 00000E6D 0F9506[A608] <1> setnz [KeepPXE]
|
|
3234 00000E72 29E5 <1> sub bp,sp ; unload_pxe may move the stack around
|
|
3235 00000E74 E8D208 <1> call unload_pxe
|
|
3236 00000E77 01E5 <1> add bp,sp ; restore frame pointer...
|
|
3237 <1> %elif IS_SYSLINUX || IS_MDSLINUX || IS_EXTLINUX
|
|
3238 <1> ; Restore original FDC table
|
|
3239 <1> mov eax,[OrigFDCTabPtr]
|
|
3240 <1> mov [fdctab],eax
|
|
3241 <1> %endif
|
|
3242 <1> ; Reset the floppy disk subsystem
|
|
3243 00000E79 31C0 <1> xor ax,ax
|
|
3244 00000E7B 31D2 <1> xor dx,dx
|
|
3245 00000E7D CD13 <1> int 13h
|
|
3246 00000E7F F8 <1> clc
|
|
3247 00000E80 C3 <1> ret
|
|
3248 <1>
|
|
3249 <1> ;
|
|
3250 <1> ; INT 22h AX=000Dh Clean up then replace bootstrap
|
|
3251 <1> ;
|
|
3252 <1> comapi_chainboot:
|
|
3253 00000E81 E8E6FF <1> call comapi_cleanup
|
|
3254 00000E84 668B4600 <1> mov eax,P_EDI
|
|
3255 00000E88 66A3[0400] <1> mov [trackbuf+4],eax ; Copy from
|
|
3256 00000E8C 668B4618 <1> mov eax,P_ECX
|
|
3257 00000E90 66A3[0800] <1> mov [trackbuf+8],eax ; Total bytes
|
|
3258 00000E94 66B8007C0000 <1> mov eax,7C00h
|
|
3259 00000E9A 66A3[0000] <1> mov [trackbuf],eax ; Copy to
|
|
3260 00000E9E 66A3[6455] <1> mov [EntryPoint],eax ; CS:IP entry point
|
|
3261 00000EA2 668B7604 <1> mov esi,P_ESI
|
|
3262 00000EA6 668B5610 <1> mov edx,P_EBX
|
|
3263 00000EAA 8B5E26 <1> mov bx,P_DS
|
|
3264 00000EAD E96802 <1> jmp replace_bootstrap_one
|
|
3265 <1>
|
|
3266 <1>
|
|
3267 <1> ;
|
|
3268 <1> ; INT 22h AX=000Eh Get configuration file name
|
|
3269 <1> ;
|
|
3270 <1> comapi_configfile:
|
|
3271 00000EB0 8C4E24 <1> mov P_ES,cs
|
|
3272 00000EB3 C74610[0445] <1> mov P_BX,ConfigName
|
|
3273 00000EB8 F8 <1> clc
|
|
3274 00000EB9 C3 <1> ret
|
|
3275 <1>
|
|
3276 <1> ;
|
|
3277 <1> ; INT 22h AX=000Fh Get IPAPPEND strings
|
|
3278 <1> ;
|
|
3279 <1> %if IS_PXELINUX
|
|
3280 <1> comapi_ipappend:
|
|
3281 00000EBA 8C4E24 <1> mov P_ES,cs
|
|
3282 00000EBD C746180200 <1> mov P_CX,numIPAppends
|
|
3283 00000EC2 C74610[1600] <1> mov P_BX,IPAppends
|
|
3284 00000EC7 F8 <1> clc
|
|
3285 00000EC8 C3 <1> ret
|
|
3286 <1>
|
|
3287 <1> section .data
|
|
3288 <1> alignb 2, db 0
|
|
3289 00000016 [1047] <1> IPAppends dw IPOption
|
|
3290 00000018 [2700] <1> dw BOOTIFStr
|
|
3291 <1> numIPAppends equ ($-IPAppends)/2
|
|
3292 <1>
|
|
3293 <1> %else
|
|
3294 <1> comapi_ipappend equ comapi_err
|
|
3295 <1> %endif
|
|
3296 <1>
|
|
3297 <1> ;
|
|
3298 <1> ; INT 22h AX=0010h Resolve hostname
|
|
3299 <1> ;
|
|
3300 <1> %if IS_PXELINUX
|
|
3301 <1> comapi_dnsresolv:
|
|
3302 0000001A 8E5E24 <1> mov ds,P_ES
|
|
3303 0000001D 8B7610 <1> mov si,P_BX
|
|
3304 00000020 E8(4F26) <1> call dns_resolv
|
|
3305 00000023 6689461C <1> mov P_EAX,eax
|
|
3306 00000027 C3 <1> ret
|
|
3307 <1> %else
|
|
3308 <1> comapi_dnsresolv equ comapi_err
|
|
3309 <1> %endif
|
|
3310 <1>
|
|
3311 <1> section .data
|
|
3312 <1> %macro int21 2
|
|
3313 <1> db %1
|
|
3314 <1> dw %2
|
|
3315 <1> %endmacro
|
|
3316 <1>
|
|
3317 <1>
|
|
3318 <1> ;
|
|
3319 <1> ; INT 22h AX=0011h Maximum number of shuffle descriptors
|
|
3320 <1> ;
|
|
3321 <1> comapi_maxshuffle:
|
|
3322 00000028 C746185505 <1> mov P_CX,(2*trackbufsize)/12
|
|
3323 0000002D C3 <1> ret
|
|
3324 <1>
|
|
3325 <1> ;
|
|
3326 <1> ; INT 22h AX=0012h Cleanup, shuffle and boot
|
|
3327 <1> ;
|
|
3328 <1> comapi_shuffle:
|
|
3329 0000002E E8(6A0E) <1> call comapi_cleanup
|
|
3330 00000031 8B4E18 <1> mov cx,P_CX
|
|
3331 00000034 81F95505 <1> cmp cx,(2*trackbufsize)/12
|
|
3332 00000038 7729 <1> ja .error
|
|
3333 <1>
|
|
3334 0000003A 51 <1> push cx ; On stack: descriptor count
|
|
3335 <1>
|
|
3336 0000003B 678D0C49 <1> lea cx,[ecx+ecx*2] ; CX *= 3
|
|
3337 <1>
|
|
3338 0000003F 8E6624 <1> mov fs,P_ES
|
|
3339 00000042 8B7600 <1> mov si,P_DI
|
|
3340 00000045 BF[0000] <1> mov di,trackbuf
|
|
3341 00000048 57 <1> push di ; On stack: descriptor list address
|
|
3342 00000049 64F366A5 <1> fs rep movsd ; Copy the list
|
|
3343 <1>
|
|
3344 0000004D 668B4608 <1> mov eax,P_EBP
|
|
3345 00000051 66A3[6455] <1> mov [EntryPoint],eax ; CS:IP entry point
|
|
3346 00000055 668B7604 <1> mov esi,P_ESI
|
|
3347 00000059 668B5610 <1> mov edx,P_EBX
|
|
3348 0000005D 8B5E26 <1> mov bx,P_DS
|
|
3349 00000060 E9(1D11) <1> jmp replace_bootstrap
|
|
3350 <1> .error:
|
|
3351 00000063 F9 <1> stc
|
|
3352 00000064 C3 <1> ret
|
|
3353 <1>
|
|
3354 <1> ;
|
|
3355 <1> ; INT 22h AX=0013h Idle call
|
|
3356 <1> ;
|
|
3357 <1> comapi_idle:
|
|
3358 <1> DO_IDLE
|
|
3359 00000065 E8(F219) <2> call check_for_arp
|
|
3360 00000068 F8 <1> clc
|
|
3361 00000069 C3 <1> ret
|
|
3362 <1>
|
|
3363 <1> int21_table:
|
|
3364 <1> int21 00h, comboot_return
|
|
3365 0000006A 00 <2> db %1
|
|
3366 0000006B [500C] <2> dw %2
|
|
3367 <1> int21 01h, comboot_getkey
|
|
3368 0000006D 01 <2> db %1
|
|
3369 0000006E [CD0C] <2> dw %2
|
|
3370 <1> int21 02h, comboot_writechr
|
|
3371 00000070 02 <2> db %1
|
|
3372 00000071 [DB0C] <2> dw %2
|
|
3373 <1> int21 04h, comboot_writeserial
|
|
3374 00000073 04 <2> db %1
|
|
3375 00000074 [E30C] <2> dw %2
|
|
3376 <1> int21 08h, comboot_getkeynoecho
|
|
3377 00000076 08 <2> db %1
|
|
3378 00000077 [EB0C] <2> dw %2
|
|
3379 <1> int21 09h, comboot_writestr
|
|
3380 00000079 09 <2> db %1
|
|
3381 0000007A [F00C] <2> dw %2
|
|
3382 <1> int21 0Bh, comboot_checkkey
|
|
3383 0000007C 0B <2> db %1
|
|
3384 0000007D [030D] <2> dw %2
|
|
3385 <1> int21 30h, comboot_checkver
|
|
3386 0000007F 30 <2> db %1
|
|
3387 00000080 [170D] <2> dw %2
|
|
3388 <1> int21 4Ch, comboot_return
|
|
3389 00000082 4C <2> db %1
|
|
3390 00000083 [500C] <2> dw %2
|
|
3391 <1> int21 -1, comboot_bogus
|
|
3392 00000085 FF <2> db %1
|
|
3393 00000086 [A60C] <2> dw %2
|
|
3394 <1> int21_count equ ($-int21_table)/3
|
|
3395 <1>
|
|
3396 <1> align 2, db 0
|
|
3397 <1> int22_table:
|
|
3398 00000088 [810D] <1> dw comapi_err ; 0000 unimplemented syscall
|
|
3399 0000008A [830D] <1> dw comapi_get_version ; 0001 get SYSLINUX version
|
|
3400 0000008C [A40D] <1> dw comapi_writestr ; 0002 write string
|
|
3401 0000008E [AF0D] <1> dw comapi_run ; 0003 run specified command
|
|
3402 00000090 [C30D] <1> dw comapi_run_default ; 0004 run default command
|
|
3403 00000092 [C90D] <1> dw comapi_textmode ; 0005 force text mode
|
|
3404 00000094 [CE0D] <1> dw comapi_open ; 0006 open file
|
|
3405 00000096 [F50D] <1> dw comapi_read ; 0007 read file
|
|
3406 00000098 [0C0E] <1> dw comapi_close ; 0008 close file
|
|
3407 0000009A [0E0E] <1> dw comapi_pxecall ; 0009 call PXE stack
|
|
3408 0000009C [1F0E] <1> dw comapi_derinfo ; 000A derivative-specific info
|
|
3409 0000009E [430E] <1> dw comapi_serialcfg ; 000B get serial port config
|
|
3410 000000A0 [6A0E] <1> dw comapi_cleanup ; 000C perform final cleanup
|
|
3411 000000A2 [810E] <1> dw comapi_chainboot ; 000D clean up then bootstrap
|
|
3412 000000A4 [B00E] <1> dw comapi_configfile ; 000E get name of config file
|
|
3413 000000A6 [BA0E] <1> dw comapi_ipappend ; 000F get ipappend strings
|
|
3414 000000A8 [1A00] <1> dw comapi_dnsresolv ; 0010 resolve hostname
|
|
3415 000000AA [2800] <1> dw comapi_maxshuffle ; 0011 maximum shuffle descriptors
|
|
3416 000000AC [2E00] <1> dw comapi_shuffle ; 0012 cleanup, shuffle and boot
|
|
3417 000000AE [6500] <1> dw comapi_idle ; 0013 idle call
|
|
3418 <1> int22_count equ ($-int22_table)/2
|
|
3419 <1>
|
|
3420 000000B0 00 <1> APIKeyWait db 0
|
|
3421 000000B1 00 <1> APIKeyFlag db 0
|
|
3422 %include "com32.inc"
|
|
3423 <1> ;; $Id: com32.inc,v 1.9 2005/01/06 22:34:06 hpa Exp $
|
|
3424 <1> ;; -----------------------------------------------------------------------
|
|
3425 <1> ;;
|
|
3426 <1> ;; Copyright 1994-2003 H. Peter Anvin - All Rights Reserved
|
|
3427 <1> ;;
|
|
3428 <1> ;; This program is free software; you can redistribute it and/or modify
|
|
3429 <1> ;; it under the terms of the GNU General Public License as published by
|
|
3430 <1> ;; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
|
|
3431 <1> ;; Boston MA 02111-1307, USA; either version 2 of the License, or
|
|
3432 <1> ;; (at your option) any later version; incorporated herein by reference.
|
|
3433 <1> ;;
|
|
3434 <1> ;; -----------------------------------------------------------------------
|
|
3435 <1>
|
|
3436 <1> ;;
|
|
3437 <1> ;; com32.inc
|
|
3438 <1> ;;
|
|
3439 <1> ;; Common code for running a COM32 image
|
|
3440 <1> ;;
|
|
3441 <1>
|
|
3442 <1> ;
|
|
3443 <1> ; Load a COM32 image. A COM32 image is the 32-bit analogue to a DOS
|
|
3444 <1> ; .com file. A COM32 image is loaded at address 0x101000, with %esp
|
|
3445 <1> ; set to the high end of usable memory.
|
|
3446 <1> ;
|
|
3447 <1> ; A COM32 image should begin with the magic bytes:
|
|
3448 <1> ; B8 FF 4C CD 21, which is "mov eax,0x21cd4cff" in 32-bit mode and
|
|
3449 <1> ; "mov ax,0x4cff; int 0x21" in 16-bit mode. This will abort the
|
|
3450 <1> ; program with an error if run in 16-bit mode.
|
|
3451 <1> ;
|
|
3452 <1> pm_idt: equ 0x100000
|
|
3453 <1> pm_entry: equ 0x101000
|
|
3454 <1>
|
|
3455 <1> bits 16
|
|
3456 <1> section .data
|
|
3457 <1> align 2, db 0
|
|
3458 <1> com32_pmidt:
|
|
3459 000000B2 0008 <1> dw 8*256 ; Limit
|
|
3460 000000B4 00001000 <1> dd pm_idt ; Address
|
|
3461 <1>
|
|
3462 <1> com32_rmidt:
|
|
3463 000000B8 FFFF <1> dw 0ffffh ; Limit
|
|
3464 000000BA 00000000 <1> dd 0 ; Address
|
|
3465 <1>
|
|
3466 <1> section .text
|
|
3467 <1> is_com32_image:
|
|
3468 00000EC9 56 <1> push si ; Save file handle
|
|
3469 00000ECA 52 <1> push dx ; File length held in DX:AX
|
|
3470 00000ECB 50 <1> push ax
|
|
3471 <1>
|
|
3472 00000ECC E8E901 <1> call make_plain_cmdline
|
|
3473 <1> ; Copy the command line into the low cmdline buffer
|
|
3474 00000ECF B80040 <1> mov ax,real_mode_seg
|
|
3475 00000ED2 8EE0 <1> mov fs,ax
|
|
3476 00000ED4 BE0090 <1> mov si,cmd_line_here
|
|
3477 00000ED7 BF[D408] <1> mov di,command_line
|
|
3478 00000EDA 8B0E[EE00] <1> mov cx,[CmdLinePtr]
|
|
3479 00000EDE 41 <1> inc cx ; Include final null
|
|
3480 00000EDF 29F1 <1> sub cx,si
|
|
3481 00000EE1 64F3A4 <1> fs rep movsb
|
|
3482 <1>
|
|
3483 00000EE4 E8A415 <1> call highmemsize ; We need the high memory size...
|
|
3484 00000EE7 E86BFD <1> call comboot_setup_api ; Set up the COMBOOT-style API
|
|
3485 <1>
|
|
3486 00000EEA 66BF00101000 <1> mov edi,pm_entry ; Load address
|
|
3487 00000EF0 6658 <1> pop eax ; File length
|
|
3488 00000EF2 5E <1> pop si ; File handle
|
|
3489 00000EF3 31D2 <1> xor dx,dx ; No padding
|
|
3490 00000EF5 E8C312 <1> call load_high
|
|
3491 00000EF8 E84C0F <1> call crlf
|
|
3492 <1>
|
|
3493 <1> com32_start:
|
|
3494 00000EFB 66BB[440F0000] <1> mov ebx,com32_call_start ; Where to go in PM
|
|
3495 <1>
|
|
3496 <1> com32_enter_pm:
|
|
3497 00000F01 FA <1> cli
|
|
3498 00000F02 8CC8 <1> mov ax,cs
|
|
3499 00000F04 8ED8 <1> mov ds,ax
|
|
3500 00000F06 8926[6855] <1> mov [SavedSSSP],sp
|
|
3501 00000F0A 8C16[6A55] <1> mov [SavedSSSP+2],ss
|
|
3502 00000F0E FC <1> cld
|
|
3503 00000F0F E8(4B01) <1> call a20_test
|
|
3504 00000F12 7503 <1> jnz .a20ok
|
|
3505 00000F14 E8(CC00) <1> call enable_a20
|
|
3506 <1>
|
|
3507 <1> .a20ok:
|
|
3508 00000F17 0F0116[0000] <1> lgdt [bcopy_gdt] ; We can use the same GDT just fine
|
|
3509 00000F1C 0F011E[B200] <1> lidt [com32_pmidt] ; Set up the IDT
|
|
3510 00000F21 0F20C0 <1> mov eax,cr0
|
|
3511 00000F24 0C01 <1> or al,1
|
|
3512 00000F26 0F22C0 <1> mov cr0,eax ; Enter protected mode
|
|
3513 00000F29 EA[2E0F]2000 <1> jmp 20h:.in_pm
|
|
3514 <1>
|
|
3515 <1> bits 32
|
|
3516 <1> .in_pm:
|
|
3517 00000F2E 31C0 <1> xor eax,eax ; Available for future use...
|
|
3518 00000F30 8EE0 <1> mov fs,eax
|
|
3519 00000F32 8EE8 <1> mov gs,eax
|
|
3520 <1>
|
|
3521 00000F34 B028 <1> mov al,28h ; Set up data segments
|
|
3522 00000F36 8EC0 <1> mov es,eax
|
|
3523 00000F38 8ED8 <1> mov ds,eax
|
|
3524 00000F3A 8ED0 <1> mov ss,eax
|
|
3525 <1>
|
|
3526 00000F3C 8B25[A0080000] <1> mov esp,[PMESP] ; Load protmode %esp if available
|
|
3527 00000F42 FFE3 <1> jmp ebx ; Go to where we need to go
|
|
3528 <1>
|
|
3529 <1> ;
|
|
3530 <1> ; This is invoked right before the actually starting the COM32
|
|
3531 <1> ; progam, in 32-bit mode...
|
|
3532 <1> ;
|
|
3533 <1> com32_call_start:
|
|
3534 <1> ;
|
|
3535 <1> ; Point the stack to the end of high memory
|
|
3536 <1> ;
|
|
3537 00000F44 678B26[981F] <1> mov esp,[word HighMemSize]
|
|
3538 <1>
|
|
3539 <1> ;
|
|
3540 <1> ; Set up the protmode IDT and the interrupt jump buffers
|
|
3541 <1> ; We set these up in the system area at 0x100000,
|
|
3542 <1> ; but we could also put them beyond the stack.
|
|
3543 <1> ;
|
|
3544 00000F49 BF00001000 <1> mov edi,pm_idt
|
|
3545 <1>
|
|
3546 <1> ; Form an interrupt gate descriptor
|
|
3547 00000F4E B800082000 <1> mov eax,0x00200000+((pm_idt+8*256)&0x0000ffff)
|
|
3548 00000F53 BB00EE1000 <1> mov ebx,0x0000ee00+((pm_idt+8*256)&0xffff0000)
|
|
3549 00000F58 31C9 <1> xor ecx,ecx
|
|
3550 00000F5A FEC5 <1> inc ch ; ecx <- 256
|
|
3551 <1>
|
|
3552 00000F5C 51 <1> push ecx
|
|
3553 <1> .make_idt:
|
|
3554 00000F5D AB <1> stosd
|
|
3555 00000F5E 83C008 <1> add eax,8
|
|
3556 00000F61 93 <1> xchg eax,ebx
|
|
3557 00000F62 AB <1> stosd
|
|
3558 00000F63 93 <1> xchg eax,ebx
|
|
3559 00000F64 E2F7 <1> loop .make_idt
|
|
3560 <1>
|
|
3561 00000F66 59 <1> pop ecx
|
|
3562 <1>
|
|
3563 <1> ; Each entry in the interrupt jump buffer contains
|
|
3564 <1> ; the following instructions:
|
|
3565 <1> ;
|
|
3566 <1> ; 00000000 60 pushad
|
|
3567 <1> ; 00000001 B0xx mov al,<interrupt#>
|
|
3568 <1> ; 00000003 E9xxxxxxxx jmp com32_handle_interrupt
|
|
3569 <1>
|
|
3570 00000F67 B860B000E9 <1> mov eax,0e900b060h
|
|
3571 00000F6C BB[1B08F0FF] <1> mov ebx,com32_handle_interrupt-(pm_idt+8*256+8)
|
|
3572 <1>
|
|
3573 <1> .make_ijb:
|
|
3574 00000F71 AB <1> stosd
|
|
3575 00000F72 284FFE <1> sub [edi-2],cl ; Interrupt #
|
|
3576 00000F75 93 <1> xchg eax,ebx
|
|
3577 00000F76 AB <1> stosd
|
|
3578 00000F77 83E808 <1> sub eax,8
|
|
3579 00000F7A 93 <1> xchg eax,ebx
|
|
3580 00000F7B E2F4 <1> loop .make_ijb
|
|
3581 <1>
|
|
3582 <1> ; Now everything is set up for interrupts...
|
|
3583 <1>
|
|
3584 00000F7D 68[36100000] <1> push dword com32_farcall ; Farcall entry point
|
|
3585 00000F82 6800000100 <1> push dword (1 << 16) ; 64K bounce buffer
|
|
3586 00000F87 6800000400 <1> push dword (comboot_seg << 4) ; Bounce buffer address
|
|
3587 00000F8C 68[3E100000] <1> push dword com32_intcall ; Intcall entry point
|
|
3588 00000F91 68[D4080000] <1> push dword command_line ; Command line pointer
|
|
3589 00000F96 6A05 <1> push dword 5 ; Argument count
|
|
3590 00000F98 FB <1> sti ; Interrupts OK now
|
|
3591 00000F99 E8(00101000) <1> call pm_entry ; Run the program...
|
|
3592 <1> ; ... on return, fall through to com32_exit ...
|
|
3593 <1>
|
|
3594 <1> com32_exit:
|
|
3595 00000F9E 66BB[E30F] <1> mov bx,com32_done ; Return to command loop
|
|
3596 <1>
|
|
3597 <1> com32_enter_rm:
|
|
3598 00000FA2 FA <1> cli
|
|
3599 00000FA3 FC <1> cld
|
|
3600 00000FA4 8925[A0080000] <1> mov [PMESP],esp ; Save exit %esp
|
|
3601 00000FAA 31E4 <1> xor esp,esp ; Make sure the high bits are zero
|
|
3602 00000FAC EA[B30F0000]0800 <1> jmp 08h:.in_pm16 ; Return to 16-bit mode first
|
|
3603 <1>
|
|
3604 <1> bits 16
|
|
3605 <1> .in_pm16:
|
|
3606 00000FB3 B81800 <1> mov ax,18h ; Real-mode-like segment
|
|
3607 00000FB6 8EC0 <1> mov es,ax
|
|
3608 00000FB8 8ED8 <1> mov ds,ax
|
|
3609 00000FBA 8ED0 <1> mov ss,ax
|
|
3610 00000FBC 8EE0 <1> mov fs,ax
|
|
3611 00000FBE 8EE8 <1> mov gs,ax
|
|
3612 <1>
|
|
3613 00000FC0 0F011E[B800] <1> lidt [com32_rmidt] ; Real-mode IDT (rm needs no GDT)
|
|
3614 00000FC5 0F20C0 <1> mov eax,cr0
|
|
3615 00000FC8 24FE <1> and al,~1
|
|
3616 00000FCA 0F22C0 <1> mov cr0,eax
|
|
3617 00000FCD EA[D20F]0000 <1> jmp 0:.in_rm
|
|
3618 <1>
|
|
3619 <1> .in_rm: ; Back in real mode
|
|
3620 00000FD2 8CC8 <1> mov ax,cs ; Set up sane segments
|
|
3621 00000FD4 8ED8 <1> mov ds,ax
|
|
3622 00000FD6 8EC0 <1> mov es,ax
|
|
3623 00000FD8 8EE0 <1> mov fs,ax
|
|
3624 00000FDA 8EE8 <1> mov gs,ax
|
|
3625 00000FDC 0FB226[6855] <1> lss sp,[SavedSSSP] ; Restore stack
|
|
3626 00000FE1 FFE3 <1> jmp bx ; Go to whereever we need to go...
|
|
3627 <1>
|
|
3628 <1> com32_done:
|
|
3629 00000FE3 E8(6D01) <1> call disable_a20
|
|
3630 00000FE6 FB <1> sti
|
|
3631 00000FE7 E9CAF4 <1> jmp enter_command
|
|
3632 <1>
|
|
3633 <1> ;
|
|
3634 <1> ; 16-bit support code
|
|
3635 <1> ;
|
|
3636 <1> bits 16
|
|
3637 <1>
|
|
3638 <1> ;
|
|
3639 <1> ; 16-bit interrupt-handling code
|
|
3640 <1> ;
|
|
3641 <1> com32_int_rm:
|
|
3642 00000FEA 9C <1> pushf ; Flags on stack
|
|
3643 00000FEB 0E <1> push cs ; Return segment
|
|
3644 00000FEC 68[F20F] <1> push word .cont ; Return address
|
|
3645 00000FEF 6652 <1> push dword edx ; Segment:offset of IVT entry
|
|
3646 00000FF1 CB <1> retf ; Invoke IVT routine
|
|
3647 <1> .cont: ; ... on resume ...
|
|
3648 00000FF2 66BB[34100000] <1> mov ebx,com32_int_resume
|
|
3649 00000FF8 E906FF <1> jmp com32_enter_pm ; Go back to PM
|
|
3650 <1>
|
|
3651 <1> ;
|
|
3652 <1> ; 16-bit system call handling code
|
|
3653 <1> ;
|
|
3654 <1> com32_sys_rm:
|
|
3655 00000FFB 0FA9 <1> pop gs
|
|
3656 00000FFD 0FA1 <1> pop fs
|
|
3657 00000FFF 07 <1> pop es
|
|
3658 00001000 1F <1> pop ds
|
|
3659 00001001 6661 <1> popad
|
|
3660 00001003 669D <1> popfd
|
|
3661 00001005 2E8926[A408] <1> mov [cs:Com32SysSP],sp
|
|
3662 0000100A CB <1> retf ; Invoke routine
|
|
3663 <1> .return:
|
|
3664 <1> ; We clean up SP here because we don't know if the
|
|
3665 <1> ; routine returned with RET, RETF or IRET
|
|
3666 0000100B 2E8B26[A408] <1> mov sp,[cs:Com32SysSP]
|
|
3667 00001010 669C <1> pushfd
|
|
3668 00001012 6660 <1> pushad
|
|
3669 00001014 1E <1> push ds
|
|
3670 00001015 06 <1> push es
|
|
3671 00001016 0FA0 <1> push fs
|
|
3672 00001018 0FA8 <1> push gs
|
|
3673 0000101A 66BB[8E100000] <1> mov ebx,com32_sys_resume
|
|
3674 00001020 E9DEFE <1> jmp com32_enter_pm
|
|
3675 <1>
|
|
3676 <1> ;
|
|
3677 <1> ; 32-bit support code
|
|
3678 <1> ;
|
|
3679 <1> bits 32
|
|
3680 <1>
|
|
3681 <1> ;
|
|
3682 <1> ; This is invoked on getting an interrupt in protected mode. At
|
|
3683 <1> ; this point, we need to context-switch to real mode and invoke
|
|
3684 <1> ; the interrupt routine.
|
|
3685 <1> ;
|
|
3686 <1> ; When this gets invoked, the registers are saved on the stack and
|
|
3687 <1> ; AL contains the register number.
|
|
3688 <1> ;
|
|
3689 <1> com32_handle_interrupt:
|
|
3690 00001023 0FB6C0 <1> movzx eax,al
|
|
3691 00001026 31DB <1> xor ebx,ebx ; Actually makes the code smaller
|
|
3692 00001028 8B1483 <1> mov edx,[ebx+eax*4] ; Get the segment:offset of the routine
|
|
3693 0000102B 66BB[EA0F] <1> mov bx,com32_int_rm
|
|
3694 0000102F E96EFFFFFF <1> jmp com32_enter_rm ; Go to real mode
|
|
3695 <1>
|
|
3696 <1> com32_int_resume:
|
|
3697 00001034 61 <1> popad
|
|
3698 00001035 CF <1> iret
|
|
3699 <1>
|
|
3700 <1> ;
|
|
3701 <1> ; Intcall/farcall invocation. We manifest a structure on the real-mode stack,
|
|
3702 <1> ; containing the com32sys_t structure from <com32.h> as well as
|
|
3703 <1> ; the following entries (from low to high address):
|
|
3704 <1> ; - Target offset
|
|
3705 <1> ; - Target segment
|
|
3706 <1> ; - Return offset
|
|
3707 <1> ; - Return segment (== real mode cs == 0)
|
|
3708 <1> ; - Return flags
|
|
3709 <1> ;
|
|
3710 <1> com32_farcall:
|
|
3711 00001036 9C <1> pushfd ; Save IF among other things...
|
|
3712 00001037 60 <1> pushad ; We only need to save some, but...
|
|
3713 <1>
|
|
3714 00001038 8B442428 <1> mov eax,[esp+10*4] ; CS:IP
|
|
3715 0000103C EB0E <1> jmp com32_syscall
|
|
3716 <1>
|
|
3717 <1>
|
|
3718 <1> com32_intcall:
|
|
3719 0000103E 9C <1> pushfd ; Save IF among other things...
|
|
3720 0000103F 60 <1> pushad ; We only need to save some, but...
|
|
3721 <1>
|
|
3722 00001040 0FB6442428 <1> movzx eax,byte [esp+10*4] ; INT number
|
|
3723 00001045 8B048500000000 <1> mov eax,[eax*4] ; Get CS:IP from low memory
|
|
3724 <1>
|
|
3725 <1> com32_syscall:
|
|
3726 0000104C FC <1> cld
|
|
3727 <1>
|
|
3728 0000104D 670FB73E[6855] <1> movzx edi,word [word SavedSSSP]
|
|
3729 00001053 670FB71E[6A55] <1> movzx ebx,word [word SavedSSSP+2]
|
|
3730 00001059 83EF36 <1> sub edi,54 ; Allocate 54 bytes
|
|
3731 0000105C 6667893E[6855] <1> mov [word SavedSSSP],di
|
|
3732 00001062 C1E304 <1> shl ebx,4
|
|
3733 00001065 01DF <1> add edi,ebx ; Create linear address
|
|
3734 <1>
|
|
3735 00001067 8B74242C <1> mov esi,[esp+11*4] ; Source regs
|
|
3736 0000106B 31C9 <1> xor ecx,ecx
|
|
3737 0000106D B10B <1> mov cl,11 ; 44 bytes to copy
|
|
3738 0000106F F3A5 <1> rep movsd
|
|
3739 <1>
|
|
3740 <1> ; EAX is already set up to be CS:IP
|
|
3741 00001071 AB <1> stosd ; Save in stack frame
|
|
3742 00001072 B8[0B100000] <1> mov eax,com32_sys_rm.return ; Return seg:offs
|
|
3743 00001077 AB <1> stosd ; Save in stack frame
|
|
3744 00001078 8B47F4 <1> mov eax,[edi-12] ; Return flags
|
|
3745 0000107B 25D70C2000 <1> and eax,0x200cd7 ; Mask (potentially) unsafe flags
|
|
3746 00001080 8947F4 <1> mov [edi-12],eax ; Primary flags entry
|
|
3747 00001083 66AB <1> stosw ; Return flags
|
|
3748 <1>
|
|
3749 00001085 66BB[FB0F] <1> mov bx,com32_sys_rm
|
|
3750 00001089 E914FFFFFF <1> jmp com32_enter_rm ; Go to real mode
|
|
3751 <1>
|
|
3752 <1> ; On return, the 44-byte return structure is on the
|
|
3753 <1> ; real-mode stack, plus the 10 additional bytes used
|
|
3754 <1> ; by the target address (see above.)
|
|
3755 <1> com32_sys_resume:
|
|
3756 0000108E 670FB736[6855] <1> movzx esi,word [word SavedSSSP]
|
|
3757 00001094 670FB706[6A55] <1> movzx eax,word [word SavedSSSP+2]
|
|
3758 0000109A 8B7C2430 <1> mov edi,[esp+12*4] ; Dest regs
|
|
3759 0000109E C1E004 <1> shl eax,4
|
|
3760 000010A1 01C6 <1> add esi,eax ; Create linear address
|
|
3761 000010A3 21FF <1> and edi,edi ; NULL pointer?
|
|
3762 000010A5 7502 <1> jnz .do_copy
|
|
3763 000010A7 89F7 <1> .no_copy: mov edi,esi ; Do a dummy copy-to-self
|
|
3764 000010A9 31C9 <1> .do_copy: xor ecx,ecx
|
|
3765 000010AB B10B <1> mov cl,11 ; 44 bytes
|
|
3766 000010AD F3A5 <1> rep movsd ; Copy register block
|
|
3767 <1>
|
|
3768 000010AF 678306[6855]36 <1> add dword [word SavedSSSP],54 ; Remove from stack
|
|
3769 <1>
|
|
3770 000010B5 61 <1> popad
|
|
3771 000010B6 9D <1> popfd
|
|
3772 000010B7 C3 <1> ret ; Return to 32-bit program
|
|
3773 <1>
|
|
3774 <1> bits 16
|
|
3775 <1>
|
|
3776 <1> section .bss
|
|
3777 0000089F <res 00000001> <1> alignb 4
|
|
3778 000008A0 <res 00000004> <1> PMESP resd 1 ; Protected-mode ESP
|
|
3779 000008A4 <res 00000002> <1> Com32SysSP resw 1 ; SP saved during COM32 syscall
|
|
3780 <1>
|
|
3781 <1> section .text
|
|
3782 %include "cmdline.inc"
|
|
3783 <1> ;; $Id: cmdline.inc,v 1.2 2004/12/14 22:46:24 hpa Exp $
|
|
3784 <1> ;; -----------------------------------------------------------------------
|
|
3785 <1> ;;
|
|
3786 <1> ;; Copyright 2003 H. Peter Anvin - All Rights Reserved
|
|
3787 <1> ;;
|
|
3788 <1> ;; This program is free software; you can redistribute it and/or modify
|
|
3789 <1> ;; it under the terms of the GNU General Public License as published by
|
|
3790 <1> ;; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
|
|
3791 <1> ;; Boston MA 02111-1307, USA; either version 2 of the License, or
|
|
3792 <1> ;; (at your option) any later version; incorporated herein by reference.
|
|
3793 <1> ;;
|
|
3794 <1> ;; -----------------------------------------------------------------------
|
|
3795 <1>
|
|
3796 <1> ;;
|
|
3797 <1> ;; cmdline.inc
|
|
3798 <1> ;;
|
|
3799 <1> ;; Common routine to assemble [null-terminated] command line into
|
|
3800 <1> ;; real_mode_seg:cmd_line_here.
|
|
3801 <1> ;; Not used by plain kernel due to BOOT_IMAGE= etc.
|
|
3802 <1> ;;
|
|
3803 <1>
|
|
3804 <1> ;
|
|
3805 <1> ; Assumes DS == CS
|
|
3806 <1> make_plain_cmdline:
|
|
3807 000010B8 06 <1> push es
|
|
3808 <1> ; ui.inc has already copied the actual command line
|
|
3809 000010B9 B80040 <1> mov ax,real_mode_seg
|
|
3810 000010BC 8EC0 <1> mov es,ax
|
|
3811 <1>
|
|
3812 000010BE 8B36[8208] <1> mov si,[CmdOptPtr]
|
|
3813 000010C2 8B3E[EE00] <1> mov di,[CmdLinePtr]
|
|
3814 <1>
|
|
3815 000010C6 AC <1> .loop: lodsb
|
|
3816 000010C7 AA <1> stosb
|
|
3817 000010C8 20C0 <1> and al,al
|
|
3818 000010CA 75FA <1> jnz .loop
|
|
3819 <1>
|
|
3820 000010CC 4F <1> dec di
|
|
3821 000010CD 893E[EE00] <1> mov [CmdLinePtr],di
|
|
3822 <1>
|
|
3823 000010D1 07 <1> pop es
|
|
3824 000010D2 C3 <1> ret
|
|
3825 <1>
|
|
3826 <1>
|
|
3827
|
|
3828 ;
|
|
3829 ; Boot sector loading code
|
|
3830 ;
|
|
3831 %include "bootsect.inc"
|
|
3832 <1> ;; $Id: bootsect.inc,v 1.15 2005/01/12 00:34:54 hpa Exp $
|
|
3833 <1> ;; -----------------------------------------------------------------------
|
|
3834 <1> ;;
|
|
3835 <1> ;; Copyright 1994-2005 H. Peter Anvin - All Rights Reserved
|
|
3836 <1> ;;
|
|
3837 <1> ;; This program is free software; you can redistribute it and/or modify
|
|
3838 <1> ;; it under the terms of the GNU General Public License as published by
|
|
3839 <1> ;; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
|
|
3840 <1> ;; Boston MA 02111-1307, USA; either version 2 of the License, or
|
|
3841 <1> ;; (at your option) any later version; incorporated herein by reference.
|
|
3842 <1> ;;
|
|
3843 <1> ;; -----------------------------------------------------------------------
|
|
3844 <1>
|
|
3845 <1> ;;
|
|
3846 <1> ;; bootsect.inc
|
|
3847 <1> ;;
|
|
3848 <1> ;; Load a boot sector (or other bootstrap program.)
|
|
3849 <1> ;;
|
|
3850 <1> ;; Unlike previous versions of this software, this doesn't require that
|
|
3851 <1> ;; the length is 512 bytes. This allows PXE bootstraps and WinNT
|
|
3852 <1> ;; "CD boot sectors" to be invoked.
|
|
3853 <1> ;;
|
|
3854 <1>
|
|
3855 <1> ;
|
|
3856 <1> ; Load a boot sector
|
|
3857 <1> ;
|
|
3858 <1> is_bootsector:
|
|
3859 <1> %if IS_SYSLINUX || IS_MDSLINUX
|
|
3860 <1> ; Transfer zero bytes
|
|
3861 <1> mov byte [CopySuper],0
|
|
3862 <1> jmp short load_bootsec
|
|
3863 <1>
|
|
3864 <1> is_bss_sector:
|
|
3865 <1> ; Transfer the superblock
|
|
3866 <1> mov byte [CopySuper],superblock_len
|
|
3867 <1> %endif
|
|
3868 <1> load_bootsec:
|
|
3869 000010D3 92 <1> xchg dx,ax
|
|
3870 000010D4 66C1E010 <1> shl eax,16
|
|
3871 000010D8 92 <1> xchg dx,ax ; Now EAX = file length
|
|
3872 000010D9 66BF00001000 <1> mov edi, 100000h
|
|
3873 000010DF 66893E[0400] <1> mov [trackbuf+4],edi ; Copy from this address
|
|
3874 000010E4 6657 <1> push edi ; Save load address
|
|
3875 000010E6 31D2 <1> xor dx,dx ; No padding
|
|
3876 000010E8 E8D010 <1> call load_high
|
|
3877 000010EB E8590D <1> call crlf
|
|
3878 <1>
|
|
3879 000010EE 6681EF00001000 <1> sub edi,100000h
|
|
3880 000010F5 66893E[0800] <1> mov [trackbuf+8],edi ; Save length
|
|
3881 <1>
|
|
3882 000010FA 66B8007C0000 <1> mov eax,7C00h ; Entry point
|
|
3883 00001100 66A3[0000] <1> mov [trackbuf],eax ; Copy to this address
|
|
3884 00001104 66A3[6455] <1> mov [EntryPoint],eax ; Jump to this address when done
|
|
3885 <1>
|
|
3886 <1> %if IS_SYSLINUX || IS_MDSLINUX
|
|
3887 <1> movzx ecx,byte [CopySuper]
|
|
3888 <1> jcxz .not_bss
|
|
3889 <1>
|
|
3890 <1> ; For a BSS boot sector we have to patch.
|
|
3891 <1> mov esi,superblock
|
|
3892 <1> mov edi,100000h+(superblock-bootsec)
|
|
3893 <1> call bcopy
|
|
3894 <1>
|
|
3895 <1> .not_bss:
|
|
3896 <1> %endif
|
|
3897 <1>
|
|
3898 00001108 6631D2 <1> xor edx,edx
|
|
3899 0000110B 6631F6 <1> xor esi,esi
|
|
3900 <1> %if IS_SYSLINUX || IS_MDSLINUX || IS_EXTLINUX
|
|
3901 <1> ; Restore original FDC table
|
|
3902 <1> mov eax,[OrigFDCTabPtr]
|
|
3903 <1> mov [fdctab],eax
|
|
3904 <1>
|
|
3905 <1> mov dl,[DriveNumber]
|
|
3906 <1> mov si,PartInfo ; Partition info buffer
|
|
3907 <1> mov di,800h-18 ; Put partition info here
|
|
3908 <1> push di
|
|
3909 <1> mov cx,8 ; 16 bytes
|
|
3910 <1> xor ax,ax
|
|
3911 <1> rep movsw
|
|
3912 <1> pop si ; DS:SI points to partition info
|
|
3913 <1> %elif IS_ISOLINUX
|
|
3914 <1> mov dl,[DriveNo]
|
|
3915 <1> %elif IS_PXELINUX
|
|
3916 0000110E C606[A608]01 <1> mov byte [KeepPXE],1 ; Chainloading another NBP
|
|
3917 00001113 E8CF06 <1> call reset_pxe
|
|
3918 <1> %endif
|
|
3919 00001116 31DB <1> xor bx,bx
|
|
3920 <1>
|
|
3921 <1> ;
|
|
3922 <1> ; replace_bootstrap for the special case where we have exactly one
|
|
3923 <1> ; descriptor, and it's the first entry in the trackbuf
|
|
3924 <1> ;
|
|
3925 <1>
|
|
3926 <1> replace_bootstrap_one:
|
|
3927 00001118 68[0000] <1> push word trackbuf ; Address of descriptor list
|
|
3928 0000111B 6A01 <1> push word 1 ; Length of descriptor list
|
|
3929 <1> ; Fall through
|
|
3930 <1>
|
|
3931 <1> ;
|
|
3932 <1> ; Entrypoint for "shut down and replace bootstrap" -- also invoked by
|
|
3933 <1> ; the COMBOOT API. This routine expects two words on the stack:
|
|
3934 <1> ; address of the copy list (versus DS) and count. Additionally,
|
|
3935 <1> ; the values of ESI and EDX are passed on to the new bootstrap;
|
|
3936 <1> ; the value of BX becomes the new DS.
|
|
3937 <1> ;
|
|
3938 <1> replace_bootstrap:
|
|
3939 <1> ;
|
|
3940 <1> ; Prepare for shutting down
|
|
3941 <1> ;
|
|
3942 0000111D E82513 <1> call vgaclearmode
|
|
3943 <1>
|
|
3944 <1> ;
|
|
3945 <1> ; Set up initial stack frame (not used by PXE if keeppxe is
|
|
3946 <1> ; set - we use the PXE stack then.)
|
|
3947 <1> ; AFTER THIS POINT ONLY .earlybss IS AVAILABLE, NOT .bss
|
|
3948 <1> ;
|
|
3949 00001120 31C0 <1> xor ax,ax
|
|
3950 00001122 8ED8 <1> mov ds,ax
|
|
3951 00001124 8EC0 <1> mov es,ax
|
|
3952 <1>
|
|
3953 <1> %if IS_PXELINUX
|
|
3954 00001126 F606[A608]01 <1> test byte [KeepPXE],01h
|
|
3955 0000112B 7406 <1> jz .stdstack
|
|
3956 0000112D C43E[6047] <1> les di,[InitStack] ; Reset stack to PXE original
|
|
3957 00001131 EB0A <1> jmp .stackok
|
|
3958 <1> %endif
|
|
3959 <1> .stdstack:
|
|
3960 00001133 BFD47B <1> mov di,7C00h-44
|
|
3961 00001136 57 <1> push di
|
|
3962 00001137 B91600 <1> mov cx,22 ; 44 bytes
|
|
3963 0000113A F3AB <1> rep stosw
|
|
3964 0000113C 5F <1> pop di
|
|
3965 <1> .stackok:
|
|
3966 <1>
|
|
3967 0000113D 266689551C <1> mov [es:di+28],edx
|
|
3968 00001142 266689750C <1> mov [es:di+12],esi
|
|
3969 00001147 26895D06 <1> mov [es:di+6],bx
|
|
3970 <1>
|
|
3971 0000114B 58 <1> pop ax ; Copy list count
|
|
3972 0000114C 5B <1> pop bx ; Copy from...
|
|
3973 <1>
|
|
3974 0000114D FA <1> cli
|
|
3975 0000114E 8CC1 <1> mov cx,es
|
|
3976 00001150 8ED1 <1> mov ss,cx
|
|
3977 00001152 660FB7E7 <1> movzx esp,di
|
|
3978 <1>
|
|
3979 00001156 E9(CD01) <1> jmp shuffle_and_boot
|
|
3980 <1>
|
|
3981 <1> %if IS_SYSLINUX || IS_MDSLINUX
|
|
3982 <1> ; Nothing
|
|
3983 <1> %else
|
|
3984 <1> is_bss_sector:
|
|
3985 00001159 BE[BB03] <1> mov si,err_bssimage
|
|
3986 0000115C E8F50C <1> call cwritestr
|
|
3987 0000115F E952F3 <1> jmp enter_command
|
|
3988 <1> %endif
|
|
3989
|
|
3990 ;
|
|
3991 ; Boot to the local disk by returning the appropriate PXE magic.
|
|
3992 ; AX contains the appropriate return code.
|
|
3993 ;
|
|
3994 local_boot:
|
|
3995 00001162 8CCE mov si,cs
|
|
3996 00001164 8EDE mov ds,si ; Restore DI
|
|
3997 00001166 660FB226[A008] lss esp,[BaseStack]
|
|
3998 0000116C A3[0E00] mov [LocalBootType],ax
|
|
3999 0000116F E8D312 call vgaclearmode
|
|
4000 00001172 BE[7C06] mov si,localboot_msg
|
|
4001 00001175 E8DC0C call writestr
|
|
4002 ; Restore the environment we were called with
|
|
4003 00001178 0FB226[6047] lss sp,[InitStack]
|
|
4004 0000117D 0FA9 pop gs
|
|
4005 0000117F 0FA1 pop fs
|
|
4006 00001181 07 pop es
|
|
4007 00001182 1F pop ds
|
|
4008 00001183 6661 popad
|
|
4009 00001185 2EA1[0E00] mov ax,[cs:LocalBootType]
|
|
4010 00001189 669D popfd
|
|
4011 0000118B CB retf ; Return to PXE
|
|
4012
|
|
4013 ;
|
|
4014 ; abort_check: let the user abort with <ESC> or <Ctrl-C>
|
|
4015 ;
|
|
4016 abort_check:
|
|
4017 0000118C E84D0C call pollchar
|
|
4018 0000118F 7423 jz ac_ret1
|
|
4019 00001191 60 pusha
|
|
4020 00001192 E8710C call getchar
|
|
4021 00001195 3C1B cmp al,27 ; <ESC>
|
|
4022 00001197 7404 je ac_kill
|
|
4023 00001199 3C03 cmp al,3 ; <Ctrl-C>
|
|
4024 0000119B 7516 jne ac_ret2
|
|
4025 0000119D BE[D706] ac_kill: mov si,aborted_msg
|
|
4026
|
|
4027 ;
|
|
4028 ; abort_load: Called by various routines which wants to print a fatal
|
|
4029 ; error message and return to the command prompt. Since this
|
|
4030 ; may happen at just about any stage of the boot process, assume
|
|
4031 ; our state is messed up, and just reset the segment registers
|
|
4032 ; and the stack forcibly.
|
|
4033 ;
|
|
4034 ; SI = offset (in _text) of error message to print
|
|
4035 ;
|
|
4036 abort_load:
|
|
4037 000011A0 8CC8 mov ax,cs ; Restore CS = DS = ES
|
|
4038 000011A2 8ED8 mov ds,ax
|
|
4039 000011A4 8EC0 mov es,ax
|
|
4040 000011A6 660FB226[A008] lss esp,[BaseStack]
|
|
4041 000011AC FB sti
|
|
4042 000011AD E8A40C call cwritestr ; Expects SI -> error msg
|
|
4043 000011B0 E901F3 al_ok: jmp enter_command ; Return to command prompt
|
|
4044 ;
|
|
4045 ; End of abort_check
|
|
4046 ;
|
|
4047 000011B3 61 ac_ret2: popa
|
|
4048 000011B4 C3 ac_ret1: ret
|
|
4049
|
|
4050
|
|
4051 ;
|
|
4052 ; kaboom: write a message and bail out. Wait for quite a while,
|
|
4053 ; or a user keypress, then do a hard reboot.
|
|
4054 ;
|
|
4055 kaboom:
|
|
4056 000011B5 8CC8 mov ax,cs
|
|
4057 000011B7 8EC0 mov es,ax
|
|
4058 000011B9 8ED8 mov ds,ax
|
|
4059 000011BB 660FB226[A008] lss esp,[BaseStack]
|
|
4060 000011C1 FB sti
|
|
4061 000011C2 BE[F403] .patch: mov si,bailmsg
|
|
4062 000011C5 E88C0C call writestr ; Returns with AL = 0
|
|
4063 000011C8 E8110C .drain: call pollchar
|
|
4064 000011CB 7405 jz .drained
|
|
4065 000011CD E8360C call getchar
|
|
4066 000011D0 EBF6 jmp short .drain
|
|
4067 .drained:
|
|
4068 000011D2 668B3E[0000] mov edi,[RebootTime]
|
|
4069 000011D7 A0[0909] mov al,[DHCPMagic]
|
|
4070 000011DA 2409 and al,09h ; Magic+Timeout
|
|
4071 000011DC 3C09 cmp al,09h
|
|
4072 000011DE 7406 je .time_set
|
|
4073 000011E0 66BF2C010000 mov edi,REBOOT_TIME
|
|
4074 .time_set:
|
|
4075 000011E6 B91200 mov cx,18
|
|
4076 000011E9 51 .wait1: push cx
|
|
4077 000011EA 6689F9 mov ecx,edi
|
|
4078 000011ED 8B166C04 .wait2: mov dx,[BIOS_timer]
|
|
4079 000011F1 E8E80B .wait3: call pollchar
|
|
4080 000011F4 7511 jnz .keypress
|
|
4081 000011F6 3B166C04 cmp dx,[BIOS_timer]
|
|
4082 000011FA 74F5 je .wait3
|
|
4083 000011FC 67E2EE loop .wait2,ecx
|
|
4084 000011FF B02E mov al,'.'
|
|
4085 00001201 E88113 call writechr
|
|
4086 00001204 59 pop cx
|
|
4087 00001205 E2E2 loop .wait1
|
|
4088 .keypress:
|
|
4089 00001207 E83D0C call crlf
|
|
4090 0000120A C70672040000 mov word [BIOS_magic],0 ; Cold reboot
|
|
4091 00001210 EAF0FF00F0 jmp 0F000h:0FFF0h ; Reset vector address
|
|
4092
|
|
4093 ;
|
|
4094 ; memory_scan_for_pxe_struct:
|
|
4095 ;
|
|
4096 ; If none of the standard methods find the !PXE structure, look for it
|
|
4097 ; by scanning memory.
|
|
4098 ;
|
|
4099 ; On exit, if found:
|
|
4100 ; CF = 0, ES:BX -> !PXE structure
|
|
4101 ; Otherwise CF = 1, all registers saved
|
|
4102 ;
|
|
4103 memory_scan_for_pxe_struct:
|
|
4104 00001215 1E push ds
|
|
4105 00001216 60 pusha
|
|
4106 00001217 8CC8 mov ax,cs
|
|
4107 00001219 8ED8 mov ds,ax
|
|
4108 0000121B BE[7005] mov si,trymempxe_msg
|
|
4109 0000121E E8330C call writestr
|
|
4110 00001221 A11304 mov ax,[BIOS_fbm] ; Starting segment
|
|
4111 00001224 C1E006 shl ax,(10-4) ; Kilobytes -> paragraphs
|
|
4112 ; mov ax,01000h ; Start to look here
|
|
4113 00001227 48 dec ax ; To skip inc ax
|
|
4114 .mismatch:
|
|
4115 00001228 40 inc ax
|
|
4116 00001229 3D00A0 cmp ax,0A000h ; End of memory
|
|
4117 0000122C 7346 jae .not_found
|
|
4118 0000122E E8430C call writehex4
|
|
4119 00001231 BE[D206] mov si,fourbs_msg
|
|
4120 00001234 E81D0C call writestr
|
|
4121 00001237 8EC0 mov es,ax
|
|
4122 00001239 26668B160000 mov edx,[es:0]
|
|
4123 0000123F 6681FA21505845 cmp edx,'!PXE'
|
|
4124 00001246 75E0 jne .mismatch
|
|
4125 00001248 260FB60E0400 movzx cx,byte [es:4] ; Length of structure
|
|
4126 0000124E 80F908 cmp cl,08h ; Minimum length
|
|
4127 00001251 72D5 jb .mismatch
|
|
4128 00001253 50 push ax
|
|
4129 00001254 31C0 xor ax,ax
|
|
4130 00001256 31F6 xor si,si
|
|
4131 00001258 26AC .checksum: es lodsb
|
|
4132 0000125A 00C4 add ah,al
|
|
4133 0000125C E2FA loop .checksum
|
|
4134 0000125E 58 pop ax
|
|
4135 0000125F 75C7 jnz .mismatch ; Checksum must == 0
|
|
4136 00001261 89E5 .found: mov bp,sp
|
|
4137 00001263 31DB xor bx,bx
|
|
4138 00001265 895E08 mov [bp+8],bx ; Save BX into stack frame (will be == 0)
|
|
4139 00001268 8CC0 mov ax,es
|
|
4140 0000126A E8070C call writehex4
|
|
4141 0000126D E8D70B call crlf
|
|
4142 00001270 61 popa
|
|
4143 00001271 1F pop ds
|
|
4144 00001272 F8 clc
|
|
4145 00001273 C3 ret
|
|
4146 00001274 BE[4706] .not_found: mov si,notfound_msg
|
|
4147 00001277 E8DA0B call writestr
|
|
4148 0000127A 61 popa
|
|
4149 0000127B 1F pop ds
|
|
4150 0000127C F9 stc
|
|
4151 0000127D C3 ret
|
|
4152
|
|
4153 ;
|
|
4154 ; memory_scan_for_pxenv_struct:
|
|
4155 ;
|
|
4156 ; If none of the standard methods find the PXENV+ structure, look for it
|
|
4157 ; by scanning memory.
|
|
4158 ;
|
|
4159 ; On exit, if found:
|
|
4160 ; CF = 0, ES:BX -> PXENV+ structure
|
|
4161 ; Otherwise CF = 1, all registers saved
|
|
4162 ;
|
|
4163 memory_scan_for_pxenv_struct:
|
|
4164 0000127E 60 pusha
|
|
4165 0000127F BE[9705] mov si,trymempxenv_msg
|
|
4166 00001282 E8CF0B call writestr
|
|
4167 ; mov ax,[BIOS_fbm] ; Starting segment
|
|
4168 ; shl ax,(10-4) ; Kilobytes -> paragraphs
|
|
4169 00001285 B80010 mov ax,01000h ; Start to look here
|
|
4170 00001288 48 dec ax ; To skip inc ax
|
|
4171 .mismatch:
|
|
4172 00001289 40 inc ax
|
|
4173 0000128A 3D00A0 cmp ax,0A000h ; End of memory
|
|
4174 0000128D 7344 jae .not_found
|
|
4175 0000128F 8EC0 mov es,ax
|
|
4176 00001291 26668B160000 mov edx,[es:0]
|
|
4177 00001297 6681FA5058454E cmp edx,'PXEN'
|
|
4178 0000129E 75E9 jne .mismatch
|
|
4179 000012A0 268B160400 mov dx,[es:4]
|
|
4180 000012A5 81FA562B cmp dx,'V+'
|
|
4181 000012A9 75DE jne .mismatch
|
|
4182 000012AB 260FB60E0800 movzx cx,byte [es:8] ; Length of structure
|
|
4183 000012B1 80F926 cmp cl,26h ; Minimum length
|
|
4184 000012B4 72D3 jb .mismatch
|
|
4185 000012B6 31C0 xor ax,ax
|
|
4186 000012B8 31F6 xor si,si
|
|
4187 000012BA 26AC .checksum: es lodsb
|
|
4188 000012BC 00C4 add ah,al
|
|
4189 000012BE E2FA loop .checksum
|
|
4190 000012C0 20E4 and ah,ah
|
|
4191 000012C2 75C5 jnz .mismatch ; Checksum must == 0
|
|
4192 000012C4 89E5 .found: mov bp,sp
|
|
4193 000012C6 895E08 mov [bp+8],bx ; Save BX into stack frame
|
|
4194 000012C9 89D8 mov ax,bx
|
|
4195 000012CB E8A60B call writehex4
|
|
4196 000012CE E8760B call crlf
|
|
4197 000012D1 F8 clc
|
|
4198 000012D2 C3 ret
|
|
4199 000012D3 BE[4706] .not_found: mov si,notfound_msg
|
|
4200 000012D6 E87B0B call writestr
|
|
4201 000012D9 6661 popad
|
|
4202 000012DB F9 stc
|
|
4203 000012DC C3 ret
|
|
4204
|
|
4205 ;
|
|
4206 ; searchdir:
|
|
4207 ;
|
|
4208 ; Open a TFTP connection to the server
|
|
4209 ;
|
|
4210 ; On entry:
|
|
4211 ; DS:DI = mangled filename
|
|
4212 ; If successful:
|
|
4213 ; ZF clear
|
|
4214 ; SI = socket pointer
|
|
4215 ; DX:AX = file length in bytes
|
|
4216 ; If unsuccessful
|
|
4217 ; ZF set
|
|
4218 ;
|
|
4219
|
|
4220 searchdir:
|
|
4221 000012DD 06 push es
|
|
4222 000012DE 8CD8 mov ax,ds
|
|
4223 000012E0 8EC0 mov es,ax
|
|
4224 000012E2 89FE mov si,di
|
|
4225 000012E4 55 push bp
|
|
4226 000012E5 89E5 mov bp,sp
|
|
4227
|
|
4228 000012E7 E8DB01 call allocate_socket
|
|
4229 000012EA 0F84CF01 jz .error
|
|
4230
|
|
4231 000012EE B80600 mov ax,PKT_RETRY ; Retry counter
|
|
4232 000012F1 C706[1000]0C00 mov word [PktTimeout],PKT_TIMEOUT ; Initial timeout
|
|
4233
|
|
4234 000012F7 50 .sendreq: push ax ; [bp-2] - Retry counter
|
|
4235 000012F8 56 push si ; [bp-4] - File name
|
|
4236
|
|
4237 000012F9 BF[8000] mov di,packet_buf
|
|
4238 000012FC 893E[8608] mov [pxe_udp_write_pkt.buffer],di
|
|
4239
|
|
4240 00001300 B80001 mov ax,TFTP_RRQ ; TFTP opcode
|
|
4241 00001303 AB stosw
|
|
4242
|
|
4243 00001304 66AD lodsd ; EAX <- server override (if any)
|
|
4244 00001306 6621C0 and eax,eax
|
|
4245 00001309 750D jnz .noprefix ; No prefix, and we have the server
|
|
4246
|
|
4247 0000130B 56 push si ; Add common prefix
|
|
4248 0000130C BE[0046] mov si,PathPrefix
|
|
4249 0000130F E86A12 call strcpy
|
|
4250 00001312 4F dec di
|
|
4251 00001313 5E pop si
|
|
4252
|
|
4253 00001314 66A1[F008] mov eax,[ServerIP] ; Get default server
|
|
4254
|
|
4255 .noprefix:
|
|
4256 00001318 E86112 call strcpy ; Filename
|
|
4257
|
|
4258 0000131B 66894704 mov [bx+tftp_remoteip],eax
|
|
4259
|
|
4260 0000131F 53 push bx ; [bp-6] - TFTP block
|
|
4261 00001320 8B1F mov bx,[bx]
|
|
4262 00001322 53 push bx ; [bp-8] - TID (local port no)
|
|
4263
|
|
4264 00001323 C606[7608]00 mov [pxe_udp_write_pkt.status],byte 0
|
|
4265 00001328 66A3[7808] mov [pxe_udp_write_pkt.sip],eax
|
|
4266 ; Now figure out the gateway
|
|
4267 0000132C 663306[EC08] xor eax,[MyIP]
|
|
4268 00001331 662306[F408] and eax,[Netmask]
|
|
4269 00001336 7404 jz .nogwneeded
|
|
4270 00001338 66A1[F808] mov eax,[Gateway]
|
|
4271 .nogwneeded:
|
|
4272 0000133C 66A3[7C08] mov [pxe_udp_write_pkt.gip],eax
|
|
4273 00001340 891E[8008] mov [pxe_udp_write_pkt.lport],bx
|
|
4274 00001344 A1[FC08] mov ax,[ServerPort]
|
|
4275 00001347 A3[8208] mov [pxe_udp_write_pkt.rport],ax
|
|
4276 0000134A BE[A708] mov si,tftp_tail
|
|
4277 0000134D B91B00 mov cx,tftp_tail_len
|
|
4278 00001350 F3A4 rep movsb
|
|
4279 00001352 81EF[8000] sub di,packet_buf ; Get packet size
|
|
4280 00001356 893E[8408] mov [pxe_udp_write_pkt.buffersize],di
|
|
4281
|
|
4282 0000135A BF[7608] mov di,pxe_udp_write_pkt
|
|
4283 0000135D BB3300 mov bx,PXENV_UDP_WRITE
|
|
4284 00001360 E84402 call pxenv
|
|
4285 00001363 0F824D01 jc .failure
|
|
4286 00001367 833E[7608]00 cmp word [pxe_udp_write_pkt.status],byte 0
|
|
4287 0000136C 0F854401 jne .failure
|
|
4288
|
|
4289 ;
|
|
4290 ; Danger, Will Robinson! We need to support timeout
|
|
4291 ; and retry lest we just lost a packet...
|
|
4292 ;
|
|
4293
|
|
4294 ; Packet transmitted OK, now we need to receive
|
|
4295 00001370 FF36[1000] .getpacket: push word [PktTimeout] ; [bp-10]
|
|
4296 00001374 FF366C04 push word [BIOS_timer] ; [bp-12]
|
|
4297
|
|
4298 00001378 8B5EF8 .pkt_loop: mov bx,[bp-8] ; TID
|
|
4299 0000137B BF[8000] mov di,packet_buf
|
|
4300 0000137E C706[8A08]0000 mov word [pxe_udp_read_pkt.status],0
|
|
4301 00001384 893E[9A08] mov [pxe_udp_read_pkt.buffer],di
|
|
4302 00001388 8C1E[9C08] mov [pxe_udp_read_pkt.buffer+2],ds
|
|
4303 0000138C C706[9808]0008 mov word [pxe_udp_read_pkt.buffersize],packet_buf_size
|
|
4304 00001392 66A1[EC08] mov eax,[MyIP]
|
|
4305 00001396 66A3[9008] mov [pxe_udp_read_pkt.dip],eax
|
|
4306 0000139A 891E[9608] mov [pxe_udp_read_pkt.lport],bx
|
|
4307 0000139E BF[8A08] mov di,pxe_udp_read_pkt
|
|
4308 000013A1 BB3200 mov bx,PXENV_UDP_READ
|
|
4309 000013A4 E80002 call pxenv
|
|
4310 000013A7 21C0 and ax,ax
|
|
4311 000013A9 741A jz .got_packet ; Wait for packet
|
|
4312 .no_packet:
|
|
4313 000013AB 8B166C04 mov dx,[BIOS_timer]
|
|
4314 000013AF 3B56F4 cmp dx,[bp-12]
|
|
4315 000013B2 74C4 je .pkt_loop
|
|
4316 000013B4 8956F4 mov [bp-12],dx
|
|
4317 000013B7 FF4EF6 dec word [bp-10] ; Timeout
|
|
4318 000013BA 75BC jnz .pkt_loop
|
|
4319 000013BC 58 pop ax ; Adjust stack
|
|
4320 000013BD 58 pop ax
|
|
4321 000013BE D126[1000] shl word [PktTimeout],1 ; Exponential backoff
|
|
4322 000013C2 E9EF00 jmp .failure
|
|
4323
|
|
4324 .got_packet:
|
|
4325 000013C5 8B76FA mov si,[bp-6] ; TFTP pointer
|
|
4326 000013C8 8B5EF8 mov bx,[bp-8] ; TID
|
|
4327
|
|
4328 000013CB 668B4404 mov eax,[si+tftp_remoteip]
|
|
4329 000013CF 663906[8C08] cmp [pxe_udp_read_pkt.sip],eax ; This is technically not to the TFTP spec?
|
|
4330 000013D4 75D5 jne .no_packet
|
|
4331
|
|
4332 ; Got packet - reset timeout
|
|
4333 000013D6 C706[1000]0C00 mov word [PktTimeout],PKT_TIMEOUT
|
|
4334
|
|
4335 000013DC 58 pop ax ; Adjust stack
|
|
4336 000013DD 58 pop ax
|
|
4337
|
|
4338 000013DE A1[9408] mov ax,[pxe_udp_read_pkt.rport]
|
|
4339 000013E1 894402 mov [si+tftp_remoteport],ax
|
|
4340
|
|
4341 ; filesize <- -1 == unknown
|
|
4342 000013E4 66C7440CFFFFFFFF mov dword [si+tftp_filesize], -1
|
|
4343 ; Default blksize unless blksize option negotiated
|
|
4344 000013EC C744100002 mov word [si+tftp_blksize], TFTP_BLOCKSIZE
|
|
4345
|
|
4346 000013F1 8B0E[9808] mov cx,[pxe_udp_read_pkt.buffersize]
|
|
4347 000013F5 83E902 sub cx,2 ; CX <- bytes after opcode
|
|
4348 000013F8 0F82B800 jb .failure ; Garbled reply
|
|
4349
|
|
4350 000013FC BE[8000] mov si,packet_buf
|
|
4351 000013FF AD lodsw
|
|
4352
|
|
4353 00001400 3D0005 cmp ax, TFTP_ERROR
|
|
4354 00001403 0F84A800 je .bailnow ; ERROR reply: don't try again
|
|
4355
|
|
4356 00001407 3D0006 cmp ax, TFTP_OACK
|
|
4357 0000140A 757C jne .no_tsize
|
|
4358
|
|
4359 ; Now we need to parse the OACK packet to get the transfer
|
|
4360 ; size. SI -> first byte of options; CX -> byte count
|
|
4361 .parse_oack:
|
|
4362 0000140C E37A jcxz .no_tsize ; No options acked
|
|
4363 .get_opt_name:
|
|
4364 0000140E 89F7 mov di,si
|
|
4365 00001410 89F3 mov bx,si
|
|
4366 00001412 AC .opt_name_loop: lodsb
|
|
4367 00001413 20C0 and al,al
|
|
4368 00001415 7407 jz .got_opt_name
|
|
4369 00001417 0C20 or al,20h ; Convert to lowercase
|
|
4370 00001419 AA stosb
|
|
4371 0000141A E2F6 loop .opt_name_loop
|
|
4372 ; We ran out, and no final null
|
|
4373 0000141C EB6A jmp .err_reply
|
|
4374 .got_opt_name: ; si -> option value
|
|
4375 0000141E 49 dec cx ; bytes left in pkt
|
|
4376 0000141F 7467 jz .err_reply ; Option w/o value
|
|
4377
|
|
4378 ; Parse option pointed to by bx; guaranteed to be
|
|
4379 ; null-terminated.
|
|
4380 00001421 51 push cx
|
|
4381 00001422 56 push si
|
|
4382 00001423 89DE mov si,bx ; -> option name
|
|
4383 00001425 BB[C208] mov bx,tftp_opt_table
|
|
4384 00001428 B90200 mov cx,tftp_opts
|
|
4385 .opt_loop:
|
|
4386 0000142B 51 push cx
|
|
4387 0000142C 56 push si
|
|
4388 0000142D 8B3F mov di,[bx] ; Option pointer
|
|
4389 0000142F 8B4F02 mov cx,[bx+2] ; Option len
|
|
4390 00001432 F3A6 repe cmpsb
|
|
4391 00001434 5E pop si
|
|
4392 00001435 59 pop cx
|
|
4393 00001436 7409 je .get_value ; OK, known option
|
|
4394 00001438 83C306 add bx,6
|
|
4395 0000143B E2EE loop .opt_loop
|
|
4396
|
|
4397 0000143D 5E pop si
|
|
4398 0000143E 59 pop cx
|
|
4399 0000143F EB47 jmp .err_reply ; Non-negotiated option returned
|
|
4400
|
|
4401 00001441 5E .get_value: pop si ; si -> option value
|
|
4402 00001442 59 pop cx ; cx -> bytes left in pkt
|
|
4403 00001443 8B5F04 mov bx,[bx+4] ; Pointer to data target
|
|
4404 00001446 035EFA add bx,[bp-6] ; TFTP socket pointer
|
|
4405 00001449 6631C0 xor eax,eax
|
|
4406 0000144C 6631D2 xor edx,edx
|
|
4407 0000144F AC .value_loop: lodsb
|
|
4408 00001450 20C0 and al,al
|
|
4409 00001452 7414 jz .got_value
|
|
4410 00001454 2C30 sub al,'0'
|
|
4411 00001456 3C09 cmp al, 9
|
|
4412 00001458 772E ja .err_reply ; Not a decimal digit
|
|
4413 0000145A 666BD20A imul edx,10
|
|
4414 0000145E 6601C2 add edx,eax
|
|
4415 00001461 668917 mov [bx],edx
|
|
4416 00001464 E2E9 loop .value_loop
|
|
4417 ; Ran out before final null, accept anyway
|
|
4418 00001466 EB03 jmp short .done_pkt
|
|
4419
|
|
4420 .got_value:
|
|
4421 00001468 49 dec cx
|
|
4422 00001469 75A3 jnz .get_opt_name ; Not end of packet
|
|
4423
|
|
4424 ; ZF == 1
|
|
4425
|
|
4426 ; Success, done!
|
|
4427 .done_pkt:
|
|
4428 0000146B 5E pop si ; Junk
|
|
4429 0000146C 5E pop si ; We want the packet ptr in SI
|
|
4430
|
|
4431 0000146D 668B440C mov eax,[si+tftp_filesize]
|
|
4432 00001471 6683F8FF cmp eax,-1
|
|
4433 00001475 7411 jz .no_tsize
|
|
4434 00001477 6689C2 mov edx,eax
|
|
4435 0000147A 66C1EA10 shr edx,16 ; DX:AX == EAX
|
|
4436
|
|
4437 0000147E 6621C0 and eax,eax ; Set ZF depending on file size
|
|
4438 00001481 5D pop bp ; Junk
|
|
4439 00001482 5D pop bp ; Junk (retry counter)
|
|
4440 00001483 743A jz .error_si ; ZF = 1 need to free the socket
|
|
4441 00001485 5D pop bp
|
|
4442 00001486 07 pop es
|
|
4443 00001487 C3 ret
|
|
4444
|
|
4445 .no_tsize:
|
|
4446 .err_reply: ; Option negotiation error. Send ERROR reply.
|
|
4447 ; ServerIP and gateway are already programmed in
|
|
4448 00001488 8B76FA mov si,[bp-6]
|
|
4449 0000148B 8B4402 mov ax,[si+tftp_remoteport]
|
|
4450 0000148E A3[8208] mov word [pxe_udp_write_pkt.rport],ax
|
|
4451 00001491 C706[8608][CE08] mov word [pxe_udp_write_pkt.buffer],tftp_opt_err
|
|
4452 00001497 C706[8408]1A00 mov word [pxe_udp_write_pkt.buffersize],tftp_opt_err_len
|
|
4453 0000149D BF[7608] mov di,pxe_udp_write_pkt
|
|
4454 000014A0 BB3300 mov bx,PXENV_UDP_WRITE
|
|
4455 000014A3 E80101 call pxenv
|
|
4456
|
|
4457 ; Write an error message and explode
|
|
4458 000014A6 BE[9A04] mov si,err_oldtftp
|
|
4459 000014A9 E8A809 call writestr
|
|
4460 000014AC E906FD jmp kaboom
|
|
4461
|
|
4462 000014AF C746FE0100 .bailnow: mov word [bp-2],1 ; Immediate error - no retry
|
|
4463
|
|
4464 000014B4 5B .failure: pop bx ; Junk
|
|
4465 000014B5 5B pop bx
|
|
4466 000014B6 5E pop si
|
|
4467 000014B7 58 pop ax
|
|
4468 000014B8 48 dec ax ; Retry counter
|
|
4469 000014B9 0F853AFE jnz .sendreq ; Try again
|
|
4470
|
|
4471 000014BD 89DE .error: mov si,bx ; Socket pointer
|
|
4472 .error_si: ; Socket pointer already in SI
|
|
4473 000014BF E83000 call free_socket ; ZF <- 1, SI <- 0
|
|
4474 000014C2 5D pop bp
|
|
4475 000014C3 07 pop es
|
|
4476 000014C4 C3 ret
|
|
4477
|
|
4478 ;
|
|
4479 ; allocate_socket: Allocate a local UDP port structure
|
|
4480 ;
|
|
4481 ; If successful:
|
|
4482 ; ZF set
|
|
4483 ; BX = socket pointer
|
|
4484 ; If unsuccessful:
|
|
4485 ; ZF clear
|
|
4486 ;
|
|
4487 allocate_socket:
|
|
4488 000014C5 51 push cx
|
|
4489 000014C6 BB[0040] mov bx,Files
|
|
4490 000014C9 B92000 mov cx,MAX_OPEN
|
|
4491 000014CC 833F00 .check: cmp word [bx], byte 0
|
|
4492 000014CF 7409 je .found
|
|
4493 000014D1 83C320 add bx,open_file_t_size
|
|
4494 000014D4 E2F6 loop .check
|
|
4495 000014D6 31C9 xor cx,cx ; ZF = 1
|
|
4496 000014D8 59 pop cx
|
|
4497 000014D9 C3 ret
|
|
4498 ; Allocate a socket number. Socket numbers are made
|
|
4499 ; guaranteed unique by including the socket slot number
|
|
4500 ; (inverted, because we use the loop counter cx); add a
|
|
4501 ; counter value to keep the numbers from being likely to
|
|
4502 ; get immediately reused.
|
|
4503 ;
|
|
4504 ; The NextSocket variable also contains the top two bits
|
|
4505 ; set. This generates a value in the range 49152 to
|
|
4506 ; 57343.
|
|
4507 .found:
|
|
4508 000014DA 49 dec cx
|
|
4509 000014DB 50 push ax
|
|
4510 000014DC A1[A408] mov ax,[NextSocket]
|
|
4511 000014DF 40 inc ax
|
|
4512 000014E0 25FFC0 and ax,((1 << (13-MAX_OPEN_LG2))-1) | 0xC000
|
|
4513 000014E3 A3[A408] mov [NextSocket],ax
|
|
4514 000014E6 C1E108 shl cx,13-MAX_OPEN_LG2
|
|
4515 000014E9 01C1 add cx,ax ; ZF = 0
|
|
4516 000014EB 86E9 xchg ch,cl ; Convert to network byte order
|
|
4517 000014ED 890F mov [bx],cx ; Socket in use
|
|
4518 000014EF 58 pop ax
|
|
4519 000014F0 59 pop cx
|
|
4520 000014F1 C3 ret
|
|
4521
|
|
4522 ;
|
|
4523 ; Free socket: socket in SI; return SI = 0, ZF = 1 for convenience
|
|
4524 ;
|
|
4525 free_socket:
|
|
4526 000014F2 06 push es
|
|
4527 000014F3 60 pusha
|
|
4528 000014F4 31C0 xor ax,ax
|
|
4529 000014F6 8EC0 mov es,ax
|
|
4530 000014F8 89F7 mov di,si
|
|
4531 000014FA B90F00 mov cx,tftp_pktbuf >> 1 ; tftp_pktbuf is not cleared
|
|
4532 000014FD F3AB rep stosw
|
|
4533 000014FF 61 popa
|
|
4534 00001500 07 pop es
|
|
4535 00001501 31F6 xor si,si
|
|
4536 00001503 C3 ret
|
|
4537
|
|
4538 ;
|
|
4539 ; parse_dotquad:
|
|
4540 ; Read a dot-quad pathname in DS:SI and output an IP
|
|
4541 ; address in EAX, with SI pointing to the first
|
|
4542 ; nonmatching character.
|
|
4543 ;
|
|
4544 ; Return CF=1 on error.
|
|
4545 ;
|
|
4546 parse_dotquad:
|
|
4547 00001504 51 push cx
|
|
4548 00001505 B90400 mov cx,4
|
|
4549 00001508 6631C0 xor eax,eax
|
|
4550 .parseloop:
|
|
4551 0000150B 88E5 mov ch,ah
|
|
4552 0000150D 88C4 mov ah,al
|
|
4553 0000150F AC lodsb
|
|
4554 00001510 2C30 sub al,'0'
|
|
4555 00001512 720A jb .notnumeric
|
|
4556 00001514 3C09 cmp al,9
|
|
4557 00001516 7706 ja .notnumeric
|
|
4558 00001518 D50A aad ; AL += 10 * AH; AH = 0;
|
|
4559 0000151A 86E5 xchg ah,ch
|
|
4560 0000151C EBED jmp .parseloop
|
|
4561 .notnumeric:
|
|
4562 0000151E 3CFE cmp al,'.'-'0'
|
|
4563 00001520 9C pushf
|
|
4564 00001521 88E0 mov al,ah
|
|
4565 00001523 88EC mov ah,ch
|
|
4566 00001525 30ED xor ch,ch
|
|
4567 00001527 66C1C808 ror eax,8
|
|
4568 0000152B 9D popf
|
|
4569 0000152C 7504 jne .error
|
|
4570 0000152E E2DB loop .parseloop
|
|
4571 00001530 EB06 jmp .done
|
|
4572 .error:
|
|
4573 00001532 E203 loop .realerror ; If CX := 1 then we're done
|
|
4574 00001534 F8 clc
|
|
4575 00001535 EB01 jmp .done
|
|
4576 .realerror:
|
|
4577 00001537 F9 stc
|
|
4578 .done:
|
|
4579 00001538 4E dec si ; CF unchanged!
|
|
4580 00001539 59 pop cx
|
|
4581 0000153A C3 ret
|
|
4582 ;
|
|
4583 ; mangle_name: Mangle a filename pointed to by DS:SI into a buffer pointed
|
|
4584 ; to by ES:DI; ends on encountering any whitespace.
|
|
4585 ;
|
|
4586 ; This verifies that a filename is < FILENAME_MAX characters
|
|
4587 ; and doesn't contain whitespace, and zero-pads the output buffer,
|
|
4588 ; so "repe cmpsb" can do a compare.
|
|
4589 ;
|
|
4590 ; The first four bytes of the manged name is the IP address of
|
|
4591 ; the download host.
|
|
4592 ;
|
|
4593 mangle_name:
|
|
4594 0000153B 56 push si
|
|
4595 0000153C 66A1[F008] mov eax,[ServerIP]
|
|
4596 00001540 803C00 cmp byte [si],0
|
|
4597 00001543 742F je .noip ; Null filename?!?!
|
|
4598 00001545 813C3A3A cmp word [si],'::' ; Leading ::?
|
|
4599 00001549 742F je .gotprefix
|
|
4600
|
|
4601 .more:
|
|
4602 0000154B 46 inc si
|
|
4603 0000154C 803C00 cmp byte [si],0
|
|
4604 0000154F 7423 je .noip
|
|
4605 00001551 813C3A3A cmp word [si],'::'
|
|
4606 00001555 75F4 jne .more
|
|
4607
|
|
4608 ; We have a :: prefix of some sort, it could be either
|
|
4609 ; a DNS name or a dot-quad IP address. Try the dot-quad
|
|
4610 ; first...
|
|
4611 .here:
|
|
4612 00001557 5E pop si
|
|
4613 00001558 56 push si
|
|
4614 00001559 E8A8FF call parse_dotquad
|
|
4615 0000155C 7206 jc .notdq
|
|
4616 0000155E 813C3A3A cmp word [si],'::'
|
|
4617 00001562 7416 je .gotprefix
|
|
4618 .notdq:
|
|
4619 00001564 5E pop si
|
|
4620 00001565 56 push si
|
|
4621 00001566 E8E610 call dns_resolv
|
|
4622 00001569 813C3A3A cmp word [si],'::'
|
|
4623 0000156D 7505 jne .noip
|
|
4624 0000156F 6621C0 and eax,eax
|
|
4625 00001572 7506 jnz .gotprefix
|
|
4626
|
|
4627 .noip:
|
|
4628 00001574 5E pop si
|
|
4629 00001575 6631C0 xor eax,eax
|
|
4630 00001578 EB03 jmp .prefix_done
|
|
4631
|
|
4632 .gotprefix:
|
|
4633 0000157A 59 pop cx ; Adjust stack
|
|
4634 0000157B 46 inc si ; Skip double colon
|
|
4635 0000157C 46 inc si
|
|
4636
|
|
4637 .prefix_done:
|
|
4638 0000157D 66AB stosd ; Save IP address prefix
|
|
4639 0000157F B97B00 mov cx,FILENAME_MAX-5
|
|
4640
|
|
4641 .mn_loop:
|
|
4642 00001582 AC lodsb
|
|
4643 00001583 3C20 cmp al,' ' ; If control or space, end
|
|
4644 00001585 7603 jna .mn_end
|
|
4645 00001587 AA stosb
|
|
4646 00001588 E2F8 loop .mn_loop
|
|
4647 .mn_end:
|
|
4648 0000158A 41 inc cx ; At least one null byte
|
|
4649 0000158B 31C0 xor ax,ax ; Zero-fill name
|
|
4650 0000158D F3AA rep stosb ; Doesn't do anything if CX=0
|
|
4651 0000158F C3 ret ; Done
|
|
4652
|
|
4653 ;
|
|
4654 ; unmangle_name: Does the opposite of mangle_name; converts a DOS-mangled
|
|
4655 ; filename to the conventional representation. This is needed
|
|
4656 ; for the BOOT_IMAGE= parameter for the kernel.
|
|
4657 ; NOTE: A 13-byte buffer is mandatory, even if the string is
|
|
4658 ; known to be shorter.
|
|
4659 ;
|
|
4660 ; DS:SI -> input mangled file name
|
|
4661 ; ES:DI -> output buffer
|
|
4662 ;
|
|
4663 ; On return, DI points to the first byte after the output name,
|
|
4664 ; which is set to a null byte.
|
|
4665 ;
|
|
4666 unmangle_name:
|
|
4667 00001590 6650 push eax
|
|
4668 00001592 66AD lodsd
|
|
4669 00001594 6621C0 and eax,eax
|
|
4670 00001597 7407 jz .noip
|
|
4671 00001599 E85702 call gendotquad
|
|
4672 0000159C B83A3A mov ax,'::'
|
|
4673 0000159F AB stosw
|
|
4674 .noip:
|
|
4675 000015A0 E8D90F call strcpy
|
|
4676 000015A3 4F dec di ; Point to final null byte
|
|
4677 000015A4 6658 pop eax
|
|
4678 000015A6 C3 ret
|
|
4679
|
|
4680 ;
|
|
4681 ; pxenv
|
|
4682 ;
|
|
4683 ; This is the main PXENV+/!PXE entry point, using the PXENV+
|
|
4684 ; calling convention. This is a separate local routine so
|
|
4685 ; we can hook special things from it if necessary.
|
|
4686 ;
|
|
4687
|
|
4688 pxenv:
|
|
4689 000015A7 9A[AE15]0000 .jump: call 0:pxe_thunk ; Default to calling the thunk
|
|
4690 000015AC FC cld ; Make sure DF <- 0
|
|
4691 000015AD C3 ret
|
|
4692
|
|
4693 ; Must be after function def due to NASM bug
|
|
4694 PXENVEntry equ pxenv.jump+1
|
|
4695
|
|
4696 ;
|
|
4697 ; pxe_thunk
|
|
4698 ;
|
|
4699 ; Convert from the PXENV+ calling convention (BX, ES, DI) to the !PXE
|
|
4700 ; calling convention (using the stack.)
|
|
4701 ;
|
|
4702 ; This is called as a far routine so that we can just stick it into
|
|
4703 ; the PXENVEntry variable.
|
|
4704 ;
|
|
4705 000015AE 06 pxe_thunk: push es
|
|
4706 000015AF 57 push di
|
|
4707 000015B0 53 push bx
|
|
4708 000015B1 9A00000000 .jump: call 0:0
|
|
4709 000015B6 83C406 add sp,byte 6
|
|
4710 000015B9 83F801 cmp ax,byte 1
|
|
4711 000015BC F5 cmc ; Set CF unless ax == 0
|
|
4712 000015BD CB retf
|
|
4713
|
|
4714 ; Must be after function def due to NASM bug
|
|
4715 PXEEntry equ pxe_thunk.jump+1
|
|
4716
|
|
4717 ;
|
|
4718 ; getfssec: Get multiple clusters from a file, given the starting cluster.
|
|
4719 ;
|
|
4720 ; In this case, get multiple blocks from a specific TCP connection.
|
|
4721 ;
|
|
4722 ; On entry:
|
|
4723 ; ES:BX -> Buffer
|
|
4724 ; SI -> TFTP socket pointer
|
|
4725 ; CX -> 512-byte block count; 0FFFFh = until end of file
|
|
4726 ; On exit:
|
|
4727 ; SI -> TFTP socket pointer (or 0 on EOF)
|
|
4728 ; CF = 1 -> Hit EOF
|
|
4729 ;
|
|
4730 000015BE 56 getfssec: push si
|
|
4731 000015BF 0FA0 push fs
|
|
4732 000015C1 89DF mov di,bx
|
|
4733 000015C3 89F3 mov bx,si
|
|
4734 000015C5 B80010 mov ax,pktbuf_seg
|
|
4735 000015C8 8EE0 mov fs,ax
|
|
4736
|
|
4737 000015CA 660FB7C9 movzx ecx,cx
|
|
4738 000015CE 66C1E109 shl ecx,TFTP_BLOCKSIZE_LG2 ; Convert to bytes
|
|
4739 000015D2 7426 jz .hit_eof ; Nothing to do?
|
|
4740
|
|
4741 .need_more:
|
|
4742 000015D4 6651 push ecx
|
|
4743
|
|
4744 000015D6 660FB74714 movzx eax,word [bx+tftp_bytesleft]
|
|
4745 000015DB 6639C1 cmp ecx,eax
|
|
4746 000015DE 7605 jna .ok_size
|
|
4747 000015E0 6689C1 mov ecx,eax
|
|
4748 000015E3 E32C jcxz .need_packet ; No bytes available?
|
|
4749 .ok_size:
|
|
4750
|
|
4751 000015E5 89C8 mov ax,cx ; EAX<31:16> == ECX<31:16> == 0
|
|
4752 000015E7 8B7718 mov si,[bx+tftp_dataptr]
|
|
4753 000015EA 294F14 sub [bx+tftp_bytesleft],cx
|
|
4754 000015ED 64F3A4 fs rep movsb ; Copy from packet buffer
|
|
4755 000015F0 897718 mov [bx+tftp_dataptr],si
|
|
4756
|
|
4757 000015F3 6659 pop ecx
|
|
4758 000015F5 6629C1 sub ecx,eax
|
|
4759 000015F8 75DA jnz .need_more
|
|
4760
|
|
4761
|
|
4762 .hit_eof:
|
|
4763 000015FA 0FA1 pop fs
|
|
4764 000015FC 5E pop si
|
|
4765
|
|
4766 ; Is there anything left of this?
|
|
4767 000015FD 668B440C mov eax,[si+tftp_filesize]
|
|
4768 00001601 662B4408 sub eax,[si+tftp_filepos]
|
|
4769 00001605 7509 jnz .bytes_left ; CF <- 0
|
|
4770
|
|
4771 00001607 394414 cmp [si+tftp_bytesleft],ax
|
|
4772 0000160A 7504 jnz .bytes_left ; CF <- 0
|
|
4773
|
|
4774 ; The socket is closed and the buffer drained
|
|
4775 ; Close socket structure and re-init for next user
|
|
4776 0000160C E8E3FE call free_socket
|
|
4777 0000160F F9 stc
|
|
4778 .bytes_left:
|
|
4779 00001610 C3 ret
|
|
4780
|
|
4781 ;
|
|
4782 ; No data in buffer, check to see if we can get a packet...
|
|
4783 ;
|
|
4784 .need_packet:
|
|
4785 00001611 6659 pop ecx
|
|
4786 00001613 668B470C mov eax,[bx+tftp_filesize]
|
|
4787 00001617 663B4708 cmp eax,[bx+tftp_filepos]
|
|
4788 0000161B 74DD je .hit_eof ; Already EOF'd; socket already closed
|
|
4789
|
|
4790 0000161D 6660 pushad
|
|
4791 0000161F 06 push es
|
|
4792 00001620 89DE mov si,bx
|
|
4793 00001622 E80500 call get_packet
|
|
4794 00001625 07 pop es
|
|
4795 00001626 6661 popad
|
|
4796
|
|
4797 00001628 EBAA jmp .need_more
|
|
4798
|
|
4799 ;
|
|
4800 ; Get a fresh packet; expects fs -> pktbuf_seg and ds:si -> socket structure
|
|
4801 ;
|
|
4802 get_packet:
|
|
4803 0000162A 8CD8 mov ax,ds
|
|
4804 0000162C 8EC0 mov es,ax
|
|
4805
|
|
4806 .packet_loop:
|
|
4807 ; Start by ACKing the previous packet; this should cause the
|
|
4808 ; next packet to be sent.
|
|
4809 0000162E B90600 mov cx,PKT_RETRY
|
|
4810 00001631 C706[1000]0C00 mov word [PktTimeout],PKT_TIMEOUT
|
|
4811
|
|
4812 00001637 51 .send_ack: push cx ; <D> Retry count
|
|
4813
|
|
4814 00001638 8B4416 mov ax,[si+tftp_lastpkt]
|
|
4815 0000163B E8C400 call ack_packet ; Send ACK
|
|
4816
|
|
4817 ; We used to test the error code here, but sometimes
|
|
4818 ; PXE would return negative status even though we really
|
|
4819 ; did send the ACK. Now, just treat a failed send as
|
|
4820 ; a normally lost packet, and let it time out in due
|
|
4821 ; course of events.
|
|
4822
|
|
4823 .send_ok: ; Now wait for packet.
|
|
4824 0000163E 8B166C04 mov dx,[BIOS_timer] ; Get current time
|
|
4825
|
|
4826 00001642 8B0E[1000] mov cx,[PktTimeout]
|
|
4827 00001646 51 .wait_data: push cx ; <E> Timeout
|
|
4828 00001647 52 push dx ; <F> Old time
|
|
4829
|
|
4830 00001648 8B5C1E mov bx,[si+tftp_pktbuf]
|
|
4831 0000164B 891E[9A08] mov [pxe_udp_read_pkt.buffer],bx
|
|
4832 0000164F 8C26[9C08] mov [pxe_udp_read_pkt.buffer+2],fs
|
|
4833 00001653 C706[9808]0008 mov [pxe_udp_read_pkt.buffersize],word PKTBUF_SIZE
|
|
4834 00001659 668B4404 mov eax,[si+tftp_remoteip]
|
|
4835 0000165D 66A3[8C08] mov [pxe_udp_read_pkt.sip],eax
|
|
4836 00001661 66A1[EC08] mov eax,[MyIP]
|
|
4837 00001665 66A3[9008] mov [pxe_udp_read_pkt.dip],eax
|
|
4838 00001669 8B4402 mov ax,[si+tftp_remoteport]
|
|
4839 0000166C A3[9408] mov [pxe_udp_read_pkt.rport],ax
|
|
4840 0000166F 8B04 mov ax,[si+tftp_localport]
|
|
4841 00001671 A3[9608] mov [pxe_udp_read_pkt.lport],ax
|
|
4842 00001674 BF[8A08] mov di,pxe_udp_read_pkt
|
|
4843 00001677 BB3200 mov bx,PXENV_UDP_READ
|
|
4844 0000167A 56 push si ; <G>
|
|
4845 0000167B E829FF call pxenv
|
|
4846 0000167E 5E pop si ; <G>
|
|
4847 0000167F 21C0 and ax,ax
|
|
4848 00001681 7416 jz .recv_ok
|
|
4849
|
|
4850 ; No packet, or receive failure
|
|
4851 00001683 8B166C04 mov dx,[BIOS_timer]
|
|
4852 00001687 58 pop ax ; <F> Old time
|
|
4853 00001688 59 pop cx ; <E> Timeout
|
|
4854 00001689 39D0 cmp ax,dx ; Same time -> don't advance timeout
|
|
4855 0000168B 74B9 je .wait_data ; Same clock tick
|
|
4856 0000168D E2B7 loop .wait_data ; Decrease timeout
|
|
4857
|
|
4858 0000168F 59 pop cx ; <D> Didn't get any, send another ACK
|
|
4859 00001690 D126[1000] shl word [PktTimeout],1 ; Exponential backoff
|
|
4860 00001694 E2A1 loop .send_ack
|
|
4861 00001696 E91CFB jmp kaboom ; Forget it...
|
|
4862
|
|
4863 00001699 5A .recv_ok: pop dx ; <F>
|
|
4864 0000169A 59 pop cx ; <E>
|
|
4865
|
|
4866 0000169B 833E[9808]04 cmp word [pxe_udp_read_pkt.buffersize],byte 4
|
|
4867 000016A0 72A4 jb .wait_data ; Bad size for a DATA packet
|
|
4868
|
|
4869 000016A2 8B5C1E mov bx,[si+tftp_pktbuf]
|
|
4870 000016A5 64813F0003 cmp word [fs:bx],TFTP_DATA ; Not a data packet?
|
|
4871 000016AA 759A jne .wait_data ; Then wait for something else
|
|
4872
|
|
4873 000016AC 8B4416 mov ax,[si+tftp_lastpkt]
|
|
4874 000016AF 86E0 xchg ah,al ; Host byte order
|
|
4875 000016B1 40 inc ax ; Which packet are we waiting for?
|
|
4876 000016B2 86E0 xchg ah,al ; Network byte order
|
|
4877 000016B4 64394702 cmp [fs:bx+2],ax
|
|
4878 000016B8 740A je .right_packet
|
|
4879
|
|
4880 ; Wrong packet, ACK the packet and then try again
|
|
4881 ; This is presumably because the ACK got lost,
|
|
4882 ; so the server just resent the previous packet
|
|
4883 000016BA 648B4702 mov ax,[fs:bx+2]
|
|
4884 000016BE E84100 call ack_packet
|
|
4885 000016C1 E97AFF jmp .send_ok ; Reset timeout
|
|
4886
|
|
4887 .right_packet: ; It's the packet we want. We're also EOF if the size < blocksize
|
|
4888
|
|
4889 000016C4 59 pop cx ; <D> Don't need the retry count anymore
|
|
4890
|
|
4891 000016C5 894416 mov [si+tftp_lastpkt],ax ; Update last packet number
|
|
4892
|
|
4893 000016C8 660FB70E[9808] movzx ecx,word [pxe_udp_read_pkt.buffersize]
|
|
4894 000016CE 83E904 sub cx,byte 4 ; Skip TFTP header
|
|
4895
|
|
4896 ; If this is a zero-length block, don't mess with the pointers,
|
|
4897 ; since we may have just set up the previous block that way
|
|
4898 000016D1 741F jz .last_block
|
|
4899
|
|
4900 ; Set pointer to data block
|
|
4901 000016D3 8D4704 lea ax,[bx+4] ; Data past TFTP header
|
|
4902 000016D6 894418 mov [si+tftp_dataptr],ax
|
|
4903
|
|
4904 000016D9 66014C08 add [si+tftp_filepos],ecx
|
|
4905 000016DD 894C14 mov [si+tftp_bytesleft],cx
|
|
4906
|
|
4907 000016E0 3B4C10 cmp cx,[si+tftp_blksize] ; Is it a full block?
|
|
4908 000016E3 720D jb .last_block ; If so, it's not EOF
|
|
4909
|
|
4910 ; If we had the exact right number of bytes, always get
|
|
4911 ; one more packet to get the (zero-byte) EOF packet and
|
|
4912 ; close the socket.
|
|
4913 000016E5 668B4408 mov eax,[si+tftp_filepos]
|
|
4914 000016E9 6639440C cmp [si+tftp_filesize],eax
|
|
4915 000016ED 0F843DFF je .packet_loop
|
|
4916
|
|
4917 000016F1 C3 ret
|
|
4918
|
|
4919
|
|
4920 .last_block: ; Last block - ACK packet immediately
|
|
4921 000016F2 648B4702 mov ax,[fs:bx+2]
|
|
4922 000016F6 E80900 call ack_packet
|
|
4923
|
|
4924 ; Make sure we know we are at end of file
|
|
4925 000016F9 668B4408 mov eax,[si+tftp_filepos]
|
|
4926 000016FD 6689440C mov [si+tftp_filesize],eax
|
|
4927
|
|
4928 00001701 C3 ret
|
|
4929
|
|
4930 ;
|
|
4931 ; ack_packet:
|
|
4932 ;
|
|
4933 ; Send ACK packet. This is a common operation and so is worth canning.
|
|
4934 ;
|
|
4935 ; Entry:
|
|
4936 ; SI = TFTP block
|
|
4937 ; AX = Packet # to ack (network byte order)
|
|
4938 ; Exit:
|
|
4939 ; ZF = 0 -> Error
|
|
4940 ; All registers preserved
|
|
4941 ;
|
|
4942 ; This function uses the pxe_udp_write_pkt but not the packet_buf.
|
|
4943 ;
|
|
4944 ack_packet:
|
|
4945 00001702 6660 pushad
|
|
4946 00001704 A3[EA08] mov [ack_packet_buf+2],ax ; Packet number to ack
|
|
4947 00001707 8B04 mov ax,[si]
|
|
4948 00001709 A3[8008] mov [pxe_udp_write_pkt.lport],ax
|
|
4949 0000170C 8B4402 mov ax,[si+tftp_remoteport]
|
|
4950 0000170F A3[8208] mov [pxe_udp_write_pkt.rport],ax
|
|
4951 00001712 668B4404 mov eax,[si+tftp_remoteip]
|
|
4952 00001716 66A3[7808] mov [pxe_udp_write_pkt.sip],eax
|
|
4953 0000171A 663306[EC08] xor eax,[MyIP]
|
|
4954 0000171F 662306[F408] and eax,[Netmask]
|
|
4955 00001724 7404 jz .nogw
|
|
4956 00001726 66A1[F808] mov eax,[Gateway]
|
|
4957 .nogw:
|
|
4958 0000172A 66A3[7C08] mov [pxe_udp_write_pkt.gip],eax
|
|
4959 0000172E C706[8608][E808] mov [pxe_udp_write_pkt.buffer],word ack_packet_buf
|
|
4960 00001734 C706[8408]0400 mov [pxe_udp_write_pkt.buffersize], word 4
|
|
4961 0000173A BF[7608] mov di,pxe_udp_write_pkt
|
|
4962 0000173D BB3300 mov bx,PXENV_UDP_WRITE
|
|
4963 00001740 E864FE call pxenv
|
|
4964 00001743 83F800 cmp ax,byte 0 ; ZF = 1 if write OK
|
|
4965 00001746 6661 popad
|
|
4966 00001748 C3 ret
|
|
4967
|
|
4968 ;
|
|
4969 ; unload_pxe:
|
|
4970 ;
|
|
4971 ; This function unloads the PXE and UNDI stacks and unclaims
|
|
4972 ; the memory.
|
|
4973 ;
|
|
4974 unload_pxe:
|
|
4975 00001749 F606[A608]01 test byte [KeepPXE],01h ; Should we keep PXE around?
|
|
4976 0000174E 0F859300 jnz reset_pxe
|
|
4977
|
|
4978 00001752 1E push ds
|
|
4979 00001753 06 push es
|
|
4980
|
|
4981 00001754 8CC8 mov ax,cs
|
|
4982 00001756 8ED8 mov ds,ax
|
|
4983 00001758 8EC0 mov es,ax
|
|
4984
|
|
4985 0000175A BE[4008] mov si,new_api_unload
|
|
4986 0000175D 803E[0900]02 cmp byte [APIVer+1],2 ; Major API version >= 2?
|
|
4987 00001762 7303 jae .new_api
|
|
4988 00001764 BE[4508] mov si,old_api_unload
|
|
4989 .new_api:
|
|
4990
|
|
4991 00001767 31C0 .call_loop: xor ax,ax
|
|
4992 00001769 AC lodsb
|
|
4993 0000176A 21C0 and ax,ax
|
|
4994 0000176C 741C jz .call_done
|
|
4995 0000176E 93 xchg bx,ax
|
|
4996 0000176F BF[6400] mov di,pxe_unload_stack_pkt
|
|
4997 00001772 57 push di
|
|
4998 00001773 31C0 xor ax,ax
|
|
4999 00001775 B90B00 mov cx,pxe_unload_stack_pkt_len >> 1
|
|
5000 00001778 F3AB rep stosw
|
|
5001 0000177A 5F pop di
|
|
5002 0000177B E829FE call pxenv
|
|
5003 0000177E 7240 jc .cant_free
|
|
5004 00001780 A1[6400] mov ax,word [pxe_unload_stack_pkt.status]
|
|
5005 00001783 83F800 cmp ax,PXENV_STATUS_SUCCESS
|
|
5006 00001786 7538 jne .cant_free
|
|
5007 00001788 EBDD jmp .call_loop
|
|
5008
|
|
5009 .call_done:
|
|
5010 ;
|
|
5011 ; This isn't necessary anymore; we can use the memory area previously
|
|
5012 ; used by the PXE stack indefinitely, and the chainload code sets up
|
|
5013 ; a new stack independently. Leave the source code in here for now,
|
|
5014 ; but expect to rip it out soonish.
|
|
5015 ;
|
|
5016 %if 0 ; USE_PXE_PROVIDED_STACK
|
|
5017 ; We need to switch to our local stack here...
|
|
5018 pusha
|
|
5019 pushf
|
|
5020 push gs
|
|
5021
|
|
5022 mov si,sp
|
|
5023 mov ax,ss
|
|
5024 mov gs,ax
|
|
5025 sub ax,[BaseStack+4] ; Are we using the base stack
|
|
5026 je .is_base_stack ; (as opposed to the COMBOOT stack)?
|
|
5027
|
|
5028 lgs si,[SavedSSSP] ; COMBOOT stack
|
|
5029 .is_base_stack:
|
|
5030
|
|
5031 mov cx,[InitStack]
|
|
5032 mov di,StackBuf
|
|
5033 mov [BaseStack],di
|
|
5034 mov [BaseStack+4],es
|
|
5035 sub cx,si
|
|
5036 sub di,cx
|
|
5037 mov [SavedSSSP],di ; New SP
|
|
5038 mov [SavedSSSP+2],es
|
|
5039 gs rep movsb
|
|
5040
|
|
5041 and ax,ax ; Remember which stack
|
|
5042 jne .combootstack
|
|
5043
|
|
5044 ; Update the base stack pointer since it's in use
|
|
5045 lss sp,[SavedSSSP]
|
|
5046
|
|
5047 .combootstack:
|
|
5048 pop gs
|
|
5049 popf
|
|
5050 popa
|
|
5051 %endif
|
|
5052 0000178A BB00FF mov bx,0FF00h
|
|
5053
|
|
5054 0000178D 8B16[1200] mov dx,[RealBaseMem]
|
|
5055 00001791 3B161304 cmp dx,[BIOS_fbm] ; Sanity check
|
|
5056 00001795 7629 jna .cant_free
|
|
5057 00001797 43 inc bx
|
|
5058
|
|
5059 ; Check that PXE actually unhooked the INT 1Ah chain
|
|
5060 00001798 660FB7066800 movzx eax,word [4*0x1a]
|
|
5061 0000179E 660FB70E6A00 movzx ecx,word [4*0x1a+2]
|
|
5062 000017A4 66C1E104 shl ecx,4
|
|
5063 000017A8 6601C8 add eax,ecx
|
|
5064 000017AB 66C1E80A shr eax,10
|
|
5065 000017AF 39D0 cmp ax,dx ; Not in range
|
|
5066 000017B1 7306 jae .ok
|
|
5067 000017B3 3B061304 cmp ax,[BIOS_fbm]
|
|
5068 000017B7 7307 jae .cant_free
|
|
5069 ; inc bx
|
|
5070
|
|
5071 .ok:
|
|
5072 000017B9 89161304 mov [BIOS_fbm],dx
|
|
5073 .pop_ret:
|
|
5074 000017BD 07 pop es
|
|
5075 000017BE 1F pop ds
|
|
5076 000017BF C3 ret
|
|
5077
|
|
5078 .cant_free:
|
|
5079 000017C0 BE[2406] mov si,cant_free_msg
|
|
5080 000017C3 E88E06 call writestr
|
|
5081 000017C6 50 push ax
|
|
5082 000017C7 93 xchg bx,ax
|
|
5083 000017C8 E8A906 call writehex4
|
|
5084 000017CB B02D mov al,'-'
|
|
5085 000017CD E8B50D call writechr
|
|
5086 000017D0 58 pop ax
|
|
5087 000017D1 E8A006 call writehex4
|
|
5088 000017D4 B02D mov al,'-'
|
|
5089 000017D6 E8AC0D call writechr
|
|
5090 000017D9 66A16800 mov eax,[4*0x1a]
|
|
5091 000017DD E8A106 call writehex8
|
|
5092 000017E0 E86406 call crlf
|
|
5093 000017E3 EBD8 jmp .pop_ret
|
|
5094
|
|
5095 ; We want to keep PXE around, but still we should reset
|
|
5096 ; it to the standard bootup configuration
|
|
5097 reset_pxe:
|
|
5098 000017E5 06 push es
|
|
5099 000017E6 0E push cs
|
|
5100 000017E7 07 pop es
|
|
5101 000017E8 BB3100 mov bx,PXENV_UDP_CLOSE
|
|
5102 000017EB BF[7408] mov di,pxe_udp_close_pkt
|
|
5103 000017EE E8B6FD call pxenv
|
|
5104 000017F1 07 pop es
|
|
5105 000017F2 C3 ret
|
|
5106
|
|
5107 ;
|
|
5108 ; gendotquad
|
|
5109 ;
|
|
5110 ; Take an IP address (in network byte order) in EAX and
|
|
5111 ; output a dotted quad string to ES:DI.
|
|
5112 ; DI points to terminal null at end of string on exit.
|
|
5113 ;
|
|
5114 gendotquad:
|
|
5115 000017F3 6650 push eax
|
|
5116 000017F5 51 push cx
|
|
5117 000017F6 B90400 mov cx,4
|
|
5118 .genchar:
|
|
5119 000017F9 6650 push eax
|
|
5120 000017FB 3C0A cmp al,10 ; < 10?
|
|
5121 000017FD 7216 jb .lt10 ; If so, skip first 2 digits
|
|
5122
|
|
5123 000017FF 3C64 cmp al,100 ; < 100
|
|
5124 00001801 7209 jb .lt100 ; If so, skip first digit
|
|
5125
|
|
5126 00001803 D464 aam 100
|
|
5127 ; Now AH = 100-digit; AL = remainder
|
|
5128 00001805 80C430 add ah,'0'
|
|
5129 00001808 268825 mov [es:di],ah
|
|
5130 0000180B 47 inc di
|
|
5131
|
|
5132 .lt100:
|
|
5133 0000180C D40A aam 10
|
|
5134 ; Now AH = 10-digit; AL = remainder
|
|
5135 0000180E 80C430 add ah,'0'
|
|
5136 00001811 268825 mov [es:di],ah
|
|
5137 00001814 47 inc di
|
|
5138
|
|
5139 .lt10:
|
|
5140 00001815 0430 add al,'0'
|
|
5141 00001817 AA stosb
|
|
5142 00001818 B02E mov al,'.'
|
|
5143 0000181A AA stosb
|
|
5144 0000181B 6658 pop eax
|
|
5145 0000181D 66C1C808 ror eax,8 ; Move next char into LSB
|
|
5146 00001821 E2D6 loop .genchar
|
|
5147 00001823 4F dec di
|
|
5148 00001824 26C60500 mov [es:di], byte 0
|
|
5149 00001828 59 pop cx
|
|
5150 00001829 6658 pop eax
|
|
5151 0000182B C3 ret
|
|
5152
|
|
5153 ;
|
|
5154 ; parse_dhcp
|
|
5155 ;
|
|
5156 ; Parse a DHCP packet. This includes dealing with "overloaded"
|
|
5157 ; option fields (see RFC 2132, section 9.3)
|
|
5158 ;
|
|
5159 ; This should fill in the following global variables, if the
|
|
5160 ; information is present:
|
|
5161 ;
|
|
5162 ; MyIP - client IP address
|
|
5163 ; ServerIP - boot server IP address
|
|
5164 ; Netmask - network mask
|
|
5165 ; Gateway - default gateway router IP
|
|
5166 ; BootFile - boot file name
|
|
5167 ; DNSServers - DNS server IPs
|
|
5168 ; LocalDomain - Local domain name
|
|
5169 ;
|
|
5170 ; This assumes the DHCP packet is in "trackbuf" and the length
|
|
5171 ; of the packet in in CX on entry.
|
|
5172 ;
|
|
5173
|
|
5174 parse_dhcp:
|
|
5175 0000182C C606[1400]00 mov byte [OverLoad],0 ; Assume no overload
|
|
5176 00001831 66A1[1000] mov eax, [trackbuf+bootp.yip]
|
|
5177 00001835 6621C0 and eax, eax
|
|
5178 00001838 7408 jz .noyip
|
|
5179 0000183A 3CE0 cmp al,224 ; Class D or higher -> bad
|
|
5180 0000183C 7304 jae .noyip
|
|
5181 0000183E 66A3[EC08] mov [MyIP], eax
|
|
5182 .noyip:
|
|
5183 00001842 66A1[1400] mov eax, [trackbuf+bootp.sip]
|
|
5184 00001846 6621C0 and eax, eax
|
|
5185 00001849 7408 jz .nosip
|
|
5186 0000184B 3CE0 cmp al,224 ; Class D or higher -> bad
|
|
5187 0000184D 7304 jae .nosip
|
|
5188 0000184F 66A3[F008] mov [ServerIP], eax
|
|
5189 .nosip:
|
|
5190 00001853 81E9F000 sub cx, bootp.options
|
|
5191 00001857 7610 jbe .nooptions
|
|
5192 00001859 BE[EC00] mov si, trackbuf+bootp.option_magic
|
|
5193 0000185C 66AD lodsd
|
|
5194 0000185E 663D63825363 cmp eax, BOOTP_OPTION_MAGIC
|
|
5195 00001864 7503 jne .nooptions
|
|
5196 00001866 E83400 call parse_dhcp_options
|
|
5197 .nooptions:
|
|
5198 00001869 BE[6C00] mov si, trackbuf+bootp.bootfile
|
|
5199 0000186C F606[1400]01 test byte [OverLoad],1
|
|
5200 00001871 7408 jz .nofileoverload
|
|
5201 00001873 B98000 mov cx,128
|
|
5202 00001876 E82400 call parse_dhcp_options
|
|
5203 00001879 EB11 jmp short .parsed_file
|
|
5204 .nofileoverload:
|
|
5205 0000187B 803C00 cmp byte [si], 0
|
|
5206 0000187E 740C jz .parsed_file ; No bootfile name
|
|
5207 00001880 BF[0044] mov di,BootFile
|
|
5208 00001883 B92000 mov cx,32
|
|
5209 00001886 F366A5 rep movsd
|
|
5210 00001889 30C0 xor al,al
|
|
5211 0000188B AA stosb ; Null-terminate
|
|
5212 .parsed_file:
|
|
5213 0000188C BE[2C00] mov si, trackbuf+bootp.sname
|
|
5214 0000188F F606[1400]02 test byte [OverLoad],2
|
|
5215 00001894 7406 jz .nosnameoverload
|
|
5216 00001896 B94000 mov cx,64
|
|
5217 00001899 E80100 call parse_dhcp_options
|
|
5218 .nosnameoverload:
|
|
5219 0000189C C3 ret
|
|
5220
|
|
5221 ;
|
|
5222 ; Parse a sequence of DHCP options, pointed to by DS:SI; the field
|
|
5223 ; size is CX -- some DHCP servers leave option fields unterminated
|
|
5224 ; in violation of the spec.
|
|
5225 ;
|
|
5226 ; For parse_some_dhcp_options, DH contains the minimum value for
|
|
5227 ; the option to recognize -- this is used to restrict parsing to
|
|
5228 ; PXELINUX-specific options only.
|
|
5229 ;
|
|
5230 parse_dhcp_options:
|
|
5231 0000189D 31D2 xor dx,dx
|
|
5232
|
|
5233 parse_some_dhcp_options:
|
|
5234 .loop:
|
|
5235 0000189F 21C9 and cx,cx
|
|
5236 000018A1 0F84A200 jz .done
|
|
5237
|
|
5238 000018A5 AC lodsb
|
|
5239 000018A6 49 dec cx
|
|
5240 000018A7 0F849C00 jz .done ; Last byte; must be PAD, END or malformed
|
|
5241 000018AB 3C00 cmp al, 0 ; PAD option
|
|
5242 000018AD 74F0 je .loop
|
|
5243 000018AF 3CFF cmp al,255 ; END option
|
|
5244 000018B1 0F849200 je .done
|
|
5245
|
|
5246 ; Anything else will have a length field
|
|
5247 000018B5 88C2 mov dl,al ; DL <- option number
|
|
5248 000018B7 31C0 xor ax,ax
|
|
5249 000018B9 AC lodsb ; AX <- option length
|
|
5250 000018BA 49 dec cx
|
|
5251 000018BB 29C1 sub cx,ax ; Decrement bytes left counter
|
|
5252 000018BD 0F828600 jb .done ; Malformed option: length > field size
|
|
5253
|
|
5254 000018C1 38F2 cmp dl,dh ; Is the option value valid?
|
|
5255 000018C3 0F82D600 jb .opt_done
|
|
5256
|
|
5257 000018C7 80FA01 cmp dl,1 ; SUBNET MASK option
|
|
5258 000018CA 750B jne .not_subnet
|
|
5259 000018CC 668B1C mov ebx,[si]
|
|
5260 000018CF 66891E[F408] mov [Netmask],ebx
|
|
5261 000018D4 E9C600 jmp .opt_done
|
|
5262 .not_subnet:
|
|
5263
|
|
5264 000018D7 80FA03 cmp dl,3 ; ROUTER option
|
|
5265 000018DA 750B jne .not_router
|
|
5266 000018DC 668B1C mov ebx,[si]
|
|
5267 000018DF 66891E[F808] mov [Gateway],ebx
|
|
5268 000018E4 E9B600 jmp .opt_done
|
|
5269 .not_router:
|
|
5270
|
|
5271 000018E7 80FA06 cmp dl,6 ; DNS SERVERS option
|
|
5272 000018EA 751B jne .not_dns
|
|
5273 000018EC 60 pusha
|
|
5274 000018ED 89C1 mov cx,ax
|
|
5275 000018EF C1E902 shr cx,2
|
|
5276 000018F2 80F904 cmp cl,DNS_MAX_SERVERS
|
|
5277 000018F5 7602 jna .oklen
|
|
5278 000018F7 B104 mov cl,DNS_MAX_SERVERS
|
|
5279 .oklen:
|
|
5280 000018F9 BF[9C24] mov di,DNSServers
|
|
5281 000018FC F366A5 rep movsd
|
|
5282 000018FF 893E[3901] mov [LastDNSServer],di
|
|
5283 00001903 61 popa
|
|
5284 00001904 E99600 jmp .opt_done
|
|
5285 .not_dns:
|
|
5286
|
|
5287 00001907 80FA0F cmp dl,15 ; DNS LOCAL DOMAIN option
|
|
5288 0000190A 7514 jne .not_localdomain
|
|
5289 0000190C 60 pusha
|
|
5290 0000190D 89F3 mov bx,si
|
|
5291 0000190F 01C3 add bx,ax
|
|
5292 00001911 31C0 xor ax,ax
|
|
5293 00001913 8607 xchg [bx],al ; Zero-terminate option
|
|
5294 00001915 BF[9C23] mov di,LocalDomain
|
|
5295 00001918 E8F10C call dns_mangle ; Convert to DNS label set
|
|
5296 0000191B 8807 mov [bx],al ; Restore ending byte
|
|
5297 0000191D 61 popa
|
|
5298 0000191E EB7D jmp .opt_done
|
|
5299 .not_localdomain:
|
|
5300
|
|
5301 00001920 80FA2B cmp dl,43 ; VENDOR ENCAPSULATED option
|
|
5302 00001923 750B jne .not_vendor
|
|
5303 00001925 60 pusha
|
|
5304 00001926 B6D0 mov dh,208 ; Only recognize PXELINUX options
|
|
5305 00001928 89C1 mov cx,ax ; Length of option = max bytes to parse
|
|
5306 0000192A E872FF call parse_some_dhcp_options ; Parse recursive structure
|
|
5307 0000192D 61 popa
|
|
5308 0000192E EB6D jmp .opt_done
|
|
5309 .not_vendor:
|
|
5310
|
|
5311 00001930 80FA34 cmp dl,52 ; OPTION OVERLOAD option
|
|
5312 00001933 7508 jne .not_overload
|
|
5313 00001935 8A1C mov bl,[si]
|
|
5314 00001937 881E[1400] mov [OverLoad],bl
|
|
5315 0000193B EB60 jmp .opt_done
|
|
5316 .not_overload:
|
|
5317
|
|
5318 0000193D 80FA43 cmp dl,67 ; BOOTFILE NAME option
|
|
5319 00001940 7506 jne .not_bootfile
|
|
5320 00001942 BF[0044] mov di,BootFile
|
|
5321 00001945 EB5B jmp short .copyoption
|
|
5322 .done:
|
|
5323 00001947 C3 ret ; This is here to make short jumps easier
|
|
5324 .not_bootfile:
|
|
5325
|
|
5326 00001948 80FAD0 cmp dl,208 ; PXELINUX MAGIC option
|
|
5327 0000194B 7514 jne .not_pl_magic
|
|
5328 0000194D 3C04 cmp al,4 ; Must have length == 4
|
|
5329 0000194F 754C jne .opt_done
|
|
5330 00001951 66813CF100747E cmp dword [si], htonl(0xF100747E) ; Magic number
|
|
5331 00001958 7543 jne .opt_done
|
|
5332 0000195A 800E[0909]01 or byte [DHCPMagic], byte 1 ; Found magic #
|
|
5333 0000195F EB3C jmp short .opt_done
|
|
5334 .not_pl_magic:
|
|
5335
|
|
5336 00001961 80FAD1 cmp dl,209 ; PXELINUX CONFIGFILE option
|
|
5337 00001964 750A jne .not_pl_config
|
|
5338 00001966 BF[0445] mov di,ConfigName
|
|
5339 00001969 800E[0909]02 or byte [DHCPMagic], byte 2 ; Got config file
|
|
5340 0000196E EB32 jmp short .copyoption
|
|
5341 .not_pl_config:
|
|
5342
|
|
5343 00001970 80FAD2 cmp dl,210 ; PXELINUX PATHPREFIX option
|
|
5344 00001973 750A jne .not_pl_prefix
|
|
5345 00001975 BF[0046] mov di,PathPrefix
|
|
5346 00001978 800E[0909]04 or byte [DHCPMagic], byte 4 ; Got path prefix
|
|
5347 0000197D EB23 jmp short .copyoption
|
|
5348 .not_pl_prefix:
|
|
5349
|
|
5350 0000197F 80FAD3 cmp dl,211 ; PXELINUX REBOOTTIME option
|
|
5351 00001982 7519 jne .not_pl_timeout
|
|
5352 00001984 3C04 cmp al,4
|
|
5353 00001986 7515 jne .opt_done
|
|
5354 00001988 668B1C mov ebx,[si]
|
|
5355 0000198B 86DF xchg bl,bh ; Convert to host byte order
|
|
5356 0000198D 66C1C310 rol ebx,16
|
|
5357 00001991 86DF xchg bl,bh
|
|
5358 00001993 66891E[0000] mov [RebootTime],ebx
|
|
5359 00001998 800E[0909]08 or byte [DHCPMagic], byte 8 ; Got RebootTime
|
|
5360 ; jmp short .opt_done
|
|
5361 .not_pl_timeout:
|
|
5362
|
|
5363 ; Unknown option. Skip to the next one.
|
|
5364 .opt_done:
|
|
5365 0000199D 01C6 add si,ax
|
|
5366 .opt_done_noskip:
|
|
5367 0000199F E9FDFE jmp .loop
|
|
5368
|
|
5369 ; Common code for copying an option verbatim
|
|
5370 .copyoption:
|
|
5371 000019A2 91 xchg cx,ax
|
|
5372 000019A3 F3A4 rep movsb
|
|
5373 000019A5 91 xchg cx,ax ; Now ax == 0
|
|
5374 000019A6 AA stosb ; Null-terminate
|
|
5375 000019A7 EBF6 jmp short .opt_done_noskip
|
|
5376
|
|
5377 ;
|
|
5378 ; genipopt
|
|
5379 ;
|
|
5380 ; Generate an ip=<client-ip>:<boot-server-ip>:<gw-ip>:<netmask>
|
|
5381 ; option into IPOption based on a DHCP packet in trackbuf.
|
|
5382 ; Assumes CS == DS == ES.
|
|
5383 ;
|
|
5384 genipopt:
|
|
5385 000019A9 6660 pushad
|
|
5386 000019AB BF[1047] mov di,IPOption
|
|
5387 000019AE 66B869703D00 mov eax,'ip='
|
|
5388 000019B4 66AB stosd
|
|
5389 000019B6 4F dec di
|
|
5390 000019B7 66A1[EC08] mov eax,[MyIP]
|
|
5391 000019BB E835FE call gendotquad
|
|
5392 000019BE B03A mov al,':'
|
|
5393 000019C0 AA stosb
|
|
5394 000019C1 66A1[F008] mov eax,[ServerIP]
|
|
5395 000019C5 E82BFE call gendotquad
|
|
5396 000019C8 B03A mov al,':'
|
|
5397 000019CA AA stosb
|
|
5398 000019CB 66A1[F808] mov eax,[Gateway]
|
|
5399 000019CF E821FE call gendotquad
|
|
5400 000019D2 B03A mov al,':'
|
|
5401 000019D4 AA stosb
|
|
5402 000019D5 66A1[F408] mov eax,[Netmask]
|
|
5403 000019D9 E817FE call gendotquad ; Zero-terminates its output
|
|
5404 000019DC 81EF[1047] sub di,IPOption
|
|
5405 000019E0 893E[0A00] mov [IPOptionLen],di
|
|
5406 000019E4 6661 popad
|
|
5407 000019E6 C3 ret
|
|
5408
|
|
5409 ;
|
|
5410 ; Call the receive loop while idle. This is done mostly so we can respond to
|
|
5411 ; ARP messages, but perhaps in the future this can be used to do network
|
|
5412 ; console.
|
|
5413 ;
|
|
5414 ; hpa sez: people using automatic control on the serial port get very
|
|
5415 ; unhappy if we poll for ARP too often (the PXE stack is pretty slow,
|
|
5416 ; typically.) Therefore, only poll if at least 4 BIOS timer ticks have
|
|
5417 ; passed since the last poll, and reset this when a character is
|
|
5418 ; received (RESET_IDLE).
|
|
5419 ;
|
|
5420 reset_idle:
|
|
5421 000019E7 50 push ax
|
|
5422 000019E8 2EA16C04 mov ax,[cs:BIOS_timer]
|
|
5423 000019EC 2EA3[0C00] mov [cs:IdleTimer],ax
|
|
5424 000019F0 58 pop ax
|
|
5425 000019F1 C3 ret
|
|
5426
|
|
5427 check_for_arp:
|
|
5428 000019F2 50 push ax
|
|
5429 000019F3 2EA16C04 mov ax,[cs:BIOS_timer]
|
|
5430 000019F7 2E2B06[0C00] sub ax,[cs:IdleTimer]
|
|
5431 000019FC 83F804 cmp ax,4
|
|
5432 000019FF 58 pop ax
|
|
5433 00001A00 7301 jae .need_poll
|
|
5434 00001A02 C3 ret
|
|
5435 00001A03 6660 .need_poll: pushad
|
|
5436 00001A05 1E push ds
|
|
5437 00001A06 06 push es
|
|
5438 00001A07 8CC8 mov ax,cs
|
|
5439 00001A09 8ED8 mov ds,ax
|
|
5440 00001A0B 8EC0 mov es,ax
|
|
5441 00001A0D BF[8000] mov di,packet_buf
|
|
5442 00001A10 A2[8A08] mov [pxe_udp_read_pkt.status],al ; 0
|
|
5443 00001A13 893E[9A08] mov [pxe_udp_read_pkt.buffer],di
|
|
5444 00001A17 8C1E[9C08] mov [pxe_udp_read_pkt.buffer+2],ds
|
|
5445 00001A1B C706[9808]0008 mov word [pxe_udp_read_pkt.buffersize],packet_buf_size
|
|
5446 00001A21 66A1[EC08] mov eax,[MyIP]
|
|
5447 00001A25 66A3[9008] mov [pxe_udp_read_pkt.dip],eax
|
|
5448 00001A29 C706[9608]0009 mov word [pxe_udp_read_pkt.lport],htons(9) ; discard port
|
|
5449 00001A2F BF[8A08] mov di,pxe_udp_read_pkt
|
|
5450 00001A32 BB3200 mov bx,PXENV_UDP_READ
|
|
5451 00001A35 E86FFB call pxenv
|
|
5452 ; Ignore result...
|
|
5453 00001A38 07 pop es
|
|
5454 00001A39 1F pop ds
|
|
5455 00001A3A 6661 popad
|
|
5456 RESET_IDLE
|
|
5457 00001A3C E8A8FF <1> call reset_idle
|
|
5458 00001A3F C3 ret
|
|
5459
|
|
5460 ; -----------------------------------------------------------------------------
|
|
5461 ; Common modules
|
|
5462 ; -----------------------------------------------------------------------------
|
|
5463
|
|
5464 %include "getc.inc" ; getc et al
|
|
5465 <1> ;; $Id: getc.inc,v 1.6 2004/12/17 06:42:01 hpa Exp $
|
|
5466 <1> ;; -----------------------------------------------------------------------
|
|
5467 <1> ;;
|
|
5468 <1> ;; Copyright 1994-2002 H. Peter Anvin - All Rights Reserved
|
|
5469 <1> ;;
|
|
5470 <1> ;; This program is free software; you can redistribute it and/or modify
|
|
5471 <1> ;; it under the terms of the GNU General Public License as published by
|
|
5472 <1> ;; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
|
|
5473 <1> ;; Boston MA 02111-1307, USA; either version 2 of the License, or
|
|
5474 <1> ;; (at your option) any later version; incorporated herein by reference.
|
|
5475 <1> ;;
|
|
5476 <1> ;; -----------------------------------------------------------------------
|
|
5477 <1>
|
|
5478 <1> ;;
|
|
5479 <1> ;; getc.inc
|
|
5480 <1> ;;
|
|
5481 <1> ;; Simple file handling library (open, getc, ungetc)
|
|
5482 <1> ;;
|
|
5483 <1>
|
|
5484 <1> ;
|
|
5485 <1> ; open,getc: Load a file a character at a time for parsing in a manner
|
|
5486 <1> ; similar to the C library getc routine. Only one simultaneous
|
|
5487 <1> ; use is supported. Note: "open" trashes the trackbuf.
|
|
5488 <1> ;
|
|
5489 <1> ; open: Input: mangled filename in DS:DI
|
|
5490 <1> ; Output: ZF set on file not found or zero length
|
|
5491 <1> ;
|
|
5492 <1> ; openfd: Input: file handle in SI
|
|
5493 <1> ; Output: none
|
|
5494 <1> ;
|
|
5495 <1> ; getc: Output: CF set on end of file
|
|
5496 <1> ; Character loaded in AL
|
|
5497 <1> ;
|
|
5498 <1> open:
|
|
5499 00001A40 E89AF8 <1> call searchdir
|
|
5500 00001A43 7425 <1> jz openfd.ret
|
|
5501 <1> openfd:
|
|
5502 00001A45 9C <1> pushf
|
|
5503 00001A46 A3[B808] <1> mov [FBytes],ax
|
|
5504 00001A49 8916[BA08] <1> mov [FBytes+2],dx
|
|
5505 00001A4D 66A1[B808] <1> mov eax,[FBytes]
|
|
5506 00001A51 6605FF010000 <1> add eax,SECTOR_SIZE-1
|
|
5507 00001A57 66C1E809 <1> shr eax,SECTOR_SHIFT
|
|
5508 00001A5B 66A3[BC08] <1> mov [FSectors],eax ; Number of sectors
|
|
5509 00001A5F 8936[C008] <1> mov [FNextClust],si ; Cluster pointer
|
|
5510 00001A63 A1[0609] <1> mov ax,[EndOfGetCBuf] ; Pointer at end of buffer ->
|
|
5511 00001A66 A3[C208] <1> mov [FPtr],ax ; nothing loaded yet
|
|
5512 00001A69 9D <1> popf ; Restore no ZF
|
|
5513 00001A6A C3 <1> .ret: ret
|
|
5514 <1>
|
|
5515 <1> getc:
|
|
5516 00001A6B F9 <1> stc ; If we exit here -> EOF
|
|
5517 00001A6C 668B0E[B808] <1> mov ecx,[FBytes]
|
|
5518 00001A71 67E33F <1> jecxz .ret
|
|
5519 00001A74 8B36[C208] <1> mov si,[FPtr]
|
|
5520 00001A78 3B36[0609] <1> cmp si,[EndOfGetCBuf]
|
|
5521 00001A7C 722A <1> jb .loaded
|
|
5522 <1> ; Buffer empty -- load another set
|
|
5523 00001A7E 668B0E[BC08] <1> mov ecx,[FSectors]
|
|
5524 00001A83 6683F910 <1> cmp ecx,trackbufsize >> SECTOR_SHIFT
|
|
5525 00001A87 7606 <1> jna .oksize
|
|
5526 00001A89 66B910000000 <1> mov ecx,trackbufsize >> SECTOR_SHIFT
|
|
5527 00001A8F 66290E[BC08] <1> .oksize: sub [FSectors],ecx ; Reduce remaining clusters
|
|
5528 00001A94 8B36[C008] <1> mov si,[FNextClust]
|
|
5529 00001A98 06 <1> push es ; ES may be != DS, save old ES
|
|
5530 00001A99 1E <1> push ds
|
|
5531 00001A9A 07 <1> pop es
|
|
5532 00001A9B BB[0020] <1> mov bx,getcbuf
|
|
5533 00001A9E 53 <1> push bx
|
|
5534 00001A9F E81CFB <1> call getfssec ; Load a trackbuf full of data
|
|
5535 00001AA2 8936[C008] <1> mov [FNextClust],si ; Store new next pointer
|
|
5536 00001AA6 5E <1> pop si ; SI -> newly loaded data
|
|
5537 00001AA7 07 <1> pop es ; Restore ES
|
|
5538 00001AA8 AC <1> .loaded: lodsb ; Load a byte, increment SI
|
|
5539 00001AA9 8936[C208] <1> mov [FPtr],si ; Update next byte pointer
|
|
5540 00001AAD 66FF0E[B808] <1> dec dword [FBytes] ; Update bytes left counter
|
|
5541 00001AB2 F8 <1> clc ; Not EOF
|
|
5542 00001AB3 C3 <1> .ret: ret
|
|
5543 <1>
|
|
5544 <1> ;
|
|
5545 <1> ; ungetc: Push a character (in AL) back into the getc buffer
|
|
5546 <1> ; Note: if more than one byte is pushed back, this may cause
|
|
5547 <1> ; bytes to be written below the getc buffer boundary. If there
|
|
5548 <1> ; is a risk for this to occur, the getcbuf base address should
|
|
5549 <1> ; be moved up.
|
|
5550 <1> ;
|
|
5551 <1> ungetc:
|
|
5552 00001AB4 8B36[C208] <1> mov si,[FPtr]
|
|
5553 00001AB8 4E <1> dec si
|
|
5554 00001AB9 8804 <1> mov [si],al
|
|
5555 00001ABB 8936[C208] <1> mov [FPtr],si
|
|
5556 00001ABF 66FF06[B808] <1> inc dword [FBytes]
|
|
5557 00001AC4 C3 <1> ret
|
|
5558 <1>
|
|
5559 <1> ;
|
|
5560 <1> ; skipspace: Skip leading whitespace using "getc". If we hit end-of-line
|
|
5561 <1> ; or end-of-file, return with carry set; ZF = true of EOF
|
|
5562 <1> ; ZF = false for EOLN; otherwise CF = ZF = 0.
|
|
5563 <1> ;
|
|
5564 <1> ; Otherwise AL = first character after whitespace
|
|
5565 <1> ;
|
|
5566 <1> skipspace:
|
|
5567 00001AC5 E8A3FF <1> .loop: call getc
|
|
5568 00001AC8 720D <1> jc .eof
|
|
5569 00001ACA 3C1A <1> cmp al,1Ah ; DOS EOF
|
|
5570 00001ACC 7409 <1> je .eof
|
|
5571 00001ACE 3C0A <1> cmp al,0Ah
|
|
5572 00001AD0 7409 <1> je .eoln
|
|
5573 00001AD2 3C20 <1> cmp al,' '
|
|
5574 00001AD4 76EF <1> jbe .loop
|
|
5575 00001AD6 C3 <1> ret ; CF = ZF = 0
|
|
5576 00001AD7 38C0 <1> .eof: cmp al,al ; Set ZF
|
|
5577 00001AD9 F9 <1> stc ; Set CF
|
|
5578 00001ADA C3 <1> ret
|
|
5579 00001ADB 04FF <1> .eoln: add al,0FFh ; Set CF, clear ZF
|
|
5580 00001ADD C3 <1> ret
|
|
5581 <1>
|
|
5582 <1> ;
|
|
5583 <1> ; getint: Load an integer from the getc file.
|
|
5584 <1> ; Return CF if error; otherwise return integer in EBX
|
|
5585 <1> ;
|
|
5586 <1> getint:
|
|
5587 00001ADE BF[A808] <1> mov di,NumBuf
|
|
5588 00001AE1 81FF[B708] <1> .getnum: cmp di,NumBufEnd ; Last byte in NumBuf
|
|
5589 00001AE5 730F <1> jae .loaded
|
|
5590 00001AE7 57 <1> push di
|
|
5591 00001AE8 E880FF <1> call getc
|
|
5592 00001AEB 5F <1> pop di
|
|
5593 00001AEC 7208 <1> jc .loaded
|
|
5594 00001AEE AA <1> stosb
|
|
5595 00001AEF 3C2D <1> cmp al,'-'
|
|
5596 00001AF1 73EE <1> jnb .getnum
|
|
5597 00001AF3 E8BEFF <1> call ungetc ; Unget non-numeric
|
|
5598 00001AF6 C60500 <1> .loaded: mov byte [di],0
|
|
5599 00001AF9 BE[A808] <1> mov si,NumBuf
|
|
5600 <1> ; Fall through to parseint
|
|
5601 <1>
|
|
5602 <1> ;
|
|
5603 <1> ; parseint: Convert an integer to a number in EBX
|
|
5604 <1> ; Get characters from string in DS:SI
|
|
5605 <1> ; Return CF on error
|
|
5606 <1> ; DS:SI points to first character after number
|
|
5607 <1> ;
|
|
5608 <1> ; Syntaxes accepted: [-]dec, [-]0+oct, [-]0x+hex, val+K, val+M
|
|
5609 <1> ;
|
|
5610 <1> parseint:
|
|
5611 00001AFC 6650 <1> push eax
|
|
5612 00001AFE 6651 <1> push ecx
|
|
5613 00001B00 55 <1> push bp
|
|
5614 00001B01 6631C0 <1> xor eax,eax ; Current digit (keep eax == al)
|
|
5615 00001B04 6689C3 <1> mov ebx,eax ; Accumulator
|
|
5616 00001B07 6689D9 <1> mov ecx,ebx ; Base
|
|
5617 00001B0A 31ED <1> xor bp,bp ; Used for negative flag
|
|
5618 00001B0C AC <1> .begin: lodsb
|
|
5619 00001B0D 3C2D <1> cmp al,'-'
|
|
5620 00001B0F 7505 <1> jne .not_minus
|
|
5621 00001B11 83F501 <1> xor bp,1 ; Set unary minus flag
|
|
5622 00001B14 EBF6 <1> jmp short .begin
|
|
5623 <1> .not_minus:
|
|
5624 00001B16 3C30 <1> cmp al,'0'
|
|
5625 00001B18 724F <1> jb .err
|
|
5626 00001B1A 7408 <1> je .octhex
|
|
5627 00001B1C 3C39 <1> cmp al,'9'
|
|
5628 00001B1E 7749 <1> ja .err
|
|
5629 00001B20 B10A <1> mov cl,10 ; Base = decimal
|
|
5630 00001B22 EB17 <1> jmp short .foundbase
|
|
5631 <1> .octhex:
|
|
5632 00001B24 AC <1> lodsb
|
|
5633 00001B25 3C30 <1> cmp al,'0'
|
|
5634 00001B27 7225 <1> jb .km ; Value is zero
|
|
5635 00001B29 0C20 <1> or al,20h ; Downcase
|
|
5636 00001B2B 3C78 <1> cmp al,'x'
|
|
5637 00001B2D 7408 <1> je .ishex
|
|
5638 00001B2F 3C37 <1> cmp al,'7'
|
|
5639 00001B31 7736 <1> ja .err
|
|
5640 00001B33 B108 <1> mov cl,8 ; Base = octal
|
|
5641 00001B35 EB04 <1> jmp short .foundbase
|
|
5642 <1> .ishex:
|
|
5643 00001B37 B030 <1> mov al,'0' ; No numeric value accrued yet
|
|
5644 00001B39 B110 <1> mov cl,16 ; Base = hex
|
|
5645 <1> .foundbase:
|
|
5646 00001B3B E83A00 <1> call unhexchar
|
|
5647 00001B3E 720E <1> jc .km ; Not a (hex) digit
|
|
5648 00001B40 38C8 <1> cmp al,cl
|
|
5649 00001B42 730A <1> jae .km ; Invalid for base
|
|
5650 00001B44 660FAFD9 <1> imul ebx,ecx ; Multiply accumulated by base
|
|
5651 00001B48 6601C3 <1> add ebx,eax ; Add current digit
|
|
5652 00001B4B AC <1> lodsb
|
|
5653 00001B4C EBED <1> jmp short .foundbase
|
|
5654 <1> .km:
|
|
5655 00001B4E 4E <1> dec si ; Back up to last non-numeric
|
|
5656 00001B4F AC <1> lodsb
|
|
5657 00001B50 0C20 <1> or al,20h
|
|
5658 00001B52 3C6B <1> cmp al,'k'
|
|
5659 00001B54 7416 <1> je .isk
|
|
5660 00001B56 3C6D <1> cmp al,'m'
|
|
5661 00001B58 7418 <1> je .ism
|
|
5662 00001B5A 4E <1> dec si ; Back up
|
|
5663 00001B5B 21ED <1> .fini: and bp,bp
|
|
5664 00001B5D 7404 <1> jz .ret ; CF=0!
|
|
5665 00001B5F 66F7DB <1> neg ebx ; Value was negative
|
|
5666 00001B62 F8 <1> .done: clc
|
|
5667 00001B63 5D <1> .ret: pop bp
|
|
5668 00001B64 6659 <1> pop ecx
|
|
5669 00001B66 6658 <1> pop eax
|
|
5670 00001B68 C3 <1> ret
|
|
5671 00001B69 F9 <1> .err: stc
|
|
5672 00001B6A EBF7 <1> jmp short .ret
|
|
5673 00001B6C 66C1E30A <1> .isk: shl ebx,10 ; x 2^10
|
|
5674 00001B70 EBF0 <1> jmp short .done
|
|
5675 00001B72 66C1E314 <1> .ism: shl ebx,20 ; x 2^20
|
|
5676 00001B76 EBEA <1> jmp short .done
|
|
5677 <1>
|
|
5678 <1>
|
|
5679 <1> section .bss
|
|
5680 000008A6 <res 00000001>- <1> alignb 4
|
|
5681 000008A6 <rept> <1>
|
|
5682 000008A8 <res 0000000F> <1> NumBuf resb 15 ; Buffer to load number
|
|
5683 000008B7 <res 00000001> <1> NumBufEnd resb 1 ; Last byte in NumBuf
|
|
5684 000008B8 <res 00000004> <1> FBytes resd 1 ; Number of bytes left in getc file
|
|
5685 000008BC <res 00000004> <1> FSectors resd 1 ; Number of sectors in getc file
|
|
5686 000008C0 <res 00000002> <1> FNextClust resw 1 ; Pointer to next cluster in d:o
|
|
5687 000008C2 <res 00000002> <1> FPtr resw 1 ; Pointer to next char in buffer
|
|
5688 <1>
|
|
5689 <1> ;
|
|
5690 <1> ; unhexchar: Convert a hexadecimal digit in AL to the equivalent number;
|
|
5691 <1> ; return CF=1 if not a hex digit
|
|
5692 <1> ;
|
|
5693 <1> section .text
|
|
5694 <1> unhexchar:
|
|
5695 00001B78 3C30 <1> cmp al,'0'
|
|
5696 00001B7A 7215 <1> jb .ret ; If failure, CF == 1 already
|
|
5697 00001B7C 3C39 <1> cmp al,'9'
|
|
5698 00001B7E 7703 <1> ja .notdigit
|
|
5699 00001B80 2C30 <1> sub al,'0' ; CF <- 0
|
|
5700 00001B82 C3 <1> ret
|
|
5701 00001B83 0C20 <1> .notdigit: or al,20h ; upper case -> lower case
|
|
5702 00001B85 3C61 <1> cmp al,'a'
|
|
5703 00001B87 7208 <1> jb .ret ; If failure, CF == 1 already
|
|
5704 00001B89 3C66 <1> cmp al,'f'
|
|
5705 00001B8B 7703 <1> ja .err
|
|
5706 00001B8D 2C57 <1> sub al,'a'-10 ; CF <- 0
|
|
5707 00001B8F C3 <1> ret
|
|
5708 00001B90 F9 <1> .err: stc
|
|
5709 00001B91 C3 <1> .ret: ret
|
|
5710 <1>
|
|
5711 <1> ;
|
|
5712 <1> ;
|
|
5713 <1> ; getline: Get a command line, converting control characters to spaces
|
|
5714 <1> ; and collapsing streches to one; a space is appended to the
|
|
5715 <1> ; end of the string, unless the line is empty.
|
|
5716 <1> ; The line is terminated by ^J, ^Z or EOF and is written
|
|
5717 <1> ; to ES:DI. On return, DI points to first char after string.
|
|
5718 <1> ; CF is set if we hit EOF.
|
|
5719 <1> ;
|
|
5720 <1> getline:
|
|
5721 00001B92 E830FF <1> call skipspace
|
|
5722 00001B95 B201 <1> mov dl,1 ; Empty line -> empty string.
|
|
5723 00001B97 742B <1> jz .eof ; eof
|
|
5724 00001B99 7226 <1> jc .eoln ; eoln
|
|
5725 00001B9B E816FF <1> call ungetc
|
|
5726 00001B9E 52 <1> .fillloop: push dx
|
|
5727 00001B9F 57 <1> push di
|
|
5728 00001BA0 E8C8FE <1> call getc
|
|
5729 00001BA3 5F <1> pop di
|
|
5730 00001BA4 5A <1> pop dx
|
|
5731 00001BA5 721E <1> jc .ret ; CF set!
|
|
5732 00001BA7 3C20 <1> cmp al,' '
|
|
5733 00001BA9 7605 <1> jna .ctrl
|
|
5734 00001BAB 31D2 <1> xor dx,dx
|
|
5735 00001BAD AA <1> .store: stosb
|
|
5736 00001BAE EBEE <1> jmp short .fillloop
|
|
5737 00001BB0 3C0A <1> .ctrl: cmp al,10
|
|
5738 00001BB2 7411 <1> je .ret ; CF clear!
|
|
5739 00001BB4 3C1A <1> cmp al,26
|
|
5740 00001BB6 740C <1> je .eof
|
|
5741 00001BB8 20D2 <1> and dl,dl
|
|
5742 00001BBA 75E2 <1> jnz .fillloop ; Ignore multiple spaces
|
|
5743 00001BBC B020 <1> mov al,' ' ; Ctrl -> space
|
|
5744 00001BBE 42 <1> inc dx
|
|
5745 00001BBF EBEC <1> jmp short .store
|
|
5746 00001BC1 F8 <1> .eoln: clc ; End of line is not end of file
|
|
5747 00001BC2 EB01 <1> jmp short .ret
|
|
5748 00001BC4 F9 <1> .eof: stc
|
|
5749 00001BC5 9C <1> .ret: pushf ; We want the last char to be space!
|
|
5750 00001BC6 20D2 <1> and dl,dl
|
|
5751 00001BC8 7503 <1> jnz .xret
|
|
5752 00001BCA B020 <1> mov al,' '
|
|
5753 00001BCC AA <1> stosb
|
|
5754 00001BCD 9D <1> .xret: popf
|
|
5755 00001BCE C3 <1> ret
|
|
5756 %include "conio.inc" ; Console I/O
|
|
5757 <1> ;; $Id: conio.inc,v 1.13 2005/06/16 04:39:19 hpa Exp $
|
|
5758 <1> ;; -----------------------------------------------------------------------
|
|
5759 <1> ;;
|
|
5760 <1> ;; Copyright 1994-2005 H. Peter Anvin - All Rights Reserved
|
|
5761 <1> ;;
|
|
5762 <1> ;; This program is free software; you can redistribute it and/or modify
|
|
5763 <1> ;; it under the terms of the GNU General Public License as published by
|
|
5764 <1> ;; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
|
|
5765 <1> ;; Boston MA 02111-1307, USA; either version 2 of the License, or
|
|
5766 <1> ;; (at your option) any later version; incorporated herein by reference.
|
|
5767 <1> ;;
|
|
5768 <1> ;; -----------------------------------------------------------------------
|
|
5769 <1>
|
|
5770 <1> ;;
|
|
5771 <1> ;; conio.inc
|
|
5772 <1> ;;
|
|
5773 <1> ;; Console I/O code, except:
|
|
5774 <1> ;; writechr, writestr - module-dependent
|
|
5775 <1> ;; cwritestr, crlf - writestr.inc
|
|
5776 <1> ;; writehex* - writehex.inc
|
|
5777 <1> ;;
|
|
5778 <1>
|
|
5779 <1> ;
|
|
5780 <1> ; loadkeys: Load a LILO-style keymap; SI and DX:AX set by searchdir
|
|
5781 <1> ;
|
|
5782 <1> section .text
|
|
5783 <1>
|
|
5784 <1> loadkeys:
|
|
5785 00001BCF 21D2 <1> and dx,dx ; Should be 256 bytes exactly
|
|
5786 00001BD1 751A <1> jne loadkeys_ret
|
|
5787 00001BD3 3D0001 <1> cmp ax,256
|
|
5788 00001BD6 7515 <1> jne loadkeys_ret
|
|
5789 <1>
|
|
5790 00001BD8 BB[0000] <1> mov bx,trackbuf
|
|
5791 00001BDB B90100 <1> mov cx,1 ; 1 cluster should be >= 256 bytes
|
|
5792 00001BDE E8DDF9 <1> call getfssec
|
|
5793 <1>
|
|
5794 00001BE1 BE[0000] <1> mov si,trackbuf
|
|
5795 00001BE4 BF[DC15] <1> mov di,KbdMap
|
|
5796 00001BE7 B94000 <1> mov cx,256 >> 2
|
|
5797 00001BEA F366A5 <1> rep movsd
|
|
5798 <1>
|
|
5799 00001BED C3 <1> loadkeys_ret: ret
|
|
5800 <1>
|
|
5801 <1> ;
|
|
5802 <1> ; get_msg_file: Load a text file and write its contents to the screen,
|
|
5803 <1> ; interpreting color codes. Is called with SI and DX:AX
|
|
5804 <1> ; set by routine searchdir
|
|
5805 <1> ;
|
|
5806 <1> get_msg_file:
|
|
5807 00001BEE 06 <1> push es
|
|
5808 00001BEF 66C1E210 <1> shl edx,16 ; EDX <- DX:AX (length of file)
|
|
5809 00001BF3 89C2 <1> mov dx,ax
|
|
5810 00001BF5 B80020 <1> mov ax,xfer_buf_seg ; Use for temporary storage
|
|
5811 00001BF8 8EC0 <1> mov es,ax
|
|
5812 <1>
|
|
5813 00001BFA C606[CF08]07 <1> mov byte [TextAttribute],07h ; Default grey on white
|
|
5814 00001BFF C606[D008]07 <1> mov byte [DisplayMask],07h ; Display text in all modes
|
|
5815 00001C04 E87901 <1> call msg_initvars
|
|
5816 <1>
|
|
5817 00001C07 6652 <1> get_msg_chunk: push edx ; EDX = length of file
|
|
5818 00001C09 31DB <1> xor bx,bx ; == xbs_textbuf
|
|
5819 00001C0B 8B0E[0009] <1> mov cx,[BufSafe]
|
|
5820 00001C0F E8ACF9 <1> call getfssec
|
|
5821 00001C12 665A <1> pop edx
|
|
5822 00001C14 56 <1> push si ; Save current cluster
|
|
5823 00001C15 31F6 <1> xor si,si ; == xbs_textbuf
|
|
5824 00001C17 8B0E[0409] <1> mov cx,[BufSafeBytes] ; Number of bytes left in chunk
|
|
5825 <1> print_msg_file:
|
|
5826 00001C1B 51 <1> push cx
|
|
5827 00001C1C 6652 <1> push edx
|
|
5828 00001C1E 26AC <1> es lodsb
|
|
5829 00001C20 3C1A <1> cmp al,1Ah ; DOS EOF?
|
|
5830 00001C22 7418 <1> je msg_done_pop
|
|
5831 00001C24 56 <1> push si
|
|
5832 00001C25 8A0E[1001] <1> mov cl,[UsingVGA]
|
|
5833 00001C29 FEC1 <1> inc cl ; 01h = text mode, 02h = graphics
|
|
5834 00001C2B FF16[C408] <1> call [NextCharJump] ; Do what shall be done
|
|
5835 00001C2F 5E <1> pop si
|
|
5836 00001C30 665A <1> pop edx
|
|
5837 00001C32 59 <1> pop cx
|
|
5838 00001C33 664A <1> dec edx
|
|
5839 00001C35 7408 <1> jz msg_done
|
|
5840 00001C37 E2E2 <1> loop print_msg_file
|
|
5841 00001C39 5E <1> pop si
|
|
5842 00001C3A EBCB <1> jmp short get_msg_chunk
|
|
5843 <1> msg_done_pop:
|
|
5844 00001C3C 83C406 <1> add sp,byte 6 ; Drop pushed EDX, CX
|
|
5845 <1> msg_done:
|
|
5846 00001C3F 5E <1> pop si
|
|
5847 00001C40 07 <1> pop es
|
|
5848 00001C41 C3 <1> ret
|
|
5849 <1> msg_putchar: ; Normal character
|
|
5850 00001C42 3C0F <1> cmp al,0Fh ; ^O = color code follows
|
|
5851 00001C44 7467 <1> je msg_ctrl_o
|
|
5852 00001C46 3C0D <1> cmp al,0Dh ; Ignore <CR>
|
|
5853 00001C48 745A <1> je msg_ignore
|
|
5854 00001C4A 3C0A <1> cmp al,0Ah ; <LF> = newline
|
|
5855 00001C4C 7466 <1> je msg_newline
|
|
5856 00001C4E 3C0C <1> cmp al,0Ch ; <FF> = clear screen
|
|
5857 00001C50 0F849500 <1> je msg_formfeed
|
|
5858 00001C54 3C07 <1> cmp al,07h ; <BEL> = beep
|
|
5859 00001C56 744D <1> je msg_beep
|
|
5860 00001C58 3C19 <1> cmp al,19h ; <EM> = return to text mode
|
|
5861 00001C5A 0F840601 <1> je msg_novga
|
|
5862 00001C5E 3C18 <1> cmp al,18h ; <CAN> = VGA filename follows
|
|
5863 00001C60 0F84CF00 <1> je msg_vga
|
|
5864 00001C64 7306 <1> jnb .not_modectl
|
|
5865 00001C66 3C10 <1> cmp al,10h ; 10h to 17h are mode controls
|
|
5866 00001C68 0F832401 <1> jae msg_modectl
|
|
5867 <1> .not_modectl:
|
|
5868 <1>
|
|
5869 00001C6C E82801 <1> msg_normal: call write_serial_displaymask ; Write to serial port
|
|
5870 00001C6F 840E[D008] <1> test [DisplayMask],cl
|
|
5871 00001C73 742F <1> jz msg_ignore ; Not screen
|
|
5872 00001C75 F606[BE00]01 <1> test byte [DisplayCon],01h
|
|
5873 00001C7A 7428 <1> jz msg_ignore
|
|
5874 00001C7C 8A1E[CF08] <1> mov bl,[TextAttribute]
|
|
5875 00001C80 8A3E6204 <1> mov bh,[BIOS_page]
|
|
5876 00001C84 B409 <1> mov ah,09h ; Write character/attribute
|
|
5877 00001C86 B90100 <1> mov cx,1 ; One character only
|
|
5878 00001C89 CD10 <1> int 10h ; Write to screen
|
|
5879 00001C8B A0[C608] <1> mov al,[CursorCol]
|
|
5880 00001C8E 40 <1> inc ax
|
|
5881 00001C8F 3A06[C808] <1> cmp al,[VidCols]
|
|
5882 00001C93 7725 <1> ja msg_line_wrap ; Screen wraparound
|
|
5883 00001C95 A2[C608] <1> mov [CursorCol],al
|
|
5884 <1>
|
|
5885 00001C98 8A3E6204 <1> msg_gotoxy: mov bh,[BIOS_page]
|
|
5886 00001C9C 8B16[C608] <1> mov dx,[CursorDX]
|
|
5887 00001CA0 B402 <1> mov ah,02h ; Set cursor position
|
|
5888 00001CA2 CD10 <1> int 10h
|
|
5889 00001CA4 C3 <1> msg_ignore: ret
|
|
5890 <1>
|
|
5891 00001CA5 B8070E <1> msg_beep: mov ax,0E07h ; Beep
|
|
5892 00001CA8 31DB <1> xor bx,bx
|
|
5893 00001CAA CD10 <1> int 10h
|
|
5894 00001CAC C3 <1> ret
|
|
5895 <1>
|
|
5896 <1> msg_ctrl_o: ; ^O = color code follows
|
|
5897 00001CAD C706[C408][0A1D] <1> mov word [NextCharJump],msg_setbg
|
|
5898 00001CB3 C3 <1> ret
|
|
5899 <1> msg_newline: ; Newline char or end of line
|
|
5900 00001CB4 BE[E006] <1> mov si,crlf_msg
|
|
5901 00001CB7 E81001 <1> call write_serial_str_displaymask
|
|
5902 <1> msg_line_wrap: ; Screen wraparound
|
|
5903 00001CBA 840E[D008] <1> test [DisplayMask],cl
|
|
5904 00001CBE 74E4 <1> jz msg_ignore
|
|
5905 00001CC0 C606[C608]00 <1> mov byte [CursorCol],0
|
|
5906 00001CC5 A0[C708] <1> mov al,[CursorRow]
|
|
5907 00001CC8 40 <1> inc ax
|
|
5908 00001CC9 3A06[C908] <1> cmp al,[VidRows]
|
|
5909 00001CCD 7705 <1> ja msg_scroll
|
|
5910 00001CCF A2[C708] <1> mov [CursorRow],al
|
|
5911 00001CD2 EBC4 <1> jmp short msg_gotoxy
|
|
5912 00001CD4 31C9 <1> msg_scroll: xor cx,cx ; Upper left hand corner
|
|
5913 00001CD6 8B16[C808] <1> mov dx,[ScreenSize]
|
|
5914 00001CDA 8836[C708] <1> mov [CursorRow],dh ; New cursor at the bottom
|
|
5915 00001CDE 8A3E[C000] <1> mov bh,[ScrollAttribute]
|
|
5916 00001CE2 B80106 <1> mov ax,0601h ; Scroll up one line
|
|
5917 00001CE5 CD10 <1> int 10h
|
|
5918 00001CE7 EBAF <1> jmp short msg_gotoxy
|
|
5919 <1> msg_formfeed: ; Form feed character
|
|
5920 00001CE9 BE[E306] <1> mov si,crff_msg
|
|
5921 00001CEC E8DB00 <1> call write_serial_str_displaymask
|
|
5922 00001CEF 840E[D008] <1> test [DisplayMask],cl
|
|
5923 00001CF3 74AF <1> jz msg_ignore
|
|
5924 00001CF5 31C9 <1> xor cx,cx
|
|
5925 00001CF7 890E[C608] <1> mov [CursorDX],cx ; Upper lefthand corner
|
|
5926 00001CFB 8B16[C808] <1> mov dx,[ScreenSize]
|
|
5927 00001CFF 8A3E[CF08] <1> mov bh,[TextAttribute]
|
|
5928 00001D03 B80006 <1> mov ax,0600h ; Clear screen region
|
|
5929 00001D06 CD10 <1> int 10h
|
|
5930 00001D08 EB8E <1> jmp msg_gotoxy
|
|
5931 <1> msg_setbg: ; Color background character
|
|
5932 00001D0A E86BFE <1> call unhexchar
|
|
5933 00001D0D 722F <1> jc msg_color_bad
|
|
5934 00001D0F C0E004 <1> shl al,4
|
|
5935 00001D12 840E[D008] <1> test [DisplayMask],cl
|
|
5936 00001D16 7403 <1> jz .dontset
|
|
5937 00001D18 A2[CF08] <1> mov [TextAttribute],al
|
|
5938 <1> .dontset:
|
|
5939 00001D1B C706[C408][221D] <1> mov word [NextCharJump],msg_setfg
|
|
5940 00001D21 C3 <1> ret
|
|
5941 <1> msg_setfg: ; Color foreground character
|
|
5942 00001D22 E853FE <1> call unhexchar
|
|
5943 00001D25 7217 <1> jc msg_color_bad
|
|
5944 00001D27 840E[D008] <1> test [DisplayMask],cl
|
|
5945 00001D2B 7404 <1> jz .dontset
|
|
5946 00001D2D 0806[CF08] <1> or [TextAttribute],al ; setbg set foreground to 0
|
|
5947 <1> .dontset:
|
|
5948 00001D31 EB10 <1> jmp short msg_putcharnext
|
|
5949 <1> msg_vga:
|
|
5950 00001D33 C706[C408][4A1D] <1> mov word [NextCharJump],msg_filename
|
|
5951 00001D39 BF[791E] <1> mov di, VGAFileBuf
|
|
5952 00001D3C EB21 <1> jmp short msg_setvgafileptr
|
|
5953 <1>
|
|
5954 <1> msg_color_bad:
|
|
5955 00001D3E C606[CF08]07 <1> mov byte [TextAttribute],07h ; Default attribute
|
|
5956 <1> msg_putcharnext:
|
|
5957 00001D43 C706[C408][421C] <1> mov word [NextCharJump],msg_putchar
|
|
5958 00001D49 C3 <1> ret
|
|
5959 <1>
|
|
5960 <1> msg_filename: ; Getting VGA filename
|
|
5961 00001D4A 3C0A <1> cmp al,0Ah ; <LF> = end of filename
|
|
5962 00001D4C 741B <1> je msg_viewimage
|
|
5963 00001D4E 3C20 <1> cmp al,' '
|
|
5964 00001D50 7611 <1> jbe msg_ret ; Ignore space/control char
|
|
5965 00001D52 8B3E[661E] <1> mov di,[VGAFilePtr]
|
|
5966 00001D56 81FF[F91E] <1> cmp di,VGAFileBufEnd
|
|
5967 00001D5A 7307 <1> jnb msg_ret
|
|
5968 00001D5C 8805 <1> mov [di],al ; Can't use stosb (DS:)
|
|
5969 00001D5E 47 <1> inc di
|
|
5970 <1> msg_setvgafileptr:
|
|
5971 00001D5F 893E[661E] <1> mov [VGAFilePtr],di
|
|
5972 00001D63 C3 <1> msg_ret: ret
|
|
5973 <1>
|
|
5974 <1> msg_novga:
|
|
5975 00001D64 E8DE06 <1> call vgaclearmode
|
|
5976 00001D67 EB17 <1> jmp short msg_initvars
|
|
5977 <1>
|
|
5978 <1> msg_viewimage:
|
|
5979 00001D69 06 <1> push es
|
|
5980 00001D6A 1E <1> push ds
|
|
5981 00001D6B 07 <1> pop es ; ES <- DS
|
|
5982 00001D6C BE[791E] <1> mov si,VGAFileBuf
|
|
5983 00001D6F BF[F91E] <1> mov di,VGAFileMBuf
|
|
5984 00001D72 57 <1> push di
|
|
5985 00001D73 E8C5F7 <1> call mangle_name
|
|
5986 00001D76 5F <1> pop di
|
|
5987 00001D77 E863F5 <1> call searchdir
|
|
5988 00001D7A 07 <1> pop es
|
|
5989 00001D7B 74C6 <1> jz msg_putcharnext ; Not there
|
|
5990 00001D7D E83F05 <1> call vgadisplayfile
|
|
5991 <1> ; Fall through
|
|
5992 <1>
|
|
5993 <1> ; Subroutine to initialize variables, also needed
|
|
5994 <1> ; after loading a graphics file
|
|
5995 <1> msg_initvars:
|
|
5996 00001D80 60 <1> pusha
|
|
5997 00001D81 8A3E6204 <1> mov bh,[BIOS_page]
|
|
5998 00001D85 B403 <1> mov ah,03h ; Read cursor position
|
|
5999 00001D87 CD10 <1> int 10h
|
|
6000 00001D89 8916[C608] <1> mov [CursorDX],dx
|
|
6001 00001D8D 61 <1> popa
|
|
6002 00001D8E EBB3 <1> jmp short msg_putcharnext ; Initialize state machine
|
|
6003 <1>
|
|
6004 <1> msg_modectl:
|
|
6005 00001D90 2407 <1> and al,07h
|
|
6006 00001D92 A2[D008] <1> mov [DisplayMask],al
|
|
6007 00001D95 EBAC <1> jmp short msg_putcharnext
|
|
6008 <1>
|
|
6009 <1> ;
|
|
6010 <1> ; write_serial: If serial output is enabled, write character on serial port
|
|
6011 <1> ; write_serial_displaymask: d:o, but ignore if DisplayMask & 04h == 0
|
|
6012 <1> ;
|
|
6013 <1> write_serial_displaymask:
|
|
6014 00001D97 F606[D008]04 <1> test byte [DisplayMask], 04h
|
|
6015 00001D9C 742B <1> jz write_serial.end
|
|
6016 <1> write_serial:
|
|
6017 00001D9E 669C <1> pushfd
|
|
6018 00001DA0 6660 <1> pushad
|
|
6019 00001DA2 8B1E[F600] <1> mov bx,[SerialPort]
|
|
6020 00001DA6 21DB <1> and bx,bx
|
|
6021 00001DA8 741B <1> je .noserial
|
|
6022 00001DAA 50 <1> push ax
|
|
6023 00001DAB 8A26[CD08] <1> mov ah,[FlowInput]
|
|
6024 <1> .waitspace:
|
|
6025 <1> ; Wait for space in transmit register
|
|
6026 00001DAF 8D5705 <1> lea dx,[bx+5] ; DX -> LSR
|
|
6027 00001DB2 EC <1> in al,dx
|
|
6028 00001DB3 A820 <1> test al,20h
|
|
6029 00001DB5 74F8 <1> jz .waitspace
|
|
6030 <1>
|
|
6031 <1> ; Wait for input flow control
|
|
6032 00001DB7 42 <1> inc dx ; DX -> MSR
|
|
6033 00001DB8 EC <1> in al,dx
|
|
6034 00001DB9 20E0 <1> and al,ah
|
|
6035 00001DBB 38E0 <1> cmp al,ah
|
|
6036 00001DBD 75F0 <1> jne .waitspace
|
|
6037 <1> .no_flow:
|
|
6038 <1>
|
|
6039 00001DBF 87D3 <1> xchg dx,bx ; DX -> THR
|
|
6040 00001DC1 58 <1> pop ax
|
|
6041 00001DC2 E8(C600) <1> call slow_out ; Send data
|
|
6042 00001DC5 6661 <1> .noserial: popad
|
|
6043 00001DC7 669D <1> popfd
|
|
6044 00001DC9 C3 <1> .end: ret
|
|
6045 <1>
|
|
6046 <1> ;
|
|
6047 <1> ; write_serial_str: write_serial for strings
|
|
6048 <1> ; write_serial_str_displaymask: d:o, but ignore if DisplayMask & 04h == 0
|
|
6049 <1> ;
|
|
6050 <1> write_serial_str_displaymask:
|
|
6051 00001DCA F606[D008]04 <1> test byte [DisplayMask], 04h
|
|
6052 00001DCF 740A <1> jz write_serial_str.end
|
|
6053 <1>
|
|
6054 <1> write_serial_str:
|
|
6055 00001DD1 AC <1> .loop lodsb
|
|
6056 00001DD2 20C0 <1> and al,al
|
|
6057 00001DD4 7405 <1> jz .end
|
|
6058 00001DD6 E8C5FF <1> call write_serial
|
|
6059 00001DD9 EBF6 <1> jmp short .loop
|
|
6060 00001DDB C3 <1> .end: ret
|
|
6061 <1>
|
|
6062 <1> ;
|
|
6063 <1> ; pollchar: check if we have an input character pending (ZF = 0)
|
|
6064 <1> ;
|
|
6065 <1> pollchar:
|
|
6066 00001DDC 6660 <1> pushad
|
|
6067 00001DDE B411 <1> mov ah,11h ; Poll keyboard
|
|
6068 00001DE0 CD16 <1> int 16h
|
|
6069 00001DE2 751F <1> jnz .done ; Keyboard response
|
|
6070 00001DE4 8B16[F600] <1> mov dx,[SerialPort]
|
|
6071 00001DE8 21D2 <1> and dx,dx
|
|
6072 00001DEA 7417 <1> jz .done ; No serial port -> no input
|
|
6073 00001DEC 83C205 <1> add dx,byte 5 ; DX -> LSR
|
|
6074 00001DEF EC <1> in al,dx
|
|
6075 00001DF0 A801 <1> test al,1 ; ZF = 0 if data pending
|
|
6076 00001DF2 740F <1> jz .done
|
|
6077 00001DF4 42 <1> inc dx ; DX -> MSR
|
|
6078 00001DF5 8A26[CE08] <1> mov ah,[FlowIgnore] ; Required status bits
|
|
6079 00001DF9 EC <1> in al,dx
|
|
6080 00001DFA 20E0 <1> and al,ah
|
|
6081 00001DFC 38E0 <1> cmp al,ah
|
|
6082 00001DFE 0F95C0 <1> setne al
|
|
6083 00001E01 FEC8 <1> dec al ; Set ZF = 0 if equal
|
|
6084 00001E03 6661 <1> .done: popad
|
|
6085 00001E05 C3 <1> ret
|
|
6086 <1>
|
|
6087 <1> ;
|
|
6088 <1> ; getchar: Read a character from keyboard or serial port
|
|
6089 <1> ;
|
|
6090 <1> getchar:
|
|
6091 <1> RESET_IDLE
|
|
6092 00001E06 E8DEFB <2> call reset_idle
|
|
6093 <1> .again:
|
|
6094 <1> DO_IDLE
|
|
6095 00001E09 E8E6FB <2> call check_for_arp
|
|
6096 00001E0C B411 <1> mov ah,11h ; Poll keyboard
|
|
6097 00001E0E CD16 <1> int 16h
|
|
6098 00001E10 7522 <1> jnz .kbd ; Keyboard input?
|
|
6099 00001E12 8B1E[F600] <1> mov bx,[SerialPort]
|
|
6100 00001E16 21DB <1> and bx,bx
|
|
6101 00001E18 74EF <1> jz .again
|
|
6102 00001E1A 8D5705 <1> lea dx,[bx+5] ; DX -> LSR
|
|
6103 00001E1D EC <1> in al,dx
|
|
6104 00001E1E A801 <1> test al,1
|
|
6105 00001E20 74E7 <1> jz .again
|
|
6106 00001E22 42 <1> inc dx ; DX -> MSR
|
|
6107 00001E23 8A26[CE08] <1> mov ah,[FlowIgnore]
|
|
6108 00001E27 EC <1> in al,dx
|
|
6109 00001E28 20E0 <1> and al,ah
|
|
6110 00001E2A 38E0 <1> cmp al,ah
|
|
6111 00001E2C 75DB <1> jne .again
|
|
6112 00001E2E 30E4 <1> .serial: xor ah,ah ; Avoid confusion
|
|
6113 00001E30 87D3 <1> xchg dx,bx ; Data port
|
|
6114 00001E32 EC <1> in al,dx
|
|
6115 00001E33 C3 <1> ret
|
|
6116 00001E34 B410 <1> .kbd: mov ah,10h ; Get keyboard input
|
|
6117 00001E36 CD16 <1> int 16h
|
|
6118 00001E38 3CE0 <1> cmp al,0E0h
|
|
6119 00001E3A 7502 <1> jnz .not_ext
|
|
6120 00001E3C 30C0 <1> xor al,al
|
|
6121 <1> .not_ext:
|
|
6122 00001E3E 20C0 <1> and al,al
|
|
6123 00001E40 7404 <1> jz .func_key
|
|
6124 00001E42 BB[DC15] <1> mov bx,KbdMap ; Convert character sets
|
|
6125 00001E45 D7 <1> xlatb
|
|
6126 00001E46 C3 <1> .func_key: ret
|
|
6127 <1>
|
|
6128 <1> %ifdef DEBUG_TRACERS
|
|
6129 <1> ;
|
|
6130 <1> ; debug hack to print a character with minimal code impact
|
|
6131 <1> ;
|
|
6132 <1> debug_tracer: pushad
|
|
6133 <1> pushfd
|
|
6134 <1> mov bp,sp
|
|
6135 <1> mov bx,[bp+9*4] ; Get return address
|
|
6136 <1> mov al,[cs:bx] ; Get data byte
|
|
6137 <1> inc word [bp+9*4] ; Return to after data byte
|
|
6138 <1> call writechr
|
|
6139 <1> popfd
|
|
6140 <1> popad
|
|
6141 <1> ret
|
|
6142 <1> %endif ; DEBUG_TRACERS
|
|
6143 <1>
|
|
6144 <1> section .data
|
|
6145 <1> ; This is a word to pc_setint16 can set it
|
|
6146 000000BE 0100 <1> DisplayCon dw 01h ; Console display enabled
|
|
6147 <1>
|
|
6148 000000C0 07 <1> ScrollAttribute db 07h ; Grey on white (normal text color)
|
|
6149 <1>
|
|
6150 <1> section .bss
|
|
6151 <1> alignb 2
|
|
6152 000008C4 <res 00000002> <1> NextCharJump resw 1 ; Routine to interpret next print char
|
|
6153 <1> CursorDX equ $
|
|
6154 000008C6 <res 00000001> <1> CursorCol resb 1 ; Cursor column for message file
|
|
6155 000008C7 <res 00000001> <1> CursorRow resb 1 ; Cursor row for message file
|
|
6156 <1> ScreenSize equ $
|
|
6157 000008C8 <res 00000001> <1> VidCols resb 1 ; Columns on screen-1
|
|
6158 000008C9 <res 00000001> <1> VidRows resb 1 ; Rows on screen-1
|
|
6159 <1>
|
|
6160 <1> ; Serial console stuff...
|
|
6161 000008CA <res 00000002> <1> BaudDivisor resw 1 ; Baud rate divisor
|
|
6162 <1> FlowControl equ $
|
|
6163 000008CC <res 00000001> <1> FlowOutput resb 1 ; Outputs to assert for serial flow
|
|
6164 000008CD <res 00000001> <1> FlowInput resb 1 ; Input bits for serial flow
|
|
6165 000008CE <res 00000001> <1> FlowIgnore resb 1 ; Ignore input unless these bits set
|
|
6166 <1>
|
|
6167 000008CF <res 00000001> <1> TextAttribute resb 1 ; Text attribute for message file
|
|
6168 000008D0 <res 00000001> <1> DisplayMask resb 1 ; Display modes mask
|
|
6169 %include "writestr.inc" ; String output
|
|
6170 <1> ;; $Id: writestr.inc,v 1.5 2005/01/18 13:13:50 hpa Exp $
|
|
6171 <1> ;; -----------------------------------------------------------------------
|
|
6172 <1> ;;
|
|
6173 <1> ;; Copyright 1994-2002 H. Peter Anvin - All Rights Reserved
|
|
6174 <1> ;;
|
|
6175 <1> ;; This program is free software; you can redistribute it and/or modify
|
|
6176 <1> ;; it under the terms of the GNU General Public License as published by
|
|
6177 <1> ;; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
|
|
6178 <1> ;; Boston MA 02111-1307, USA; either version 2 of the License, or
|
|
6179 <1> ;; (at your option) any later version; incorporated herein by reference.
|
|
6180 <1> ;;
|
|
6181 <1> ;; -----------------------------------------------------------------------
|
|
6182 <1>
|
|
6183 <1> ;;
|
|
6184 <1> ;; writestr.inc
|
|
6185 <1> ;;
|
|
6186 <1> ;; Code to write a simple string.
|
|
6187 <1> ;;
|
|
6188 <1>
|
|
6189 <1> section .text
|
|
6190 <1> ;
|
|
6191 <1> ; crlf: Print a newline
|
|
6192 <1> ;
|
|
6193 00001E47 50 <1> crlf: push ax
|
|
6194 00001E48 B00D <1> mov al,CR
|
|
6195 00001E4A E83807 <1> call writechr
|
|
6196 00001E4D B00A <1> mov al,LF
|
|
6197 00001E4F E83307 <1> call writechr
|
|
6198 00001E52 58 <1> pop ax
|
|
6199 00001E53 C3 <1> ret
|
|
6200 <1>
|
|
6201 <1> ;
|
|
6202 <1> ; cwritestr: write a null-terminated string to the console, saving
|
|
6203 <1> ; registers on entry.
|
|
6204 <1> ;
|
|
6205 <1> ; Note: writestr and cwritestr are distinct in SYSLINUX (only)
|
|
6206 <1> ;
|
|
6207 <1> cwritestr:
|
|
6208 00001E54 669C <1> pushfd
|
|
6209 00001E56 6660 <1> pushad
|
|
6210 00001E58 AC <1> .top: lodsb
|
|
6211 00001E59 20C0 <1> and al,al
|
|
6212 00001E5B 7405 <1> jz .end
|
|
6213 00001E5D E82507 <1> call writechr
|
|
6214 00001E60 EBF6 <1> jmp short .top
|
|
6215 00001E62 6661 <1> .end: popad
|
|
6216 00001E64 669D <1> popfd
|
|
6217 00001E66 C3 <1> ret
|
|
6218 writestr equ cwritestr
|
|
6219 %include "writehex.inc" ; Hexadecimal output
|
|
6220 <1> ;; $Id: writehex.inc,v 1.3 2005/01/18 13:13:50 hpa Exp $
|
|
6221 <1> ;; -----------------------------------------------------------------------
|
|
6222 <1> ;;
|
|
6223 <1> ;; Copyright 1994-2002 H. Peter Anvin - All Rights Reserved
|
|
6224 <1> ;;
|
|
6225 <1> ;; This program is free software; you can redistribute it and/or modify
|
|
6226 <1> ;; it under the terms of the GNU General Public License as published by
|
|
6227 <1> ;; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
|
|
6228 <1> ;; Boston MA 02111-1307, USA; either version 2 of the License, or
|
|
6229 <1> ;; (at your option) any later version; incorporated herein by reference.
|
|
6230 <1> ;;
|
|
6231 <1> ;; -----------------------------------------------------------------------
|
|
6232 <1>
|
|
6233 <1> ;;
|
|
6234 <1> ;; writehex.inc
|
|
6235 <1> ;;
|
|
6236 <1> ;; Write hexadecimal numbers to the console
|
|
6237 <1> ;;
|
|
6238 <1>
|
|
6239 <1> section .text
|
|
6240 <1> ;
|
|
6241 <1> ; writehex[248]: Write a hex number in (AL, AX, EAX) to the console
|
|
6242 <1> ;
|
|
6243 <1> writehex2:
|
|
6244 00001E67 669C <1> pushfd
|
|
6245 00001E69 6660 <1> pushad
|
|
6246 00001E6B 66C1C018 <1> rol eax,24
|
|
6247 00001E6F B90200 <1> mov cx,2
|
|
6248 00001E72 EB14 <1> jmp short writehex_common
|
|
6249 <1> writehex4:
|
|
6250 00001E74 669C <1> pushfd
|
|
6251 00001E76 6660 <1> pushad
|
|
6252 00001E78 66C1C010 <1> rol eax,16
|
|
6253 00001E7C B90400 <1> mov cx,4
|
|
6254 00001E7F EB07 <1> jmp short writehex_common
|
|
6255 <1> writehex8:
|
|
6256 00001E81 669C <1> pushfd
|
|
6257 00001E83 6660 <1> pushad
|
|
6258 00001E85 B90800 <1> mov cx,8
|
|
6259 <1> writehex_common:
|
|
6260 00001E88 66C1C004 <1> .loop: rol eax,4
|
|
6261 00001E8C 6650 <1> push eax
|
|
6262 00001E8E 240F <1> and al,0Fh
|
|
6263 00001E90 3C0A <1> cmp al,10
|
|
6264 00001E92 7304 <1> jae .high
|
|
6265 00001E94 0430 <1> .low: add al,'0'
|
|
6266 00001E96 EB02 <1> jmp short .ischar
|
|
6267 00001E98 0437 <1> .high: add al,'A'-10
|
|
6268 00001E9A E8E806 <1> .ischar: call writechr
|
|
6269 00001E9D 6658 <1> pop eax
|
|
6270 00001E9F E2E7 <1> loop .loop
|
|
6271 00001EA1 6661 <1> popad
|
|
6272 00001EA3 669D <1> popfd
|
|
6273 00001EA5 C3 <1> ret
|
|
6274 <1>
|
|
6275 %include "parseconfig.inc" ; High-level config file handling
|
|
6276 <1> ;; $Id: parseconfig.inc,v 1.22 2005/04/06 09:53:39 hpa Exp $
|
|
6277 <1> ;; -----------------------------------------------------------------------
|
|
6278 <1> ;;
|
|
6279 <1> ;; Copyright 1994-2004 H. Peter Anvin - All Rights Reserved
|
|
6280 <1> ;;
|
|
6281 <1> ;; This program is free software; you can redistribute it and/or modify
|
|
6282 <1> ;; it under the terms of the GNU General Public License as published by
|
|
6283 <1> ;; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
|
|
6284 <1> ;; Boston MA 02111-1307, USA; either version 2 of the License, or
|
|
6285 <1> ;; (at your option) any later version; incorporated herein by reference.
|
|
6286 <1> ;;
|
|
6287 <1> ;; -----------------------------------------------------------------------
|
|
6288 <1>
|
|
6289 <1> ;;
|
|
6290 <1> ;; parseconfig.inc
|
|
6291 <1> ;;
|
|
6292 <1> ;; Configuration file operations
|
|
6293 <1> ;;
|
|
6294 <1>
|
|
6295 <1> section .text
|
|
6296 <1> ;
|
|
6297 <1> ; "default" command
|
|
6298 <1> ;
|
|
6299 00001EA6 BF[D80A] <1> pc_default: mov di,default_cmd
|
|
6300 00001EA9 E8E6FC <1> call getline
|
|
6301 00001EAC C645FF00 <1> mov byte [di-1],0 ; null-terminate
|
|
6302 00001EB0 C3 <1> ret
|
|
6303 <1>
|
|
6304 <1> ;
|
|
6305 <1> ; "ontimeout" command
|
|
6306 <1> ;
|
|
6307 00001EB1 BF[DC11] <1> pc_ontimeout: mov di,Ontimeout
|
|
6308 00001EB4 E8DBFC <1> call getline
|
|
6309 00001EB7 81EF[DD11] <1> sub di,Ontimeout+1 ; Don't need final space
|
|
6310 00001EBB 893E[E800] <1> mov [OntimeoutLen],di
|
|
6311 00001EBF C3 <1> ret
|
|
6312 <1>
|
|
6313 <1> ;
|
|
6314 <1> ; "onerror" command
|
|
6315 <1> ;
|
|
6316 00001EC0 BF[DC13] <1> pc_onerror: mov di,Onerror
|
|
6317 00001EC3 E8CCFC <1> call getline
|
|
6318 00001EC6 81EF[DC13] <1> sub di,Onerror
|
|
6319 00001ECA 893E[EA00] <1> mov [OnerrorLen],di
|
|
6320 00001ECE C3 <1> ret
|
|
6321 <1>
|
|
6322 <1> ;
|
|
6323 <1> ; "append" command
|
|
6324 <1> ;
|
|
6325 00001ECF 803E[FA00]00 <1> pc_append: cmp byte [VKernel],0
|
|
6326 00001ED4 770F <1> ja .vk
|
|
6327 00001ED6 BF[DC0F] <1> mov di,AppendBuf
|
|
6328 00001ED9 E8B6FC <1> call getline
|
|
6329 00001EDC 81EF[DC0F] <1> sub di,AppendBuf
|
|
6330 00001EE0 893E[E600] <1> .app1: mov [AppendLen],di
|
|
6331 00001EE4 C3 <1> ret
|
|
6332 00001EE5 BF[DC0D] <1> .vk: mov di,VKernelBuf+vk_append ; "append" command (vkernel)
|
|
6333 00001EE8 E8A7FC <1> call getline
|
|
6334 00001EEB 81EF[DC0D] <1> sub di,VKernelBuf+vk_append
|
|
6335 00001EEF 83FF02 <1> cmp di,byte 2
|
|
6336 00001EF2 7509 <1> jne .app2
|
|
6337 00001EF4 803E[DC0D]2D <1> cmp byte [VKernelBuf+vk_append],'-'
|
|
6338 00001EF9 7502 <1> jne .app2
|
|
6339 00001EFB 31FF <1> xor di,di ; If "append -" -> null string
|
|
6340 00001EFD 893E[DA0D] <1> .app2: mov [VKernelBuf+vk_appendlen],di
|
|
6341 00001F01 C3 <1> ret
|
|
6342 <1>
|
|
6343 <1> ;
|
|
6344 <1> ; "ipappend" command (PXELINUX only)
|
|
6345 <1> ;
|
|
6346 <1> %if IS_PXELINUX
|
|
6347 00001F02 E8D9FB <1> pc_ipappend: call getint
|
|
6348 00001F05 720B <1> jc .err
|
|
6349 00001F07 803E[FA00]00 <1> cmp byte [VKernel],0
|
|
6350 00001F0C 7505 <1> jne .vk
|
|
6351 00001F0E 881E[0809] <1> mov [IPAppend],bl
|
|
6352 00001F12 C3 <1> .err: ret
|
|
6353 00001F13 881E[D80D] <1> .vk: mov [VKernelBuf+vk_ipappend],bl
|
|
6354 00001F17 C3 <1> ret
|
|
6355 <1> %endif
|
|
6356 <1>
|
|
6357 <1> ;
|
|
6358 <1> ; "localboot" command (PXELINUX, ISOLINUX)
|
|
6359 <1> ;
|
|
6360 <1> %if IS_PXELINUX || IS_ISOLINUX
|
|
6361 00001F18 E8C3FB <1> pc_localboot: call getint
|
|
6362 00001F1B 803E[FA00]00 <1> cmp byte [VKernel],0 ; ("label" section only)
|
|
6363 00001F20 740E <1> je .err
|
|
6364 00001F22 BF[580D] <1> mov di,VKernelBuf+vk_rname
|
|
6365 00001F25 31C0 <1> xor ax,ax
|
|
6366 00001F27 B98000 <1> mov cx,FILENAME_MAX
|
|
6367 00001F2A F3AA <1> rep stosb ; Null kernel name
|
|
6368 <1> %if IS_PXELINUX
|
|
6369 <1> ; PXELINUX uses the first 4 bytes of vk_rname for the
|
|
6370 <1> ; mangled IP address
|
|
6371 00001F2C 891E[5D0D] <1> mov [VKernelBuf+vk_rname+5], bx ; Return type
|
|
6372 <1> %else
|
|
6373 <1> mov [VKernelBuf+vk_rname+1], bx ; Return type
|
|
6374 <1> %endif
|
|
6375 00001F30 C3 <1> .err: ret
|
|
6376 <1> %endif
|
|
6377 <1>
|
|
6378 <1> ;
|
|
6379 <1> ; "kernel" command
|
|
6380 00001F31 803E[FA00]00 <1> pc_kernel: cmp byte [VKernel],0
|
|
6381 00001F36 7409 <1> je .err ; ("label" section only)
|
|
6382 00001F38 E84001 <1> call pc_getline
|
|
6383 00001F3B BF[580D] <1> mov di,VKernelBuf+vk_rname
|
|
6384 00001F3E E8FAF5 <1> call mangle_name
|
|
6385 00001F41 C3 <1> .err: ret
|
|
6386 <1>
|
|
6387 <1> ;
|
|
6388 <1> ; "timeout" command
|
|
6389 <1> ;
|
|
6390 00001F42 E899FB <1> pc_timeout: call getint
|
|
6391 00001F45 720B <1> jc .err
|
|
6392 00001F47 B815D2 <1> mov ax,0D215h ; There are approx 1.D215h
|
|
6393 00001F4A F7E3 <1> mul bx ; clock ticks per 1/10 s
|
|
6394 00001F4C 01D3 <1> add bx,dx
|
|
6395 00001F4E 891E[EC00] <1> mov [KbdTimeOut],bx
|
|
6396 00001F52 C3 <1> .err: ret
|
|
6397 <1>
|
|
6398 <1> ;
|
|
6399 <1> ; Generic integer variable setting commands:
|
|
6400 <1> ; "prompt", "implicit"
|
|
6401 <1> ;
|
|
6402 <1> pc_setint16:
|
|
6403 00001F53 50 <1> push ax
|
|
6404 00001F54 E887FB <1> call getint
|
|
6405 00001F57 5E <1> pop si
|
|
6406 00001F58 7202 <1> jc .err
|
|
6407 00001F5A 891C <1> mov [si],bx
|
|
6408 00001F5C C3 <1> .err: ret
|
|
6409 <1>
|
|
6410 <1> ;
|
|
6411 <1> ; Generic file-processing commands:
|
|
6412 <1> ; "display", "font", "kbdmap"
|
|
6413 <1> ;
|
|
6414 00001F5D 50 <1> pc_filecmd: push ax ; Function to tailcall
|
|
6415 00001F5E E81A01 <1> call pc_getline
|
|
6416 00001F61 BF[601D] <1> mov di,MNameBuf
|
|
6417 00001F64 57 <1> push di
|
|
6418 00001F65 E8D3F5 <1> call mangle_name
|
|
6419 00001F68 5F <1> pop di
|
|
6420 00001F69 E871F3 <1> call searchdir ; tailcall
|
|
6421 00001F6C 7501 <1> jnz .ok
|
|
6422 00001F6E 58 <1> pop ax ; Drop the successor function
|
|
6423 00001F6F C3 <1> .ok: ret ; Tailcall if OK, error return
|
|
6424 <1>
|
|
6425 <1> ;
|
|
6426 <1> ; "serial" command
|
|
6427 <1> ;
|
|
6428 00001F70 E86BFB <1> pc_serial: call getint
|
|
6429 00001F73 7207 <1> jc .err
|
|
6430 00001F75 53 <1> push bx ; Serial port #
|
|
6431 00001F76 E84CFB <1> call skipspace
|
|
6432 00001F79 7302 <1> jnc .ok
|
|
6433 00001F7B 5B <1> pop bx
|
|
6434 00001F7C C3 <1> .err: ret
|
|
6435 <1> .ok:
|
|
6436 00001F7D E834FB <1> call ungetc
|
|
6437 00001F80 E85BFB <1> call getint
|
|
6438 00001F83 C706[CC08]0000 <1> mov [FlowControl], word 0 ; Default to no flow control
|
|
6439 00001F89 7229 <1> jc .nobaud
|
|
6440 <1> .valid_baud:
|
|
6441 00001F8B 6653 <1> push ebx
|
|
6442 00001F8D E835FB <1> call skipspace
|
|
6443 00001F90 7208 <1> jc .no_flow
|
|
6444 00001F92 E81FFB <1> call ungetc
|
|
6445 00001F95 E846FB <1> call getint ; Hardware flow control?
|
|
6446 00001F98 7302 <1> jnc .valid_flow
|
|
6447 <1> .no_flow:
|
|
6448 00001F9A 31DB <1> xor bx,bx ; Default -> no flow control
|
|
6449 <1> .valid_flow:
|
|
6450 00001F9C 80E70F <1> and bh,0Fh ; FlowIgnore
|
|
6451 00001F9F C0E704 <1> shl bh,4
|
|
6452 00001FA2 883E[CE08] <1> mov [FlowIgnore],bh
|
|
6453 00001FA6 88DF <1> mov bh,bl
|
|
6454 00001FA8 81E303F0 <1> and bx,0F003h ; Valid bits
|
|
6455 00001FAC 891E[CC08] <1> mov [FlowControl],bx
|
|
6456 00001FB0 665B <1> pop ebx ; Baud rate
|
|
6457 00001FB2 EB06 <1> jmp short .parse_baud
|
|
6458 <1> .nobaud:
|
|
6459 00001FB4 66BB80250000 <1> mov ebx,DEFAULT_BAUD ; No baud rate given
|
|
6460 <1> .parse_baud:
|
|
6461 00001FBA 5F <1> pop di ; Serial port #
|
|
6462 00001FBB 6683FB4B <1> cmp ebx,byte 75
|
|
6463 00001FBF 72BB <1> jb .err ; < 75 baud == bogus
|
|
6464 00001FC1 66B800C20100 <1> mov eax,BAUD_DIVISOR
|
|
6465 00001FC7 6699 <1> cdq
|
|
6466 00001FC9 66F7F3 <1> div ebx
|
|
6467 00001FCC A3[CA08] <1> mov [BaudDivisor],ax
|
|
6468 00001FCF 50 <1> push ax ; Baud rate divisor
|
|
6469 00001FD0 83FF03 <1> cmp di,3
|
|
6470 00001FD3 7706 <1> ja .port_is_io ; If port > 3 then port is I/O addr
|
|
6471 00001FD5 D1E7 <1> shl di,1
|
|
6472 00001FD7 8BBD0004 <1> mov di,[di+serial_base] ; Get the I/O port from the BIOS
|
|
6473 <1> .port_is_io:
|
|
6474 00001FDB 893E[F600] <1> mov [SerialPort],di
|
|
6475 00001FDF 8D5503 <1> lea dx,[di+3] ; DX -> LCR
|
|
6476 00001FE2 B083 <1> mov al,83h ; Enable DLAB
|
|
6477 00001FE4 E8(C600) <1> call slow_out
|
|
6478 00001FE7 58 <1> pop ax ; Divisor
|
|
6479 00001FE8 89FA <1> mov dx,di ; DX -> LS
|
|
6480 00001FEA E8(C600) <1> call slow_out
|
|
6481 00001FED 42 <1> inc dx ; DX -> MS
|
|
6482 00001FEE 88E0 <1> mov al,ah
|
|
6483 00001FF0 E8(C600) <1> call slow_out
|
|
6484 00001FF3 B003 <1> mov al,03h ; Disable DLAB
|
|
6485 00001FF5 83C202 <1> add dx,byte 2 ; DX -> LCR
|
|
6486 00001FF8 E8(C600) <1> call slow_out
|
|
6487 00001FFB EC <1> in al,dx ; Read back LCR (detect missing hw)
|
|
6488 00001FFC 3C03 <1> cmp al,03h ; If nothing here we'll read 00 or FF
|
|
6489 00001FFE 7520 <1> jne .serial_port_bad ; Assume serial port busted
|
|
6490 00002000 83EA02 <1> sub dx,byte 2 ; DX -> IER
|
|
6491 00002003 30C0 <1> xor al,al ; IRQ disable
|
|
6492 00002005 E8(C600) <1> call slow_out
|
|
6493 <1>
|
|
6494 00002008 83C203 <1> add dx,byte 3 ; DX -> MCR
|
|
6495 0000200B EC <1> in al,dx
|
|
6496 0000200C 0A06[CC08] <1> or al,[FlowOutput] ; Assert bits
|
|
6497 00002010 E8(C600) <1> call slow_out
|
|
6498 <1>
|
|
6499 <1> ; Show some life
|
|
6500 00002013 BE[EE06] <1> mov si,syslinux_banner
|
|
6501 00002016 E8B8FD <1> call write_serial_str
|
|
6502 00002019 BE[4B01] <1> mov si,copyright_str
|
|
6503 0000201C E8B2FD <1> call write_serial_str
|
|
6504 0000201F C3 <1> ret
|
|
6505 <1>
|
|
6506 <1> .serial_port_bad:
|
|
6507 00002020 C706[F600]0000 <1> mov [SerialPort], word 0
|
|
6508 00002026 C3 <1> ret
|
|
6509 <1>
|
|
6510 <1> ;
|
|
6511 <1> ; "F"-key command
|
|
6512 <1> ;
|
|
6513 00002027 50 <1> pc_fkey: push ax
|
|
6514 00002028 E85000 <1> call pc_getline
|
|
6515 0000202B 5F <1> pop di
|
|
6516 0000202C E80CF5 <1> call mangle_name ; Mangle file name
|
|
6517 0000202F C3 <1> ret
|
|
6518 <1>
|
|
6519 <1> ;
|
|
6520 <1> ; "label" command
|
|
6521 <1> ;
|
|
6522 00002030 E86300 <1> pc_label: call commit_vk ; Commit any current vkernel
|
|
6523 00002033 BF[D80C] <1> mov di,VKernelBuf ; Erase the vkernelbuf for better compression
|
|
6524 00002036 B98201 <1> mov cx,(vk_size >> 1)
|
|
6525 00002039 31C0 <1> xor ax,ax
|
|
6526 0000203B F3AB <1> rep stosw
|
|
6527 0000203D E83B00 <1> call pc_getline
|
|
6528 00002040 BF[D80C] <1> mov di,VKernelBuf+vk_vname
|
|
6529 00002043 E8F5F4 <1> call mangle_name ; Mangle virtual name
|
|
6530 00002046 C606[FA00]01 <1> mov byte [VKernel],1 ; We've seen a "label" statement
|
|
6531 0000204B BE[D80C] <1> mov si,VKernelBuf+vk_vname ; By default, rname == vname
|
|
6532 0000204E BF[580D] <1> mov di,VKernelBuf+vk_rname
|
|
6533 00002051 B98000 <1> mov cx,FILENAME_MAX
|
|
6534 00002054 F3A4 <1> rep movsb
|
|
6535 00002056 BE[DC0F] <1> mov si,AppendBuf ; Default append==global append
|
|
6536 00002059 BF[DC0D] <1> mov di,VKernelBuf+vk_append
|
|
6537 0000205C 8B0E[E600] <1> mov cx,[AppendLen]
|
|
6538 00002060 890E[DA0D] <1> mov [VKernelBuf+vk_appendlen],cx
|
|
6539 00002064 F3A4 <1> rep movsb
|
|
6540 <1> %if IS_PXELINUX ; PXELINUX only
|
|
6541 00002066 A0[0809] <1> mov al,[IPAppend] ; Default ipappend==global ipappend
|
|
6542 00002069 A2[D80D] <1> mov [VKernelBuf+vk_ipappend],al
|
|
6543 <1> %endif
|
|
6544 0000206C C3 <1> ret
|
|
6545 <1>
|
|
6546 <1> ;
|
|
6547 <1> ; "say" command
|
|
6548 <1> ;
|
|
6549 0000206D E80B00 <1> pc_say: call pc_getline ; "say" command
|
|
6550 00002070 E8E1FD <1> call writestr
|
|
6551 00002073 E9D1FD <1> jmp crlf ; tailcall
|
|
6552 <1>
|
|
6553 <1> ;
|
|
6554 <1> ; "noescape" command
|
|
6555 <1> ;
|
|
6556 <1> pc_noescape:
|
|
6557 00002076 C606[8408]00 <1> mov byte [KbdFlags],0
|
|
6558 <1> ; Fall into pc_getline
|
|
6559 <1>
|
|
6560 <1> ;
|
|
6561 <1> ; Comment line
|
|
6562 <1> ;
|
|
6563 <1> pc_comment: ; Fall into pc_getline
|
|
6564 <1>
|
|
6565 <1> ;
|
|
6566 <1> ; Common subroutine: load line into trackbuf; returns with SI -> trackbuf
|
|
6567 <1> ;
|
|
6568 0000207B BF[0000] <1> pc_getline: mov di,trackbuf
|
|
6569 0000207E 57 <1> push di
|
|
6570 0000207F E810FB <1> call getline
|
|
6571 00002082 30C0 <1> xor al,al
|
|
6572 00002084 AA <1> stosb ; Null-terminate
|
|
6573 00002085 5E <1> pop si
|
|
6574 00002086 C3 <1> ret
|
|
6575 <1>
|
|
6576 <1> ;
|
|
6577 <1> ; Main loop for configuration file parsing
|
|
6578 <1> ;
|
|
6579 <1> parse_config:
|
|
6580 00002087 BF[D80C] <1> mov di,VKernelBuf ; Clear VKernelBuf at start
|
|
6581 0000208A 31C0 <1> xor ax,ax
|
|
6582 0000208C B90403 <1> mov cx,vk_size
|
|
6583 0000208F F3AA <1> rep stosb
|
|
6584 <1> .again:
|
|
6585 00002091 E8C400 <1> call getcommand
|
|
6586 00002094 73FB <1> jnc .again ; If not EOF do it again
|
|
6587 <1> ;
|
|
6588 <1> ; The fall through to commit_vk to commit any final
|
|
6589 <1> ; VKernel being read
|
|
6590 <1> ;
|
|
6591 <1> ;
|
|
6592 <1> ; commit_vk: Store the current VKernelBuf into buffer segment
|
|
6593 <1> ;
|
|
6594 <1> commit_vk:
|
|
6595 <1> ; For better compression, clean up the append field
|
|
6596 00002096 A1[DA0D] <1> mov ax,[VKernelBuf+vk_appendlen]
|
|
6597 00002099 BF[DC0D] <1> mov di,VKernelBuf+vk_append
|
|
6598 0000209C 01C7 <1> add di,ax
|
|
6599 0000209E B90002 <1> mov cx,max_cmd_len+1
|
|
6600 000020A1 29C1 <1> sub cx,ax
|
|
6601 000020A3 31C0 <1> xor ax,ax
|
|
6602 000020A5 F3AA <1> rep stosb
|
|
6603 <1>
|
|
6604 <1> ; Pack temporarily into trackbuf
|
|
6605 000020A7 BE[D80C] <1> mov si,VKernelBuf
|
|
6606 000020AA BF[0000] <1> mov di,trackbuf
|
|
6607 000020AD B90403 <1> mov cx,vk_size
|
|
6608 000020B0 E82100 <1> call rllpack
|
|
6609 <1> ; Now DX = number of bytes
|
|
6610 000020B3 8B3E[F800] <1> mov di,[VKernelBytes]
|
|
6611 000020B7 89D1 <1> mov cx,dx
|
|
6612 000020B9 01FA <1> add dx,di
|
|
6613 000020BB 7210 <1> jc .overflow ; If > 1 segment
|
|
6614 000020BD 8916[F800] <1> mov [VKernelBytes],dx
|
|
6615 000020C1 BE[0000] <1> mov si,trackbuf
|
|
6616 000020C4 06 <1> push es
|
|
6617 000020C5 680030 <1> push word vk_seg
|
|
6618 000020C8 07 <1> pop es
|
|
6619 000020C9 F3A4 <1> rep movsb
|
|
6620 000020CB 07 <1> pop es
|
|
6621 000020CC C3 <1> ret
|
|
6622 <1> .overflow:
|
|
6623 000020CD BE[C100] <1> mov si,vk_overflow_msg
|
|
6624 000020D0 E881FD <1> call writestr
|
|
6625 000020D3 C3 <1> ret
|
|
6626 <1>
|
|
6627 <1> section .data
|
|
6628 000000C1 4F7574206F66206D65- <1> vk_overflow_msg db 'Out of memory parsing config file', CR, LF, 0
|
|
6629 000000CA 6D6F72792070617273- <1>
|
|
6630 000000D3 696E6720636F6E6669- <1>
|
|
6631 000000DC 672066696C650D0A00 <1>
|
|
6632 <1>
|
|
6633 000000E5 00 <1> align 2, db 0
|
|
6634 000000E6 0000 <1> AppendLen dw 0 ; Bytes in append= command
|
|
6635 000000E8 0000 <1> OntimeoutLen dw 0 ; Bytes in ontimeout command
|
|
6636 000000EA 0000 <1> OnerrorLen dw 0 ; Bytes in onerror command
|
|
6637 000000EC 0000 <1> KbdTimeOut dw 0 ; Keyboard timeout (if any)
|
|
6638 000000EE 0090 <1> CmdLinePtr dw cmd_line_here ; Command line advancing pointer
|
|
6639 000000F0 0000 <1> ForcePrompt dw 0 ; Force prompt
|
|
6640 000000F2 0100 <1> AllowImplicit dw 1 ; Allow implicit kernels
|
|
6641 000000F4 0100 <1> AllowOptions dw 1 ; User-specified options allowed
|
|
6642 000000F6 0000 <1> SerialPort dw 0 ; Serial port base (or 0 for no serial port)
|
|
6643 000000F8 0000 <1> VKernelBytes dw 0 ; Number of bytes used by vkernels
|
|
6644 000000FA 00 <1> VKernel db 0 ; Have we seen any "label" statements?
|
|
6645 <1>
|
|
6646 <1> section .bss
|
|
6647 000008D1 <res 00000001>- <1> alignb 4 ; For the good of REP MOVSD
|
|
6648 000008D1 <rept> <1>
|
|
6649 000008D4 <res 00000201> <1> command_line resb max_cmd_len+2 ; Command line buffer
|
|
6650 00000AD5 <res 00000001>- <1> alignb 4
|
|
6651 00000AD5 <rept> <1>
|
|
6652 00000AD8 <res 00000200> <1> default_cmd resb max_cmd_len+1 ; "default" command line
|
|
6653 <1>
|
|
6654 <1> %include "rllpack.inc"
|
|
6655 <2> ; -*- fundamental -*-
|
|
6656 <2> ; -----------------------------------------------------------------------
|
|
6657 <2> ;
|
|
6658 <2> ; Copyright 2004 H. Peter Anvin - All Rights Reserved
|
|
6659 <2> ;
|
|
6660 <2> ; This program is free software; you can redistribute it and/or modify
|
|
6661 <2> ; it under the terms of the GNU General Public License as published by
|
|
6662 <2> ; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
|
|
6663 <2> ; Boston MA 02111-1307, USA; either version 2 of the License, or
|
|
6664 <2> ; (at your option) any later version; incorporated herein by reference.
|
|
6665 <2> ;
|
|
6666 <2> ; -----------------------------------------------------------------------
|
|
6667 <2> ; $Id: rllpack.inc,v 1.2 2004/12/17 07:52:54 hpa Exp $
|
|
6668 <2>
|
|
6669 <2> ;
|
|
6670 <2> ; rllpack.inc
|
|
6671 <2> ;
|
|
6672 <2> ; Very simple RLL compressor/decompressor, used to pack binary structures
|
|
6673 <2> ; together.
|
|
6674 <2> ;
|
|
6675 <2> ; Format of leading byte
|
|
6676 <2> ; 1-128 = x verbatim bytes follow
|
|
6677 <2> ; 129-255 = (x-126) times subsequent byte
|
|
6678 <2> ; 0 = end of data
|
|
6679 <2> ;
|
|
6680 <2>
|
|
6681 <2> section .text
|
|
6682 <2>
|
|
6683 <2> ;
|
|
6684 <2> ; rllpack:
|
|
6685 <2> ; Pack CX bytes from DS:SI into ES:DI
|
|
6686 <2> ; Returns updated SI, DI and CX = number of bytes output
|
|
6687 <2> ;
|
|
6688 <2> rllpack:
|
|
6689 000020D4 50 <2> push ax
|
|
6690 000020D5 53 <2> push bx
|
|
6691 000020D6 51 <2> push cx
|
|
6692 000020D7 55 <2> push bp
|
|
6693 000020D8 57 <2> push di
|
|
6694 <2> .startseq:
|
|
6695 000020D9 31C0 <2> xor ax,ax ; Zero byte
|
|
6696 000020DB 31DB <2> xor bx,bx ; Run length zero
|
|
6697 000020DD 89FD <2> mov bp,di ; Pointer to header byte
|
|
6698 000020DF AA <2> stosb ; Store header byte (might be zero)
|
|
6699 000020E0 E349 <2> jcxz .done_null
|
|
6700 <2> .stdbyte:
|
|
6701 000020E2 AC <2> lodsb
|
|
6702 000020E3 AA <2> stosb
|
|
6703 000020E4 49 <2> dec cx
|
|
6704 000020E5 38C4 <2> cmp ah,al
|
|
6705 000020E7 740F <2> je .same
|
|
6706 <2> .diff:
|
|
6707 000020E9 88C4 <2> mov ah,al
|
|
6708 000020EB 31DB <2> xor bx,bx
|
|
6709 <2> .plainbyte:
|
|
6710 000020ED 43 <2> inc bx
|
|
6711 000020EE 26FE4600 <2> inc byte [es:bp]
|
|
6712 000020F2 E334 <2> jcxz .done
|
|
6713 000020F4 79EC <2> jns .stdbyte
|
|
6714 000020F6 EBE1 <2> jmp .startseq
|
|
6715 <2> .same:
|
|
6716 000020F8 80FB02 <2> cmp bl,2
|
|
6717 000020FB 72F0 <2> jb .plainbyte
|
|
6718 <2> ; 3 bytes or more in a row, time to convert sequence
|
|
6719 000020FD 26285E00 <2> sub byte [es:bp],bl
|
|
6720 00002101 7501 <2> jnz .normal
|
|
6721 00002103 4F <2> dec di ; We killed a whole stretch, remove start byte
|
|
6722 <2> .normal:
|
|
6723 00002104 43 <2> inc bx
|
|
6724 00002105 29DF <2> sub di,bx
|
|
6725 00002107 89FD <2> mov bp,di
|
|
6726 00002109 88D8 <2> mov al,bl
|
|
6727 0000210B 047E <2> add al,126
|
|
6728 0000210D AA <2> stosb
|
|
6729 0000210E 88E0 <2> mov al,ah
|
|
6730 00002110 AA <2> stosb
|
|
6731 <2> .getrun:
|
|
6732 00002111 E315 <2> jcxz .done
|
|
6733 00002113 80FB81 <2> cmp bl,255-126
|
|
6734 00002116 73C1 <2> jae .startseq
|
|
6735 00002118 AC <2> lodsb
|
|
6736 00002119 38E0 <2> cmp al,ah
|
|
6737 0000211B 7508 <2> jne .nomatch
|
|
6738 0000211D 43 <2> inc bx
|
|
6739 0000211E 26FE4600 <2> inc byte [es:bp]
|
|
6740 00002122 49 <2> dec cx
|
|
6741 00002123 EBEC <2> jmp .getrun
|
|
6742 <2> .nomatch:
|
|
6743 00002125 4E <2> dec si
|
|
6744 00002126 EBB1 <2> jmp .startseq
|
|
6745 <2> .done:
|
|
6746 00002128 30C0 <2> xor al,al
|
|
6747 0000212A AA <2> stosb
|
|
6748 <2> .done_null:
|
|
6749 0000212B 5A <2> pop dx
|
|
6750 0000212C 29FA <2> sub dx,di
|
|
6751 0000212E F7DA <2> neg dx
|
|
6752 00002130 5D <2> pop bp
|
|
6753 00002131 59 <2> pop cx
|
|
6754 00002132 5B <2> pop bx
|
|
6755 00002133 58 <2> pop ax
|
|
6756 00002134 C3 <2> ret
|
|
6757 <2> ;
|
|
6758 <2> ; rllunpack:
|
|
6759 <2> ; Unpack bytes from DS:SI into ES:DI
|
|
6760 <2> ; On return SI, DI are updated and CX contains number of bytes output
|
|
6761 <2> ;
|
|
6762 <2> rllunpack:
|
|
6763 00002135 50 <2> push ax
|
|
6764 00002136 57 <2> push di
|
|
6765 00002137 31C9 <2> xor cx,cx
|
|
6766 <2> .header:
|
|
6767 00002139 AC <2> lodsb
|
|
6768 0000213A 20C0 <2> and al,al
|
|
6769 0000213C 7413 <2> jz .done
|
|
6770 0000213E 3C81 <2> cmp al,129
|
|
6771 00002140 7306 <2> jae .isrun
|
|
6772 <2> ; Not a run
|
|
6773 00002142 88C1 <2> mov cl,al
|
|
6774 00002144 F3A4 <2> rep movsb
|
|
6775 00002146 EBF1 <2> jmp .header
|
|
6776 <2> .isrun:
|
|
6777 00002148 2C7E <2> sub al,126
|
|
6778 0000214A 88C1 <2> mov cl,al
|
|
6779 0000214C AC <2> lodsb
|
|
6780 0000214D F3AA <2> rep stosb
|
|
6781 0000214F EBE8 <2> jmp .header
|
|
6782 <2> .done:
|
|
6783 00002151 59 <2> pop cx
|
|
6784 00002152 29F9 <2> sub cx,di
|
|
6785 00002154 F7D9 <2> neg cx
|
|
6786 00002156 58 <2> pop ax
|
|
6787 00002157 C3 <2> ret
|
|
6788 %include "parsecmd.inc" ; Low-level config file handling
|
|
6789 <1> ;; $Id: parsecmd.inc,v 1.10 2004/12/21 06:30:55 hpa Exp $
|
|
6790 <1> ;; -----------------------------------------------------------------------
|
|
6791 <1> ;;
|
|
6792 <1> ;; Copyright 1994-2002 H. Peter Anvin - All Rights Reserved
|
|
6793 <1> ;;
|
|
6794 <1> ;; This program is free software; you can redistribute it and/or modify
|
|
6795 <1> ;; it under the terms of the GNU General Public License as published by
|
|
6796 <1> ;; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
|
|
6797 <1> ;; Boston MA 02111-1307, USA; either version 2 of the License, or
|
|
6798 <1> ;; (at your option) any later version; incorporated herein by reference.
|
|
6799 <1> ;;
|
|
6800 <1> ;; -----------------------------------------------------------------------
|
|
6801 <1>
|
|
6802 <1> ;;
|
|
6803 <1> ;; parsecmd.inc
|
|
6804 <1> ;;
|
|
6805 <1> ;; Command line parser code
|
|
6806 <1> ;;
|
|
6807 <1>
|
|
6808 <1> section .text
|
|
6809 <1>
|
|
6810 <1> ; -------------------------------------------------------------------------
|
|
6811 <1> ; getcommand: Get a keyword from the current "getc" file and match it
|
|
6812 <1> ; against a list of keywords (keywd_table). Each entry in
|
|
6813 <1> ; that table should have the following form:
|
|
6814 <1> ; <32 bit hash value> <16 bit handler offset>
|
|
6815 <1> ;
|
|
6816 <1> ; The handler is called, and upon return this function
|
|
6817 <1> ; returns with CF = 0. On EOF, this function returns
|
|
6818 <1> ; with CF = 1.
|
|
6819 <1> ; -------------------------------------------------------------------------
|
|
6820 <1>
|
|
6821 <1> getcommand:
|
|
6822 <1> .find:
|
|
6823 00002158 E86AF9 <1> call skipspace ; Skip leading whitespace
|
|
6824 0000215B 7451 <1> jz .eof ; End of file
|
|
6825 0000215D 72F9 <1> jc .find ; End of line: try again
|
|
6826 <1>
|
|
6827 0000215F 0C20 <1> or al,20h ; Convert to lower case
|
|
6828 00002161 660FB6D8 <1> movzx ebx,al ; Hash for a one-char keyword
|
|
6829 <1> .read_loop:
|
|
6830 00002165 6653 <1> push ebx
|
|
6831 00002167 E801F9 <1> call getc
|
|
6832 0000216A 665B <1> pop ebx
|
|
6833 0000216C 7240 <1> jc .eof
|
|
6834 0000216E 3C20 <1> cmp al,' ' ; Whitespace
|
|
6835 00002170 760A <1> jbe .done
|
|
6836 00002172 0C20 <1> or al,20h
|
|
6837 00002174 66C1C305 <1> rol ebx,5
|
|
6838 00002178 30C3 <1> xor bl,al
|
|
6839 0000217A EBE9 <1> jmp short .read_loop
|
|
6840 0000217C E835F9 <1> .done: call ungetc
|
|
6841 0000217F E843F9 <1> call skipspace
|
|
6842 00002182 742A <1> jz .eof
|
|
6843 00002184 7219 <1> jc .noparm
|
|
6844 00002186 E82BF9 <1> call ungetc ; Return nonwhitespace char to buf
|
|
6845 00002189 BE[2807] <1> mov si,keywd_table
|
|
6846 0000218C B92000 <1> mov cx,keywd_count
|
|
6847 <1> .table_search:
|
|
6848 0000218F 66AD <1> lodsd
|
|
6849 00002191 6639C3 <1> cmp ebx,eax
|
|
6850 00002194 7413 <1> je .found_keywd
|
|
6851 00002196 66AD <1> lodsd ; Skip entrypoint/argument
|
|
6852 00002198 E2F5 <1> loop .table_search
|
|
6853 <1>
|
|
6854 <1> ; Otherwise unrecognized keyword
|
|
6855 0000219A BE[9E02] <1> mov si,err_badcfg
|
|
6856 0000219D EB05 <1> jmp short .error
|
|
6857 <1>
|
|
6858 <1> ; No parameter
|
|
6859 <1> .noparm:
|
|
6860 0000219F BE[C002] <1> mov si,err_noparm
|
|
6861 000021A2 B00A <1> mov al,10 ; Already at EOL
|
|
6862 <1> .error:
|
|
6863 000021A4 E8ADFC <1> call cwritestr
|
|
6864 000021A7 EB07 <1> jmp short .skipline
|
|
6865 <1>
|
|
6866 000021A9 AD <1> .found_keywd: lodsw ; Load argument into ax
|
|
6867 000021AA FF14 <1> call [si]
|
|
6868 000021AC F8 <1> clc
|
|
6869 000021AD C3 <1> ret
|
|
6870 <1>
|
|
6871 000021AE F9 <1> .eof: stc
|
|
6872 000021AF C3 <1> ret
|
|
6873 <1>
|
|
6874 000021B0 3C0A <1> .skipline: cmp al,10 ; Search for LF
|
|
6875 000021B2 74A4 <1> je .find
|
|
6876 000021B4 E8B4F8 <1> call getc
|
|
6877 000021B7 72F5 <1> jc .eof
|
|
6878 000021B9 EBF5 <1> jmp short .skipline
|
|
6879 <1>
|
|
6880 <1> section .bss
|
|
6881 <1> alignb 4
|
|
6882 <1> vk_size equ (vk_end + 3) & ~3
|
|
6883 00000CD8 <res 00000304> <1> VKernelBuf: resb vk_size ; "Current" vkernel
|
|
6884 00000FDC <res 00000200> <1> AppendBuf resb max_cmd_len+1 ; append=
|
|
6885 000011DC <res 00000200> <1> Ontimeout resb max_cmd_len+1 ; ontimeout
|
|
6886 000013DC <res 00000200> <1> Onerror resb max_cmd_len+1 ; onerror
|
|
6887 000015DC <res 00000100> <1> KbdMap resb 256 ; Keyboard map
|
|
6888 000016DC <res 00000500> <1> FKeyName resb 10*FILENAME_MAX ; File names for F-key help
|
|
6889 00001BDC <res 00000002> <1> KernelCNameLen resw 1 ; Length of unmangled kernel name
|
|
6890 00001BDE <res 00000002> <1> InitRDCNameLen resw 1 ; Length of unmangled initrd name
|
|
6891 <1> %if IS_SYSLINUX
|
|
6892 <1> KernelName resb FILENAME_MAX+1 ; Mangled name for kernel
|
|
6893 <1> KernelCName resb FILENAME_MAX+2 ; Unmangled kernel name
|
|
6894 <1> InitRDCName resb FILENAME_MAX+2 ; Unmangled initrd name
|
|
6895 <1> %else
|
|
6896 00001BE0 <res 00000080> <1> KernelName resb FILENAME_MAX ; Mangled name for kernel
|
|
6897 00001C60 <res 00000080> <1> KernelCName resb FILENAME_MAX ; Unmangled kernel name
|
|
6898 00001CE0 <res 00000080> <1> InitRDCName resb FILENAME_MAX ; Unmangled initrd name
|
|
6899 <1> %endif
|
|
6900 00001D60 <res 00000080> <1> MNameBuf resb FILENAME_MAX
|
|
6901 00001DE0 <res 00000080> <1> InitRD resb FILENAME_MAX
|
|
6902 %include "bcopy32.inc" ; 32-bit bcopy
|
|
6903 <1> ;; $Id: bcopy32.inc,v 1.16 2005/01/06 22:34:06 hpa Exp $
|
|
6904 <1> ;; -----------------------------------------------------------------------
|
|
6905 <1> ;;
|
|
6906 <1> ;; Copyright 1994-2005 H. Peter Anvin - All Rights Reserved
|
|
6907 <1> ;;
|
|
6908 <1> ;; This program is free software; you can redistribute it and/or modify
|
|
6909 <1> ;; it under the terms of the GNU General Public License as published by
|
|
6910 <1> ;; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
|
|
6911 <1> ;; Boston MA 02111-1307, USA; either version 2 of the License, or
|
|
6912 <1> ;; (at your option) any later version; incorporated herein by reference.
|
|
6913 <1> ;;
|
|
6914 <1> ;; -----------------------------------------------------------------------
|
|
6915 <1>
|
|
6916 <1> ;;
|
|
6917 <1> ;; bcopy32.inc
|
|
6918 <1> ;;
|
|
6919 <1> ;; 32-bit bcopy routine for real mode
|
|
6920 <1> ;;
|
|
6921 <1>
|
|
6922 <1> ;
|
|
6923 <1> ; 32-bit bcopy routine for real mode
|
|
6924 <1> ;
|
|
6925 <1> ; We enter protected mode, set up a flat 32-bit environment, run rep movsd
|
|
6926 <1> ; and then exit. IMPORTANT: This code assumes cs == 0.
|
|
6927 <1> ;
|
|
6928 <1> ; This code is probably excessively anal-retentive in its handling of
|
|
6929 <1> ; segments, but this stuff is painful enough as it is without having to rely
|
|
6930 <1> ; on everything happening "as it ought to."
|
|
6931 <1> ;
|
|
6932 <1> ; NOTE: this code is relocated into low memory, just after the .earlybss
|
|
6933 <1> ; segment, in order to support to "bcopy over self" operation.
|
|
6934 <1> ;
|
|
6935 <1>
|
|
6936 <1> section .bcopy32
|
|
6937 <1> align 8
|
|
6938 <1> __bcopy_start:
|
|
6939 <1>
|
|
6940 <1> ; This is in the .text segment since it needs to be
|
|
6941 <1> ; contiguous with the rest of the bcopy stuff
|
|
6942 <1>
|
|
6943 00000000 2F00 <1> bcopy_gdt: dw bcopy_gdt_size-1 ; Null descriptor - contains GDT
|
|
6944 00000002 [00000000] <1> dd bcopy_gdt ; pointer for LGDT instruction
|
|
6945 00000006 0000 <1> dw 0
|
|
6946 00000008 FFFF0000 <1> dd 0000ffffh ; Code segment, use16, readable,
|
|
6947 0000000C 009B0000 <1> dd 00009b00h ; present, dpl 0, cover 64K
|
|
6948 00000010 FFFF0000 <1> dd 0000ffffh ; Data segment, use16, read/write,
|
|
6949 00000014 00938F00 <1> dd 008f9300h ; present, dpl 0, cover all 4G
|
|
6950 00000018 FFFF0000 <1> dd 0000ffffh ; Data segment, use16, read/write,
|
|
6951 0000001C 00930000 <1> dd 00009300h ; present, dpl 0, cover 64K
|
|
6952 <1> ; The rest are used for COM32 only
|
|
6953 00000020 FFFF0000 <1> dd 0000ffffh ; Code segment, use32, readable,
|
|
6954 00000024 009BCF00 <1> dd 00cf9b00h ; present, dpl 0, cover all 4G
|
|
6955 00000028 FFFF0000 <1> dd 0000ffffh ; Data segment, use32, read/write,
|
|
6956 0000002C 0093CF00 <1> dd 00cf9300h ; present, dpl 0, cover all 4G
|
|
6957 <1> bcopy_gdt_size: equ $-bcopy_gdt
|
|
6958 <1>
|
|
6959 <1> ;
|
|
6960 <1> ; bcopy:
|
|
6961 <1> ; 32-bit copy, overlap safe
|
|
6962 <1> ;
|
|
6963 <1> ; Inputs:
|
|
6964 <1> ; ESI - source pointer
|
|
6965 <1> ; EDI - target pointer
|
|
6966 <1> ; ECX - byte count
|
|
6967 <1> ; DF - zero
|
|
6968 <1> ;
|
|
6969 <1> ; Outputs:
|
|
6970 <1> ; ESI - first byte after source
|
|
6971 <1> ; EDI - first byte after target
|
|
6972 <1> ; ECX - zero
|
|
6973 <1> ;
|
|
6974 00000030 6650 <1> bcopy: push eax
|
|
6975 00000032 6656 <1> push esi
|
|
6976 00000034 6657 <1> push edi
|
|
6977 00000036 6651 <1> push ecx
|
|
6978 00000038 9C <1> pushf ; Saves, among others, the IF flag
|
|
6979 00000039 1E <1> push ds
|
|
6980 0000003A 06 <1> push es
|
|
6981 <1>
|
|
6982 0000003B FA <1> cli
|
|
6983 0000003C E88D00 <1> call enable_a20
|
|
6984 <1>
|
|
6985 0000003F 662E0F0116[0000] <1> o32 lgdt [cs:bcopy_gdt]
|
|
6986 00000046 0F20C0 <1> mov eax,cr0
|
|
6987 00000049 0C01 <1> or al,1
|
|
6988 0000004B 0F22C0 <1> mov cr0,eax ; Enter protected mode
|
|
6989 0000004E EA[5300]0800 <1> jmp 08h:.in_pm
|
|
6990 <1>
|
|
6991 00000053 B81000 <1> .in_pm: mov ax,10h ; Data segment selector
|
|
6992 00000056 8EC0 <1> mov es,ax
|
|
6993 00000058 8ED8 <1> mov ds,ax
|
|
6994 <1>
|
|
6995 <1> ; Don't mess with ss, fs, and gs. They are never changed
|
|
6996 <1> ; and should be able to make it back out of protected mode.
|
|
6997 <1> ; This works because (and only because) we don't take
|
|
6998 <1> ; interrupt in protected mode.
|
|
6999 <1>
|
|
7000 0000005A 6639FE <1> cmp esi,edi ; If source > destination, we might
|
|
7001 0000005D 7713 <1> ja .reverse ; have to copy backwards
|
|
7002 <1>
|
|
7003 <1> .forward:
|
|
7004 0000005F 88C8 <1> mov al,cl ; Save low bits
|
|
7005 00000061 2403 <1> and al,3
|
|
7006 00000063 66C1E902 <1> shr ecx,2 ; Convert to dwords
|
|
7007 00000067 67F366A5 <1> a32 rep movsd ; Do our business
|
|
7008 <1> ; At this point ecx == 0
|
|
7009 <1>
|
|
7010 0000006B 88C1 <1> mov cl,al ; Copy any fractional dword
|
|
7011 0000006D 67F3A4 <1> a32 rep movsb
|
|
7012 00000070 EB2B <1> jmp .exit
|
|
7013 <1>
|
|
7014 <1> .reverse:
|
|
7015 00000072 FD <1> std ; Reverse copy
|
|
7016 00000073 66678D740EFF <1> lea esi,[esi+ecx-1] ; Point to final byte
|
|
7017 00000079 66678D7C0FFF <1> lea edi,[edi+ecx-1]
|
|
7018 0000007F 6689C8 <1> mov eax,ecx
|
|
7019 00000082 6683E103 <1> and ecx,3
|
|
7020 00000086 66C1E802 <1> shr eax,2
|
|
7021 0000008A 67F3A4 <1> a32 rep movsb
|
|
7022 <1>
|
|
7023 <1> ; Change ESI/EDI to point to the last dword, instead
|
|
7024 <1> ; of the last byte.
|
|
7025 0000008D 6683EE03 <1> sub esi,3
|
|
7026 00000091 6683EF03 <1> sub edi,3
|
|
7027 00000095 6689C1 <1> mov ecx,eax
|
|
7028 00000098 67F366A5 <1> a32 rep movsd
|
|
7029 <1>
|
|
7030 0000009C FC <1> cld
|
|
7031 <1>
|
|
7032 <1> .exit:
|
|
7033 0000009D B81800 <1> mov ax,18h ; "Real-mode-like" data segment
|
|
7034 000000A0 8EC0 <1> mov es,ax
|
|
7035 000000A2 8ED8 <1> mov ds,ax
|
|
7036 <1>
|
|
7037 000000A4 0F20C0 <1> mov eax,cr0
|
|
7038 000000A7 24FE <1> and al,~1
|
|
7039 000000A9 0F22C0 <1> mov cr0,eax ; Disable protected mode
|
|
7040 000000AC EA[B100]0000 <1> jmp 0:.in_rm
|
|
7041 <1>
|
|
7042 <1> .in_rm: ; Back in real mode
|
|
7043 000000B1 07 <1> pop es
|
|
7044 000000B2 1F <1> pop ds
|
|
7045 000000B3 E8B700 <1> call disable_a20
|
|
7046 <1>
|
|
7047 000000B6 9D <1> popf ; Re-enables interrupts
|
|
7048 000000B7 6658 <1> pop eax
|
|
7049 000000B9 665F <1> pop edi
|
|
7050 000000BB 665E <1> pop esi
|
|
7051 000000BD 6601C7 <1> add edi,eax
|
|
7052 000000C0 6601C6 <1> add esi,eax
|
|
7053 000000C3 6658 <1> pop eax
|
|
7054 000000C5 C3 <1> ret
|
|
7055 <1>
|
|
7056 <1> ;
|
|
7057 <1> ; Routines to enable and disable (yuck) A20. These routines are gathered
|
|
7058 <1> ; from tips from a couple of sources, including the Linux kernel and
|
|
7059 <1> ; http://www.x86.org/. The need for the delay to be as large as given here
|
|
7060 <1> ; is indicated by Donnie Barnes of RedHat, the problematic system being an
|
|
7061 <1> ; IBM ThinkPad 760EL.
|
|
7062 <1> ;
|
|
7063 <1> ; We typically toggle A20 twice for every 64K transferred.
|
|
7064 <1> ;
|
|
7065 <1> %define io_delay call _io_delay
|
|
7066 <1> %define IO_DELAY_PORT 80h ; Invalid port (we hope!)
|
|
7067 <1> %define disable_wait 32 ; How long to wait for a disable
|
|
7068 <1>
|
|
7069 <1> ; Note the skip of 2 here
|
|
7070 <1> %define A20_DUNNO 0 ; A20 type unknown
|
|
7071 <1> %define A20_NONE 2 ; A20 always on?
|
|
7072 <1> %define A20_BIOS 4 ; A20 BIOS enable
|
|
7073 <1> %define A20_KBC 6 ; A20 through KBC
|
|
7074 <1> %define A20_FAST 8 ; A20 through port 92h
|
|
7075 <1>
|
|
7076 000000C6 EE <1> slow_out: out dx, al ; Fall through
|
|
7077 <1>
|
|
7078 000000C7 E680 <1> _io_delay: out IO_DELAY_PORT,al
|
|
7079 000000C9 E680 <1> out IO_DELAY_PORT,al
|
|
7080 000000CB C3 <1> ret
|
|
7081 <1>
|
|
7082 <1> enable_a20:
|
|
7083 000000CC 6660 <1> pushad
|
|
7084 000000CE 2EC606[6E55]FF <1> mov byte [cs:A20Tries],255 ; Times to try to make this work
|
|
7085 <1>
|
|
7086 <1> try_enable_a20:
|
|
7087 <1> ;
|
|
7088 <1> ; Flush the caches
|
|
7089 <1> ;
|
|
7090 <1> %if DO_WBINVD
|
|
7091 <1> call try_wbinvd
|
|
7092 <1> %endif
|
|
7093 <1>
|
|
7094 <1> ;
|
|
7095 <1> ; If the A20 type is known, jump straight to type
|
|
7096 <1> ;
|
|
7097 000000D4 2E8B2E[0802] <1> mov bp,[cs:A20Type]
|
|
7098 000000D9 2EFFA6[F401] <1> jmp word [cs:bp+A20List]
|
|
7099 <1>
|
|
7100 <1> ;
|
|
7101 <1> ; First, see if we are on a system with no A20 gate
|
|
7102 <1> ;
|
|
7103 <1> a20_dunno:
|
|
7104 <1> a20_none:
|
|
7105 000000DE 2EC606[0802]02 <1> mov byte [cs:A20Type], A20_NONE
|
|
7106 000000E4 E86400 <1> call a20_test
|
|
7107 000000E7 755F <1> jnz a20_done
|
|
7108 <1>
|
|
7109 <1> ;
|
|
7110 <1> ; Next, try the BIOS (INT 15h AX=2401h)
|
|
7111 <1> ;
|
|
7112 <1> a20_bios:
|
|
7113 000000E9 2EC606[0802]04 <1> mov byte [cs:A20Type], A20_BIOS
|
|
7114 000000EF B80124 <1> mov ax,2401h
|
|
7115 000000F2 9C <1> pushf ; Some BIOSes muck with IF
|
|
7116 000000F3 CD15 <1> int 15h
|
|
7117 000000F5 9D <1> popf
|
|
7118 <1>
|
|
7119 000000F6 E85200 <1> call a20_test
|
|
7120 000000F9 754D <1> jnz a20_done
|
|
7121 <1>
|
|
7122 <1> ;
|
|
7123 <1> ; Enable the keyboard controller A20 gate
|
|
7124 <1> ;
|
|
7125 <1> a20_kbc:
|
|
7126 000000FB B201 <1> mov dl, 1 ; Allow early exit
|
|
7127 000000FD E8AC00 <1> call empty_8042
|
|
7128 00000100 7546 <1> jnz a20_done ; A20 live, no need to use KBC
|
|
7129 <1>
|
|
7130 00000102 2EC606[0802]06 <1> mov byte [cs:A20Type], A20_KBC ; Starting KBC command sequence
|
|
7131 <1>
|
|
7132 00000108 B0D1 <1> mov al,0D1h ; Command write
|
|
7133 0000010A E664 <1> out 064h, al
|
|
7134 0000010C E89B00 <1> call empty_8042_uncond
|
|
7135 <1>
|
|
7136 0000010F B0DF <1> mov al,0DFh ; A20 on
|
|
7137 00000111 E660 <1> out 060h, al
|
|
7138 00000113 E89400 <1> call empty_8042_uncond
|
|
7139 <1>
|
|
7140 <1> ; Verify that A20 actually is enabled. Do that by
|
|
7141 <1> ; observing a word in low memory and the same word in
|
|
7142 <1> ; the HMA until they are no longer coherent. Note that
|
|
7143 <1> ; we don't do the same check in the disable case, because
|
|
7144 <1> ; we don't want to *require* A20 masking (SYSLINUX should
|
|
7145 <1> ; work fine without it, if the BIOS does.)
|
|
7146 00000116 51 <1> .kbc_wait: push cx
|
|
7147 00000117 31C9 <1> xor cx,cx
|
|
7148 <1> .kbc_wait_loop:
|
|
7149 00000119 E82F00 <1> call a20_test
|
|
7150 0000011C 7529 <1> jnz a20_done_pop
|
|
7151 0000011E E2F9 <1> loop .kbc_wait_loop
|
|
7152 <1>
|
|
7153 00000120 59 <1> pop cx
|
|
7154 <1> ;
|
|
7155 <1> ; Running out of options here. Final attempt: enable the "fast A20 gate"
|
|
7156 <1> ;
|
|
7157 <1> a20_fast:
|
|
7158 00000121 2EC606[0802]08 <1> mov byte [cs:A20Type], A20_FAST ; Haven't used the KBC yet
|
|
7159 00000127 E492 <1> in al, 092h
|
|
7160 00000129 0C02 <1> or al,02h
|
|
7161 0000012B 24FE <1> and al,~01h ; Don't accidentally reset the machine!
|
|
7162 0000012D E692 <1> out 092h, al
|
|
7163 <1>
|
|
7164 0000012F 51 <1> .fast_wait: push cx
|
|
7165 00000130 31C9 <1> xor cx,cx
|
|
7166 <1> .fast_wait_loop:
|
|
7167 00000132 E81600 <1> call a20_test
|
|
7168 00000135 7510 <1> jnz a20_done_pop
|
|
7169 00000137 E2F9 <1> loop .fast_wait_loop
|
|
7170 <1>
|
|
7171 00000139 59 <1> pop cx
|
|
7172 <1>
|
|
7173 <1> ;
|
|
7174 <1> ; Oh bugger. A20 is not responding. Try frobbing it again; eventually give up
|
|
7175 <1> ; and report failure to the user.
|
|
7176 <1> ;
|
|
7177 <1>
|
|
7178 <1>
|
|
7179 0000013A 2EFE0E[6E55] <1> dec byte [cs:A20Tries]
|
|
7180 0000013F 7593 <1> jnz try_enable_a20
|
|
7181 <1>
|
|
7182 00000141 BE[D703] <1> mov si, err_a20
|
|
7183 00000144 E9(A011) <1> jmp abort_load
|
|
7184 <1> ;
|
|
7185 <1> ; A20 unmasked, proceed...
|
|
7186 <1> ;
|
|
7187 00000147 59 <1> a20_done_pop: pop cx
|
|
7188 00000148 6661 <1> a20_done: popad
|
|
7189 0000014A C3 <1> ret
|
|
7190 <1>
|
|
7191 <1> ;
|
|
7192 <1> ; This routine tests if A20 is enabled (ZF = 0). This routine
|
|
7193 <1> ; must not destroy any register contents.
|
|
7194 <1> ;
|
|
7195 <1> a20_test:
|
|
7196 0000014B 06 <1> push es
|
|
7197 0000014C 51 <1> push cx
|
|
7198 0000014D 50 <1> push ax
|
|
7199 0000014E B9FFFF <1> mov cx,0FFFFh ; HMA = segment 0FFFFh
|
|
7200 00000151 8EC1 <1> mov es,cx
|
|
7201 00000153 B92000 <1> mov cx,32 ; Loop count
|
|
7202 00000156 2EA1[6C55] <1> mov ax,[cs:A20Test]
|
|
7203 0000015A 40 <1> .a20_wait: inc ax
|
|
7204 0000015B 2EA3[6C55] <1> mov [cs:A20Test],ax
|
|
7205 0000015F E865FF <1> io_delay ; Serialize, and fix delay
|
|
7206 00000162 263B06[7C55] <1> cmp ax,[es:A20Test+10h]
|
|
7207 00000167 E1F1 <1> loopz .a20_wait
|
|
7208 00000169 58 <1> .a20_done: pop ax
|
|
7209 0000016A 59 <1> pop cx
|
|
7210 0000016B 07 <1> pop es
|
|
7211 0000016C C3 <1> ret
|
|
7212 <1>
|
|
7213 <1> disable_a20:
|
|
7214 0000016D 6660 <1> pushad
|
|
7215 <1> ;
|
|
7216 <1> ; Flush the caches
|
|
7217 <1> ;
|
|
7218 <1> %if DO_WBINVD
|
|
7219 <1> call try_wbinvd
|
|
7220 <1> %endif
|
|
7221 <1>
|
|
7222 0000016F 2E8B2E[0802] <1> mov bp,[cs:A20Type]
|
|
7223 00000174 2EFFA6[FE01] <1> jmp word [cs:bp+A20DList]
|
|
7224 <1>
|
|
7225 <1> a20d_bios:
|
|
7226 00000179 B80024 <1> mov ax,2400h
|
|
7227 0000017C 9C <1> pushf ; Some BIOSes muck with IF
|
|
7228 0000017D CD15 <1> int 15h
|
|
7229 0000017F 9D <1> popf
|
|
7230 00000180 EB19 <1> jmp short a20d_snooze
|
|
7231 <1>
|
|
7232 <1> ;
|
|
7233 <1> ; Disable the "fast A20 gate"
|
|
7234 <1> ;
|
|
7235 <1> a20d_fast:
|
|
7236 00000182 E492 <1> in al, 092h
|
|
7237 00000184 24FC <1> and al,~03h
|
|
7238 00000186 E692 <1> out 092h, al
|
|
7239 00000188 EB11 <1> jmp short a20d_snooze
|
|
7240 <1>
|
|
7241 <1> ;
|
|
7242 <1> ; Disable the keyboard controller A20 gate
|
|
7243 <1> ;
|
|
7244 <1> a20d_kbc:
|
|
7245 0000018A E81D00 <1> call empty_8042_uncond
|
|
7246 0000018D B0D1 <1> mov al,0D1h
|
|
7247 0000018F E664 <1> out 064h, al ; Command write
|
|
7248 00000191 E81600 <1> call empty_8042_uncond
|
|
7249 00000194 B0DD <1> mov al,0DDh ; A20 off
|
|
7250 00000196 E660 <1> out 060h, al
|
|
7251 00000198 E80F00 <1> call empty_8042_uncond
|
|
7252 <1> ; Wait a bit for it to take effect
|
|
7253 <1> a20d_snooze:
|
|
7254 0000019B 51 <1> push cx
|
|
7255 0000019C B92000 <1> mov cx, disable_wait
|
|
7256 0000019F E8A9FF <1> .delayloop: call a20_test
|
|
7257 000001A2 7402 <1> jz .disabled
|
|
7258 000001A4 E2F9 <1> loop .delayloop
|
|
7259 000001A6 59 <1> .disabled: pop cx
|
|
7260 <1> a20d_dunno:
|
|
7261 <1> a20d_none:
|
|
7262 000001A7 6661 <1> popad
|
|
7263 000001A9 C3 <1> ret
|
|
7264 <1>
|
|
7265 <1> ;
|
|
7266 <1> ; Routine to empty the 8042 KBC controller. If dl != 0
|
|
7267 <1> ; then we will test A20 in the loop and exit if A20 is
|
|
7268 <1> ; suddenly enabled.
|
|
7269 <1> ;
|
|
7270 <1> empty_8042_uncond:
|
|
7271 000001AA 30D2 <1> xor dl,dl
|
|
7272 <1> empty_8042:
|
|
7273 000001AC E89CFF <1> call a20_test
|
|
7274 000001AF 7404 <1> jz .a20_on
|
|
7275 000001B1 20D2 <1> and dl,dl
|
|
7276 000001B3 7517 <1> jnz .done
|
|
7277 000001B5 E80FFF <1> .a20_on: io_delay
|
|
7278 000001B8 E464 <1> in al, 064h ; Status port
|
|
7279 000001BA A801 <1> test al,1
|
|
7280 000001BC 7407 <1> jz .no_output
|
|
7281 000001BE E806FF <1> io_delay
|
|
7282 000001C1 E460 <1> in al, 060h ; Read input
|
|
7283 000001C3 EBE7 <1> jmp short empty_8042
|
|
7284 <1> .no_output:
|
|
7285 000001C5 A802 <1> test al,2
|
|
7286 000001C7 75E3 <1> jnz empty_8042
|
|
7287 000001C9 E8FBFE <1> io_delay
|
|
7288 000001CC C3 <1> .done: ret
|
|
7289 <1>
|
|
7290 <1> ;
|
|
7291 <1> ; Execute a WBINVD instruction if possible on this CPU
|
|
7292 <1> ;
|
|
7293 <1> %if DO_WBINVD
|
|
7294 <1> try_wbinvd:
|
|
7295 <1> wbinvd
|
|
7296 <1> ret
|
|
7297 <1> %endif
|
|
7298 <1>
|
|
7299 <1> ;
|
|
7300 <1> ; bcopy_over_self:
|
|
7301 <1> ;
|
|
7302 <1> ; This routine is used to shuffle memory around, followed by
|
|
7303 <1> ; invoking an entry point somewhere in low memory. This routine
|
|
7304 <1> ; can clobber any memory above 7C00h, we therefore have to move
|
|
7305 <1> ; necessary code into the trackbuf area before doing the copy,
|
|
7306 <1> ; and do adjustments to anything except BSS area references.
|
|
7307 <1> ;
|
|
7308 <1> ; NOTE: Since PXELINUX relocates itself, put all these
|
|
7309 <1> ; references in the ".earlybss" segment.
|
|
7310 <1> ;
|
|
7311 <1> ; After performing the copy, this routine resets the stack and
|
|
7312 <1> ; jumps to the specified entrypoint.
|
|
7313 <1> ;
|
|
7314 <1> ; IMPORTANT: This routine does not canonicalize the stack or the
|
|
7315 <1> ; SS register. That is the responsibility of the caller.
|
|
7316 <1> ;
|
|
7317 <1> ; Inputs:
|
|
7318 <1> ; DS:BX -> Pointer to list of (dst, src, len) pairs
|
|
7319 <1> ; AX -> Number of list entries
|
|
7320 <1> ; [CS:EntryPoint] -> CS:IP to jump to
|
|
7321 <1> ; On stack - initial state (fd, ad, ds, es, fs, gs)
|
|
7322 <1> ;
|
|
7323 <1> shuffle_and_boot:
|
|
7324 000001CD 21C0 <1> and ax,ax
|
|
7325 000001CF 7414 <1> jz .done
|
|
7326 <1> .loop:
|
|
7327 000001D1 668B3F <1> mov edi,[bx]
|
|
7328 000001D4 668B7704 <1> mov esi,[bx+4]
|
|
7329 000001D8 668B4F08 <1> mov ecx,[bx+8]
|
|
7330 000001DC E851FE <1> call bcopy
|
|
7331 000001DF 83C30C <1> add bx,12
|
|
7332 000001E2 48 <1> dec ax
|
|
7333 000001E3 75EC <1> jnz .loop
|
|
7334 <1>
|
|
7335 <1> .done:
|
|
7336 000001E5 0FA9 <1> pop gs
|
|
7337 000001E7 0FA1 <1> pop fs
|
|
7338 000001E9 07 <1> pop es
|
|
7339 000001EA 1F <1> pop ds
|
|
7340 000001EB 6661 <1> popad
|
|
7341 000001ED 669D <1> popfd
|
|
7342 000001EF 2EFF2E[6455] <1> jmp far [cs:EntryPoint]
|
|
7343 <1>
|
|
7344 <1> align 2
|
|
7345 000001F4 [DE00][DE00][E900]- <1> A20List dw a20_dunno, a20_none, a20_bios, a20_kbc, a20_fast
|
|
7346 000001FA [FB00][2101] <1>
|
|
7347 000001FE [A701][A701][7901]- <1> A20DList dw a20d_dunno, a20d_none, a20d_bios, a20d_kbc, a20d_fast
|
|
7348 00000204 [8A01][8201] <1>
|
|
7349 <1> a20_adjust_cnt equ ($-A20List)/2
|
|
7350 <1>
|
|
7351 00000208 0200 <1> A20Type dw A20_NONE ; A20 type
|
|
7352 <1>
|
|
7353 <1> ; Total size of .bcopy32 section
|
|
7354 0000020A 00<rept> <1> alignb 4, db 0 ; Even number of dwords
|
|
7355 <1> __bcopy_size equ $-__bcopy_start
|
|
7356 <1>
|
|
7357 <1> section .earlybss
|
|
7358 <1> alignb 2
|
|
7359 00005564 <res 00000004> <1> EntryPoint resd 1 ; CS:IP for shuffle_and_boot
|
|
7360 00005568 <res 00000004> <1> SavedSSSP resd 1 ; Saved real mode SS:SP
|
|
7361 0000556C <res 00000002> <1> A20Test resw 1 ; Counter for testing status of A20
|
|
7362 0000556E <res 00000001> <1> A20Tries resb 1 ; Times until giving up on A20
|
|
7363 %include "loadhigh.inc" ; Load a file into high memory
|
|
7364 <1> ;; $Id: loadhigh.inc,v 1.7 2005/01/06 22:34:06 hpa Exp $
|
|
7365 <1> ;; -----------------------------------------------------------------------
|
|
7366 <1> ;;
|
|
7367 <1> ;; Copyright 1994-2002 H. Peter Anvin - All Rights Reserved
|
|
7368 <1> ;;
|
|
7369 <1> ;; This program is free software; you can redistribute it and/or modify
|
|
7370 <1> ;; it under the terms of the GNU General Public License as published by
|
|
7371 <1> ;; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
|
|
7372 <1> ;; Boston MA 02111-1307, USA; either version 2 of the License, or
|
|
7373 <1> ;; (at your option) any later version; incorporated herein by reference.
|
|
7374 <1> ;;
|
|
7375 <1> ;; -----------------------------------------------------------------------
|
|
7376 <1>
|
|
7377 <1> ;;
|
|
7378 <1> ;; loadhigh.inc
|
|
7379 <1> ;;
|
|
7380 <1> ;; Load a file into high memory
|
|
7381 <1> ;;
|
|
7382 <1>
|
|
7383 <1> section .text
|
|
7384 <1>
|
|
7385 <1> ;
|
|
7386 <1> ; load_high: loads (the remainder of) a file into high memory.
|
|
7387 <1> ; This routine prints dots for each 64K transferred, and
|
|
7388 <1> ; calls abort_check periodically.
|
|
7389 <1> ;
|
|
7390 <1> ; The xfer_buf_seg is used as a bounce buffer.
|
|
7391 <1> ;
|
|
7392 <1> ; The input address (EDI) should be dword aligned, and the final
|
|
7393 <1> ; stretch is padded with zeroes if necessary.
|
|
7394 <1> ;
|
|
7395 <1> ; Inputs: SI = file handle/cluster pointer
|
|
7396 <1> ; EDI = target address in high memory
|
|
7397 <1> ; EAX = size of remaining file in bytes
|
|
7398 <1> ; DX = zero-padding mask (e.g. 0003h for pad to dword)
|
|
7399 <1> ;
|
|
7400 <1> ; Outputs: SI = file handle/cluster pointer
|
|
7401 <1> ; EDI = first untouched address (not including padding)
|
|
7402 <1> ;
|
|
7403 <1> load_high:
|
|
7404 000021BB 06 <1> push es
|
|
7405 <1>
|
|
7406 000021BC BB0020 <1> mov bx,xfer_buf_seg
|
|
7407 000021BF 8EC3 <1> mov es,bx
|
|
7408 <1>
|
|
7409 <1> .read_loop:
|
|
7410 000021C1 21F6 <1> and si,si ; If SI == 0 then we have end of file
|
|
7411 000021C3 7460 <1> jz .eof
|
|
7412 000021C5 56 <1> push si
|
|
7413 000021C6 BE[D006] <1> mov si,dot_msg
|
|
7414 000021C9 E888FC <1> call cwritestr
|
|
7415 000021CC 5E <1> pop si
|
|
7416 000021CD E8BCEF <1> call abort_check
|
|
7417 <1>
|
|
7418 000021D0 6650 <1> push eax ; <A> Total bytes to transfer
|
|
7419 000021D2 663D00000100 <1> cmp eax,(1 << 16) ; Max 64K in one transfer
|
|
7420 000021D8 7606 <1> jna .size_ok
|
|
7421 000021DA 66B800000100 <1> mov eax,(1 << 16)
|
|
7422 <1> .size_ok:
|
|
7423 000021E0 6650 <1> push eax ; <B> Bytes transferred this chunk
|
|
7424 000021E2 6605FF010000 <1> add eax,SECTOR_SIZE-1
|
|
7425 000021E8 66C1E809 <1> shr eax,SECTOR_SHIFT ; Convert to sectors
|
|
7426 <1>
|
|
7427 <1> ; Now (e)ax contains the number of sectors to get
|
|
7428 000021EC 6657 <1> push edi ; <C> Target buffer
|
|
7429 000021EE 89C1 <1> mov cx,ax
|
|
7430 000021F0 31DB <1> xor bx,bx ; ES:0
|
|
7431 000021F2 E8C9F3 <1> call getfssec ; Load the data into xfer_buf_seg
|
|
7432 000021F5 665F <1> pop edi ; <C> Target buffer
|
|
7433 000021F7 6659 <1> pop ecx ; <B> Byte count this round
|
|
7434 000021F9 6651 <1> push ecx ; <B> Byte count this round
|
|
7435 000021FB 6657 <1> push edi ; <C> Target buffer
|
|
7436 <1> .fix_slop:
|
|
7437 000021FD 85D1 <1> test cx,dx
|
|
7438 000021FF 7409 <1> jz .noslop
|
|
7439 <1> ; The last dword fractional - pad with zeroes
|
|
7440 <1> ; Zero-padding is critical for multi-file initramfs.
|
|
7441 00002201 2667C60100 <1> mov byte [es:ecx],0
|
|
7442 00002206 6641 <1> inc ecx
|
|
7443 00002208 EBF3 <1> jmp short .fix_slop
|
|
7444 <1> .noslop:
|
|
7445 0000220A 6656 <1> push esi ; <D> File handle/cluster pointer
|
|
7446 0000220C 66BE00000200 <1> mov esi,(xfer_buf_seg << 4) ; Source address
|
|
7447 00002212 E8(3000) <1> call bcopy ; Copy to high memory
|
|
7448 00002215 665E <1> pop esi ; <D> File handle/cluster pointer
|
|
7449 00002217 665F <1> pop edi ; <C> Target buffer
|
|
7450 00002219 6659 <1> pop ecx ; <B> Byte count this round
|
|
7451 0000221B 6658 <1> pop eax ; <A> Total bytes to transfer
|
|
7452 0000221D 6601CF <1> add edi,ecx
|
|
7453 00002220 6629C8 <1> sub eax,ecx
|
|
7454 00002223 759C <1> jnz .read_loop ; More to read...
|
|
7455 <1>
|
|
7456 <1> .eof:
|
|
7457 00002225 07 <1> pop es
|
|
7458 00002226 C3 <1> ret
|
|
7459 <1>
|
|
7460 %include "font.inc" ; VGA font stuff
|
|
7461 <1> ;; $Id: font.inc,v 1.7 2004/12/27 07:04:08 hpa Exp $
|
|
7462 <1> ;; -----------------------------------------------------------------------
|
|
7463 <1> ;;
|
|
7464 <1> ;; Copyright 1994-2004 H. Peter Anvin - All Rights Reserved
|
|
7465 <1> ;;
|
|
7466 <1> ;; This program is free software; you can redistribute it and/or modify
|
|
7467 <1> ;; it under the terms of the GNU General Public License as published by
|
|
7468 <1> ;; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
|
|
7469 <1> ;; Boston MA 02111-1307, USA; either version 2 of the License, or
|
|
7470 <1> ;; (at your option) any later version; incorporated herein by reference.
|
|
7471 <1> ;;
|
|
7472 <1> ;; -----------------------------------------------------------------------
|
|
7473 <1>
|
|
7474 <1> ;;
|
|
7475 <1> ;; font.inc
|
|
7476 <1> ;;
|
|
7477 <1> ;; VGA font handling code
|
|
7478 <1> ;;
|
|
7479 <1>
|
|
7480 <1> section .text
|
|
7481 <1>
|
|
7482 <1> ;
|
|
7483 <1> ; loadfont: Load a .psf font file and install it onto the VGA console
|
|
7484 <1> ; (if we're not on a VGA screen then ignore.) It is called with
|
|
7485 <1> ; SI and DX:AX set by routine searchdir
|
|
7486 <1> ;
|
|
7487 <1> loadfont:
|
|
7488 00002227 BB[0000] <1> mov bx,trackbuf ; The trackbuf is >= 16K; the part
|
|
7489 0000222A 8B0E[0009] <1> mov cx,[BufSafe] ; of a PSF file we care about is no
|
|
7490 0000222E E88DF3 <1> call getfssec ; more than 8K+4 bytes
|
|
7491 <1>
|
|
7492 00002231 A1[0000] <1> mov ax,[trackbuf] ; Magic number
|
|
7493 00002234 3D3604 <1> cmp ax,0436h
|
|
7494 00002237 755B <1> jne lf_ret
|
|
7495 <1>
|
|
7496 00002239 A0[0200] <1> mov al,[trackbuf+2] ; File mode
|
|
7497 0000223C 3C05 <1> cmp al,5 ; Font modes 0-5 supported
|
|
7498 0000223E 7754 <1> ja lf_ret
|
|
7499 <1>
|
|
7500 00002240 8A3E[0300] <1> mov bh,byte [trackbuf+3] ; Height of font
|
|
7501 00002244 80FF02 <1> cmp bh,2 ; VGA minimum
|
|
7502 00002247 724B <1> jb lf_ret
|
|
7503 00002249 80FF20 <1> cmp bh,32 ; VGA maximum
|
|
7504 0000224C 7746 <1> ja lf_ret
|
|
7505 <1>
|
|
7506 <1> ; Copy to font buffer
|
|
7507 0000224E BE[0400] <1> mov si,trackbuf+4 ; Start of font data
|
|
7508 00002251 883E[FC00] <1> mov [VGAFontSize],bh
|
|
7509 00002255 BF[0000] <1> mov di,vgafontbuf
|
|
7510 00002258 B90008 <1> mov cx,(32*256) >> 2 ; Maximum size
|
|
7511 0000225B F366A5 <1> rep movsd
|
|
7512 <1>
|
|
7513 0000225E C606[FE00]01 <1> mov [UserFont], byte 1 ; Set font flag
|
|
7514 <1>
|
|
7515 <1> ; Fall through to use_font
|
|
7516 <1>
|
|
7517 <1> ;
|
|
7518 <1> ; use_font:
|
|
7519 <1> ; This routine activates whatever font happens to be in the
|
|
7520 <1> ; vgafontbuf, and updates the adjust_screen data.
|
|
7521 <1> ; Must be called with CS = DS = ES
|
|
7522 <1> ;
|
|
7523 <1> use_font:
|
|
7524 00002263 F606[FE00]01 <1> test [UserFont], byte 1 ; Are we using a user-specified font?
|
|
7525 00002268 743C <1> jz adjust_screen ; If not, just do the normal stuff
|
|
7526 <1>
|
|
7527 0000226A BD[0000] <1> mov bp,vgafontbuf
|
|
7528 0000226D 8A3E[FC00] <1> mov bh,[VGAFontSize]
|
|
7529 <1>
|
|
7530 00002271 30DB <1> xor bl,bl ; Needed by both INT 10h calls
|
|
7531 00002273 803E[1001]01 <1> cmp [UsingVGA], byte 1 ; Are we in graphics mode?
|
|
7532 00002278 751B <1> jne .text
|
|
7533 <1>
|
|
7534 <1> .graphics:
|
|
7535 0000227A 31C9 <1> xor cx,cx
|
|
7536 0000227C 88F9 <1> mov cl,bh ; CX = bytes/character
|
|
7537 0000227E B8E001 <1> mov ax,480
|
|
7538 00002281 F6F1 <1> div cl ; Compute char rows per screen
|
|
7539 00002283 88C2 <1> mov dl,al
|
|
7540 00002285 FEC8 <1> dec al
|
|
7541 00002287 A2[C908] <1> mov [VidRows],al
|
|
7542 0000228A B82111 <1> mov ax,1121h ; Set user character table
|
|
7543 0000228D CD10 <1> int 10h
|
|
7544 0000228F C606[C808]4F <1> mov [VidCols], byte 79 ; Always 80 bytes/line
|
|
7545 00002294 C3 <1> .lf_ret: ret ; No need to call adjust_screen
|
|
7546 <1>
|
|
7547 <1> .text:
|
|
7548 00002295 B90001 <1> mov cx,256
|
|
7549 00002298 31D2 <1> xor dx,dx
|
|
7550 0000229A B81011 <1> mov ax,1110h
|
|
7551 0000229D CD10 <1> int 10h ; Load into VGA RAM
|
|
7552 <1>
|
|
7553 0000229F 30DB <1> xor bl,bl
|
|
7554 000022A1 B80311 <1> mov ax,1103h ; Select page 0
|
|
7555 000022A4 CD10 <1> int 10h
|
|
7556 <1>
|
|
7557 <1> ; Fall through to adjust_screen
|
|
7558 <1>
|
|
7559 <1> lf_ret equ use_font.lf_ret
|
|
7560 <1>
|
|
7561 <1> ;
|
|
7562 <1> ; adjust_screen: Set the internal variables associated with the screen size.
|
|
7563 <1> ; This is a subroutine in case we're loading a custom font.
|
|
7564 <1> ;
|
|
7565 <1> adjust_screen:
|
|
7566 000022A6 60 <1> pusha
|
|
7567 000022A7 A08404 <1> mov al,[BIOS_vidrows]
|
|
7568 000022AA 20C0 <1> and al,al
|
|
7569 000022AC 7502 <1> jnz vidrows_ok
|
|
7570 000022AE B018 <1> mov al,24 ; No vidrows in BIOS, assume 25
|
|
7571 <1> ; (Remember: vidrows == rows-1)
|
|
7572 000022B0 A2[C908] <1> vidrows_ok: mov [VidRows],al
|
|
7573 000022B3 B40F <1> mov ah,0fh
|
|
7574 000022B5 CD10 <1> int 10h ; Read video state
|
|
7575 000022B7 FECC <1> dec ah ; Store count-1 (same as rows)
|
|
7576 000022B9 8826[C808] <1> mov [VidCols],ah
|
|
7577 000022BD 61 <1> popa
|
|
7578 000022BE C3 <1> ret
|
|
7579 <1>
|
|
7580 <1>
|
|
7581 <1> ; VGA font buffer at the end of memory (so loading a font works even
|
|
7582 <1> ; in graphics mode, but don't put too much pressure on the .bss)
|
|
7583 <1> section .latebss
|
|
7584 00000000 <res 00002000> <1> vgafontbuf resb 8192
|
|
7585 <1>
|
|
7586 <1> section .data
|
|
7587 000000FB 00 <1> align 2, db 0
|
|
7588 000000FC 1000 <1> VGAFontSize dw 16 ; Defaults to 16 byte font
|
|
7589 000000FE 00 <1> UserFont db 0 ; Using a user-specified font
|
|
7590 <1>
|
|
7591 <1>
|
|
7592 %include "graphics.inc" ; VGA graphics
|
|
7593 <1> ;; $Id: graphics.inc,v 1.4 2004/12/17 06:42:01 hpa Exp $
|
|
7594 <1> ;; -----------------------------------------------------------------------
|
|
7595 <1> ;;
|
|
7596 <1> ;; Copyright 1994-2002 H. Peter Anvin - All Rights Reserved
|
|
7597 <1> ;;
|
|
7598 <1> ;; This program is free software; you can redistribute it and/or modify
|
|
7599 <1> ;; it under the terms of the GNU General Public License as published by
|
|
7600 <1> ;; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
|
|
7601 <1> ;; Boston MA 02111-1307, USA; either version 2 of the License, or
|
|
7602 <1> ;; (at your option) any later version; incorporated herein by reference.
|
|
7603 <1> ;;
|
|
7604 <1> ;; -----------------------------------------------------------------------
|
|
7605 <1>
|
|
7606 <1> ; ----------------------------------------------------------------------------
|
|
7607 <1> ; VGA splash screen code
|
|
7608 <1> ; ----------------------------------------------------------------------------
|
|
7609 <1>
|
|
7610 <1> ;
|
|
7611 <1> ; vgadisplayfile:
|
|
7612 <1> ; Display a graphical splash screen.
|
|
7613 <1> ;
|
|
7614 <1> ; Input:
|
|
7615 <1> ;
|
|
7616 <1> ; SI = cluster/socket pointer
|
|
7617 <1> ;
|
|
7618 <1> section .text
|
|
7619 <1>
|
|
7620 <1> vgadisplayfile:
|
|
7621 000022BF 8936[641E] <1> mov [VGACluster],si
|
|
7622 000022C3 06 <1> push es
|
|
7623 <1>
|
|
7624 <1> ; This is a cheap and easy way to make sure the screen is
|
|
7625 <1> ; cleared in case we were in graphics mode already
|
|
7626 000022C4 E87E01 <1> call vgaclearmode
|
|
7627 000022C7 E84D01 <1> call vgasetmode
|
|
7628 000022CA 7514 <1> jnz .error_nz
|
|
7629 <1>
|
|
7630 <1> .graphalready:
|
|
7631 000022CC B80020 <1> mov ax,xfer_buf_seg ; Use as temporary storage
|
|
7632 000022CF 8EC0 <1> mov es,ax
|
|
7633 000022D1 8EE0 <1> mov fs,ax
|
|
7634 <1>
|
|
7635 000022D3 E8F300 <1> call vgagetchunk ; Get the first chunk
|
|
7636 <1>
|
|
7637 <1> ; The header WILL be in the first chunk.
|
|
7638 000022D6 2666813E00203DF313- <1> cmp dword [es:xbs_vgabuf],0x1413f33d ; Magic number
|
|
7639 000022DF 14 <1>
|
|
7640 000022E0 757D <1> .error_nz: jne .error
|
|
7641 000022E2 26A10420 <1> mov ax,[es:xbs_vgabuf+4]
|
|
7642 000022E6 A3[601E] <1> mov [GraphXSize],ax
|
|
7643 <1>
|
|
7644 000022E9 BA0820 <1> mov dx,xbs_vgabuf+8 ; Color map offset
|
|
7645 000022EC B81210 <1> mov ax,1012h ; Set RGB registers
|
|
7646 000022EF 31DB <1> xor bx,bx ; First register number
|
|
7647 000022F1 B91000 <1> mov cx,16 ; 16 registers
|
|
7648 000022F4 CD10 <1> int 10h
|
|
7649 <1>
|
|
7650 <1> .movecursor:
|
|
7651 000022F6 26A10620 <1> mov ax,[es:xbs_vgabuf+6] ; Number of pixel rows
|
|
7652 000022FA 8B16[FC00] <1> mov dx,[VGAFontSize]
|
|
7653 000022FE 01D0 <1> add ax,dx
|
|
7654 00002300 48 <1> dec ax
|
|
7655 00002301 F6F2 <1> div dl
|
|
7656 00002303 31D2 <1> xor dx,dx ; Set column to 0
|
|
7657 00002305 3A06[C908] <1> cmp al,[VidRows]
|
|
7658 00002309 7205 <1> jb .rowsok
|
|
7659 0000230B A0[C908] <1> mov al,[VidRows]
|
|
7660 0000230E FEC8 <1> dec al
|
|
7661 <1> .rowsok:
|
|
7662 00002310 88C6 <1> mov dh,al
|
|
7663 00002312 B402 <1> mov ah,2
|
|
7664 00002314 31DB <1> xor bx,bx
|
|
7665 00002316 CD10 <1> int 10h ; Set cursor below image
|
|
7666 <1>
|
|
7667 00002318 268B0E0620 <1> mov cx,[es:xbs_vgabuf+6] ; Number of graphics rows
|
|
7668 <1>
|
|
7669 0000231D BE3820 <1> mov si,xbs_vgabuf+8+3*16 ; Beginning of pixel data
|
|
7670 00002320 C706[621E]0000 <1> mov word [VGAPos],0
|
|
7671 <1>
|
|
7672 <1> .drawpixelrow:
|
|
7673 00002326 51 <1> push cx
|
|
7674 00002327 8B0E[601E] <1> mov cx,[GraphXSize]
|
|
7675 0000232B BF0040 <1> mov di,xbs_vgatmpbuf ; Row buffer
|
|
7676 0000232E E83000 <1> call rledecode ; Decode one row
|
|
7677 00002331 56 <1> push si
|
|
7678 00002332 BE0040 <1> mov si,xbs_vgatmpbuf
|
|
7679 00002335 89F7 <1> mov di,si
|
|
7680 00002337 033E[601E] <1> add di,[GraphXSize]
|
|
7681 0000233B B9A000 <1> mov cx,640/4
|
|
7682 0000233E 6631C0 <1> xor eax,eax
|
|
7683 00002341 F366AB <1> rep stosd ; Clear rest of row
|
|
7684 00002344 BF00A0 <1> mov di,0A000h ; VGA segment
|
|
7685 00002347 8EC7 <1> mov es,di
|
|
7686 00002349 8B3E[621E] <1> mov di,[VGAPos]
|
|
7687 0000234D BD8002 <1> mov bp,640
|
|
7688 00002350 E89500 <1> call packedpixel2vga
|
|
7689 00002353 8306[621E]50 <1> add word [VGAPos],byte 80 ; Advance to next pixel row
|
|
7690 00002358 0FA0 <1> push fs
|
|
7691 0000235A 07 <1> pop es
|
|
7692 0000235B 5E <1> pop si
|
|
7693 0000235C 59 <1> pop cx
|
|
7694 0000235D E2C7 <1> loop .drawpixelrow
|
|
7695 <1>
|
|
7696 <1> .error:
|
|
7697 0000235F 07 <1> pop es
|
|
7698 00002360 C3 <1> ret
|
|
7699 <1>
|
|
7700 <1> ;
|
|
7701 <1> ; rledecode:
|
|
7702 <1> ; Decode a pixel row in RLE16 format.
|
|
7703 <1> ;
|
|
7704 <1> ; FS:SI -> input
|
|
7705 <1> ; CX -> pixel count
|
|
7706 <1> ; ES:DI -> output (packed pixel)
|
|
7707 <1> ;
|
|
7708 <1> rledecode:
|
|
7709 00002361 66D1E6 <1> shl esi,1 ; Nybble pointer
|
|
7710 00002364 30D2 <1> xor dl,dl ; Last pixel
|
|
7711 <1> .loop:
|
|
7712 00002366 E83E00 <1> call .getnybble
|
|
7713 00002369 38D0 <1> cmp al,dl
|
|
7714 0000236B 740D <1> je .run ; Start of run sequence
|
|
7715 0000236D AA <1> stosb
|
|
7716 0000236E 88C2 <1> mov dl,al
|
|
7717 00002370 49 <1> dec cx
|
|
7718 00002371 75F3 <1> jnz .loop
|
|
7719 <1> .done:
|
|
7720 00002373 66D1EE <1> shr esi,1
|
|
7721 00002376 83D600 <1> adc si,byte 0
|
|
7722 00002379 C3 <1> ret
|
|
7723 <1> .run:
|
|
7724 0000237A 31DB <1> xor bx,bx
|
|
7725 0000237C E82800 <1> call .getnybble
|
|
7726 0000237F 20C0 <1> and al,al
|
|
7727 00002381 7410 <1> jz .longrun
|
|
7728 00002383 88C3 <1> mov bl,al
|
|
7729 <1> .dorun:
|
|
7730 00002385 51 <1> push cx
|
|
7731 00002386 89D9 <1> mov cx,bx
|
|
7732 00002388 88D0 <1> mov al,dl
|
|
7733 0000238A F3AA <1> rep stosb
|
|
7734 0000238C 59 <1> pop cx
|
|
7735 0000238D 29D9 <1> sub cx,bx
|
|
7736 0000238F 77D5 <1> ja .loop
|
|
7737 00002391 EBE0 <1> jmp short .done
|
|
7738 <1> .longrun:
|
|
7739 00002393 E81100 <1> call .getnybble
|
|
7740 00002396 88C4 <1> mov ah,al
|
|
7741 00002398 E80C00 <1> call .getnybble
|
|
7742 0000239B C0E004 <1> shl al,4
|
|
7743 0000239E 08E0 <1> or al,ah
|
|
7744 000023A0 88C3 <1> mov bl,al
|
|
7745 000023A2 83C310 <1> add bx,16
|
|
7746 000023A5 EBDE <1> jmp short .dorun
|
|
7747 <1> .getnybble:
|
|
7748 000023A7 66D1EE <1> shr esi,1
|
|
7749 000023AA 64AC <1> fs lodsb
|
|
7750 000023AC 7208 <1> jc .high
|
|
7751 000023AE 4E <1> dec si
|
|
7752 000023AF 240F <1> and al,0Fh
|
|
7753 000023B1 F9 <1> stc
|
|
7754 000023B2 66D1D6 <1> rcl esi,1
|
|
7755 000023B5 C3 <1> ret
|
|
7756 <1> .high:
|
|
7757 000023B6 C0E804 <1> shr al,4
|
|
7758 000023B9 81FE0040 <1> cmp si,xbs_vgabuf+trackbufsize ; Chunk overrun
|
|
7759 000023BD 7206 <1> jb .nonewchunk
|
|
7760 000023BF E80700 <1> call vgagetchunk
|
|
7761 000023C2 BE0020 <1> mov si,xbs_vgabuf ; Start at beginning of buffer
|
|
7762 <1> .nonewchunk:
|
|
7763 000023C5 66D1E6 <1> shl esi,1
|
|
7764 000023C8 C3 <1> ret
|
|
7765 <1>
|
|
7766 <1> ;
|
|
7767 <1> ; vgagetchunk:
|
|
7768 <1> ; Get a new trackbufsize chunk of VGA image data
|
|
7769 <1> ;
|
|
7770 <1> ; On input, ES is assumed to point to the buffer segment.
|
|
7771 <1> ;
|
|
7772 <1> vgagetchunk:
|
|
7773 000023C9 6660 <1> pushad
|
|
7774 000023CB 8B36[641E] <1> mov si,[VGACluster]
|
|
7775 000023CF 21F6 <1> and si,si
|
|
7776 000023D1 7412 <1> jz .eof ; EOF overrun, not much to do...
|
|
7777 <1>
|
|
7778 000023D3 8B0E[0009] <1> mov cx,[BufSafe] ; One trackbuf worth of data
|
|
7779 000023D7 BB0020 <1> mov bx,xbs_vgabuf
|
|
7780 000023DA E8E1F1 <1> call getfssec
|
|
7781 <1>
|
|
7782 000023DD 7302 <1> jnc .noteof
|
|
7783 000023DF 31F6 <1> xor si,si
|
|
7784 000023E1 8936[641E] <1> .noteof: mov [VGACluster],si
|
|
7785 <1>
|
|
7786 000023E5 6661 <1> .eof: popad
|
|
7787 000023E7 C3 <1> ret
|
|
7788 <1>
|
|
7789 <1> ;
|
|
7790 <1> ; packedpixel2vga:
|
|
7791 <1> ; Convert packed-pixel to VGA bitplanes
|
|
7792 <1> ;
|
|
7793 <1> ; FS:SI -> packed pixel string
|
|
7794 <1> ; BP -> pixel count (multiple of 8)
|
|
7795 <1> ; ES:DI -> output
|
|
7796 <1> ;
|
|
7797 <1> packedpixel2vga:
|
|
7798 000023E8 BAC403 <1> mov dx,3C4h ; VGA Sequencer Register select port
|
|
7799 000023EB B002 <1> mov al,2 ; Sequencer mask
|
|
7800 000023ED EE <1> out dx,al ; Select the sequencer mask
|
|
7801 000023EE 42 <1> inc dx ; VGA Sequencer Register data port
|
|
7802 000023EF B001 <1> mov al,1
|
|
7803 000023F1 88C3 <1> mov bl,al
|
|
7804 <1> .planeloop:
|
|
7805 000023F3 60 <1> pusha
|
|
7806 000023F4 EE <1> out dx,al
|
|
7807 <1> .loop1:
|
|
7808 000023F5 B90800 <1> mov cx,8
|
|
7809 <1> .loop2:
|
|
7810 000023F8 87CB <1> xchg cx,bx
|
|
7811 000023FA 64AC <1> fs lodsb
|
|
7812 000023FC D2E8 <1> shr al,cl
|
|
7813 000023FE D0D5 <1> rcl ch,1 ; VGA is bigendian. Sigh.
|
|
7814 00002400 87CB <1> xchg cx,bx
|
|
7815 00002402 E2F4 <1> loop .loop2
|
|
7816 00002404 88F8 <1> mov al,bh
|
|
7817 00002406 AA <1> stosb
|
|
7818 00002407 83ED08 <1> sub bp,byte 8
|
|
7819 0000240A 77E9 <1> ja .loop1
|
|
7820 0000240C 61 <1> popa
|
|
7821 0000240D FEC3 <1> inc bl
|
|
7822 0000240F D0E0 <1> shl al,1
|
|
7823 00002411 80FB04 <1> cmp bl,4
|
|
7824 00002414 76DD <1> jbe .planeloop
|
|
7825 00002416 C3 <1> ret
|
|
7826 <1>
|
|
7827 <1> ;
|
|
7828 <1> ; vgasetmode:
|
|
7829 <1> ; Enable VGA graphics, if possible; return ZF=1 on success
|
|
7830 <1> ; DS must be set to the base segment; ES is set to DS.
|
|
7831 <1> ;
|
|
7832 <1> vgasetmode:
|
|
7833 00002417 1E <1> push ds
|
|
7834 00002418 07 <1> pop es
|
|
7835 00002419 B8001A <1> mov ax,1A00h ; Get video card and monitor
|
|
7836 0000241C 31DB <1> xor bx,bx
|
|
7837 0000241E CD10 <1> int 10h
|
|
7838 00002420 80EB07 <1> sub bl, 7 ; BL=07h and BL=08h OK
|
|
7839 00002423 80FB01 <1> cmp bl, 1
|
|
7840 00002426 771C <1> ja .error ; ZF=0
|
|
7841 <1> ; mov bx,TextColorReg
|
|
7842 <1> ; mov dx,1009h ; Read color registers
|
|
7843 <1> ; int 10h
|
|
7844 00002428 B81200 <1> mov ax,0012h ; Set mode = 640x480 VGA 16 colors
|
|
7845 0000242B CD10 <1> int 10h
|
|
7846 0000242D BA[FF00] <1> mov dx,linear_color
|
|
7847 00002430 B80210 <1> mov ax,1002h ; Write color registers
|
|
7848 00002433 CD10 <1> int 10h
|
|
7849 00002435 C606[1001]01 <1> mov [UsingVGA], byte 1
|
|
7850 <1>
|
|
7851 0000243A E826FE <1> call use_font ; Set graphics font/data
|
|
7852 0000243D C606[C000]00 <1> mov byte [ScrollAttribute], 00h
|
|
7853 <1>
|
|
7854 00002442 31C0 <1> xor ax,ax ; Set ZF
|
|
7855 <1> .error:
|
|
7856 00002444 C3 <1> ret
|
|
7857 <1>
|
|
7858 <1> ;
|
|
7859 <1> ; vgaclearmode:
|
|
7860 <1> ; Disable VGA graphics. It is not safe to assume any value
|
|
7861 <1> ; for DS or ES.
|
|
7862 <1> ;
|
|
7863 <1> vgaclearmode:
|
|
7864 00002445 1E <1> push ds
|
|
7865 00002446 06 <1> push es
|
|
7866 00002447 6660 <1> pushad
|
|
7867 00002449 8CC8 <1> mov ax,cs
|
|
7868 0000244B 8ED8 <1> mov ds,ax
|
|
7869 0000244D 8EC0 <1> mov es,ax
|
|
7870 0000244F 803E[1001]01 <1> cmp [UsingVGA], byte 1
|
|
7871 00002454 7512 <1> jne .done
|
|
7872 00002456 B80300 <1> mov ax,0003h ; Return to normal video mode
|
|
7873 00002459 CD10 <1> int 10h
|
|
7874 <1> ; mov dx,TextColorReg ; Restore color registers
|
|
7875 <1> ; mov ax,1002h
|
|
7876 <1> ; int 10h
|
|
7877 0000245B C606[1001]00 <1> mov [UsingVGA], byte 0
|
|
7878 <1>
|
|
7879 00002460 E800FE <1> call use_font ; Restore text font/data
|
|
7880 00002463 C606[C000]07 <1> mov byte [ScrollAttribute], 07h
|
|
7881 <1> .done:
|
|
7882 00002468 6661 <1> popad
|
|
7883 0000246A 07 <1> pop es
|
|
7884 0000246B 1F <1> pop ds
|
|
7885 0000246C C3 <1> ret
|
|
7886 <1>
|
|
7887 <1> ;
|
|
7888 <1> ; vgashowcursor/vgahidecursor:
|
|
7889 <1> ; If VGA graphics is enabled, draw a cursor/clear a cursor
|
|
7890 <1> ;
|
|
7891 <1> vgashowcursor:
|
|
7892 0000246D 6660 <1> pushad
|
|
7893 0000246F B05F <1> mov al,'_'
|
|
7894 00002471 EB04 <1> jmp short vgacursorcommon
|
|
7895 <1> vgahidecursor:
|
|
7896 00002473 6660 <1> pushad
|
|
7897 00002475 B020 <1> mov al,' '
|
|
7898 <1> vgacursorcommon:
|
|
7899 00002477 803E[1001]01 <1> cmp [UsingVGA], byte 1
|
|
7900 0000247C 750A <1> jne .done
|
|
7901 0000247E B409 <1> mov ah,09h
|
|
7902 00002480 BB0700 <1> mov bx,0007h
|
|
7903 00002483 B90100 <1> mov cx,1
|
|
7904 00002486 CD10 <1> int 10h
|
|
7905 <1> .done:
|
|
7906 00002488 6661 <1> popad
|
|
7907 0000248A C3 <1> ret
|
|
7908 <1>
|
|
7909 <1>
|
|
7910 <1> section .data
|
|
7911 <1> ; Map colors to consecutive DAC registers
|
|
7912 000000FF 000102030405060708- <1> linear_color db 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0
|
|
7913 00000108 090A0B0C0D0E0F00 <1>
|
|
7914 00000110 00 <1> UsingVGA db 0
|
|
7915 <1>
|
|
7916 <1> section .bss
|
|
7917 <1> alignb 2
|
|
7918 00001E60 <res 00000002> <1> GraphXSize resw 1 ; Width of splash screen file
|
|
7919 00001E62 <res 00000002> <1> VGAPos resw 1 ; Pointer into VGA memory
|
|
7920 00001E64 <res 00000002> <1> VGACluster resw 1 ; Cluster pointer for VGA image file
|
|
7921 00001E66 <res 00000002> <1> VGAFilePtr resw 1 ; Pointer into VGAFileBuf
|
|
7922 00001E68 <res 00000011> <1> TextColorReg resb 17 ; VGA color registers for text mode
|
|
7923 <1> %if IS_SYSLINUX
|
|
7924 <1> VGAFileBuf resb FILENAME_MAX+2 ; Unmangled VGA image name
|
|
7925 <1> %else
|
|
7926 00001E79 <res 00000080> <1> VGAFileBuf resb FILENAME_MAX ; Unmangled VGA image name
|
|
7927 <1> %endif
|
|
7928 <1> VGAFileBufEnd equ $
|
|
7929 00001EF9 <res 00000080> <1> VGAFileMBuf resb FILENAME_MAX ; Mangled VGA image name
|
|
7930 <1>
|
|
7931 %include "highmem.inc" ; High memory sizing
|
|
7932 <1> ;; $Id: highmem.inc,v 1.4 2004/12/17 06:42:01 hpa Exp $
|
|
7933 <1> ;; -----------------------------------------------------------------------
|
|
7934 <1> ;;
|
|
7935 <1> ;; Copyright 1994-2004 H. Peter Anvin - All Rights Reserved
|
|
7936 <1> ;;
|
|
7937 <1> ;; This program is free software; you can redistribute it and/or modify
|
|
7938 <1> ;; it under the terms of the GNU General Public License as published by
|
|
7939 <1> ;; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
|
|
7940 <1> ;; Boston MA 02111-1307, USA; either version 2 of the License, or
|
|
7941 <1> ;; (at your option) any later version; incorporated herein by reference.
|
|
7942 <1> ;;
|
|
7943 <1> ;; -----------------------------------------------------------------------
|
|
7944 <1>
|
|
7945 <1> ;;
|
|
7946 <1> ;; highmem.inc
|
|
7947 <1> ;;
|
|
7948 <1> ;; Probe for the size of high memory. This can be overridden by a
|
|
7949 <1> ;; mem= command on the command line while booting a new kernel.
|
|
7950 <1> ;;
|
|
7951 <1>
|
|
7952 <1> section .text
|
|
7953 <1>
|
|
7954 <1> ;
|
|
7955 <1> ; This is set up as a subroutine; it will set up the global variable
|
|
7956 <1> ; HighMemSize. All registers are preserved. Assumes DS == CS.
|
|
7957 <1> ;
|
|
7958 <1> highmemsize:
|
|
7959 0000248B 06 <1> push es
|
|
7960 0000248C 6660 <1> pushad
|
|
7961 <1>
|
|
7962 <1> ;
|
|
7963 <1> ; First, try INT 15:E820 (get BIOS memory map)
|
|
7964 <1> ;
|
|
7965 <1> get_e820:
|
|
7966 0000248E 6631DB <1> xor ebx,ebx ; Start with first record
|
|
7967 00002491 66C706[941F]0000F0- <1> mov dword [E820Max],-(1 << 20) ; Max amount of high memory
|
|
7968 00002499 FF <1>
|
|
7969 0000249A 66891E[901F] <1> mov dword [E820Mem],ebx ; Detected amount of high memory
|
|
7970 0000249F 8EC3 <1> mov es,bx ; Need ES = DS = 0 for now
|
|
7971 000024A1 EB05 <1> jmp short .do_e820 ; Skip "at end" check first time!
|
|
7972 000024A3 6621DB <1> .int_loop: and ebx,ebx ; If we're back at beginning...
|
|
7973 000024A6 7478 <1> jz .e820_done ; ... we're done
|
|
7974 000024A8 66B820E80000 <1> .do_e820: mov eax,0000E820h
|
|
7975 000024AE 66BA50414D53 <1> mov edx,534D4150h ; "SMAP" backwards
|
|
7976 000024B4 6631C9 <1> xor ecx,ecx
|
|
7977 000024B7 B114 <1> mov cl,20 ; ECX <- 20
|
|
7978 000024B9 BF[7C1F] <1> mov di,E820Buf
|
|
7979 000024BC CD15 <1> int 15h
|
|
7980 000024BE 7307 <1> jnc .no_carry
|
|
7981 <1> ; If carry, ebx == 0 means error, ebx != 0 means we're done
|
|
7982 000024C0 6621DB <1> and ebx,ebx
|
|
7983 000024C3 755B <1> jnz .e820_done
|
|
7984 000024C5 EB6F <1> jmp no_e820
|
|
7985 <1> .no_carry:
|
|
7986 000024C7 663D50414D53 <1> cmp eax,534D4150h
|
|
7987 000024CD 7567 <1> jne no_e820
|
|
7988 <1> ;
|
|
7989 <1> ; Look for a memory block starting at <= 1 MB and continuing upward
|
|
7990 <1> ;
|
|
7991 000024CF 66833E[801F]00 <1> cmp dword [E820Buf+4], byte 0
|
|
7992 000024D5 77CC <1> ja .int_loop ; Start >= 4 GB?
|
|
7993 000024D7 66BA00001000 <1> mov edx, (1 << 20)
|
|
7994 000024DD 662B16[7C1F] <1> sub edx, [E820Buf]
|
|
7995 000024E2 7319 <1> jnb .ram_range ; Start >= 1 MB?
|
|
7996 <1> ; If we get here, it starts > 1 MB but < 4 GB; if this is a
|
|
7997 <1> ; *non*-memory range, remember this as unusable; some BIOSes
|
|
7998 <1> ; get the length of primary RAM wrong!
|
|
7999 000024E4 66833E[8C1F]01 <1> cmp dword [E820Buf+16], byte 1
|
|
8000 000024EA 74B7 <1> je .int_loop ; If it's memory, don't worry about it
|
|
8001 000024EC 66F7DA <1> neg edx ; This means what for memory limit?
|
|
8002 000024EF 663B16[941F] <1> cmp edx,[E820Max] ; Better or worse
|
|
8003 000024F4 73AD <1> jnb .int_loop
|
|
8004 000024F6 668916[941F] <1> mov [E820Max],edx
|
|
8005 000024FB EBA6 <1> jmp .int_loop
|
|
8006 <1>
|
|
8007 <1> .ram_range:
|
|
8008 000024FD F9 <1> stc
|
|
8009 000024FE 6619C0 <1> sbb eax,eax ; eax <- 0xFFFFFFFF
|
|
8010 00002501 66833E[881F]00 <1> cmp dword [E820Buf+12], byte 0
|
|
8011 00002507 7704 <1> ja .huge ; Size >= 4 GB
|
|
8012 00002509 66A1[841F] <1> mov eax, [E820Buf+8]
|
|
8013 0000250D 6629D0 <1> .huge: sub eax, edx ; Adjust size to start at 1 MB
|
|
8014 00002510 7691 <1> jbe .int_loop ; Completely below 1 MB?
|
|
8015 <1>
|
|
8016 <1> ; Now EAX contains the size of memory 1 MB...up
|
|
8017 00002512 66833E[8C1F]01 <1> cmp dword [E820Buf+16], byte 1
|
|
8018 00002518 7589 <1> jne .int_loop ; High memory isn't usable memory!!!!
|
|
8019 <1>
|
|
8020 <1> ; We're good!
|
|
8021 0000251A 66A3[901F] <1> mov [E820Mem],eax
|
|
8022 0000251E EB83 <1> jmp .int_loop ; Still need to add low 1 MB
|
|
8023 <1>
|
|
8024 <1> .e820_done:
|
|
8025 00002520 66A1[901F] <1> mov eax,[E820Mem]
|
|
8026 00002524 6621C0 <1> and eax,eax
|
|
8027 00002527 740D <1> jz no_e820 ; Nothing found by E820?
|
|
8028 00002529 663B06[941F] <1> cmp eax,[E820Max] ; Make sure we're not limited
|
|
8029 0000252E 7638 <1> jna got_highmem_add1mb
|
|
8030 00002530 66A1[941F] <1> mov eax,[E820Max]
|
|
8031 00002534 EB32 <1> jmp got_highmem_add1mb
|
|
8032 <1>
|
|
8033 <1> ;
|
|
8034 <1> ; INT 15:E820 failed. Try INT 15:E801.
|
|
8035 <1> ;
|
|
8036 <1> no_e820:
|
|
8037 00002536 B801E8 <1> mov ax,0e801h ; Query high memory (semi-recent)
|
|
8038 00002539 CD15 <1> int 15h
|
|
8039 0000253B 7215 <1> jc no_e801
|
|
8040 0000253D 3D003C <1> cmp ax,3c00h
|
|
8041 00002540 7710 <1> ja no_e801 ; > 3C00h something's wrong with this call
|
|
8042 00002542 721A <1> jb e801_hole ; If memory hole we can only use low part
|
|
8043 <1>
|
|
8044 00002544 89D8 <1> mov ax,bx
|
|
8045 00002546 66C1E010 <1> shl eax,16 ; 64K chunks
|
|
8046 0000254A 660500000001 <1> add eax,(16 << 20) ; Add first 16M
|
|
8047 00002550 EB1C <1> jmp short got_highmem
|
|
8048 <1>
|
|
8049 <1> ;
|
|
8050 <1> ; INT 15:E801 failed. Try INT 15:88.
|
|
8051 <1> ;
|
|
8052 <1> no_e801:
|
|
8053 00002552 B488 <1> mov ah,88h ; Query high memory (oldest)
|
|
8054 00002554 CD15 <1> int 15h
|
|
8055 00002556 3D0038 <1> cmp ax,14*1024 ; Don't trust memory >15M
|
|
8056 00002559 7603 <1> jna e801_hole
|
|
8057 0000255B B80038 <1> mov ax,14*1024
|
|
8058 <1> e801_hole:
|
|
8059 0000255E 6625FFFF0000 <1> and eax,0ffffh
|
|
8060 00002564 66C1E00A <1> shl eax,10 ; Convert from kilobytes
|
|
8061 <1> got_highmem_add1mb:
|
|
8062 00002568 660500001000 <1> add eax,(1 << 20) ; First megabyte
|
|
8063 <1> got_highmem:
|
|
8064 <1> %if HIGHMEM_SLOP != 0
|
|
8065 0000256E 662D00000200 <1> sub eax,HIGHMEM_SLOP
|
|
8066 <1> %endif
|
|
8067 00002574 66A3[981F] <1> mov [HighMemSize],eax
|
|
8068 00002578 6661 <1> popad
|
|
8069 0000257A 07 <1> pop es
|
|
8070 0000257B C3 <1> ret ; Done!
|
|
8071 <1>
|
|
8072 <1> section .bss
|
|
8073 00001F79 <res 00000001>- <1> alignb 4
|
|
8074 00001F79 <rept> <1>
|
|
8075 00001F7C <res 00000014> <1> E820Buf resd 5 ; INT 15:E820 data buffer
|
|
8076 00001F90 <res 00000004> <1> E820Mem resd 1 ; Memory detected by E820
|
|
8077 00001F94 <res 00000004> <1> E820Max resd 1 ; Is E820 memory capped?
|
|
8078 00001F98 <res 00000004> <1> HighMemSize resd 1 ; End of memory pointer (bytes)
|
|
8079 %include "strcpy.inc" ; strcpy()
|
|
8080 <1> ;
|
|
8081 <1> ; strcpy: Copy DS:SI -> ES:DI up to and including a null byte;
|
|
8082 <1> ; on exit SI and DI point to the byte *after* the null byte
|
|
8083 <1> ;
|
|
8084 <1> section .text
|
|
8085 <1>
|
|
8086 0000257C 50 <1> strcpy: push ax
|
|
8087 0000257D AC <1> .loop: lodsb
|
|
8088 0000257E AA <1> stosb
|
|
8089 0000257F 20C0 <1> and al,al
|
|
8090 00002581 75FA <1> jnz .loop
|
|
8091 00002583 58 <1> pop ax
|
|
8092 00002584 C3 <1> ret
|
|
8093 <1>
|
|
8094 %include "rawcon.inc" ; Console I/O w/o using the console functions
|
|
8095 <1> ;
|
|
8096 <1> ; writechr: Write a single character in AL to the console without
|
|
8097 <1> ; mangling any registers. This does raw console writes,
|
|
8098 <1> ; since some PXE BIOSes seem to interfere regular console I/O.
|
|
8099 <1> ;
|
|
8100 <1> %if IS_ISOLINUX
|
|
8101 <1> writechr_full:
|
|
8102 <1> %else
|
|
8103 <1> writechr:
|
|
8104 <1> %endif
|
|
8105 00002585 1E <1> push ds
|
|
8106 00002586 0E <1> push cs
|
|
8107 00002587 1F <1> pop ds
|
|
8108 00002588 E813F8 <1> call write_serial ; write to serial port if needed
|
|
8109 0000258B 669C <1> pushfd
|
|
8110 0000258D F606[BE00]01 <1> test byte [DisplayCon],01h ; Write to screen?
|
|
8111 00002592 7443 <1> jz .nothing
|
|
8112 <1>
|
|
8113 00002594 6660 <1> pushad
|
|
8114 00002596 8A3E6204 <1> mov bh,[BIOS_page]
|
|
8115 0000259A 50 <1> push ax
|
|
8116 0000259B B403 <1> mov ah,03h ; Read cursor position
|
|
8117 0000259D CD10 <1> int 10h
|
|
8118 0000259F 58 <1> pop ax
|
|
8119 000025A0 3C08 <1> cmp al,8
|
|
8120 000025A2 7456 <1> je .bs
|
|
8121 000025A4 3C0D <1> cmp al,13
|
|
8122 000025A6 744E <1> je .cr
|
|
8123 000025A8 3C0A <1> cmp al,10
|
|
8124 000025AA 7419 <1> je .lf
|
|
8125 000025AC 52 <1> push dx
|
|
8126 000025AD 8A3E6204 <1> mov bh,[BIOS_page]
|
|
8127 000025B1 B307 <1> mov bl,07h ; White on black
|
|
8128 000025B3 B90100 <1> mov cx,1 ; One only
|
|
8129 000025B6 B409 <1> mov ah,09h ; Write char and attribute
|
|
8130 000025B8 CD10 <1> int 10h
|
|
8131 000025BA 5A <1> pop dx
|
|
8132 000025BB FEC2 <1> inc dl
|
|
8133 000025BD 3A16[C808] <1> cmp dl,[VidCols]
|
|
8134 000025C1 760A <1> jna .curxyok
|
|
8135 000025C3 30D2 <1> xor dl,dl
|
|
8136 000025C5 FEC6 <1> .lf: inc dh
|
|
8137 000025C7 3A36[C908] <1> cmp dh,[VidRows]
|
|
8138 000025CB 770E <1> ja .scroll
|
|
8139 000025CD 8A3E6204 <1> .curxyok: mov bh,[BIOS_page]
|
|
8140 000025D1 B402 <1> mov ah,02h ; Set cursor position
|
|
8141 000025D3 CD10 <1> int 10h
|
|
8142 000025D5 6661 <1> .ret: popad
|
|
8143 <1> .nothing:
|
|
8144 000025D7 669D <1> popfd
|
|
8145 000025D9 1F <1> pop ds
|
|
8146 000025DA C3 <1> ret
|
|
8147 000025DB FECE <1> .scroll: dec dh
|
|
8148 000025DD 8A3E6204 <1> mov bh,[BIOS_page]
|
|
8149 000025E1 B402 <1> mov ah,02h
|
|
8150 000025E3 CD10 <1> int 10h
|
|
8151 000025E5 B80106 <1> mov ax,0601h ; Scroll up one line
|
|
8152 000025E8 8A3E[C000] <1> mov bh,[ScrollAttribute]
|
|
8153 000025EC 31C9 <1> xor cx,cx
|
|
8154 000025EE 8B16[C808] <1> mov dx,[ScreenSize] ; The whole screen
|
|
8155 000025F2 CD10 <1> int 10h
|
|
8156 000025F4 EBDF <1> jmp short .ret
|
|
8157 000025F6 30D2 <1> .cr: xor dl,dl
|
|
8158 000025F8 EBD3 <1> jmp short .curxyok
|
|
8159 000025FA 80EA01 <1> .bs: sub dl,1
|
|
8160 000025FD 73CE <1> jnc .curxyok
|
|
8161 000025FF 8A16[C808] <1> mov dl,[VidCols]
|
|
8162 00002603 80EE01 <1> sub dh,1
|
|
8163 00002606 73C5 <1> jnc .curxyok
|
|
8164 00002608 30F6 <1> xor dh,dh
|
|
8165 0000260A EBC1 <1> jmp short .curxyok
|
|
8166 <1>
|
|
8167 %include "dnsresolv.inc" ; DNS resolver
|
|
8168 <1> ; -*- fundamental -*-
|
|
8169 <1> ; -----------------------------------------------------------------------
|
|
8170 <1> ;
|
|
8171 <1> ; Copyright 2004 H. Peter Anvin - All Rights Reserved
|
|
8172 <1> ;
|
|
8173 <1> ; This program is free software; you can redistribute it and/or modify
|
|
8174 <1> ; it under the terms of the GNU General Public License as published by
|
|
8175 <1> ; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
|
|
8176 <1> ; Bostom MA 02111-1307, USA; either version 2 of the License, or
|
|
8177 <1> ; (at your option) any later version; incorporated herein by reference.
|
|
8178 <1> ;
|
|
8179 <1> ; -----------------------------------------------------------------------
|
|
8180 <1>
|
|
8181 <1> ;
|
|
8182 <1> ; dnsresolv.inc
|
|
8183 <1> ;
|
|
8184 <1> ; Very simple DNS resolver (assumes recursion-enabled DNS server;
|
|
8185 <1> ; this should be the normal thing for client-serving DNS servers.)
|
|
8186 <1> ;
|
|
8187 <1>
|
|
8188 <1> DNS_PORT equ htons(53) ; Default DNS port
|
|
8189 <1> DNS_MAX_PACKET equ 512 ; Defined by protocol
|
|
8190 <1> ; TFTP uses the range 49152-57343
|
|
8191 <1> DNS_LOCAL_PORT equ htons(60053) ; All local DNS queries come from this port #
|
|
8192 <1> DNS_MAX_SERVERS equ 4 ; Max no of DNS servers
|
|
8193 <1>
|
|
8194 <1> section .text
|
|
8195 <1>
|
|
8196 <1> ;
|
|
8197 <1> ; Turn a string in DS:SI into a DNS "label set" in ES:DI.
|
|
8198 <1> ; On return, DI points to the first byte after the label set,
|
|
8199 <1> ; and SI to the terminating byte.
|
|
8200 <1> ;
|
|
8201 <1> ; On return, DX contains the number of dots encountered.
|
|
8202 <1> ;
|
|
8203 <1> dns_mangle:
|
|
8204 0000260C 50 <1> push ax
|
|
8205 0000260D 53 <1> push bx
|
|
8206 0000260E 31D2 <1> xor dx,dx
|
|
8207 <1> .isdot:
|
|
8208 00002610 42 <1> inc dx
|
|
8209 00002611 30C0 <1> xor al,al
|
|
8210 00002613 89FB <1> mov bx,di
|
|
8211 00002615 AA <1> stosb
|
|
8212 <1> .getbyte:
|
|
8213 00002616 AC <1> lodsb
|
|
8214 00002617 20C0 <1> and al,al
|
|
8215 00002619 740E <1> jz .endstring
|
|
8216 0000261B 3C3A <1> cmp al,':'
|
|
8217 0000261D 740A <1> jz .endstring
|
|
8218 0000261F 3C2E <1> cmp al,'.'
|
|
8219 00002621 74ED <1> je .isdot
|
|
8220 00002623 26FE07 <1> inc byte [es:bx]
|
|
8221 00002626 AA <1> stosb
|
|
8222 00002627 EBED <1> jmp .getbyte
|
|
8223 <1> .endstring:
|
|
8224 00002629 4E <1> dec si
|
|
8225 0000262A 4A <1> dec dx ; We always counted one high
|
|
8226 0000262B 26803F00 <1> cmp byte [es:bx],0
|
|
8227 0000262F 7403 <1> jz .done
|
|
8228 00002631 30C0 <1> xor al,al
|
|
8229 00002633 AA <1> stosb
|
|
8230 <1> .done:
|
|
8231 00002634 5B <1> pop bx
|
|
8232 00002635 58 <1> pop ax
|
|
8233 00002636 C3 <1> ret
|
|
8234 <1>
|
|
8235 <1> ;
|
|
8236 <1> ; Compare two sets of DNS labels, in DS:SI and ES:DI; the one in SI
|
|
8237 <1> ; is allowed pointers relative to a packet in DNSRecvBuf.
|
|
8238 <1> ;
|
|
8239 <1> ; Assumes DS == ES. ZF = 1 if same; no registers changed.
|
|
8240 <1> ; (Note: change reference to [di] to [es:di] to remove DS == ES assumption)
|
|
8241 <1> ;
|
|
8242 <1> dns_compare:
|
|
8243 00002637 60 <1> pusha
|
|
8244 <1> %if 0
|
|
8245 <1>
|
|
8246 <1> .label:
|
|
8247 <1> lodsb
|
|
8248 <1> cmp al,0C0h
|
|
8249 <1> jb .noptr
|
|
8250 <1> and al,03Fh ; Get pointer value
|
|
8251 <1> mov ah,al ; ... in network byte order!
|
|
8252 <1> lodsb
|
|
8253 <1> mov si,DNSRecvBuf
|
|
8254 <1> add si,ax
|
|
8255 <1> jmp .label
|
|
8256 <1> .noptr:
|
|
8257 <1> cmp al,[di]
|
|
8258 <1> jne .done ; Mismatch
|
|
8259 <1> inc di
|
|
8260 <1> movzx cx,al ; End label?
|
|
8261 <1> and cx,cx ; ZF = 1 if match
|
|
8262 <1> jz .done
|
|
8263 <1>
|
|
8264 <1> ; We have a string of bytes that need to match now
|
|
8265 <1> repe cmpsb
|
|
8266 <1> je .label
|
|
8267 <1>
|
|
8268 <1> .done:
|
|
8269 <1> %else
|
|
8270 00002638 31C0 <1> xor ax,ax
|
|
8271 <1> %endif
|
|
8272 0000263A 61 <1> popa
|
|
8273 0000263B C3 <1> ret
|
|
8274 <1>
|
|
8275 <1> ;
|
|
8276 <1> ; Skip past a DNS label set in DS:SI.
|
|
8277 <1> ;
|
|
8278 <1> dns_skiplabel:
|
|
8279 0000263C 50 <1> push ax
|
|
8280 0000263D 31C0 <1> xor ax,ax ; AH == 0
|
|
8281 <1> .loop:
|
|
8282 0000263F AC <1> lodsb
|
|
8283 00002640 3CC0 <1> cmp al,0C0h ; Pointer?
|
|
8284 00002642 7308 <1> jae .ptr
|
|
8285 00002644 20C0 <1> and al,al
|
|
8286 00002646 7405 <1> jz .done
|
|
8287 00002648 01C6 <1> add si,ax
|
|
8288 0000264A EBF3 <1> jmp .loop
|
|
8289 <1> .ptr:
|
|
8290 0000264C 46 <1> inc si ; Pointer is two bytes
|
|
8291 <1> .done:
|
|
8292 0000264D 58 <1> pop ax
|
|
8293 0000264E C3 <1> ret
|
|
8294 <1>
|
|
8295 <1> ; DNS header format
|
|
8296 <1> struc dnshdr
|
|
8297 00000000 <res 00000002> <1> .id: resw 1
|
|
8298 00000002 <res 00000002> <1> .flags: resw 1
|
|
8299 00000004 <res 00000002> <1> .qdcount: resw 1
|
|
8300 00000006 <res 00000002> <1> .ancount: resw 1
|
|
8301 00000008 <res 00000002> <1> .nscount: resw 1
|
|
8302 0000000A <res 00000002> <1> .arcount: resw 1
|
|
8303 <1> endstruc
|
|
8304 <1>
|
|
8305 <1> ; DNS query
|
|
8306 <1> struc dnsquery
|
|
8307 00000000 <res 00000002> <1> .qtype: resw 1
|
|
8308 00000002 <res 00000002> <1> .qclass: resw 1
|
|
8309 <1> endstruc
|
|
8310 <1>
|
|
8311 <1> ; DNS RR
|
|
8312 <1> struc dnsrr
|
|
8313 00000000 <res 00000002> <1> .type: resw 1
|
|
8314 00000002 <res 00000002> <1> .class: resw 1
|
|
8315 00000004 <res 00000004> <1> .ttl: resd 1
|
|
8316 00000008 <res 00000002> <1> .rdlength: resw 1
|
|
8317 <1> .rdata: equ $
|
|
8318 <1> endstruc
|
|
8319 <1>
|
|
8320 <1> section .bss
|
|
8321 <1> alignb 2, db 0
|
|
8322 00001F9C <res 00000200> <1> DNSSendBuf resb DNS_MAX_PACKET
|
|
8323 0000219C <res 00000200> <1> DNSRecvBuf resb DNS_MAX_PACKET
|
|
8324 0000239C <res 00000100> <1> LocalDomain resb 256 ; Max possible length
|
|
8325 0000249C <res 00000010> <1> DNSServers resd DNS_MAX_SERVERS
|
|
8326 <1>
|
|
8327 <1> section .data
|
|
8328 <1> pxe_udp_write_pkt_dns:
|
|
8329 00000111 0000 <1> .status: dw 0 ; Status
|
|
8330 00000113 00000000 <1> .sip: dd 0 ; Server IP
|
|
8331 00000117 00000000 <1> .gip: dd 0 ; Gateway IP
|
|
8332 0000011B EA95 <1> .lport: dw DNS_LOCAL_PORT ; Local port
|
|
8333 0000011D 0035 <1> .rport: dw DNS_PORT ; Remote port
|
|
8334 0000011F 0000 <1> .buffersize: dw 0 ; Size of packet
|
|
8335 00000121 [9C1F]0000 <1> .buffer: dw DNSSendBuf, 0 ; off, seg of buffer
|
|
8336 <1>
|
|
8337 <1> pxe_udp_read_pkt_dns:
|
|
8338 00000125 0000 <1> .status: dw 0 ; Status
|
|
8339 00000127 00000000 <1> .sip: dd 0 ; Source IP
|
|
8340 0000012B 00000000 <1> .dip: dd 0 ; Destination (our) IP
|
|
8341 0000012F 0035 <1> .rport: dw DNS_PORT ; Remote port
|
|
8342 00000131 EA95 <1> .lport: dw DNS_LOCAL_PORT ; Local port
|
|
8343 00000133 0002 <1> .buffersize: dw DNS_MAX_PACKET ; Max packet size
|
|
8344 00000135 [9C21]0000 <1> .buffer: dw DNSRecvBuf, 0 ; off, seg of buffer
|
|
8345 <1>
|
|
8346 00000139 [9C24] <1> LastDNSServer dw DNSServers
|
|
8347 <1>
|
|
8348 <1> ; Actual resolver function
|
|
8349 <1> ; Points to a null-terminated or :-terminated string in DS:SI
|
|
8350 <1> ; and returns the name in EAX if it exists and can be found.
|
|
8351 <1> ; If EAX = 0 on exit, the lookup failed.
|
|
8352 <1>
|
|
8353 <1> section .text
|
|
8354 <1> dns_resolv:
|
|
8355 0000264F 1E <1> push ds
|
|
8356 00002650 06 <1> push es
|
|
8357 00002651 57 <1> push di
|
|
8358 00002652 51 <1> push cx
|
|
8359 00002653 52 <1> push dx
|
|
8360 <1>
|
|
8361 00002654 0E <1> push cs
|
|
8362 00002655 07 <1> pop es ; ES <- CS
|
|
8363 <1>
|
|
8364 <1> ; First, build query packet
|
|
8365 00002656 BF[9E1F] <1> mov di,DNSSendBuf+dnshdr.flags
|
|
8366 00002659 26FF45FE <1> inc word [es:di-2] ; New query ID
|
|
8367 0000265D B80100 <1> mov ax,htons(0100h) ; Recursion requested
|
|
8368 00002660 AB <1> stosw
|
|
8369 00002661 B80001 <1> mov ax,htons(1) ; One question
|
|
8370 00002664 AB <1> stosw
|
|
8371 00002665 31C0 <1> xor ax,ax ; No answers, NS or ARs
|
|
8372 00002667 AB <1> stosw
|
|
8373 00002668 AB <1> stosw
|
|
8374 00002669 AB <1> stosw
|
|
8375 <1>
|
|
8376 0000266A E89FFF <1> call dns_mangle ; Convert name to DNS labels
|
|
8377 <1>
|
|
8378 0000266D 0E <1> push cs ; DS <- CS
|
|
8379 0000266E 1F <1> pop ds
|
|
8380 <1>
|
|
8381 0000266F 56 <1> push si ; Save pointer to after DNS string
|
|
8382 <1>
|
|
8383 <1> ; Initialize...
|
|
8384 00002670 66A1[EC08] <1> mov eax,[MyIP]
|
|
8385 00002674 66A3[2B01] <1> mov [pxe_udp_read_pkt_dns.dip],eax
|
|
8386 <1>
|
|
8387 00002678 21D2 <1> and dx,dx
|
|
8388 0000267A 7507 <1> jnz .fqdn ; If we have dots, assume it's FQDN
|
|
8389 0000267C 4F <1> dec di ; Remove final null
|
|
8390 0000267D BE[9C23] <1> mov si,LocalDomain
|
|
8391 00002680 E8F9FE <1> call strcpy ; Uncompressed DNS label set so it ends in null
|
|
8392 <1> .fqdn:
|
|
8393 <1>
|
|
8394 00002683 B80001 <1> mov ax,htons(1)
|
|
8395 00002686 AB <1> stosw ; QTYPE = 1 = A
|
|
8396 00002687 AB <1> stosw ; QCLASS = 1 = IN
|
|
8397 <1>
|
|
8398 00002688 81EF[9C1F] <1> sub di,DNSSendBuf
|
|
8399 0000268C 893E[1F01] <1> mov [pxe_udp_write_pkt_dns.buffersize],di
|
|
8400 <1>
|
|
8401 <1> ; Now, send it to the nameserver(s)
|
|
8402 <1> ; Outer loop: exponential backoff
|
|
8403 <1> ; Inner loop: scan the various DNS servers
|
|
8404 <1>
|
|
8405 00002690 BA0C00 <1> mov dx,PKT_TIMEOUT
|
|
8406 00002693 B90600 <1> mov cx,PKT_RETRY
|
|
8407 <1> .backoff:
|
|
8408 00002696 BE[9C24] <1> mov si,DNSServers
|
|
8409 <1> .servers:
|
|
8410 00002699 3B36[3901] <1> cmp si,[LastDNSServer]
|
|
8411 0000269D 720E <1> jb .moreservers
|
|
8412 <1>
|
|
8413 <1> .nomoreservers:
|
|
8414 0000269F 01D2 <1> add dx,dx ; Exponential backoff
|
|
8415 000026A1 E2F3 <1> loop .backoff
|
|
8416 <1>
|
|
8417 000026A3 6631C0 <1> xor eax,eax ; Nothing...
|
|
8418 <1> .done:
|
|
8419 000026A6 5E <1> pop si
|
|
8420 000026A7 5A <1> pop dx
|
|
8421 000026A8 59 <1> pop cx
|
|
8422 000026A9 5F <1> pop di
|
|
8423 000026AA 07 <1> pop es
|
|
8424 000026AB 1F <1> pop ds
|
|
8425 000026AC C3 <1> ret
|
|
8426 <1>
|
|
8427 <1> .moreservers:
|
|
8428 000026AD 66AD <1> lodsd ; EAX <- next server
|
|
8429 000026AF 56 <1> push si
|
|
8430 000026B0 51 <1> push cx
|
|
8431 000026B1 52 <1> push dx
|
|
8432 <1>
|
|
8433 000026B2 C706[1101]0000 <1> mov word [pxe_udp_write_pkt_dns.status],0
|
|
8434 <1>
|
|
8435 000026B8 66A3[1301] <1> mov [pxe_udp_write_pkt_dns.sip],eax
|
|
8436 000026BC 66A3[2701] <1> mov [pxe_udp_read_pkt_dns.sip],eax
|
|
8437 000026C0 663306[EC08] <1> xor eax,[MyIP]
|
|
8438 000026C5 662306[F408] <1> and eax,[Netmask]
|
|
8439 000026CA 7404 <1> jz .nogw
|
|
8440 000026CC 66A1[F808] <1> mov eax,[Gateway]
|
|
8441 <1> .nogw:
|
|
8442 000026D0 66A3[1701] <1> mov [pxe_udp_write_pkt_dns.gip],eax
|
|
8443 <1>
|
|
8444 000026D4 BF[1101] <1> mov di,pxe_udp_write_pkt_dns
|
|
8445 000026D7 BB3300 <1> mov bx,PXENV_UDP_WRITE
|
|
8446 000026DA E8CAEE <1> call pxenv
|
|
8447 000026DD 0F829F00 <1> jc .timeout ; Treat failed transmit as timeout
|
|
8448 000026E1 833E[1101]00 <1> cmp word [pxe_udp_write_pkt_dns.status],0
|
|
8449 000026E6 0F859600 <1> jne .timeout
|
|
8450 <1>
|
|
8451 000026EA 8B0E6C04 <1> mov cx,[BIOS_timer]
|
|
8452 <1> .waitrecv:
|
|
8453 000026EE A16C04 <1> mov ax,[BIOS_timer]
|
|
8454 000026F1 29C8 <1> sub ax,cx
|
|
8455 000026F3 39D0 <1> cmp ax,dx
|
|
8456 000026F5 0F838700 <1> jae .timeout
|
|
8457 <1>
|
|
8458 000026F9 C706[2501]0000 <1> mov word [pxe_udp_read_pkt_dns.status],0
|
|
8459 000026FF C706[3301]0002 <1> mov word [pxe_udp_read_pkt_dns.buffersize],DNS_MAX_PACKET
|
|
8460 00002705 BF[2501] <1> mov di,pxe_udp_read_pkt_dns
|
|
8461 00002708 BB3200 <1> mov bx,PXENV_UDP_READ
|
|
8462 0000270B E899EE <1> call pxenv
|
|
8463 0000270E 21C0 <1> and ax,ax
|
|
8464 00002710 75DC <1> jnz .waitrecv
|
|
8465 00002712 3906[2501] <1> cmp [pxe_udp_read_pkt_dns.status],ax
|
|
8466 00002716 75D6 <1> jnz .waitrecv
|
|
8467 <1>
|
|
8468 <1> ; Got a packet, deal with it...
|
|
8469 00002718 BE[9C21] <1> mov si,DNSRecvBuf
|
|
8470 0000271B AD <1> lodsw
|
|
8471 0000271C 3B06[9C1F] <1> cmp ax,[DNSSendBuf] ; ID
|
|
8472 00002720 75CC <1> jne .waitrecv ; Not ours
|
|
8473 <1>
|
|
8474 00002722 AD <1> lodsw ; flags
|
|
8475 00002723 3480 <1> xor al,80h ; Query#/Answer bit
|
|
8476 00002725 A9F80F <1> test ax,htons(0F80Fh)
|
|
8477 00002728 7549 <1> jnz .badness
|
|
8478 <1>
|
|
8479 0000272A AD <1> lodsw
|
|
8480 0000272B 86E0 <1> xchg ah,al ; ntohs
|
|
8481 0000272D 89C1 <1> mov cx,ax ; Questions echoed
|
|
8482 0000272F AD <1> lodsw
|
|
8483 00002730 86E0 <1> xchg ah,al ; ntohs
|
|
8484 00002732 50 <1> push ax ; Replies
|
|
8485 00002733 AD <1> lodsw ; NS records
|
|
8486 00002734 AD <1> lodsw ; Authority records
|
|
8487 <1>
|
|
8488 00002735 E308 <1> jcxz .qskipped
|
|
8489 <1> .skipq:
|
|
8490 00002737 E802FF <1> call dns_skiplabel ; Skip name
|
|
8491 0000273A 83C604 <1> add si,4 ; Skip question trailer
|
|
8492 0000273D E2F8 <1> loop .skipq
|
|
8493 <1>
|
|
8494 <1> .qskipped:
|
|
8495 0000273F 59 <1> pop cx ; Number of replies
|
|
8496 00002740 E331 <1> jcxz .badness
|
|
8497 <1>
|
|
8498 <1> .parseanswer:
|
|
8499 00002742 BF[A81F] <1> mov di,DNSSendBuf+dnshdr_size
|
|
8500 00002745 E8EFFE <1> call dns_compare
|
|
8501 00002748 9C <1> pushf
|
|
8502 00002749 E8F0FE <1> call dns_skiplabel
|
|
8503 0000274C 8B4408 <1> mov ax,[si+8] ; RDLENGTH
|
|
8504 0000274F 86E0 <1> xchg ah,al ; ntohs
|
|
8505 00002751 9D <1> popf
|
|
8506 00002752 7518 <1> jnz .notsame
|
|
8507 00002754 66813C00010001 <1> cmp dword [si],htons(1)*0x10001 ; TYPE = A, CLASS = IN?
|
|
8508 0000275B 750F <1> jne .notsame
|
|
8509 0000275D 83F804 <1> cmp ax,4 ; RDLENGTH = 4?
|
|
8510 00002760 750A <1> jne .notsame
|
|
8511 <1> ;
|
|
8512 <1> ; We hit paydirt here...
|
|
8513 <1> ;
|
|
8514 00002762 668B440A <1> mov eax,[si+10]
|
|
8515 <1> .gotresult:
|
|
8516 00002766 83C406 <1> add sp,6 ; Drop timeout information
|
|
8517 00002769 E93AFF <1> jmp .done
|
|
8518 <1>
|
|
8519 <1> .notsame:
|
|
8520 0000276C 83C60A <1> add si,10
|
|
8521 0000276F 01C6 <1> add si,ax
|
|
8522 00002771 E2CF <1> loop .parseanswer
|
|
8523 <1>
|
|
8524 <1> .badness:
|
|
8525 <1> ; We got back no data from this server. Unfortunately, for a recursive,
|
|
8526 <1> ; non-authoritative query there is no such thing as an NXDOMAIN reply,
|
|
8527 <1> ; which technically means we can't draw any conclusions. However,
|
|
8528 <1> ; in practice that means the domain doesn't exist. If this turns out
|
|
8529 <1> ; to be a problem, we may want to add code to go through all the servers
|
|
8530 <1> ; before giving up.
|
|
8531 <1>
|
|
8532 <1> ; If the DNS server wasn't capable of recursion, and isn't capable
|
|
8533 <1> ; of giving us an authoritative reply (i.e. neither AA or RA set),
|
|
8534 <1> ; then at least try a different setver...
|
|
8535 00002773 F706[9E21]0480 <1> test word [DNSRecvBuf+dnshdr.flags],htons(0480h)
|
|
8536 00002779 7405 <1> jz .timeout
|
|
8537 <1>
|
|
8538 0000277B 6631C0 <1> xor eax,eax
|
|
8539 0000277E EBE6 <1> jmp .gotresult
|
|
8540 <1>
|
|
8541 <1> .timeout:
|
|
8542 00002780 5A <1> pop dx
|
|
8543 00002781 59 <1> pop cx
|
|
8544 00002782 5E <1> pop si
|
|
8545 00002783 E913FF <1> jmp .servers
|
|
8546
|
|
8547 ; -----------------------------------------------------------------------------
|
|
8548 ; Begin data section
|
|
8549 ; -----------------------------------------------------------------------------
|
|
8550
|
|
8551 section .data
|
|
8552
|
|
8553 0000013B 303132333435363738- hextbl_lower db '0123456789abcdef'
|
|
8554 00000144 39616263646566
|
|
8555 0000014B 20436F707972696768- copyright_str db ' Copyright (C) 1994-', year, ' H. Peter Anvin'
|
|
8556 00000154 742028432920313939-
|
|
8557 0000015D 342D3230303520482E-
|
|
8558 00000166 20506574657220416E-
|
|
8559 0000016F 76696E
|
|
8560 00000172 0D0A00 db CR, LF, 0
|
|
8561 00000175 626F6F743A2000 boot_prompt db 'boot: ', 0
|
|
8562 0000017C 08200800 wipe_char db BS, ' ', BS, 0
|
|
8563 00000180 436F756C64206E6F74- err_notfound db 'Could not find kernel image: ',0
|
|
8564 00000189 2066696E64206B6572-
|
|
8565 00000192 6E656C20696D616765-
|
|
8566 0000019B 3A2000
|
|
8567 0000019E 0D0A496E76616C6964- err_notkernel db CR, LF, 'Invalid or corrupt kernel image.', CR, LF, 0
|
|
8568 000001A7 206F7220636F727275-
|
|
8569 000001B0 7074206B65726E656C-
|
|
8570 000001B9 20696D6167652E0D0A-
|
|
8571 000001C2 00
|
|
8572 000001C3 497420617070656172- err_noram db 'It appears your computer has less than '
|
|
8573 000001CC 7320796F757220636F-
|
|
8574 000001D5 6D7075746572206861-
|
|
8575 000001DE 73206C657373207468-
|
|
8576 000001E7 616E20
|
|
8577 000001EA 333230 asciidec dosram_k
|
|
8578 000001ED 4B206F66206C6F7720- db 'K of low ("DOS")'
|
|
8579 000001F6 2822444F532229
|
|
8580 000001FD 0D0A db CR, LF
|
|
8581 000001FF 52414D2E20204C696E- db 'RAM. Linux needs at least this amount to boot. If you get'
|
|
8582 00000208 7578206E6565647320-
|
|
8583 00000211 6174206C6561737420-
|
|
8584 0000021A 7468697320616D6F75-
|
|
8585 00000223 6E7420746F20626F6F-
|
|
8586 0000022C 742E2020496620796F-
|
|
8587 00000235 7520676574
|
|
8588 0000023A 0D0A db CR, LF
|
|
8589 0000023C 74686973206D657373- db 'this message in error, hold down the Ctrl key while'
|
|
8590 00000245 61676520696E206572-
|
|
8591 0000024E 726F722C20686F6C64-
|
|
8592 00000257 20646F776E20746865-
|
|
8593 00000260 204374726C206B6579-
|
|
8594 00000269 207768696C65
|
|
8595 0000026F 0D0A db CR, LF
|
|
8596 00000271 626F6F74696E672C20- db 'booting, and I will take your word for it.', CR, LF, 0
|
|
8597 0000027A 616E6420492077696C-
|
|
8598 00000283 6C2074616B6520796F-
|
|
8599 0000028C 757220776F72642066-
|
|
8600 00000295 6F722069742E0D0A00
|
|
8601 0000029E 556E6B6E6F776E206B- err_badcfg db 'Unknown keyword in config file.', CR, LF, 0
|
|
8602 000002A7 6579776F726420696E-
|
|
8603 000002B0 20636F6E6669672066-
|
|
8604 000002B9 696C652E0D0A00
|
|
8605 000002C0 4D697373696E672070- err_noparm db 'Missing parameter in config file.', CR, LF, 0
|
|
8606 000002C9 6172616D6574657220-
|
|
8607 000002D2 696E20636F6E666967-
|
|
8608 000002DB 2066696C652E0D0A00
|
|
8609 000002E4 0D0A436F756C64206E- err_noinitrd db CR, LF, 'Could not find ramdisk image: ', 0
|
|
8610 000002ED 6F742066696E642072-
|
|
8611 000002F6 616D6469736B20696D-
|
|
8612 000002FF 6167653A2000
|
|
8613 00000305 4E6F7420656E6F7567- err_nohighmem db 'Not enough memory to load specified kernel.', CR, LF, 0
|
|
8614 0000030E 68206D656D6F727920-
|
|
8615 00000317 746F206C6F61642073-
|
|
8616 00000320 706563696669656420-
|
|
8617 00000329 6B65726E656C2E0D0A-
|
|
8618 00000332 00
|
|
8619 00000333 0D0A4B65726E656C20- err_highload db CR, LF, 'Kernel transfer failure.', CR, LF, 0
|
|
8620 0000033C 7472616E7366657220-
|
|
8621 00000345 6661696C7572652E0D-
|
|
8622 0000034E 0A00
|
|
8623 00000350 43616E6E6F74206C6F- err_oldkernel db 'Cannot load a ramdisk with an old kernel image.'
|
|
8624 00000359 616420612072616D64-
|
|
8625 00000362 69736B207769746820-
|
|
8626 0000036B 616E206F6C64206B65-
|
|
8627 00000374 726E656C20696D6167-
|
|
8628 0000037D 652E
|
|
8629 0000037F 0D0A00 db CR, LF, 0
|
|
8630 00000382 3A20617474656D7074- err_notdos db ': attempted DOS system call', CR, LF, 0
|
|
8631 0000038B 656420444F53207379-
|
|
8632 00000394 7374656D2063616C6C-
|
|
8633 0000039D 0D0A00
|
|
8634 000003A0 434F4D424F4F542069- err_comlarge db 'COMBOOT image too large.', CR, LF, 0
|
|
8635 000003A9 6D61676520746F6F20-
|
|
8636 000003B2 6C617267652E0D0A00
|
|
8637 000003BB 42535320696D616765- err_bssimage db 'BSS images not supported.', CR, LF, 0
|
|
8638 000003C4 73206E6F7420737570-
|
|
8639 000003CD 706F727465642E0D0A-
|
|
8640 000003D6 00
|
|
8641 000003D7 0D0A41323020676174- err_a20 db CR, LF, 'A20 gate not responding!', CR, LF, 0
|
|
8642 000003E0 65206E6F7420726573-
|
|
8643 000003E9 706F6E64696E67210D-
|
|
8644 000003F2 0A00
|
|
8645 000003F4 0D0A426F6F74206661- err_bootfailed db CR, LF, 'Boot failed: press a key to retry, or wait for reset...', CR, LF, 0
|
|
8646 000003FD 696C65643A20707265-
|
|
8647 00000406 73732061206B657920-
|
|
8648 0000040F 746F2072657472792C-
|
|
8649 00000418 206F72207761697420-
|
|
8650 00000421 666F72207265736574-
|
|
8651 0000042A 2E2E2E0D0A00
|
|
8652 bailmsg equ err_bootfailed
|
|
8653 00000430 4E6F2021505845206F- err_nopxe db "No !PXE or PXENV+ API found; we're dead...", CR, LF, 0
|
|
8654 00000439 72205058454E562B20-
|
|
8655 00000442 41504920666F756E64-
|
|
8656 0000044B 3B2077652772652064-
|
|
8657 00000454 6561642E2E2E0D0A00
|
|
8658 0000045D 505845204150492063- err_pxefailed db 'PXE API call failed, error ', 0
|
|
8659 00000466 616C6C206661696C65-
|
|
8660 0000046F 642C206572726F7220-
|
|
8661 00000478 00
|
|
8662 00000479 4661696C656420746F- err_udpinit db 'Failed to initialize UDP stack', CR, LF, 0
|
|
8663 00000482 20696E697469616C69-
|
|
8664 0000048B 7A6520554450207374-
|
|
8665 00000494 61636B0D0A00
|
|
8666 0000049A 544654502073657276- err_oldtftp db 'TFTP server does not support the tsize option', CR, LF, 0
|
|
8667 000004A3 657220646F6573206E-
|
|
8668 000004AC 6F7420737570706F72-
|
|
8669 000004B5 742074686520747369-
|
|
8670 000004BE 7A65206F7074696F6E-
|
|
8671 000004C7 0D0A00
|
|
8672 000004CA 466F756E6420505845- found_pxenv db 'Found PXENV+ structure', CR, LF, 0
|
|
8673 000004D3 4E562B207374727563-
|
|
8674 000004DC 747572650D0A00
|
|
8675 000004E3 4F6C64205058452041- using_pxenv_msg db 'Old PXE API detected, using PXENV+ structure', CR, LF, 0
|
|
8676 000004EC 504920646574656374-
|
|
8677 000004F5 65642C207573696E67-
|
|
8678 000004FE 205058454E562B2073-
|
|
8679 00000507 74727563747572650D-
|
|
8680 00000510 0A00
|
|
8681 00000512 505845204150492076- apiver_str db 'PXE API version is ',0
|
|
8682 0000051B 657273696F6E206973-
|
|
8683 00000524 2000
|
|
8684 00000526 50584520656E747279- pxeentry_msg db 'PXE entry point found (we hope) at ', 0
|
|
8685 0000052F 20706F696E7420666F-
|
|
8686 00000538 756E64202877652068-
|
|
8687 00000541 6F7065292061742000
|
|
8688 0000054A 5058454E5620656E74- pxenventry_msg db 'PXENV entry point found (we hope) at ', 0
|
|
8689 00000553 727920706F696E7420-
|
|
8690 0000055C 666F756E6420287765-
|
|
8691 00000565 20686F706529206174-
|
|
8692 0000056E 2000
|
|
8693 00000570 5363616E6E696E6720- trymempxe_msg db 'Scanning memory for !PXE structure... ', 0
|
|
8694 00000579 6D656D6F727920666F-
|
|
8695 00000582 722021505845207374-
|
|
8696 0000058B 727563747572652E2E-
|
|
8697 00000594 2E2000
|
|
8698 00000597 5363616E6E696E6720- trymempxenv_msg db 'Scanning memory for PXENV+ structure... ', 0
|
|
8699 000005A0 6D656D6F727920666F-
|
|
8700 000005A9 72205058454E562B20-
|
|
8701 000005B2 737472756374757265-
|
|
8702 000005BB 2E2E2E2000
|
|
8703 000005C0 554E44492064617461- undi_data_msg db 'UNDI data segment at: ',0
|
|
8704 000005C9 207365676D656E7420-
|
|
8705 000005D2 61743A20202000
|
|
8706 000005D9 554E44492064617461- undi_data_len_msg db 'UNDI data segment size: ',0
|
|
8707 000005E2 207365676D656E7420-
|
|
8708 000005EB 73697A653A2000
|
|
8709 000005F2 554E444920636F6465- undi_code_msg db 'UNDI code segment at: ',0
|
|
8710 000005FB 207365676D656E7420-
|
|
8711 00000604 61743A20202000
|
|
8712 0000060B 554E444920636F6465- undi_code_len_msg db 'UNDI code segment size: ',0
|
|
8713 00000614 207365676D656E7420-
|
|
8714 0000061D 73697A653A2000
|
|
8715 00000624 4661696C656420746F- cant_free_msg db 'Failed to free base memory, error ', 0
|
|
8716 0000062D 206672656520626173-
|
|
8717 00000636 65206D656D6F72792C-
|
|
8718 0000063F 206572726F722000
|
|
8719 00000647 6E6F7420666F756E64- notfound_msg db 'not found', CR, LF, 0
|
|
8720 00000650 0D0A00
|
|
8721 00000653 4D7920495020616464- myipaddr_msg db 'My IP address seems to be ',0
|
|
8722 0000065C 72657373207365656D-
|
|
8723 00000665 7320746F2062652000
|
|
8724 0000066E 544654502070726566- tftpprefix_msg db 'TFTP prefix: ', 0
|
|
8725 00000677 69783A2000
|
|
8726 0000067C 426F6F74696E672066- localboot_msg db 'Booting from local disk...', CR, LF, 0
|
|
8727 00000685 726F6D206C6F63616C-
|
|
8728 0000068E 206469736B2E2E2E0D-
|
|
8729 00000697 0A00
|
|
8730 00000699 436F6D6D616E64206C- cmdline_msg db 'Command line: ', CR, LF, 0
|
|
8731 000006A2 696E653A200D0A00
|
|
8732 000006AA 52656164792E0D0A00 ready_msg db 'Ready.', CR, LF, 0
|
|
8733 000006B3 547279696E6720746F- trying_msg db 'Trying to load: ', 0
|
|
8734 000006BC 206C6F61643A2000
|
|
8735 000006C4 0D0A crlfloading_msg db CR, LF ; Fall through
|
|
8736 000006C6 4C6F6164696E672000 loading_msg db 'Loading ', 0
|
|
8737 000006CF 2E dotdot_msg db '.'
|
|
8738 000006D0 2E00 dot_msg db '.', 0
|
|
8739 000006D2 0808080800 fourbs_msg db BS, BS, BS, BS, 0
|
|
8740 000006D7 2061626F727465642E aborted_msg db ' aborted.' ; Fall through to crlf_msg!
|
|
8741 000006E0 0D0A crlf_msg db CR, LF
|
|
8742 000006E2 00 null_msg db 0
|
|
8743 000006E3 0D0C00 crff_msg db CR, FF, 0
|
|
8744 000006E6 64656661756C7400 default_str db 'default', 0
|
|
8745 default_len equ ($-default_str)
|
|
8746 000006EE 0D0A5058454C494E55- syslinux_banner db CR, LF, 'PXELINUX ', version_str, ' ', date, ' ', 0
|
|
8747 000006F7 5820332E3039203078-
|
|
8748 00000700 343165666662636120-
|
|
8749 00000709 00
|
|
8750 0000070A 7078656C696E75782E- cfgprefix db 'pxelinux.cfg/' ; No final null!
|
|
8751 00000713 6366672F
|
|
8752 cfgprefix_len equ ($-cfgprefix)
|
|
8753
|
|
8754 ;
|
|
8755 ; Command line options we'd like to take a look at
|
|
8756 ;
|
|
8757 ; mem= and vga= are handled as normal 32-bit integer values
|
|
8758 00000717 696E697472643D initrd_cmd db 'initrd='
|
|
8759 initrd_cmd_len equ $-initrd_cmd
|
|
8760
|
|
8761 ; This one we make ourselves
|
|
8762 0000071E 424F4F5449463D bootif_str db 'BOOTIF='
|
|
8763 bootif_str_len equ $-bootif_str
|
|
8764 ;
|
|
8765 ; Config file keyword table
|
|
8766 ;
|
|
8767 %include "keywords.inc"
|
|
8768 <1> ;; $Id: keywords.inc,v 1.12 2005/01/04 22:17:17 hpa Exp $
|
|
8769 <1> ;; -----------------------------------------------------------------------
|
|
8770 <1> ;;
|
|
8771 <1> ;; Copyright 1994-2002 H. Peter Anvin - All Rights Reserved
|
|
8772 <1> ;;
|
|
8773 <1> ;; This program is free software; you can redistribute it and/or modify
|
|
8774 <1> ;; it under the terms of the GNU General Public License as published by
|
|
8775 <1> ;; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
|
|
8776 <1> ;; Boston MA 02111-1307, USA; either version 2 of the License, or
|
|
8777 <1> ;; (at your option) any later version; incorporated herein by reference.
|
|
8778 <1> ;;
|
|
8779 <1> ;; -----------------------------------------------------------------------
|
|
8780 <1>
|
|
8781 <1> ;;
|
|
8782 <1> ;; keywords.inc
|
|
8783 <1> ;;
|
|
8784 <1> ;; Common header file for the handling of keyword hash and macros
|
|
8785 <1> ;;
|
|
8786 <1>
|
|
8787 <1> %ifndef DEPEND ; Generated file
|
|
8788 <1> %include "kwdhash.gen"
|
|
8789 <2> hash_hash equ 0x00000023
|
|
8790 <2> hash_menu equ 0x003719b5
|
|
8791 <2> hash_append equ 0xc53999a4
|
|
8792 <2> hash_default equ 0xcc5159ed
|
|
8793 <2> hash_display equ 0xd509bc40
|
|
8794 <2> hash_font equ 0x0032b1b4
|
|
8795 <2> hash_implicit equ 0xa6f50207
|
|
8796 <2> hash_ipappend equ 0xc5399af0
|
|
8797 <2> hash_kbdmap equ 0xd013b850
|
|
8798 <2> hash_kernel equ 0xd068b4cc
|
|
8799 <2> hash_label equ 0x06f104cc
|
|
8800 <2> hash_localboot equ 0x04f0def4
|
|
8801 <2> hash_prompt equ 0xe7163a74
|
|
8802 <2> hash_say equ 0x0001c059
|
|
8803 <2> hash_serial equ 0xe068a84c
|
|
8804 <2> hash_console equ 0x18d831fd
|
|
8805 <2> hash_timeout equ 0xd4e332c9
|
|
8806 <2> hash_allowoptions equ 0x1648dd10
|
|
8807 <2> hash_ontimeout equ 0xd4e35eb9
|
|
8808 <2> hash_onerror equ 0x1a68c589
|
|
8809 <2> hash_noescape equ 0x0d00090e
|
|
8810 <2> hash_f0 equ 0x00000cf0
|
|
8811 <2> hash_f1 equ 0x00000cf1
|
|
8812 <2> hash_f2 equ 0x00000cf2
|
|
8813 <2> hash_f3 equ 0x00000cf3
|
|
8814 <2> hash_f4 equ 0x00000cf4
|
|
8815 <2> hash_f5 equ 0x00000cf5
|
|
8816 <2> hash_f6 equ 0x00000cf6
|
|
8817 <2> hash_f7 equ 0x00000cf7
|
|
8818 <2> hash_f8 equ 0x00000cf8
|
|
8819 <2> hash_f9 equ 0x00000cf9
|
|
8820 <2> hash_f10 equ 0x00019e10
|
|
8821 <2> hash_f11 equ 0x00019e11
|
|
8822 <2> hash_f12 equ 0x00019e12
|
|
8823 <1> %endif
|
|
8824 <1>
|
|
8825 <1> %macro keyword 2
|
|
8826 <1> dd hash_%1 ; Hash value
|
|
8827 <1> dw 0 ; No argument
|
|
8828 <1> dw %2 ; Entrypoint
|
|
8829 <1> %endmacro
|
|
8830 <1>
|
|
8831 <1> %macro keyword 3
|
|
8832 <1> dd hash_%1 ; Hash value
|
|
8833 <1> dw %3 ; 16-bit argument
|
|
8834 <1> dw %2 ; Entrypoint
|
|
8835 <1> %endmacro
|
|
8836 <1>
|
|
8837 <1> %macro keyword 4
|
|
8838 <1> dd hash_%1 ; Hash value
|
|
8839 <1> db %3, %4 ; 2 8-bit arguments
|
|
8840 <1> dw %2 ; Entrypoint
|
|
8841 <1> %endmacro
|
|
8842 <1>
|
|
8843 <1> keywd_size equ 8 ; Bytes per keyword
|
|
8844 <1>
|
|
8845 00000725 00<rept> <1> align 4, db 0
|
|
8846 <1>
|
|
8847 <1> keywd_table:
|
|
8848 <1> keyword hash, pc_comment
|
|
8849 00000728 23000000 <2> dd hash_%1
|
|
8850 0000072C 0000 <2> dw 0
|
|
8851 0000072E [7B20] <2> dw %2
|
|
8852 <1> keyword menu, pc_comment
|
|
8853 00000730 B5193700 <2> dd hash_%1
|
|
8854 00000734 0000 <2> dw 0
|
|
8855 00000736 [7B20] <2> dw %2
|
|
8856 <1> keyword append, pc_append
|
|
8857 00000738 A49939C5 <2> dd hash_%1
|
|
8858 0000073C 0000 <2> dw 0
|
|
8859 0000073E [CF1E] <2> dw %2
|
|
8860 <1> keyword default, pc_default
|
|
8861 00000740 ED5951CC <2> dd hash_%1
|
|
8862 00000744 0000 <2> dw 0
|
|
8863 00000746 [A61E] <2> dw %2
|
|
8864 <1> keyword display, pc_filecmd, get_msg_file
|
|
8865 00000748 40BC09D5 <2> dd hash_%1
|
|
8866 0000074C [EE1B] <2> dw %3
|
|
8867 0000074E [5D1F] <2> dw %2
|
|
8868 <1> keyword font, pc_filecmd, loadfont
|
|
8869 00000750 B4B13200 <2> dd hash_%1
|
|
8870 00000754 [2722] <2> dw %3
|
|
8871 00000756 [5D1F] <2> dw %2
|
|
8872 <1> keyword implicit, pc_setint16, AllowImplicit
|
|
8873 00000758 0702F5A6 <2> dd hash_%1
|
|
8874 0000075C [F200] <2> dw %3
|
|
8875 0000075E [531F] <2> dw %2
|
|
8876 <1> keyword kbdmap, pc_filecmd, loadkeys
|
|
8877 00000760 50B813D0 <2> dd hash_%1
|
|
8878 00000764 [CF1B] <2> dw %3
|
|
8879 00000766 [5D1F] <2> dw %2
|
|
8880 <1> keyword kernel, pc_kernel
|
|
8881 00000768 CCB468D0 <2> dd hash_%1
|
|
8882 0000076C 0000 <2> dw 0
|
|
8883 0000076E [311F] <2> dw %2
|
|
8884 <1> keyword label, pc_label
|
|
8885 00000770 CC04F106 <2> dd hash_%1
|
|
8886 00000774 0000 <2> dw 0
|
|
8887 00000776 [3020] <2> dw %2
|
|
8888 <1> keyword prompt, pc_setint16, ForcePrompt
|
|
8889 00000778 743A16E7 <2> dd hash_%1
|
|
8890 0000077C [F000] <2> dw %3
|
|
8891 0000077E [531F] <2> dw %2
|
|
8892 <1> keyword say, pc_say
|
|
8893 00000780 59C00100 <2> dd hash_%1
|
|
8894 00000784 0000 <2> dw 0
|
|
8895 00000786 [6D20] <2> dw %2
|
|
8896 <1> keyword serial, pc_serial
|
|
8897 00000788 4CA868E0 <2> dd hash_%1
|
|
8898 0000078C 0000 <2> dw 0
|
|
8899 0000078E [701F] <2> dw %2
|
|
8900 <1> keyword console, pc_setint16, DisplayCon
|
|
8901 00000790 FD31D818 <2> dd hash_%1
|
|
8902 00000794 [BE00] <2> dw %3
|
|
8903 00000796 [531F] <2> dw %2
|
|
8904 <1> keyword timeout, pc_timeout
|
|
8905 00000798 C932E3D4 <2> dd hash_%1
|
|
8906 0000079C 0000 <2> dw 0
|
|
8907 0000079E [421F] <2> dw %2
|
|
8908 <1> keyword ontimeout, pc_ontimeout
|
|
8909 000007A0 B95EE3D4 <2> dd hash_%1
|
|
8910 000007A4 0000 <2> dw 0
|
|
8911 000007A6 [B11E] <2> dw %2
|
|
8912 <1> keyword onerror, pc_onerror
|
|
8913 000007A8 89C5681A <2> dd hash_%1
|
|
8914 000007AC 0000 <2> dw 0
|
|
8915 000007AE [C01E] <2> dw %2
|
|
8916 <1> keyword allowoptions, pc_setint16, AllowOptions
|
|
8917 000007B0 10DD4816 <2> dd hash_%1
|
|
8918 000007B4 [F400] <2> dw %3
|
|
8919 000007B6 [531F] <2> dw %2
|
|
8920 <1> keyword noescape, pc_noescape
|
|
8921 000007B8 0E09000D <2> dd hash_%1
|
|
8922 000007BC 0000 <2> dw 0
|
|
8923 000007BE [7620] <2> dw %2
|
|
8924 <1> keyword f1, pc_fkey, FKeyName+(0<<FILENAME_MAX_LG2)
|
|
8925 000007C0 F10C0000 <2> dd hash_%1
|
|
8926 000007C4 [DC16] <2> dw %3
|
|
8927 000007C6 [2720] <2> dw %2
|
|
8928 <1> keyword f2, pc_fkey, FKeyName+(1<<FILENAME_MAX_LG2)
|
|
8929 000007C8 F20C0000 <2> dd hash_%1
|
|
8930 000007CC [5C17] <2> dw %3
|
|
8931 000007CE [2720] <2> dw %2
|
|
8932 <1> keyword f3, pc_fkey, FKeyName+(2<<FILENAME_MAX_LG2)
|
|
8933 000007D0 F30C0000 <2> dd hash_%1
|
|
8934 000007D4 [DC17] <2> dw %3
|
|
8935 000007D6 [2720] <2> dw %2
|
|
8936 <1> keyword f4, pc_fkey, FKeyName+(3<<FILENAME_MAX_LG2)
|
|
8937 000007D8 F40C0000 <2> dd hash_%1
|
|
8938 000007DC [5C18] <2> dw %3
|
|
8939 000007DE [2720] <2> dw %2
|
|
8940 <1> keyword f5, pc_fkey, FKeyName+(4<<FILENAME_MAX_LG2)
|
|
8941 000007E0 F50C0000 <2> dd hash_%1
|
|
8942 000007E4 [DC18] <2> dw %3
|
|
8943 000007E6 [2720] <2> dw %2
|
|
8944 <1> keyword f6, pc_fkey, FKeyName+(5<<FILENAME_MAX_LG2)
|
|
8945 000007E8 F60C0000 <2> dd hash_%1
|
|
8946 000007EC [5C19] <2> dw %3
|
|
8947 000007EE [2720] <2> dw %2
|
|
8948 <1> keyword f7, pc_fkey, FKeyName+(6<<FILENAME_MAX_LG2)
|
|
8949 000007F0 F70C0000 <2> dd hash_%1
|
|
8950 000007F4 [DC19] <2> dw %3
|
|
8951 000007F6 [2720] <2> dw %2
|
|
8952 <1> keyword f8, pc_fkey, FKeyName+(7<<FILENAME_MAX_LG2)
|
|
8953 000007F8 F80C0000 <2> dd hash_%1
|
|
8954 000007FC [5C1A] <2> dw %3
|
|
8955 000007FE [2720] <2> dw %2
|
|
8956 <1> keyword f9, pc_fkey, FKeyName+(8<<FILENAME_MAX_LG2)
|
|
8957 00000800 F90C0000 <2> dd hash_%1
|
|
8958 00000804 [DC1A] <2> dw %3
|
|
8959 00000806 [2720] <2> dw %2
|
|
8960 <1> keyword f10, pc_fkey, FKeyName+(9<<FILENAME_MAX_LG2)
|
|
8961 00000808 109E0100 <2> dd hash_%1
|
|
8962 0000080C [5C1B] <2> dw %3
|
|
8963 0000080E [2720] <2> dw %2
|
|
8964 <1> keyword f0, pc_fkey, FKeyName+(9<<FILENAME_MAX_LG2)
|
|
8965 00000810 F00C0000 <2> dd hash_%1
|
|
8966 00000814 [5C1B] <2> dw %3
|
|
8967 00000816 [2720] <2> dw %2
|
|
8968 <1> %if IS_PXELINUX
|
|
8969 <1> keyword ipappend, pc_ipappend
|
|
8970 00000818 F09A39C5 <2> dd hash_%1
|
|
8971 0000081C 0000 <2> dw 0
|
|
8972 0000081E [021F] <2> dw %2
|
|
8973 <1> %endif
|
|
8974 <1> %if IS_PXELINUX || IS_ISOLINUX
|
|
8975 <1> keyword localboot, pc_localboot
|
|
8976 00000820 F4DEF004 <2> dd hash_%1
|
|
8977 00000824 0000 <2> dw 0
|
|
8978 00000826 [181F] <2> dw %2
|
|
8979 <1> %endif
|
|
8980 <1>
|
|
8981 <1> keywd_count equ ($-keywd_table)/keywd_size
|
|
8982 <1>
|
|
8983
|
|
8984 ;
|
|
8985 ; Extensions to search for (in *forward* order).
|
|
8986 ; (.bs and .bss are disabled for PXELINUX, since they are not supported)
|
|
8987 ;
|
|
8988 align 4, db 0
|
|
8989 00000828 2E636274 exten_table: db '.cbt' ; COMBOOT (specific)
|
|
8990 0000082C 2E300000 db '.0', 0, 0 ; PXE bootstrap program
|
|
8991 00000830 2E636F6D db '.com' ; COMBOOT (same as DOS)
|
|
8992 00000834 2E633332 db '.c32' ; COM32
|
|
8993 exten_table_end:
|
|
8994 00000838 0000000000000000 dd 0, 0 ; Need 8 null bytes here
|
|
8995
|
|
8996 ;
|
|
8997 ; PXE unload sequences
|
|
8998 ;
|
|
8999 new_api_unload:
|
|
9000 00000840 31 db PXENV_UDP_CLOSE
|
|
9001 00000841 05 db PXENV_UNDI_SHUTDOWN
|
|
9002 00000842 70 db PXENV_UNLOAD_STACK
|
|
9003 00000843 15 db PXENV_STOP_UNDI
|
|
9004 00000844 00 db 0
|
|
9005 old_api_unload:
|
|
9006 00000845 31 db PXENV_UDP_CLOSE
|
|
9007 00000846 05 db PXENV_UNDI_SHUTDOWN
|
|
9008 00000847 70 db PXENV_UNLOAD_STACK
|
|
9009 00000848 02 db PXENV_UNDI_CLEANUP
|
|
9010 00000849 00 db 0
|
|
9011
|
|
9012 ;
|
|
9013 ; PXE query packets partially filled in
|
|
9014 ;
|
|
9015 pxe_bootp_query_pkt_2:
|
|
9016 0000084A 0000 .status: dw 0 ; Status
|
|
9017 0000084C 0200 .packettype: dw 2 ; DHCPACK packet
|
|
9018 0000084E 0020 .buffersize: dw trackbufsize ; Packet size
|
|
9019 00000850 [0000]0000 .buffer: dw trackbuf, 0 ; seg:off of buffer
|
|
9020 00000854 0020 .bufferlimit: dw trackbufsize ; Unused
|
|
9021
|
|
9022 pxe_bootp_query_pkt_3:
|
|
9023 00000856 0000 .status: dw 0 ; Status
|
|
9024 00000858 0300 .packettype: dw 3 ; Boot server packet
|
|
9025 0000085A 0020 .buffersize: dw trackbufsize ; Packet size
|
|
9026 0000085C [0000]0000 .buffer: dw trackbuf, 0 ; seg:off of buffer
|
|
9027 00000860 0020 .bufferlimit: dw trackbufsize ; Unused
|
|
9028
|
|
9029 pxe_bootp_size_query_pkt:
|
|
9030 00000862 0000 .status: dw 0 ; Status
|
|
9031 00000864 0200 .packettype: dw 2 ; DHCPACK packet
|
|
9032 00000866 0000 .buffersize: dw 0 ; Packet size
|
|
9033 00000868 00000000 .buffer: dw 0, 0 ; seg:off of buffer
|
|
9034 0000086C 0000 .bufferlimit: dw 0 ; Unused
|
|
9035
|
|
9036 pxe_udp_open_pkt:
|
|
9037 0000086E 0000 .status: dw 0 ; Status
|
|
9038 00000870 00000000 .sip: dd 0 ; Source (our) IP
|
|
9039
|
|
9040 pxe_udp_close_pkt:
|
|
9041 00000874 0000 .status: dw 0 ; Status
|
|
9042
|
|
9043 pxe_udp_write_pkt:
|
|
9044 00000876 0000 .status: dw 0 ; Status
|
|
9045 00000878 00000000 .sip: dd 0 ; Server IP
|
|
9046 0000087C 00000000 .gip: dd 0 ; Gateway IP
|
|
9047 00000880 0000 .lport: dw 0 ; Local port
|
|
9048 00000882 0000 .rport: dw 0 ; Remote port
|
|
9049 00000884 0000 .buffersize: dw 0 ; Size of packet
|
|
9050 00000886 00000000 .buffer: dw 0, 0 ; seg:off of buffer
|
|
9051
|
|
9052 pxe_udp_read_pkt:
|
|
9053 0000088A 0000 .status: dw 0 ; Status
|
|
9054 0000088C 00000000 .sip: dd 0 ; Source IP
|
|
9055 00000890 00000000 .dip: dd 0 ; Destination (our) IP
|
|
9056 00000894 0000 .rport: dw 0 ; Remote port
|
|
9057 00000896 0000 .lport: dw 0 ; Local port
|
|
9058 00000898 0000 .buffersize: dw 0 ; Max packet size
|
|
9059 0000089A 00000000 .buffer: dw 0, 0 ; seg:off of buffer
|
|
9060
|
|
9061 ;
|
|
9062 ; Misc initialized (data) variables
|
|
9063 ;
|
|
9064 0000089E 00<rept> alignb 4, db 0
|
|
9065 000008A0 [00000000] BaseStack dd StackBuf ; SS:ESP of base stack
|
|
9066 000008A4 00C0 NextSocket dw 49152 ; Counter for allocating socket numbers
|
|
9067 000008A6 00 KeepPXE db 0 ; Should PXE be kept around?
|
|
9068
|
|
9069 ;
|
|
9070 ; TFTP commands
|
|
9071 ;
|
|
9072 000008A7 6F6374657400 tftp_tail db 'octet', 0 ; Octet mode
|
|
9073 000008AD 7473697A6500 tsize_str db 'tsize' ,0 ; Request size
|
|
9074 tsize_len equ ($-tsize_str)
|
|
9075 000008B3 3000 db '0', 0
|
|
9076 000008B5 626C6B73697A6500 blksize_str db 'blksize', 0 ; Request large blocks
|
|
9077 blksize_len equ ($-blksize_str)
|
|
9078 000008BD 31343430 asciidec TFTP_LARGEBLK
|
|
9079 000008C1 00 db 0
|
|
9080 tftp_tail_len equ ($-tftp_tail)
|
|
9081
|
|
9082 alignb 2, db 0
|
|
9083 ;
|
|
9084 ; Options negotiation parsing table (string pointer, string len, offset
|
|
9085 ; into socket structure)
|
|
9086 ;
|
|
9087 tftp_opt_table:
|
|
9088 000008C2 [AD08]06000C00 dw tsize_str, tsize_len, tftp_filesize
|
|
9089 000008C8 [B508]08001000 dw blksize_str, blksize_len, tftp_blksize
|
|
9090 tftp_opts equ ($-tftp_opt_table)/6
|
|
9091
|
|
9092 ;
|
|
9093 ; Error packet to return on options negotiation error
|
|
9094 ;
|
|
9095 000008CE 0005 tftp_opt_err dw TFTP_ERROR ; ERROR packet
|
|
9096 000008D0 0008 dw TFTP_EOPTNEG ; ERROR 8: bad options
|
|
9097 000008D2 7473697A65206F7074- db 'tsize option required', 0 ; Error message
|
|
9098 000008DB 696F6E207265717569-
|
|
9099 000008E4 72656400
|
|
9100 tftp_opt_err_len equ ($-tftp_opt_err)
|
|
9101
|
|
9102 alignb 4, db 0
|
|
9103 000008E8 00040000 ack_packet_buf: dw TFTP_ACK, 0 ; TFTP ACK packet
|
|
9104
|
|
9105 ;
|
|
9106 ; IP information (initialized to "unknown" values)
|
|
9107 000008EC 00000000 MyIP dd 0 ; My IP address
|
|
9108 000008F0 00000000 ServerIP dd 0 ; IP address of boot server
|
|
9109 000008F4 00000000 Netmask dd 0 ; Netmask of this subnet
|
|
9110 000008F8 00000000 Gateway dd 0 ; Default router
|
|
9111 000008FC 0045 ServerPort dw TFTP_PORT ; TFTP server port
|
|
9112
|
|
9113 ;
|
|
9114 ; Variables that are uninitialized in SYSLINUX but initialized here
|
|
9115 ;
|
|
9116 000008FE 00<rept> alignb 4, db 0
|
|
9117 00000900 1000 BufSafe dw trackbufsize/TFTP_BLOCKSIZE ; Clusters we can load into trackbuf
|
|
9118 00000902 1000 BufSafeSec dw trackbufsize/512 ; = how many sectors?
|
|
9119 00000904 0020 BufSafeBytes dw trackbufsize ; = how many bytes?
|
|
9120 00000906 [0040] EndOfGetCBuf dw getcbuf+trackbufsize ; = getcbuf+BufSafeBytes
|
|
9121 %ifndef DEPEND
|
|
9122 %if ( trackbufsize % TFTP_BLOCKSIZE ) != 0
|
|
9123 %error trackbufsize must be a multiple of TFTP_BLOCKSIZE
|
|
9124 %endif
|
|
9125 %endif
|
|
9126 00000908 00 IPAppend db 0 ; Default IPAPPEND option
|
|
9127 00000909 00 DHCPMagic db 0 ; DHCP site-specific option info
|