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 <1> resb 20h-($-$$) ; org 20h 211 00000020 <1> kern_cmd_magic resw 1 ; 0020 Magic # for command line 212 00000022 <1> kern_cmd_offset resw 1 ; 0022 Offset for kernel command line 213 00000024 <1> resb 497-($-$$) ; org 497d 214 000001F1 <1> bs_setupsecs resb 1 ; 01F1 Sectors for setup code (0 -> 4) 215 000001F2 <1> bs_rootflags resw 1 ; 01F2 Root readonly flag 216 000001F4 <1> bs_syssize resw 1 ; 01F4 217 000001F6 <1> bs_swapdev resw 1 ; 01F6 Swap device (obsolete) 218 000001F8 <1> bs_ramsize resw 1 ; 01F8 Ramdisk flags, formerly ramdisk size 219 000001FA <1> bs_vidmode resw 1 ; 01FA Video mode 220 000001FC <1> bs_rootdev resw 1 ; 01FC Root device 221 000001FE <1> bs_bootsign resw 1 ; 01FE Boot sector signature (0AA55h) 222 00000200 <1> su_jump resb 1 ; 0200 0EBh 223 00000201 <1> su_jump2 resb 1 ; 0201 Size of following header 224 00000202 <1> su_header resd 1 ; 0202 New setup code: header 225 00000206 <1> su_version resw 1 ; 0206 See linux/arch/i386/boot/setup.S 226 00000208 <1> su_switch resw 1 ; 0208 227 0000020A <1> su_setupseg resw 1 ; 020A 228 0000020C <1> su_startsys resw 1 ; 020C 229 0000020E <1> su_kver resw 1 ; 020E Kernel version pointer 230 00000210 <1> su_loader resb 1 ; 0210 Loader ID 231 00000211 <1> su_loadflags resb 1 ; 0211 Load high flag 232 00000212 <1> su_movesize resw 1 ; 0212 233 00000214 <1> su_code32start resd 1 ; 0214 Start of code loaded high 234 00000218 <1> su_ramdiskat resd 1 ; 0218 Start of initial ramdisk 235 0000021C <1> su_ramdisklen resd 1 ; 021C Length of initial ramdisk 236 00000220 <1> su_bsklugeoffs resw 1 ; 0220 237 00000222 <1> su_bsklugeseg resw 1 ; 0222 238 00000224 <1> su_heapend resw 1 ; 0224 239 00000226 <1> su_pad1 resw 1 ; 0226 240 00000228 <1> su_cmd_line_ptr resd 1 ; 0228 241 0000022C <1> su_ramdisk_max resd 1 ; 022C 242 00000230 <1> resb (9000h-12)-($-$$) ; Were bootsect.S puts it... 243 <1> linux_stack equ $ ; 8FF4 244 <1> linux_fdctab equ $ 245 00008FF4 <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 <1> fdctab1 resw 1 300 0000007A <1> fdctab2 resw 1 301 <1> absolute 0400h 302 00000400 <1> serial_base resw 4 ; Base addresses for 4 serial ports 303 <1> absolute 0413h 304 00000413 <1> BIOS_fbm resw 1 ; Free Base Memory (kilobytes) 305 <1> absolute 0462h 306 00000462 <1> BIOS_page resb 1 ; Current video page 307 <1> absolute 046Ch 308 0000046C <1> BIOS_timer resw 1 ; Timer ticks 309 <1> absolute 0472h 310 00000472 <1> BIOS_magic resw 1 ; BIOS reset magic 311 <1> absolute 0484h 312 00000484 <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 vk_vname: resb FILENAME_MAX ; Virtual name **MUST BE FIRST!** 631 00000080 vk_rname: resb FILENAME_MAX ; Real name 632 00000100 vk_ipappend: resb 1 ; "IPAPPEND" flag 633 00000101 resb 1 ; Pad 634 00000102 vk_appendlen: resw 1 635 alignb 4 636 00000104 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 .opcode resb 1 ; BOOTP/DHCP "opcode" 657 00000001 .hardware resb 1 ; ARP hardware type 658 00000002 .hardlen resb 1 ; Hardware address length 659 00000003 .gatehops resb 1 ; Used by forwarders 660 00000004 .ident resd 1 ; Transaction ID 661 00000008 .seconds resw 1 ; Seconds elapsed 662 0000000A .flags resw 1 ; Broadcast flags 663 0000000C .cip resd 1 ; Client IP 664 00000010 .yip resd 1 ; "Your" IP 665 00000014 .sip resd 1 ; Next server IP 666 00000018 .gip resd 1 ; Relay agent IP 667 0000001C .macaddr resb 16 ; Client MAC address 668 0000002C .sname resb 64 ; Server name (optional) 669 0000006C .bootfile resb 128 ; Boot file name 670 000000EC .option_magic resd 1 ; Vendor option magic cookie 671 000000F0 .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 tftp_localport resw 1 ; Local port number (0 = not in use) 684 00000002 tftp_remoteport resw 1 ; Remote port number 685 00000004 tftp_remoteip resd 1 ; Remote IP address 686 00000008 tftp_filepos resd 1 ; Bytes downloaded (including buffer) 687 0000000C tftp_filesize resd 1 ; Total file size(*) 688 00000010 tftp_blksize resd 1 ; Block size for this connection(*) 689 00000014 tftp_bytesleft resw 1 ; Unclaimed data bytes 690 00000016 tftp_lastpkt resw 1 ; Sequence number of last packet (NBO) 691 00000018 tftp_dataptr resw 1 ; Pointer to available data 692 0000001A resw 2 ; Currently unusued 693 ; At end since it should not be zeroed on socked close 694 0000001E 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 trackbuf resb trackbufsize ; Track buffer goes here 712 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 Files resb MAX_OPEN*open_file_t_size 721 722 alignb FILENAME_MAX 723 00004400 BootFile resb 256 ; Boot file from DHCP packet 724 00004500 ConfigServer resd 1 ; Null prefix for mangled config name 725 00004504 ConfigName resb 256-4 ; Configuration file from DHCP option 726 00004600 PathPrefix resb 256 ; Path prefix derived from boot file 727 00004700 DotQuadBuf resb 16 ; Buffer for dotted-quad IP address 728 00004710 IPOption resb 80 ; ip= option buffer 729 00004760 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 RBFG_brainfuck resb 0E00h 736 737 section .bss 738 alignb 4 739 00000000 RebootTime resd 1 ; Reboot timeout, if set by option 740 00000004 StrucPtr resd 1 ; Pointer to PXENV+ or !PXE structure 741 00000008 APIVer resw 1 ; PXE API version found 742 0000000A IPOptionLen resw 1 ; Length of IPOption 743 0000000C IdleTimer resw 1 ; Time to check for ARP? 744 0000000E LocalBootType resw 1 ; Local boot return code 745 00000010 PktTimeout resw 1 ; Timeout for current packet 746 00000012 RealBaseMem resw 1 ; Amount of DOS memory after freeing 747 00000014 OverLoad resb 1 ; Set if DHCP packet uses "overloading" 748 749 ; The relative position of these fields matter! 750 00000015 MACLen resb 1 ; MAC address len 751 00000016 MACType resb 1 ; MAC address type 752 00000017 MAC resb 16 ; Actual MAC address 753 00000027 BOOTIFStr resb 7 ; Space for "BOOTIF=" 754 0000002E MACStr resb 3*17 ; MAC address as a string 755 756 ; 757 ; PXE packets which don't need static initialization 758 ; 759 00000061 - alignb 4 760 00000061 761 pxe_unload_stack_pkt: 762 00000064 .status: resw 1 ; Status 763 00000066 .reserved: resw 10 ; Reserved 764 pxe_unload_stack_pkt_len equ $-pxe_unload_stack_pkt 765 766 0000007A - alignb 16 767 0000007A 768 ; BOOTP/DHCP packet buffer 769 770 alignb 16 771 00000080 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 ; 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 ; == 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 ; 1626 00000550 742B <1> je set_func_flag 1627 00000552 3C15 <1> cmp al,'U' & 1Fh ; 1628 00000554 741B <1> je kill_command ; Kill input line 1629 00000556 3C16 <1> cmp al,'V' & 1Fh ; 1630 00000558 7459 <1> je print_version 1631 0000055A 3C18 <1> cmp al,'X' & 1Fh ; 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 ; 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 ; 1902 000006F9 57 <1> push di ; 1903 000006FA 51 <1> push cx ; 1904 000006FB 51 <1> push cx ; 1905 000006FC 57 <1> push di ; 1906 000006FD F3A6 <1> repe cmpsb 1907 000006FF 5F <1> pop di ; di == command_line 1908 00000700 5B <1> pop bx ; 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 ; cx == [OnerrorLen] 1920 00000717 5F <1> pop di ; di == command_line 1921 00000718 5E <1> pop si ; 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 <1> KernelExtPtr resw 1 ; During search, final null pointer 2011 00000882 <1> CmdOptPtr resw 1 ; Pointer to first option on cmd line 2012 00000884 <1> KbdFlags resb 1 ; Check for keyboard escapes 2013 00000885 <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= 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 - <1> alignb 4 2694 00000886 <1> 2695 00000888 <1> RamdiskMax resd 1 ; Highest address for ramdisk 2696 0000088C <1> KernelSize resd 1 ; Size of kernel in bytes 2697 00000890 <1> KernelSects resd 1 ; Size of kernel in sectors 2698 00000894 <1> KernelEnd resd 1 ; Ending address of the kernel image 2699 00000898 <1> CmdLineLen resw 1 ; Length of command line including null 2700 0000089A <1> SetupSecs resw 1 ; Number of setup sectors 2701 0000089C <1> InitRDPtr resw 1 ; Pointer to initrd= option in command line 2702 0000089E <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 :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 . 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, 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 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 <1> alignb 4 3778 000008A0 <1> PMESP resd 1 ; Protected-mode ESP 3779 000008A4 <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 or 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 ; 4022 00001197 7404 je ac_kill 4023 00001199 3C03 cmp al,3 ; 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 ; 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 ; Timeout 4828 00001647 52 push dx ; 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 ; 4845 0000167B E829FF call pxenv 4846 0000167E 5E pop si ; 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 ; Old time 4853 00001688 59 pop cx ; 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 ; 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 ; 4864 0000169A 59 pop cx ; 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 ; 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=::: 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 - <1> alignb 4 5681 000008A6 <1> 5682 000008A8 <1> NumBuf resb 15 ; Buffer to load number 5683 000008B7 <1> NumBufEnd resb 1 ; Last byte in NumBuf 5684 000008B8 <1> FBytes resd 1 ; Number of bytes left in getc file 5685 000008BC <1> FSectors resd 1 ; Number of sectors in getc file 5686 000008C0 <1> FNextClust resw 1 ; Pointer to next cluster in d:o 5687 000008C2 <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 5853 00001C48 745A <1> je msg_ignore 5854 00001C4A 3C0A <1> cmp al,0Ah ; = newline 5855 00001C4C 7466 <1> je msg_newline 5856 00001C4E 3C0C <1> cmp al,0Ch ; = clear screen 5857 00001C50 0F849500 <1> je msg_formfeed 5858 00001C54 3C07 <1> cmp al,07h ; = beep 5859 00001C56 744D <1> je msg_beep 5860 00001C58 3C19 <1> cmp al,19h ; = return to text mode 5861 00001C5A 0F840601 <1> je msg_novga 5862 00001C5E 3C18 <1> cmp al,18h ; = 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 ; = 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 <1> NextCharJump resw 1 ; Routine to interpret next print char 6153 <1> CursorDX equ $ 6154 000008C6 <1> CursorCol resb 1 ; Cursor column for message file 6155 000008C7 <1> CursorRow resb 1 ; Cursor row for message file 6156 <1> ScreenSize equ $ 6157 000008C8 <1> VidCols resb 1 ; Columns on screen-1 6158 000008C9 <1> VidRows resb 1 ; Rows on screen-1 6159 <1> 6160 <1> ; Serial console stuff... 6161 000008CA <1> BaudDivisor resw 1 ; Baud rate divisor 6162 <1> FlowControl equ $ 6163 000008CC <1> FlowOutput resb 1 ; Outputs to assert for serial flow 6164 000008CD <1> FlowInput resb 1 ; Input bits for serial flow 6165 000008CE <1> FlowIgnore resb 1 ; Ignore input unless these bits set 6166 <1> 6167 000008CF <1> TextAttribute resb 1 ; Text attribute for message file 6168 000008D0 <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 - <1> alignb 4 ; For the good of REP MOVSD 6648 000008D1 <1> 6649 000008D4 <1> command_line resb max_cmd_len+2 ; Command line buffer 6650 00000AD5 - <1> alignb 4 6651 00000AD5 <1> 6652 00000AD8 <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 <1> VKernelBuf: resb vk_size ; "Current" vkernel 6884 00000FDC <1> AppendBuf resb max_cmd_len+1 ; append= 6885 000011DC <1> Ontimeout resb max_cmd_len+1 ; ontimeout 6886 000013DC <1> Onerror resb max_cmd_len+1 ; onerror 6887 000015DC <1> KbdMap resb 256 ; Keyboard map 6888 000016DC <1> FKeyName resb 10*FILENAME_MAX ; File names for F-key help 6889 00001BDC <1> KernelCNameLen resw 1 ; Length of unmangled kernel name 6890 00001BDE <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 <1> KernelName resb FILENAME_MAX ; Mangled name for kernel 6897 00001C60 <1> KernelCName resb FILENAME_MAX ; Unmangled kernel name 6898 00001CE0 <1> InitRDCName resb FILENAME_MAX ; Unmangled initrd name 6899 <1> %endif 6900 00001D60 <1> MNameBuf resb FILENAME_MAX 6901 00001DE0 <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 <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 <1> EntryPoint resd 1 ; CS:IP for shuffle_and_boot 7360 00005568 <1> SavedSSSP resd 1 ; Saved real mode SS:SP 7361 0000556C <1> A20Test resw 1 ; Counter for testing status of A20 7362 0000556E <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 ; 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 ; 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 ; 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 ; Target buffer 7433 000021F7 6659 <1> pop ecx ; Byte count this round 7434 000021F9 6651 <1> push ecx ; Byte count this round 7435 000021FB 6657 <1> push edi ; 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 ; 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 ; File handle/cluster pointer 7449 00002217 665F <1> pop edi ; Target buffer 7450 00002219 6659 <1> pop ecx ; Byte count this round 7451 0000221B 6658 <1> pop eax ; 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 <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 <1> GraphXSize resw 1 ; Width of splash screen file 7919 00001E62 <1> VGAPos resw 1 ; Pointer into VGA memory 7920 00001E64 <1> VGACluster resw 1 ; Cluster pointer for VGA image file 7921 00001E66 <1> VGAFilePtr resw 1 ; Pointer into VGAFileBuf 7922 00001E68 <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 <1> VGAFileBuf resb FILENAME_MAX ; Unmangled VGA image name 7927 <1> %endif 7928 <1> VGAFileBufEnd equ $ 7929 00001EF9 <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 - <1> alignb 4 8074 00001F79 <1> 8075 00001F7C <1> E820Buf resd 5 ; INT 15:E820 data buffer 8076 00001F90 <1> E820Mem resd 1 ; Memory detected by E820 8077 00001F94 <1> E820Max resd 1 ; Is E820 memory capped? 8078 00001F98 <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 <1> .id: resw 1 8298 00000002 <1> .flags: resw 1 8299 00000004 <1> .qdcount: resw 1 8300 00000006 <1> .ancount: resw 1 8301 00000008 <1> .nscount: resw 1 8302 0000000A <1> .arcount: resw 1 8303 <1> endstruc 8304 <1> 8305 <1> ; DNS query 8306 <1> struc dnsquery 8307 00000000 <1> .qtype: resw 1 8308 00000002 <1> .qclass: resw 1 8309 <1> endstruc 8310 <1> 8311 <1> ; DNS RR 8312 <1> struc dnsrr 8313 00000000 <1> .type: resw 1 8314 00000002 <1> .class: resw 1 8315 00000004 <1> .ttl: resd 1 8316 00000008 <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 <1> DNSSendBuf resb DNS_MAX_PACKET 8323 0000219C <1> DNSRecvBuf resb DNS_MAX_PACKET 8324 0000239C <1> LocalDomain resb 256 ; Max possible length 8325 0000249C <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 <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< dd hash_%1 8926 000007C4 [DC16] <2> dw %3 8927 000007C6 [2720] <2> dw %2 8928 <1> keyword f2, pc_fkey, FKeyName+(1< dd hash_%1 8930 000007CC [5C17] <2> dw %3 8931 000007CE [2720] <2> dw %2 8932 <1> keyword f3, pc_fkey, FKeyName+(2< dd hash_%1 8934 000007D4 [DC17] <2> dw %3 8935 000007D6 [2720] <2> dw %2 8936 <1> keyword f4, pc_fkey, FKeyName+(3< dd hash_%1 8938 000007DC [5C18] <2> dw %3 8939 000007DE [2720] <2> dw %2 8940 <1> keyword f5, pc_fkey, FKeyName+(4< dd hash_%1 8942 000007E4 [DC18] <2> dw %3 8943 000007E6 [2720] <2> dw %2 8944 <1> keyword f6, pc_fkey, FKeyName+(5< dd hash_%1 8946 000007EC [5C19] <2> dw %3 8947 000007EE [2720] <2> dw %2 8948 <1> keyword f7, pc_fkey, FKeyName+(6< dd hash_%1 8950 000007F4 [DC19] <2> dw %3 8951 000007F6 [2720] <2> dw %2 8952 <1> keyword f8, pc_fkey, FKeyName+(7< dd hash_%1 8954 000007FC [5C1A] <2> dw %3 8955 000007FE [2720] <2> dw %2 8956 <1> keyword f9, pc_fkey, FKeyName+(8< dd hash_%1 8958 00000804 [DC1A] <2> dw %3 8959 00000806 [2720] <2> dw %2 8960 <1> keyword f10, pc_fkey, FKeyName+(9< dd hash_%1 8962 0000080C [5C1B] <2> dw %3 8963 0000080E [2720] <2> dw %2 8964 <1> keyword f0, pc_fkey, FKeyName+(9< 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 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 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