     1                                  ; -*- fundamental -*- (asm-mode sucks)
     2                                  ; $Id: ldlinux.asm,v 1.129 2002/10/25 06:47:20 hpa Exp $
     3                                  ; ****************************************************************************
     4                                  ;
     5                                  ;  ldlinux.asm
     6                                  ;
     7                                  ;  A program to boot Linux kernels off an MS-DOS formatted floppy disk.	 This
     8                                  ;  functionality is good to have for installation floppies, where it may
     9                                  ;  be hard to find a functional Linux system to run LILO off.
    10                                  ;
    11                                  ;  This program allows manipulation of the disk to take place entirely
    12                                  ;  from MS-LOSS, and can be especially useful in conjunction with the
    13                                  ;  umsdos filesystem.
    14                                  ;
    15                                  ;  This file is loaded in stages; first the boot sector at offset 7C00h,
    16                                  ;  then the first sector (cluster, really, but we can only assume 1 sector)
    17                                  ;  of LDLINUX.SYS at 7E00h and finally the remainder of LDLINUX.SYS at 8000h.
    18                                  ;
    19                                  ;   Copyright (C) 1994-2002  H. Peter Anvin
    20                                  ;
    21                                  ;  This program is free software; you can redistribute it and/or modify
    22                                  ;  it under the terms of the GNU General Public License as published by
    23                                  ;  the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
    24                                  ;  USA; either version 2 of the License, or (at your option) any later
    25                                  ;  version; incorporated herein by reference.
    26                                  ; 
    27                                  ; ****************************************************************************
    28                                  
    29                                  %define IS_SYSLINUX 1
    30                                  %include "macros.inc"
    31                              <1> ;; $Id: macros.inc,v 1.3 2002/06/02 05:12:25 hpa Exp $
    32                              <1> ;; -----------------------------------------------------------------------
    33                              <1> ;;   
    34                              <1> ;;   Copyright 1994-2002 H. Peter Anvin - All Rights Reserved
    35                              <1> ;;
    36                              <1> ;;   This program is free software; you can redistribute it and/or modify
    37                              <1> ;;   it under the terms of the GNU General Public License as published by
    38                              <1> ;;   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
    39                              <1> ;;   Bostom MA 02111-1307, USA; either version 2 of the License, or
    40                              <1> ;;   (at your option) any later version; incorporated herein by reference.
    41                              <1> ;;
    42                              <1> ;; -----------------------------------------------------------------------
    43                              <1> 
    44                              <1> ;;
    45                              <1> ;; macros.inc
    46                              <1> ;; 
    47                              <1> ;; Convenient macros
    48                              <1> ;;
    49                              <1> 
    50                              <1> %ifndef _MACROS_INC
    51                              <1> %define _MACROS_INC
    52                              <1> 
    53                              <1> ;
    54                              <1> ; Identify the module we're compiling; the "correct" should be defined
    55                              <1> ; in the module itself to 1
    56                              <1> ;
    57                              <1> %ifndef IS_SYSLINUX
    58                              <1> %define IS_SYSLINUX 0
    59                              <1> %endif
    60                              <1> %ifndef IS_PXELINUX
    61                              <1> %define IS_PXELINUX 0
    62                              <1> %endif
    63                              <1> %ifndef IS_ISOLINUX
    64                              <1> %define IS_ISOLINUX 0
    65                              <1> %endif
    66                              <1> 
    67                              <1> ;
    68                              <1> ; Macros similar to res[bwd], but which works in the code segment (after
    69                              <1> ; section .text)
    70                              <1> ;
    71                              <1> %macro	zb	1
    72                              <1> 	times %1 db 0
    73                              <1> %endmacro
    74                              <1> 
    75                              <1> %macro	zw	1
    76                              <1> 	times %1 dw 0
    77                              <1> %endmacro
    78                              <1> 
    79                              <1> %macro	zd	1
    80                              <1> 	times %1 dd 0
    81                              <1> %endmacro
    82                              <1> 
    83                              <1> ;
    84                              <1> ; Macros for network byte order of constants
    85                              <1> ;
    86                              <1> %define htons(x)  ( ( ((x) & 0FFh) << 8 ) + ( ((x) & 0FF00h) >> 8 ) )
    87                              <1> %define ntohs(x) htons(x)
    88                              <1> %define htonl(x)  ( ( ((x) & 0FFh) << 24) + ( ((x) & 0FF00h) << 8 ) + ( ((x) & 0FF0000h) >> 8 ) + ( ((x) & 0FF000000h) >> 24) )
    89                              <1> %define ntohl(x) htonl(x)
    90                              <1> 
    91                              <1> %endif ; _MACROS_INC
    92                                  %include "config.inc"
    93                              <1> ;; $Id: config.inc,v 1.2 2002/06/11 05:48:29 hpa Exp $
    94                              <1> ;; -----------------------------------------------------------------------
    95                              <1> ;;   
    96                              <1> ;;   Copyright 2002 H. Peter Anvin - All Rights Reserved
    97                              <1> ;;
    98                              <1> ;;   This program is free software; you can redistribute it and/or modify
    99                              <1> ;;   it under the terms of the GNU General Public License as published by
   100                              <1> ;;   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
   101                              <1> ;;   Bostom MA 02111-1307, USA; either version 2 of the License, or
   102                              <1> ;;   (at your option) any later version; incorporated herein by reference.
   103                              <1> ;;
   104                              <1> ;; -----------------------------------------------------------------------
   105                              <1> 
   106                              <1> ;;
   107                              <1> ;; config.inc
   108                              <1> ;;
   109                              <1> ;; Common configuration options.  Some of these are imposed by the kernel.
   110                              <1> ;;
   111                              <1> 
   112                              <1> %ifndef _CONFIG_INC
   113                              <1> %define _CONFIG_INC
   114                              <1> 
   115                              <1> max_cmd_len	equ 255			; Must be odd; 255 is the kernel limit
   116                              <1> HIGHMEM_MAX	equ 037FFFFFFh		; DEFAULT highest address for an initrd
   117                              <1> DEFAULT_BAUD	equ 9600		; Default baud rate for serial port
   118                              <1> BAUD_DIVISOR	equ 115200		; Serial port parameter
   119                              <1> 
   120                              <1> %assign	DO_WBINVD 0			; Should we use WBINVD or not?
   121                              <1> 
   122                              <1> ;
   123                              <1> ; Version number definitinons
   124                              <1> ;
   125                              <1> %ifndef DEPEND				; Generated file
   126                              <1> %include "version.gen"
   127                              <2> %define VERSION "2.00"
   128                              <2> %define VER_MAJOR 2
   129                              <2> %define VER_MINOR 0
   130                              <1> %endif
   131                              <1> 
   132                              <1> ;
   133                              <1> ; Should be updated with every release to avoid bootsector/SYS file mismatch
   134                              <1> ;
   135                              <1> %define	version_str	VERSION		; Must be 4 characters long!
   136                              <1> %define date		DATE_STR	; Defined from the Makefile
   137                              <1> %define	year		'2002'
   138                              <1> 
   139                              <1> %endif ; _CONFIG_INC
   140                                  %include "kernel.inc"
   141                              <1> ;; $Id: kernel.inc,v 1.1 2002/04/26 05:56:24 hpa Exp $
   142                              <1> ;; -----------------------------------------------------------------------
   143                              <1> ;;   
   144                              <1> ;;   Copyright 1994-2002 H. Peter Anvin - All Rights Reserved
   145                              <1> ;;
   146                              <1> ;;   This program is free software; you can redistribute it and/or modify
   147                              <1> ;;   it under the terms of the GNU General Public License as published by
   148                              <1> ;;   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
   149                              <1> ;;   Bostom MA 02111-1307, USA; either version 2 of the License, or
   150                              <1> ;;   (at your option) any later version; incorporated herein by reference.
   151                              <1> ;;
   152                              <1> ;; -----------------------------------------------------------------------
   153                              <1> 
   154                              <1> ;;
   155                              <1> ;; kernel.inc
   156                              <1> ;; 
   157                              <1> ;; Header file for the kernel interface definitions
   158                              <1> ;;
   159                              <1> 
   160                              <1> %ifndef _KERNEL_INC
   161                              <1> %define _KERNEL_INC
   162                              <1> 
   163                              <1> ;;
   164                              <1> ;; Structure of the real_mode_seg
   165                              <1> ;;
   166                              <1> 
   167                              <1> 		struc real_mode_seg_t
   168 00000000 <res 00000020>      <1> 		resb 20h-($-$$)		; org 20h
   169 00000020 <res 00000002>      <1> kern_cmd_magic	resw 1			; 0020 Magic # for command line
   170 00000022 <res 00000002>      <1> kern_cmd_offset resw 1			; 0022 Offset for kernel command line
   171 00000024 <res 000001CD>      <1> 		resb 497-($-$$)		; org 497d
   172 000001F1 <res 00000001>      <1> bs_setupsecs	resb 1			; 01F1 Sectors for setup code (0 -> 4)
   173 000001F2 <res 00000002>      <1> bs_rootflags	resw 1			; 01F2 Root readonly flag
   174 000001F4 <res 00000002>      <1> bs_syssize	resw 1			; 01F4
   175 000001F6 <res 00000002>      <1> bs_swapdev	resw 1			; 01F6 Swap device (obsolete)
   176 000001F8 <res 00000002>      <1> bs_ramsize	resw 1			; 01F8 Ramdisk flags, formerly ramdisk size
   177 000001FA <res 00000002>      <1> bs_vidmode	resw 1			; 01FA Video mode
   178 000001FC <res 00000002>      <1> bs_rootdev	resw 1			; 01FC Root device
   179 000001FE <res 00000002>      <1> bs_bootsign	resw 1			; 01FE Boot sector signature (0AA55h)
   180 00000200 <res 00000001>      <1> su_jump		resb 1			; 0200 0EBh
   181 00000201 <res 00000001>      <1> su_jump2	resb 1			; 0201 Size of following header
   182 00000202 <res 00000004>      <1> su_header	resd 1			; 0202 New setup code: header
   183 00000206 <res 00000002>      <1> su_version	resw 1			; 0206 See linux/arch/i386/boot/setup.S
   184 00000208 <res 00000002>      <1> su_switch	resw 1			; 0208
   185 0000020A <res 00000002>      <1> su_setupseg	resw 1			; 020A
   186 0000020C <res 00000002>      <1> su_startsys	resw 1			; 020C
   187 0000020E <res 00000002>      <1> su_kver		resw 1			; 020E Kernel version pointer
   188 00000210 <res 00000001>      <1> su_loader	resb 1			; 0210 Loader ID
   189 00000211 <res 00000001>      <1> su_loadflags	resb 1			; 0211 Load high flag
   190 00000212 <res 00000002>      <1> su_movesize	resw 1			; 0212
   191 00000214 <res 00000004>      <1> su_code32start	resd 1			; 0214 Start of code loaded high
   192 00000218 <res 00000004>      <1> su_ramdiskat	resd 1			; 0218 Start of initial ramdisk
   193                              <1> su_ramdisklen	equ $			; Length of initial ramdisk
   194 0000021C <res 00000002>      <1> su_ramdisklen1	resw 1			; 021C
   195 0000021E <res 00000002>      <1> su_ramdisklen2	resw 1			; 021E
   196 00000220 <res 00000002>      <1> su_bsklugeoffs	resw 1			; 0220
   197 00000222 <res 00000002>      <1> su_bsklugeseg	resw 1			; 0222
   198 00000224 <res 00000002>      <1> su_heapend	resw 1			; 0224
   199 00000226 <res 00000002>      <1> su_pad1		resw 1			; 0226
   200 00000228 <res 00000004>      <1> su_cmd_line_ptr	resd 1			; 0228
   201 0000022C <res 00000004>      <1> su_ramdisk_max	resd 1			; 022C
   202 00000230 <res 00008DC4>      <1> 		resb (9000h-12)-($-$$)	; Were bootsect.S puts it...
   203                              <1> linux_stack	equ $			; 8FF4
   204                              <1> linux_fdctab	equ $
   205 00008FF4 <res 0000000C>      <1> 		resb 9000h-($-$$)
   206                              <1> cmd_line_here	equ $			; 9000 Should be out of the way
   207                              <1> 		endstruc
   208                              <1> 
   209                              <1> ;
   210                              <1> ; Kernel command line signature
   211                              <1> ;
   212                              <1> CMD_MAGIC	equ 0A33Fh		; Command line magic
   213                              <1> 
   214                              <1> ;
   215                              <1> ; Magic number of su_header field
   216                              <1> ;
   217                              <1> HEADER_ID       equ 'HdrS'		; HdrS (in littleendian hex)
   218                              <1> 
   219                              <1> ;
   220                              <1> ; Flags for the su_loadflags field
   221                              <1> ;
   222                              <1> LOAD_HIGH	equ 01h			; Large kernel, load high
   223                              <1> CAN_USE_HEAP    equ 80h                 ; Boot loader reports heap size
   224                              <1> 
   225                              <1> ;
   226                              <1> ; ID codes for various modules
   227                              <1> ;
   228                              <1> syslinux_id	equ 031h		; 3 = SYSLINUX family; 1 = SYSLINUX
   229                              <1> pxelinux_id	equ 032h		; 3 = SYSLINUX family; 2 = PXELINUX
   230                              <1> isolinux_id	equ 033h		; 3 = SYSLINUX family; 3 = PXELINUX
   231                              <1> 
   232                              <1> %endif ; _KERNEL_INC
   233                                  %include "bios.inc"
   234                              <1> ;; $Id: bios.inc,v 1.1 2002/04/26 05:56:24 hpa Exp $
   235                              <1> ;; -----------------------------------------------------------------------
   236                              <1> ;;   
   237                              <1> ;;   Copyright 1994-2002 H. Peter Anvin - All Rights Reserved
   238                              <1> ;;
   239                              <1> ;;   This program is free software; you can redistribute it and/or modify
   240                              <1> ;;   it under the terms of the GNU General Public License as published by
   241                              <1> ;;   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
   242                              <1> ;;   Bostom MA 02111-1307, USA; either version 2 of the License, or
   243                              <1> ;;   (at your option) any later version; incorporated herein by reference.
   244                              <1> ;;
   245                              <1> ;; -----------------------------------------------------------------------
   246                              <1> 
   247                              <1> ;;
   248                              <1> ;; bios.inc
   249                              <1> ;; 
   250                              <1> ;; Header file for the BIOS data structures etc.
   251                              <1> ;;
   252                              <1> 
   253                              <1> %ifndef _BIOS_INC
   254                              <1> %define _BIOS_INC
   255                              <1> 
   256                              <1> 		absolute 4*1Eh		; In the interrupt table
   257                              <1> fdctab		equ $
   258 00000078 <res 00000002>      <1> fdctab1		resw 1
   259 0000007A <res 00000002>      <1> fdctab2		resw 1
   260                              <1> 		absolute 0400h
   261 00000400 <res 00000008>      <1> serial_base	resw 4			; Base addresses for 4 serial ports
   262                              <1> 		absolute 0413h
   263 00000413 <res 00000002>      <1> BIOS_fbm	resw 1			; Free Base Memory (kilobytes)
   264                              <1> 		absolute 046Ch
   265 0000046C <res 00000002>      <1> BIOS_timer	resw 1			; Timer ticks
   266                              <1> 		absolute 0472h
   267 00000472 <res 00000002>      <1> BIOS_magic	resw 1			; BIOS reset magic
   268                              <1>                 absolute 0484h
   269 00000484 <res 00000001>      <1> BIOS_vidrows    resb 1			; Number of screen rows
   270                              <1> 
   271                              <1> %endif ; _BIOS_INC
   272                                  %include "tracers.inc"
   273                              <1> ;; $Id: tracers.inc,v 1.1 2002/04/26 05:56:25 hpa Exp $
   274                              <1> ;; -----------------------------------------------------------------------
   275                              <1> ;;   
   276                              <1> ;;   Copyright 1994-2002 H. Peter Anvin - All Rights Reserved
   277                              <1> ;;
   278                              <1> ;;   This program is free software; you can redistribute it and/or modify
   279                              <1> ;;   it under the terms of the GNU General Public License as published by
   280                              <1> ;;   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
   281                              <1> ;;   Bostom MA 02111-1307, USA; either version 2 of the License, or
   282                              <1> ;;   (at your option) any later version; incorporated herein by reference.
   283                              <1> ;;
   284                              <1> ;; -----------------------------------------------------------------------
   285                              <1> 
   286                              <1> ;;
   287                              <1> ;; tracers.inc
   288                              <1> ;; 
   289                              <1> ;; Debugging tracers
   290                              <1> ;;
   291                              <1> 
   292                              <1> %ifndef _TRACERS_INC
   293                              <1> %define _TRACERS_INC
   294                              <1> 
   295                              <1> ; Note: The Makefile builds one version with DEBUG_MESSAGES automatically.
   296                              <1> ; %define DEBUG_TRACERS			; Uncomment to get debugging tracers
   297                              <1> ; %define DEBUG_MESSAGES		; Uncomment to get debugging messages
   298                              <1> 
   299                              <1> %ifdef DEBUG_TRACERS
   300                              <1> 
   301                              <1> %macro TRACER	1
   302                              <1> 	call debug_tracer
   303                              <1> 	db %1
   304                              <1> %endmacro
   305                              <1> 
   306                              <1> %else	; DEBUG_TRACERS
   307                              <1> 
   308                              <1> %macro	TRACER	1
   309                              <1> %endmacro
   310                              <1> 
   311                              <1> %endif	; DEBUG_TRACERS
   312                              <1> 
   313                              <1> %endif ; _TRACERS_INC
   314                                  
   315                                  ;
   316                                  ; Some semi-configurable constants... change on your own risk.
   317                                  ;
   318                                  my_id		equ syslinux_id
   319                                  FILENAME_MAX_LG2 equ 4			; log2(Max filename size Including final null)
   320                                  FILENAME_MAX	equ 11			; Max mangled filename size
   321                                  NULLFILE	equ ' '			; First char space == null filename
   322                                  retry_count	equ 6			; How patient are we with the disk?
   323                                  %assign HIGHMEM_SLOP 0			; Avoid this much memory near the top
   324                                  
   325                                  ;
   326                                  ; The following structure is used for "virtual kernels"; i.e. LILO-style
   327                                  ; option labels.  The options we permit here are `kernel' and `append
   328                                  ; Since there is no room in the bottom 64K for all of these, we
   329                                  ; stick them at vk_seg:0000 and copy them down before we need them.
   330                                  ;
   331                                  ; Note: this structure can be added to, but it must 
   332                                  ;
   333                                  %define vk_power	7		; log2(max number of vkernels)
   334                                  %define	max_vk		(1 << vk_power)	; Maximum number of vkernels
   335                                  %define vk_shift	(16-vk_power)	; Number of bits to shift
   336                                  %define vk_size		(1 << vk_shift)	; Size of a vkernel buffer
   337                                  
   338                                  		struc vkernel
   339 00000000 <res 0000000B>          vk_vname:	resb FILENAME_MAX	; Virtual name **MUST BE FIRST!**
   340 0000000B <res 0000000B>          vk_rname:	resb FILENAME_MAX	; Real name
   341 00000016 <res 00000002>          vk_appendlen:	resw 1
   342                                  		alignb 4
   343 00000018 <res 00000100>          vk_append:	resb max_cmd_len+1	; Command line
   344                                  		alignb 4
   345                                  vk_end:		equ $			; Should be <= vk_size
   346                                  		endstruc
   347                                  
   348                                  %ifndef DEPEND
   349                                  %if (vk_end > vk_size) || (vk_size*max_vk > 65536)
   350                                  %error "Too many vkernels defined, reduce vk_power"
   351                                  %endif
   352                                  %endif
   353                                  
   354                                  ;
   355                                  ; Segment assignments in the bottom 640K
   356                                  ; Stick to the low 512K in case we're using something like M-systems flash
   357                                  ; which load a driver into low RAM (evil!!)
   358                                  ;
   359                                  ; 0000h - main code/data segment (and BIOS segment)
   360                                  ;
   361                                  real_mode_seg	equ 7000h
   362                                  fat_seg		equ 5000h		; 128K area for FAT (2x64K)
   363                                  vk_seg          equ 4000h		; Virtual kernels
   364                                  xfer_buf_seg	equ 3000h		; Bounce buffer for I/O to high mem
   365                                  comboot_seg	equ 2000h		; COMBOOT image loading zone
   366                                  
   367                                  ; ---------------------------------------------------------------------------
   368                                  ;   BEGIN CODE
   369                                  ; ---------------------------------------------------------------------------
   370                                  
   371                                  ;
   372                                  ; Memory below this point is reserved for the BIOS and the MBR
   373                                  ;
   374                                   		absolute 1000h
   375                                  trackbuf	equ $			; Track buffer goes here
   376                                  trackbufsize	equ 16384		; Safe size of track buffer
   377                                  ;		trackbuf ends at 5000h
   378                                  
   379                                  
   380                                  ;
   381                                  ; Constants for the xfer_buf_seg
   382                                  ;
   383                                  ; The xfer_buf_seg is also used to store message file buffers.  We
   384                                  ; need two trackbuffers (text and graphics), plus a work buffer
   385                                  ; for the graphics decompressor.
   386                                  ;
   387                                  xbs_textbuf	equ 0			; Also hard-coded, do not change
   388                                  xbs_vgabuf	equ trackbufsize
   389                                  xbs_vgatmpbuf	equ 2*trackbufsize
   390                                  
   391                                  
   392                                                  absolute 5000h          ; Here we keep our BSS stuff
   393 00005000 <res 00000200>          VKernelBuf:	resb vk_size		; "Current" vkernel
   394                                  		alignb 4
   395 00005200 <res 00000100>          AppendBuf       resb max_cmd_len+1	; append=
   396 00005300 <res 00000100>          KbdMap		resb 256		; Keyboard map
   397 00005400 <res 000000A0>          FKeyName	resb 10*16		; File names for F-key help
   398 000054A0 <res 0000000F>          NumBuf		resb 15			; Buffer to load number
   399 000054AF <res 00000001>          NumBufEnd	resb 1			; Last byte in NumBuf
   400                                  		alignb 8
   401                                  
   402                                  		; Expanded superblock
   403                                  SuperInfo	equ $
   404 000054B0 <res 00000080>          		resq 16			; The first 16 bytes expanded 8 times
   405                                  		;
   406                                  		; These need to follow SuperInfo
   407                                  		;
   408 00005530 <res 00000004>          RootDir		resd 1			; Location of root directory
   409 00005534 <res 00000004>          DataArea	resd 1			; Location of data area
   410 00005538 <res 00000002>          RootDirSize	resw 1			; Root dir size in sectors
   411 0000553A <res 00000002>          DirScanCtr	resw 1			; Used while searching directory
   412 0000553C <res 00000002>          EndofDirSec	resw 1			; = trackbuf+bsBytesPerSec-31
   413                                  
   414 0000553E <res 00000001>-         		alignb 4
   415 0000553E <rept>             
   416 00005540 <res 00000014>          E820Buf		resd 5			; INT 15:E820 data buffer
   417 00005554 <res 00000004>          HiLoadAddr      resd 1			; Address pointer for high load loop
   418 00005558 <res 00000004>          HighMemSize	resd 1			; End of memory pointer (bytes)
   419 0000555C <res 00000004>          RamdiskMax	resd 1			; Highest address for a ramdisk
   420 00005560 <res 00000004>          KernelSize	resd 1			; Size of kernel (bytes)
   421 00005564 <res 00000004>          SavedSSSP	resd 1			; Our SS:SP while running a COMBOOT image
   422 00005568 <res 00000004>          PMESP		resd 1			; Protected-mode ESP
   423 0000556C <res 00000004>          ClustPerMoby	resd 1			; Clusters per 64K
   424 00005570 <res 00000004>          ClustSize	resd 1			; Bytes/cluster
   425 00005574 <res 0000000C>          KernelName      resb 12		        ; Mangled name for kernel
   426                                  					; (note the spare byte after!)
   427 00005580 <res 00000004>          OrigKernelExt	resd 1			; Original kernel extension
   428                                  FBytes		equ $			; Used by open/getc
   429 00005584 <res 00000002>          FBytes1		resw 1
   430 00005586 <res 00000002>          FBytes2		resw 1
   431 00005588 <res 00000002>          DirBlocksLeft	resw 1			; Ditto
   432 0000558A <res 00000002>          RunLinClust	resw 1			; Cluster # for LDLINUX.SYS
   433 0000558C <res 00000002>          BufSafe		resw 1			; Clusters we can load into trackbuf
   434 0000558E <res 00000002>          BufSafeSec	resw 1			; = how many sectors?
   435 00005590 <res 00000002>          BufSafeBytes	resw 1			; = how many bytes?
   436 00005592 <res 00000002>          EndOfGetCBuf	resw 1			; = getcbuf+BufSafeBytes
   437 00005594 <res 00000002>          KernelClust	resw 1			; Kernel size in clusters
   438 00005596 <res 00000002>          FClust		resw 1			; Number of clusters in open/getc file
   439 00005598 <res 00000002>          FNextClust	resw 1			; Pointer to next cluster in d:o
   440 0000559A <res 00000002>          FPtr		resw 1			; Pointer to next char in buffer
   441 0000559C <res 00000002>          CmdOptPtr       resw 1			; Pointer to first option on cmd line
   442 0000559E <res 00000002>          KernelCNameLen  resw 1			; Length of unmangled kernel name
   443 000055A0 <res 00000002>          InitRDCNameLen  resw 1			; Length of unmangled initrd name
   444 000055A2 <res 00000002>          NextCharJump    resw 1			; Routine to interpret next print char
   445 000055A4 <res 00000002>          SetupSecs	resw 1			; Number of setup sectors
   446 000055A6 <res 00000002>          A20Test		resw 1			; Counter for testing status of A20
   447 000055A8 <res 00000002>          A20Type		resw 1			; A20 type
   448 000055AA <res 00000002>          CmdLineLen	resw 1			; Length of command line including null
   449 000055AC <res 00000002>          GraphXSize	resw 1			; Width of splash screen file
   450 000055AE <res 00000002>          VGAPos		resw 1			; Pointer into VGA memory
   451 000055B0 <res 00000002>          VGACluster	resw 1			; Cluster pointer for VGA image file
   452 000055B2 <res 00000002>          VGAFilePtr	resw 1			; Pointer into VGAFileBuf
   453                                  TextAttrBX      equ $
   454 000055B4 <res 00000001>          TextAttribute   resb 1			; Text attribute for message file
   455 000055B5 <res 00000001>          TextPage        resb 1			; Active display page
   456                                  CursorDX        equ $
   457 000055B6 <res 00000001>          CursorCol       resb 1			; Cursor column for message file
   458 000055B7 <res 00000001>          CursorRow       resb 1			; Cursor row for message file
   459                                  ScreenSize      equ $
   460 000055B8 <res 00000001>          VidCols         resb 1			; Columns on screen-1
   461 000055B9 <res 00000001>          VidRows         resb 1			; Rows on screen-1
   462 000055BA <res 00000002>          BaudDivisor	resw 1			; Baud rate divisor
   463                                  FlowControl	equ $
   464 000055BC <res 00000001>          FlowOutput	resb 1			; Outputs to assert for serial flow
   465 000055BD <res 00000001>          FlowInput	resb 1			; Input bits for serial flow
   466 000055BE <res 00000001>          FlowIgnore	resb 1			; Ignore input unless these bits set
   467 000055BF <res 00000001>          RetryCount      resb 1			; Used for disk access retries
   468 000055C0 <res 00000001>          KbdFlags	resb 1			; Check for keyboard escapes
   469 000055C1 <res 00000001>          LoadFlags	resb 1			; Loadflags from kernel
   470 000055C2 <res 00000001>          A20Tries	resb 1			; Times until giving up on A20
   471 000055C3 <res 00000001>          FuncFlag	resb 1			; Escape sequences received from keyboard
   472 000055C4 <res 00000001>          DisplayMask	resb 1			; Display modes mask
   473 000055C5 <res 0000000B>          MNameBuf        resb 11            	; Generic mangled file name buffer
   474 000055D0 <res 0000000B>          InitRD          resb 11                 ; initrd= mangled name
   475 000055DB <res 0000000D>          KernelCName     resb 13                 ; Unmangled kernel name
   476 000055E8 <res 0000000D>          InitRDCName     resb 13            	; Unmangled initrd name
   477 000055F5 <res 00000011>          TextColorReg	resb 17			; VGA color registers for text mode
   478 00005606 <res 0000000D>          VGAFileBuf	resb 13			; Unmangled VGA image name
   479                                  VGAFileBufEnd	equ $
   480 00005613 <res 0000000B>          VGAFileMBuf	resb 11			; Mangled VGA image name
   481                                  
   482                                  		section .text
   483                                                  org 7C00h
   484                                  ;
   485                                  ; Some of the things that have to be saved very early are saved
   486                                  ; "close" to the initial stack pointer offset, in order to
   487                                  ; reduce the code size...
   488                                  ;
   489                                  StackBuf	equ $-32		; Start the stack here (grow down - 4K)
   490                                  PartInfo	equ StackBuf		; Saved partition table entry
   491                                  FloppyTable	equ PartInfo+16		; Floppy info table (must follow PartInfo)
   492                                  OrigFDCTabPtr	equ StackBuf-4		; The high dword on the stack
   493                                  
   494                                  ;
   495                                  ; Primary entry point.  Tempting as though it may be, we can't put the
   496                                  ; initial "cli" here; the jmp opcode in the first byte is part of the
   497                                  ; "magic number" (using the term very loosely) for the DOS superblock.
   498                                  ;
   499                                  bootsec		equ $
   500 00000000 EB3C                    		jmp short start		; 2 bytes
   501 00000002 90                      		nop			; 1 byte
   502                                  ;
   503                                  ; "Superblock" follows -- it's in the boot sector, so it's already
   504                                  ; loaded and ready for us
   505                                  ;
   506 00000003 5359534C494E5558        bsOemName	db 'SYSLINUX'		; The SYS command sets this, so...
   507                                  ;
   508                                  ; These are the fields we actually care about.  We end up expanding them
   509                                  ; all to dword size early in the code, so generate labels for both
   510                                  ; the expanded and unexpanded versions.
   511                                  ;;
   512                                  %macro		superb 1
   513                                  bx %+ %1	equ SuperInfo+($-superblock)*8+4
   514                                  bs %+ %1	equ $
   515                                  		zb 1
   516                                  %endmacro
   517                                  %macro		superw 1
   518                                  bx %+ %1	equ SuperInfo+($-superblock)*8
   519                                  bs %+ %1	equ $
   520                                  		zw 1
   521                                  %endmacro
   522                                  %macro		superd 1
   523                                  bx %+ %1	equ $			; no expansion for dwords
   524                                  bs %+ %1	equ $
   525                                  		zd 1
   526                                  %endmacro
   527                                  superblock	equ $
   528                                  		superw BytesPerSec
   529                              <1> bx %+ %1 equ SuperInfo+($-superblock)*8
   530                              <1> bs %+ %1 equ $
   531                              <1>  zw 1
   532 0000000B 0000                <2>  times %1 dw 0
   533                                  		superb SecPerClust
   534                              <1> bx %+ %1 equ SuperInfo+($-superblock)*8+4
   535                              <1> bs %+ %1 equ $
   536                              <1>  zb 1
   537 0000000D 00                  <2>  times %1 db 0
   538                                  		superw ResSectors
   539                              <1> bx %+ %1 equ SuperInfo+($-superblock)*8
   540                              <1> bs %+ %1 equ $
   541                              <1>  zw 1
   542 0000000E 0000                <2>  times %1 dw 0
   543                                  		superb FATs
   544                              <1> bx %+ %1 equ SuperInfo+($-superblock)*8+4
   545                              <1> bs %+ %1 equ $
   546                              <1>  zb 1
   547 00000010 00                  <2>  times %1 db 0
   548                                  		superw RootDirEnts
   549                              <1> bx %+ %1 equ SuperInfo+($-superblock)*8
   550                              <1> bs %+ %1 equ $
   551                              <1>  zw 1
   552 00000011 0000                <2>  times %1 dw 0
   553                                  		superw Sectors
   554                              <1> bx %+ %1 equ SuperInfo+($-superblock)*8
   555                              <1> bs %+ %1 equ $
   556                              <1>  zw 1
   557 00000013 0000                <2>  times %1 dw 0
   558                                  		superb Media
   559                              <1> bx %+ %1 equ SuperInfo+($-superblock)*8+4
   560                              <1> bs %+ %1 equ $
   561                              <1>  zb 1
   562 00000015 00                  <2>  times %1 db 0
   563                                  		superw FATsecs
   564                              <1> bx %+ %1 equ SuperInfo+($-superblock)*8
   565                              <1> bs %+ %1 equ $
   566                              <1>  zw 1
   567 00000016 0000                <2>  times %1 dw 0
   568                                  		superw SecPerTrack
   569                              <1> bx %+ %1 equ SuperInfo+($-superblock)*8
   570                              <1> bs %+ %1 equ $
   571                              <1>  zw 1
   572 00000018 0000                <2>  times %1 dw 0
   573                                  		superw Heads
   574                              <1> bx %+ %1 equ SuperInfo+($-superblock)*8
   575                              <1> bs %+ %1 equ $
   576                              <1>  zw 1
   577 0000001A 0000                <2>  times %1 dw 0
   578                                  superinfo_size	equ ($-superblock)-1	; How much to expand
   579                                  		superd Hidden
   580                              <1> bx %+ %1 equ $
   581                              <1> bs %+ %1 equ $
   582                              <1>  zd 1
   583 0000001C 00000000            <2>  times %1 dd 0
   584                                  		superd HugeSectors
   585                              <1> bx %+ %1 equ $
   586                              <1> bs %+ %1 equ $
   587                              <1>  zd 1
   588 00000020 00000000            <2>  times %1 dd 0
   589                                  		superb DriveNumber
   590                              <1> bx %+ %1 equ SuperInfo+($-superblock)*8+4
   591                              <1> bs %+ %1 equ $
   592                              <1>  zb 1
   593 00000024 00                  <2>  times %1 db 0
   594                                  		superb Reserved1
   595                              <1> bx %+ %1 equ SuperInfo+($-superblock)*8+4
   596                              <1> bs %+ %1 equ $
   597                              <1>  zb 1
   598 00000025 00                  <2>  times %1 db 0
   599                                  		superb BootSignature	; 29h if the following fields exist
   600                              <1> bx %+ %1 equ SuperInfo+($-superblock)*8+4
   601                              <1> bs %+ %1 equ $
   602                              <1>  zb 1
   603 00000026 00                  <2>  times %1 db 0
   604                                  		superd VolumeID
   605                              <1> bx %+ %1 equ $
   606                              <1> bs %+ %1 equ $
   607                              <1>  zd 1
   608 00000027 00000000            <2>  times %1 dd 0
   609                                  bsVolumeLabel	zb 11
   610                              <1> bsVolumeLabel :
   611 0000002B 00<rept>            <1>  times %1 db 0
   612                                  bsFileSysType	zb 8			; Must be FAT12 or FAT16 for this version
   613                              <1> bsFileSysType :
   614 00000036 00<rept>            <1>  times %1 db 0
   615                                  superblock_len	equ $-superblock
   616                                  
   617                                  SecPerClust	equ bxSecPerClust
   618                                  ;
   619                                  ; Note we don't check the constraints above now; we did that at install
   620                                  ; time (we hope!)
   621                                  ;
   622                                  
   623                                  ;floppy_table	equ $			; No sense in wasting memory, overwrite start
   624                                  
   625                                  start:
   626 0000003E FA                      		cli			; No interrupts yet, please
   627 0000003F FC                      		cld			; Copy upwards
   628                                  ;
   629                                  ; Set up the stack
   630                                  ;
   631 00000040 31C0                    		xor ax,ax
   632 00000042 8ED0                    		mov ss,ax
   633 00000044 BC[E0FF]                		mov sp,StackBuf		; Just below BSS
   634 00000047 8EC0                    		mov es,ax
   635                                  ;
   636                                  ; DS:SI may contain a partition table entry.  Preserve it for us.
   637                                  ;
   638 00000049 B90800                  		mov cx,8		; Save partition info
   639 0000004C 89E7                    		mov di,sp
   640 0000004E F3A5                    		rep movsw
   641                                  
   642 00000050 8ED8                    		mov ds,ax		; Now we can initialize DS...
   643                                  
   644 00000052 885534                  		mov [di+bsDriveNumber-FloppyTable],dl
   645                                  ;
   646                                  ; Now sautee the BIOS floppy info block to that it will support decent-
   647                                  ; size transfers; the floppy block is 11 bytes and is stored in the
   648                                  ; INT 1Eh vector (brilliant waste of resources, eh?)
   649                                  ;
   650                                  ; Of course, if BIOSes had been properly programmed, we wouldn't have
   651                                  ; had to waste precious space with this code.
   652                                  ;
   653 00000055 BB7800                  		mov bx,fdctab
   654 00000058 0FB437                  		lfs si,[bx]		; FS:SI -> original fdctab
   655 0000005B 0FA0                    		push fs			; Save on stack in case we need to bail
   656 0000005D 56                      		push si
   657                                  
   658                                  		; Save the old fdctab even if hard disk so the stack layout
   659                                  		; is the same.  The instructions above do not change the flags
   660 0000005E 20D2                    		and dl,dl		; If floppy disk (00-7F), assume no
   661                                  					; partition table
   662 00000060 7815                    		js harddisk
   663                                  
   664                                  floppy:
   665 00000062 B106                    		mov cl,6		; 12 bytes (CX == 0)
   666                                  		; es:di -> FloppyTable already
   667                                  		; This should be safe to do now, interrupts are off...
   668 00000064 893F                    		mov [bx],di		; FloppyTable
   669 00000066 894702                  		mov [bx+2],ax		; Segment 0
   670 00000069 64F3A5                  		fs rep movsw		; Faster to move words
   671 0000006C 8A0E[1800]              		mov cl,[bsSecPerTrack]  ; Patch the sector count
   672 00000070 884DF8                  		mov [di-8],cl
   673                                  		; AX == 0 here
   674 00000073 CD13                    		int 13h			; Some BIOSes need this
   675                                  
   676 00000075 EB21                    		jmp short not_harddisk
   677                                  ;
   678                                  ; The drive number and possibly partition information was passed to us
   679                                  ; by the BIOS or previous boot loader (MBR).  Current "best practice" is to
   680                                  ; trust that rather than what the superblock contains.
   681                                  ;
   682                                  ; Would it be better to zero out bsHidden if we don't have a partition table?
   683                                  ;
   684                                  ; Note: di points to beyond the end of PartInfo
   685                                  ;
   686                                  harddisk:
   687                                  ; This sanity check doesn't fit anymore...
   688                                  ;		test byte [di-16],7Fh	; Sanity check: "active flag" should
   689                                  ;		jnz no_partition	; be 00 or 80
   690 00000077 668B45F8                		mov eax,[di-8]		; Partition offset (dword)
   691 0000007B 66A3[1C00]              		mov [bsHidden],eax
   692                                  no_partition:
   693                                  ;
   694                                  ; Get disk drive parameters (don't trust the superblock.)  Don't do this for
   695                                  ; floppy drives -- INT 13:08 on floppy drives will (may?) return info about
   696                                  ; what the *drive* supports, not about the *media*.  Fortunately floppy disks
   697                                  ; tend to have a fixed, well-defined geometry which is stored in the superblock.
   698                                  ;
   699                                  		; DL == drive # still
   700 0000007F B408                    		mov ah,08h
   701 00000081 CD13                    		int 13h
   702 00000083 7213                    		jc no_driveparm
   703 00000085 20E4                    		and ah,ah
   704 00000087 750F                    		jnz no_driveparm
   705 00000089 C1EA08                  		shr dx,8
   706 0000008C 42                      		inc dx			; Contains # of heads - 1
   707 0000008D 8916[1A00]              		mov [bsHeads],dx
   708 00000091 83E13F                  		and cx,3fh
   709 00000094 890E[1800]              		mov [bsSecPerTrack],cx
   710                                  no_driveparm:
   711                                  not_harddisk:
   712                                  ;
   713                                  ; Ready to enable interrupts, captain
   714                                  ;
   715 00000098 FB                      		sti
   716                                  ;
   717                                  ; Insane hack to expand the superblock to dwords
   718                                  ;
   719                                  expand_super:
   720 00000099 6631C0                  		xor eax,eax
   721 0000009C 8EC0                    		mov es,ax			; INT 13:08 destroys ES
   722 0000009E BE[0B00]                		mov si,superblock
   723 000000A1 BFB054                  		mov di,SuperInfo
   724 000000A4 B110                    		mov cl,superinfo_size		; CH == 0
   725                                  .loop:
   726 000000A6 AD                      		lodsw
   727 000000A7 4E                      		dec si
   728 000000A8 66AB                    		stosd				; Store expanded word
   729 000000AA 30E4                    		xor ah,ah
   730 000000AC 66AB                    		stosd				; Store expanded byte
   731 000000AE E2F6                    		loop .loop
   732                                  
   733                                  ;
   734                                  ; Now we have to do some arithmetric to figure out where things are located.
   735                                  ; If Micro$oft had had brains they would already have done this for us,
   736                                  ; and stored it in the superblock at format time, but here we go,
   737                                  ; wasting precious boot sector space again...
   738                                  ;
   739                                  %define		Z di-superinfo_size*8-SuperInfo
   740                                  debugentrypt:
   741 000000B0 A1DC54                  		mov ax,[bxFATs]		; Number of FATs (eax<31:16> == 0)
   742 000000B3 668B55D8                		mov edx,[Z+bxFATsecs]	; Sectors/FAT
   743 000000B7 66F7E2                  		mul edx			; Get the size of the FAT area
   744                                  		; edx <- 0
   745 000000BA 660306[1C00]            		add eax,[bxHidden]		; Add hidden sectors
   746 000000BF 66034598                		add eax,[Z+bxResSectors]	; And reserved sectors
   747                                  
   748 000000C3 66A33055                		mov [RootDir],eax	; Location of root directory
   749 000000C7 66A33455                		mov [DataArea],eax	; First data sector
   750 000000CB 6650                    		push eax
   751                                  
   752 000000CD 668B45B0                		mov eax,[Z+bxRootDirEnts]
   753 000000D1 C1E005                  		shl ax,5		; Size of a directory entry
   754 000000D4 8B5D80                  		mov bx,[Z+bxBytesPerSec]
   755 000000D7 01D8                    		add ax,bx		; Round up, not down
   756 000000D9 48                      		dec ax
   757 000000DA F7F3                    		div bx			; Now we have the size of the root dir
   758 000000DC A33855                  		mov [RootDirSize],ax
   759 000000DF A33A55                  		mov [DirScanCtr],ax
   760 000000E2 81C3E10F                		add bx,trackbuf-31
   761 000000E6 895D0C                  		mov [Z+EndofDirSec],bx	; End of a single directory sector
   762 000000E9 66014504                		add [Z+DataArea],eax
   763 000000ED 6658                    		pop eax			; Reload root directory starting point
   764                                  
   765                                  ;
   766                                  ; Now the fun begins.  We have to search the root directory for
   767                                  ; LDLINUX.SYS and load the first sector, so we have a little more
   768                                  ; space to have fun with.  Then we can go chasing through the FAT.
   769                                  ; Joy!!
   770                                  ;
   771 000000EF 6650                    sd_nextsec:	push eax
   772 000000F1 BB0010                  		mov bx,trackbuf
   773 000000F4 53                      		push bx
   774 000000F5 E88200                  		call getonesec
   775 000000F8 5E                      		pop si
   776 000000F9 B90B00                  sd_nextentry:	mov cx,11
   777 000000FC 382C                    		cmp [si],ch		; Directory high water mark
   778 000000FE 741C                    		je kaboom
   779                                  ; This no longer fits... since we'd be dead anyway if there
   780                                  ; was a nonfile named LDLINUX.SYS on the disk, it shouldn't
   781                                  ; matter...
   782                                  ;		test byte [si+11],18h	; Must be a file
   783                                  ;		jnz sd_not_file
   784 00000100 BF[EF01]                		mov di,ldlinux_name
   785 00000103 56                      		push si
   786 00000104 F3A6                    		repe cmpsb
   787 00000106 5E                      		pop si
   788 00000107 742E                    		je found_it
   789 00000109 83C620                  sd_not_file:	add si,byte 32		; Distance to next
   790 0000010C 3B363C55                		cmp si,[EndofDirSec]
   791 00000110 72E7                    		jb sd_nextentry
   792 00000112 6658                    		pop eax
   793 00000114 6640                    		inc eax
   794 00000116 FF0E3A55                		dec word [DirScanCtr]
   795 0000011A 75D3                    		jnz sd_nextsec
   796                                  ;
   797                                  ; kaboom: write a message and bail out.
   798                                  ;
   799                                  kaboom:
   800 0000011C 31F6                    		xor si,si
   801 0000011E 8ED6                    		mov ss,si		
   802 00000120 BC[DCFF]                		mov sp,StackBuf-4 	; Reset stack
   803 00000123 8EDE                    		mov ds,si		; Reset data segment
   804 00000125 668F067800              		pop dword [fdctab]	; Restore FDC table
   805 0000012A BE[DA01]                .patch:		mov si,bailmsg
   806 0000012D E83600                  		call writestr		; Returns with AL = 0
   807 00000130 98                      		cbw			; AH <- 0
   808 00000131 CD16                    		int 16h			; Wait for keypress
   809 00000133 CD19                    		int 19h			; And try once more to boot...
   810 00000135 EBFE                    .norge:		jmp short .norge	; If int 19h returned; this is the end
   811                                  
   812                                  ;
   813                                  ; found_it: now we compute the location of the first sector, then
   814                                  ;	    load it and JUMP (since we're almost out of space)
   815                                  ;
   816                                  found_it:	; Note: we actually leave two words on the stack here
   817                                  		; (who cares?)
   818 00000137 66A1C454                		mov eax,[bxSecPerClust]
   819 0000013B 89C5                    		mov bp,ax		; Load an entire cluster
   820 0000013D 660FB75C1A              		movzx ebx,word [si+26]	; First cluster
   821 00000142 891E8A55                		mov [RunLinClust],bx	; Save for later use
   822 00000146 4B                      		dec bx			; First cluster is "cluster 2"
   823 00000147 4B                      		dec bx
   824 00000148 66F7E3                  		mul ebx
   825 0000014B 6603063455              		add eax,[DataArea]
   826 00000150 BB[0002]                		mov bx,ldlinux_sys
   827 00000153 E82700                  		call getlinsec
   828 00000156 BE[EF01]                		mov si,bs_magic
   829 00000159 BF[1F02]                		mov di,ldlinux_magic
   830 0000015C B91100                  		mov cx,magic_len
   831 0000015F F3A6                    		repe cmpsb		; Make sure that the bootsector
   832 00000161 75B9                    		jne kaboom		; matches LDLINUX.SYS
   833                                  ;
   834                                  ; Done! Jump to the entry point!
   835                                  ;
   836 00000163 E9CE00                  		jmp ldlinux_ent
   837                                  ;
   838                                  ;
   839                                  ; writestr: write a null-terminated string to the console
   840                                  ;
   841                                  writestr:
   842 00000166 AC                      .loop:		lodsb
   843 00000167 20C0                    		and al,al
   844 00000169 7409                                    jz .return
   845 0000016B B40E                    		mov ah,0Eh		; Write to screen as TTY
   846 0000016D BB0700                  		mov bx,0007h		; White on black, current page
   847 00000170 CD10                    		int 10h
   848 00000172 EBF2                    		jmp short .loop
   849 00000174 C3                      .return:	ret
   850                                  
   851                                  ;
   852                                  ; disk_error: decrement the retry count and bail if zero.
   853                                  ;	      This gets patched once we have more space to try to
   854                                  ;             optimize transfer sizes on broken machines.
   855                                  ;
   856 00000175 4E                      disk_error:	dec si			; SI holds the disk retry counter
   857 00000176 74A4                    		jz kaboom
   858                                  		; End of patched "call" instruction!
   859 00000178 EB33                    		jmp short disk_try_again
   860                                  
   861                                  ;
   862                                  ; getonesec: like getlinsec, but pre-sets the count to 1
   863                                  ;
   864                                  getonesec:
   865 0000017A BD0100                  		mov bp,1
   866                                  		; Fall through to getlinsec
   867                                  
   868                                  ;
   869                                  ; getlinsec: load a sequence of BP floppy sector given by the linear sector
   870                                  ;	     number in EAX into the buffer at ES:BX.  We try to optimize
   871                                  ;	     by loading up to a whole track at a time, but the user
   872                                  ;	     is responsible for not crossing a 64K boundary.
   873                                  ;	     (Yes, BP is weird for a count, but it was available...)
   874                                  ;
   875                                  ;	     On return, BX points to the first byte after the transferred
   876                                  ;	     block.
   877                                  ;
   878                                  ;	     The "stupid patch area" gets replaced by the code
   879                                  ;	     mov bp,1 ; nop ... (BD 01 00 90 90...) when installing with
   880                                  ;	     the -s option.
   881                                  ;
   882                                  ;            This routine assumes CS == DS.
   883                                  ;
   884                                  ; Stylistic note: use "xchg" instead of "mov" when the source is a register
   885                                  ; that is dead from that point; this saves space.  However, please keep
   886                                  ; the order to dst,src to keep things sane.
   887                                  ;
   888                                  getlinsec:
   889 0000017D 668B361855              		mov esi,[bxSecPerTrack]
   890                                  		;
   891                                  		; Dividing by sectors to get (track,sector): we may have
   892                                  		; up to 2^18 tracks, so we need to use 32-bit arithmetric.
   893                                  		;
   894 00000182 6631D2                  		xor edx,edx		; Zero-extend LBA to 64 bits
   895 00000185 66F7F6                  		div esi
   896 00000188 31C9                    		xor cx,cx
   897 0000018A 87CA                    		xchg cx,dx		; CX <- sector index (0-based)
   898                                  					; EDX <- 0
   899                                  		; eax = track #
   900 0000018C 66F7362855              		div dword [bxHeads]	; Convert track to head/cyl
   901                                  		;
   902                                  		; Now we have AX = cyl, DX = head, CX = sector (0-based),
   903                                  		; BP = sectors to transfer, SI = bsSecPerTrack,
   904                                  		; ES:BX = data target
   905                                  		;
   906 00000191 56                      gls_nextchunk:	push si			; <A> bsSecPerTrack
   907 00000192 55                      		push bp			; <B> Sectors to transfer
   908                                  
   909                                  		; Important - this gets patched with a call.  The call
   910                                  		; assumes cx, si and bp are set up, and can modify bp
   911                                  		; and destroy si.  Until we have the space to do so,
   912                                  		; transfer one sector at a time.
   913                                  gls_set_size:
   914                                  __BEGIN_STUPID_PATCH_AREA:
   915 00000193 BD0100                  		mov bp,1		; 3 bytes, same as a call insn
   916                                  __END_STUPID_PATCH_AREA:
   917                                  
   918 00000196 50                      		push ax			; <C> Cylinder #
   919 00000197 52                      		push dx			; <D> Head #
   920                                  
   921 00000198 51                      		push cx			; <E> Sector #
   922 00000199 C0E406                  		shl ah,6		; Because IBM was STOOPID
   923                                  					; and thought 8 bits were enough
   924                                  					; then thought 10 bits were enough...
   925 0000019C 59                      		pop cx			; <E> Sector #
   926 0000019D 51                      		push cx			; <E> Sector #
   927 0000019E 41                      		inc cx			; Sector numbers are 1-based, sigh
   928 0000019F 08E1                    		or cl,ah
   929 000001A1 88C5                    		mov ch,al
   930 000001A3 88D6                    		mov dh,dl
   931 000001A5 8A16[2400]              		mov dl,[bsDriveNumber]
   932 000001A9 95                      		xchg ax,bp		; Sector to transfer count
   933                                  					; (xchg shorter than mov)
   934 000001AA BE0600                  		mov si,retry_count	; # of times to retry a disk access
   935                                  ;
   936                                  ; Do the disk transfer... save the registers in case we fail :(
   937                                  ;
   938                                  disk_try_again: 
   939 000001AD 60                      		pusha			; <F>
   940 000001AE B402                    		mov ah,02h		; READ DISK
   941 000001B0 CD13                    		int 13h
   942 000001B2 61                      		popa			; <F>
   943 000001B3 72C0                    		jc disk_error
   944                                  ;
   945                                  ; Disk access successful
   946                                  ;
   947 000001B5 59                      		pop cx			; <E> Sector #
   948 000001B6 89C7                    		mov di,ax		; Reduce sector left count
   949 000001B8 F726[0B00]              		mul word [bsBytesPerSec] ; Figure out how much to advance ptr
   950 000001BC 01C3                    		add bx,ax		; Update buffer location
   951 000001BE 5A                      		pop dx			; <D> Head #
   952 000001BF 58                      		pop ax			; <C> Cyl #
   953 000001C0 5D                      		pop bp			; <B> Sectors left to transfer
   954 000001C1 5E                      		pop si			; <A> Number of sectors/track
   955 000001C2 29FD                    		sub bp,di		; Reduce with # of sectors just read
   956 000001C4 74AE                    		jz writestr.return	; Done!
   957 000001C6 01F9                    		add cx,di
   958 000001C8 39F1                    		cmp cx,si
   959 000001CA 72C5                    		jb gls_nextchunk
   960 000001CC 42                      		inc dx			; Next track on cyl
   961 000001CD 3B16[1A00]              		cmp dx,[bsHeads]	; Was this the last one?
   962 000001D1 7203                    		jb gls_nonewcyl
   963 000001D3 40                      		inc ax			; If so, new cylinder
   964 000001D4 31D2                    		xor dx,dx		; First head on new cylinder
   965 000001D6 29F1                    gls_nonewcyl:	sub cx,si		; First sector on new track
   966 000001D8 EBB7                    		jmp short gls_nextchunk
   967                                  
   968 000001DA 426F6F74206661696C-     bailmsg:	db 'Boot failed', 0Dh, 0Ah, 0
   969 000001E3 65640D0A00         
   970                                  
   971                                  bs_checkpt	equ $			; Must be <= 7DEFh
   972                                  
   973                                  %if 1
   974                                  bs_checkpt_off	equ ($-$$)
   975                                  %ifndef DEPEND
   976                                  %if bs_checkpt_off > 1EFh
   977                                  %error "Boot sector overflow"
   978                                  %endif
   979                                  %endif
   980                                  
   981                                  		zb 1EFh-($-$$)
   982 000001E8 00<rept>            <1>  times %1 db 0
   983                                  %endif
   984                                  bs_magic	equ $			; From here to the magic_len equ
   985                                  					; must match ldlinux_magic
   986 000001EF 4C444C494E55582053-     ldlinux_name:	db 'LDLINUX SYS'	; Looks like this in the root dir
   987 000001F8 5953               
   988 000001FA 7198B93D                		dd HEXDATE		; Hopefully unique between compiles
   989                                  
   990 000001FE 55AA                    bootsignature	dw 0AA55h
   991                                  magic_len	equ $-bs_magic
   992                                  
   993                                  ;
   994                                  ; ===========================================================================
   995                                  ;  End of boot sector
   996                                  ; ===========================================================================
   997                                  ;  Start of LDLINUX.SYS
   998                                  ; ===========================================================================
   999                                  
  1000                                  ldlinux_sys:
  1001                                  
  1002 00000200 0D0A5359534C494E55-     syslinux_banner	db 0Dh, 0Ah, 'SYSLINUX ', version_str, ' ', date, ' ', 0
  1003 00000209 5820322E3030203230-
  1004 00000212 30322D31302D323520-
  1005 0000021B 00                 
  1006 0000021C 0D0A1A                  		db 0Dh, 0Ah, 1Ah	; EOF if we "type" this in DOS
  1007                                  
  1008 0000021F 4C444C494E55582053-     ldlinux_magic	db 'LDLINUX SYS'
  1009 00000228 5953               
  1010 0000022A 7198B93D                		dd HEXDATE
  1011 0000022E 55AA                    		dw 0AA55h
  1012                                  
  1013                                  ;
  1014                                  ; This area is possibly patched by the installer.  It is located
  1015                                  ; immediately after the EOF + LDLINUX SYS + 4 bytes + 55 AA + alignment,
  1016                                  ; so we can find it algorithmically.
  1017                                  ;
  1018                                  		alignb 4
  1019 00000230 FF00                    MaxTransfer	dw 00FFh		; Absolutely maximum transfer size
  1020                                  
  1021 00000232 90<rept>                		align 4
  1022                                  ldlinux_ent:
  1023                                  ; 
  1024                                  ; Note that some BIOSes are buggy and run the boot sector at 07C0:0000
  1025                                  ; instead of 0000:7C00 and the like.  We don't want to add anything
  1026                                  ; more to the boot sector, so it is written to not assume a fixed
  1027                                  ; value in CS, but we don't want to deal with that anymore from now
  1028                                  ; on.
  1029                                  ;
  1030 00000234 EA[3902]0000            		jmp 0:.next
  1031                                  .next:
  1032                                  
  1033                                  ;
  1034                                  ; Tell the user we got this far
  1035                                  ;
  1036 00000239 BE[0002]                		mov si,syslinux_banner
  1037 0000023C E827FF                  		call writestr
  1038                                  ;
  1039                                  ; Remember, the boot sector loaded only the first cluster of LDLINUX.SYS.
  1040                                  ; We can really only rely on a single sector having been loaded.  Hence
  1041                                  ; we should load the FAT into RAM and start chasing pointers...
  1042                                  ;
  1043 0000023F 31C0                    		xor ax,ax
  1044 00000241 99                      		cwd
  1045 00000242 42                      		inc dx				; DX:AX <- 64K
  1046 00000243 F736B054                		div word [bxBytesPerSec]	; sectors/64K
  1047 00000247 89C6                    		mov si,ax
  1048                                  
  1049 00000249 06                      		push es
  1050 0000024A BB0050                  		mov bx,fat_seg			; Load into fat_seg:0000
  1051 0000024D 8EC3                    		mov es,bx
  1052                                  		
  1053 0000024F 66A1[1C00]              		mov eax,[bsHidden]		; Hidden sectors
  1054 00000253 660316C854              		add edx,[bxResSectors]
  1055 00000258 6601D0                  		add eax,edx
  1056 0000025B 668B0E0855              		mov ecx,[bxFATsecs]		; Sectors/FAT
  1057                                  fat_load_loop:	
  1058 00000260 6689CD                  		mov ebp,ecx			; Make sure high EBP = 0
  1059 00000263 39F5                    		cmp bp,si
  1060 00000265 7602                    		jna fat_load
  1061 00000267 89F5                    		mov bp,si			; A full 64K moby
  1062                                  fat_load:	
  1063 00000269 31DB                    		xor bx,bx			; Offset 0 in the current ES
  1064 0000026B E80701                  		call getlinsecsr
  1065 0000026E 29E9                    		sub cx,bp
  1066 00000270 740D                    		jz fat_load_done		; Last moby?
  1067 00000272 6601E8                  		add eax,ebp			; Advance sector count
  1068 00000275 8CC3                    		mov bx,es			; Next 64K moby
  1069 00000277 81C30010                		add bx,1000h
  1070 0000027B 8EC3                    		mov es,bx
  1071 0000027D EBE1                    		jmp short fat_load_loop
  1072                                  fat_load_done:
  1073 0000027F 07                      		pop es
  1074                                  ;
  1075                                  ; Fine, now we have the FAT in memory.	How big is a cluster, really?
  1076                                  ; Also figure out how many clusters will fit in an 8K buffer, and how
  1077                                  ; many sectors and bytes that is
  1078                                  ;
  1079 00000280 668B3EB054              		mov edi,[bxBytesPerSec]		; Used a lot below
  1080 00000285 66A1C454                		mov eax,[SecPerClust]
  1081 00000289 89C6                    		mov si,ax			; Also used a lot
  1082 0000028B F7E7                    		mul di
  1083 0000028D 66A37055                		mov [ClustSize],eax		; Bytes/cluster
  1084 00000291 89C3                    		mov bx,ax
  1085 00000293 B80040                  		mov ax,trackbufsize		; High bit 0
  1086 00000296 99                      		cwd
  1087 00000297 F7F3                    		div bx
  1088 00000299 A38C55                  		mov [BufSafe],ax		; # of cluster in trackbuf
  1089 0000029C F7E6                    		mul si
  1090 0000029E A38E55                  		mov [BufSafeSec],ax
  1091 000002A1 F7E7                    		mul di
  1092 000002A3 A39055                  		mov [BufSafeBytes],ax
  1093 000002A6 0500A0                  		add ax,getcbuf			; Size of getcbuf is the same
  1094 000002A9 A39255                  		mov [EndOfGetCBuf],ax		; as for trackbuf
  1095                                  ;
  1096                                  ; FAT12 or FAT16?  This computation is fscking ridiculous...
  1097                                  ;
  1098 000002AC 66A1F054                		mov eax,[bxSectors]
  1099 000002B0 21C0                    		and ax,ax
  1100 000002B2 7504                    		jnz have_secs
  1101 000002B4 66A1[2000]              		mov eax,[bsHugeSectors]
  1102 000002B8 660306[1C00]            have_secs:	add eax,[bsHidden]		; These are not included
  1103 000002BD 662B063055              		sub eax,[RootDir]		; Start of root directory
  1104 000002C2 660FB71E3855            		movzx ebx,word [RootDirSize]
  1105 000002C8 6629D8                  		sub eax,ebx			; Subtract root directory size
  1106 000002CB 6631D2                  		xor edx,edx
  1107 000002CE 66F7F6                  		div esi				; Convert to clusters
  1108 000002D1 3DF60F                  		cmp ax,4086			; FAT12 limit
  1109 000002D4 7605                    		jna is_fat12
  1110                                  		; Patch the jump
  1111 000002D6 C606[7E03]1D            		mov byte [nextcluster+1],nextcluster_fat16-(nextcluster+2)
  1112                                  is_fat12:
  1113                                  
  1114                                  ;
  1115                                  ; Patch gls_set_size so we can transfer more than one sector at a time.
  1116                                  ;
  1117 000002DB C606[9301]E8            		mov byte [gls_set_size],0xe8	; E8 = CALL NEAR
  1118 000002E0 C706[9401]1C02          		mov word [gls_set_size+1],do_gls_set_size-(gls_set_size+3)
  1119 000002E6 C606[7501]E8            		mov byte [disk_error],0xe8
  1120 000002EB C706[7601]4D02          		mov word [disk_error+1],do_disk_error-(disk_error+3)
  1121                                  
  1122                                  ;
  1123                                  ; Now we read the rest of LDLINUX.SYS.	Don't bother loading the first
  1124                                  ; cluster again, though.
  1125                                  ;
  1126                                  load_rest:
  1127 000002F1 8B0E7055                		mov cx,[ClustSize]
  1128 000002F5 BB[0002]                		mov bx,ldlinux_sys
  1129 000002F8 01CB                    		add bx,cx
  1130 000002FA 8B368A55                		mov si,[RunLinClust]
  1131 000002FE E87C00                  		call nextcluster
  1132 00000301 31D2                    		xor dx,dx
  1133 00000303 B87D20                  		mov ax,ldlinux_len-1		; To be on the safe side
  1134 00000306 01C8                    		add ax,cx
  1135 00000308 F7F1                    		div cx				; the number of clusters
  1136 0000030A 48                      		dec ax				; We've already read one
  1137 0000030B 7405                    		jz all_read_jmp
  1138 0000030D 89C1                    		mov cx,ax
  1139 0000030F E80300                  		call getfssec
  1140                                  ;
  1141                                  ; All loaded up
  1142                                  ;
  1143                                  all_read_jmp:
  1144 00000312 E9CB00                  		jmp all_read
  1145                                  ;
  1146                                  ; -----------------------------------------------------------------------------
  1147                                  ; Subroutines that have to be in the first sector
  1148                                  ; -----------------------------------------------------------------------------
  1149                                  ;
  1150                                  ; getfssec: Get multiple clusters from a file, given the starting cluster.
  1151                                  ;
  1152                                  ;	This routine makes sure the subtransfers do not cross a 64K boundary,
  1153                                  ;	and will correct the situation if it does, UNLESS *sectors* cross
  1154                                  ;	64K boundaries.
  1155                                  ;
  1156                                  ;	ES:BX	-> Buffer
  1157                                  ;	SI	-> Starting cluster number (2-based)
  1158                                  ;	CX	-> Cluster count (0FFFFh = until end of file)
  1159                                  ;
  1160                                  ;	Returns CF=1 on EOF
  1161                                  ;
  1162                                  getfssec:
  1163 00000315 6631ED                  getfragment:	xor ebp,ebp			; Fragment sector count
  1164 00000318 660FB7C6                		movzx eax,si			; Get sector address
  1165 0000031C 48                      		dec ax				; Convert to 0-based
  1166 0000031D 48                      		dec ax
  1167 0000031E 66F726C454              		mul dword [SecPerClust]
  1168 00000323 6603063455              		add eax,[DataArea]
  1169                                  getseccnt:					; See if we can read > 1 clust
  1170 00000328 032EC454                		add bp,[SecPerClust]
  1171 0000032C 49                      		dec cx				; Reduce clusters left to find
  1172 0000032D 8D7C01                  		lea di,[si+1]
  1173 00000330 E84A00                  		call nextcluster
  1174 00000333 F5                      		cmc
  1175 00000334 7207                    		jc gfs_eof			; At EOF?
  1176 00000336 E304                    		jcxz endfragment		; Or was it the last we wanted?
  1177 00000338 39FE                    		cmp si,di			; Is file continuous?
  1178 0000033A 74EC                    		jz getseccnt			; Yes, we can get
  1179 0000033C F8                      endfragment:	clc				; Not at EOF
  1180 0000033D 9C                      gfs_eof:	pushf				; Remember EOF or not
  1181 0000033E 56                      		push si
  1182 0000033F 51                      		push cx
  1183                                  gfs_getchunk:
  1184 00000340 6650                    		push eax
  1185 00000342 8CC0                    		mov ax,es			; Check for 64K boundaries.
  1186 00000344 C1E004                  		shl ax,4
  1187 00000347 01D8                    		add ax,bx
  1188 00000349 31D2                    		xor dx,dx
  1189 0000034B F7D8                    		neg ax
  1190 0000034D 0F94C2                  		setz dl				; DX <- 1 if full 64K segment
  1191 00000350 F736[0B00]              		div word [bsBytesPerSec]	; How many sectors fit?
  1192 00000354 89EE                    		mov si,bp
  1193 00000356 29C6                    		sub si,ax			; Compute remaining sectors
  1194 00000358 760E                    		jbe gfs_lastchunk
  1195 0000035A 89C5                    		mov bp,ax
  1196 0000035C 6658                    		pop eax
  1197 0000035E E81400                  		call getlinsecsr
  1198 00000361 6601E8                  		add eax,ebp			; EBP<31:16> == 0
  1199 00000364 89F5                    		mov bp,si			; Remaining sector count
  1200 00000366 EBD8                    		jmp short gfs_getchunk
  1201 00000368 6658                    gfs_lastchunk:	pop eax
  1202 0000036A E810FE                  		call getlinsec
  1203 0000036D 59                      		pop cx
  1204 0000036E 5E                      		pop si
  1205 0000036F 9D                      		popf
  1206 00000370 E302                    		jcxz gfs_return			; If we hit the count limit
  1207 00000372 73A1                    		jnc getfragment			; If we didn't hit EOF
  1208 00000374 C3                      gfs_return:	ret
  1209                                  
  1210                                  ;
  1211                                  ; getlinsecsr: save registers, call getlinsec, restore registers
  1212                                  ;
  1213 00000375 6660                    getlinsecsr:	pushad
  1214 00000377 E803FE                  		call getlinsec
  1215 0000037A 6661                    		popad
  1216 0000037C C3                      		ret
  1217                                  
  1218                                  ;
  1219                                  ; nextcluster: Advance a cluster pointer in SI to the next cluster
  1220                                  ;	       pointed at in the FAT tables.  CF=0 on return if end of file.
  1221                                  ;
  1222                                  nextcluster:
  1223 0000037D EB00                    		jmp short nextcluster_fat12	; This gets patched
  1224                                  
  1225                                  nextcluster_fat12:
  1226 0000037F 53                      		push bx
  1227 00000380 1E                      		push ds
  1228 00000381 BB0050                  		mov bx,fat_seg
  1229 00000384 8EDB                    		mov ds,bx
  1230 00000386 89F3                    		mov bx,si			; Multiply by 3/2
  1231 00000388 D1EB                    		shr bx,1			; CF now set if odd
  1232 0000038A 8B30                    		mov si,[si+bx]
  1233 0000038C 7303                    		jnc nc_even
  1234 0000038E C1EE04                  		shr si,4			; Needed for odd only
  1235                                  nc_even:
  1236 00000391 81E6FF0F                		and si,0FFFh
  1237 00000395 81FEF00F                		cmp si,0FF0h			; Clears CF if at end of file
  1238 00000399 1F                      		pop ds
  1239 0000039A 5B                      		pop bx
  1240 0000039B C3                      nc_return:	ret
  1241                                  
  1242                                  ;
  1243                                  ; FAT16 decoding routine.  Note that a 16-bit FAT can be up to 128K,
  1244                                  ; so we have to decide if we're in the "low" or the "high" 64K-segment...
  1245                                  ;
  1246                                  nextcluster_fat16:
  1247 0000039C 50                      		push ax
  1248 0000039D 1E                      		push ds
  1249 0000039E B80050                  		mov ax,fat_seg
  1250 000003A1 D1E6                    		shl si,1
  1251 000003A3 7303                    		jnc .seg0
  1252 000003A5 B80060                  		mov ax,fat_seg+1000h
  1253 000003A8 8ED8                    .seg0:		mov ds,ax
  1254 000003AA 8B34                    		mov si,[si]
  1255 000003AC 83FEF0                  		cmp si,0FFF0h
  1256 000003AF 1F                      		pop ds
  1257 000003B0 58                      		pop ax
  1258 000003B1 C3                      		ret
  1259                                  
  1260                                  ;
  1261                                  ; Routine that controls how much we can transfer in one chunk.  Called
  1262                                  ; from gls_set_size in getlinsec.
  1263                                  ;
  1264                                  do_gls_set_size:
  1265 000003B2 29CE                    		sub si,cx		; Sectors left on track
  1266 000003B4 39F5                    		cmp bp,si
  1267 000003B6 7602                    		jna .lastchunk
  1268 000003B8 89F5                    		mov bp,si		; No more than a trackful, please!
  1269                                  .lastchunk:
  1270 000003BA 3B2E[3002]              		cmp bp,[MaxTransfer]	; Absolute maximum transfer size
  1271 000003BE 7604                    		jna .oktransfer
  1272 000003C0 8B2E[3002]              		mov bp,[MaxTransfer]
  1273                                  .oktransfer:	
  1274 000003C4 C3                      		ret
  1275                                  
  1276                                  ;
  1277                                  ; This routine captures disk errors, and tries to decide if it is
  1278                                  ; time to reduce the transfer size.
  1279                                  ;
  1280                                  do_disk_error:
  1281 000003C5 4E                      		dec si			; Decrement the retry counter
  1282 000003C6 0F8452FD                		jz kaboom		; If expired, croak
  1283 000003CA 83FE02                  		cmp si,2		; If only 2 attempts left
  1284 000003CD 7704                    		ja .nodanger
  1285 000003CF B001                    		mov al,1		; Drop transfer size to 1
  1286 000003D1 EB09                    		jmp short .setsize
  1287                                  .nodanger:
  1288 000003D3 83FE04                  		cmp si,retry_count-2
  1289 000003D6 7707                    		ja .again		; First time, just try again
  1290 000003D8 D0E8                    		shr al,1		; Otherwise, try to reduce
  1291 000003DA 1400                    		adc al,0		; the max transfer size, but not to 0
  1292                                  .setsize:
  1293 000003DC A2[3002]                		mov [MaxTransfer],al
  1294                                  .again:
  1295 000003DF C3                      		ret
  1296                                  
  1297                                  ;
  1298                                  ; Debug routine
  1299                                  ;
  1300                                  %ifdef debug
  1301                                  safedumpregs:
  1302                                  		cmp word [Debug_Magic],0D00Dh
  1303                                  		jnz nc_return
  1304                                  		jmp dumpregs
  1305                                  %endif
  1306                                  
  1307                                  rl_checkpt	equ $				; Must be <= 8000h
  1308                                  
  1309                                  rl_checkpt_off	equ ($-$$)
  1310                                  %ifndef DEPEND
  1311                                  %if rl_checkpt_off > 400h
  1312                                  %error "Sector 1 overflow"
  1313                                  %endif
  1314                                  %endif
  1315                                  
  1316                                  ; ----------------------------------------------------------------------------
  1317                                  ;  End of code and data that have to be in the first sector
  1318                                  ; ----------------------------------------------------------------------------
  1319                                  
  1320                                  all_read:
  1321                                  ;
  1322                                  ; Let the user (and programmer!) know we got this far.  This used to be
  1323                                  ; in Sector 1, but makes a lot more sense here.
  1324                                  ;
  1325 000003E0 BE[941C]                		mov si,copyright_str
  1326 000003E3 E880FD                  		call writestr
  1327                                  
  1328                                  ;
  1329                                  ; Common initialization code
  1330                                  ;
  1331                                  %include "cpuinit.inc"
  1332                              <1> ;; $Id: cpuinit.inc,v 1.2 2002/06/11 05:48:29 hpa Exp $
  1333                              <1> ;; -----------------------------------------------------------------------
  1334                              <1> ;;   
  1335                              <1> ;;   Copyright 1994-2002 H. Peter Anvin - All Rights Reserved
  1336                              <1> ;;
  1337                              <1> ;;   This program is free software; you can redistribute it and/or modify
  1338                              <1> ;;   it under the terms of the GNU General Public License as published by
  1339                              <1> ;;   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
  1340                              <1> ;;   Bostom MA 02111-1307, USA; either version 2 of the License, or
  1341                              <1> ;;   (at your option) any later version; incorporated herein by reference.
  1342                              <1> ;;
  1343                              <1> ;; -----------------------------------------------------------------------
  1344                              <1> 
  1345                              <1> ;;
  1346                              <1> ;; cpuinit.inc
  1347                              <1> ;; 
  1348                              <1> ;; CPU-dependent initialization and related checks.
  1349                              <1> ;;
  1350                              <1> 
  1351                              <1> check_escapes:
  1352 000003E6 B402                <1> 		mov ah,02h			; Check keyboard flags
  1353 000003E8 CD16                <1> 		int 16h
  1354 000003EA A2C055              <1> 		mov [KbdFlags],al		; Save for boot prompt check
  1355 000003ED A804                <1> 		test al,04h			; Ctrl->skip 386 check
  1356 000003EF 7510                <1> 		jnz skip_checks
  1357                              <1> 
  1358                              <1> ;
  1359                              <1> ; Now check that there is sufficient low (DOS) memory
  1360                              <1> ;
  1361 000003F1 CD12                <1> 		int 12h
  1362 000003F3 3DE801              <1> 		cmp ax,(real_mode_seg+0xa00) >> 6
  1363 000003F6 7309                <1> 		jae enough_ram
  1364 000003F8 BE[0C1D]            <1> 		mov si,err_noram
  1365 000003FB E868FD              <1> 		call writestr
  1366 000003FE E91BFD              <1> 		jmp kaboom
  1367                              <1> enough_ram:
  1368                              <1> skip_checks:
  1369                              <1> 
  1370                              <1> ;
  1371                              <1> ; Check if we're 386 (as opposed to 486+); if so we need to blank out
  1372                              <1> ; the WBINVD instruction
  1373                              <1> ;
  1374                              <1> ; We check for 486 by setting EFLAGS.AC
  1375                              <1> ;
  1376                              <1> %if DO_WBINVD
  1377                              <1> 		pushfd				; Save the good flags
  1378                              <1> 		pushfd
  1379                              <1> 		pop eax
  1380                              <1> 		mov ebx,eax
  1381                              <1> 		xor eax,(1 << 18)		; AC bit
  1382                              <1> 		push eax
  1383                              <1> 		popfd
  1384                              <1> 		pushfd
  1385                              <1> 		pop eax
  1386                              <1> 		popfd				; Restore the original flags
  1387                              <1> 		xor eax,ebx
  1388                              <1> 		jnz is_486
  1389                              <1> ;
  1390                              <1> ; 386 - Looks like we better blot out the WBINVD instruction
  1391                              <1> ;
  1392                              <1> 		mov byte [try_wbinvd],0c3h		; Near RET
  1393                              <1> is_486:
  1394                              <1> %endif	; DO_WBINVD
  1395                              <1> ;
  1396                              <1> ; Mark A20 type as unknown.  This particular word needs to be in BSS,
  1397                              <1> ; so it needs to be initialized.
  1398                              <1> ;
  1399 00000401 C706A8550000        <1> 		mov word [A20Type],0
  1400                              <1> 
  1401                              <1> 
  1402                                  
  1403                                  ;
  1404                                  ; Initialization that does not need to go into the any of the pre-load
  1405                                  ; areas
  1406                                  ;
  1407                                  		; Now set up screen parameters
  1408 00000407 E8C615                  		call adjust_screen
  1409                                  
  1410                                  		; Wipe the F-key area
  1411 0000040A B020                    		mov al,NULLFILE
  1412 0000040C BF0054                  		mov di,FKeyName
  1413 0000040F B9A000                  		mov cx,10*(1 << FILENAME_MAX_LG2)
  1414 00000412 F3AA                    		rep stosb
  1415                                  
  1416                                  ;
  1417                                  ; Now, everything is "up and running"... patch kaboom for more
  1418                                  ; verbosity and using the full screen system
  1419                                  ;
  1420                                  		; E9 = JMP NEAR
  1421 00000414 66C706[2A01]E9BD0E-     		mov dword [kaboom.patch],0e9h+((kaboom2-(kaboom.patch+3)) << 8)
  1422 0000041C 00                 
  1423                                  
  1424                                  ;
  1425                                  ; Compute some parameters that depend on cluster size
  1426                                  ;
  1427 0000041D 6631C0                  		xor eax,eax
  1428 00000420 99                      		cwd				; DX <- 0
  1429 00000421 42                      		inc dx				; DX:AX <- 64K
  1430 00000422 F7367055                		div word [ClustSize]
  1431 00000426 66A36C55                		mov [ClustPerMoby],eax		; Clusters/64K
  1432                                  
  1433                                  ;
  1434                                  ; Now we're all set to start with our *real* business.	First load the
  1435                                  ; configuration file (if any) and parse it.
  1436                                  ;
  1437                                  ; In previous versions I avoided using 32-bit registers because of a
  1438                                  ; rumour some BIOSes clobbered the upper half of 32-bit registers at
  1439                                  ; random.  I figure, though, that if there are any of those still left
  1440                                  ; they probably won't be trying to install Linux on them...
  1441                                  ;
  1442                                  ; The code is still ripe with 16-bitisms, though.  Not worth the hassle
  1443                                  ; to take'm out.  In fact, we may want to put them back if we're going
  1444                                  ; to boot ELKS at some point.
  1445                                  ;
  1446 0000042A BE[8420]                		mov si,linuxauto_cmd		; Default command: "linux auto"
  1447 0000042D BF[9D21]                		mov di,default_cmd
  1448 00000430 B90B00                                  mov cx,linuxauto_len
  1449 00000433 F3A4                    		rep movsb
  1450                                  
  1451 00000435 BF0053                  		mov di,KbdMap			; Default keymap 1:1
  1452 00000438 30C0                    		xor al,al
  1453 0000043A FEC5                    		inc ch				; CX <- 256
  1454 0000043C AA                      mkkeymap:	stosb
  1455 0000043D FEC0                    		inc al
  1456 0000043F E2FB                    		loop mkkeymap
  1457                                  
  1458                                  ;
  1459                                  ; Load configuration file
  1460                                  ;
  1461 00000441 BF[8B1F]                		mov di,syslinux_cfg
  1462 00000444 E8590C                  		call open
  1463 00000447 7403                    		jz no_config_file
  1464                                  
  1465                                  ;
  1466                                  ; Now we have the config file open.  Parse the config file and
  1467                                  ; run the user interface.
  1468                                  ;
  1469                                  %include "ui.inc"
  1470                              <1> ;; $Id: ui.inc,v 1.1 2002/10/24 00:59:08 hpa Exp $
  1471                              <1> ;; -----------------------------------------------------------------------
  1472                              <1> ;;   
  1473                              <1> ;;   Copyright 1994-2002 H. Peter Anvin - All Rights Reserved
  1474                              <1> ;;
  1475                              <1> ;;   This program is free software; you can redistribute it and/or modify
  1476                              <1> ;;   it under the terms of the GNU General Public License as published by
  1477                              <1> ;;   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
  1478                              <1> ;;   Bostom MA 02111-1307, USA; either version 2 of the License, or
  1479                              <1> ;;   (at your option) any later version; incorporated herein by reference.
  1480                              <1> ;;
  1481                              <1> ;; -----------------------------------------------------------------------
  1482                              <1> 
  1483                              <1> ;
  1484                              <1> ; This file should be entered with the config file open (for getc)
  1485                              <1> ;
  1486 00000449 E8D711              <1> 		call parse_config		; Parse configuration file
  1487                              <1> no_config_file:
  1488                              <1> ;
  1489                              <1> ; Check whether or not we are supposed to display the boot prompt.
  1490                              <1> ;
  1491                              <1> check_for_key:
  1492 0000044C 833E[7A20]00        <1> 		cmp word [ForcePrompt],byte 0	; Force prompt?
  1493 00000451 7509                <1> 		jnz enter_command
  1494 00000453 F606C0555B          <1> 		test byte [KbdFlags],5Bh	; Caps, Scroll, Shift, Alt
  1495 00000458 0F84FA00            <1> 		jz auto_boot		; If neither, default boot
  1496                              <1> 
  1497                              <1> enter_command:
  1498 0000045C BE[BE1C]            <1> 		mov si,boot_prompt
  1499 0000045F E82110              <1> 		call cwritestr
  1500                              <1> 
  1501 00000462 C606C35500          <1> 		mov byte [FuncFlag],0		; <Ctrl-F> not pressed
  1502 00000467 BF[9C20]            <1> 		mov di,command_line
  1503                              <1> ;
  1504                              <1> ; get the very first character -- we can either time
  1505                              <1> ; out, or receive a character press at this time.  Some dorky BIOSes stuff
  1506                              <1> ; a return in the buffer on bootup, so wipe the keyboard buffer first.
  1507                              <1> ;
  1508 0000046A B401                <1> clear_buffer:	mov ah,1			; Check for pending char
  1509 0000046C CD16                <1> 		int 16h
  1510 0000046E 7406                <1> 		jz get_char_time
  1511 00000470 31C0                <1> 		xor ax,ax			; Get char
  1512 00000472 CD16                <1> 		int 16h
  1513 00000474 EBF4                <1> 		jmp short clear_buffer
  1514                              <1> get_char_time:	
  1515 00000476 E82017              <1> 		call vgashowcursor
  1516 00000479 8B0E[7220]          <1> 		mov cx,[KbdTimeOut]
  1517 0000047D 21C9                <1> 		and cx,cx
  1518 0000047F 741C                <1> 		jz get_char			; Timeout == 0 -> no timeout
  1519 00000481 41                  <1> 		inc cx				; The first loop will happen
  1520                              <1> 						; immediately as we don't
  1521                              <1> 						; know the appropriate DX value
  1522 00000482 51                  <1> time_loop:	push cx
  1523 00000483 52                  <1> tick_loop:	push dx
  1524 00000484 E89A0F              <1> 		call pollchar
  1525 00000487 7512                <1> 		jnz get_char_pop
  1526 00000489 8B166C04            <1> 		mov dx,[BIOS_timer]		; Get time "of day"
  1527 0000048D 58                  <1> 		pop ax
  1528 0000048E 39C2                <1> 		cmp dx,ax			; Has the timer advanced?
  1529 00000490 74F1                <1> 		je tick_loop
  1530 00000492 59                  <1> 		pop cx
  1531 00000493 E2ED                <1> 		loop time_loop			; If so, decrement counter
  1532 00000495 E80717              <1> 		call vgahidecursor
  1533 00000498 E9C900              <1> 		jmp command_done		; Timeout!
  1534                              <1> 
  1535 0000049B 6658                <1> get_char_pop:	pop eax				; Clear stack
  1536                              <1> get_char:
  1537 0000049D E8F916              <1> 		call vgashowcursor
  1538 000004A0 E8A80F              <1> 		call getchar
  1539 000004A3 E8F916              <1> 		call vgahidecursor
  1540 000004A6 20C0                <1> 		and al,al
  1541 000004A8 7465                <1> 		jz func_key
  1542                              <1> 
  1543 000004AA 3C7F                <1> got_ascii:	cmp al,7Fh			; <DEL> == <BS>
  1544 000004AC 7443                <1> 		je backspace
  1545 000004AE 3C20                <1> 		cmp al,' '			; ASCII?
  1546 000004B0 722A                <1> 		jb not_ascii
  1547 000004B2 7706                <1> 		ja enter_char
  1548 000004B4 81FF[9C20]          <1> 		cmp di,command_line		; Space must not be first
  1549 000004B8 74E3                <1> 		je short get_char
  1550 000004BA F606C35501          <1> enter_char:	test byte [FuncFlag],1
  1551 000004BF 740F                <1> 		jz .not_ctrl_f
  1552 000004C1 C606C35500          <1> 		mov byte [FuncFlag],0
  1553 000004C6 3C30                <1> 		cmp al,'0'
  1554 000004C8 7206                <1> 		jb .not_ctrl_f
  1555 000004CA 743B                <1> 		je ctrl_f_0
  1556 000004CC 3C39                <1> 		cmp al,'9'
  1557 000004CE 7639                <1> 		jbe ctrl_f
  1558 000004D0 81FF[9B21]          <1> .not_ctrl_f:	cmp di,max_cmd_len+command_line ; Check there's space
  1559 000004D4 73C7                <1> 		jnb short get_char
  1560 000004D6 AA                  <1> 		stosb				; Save it
  1561 000004D7 E8FD0A              <1> 		call writechr			; Echo to screen
  1562 000004DA EBC1                <1> 		jmp short get_char
  1563 000004DC C606C35500          <1> not_ascii:	mov byte [FuncFlag],0
  1564 000004E1 3C0D                <1> 		cmp al,0Dh			; Enter
  1565 000004E3 747F                <1> 		je command_done
  1566 000004E5 3C06                <1> 		cmp al,06h			; <Ctrl-F>
  1567 000004E7 7417                <1> 		je set_func_flag
  1568 000004E9 3C16                <1> 		cmp al,16h			; <Ctrl-V>
  1569 000004EB 7448                <1> 		je print_version
  1570 000004ED 3C08                <1> 		cmp al,08h			; Backspace
  1571 000004EF 75AC                <1> 		jne get_char
  1572 000004F1 81FF[9C20]          <1> backspace:	cmp di,command_line		; Make sure there is anything
  1573 000004F5 74A6                <1> 		je get_char			; to erase
  1574 000004F7 4F                  <1> 		dec di				; Unstore one character
  1575 000004F8 BE[C51C]            <1> 		mov si,wipe_char		; and erase it from the screen
  1576 000004FB E8850F              <1> 		call cwritestr
  1577 000004FE EB05                <1> 		jmp short get_char_2
  1578                              <1> 
  1579                              <1> set_func_flag:
  1580 00000500 C606C35501          <1> 		mov byte [FuncFlag],1
  1581                              <1> get_char_2:
  1582 00000505 EB96                <1> 		jmp short get_char
  1583                              <1> 
  1584 00000507 040A                <1> ctrl_f_0:	add al,10			; <Ctrl-F>0 == F10
  1585 00000509 2C31                <1> ctrl_f:		sub al,'1'
  1586 0000050B 30E4                <1> 		xor ah,ah
  1587 0000050D EB0A                <1> 		jmp short show_help
  1588                              <1> 
  1589                              <1> func_key:
  1590                              <1> 		; AL = 0 if we get here
  1591 0000050F 86C4                <1> 		xchg al,ah
  1592 00000511 3C44                <1> 		cmp al,68			; F10
  1593 00000513 77F0                <1> 		ja short get_char_2
  1594 00000515 2C3B                <1> 		sub al,59			; F1
  1595 00000517 72EC                <1> 		jb short get_char_2
  1596                              <1> show_help:	; AX = func key # (0 = F1, 9 = F10)
  1597 00000519 57                  <1> 		push di				; Save end-of-cmdline pointer
  1598 0000051A C1E004              <1> 		shl ax,FILENAME_MAX_LG2		; Convert to pointer
  1599 0000051D 050054              <1> 		add ax,FKeyName
  1600 00000520 97                  <1> 		xchg di,ax
  1601 00000521 803D20              <1> 		cmp byte [di],NULLFILE
  1602 00000524 742D                <1> 		je short fk_nofile		; Undefined F-key
  1603 00000526 E8360A              <1> 		call searchdir
  1604 00000529 7428                <1> 		jz short fk_nofile		; File not found
  1605 0000052B 56                  <1> 		push si
  1606 0000052C E8510F              <1> 		call crlf
  1607 0000052F 5E                  <1> 		pop si
  1608 00000530 E8190D              <1> 		call get_msg_file
  1609 00000533 EB0D                <1> 		jmp short fk_wrcmd
  1610                              <1> 
  1611                              <1> print_version:
  1612 00000535 57                  <1> 		push di				; Command line write pointer
  1613 00000536 BE[0002]            <1> 		mov si,syslinux_banner
  1614 00000539 E8470F              <1> 		call cwritestr
  1615 0000053C BE[941C]            <1> 		mov si,copyright_str
  1616 0000053F E8410F              <1> 		call cwritestr
  1617                              <1> 
  1618                              <1> 		; ... fall through ...
  1619                              <1> 
  1620                              <1> 		; Write the boot prompt and command line again and
  1621                              <1> 		; wait for input.  Note that this expects the cursor
  1622                              <1> 		; to already have been CRLF'd, and that the old value
  1623                              <1> 		; of DI (the command line write pointer) is on the stack.
  1624                              <1> fk_wrcmd:
  1625 00000542 BE[BE1C]            <1> 		mov si,boot_prompt
  1626 00000545 E83B0F              <1> 		call cwritestr
  1627 00000548 5F                  <1> 		pop di				; Command line write pointer
  1628 00000549 57                  <1> 		push di
  1629 0000054A C60500              <1> 		mov byte [di],0			; Null-terminate command line
  1630 0000054D BE[9C20]            <1> 		mov si,command_line
  1631 00000550 E8300F              <1> 		call cwritestr			; Write command line so far
  1632 00000553 5F                  <1> fk_nofile:	pop di
  1633 00000554 EBAF                <1> 		jmp short get_char_2
  1634                              <1> auto_boot:
  1635 00000556 BE[9D21]            <1> 		mov si,default_cmd
  1636 00000559 BF[9C20]            <1> 		mov di,command_line
  1637 0000055C B94000              <1> 		mov cx,(max_cmd_len+4) >> 2
  1638 0000055F F366A5              <1> 		rep movsd
  1639 00000562 EB0C                <1> 		jmp short load_kernel
  1640                              <1> command_done:
  1641 00000564 E8190F              <1> 		call crlf
  1642 00000567 81FF[9C20]          <1> 		cmp di,command_line		; Did we just hit return?
  1643 0000056B 74E9                <1> 		je auto_boot
  1644 0000056D 30C0                <1> 		xor al,al			; Store a final null
  1645 0000056F AA                  <1> 		stosb
  1646                              <1> 
  1647                              <1> load_kernel:					; Load the kernel now
  1648                              <1> ;
  1649                              <1> ; First we need to mangle the kernel name the way DOS would...
  1650                              <1> ;
  1651 00000570 BE[9C20]            <1> 		mov si,command_line
  1652 00000573 BF7455              <1>                 mov di,KernelName
  1653 00000576 56                  <1>                 push si
  1654 00000577 57                  <1>                 push di
  1655 00000578 E87F0A              <1> 		call mangle_name
  1656 0000057B 5F                  <1> 		pop di
  1657 0000057C 5E                  <1>                 pop si
  1658                              <1> ;
  1659                              <1> ; Fast-forward to first option (we start over from the beginning, since
  1660                              <1> ; mangle_name doesn't necessarily return a consistent ending state.)
  1661                              <1> ;
  1662 0000057D AC                  <1> clin_non_wsp:   lodsb
  1663 0000057E 3C20                <1>                 cmp al,' '
  1664 00000580 77FB                <1>                 ja clin_non_wsp
  1665 00000582 20C0                <1> clin_is_wsp:    and al,al
  1666 00000584 7405                <1>                 jz clin_opt_ptr
  1667 00000586 AC                  <1>                 lodsb
  1668 00000587 3C20                <1>                 cmp al,' '
  1669 00000589 76F7                <1>                 jbe clin_is_wsp
  1670 0000058B 4E                  <1> clin_opt_ptr:   dec si                          ; Point to first nonblank
  1671 0000058C 89369C55            <1>                 mov [CmdOptPtr],si		; Save ptr to first option
  1672                              <1> ;
  1673                              <1> ; Now check if it is a "virtual kernel"
  1674                              <1> ;
  1675 00000590 8B0E[7820]          <1> 		mov cx,[VKernelCtr]
  1676 00000594 1E                  <1> 		push ds
  1677 00000595 680040              <1> 		push word vk_seg
  1678 00000598 1F                  <1> 		pop ds
  1679 00000599 83F900              <1> 		cmp cx,byte 0
  1680 0000059C 7411                <1> 		je not_vk
  1681 0000059E 31F6                <1> 		xor si,si			; Point to first vkernel
  1682 000005A0 60                  <1> vk_check:	pusha
  1683 000005A1 B90B00              <1> 		mov cx,FILENAME_MAX
  1684 000005A4 F3A6                <1> 		repe cmpsb			; Is this it?
  1685 000005A6 7479                <1> 		je vk_found
  1686 000005A8 61                  <1> 		popa
  1687 000005A9 81C60002            <1> 		add si,vk_size
  1688 000005AD E2F1                <1> 		loop vk_check
  1689 000005AF 1F                  <1> not_vk:		pop ds
  1690                              <1> ;
  1691                              <1> ; Not a "virtual kernel" - check that's OK and construct the command line
  1692                              <1> ;
  1693 000005B0 833E[7C20]00        <1>                 cmp word [AllowImplicit],byte 0
  1694 000005B5 745F                <1>                 je bad_implicit
  1695 000005B7 06                  <1>                 push es
  1696 000005B8 56                  <1>                 push si
  1697 000005B9 57                  <1>                 push di
  1698 000005BA BF0070              <1>                 mov di,real_mode_seg
  1699 000005BD 8EC7                <1>                 mov es,di
  1700 000005BF BE0052              <1>                 mov si,AppendBuf
  1701 000005C2 BF0090              <1>                 mov di,cmd_line_here
  1702 000005C5 8B0E[7020]          <1>                 mov cx,[AppendLen]
  1703 000005C9 F3A4                <1>                 rep movsb
  1704 000005CB 893E[7420]          <1>                 mov [CmdLinePtr],di
  1705 000005CF 5F                  <1>                 pop di
  1706 000005D0 5E                  <1>                 pop si
  1707 000005D1 07                  <1>                 pop es
  1708                              <1> ;
  1709                              <1> ; Find the kernel on disk
  1710                              <1> ;
  1711 000005D2 C6067F5500          <1> get_kernel:     mov byte [KernelName+FILENAME_MAX],0	; Zero-terminate filename/extension
  1712                              <1> %if IS_SYSLINUX		; SYSLINUX has to deal with DOS mangled names...
  1713 000005D7 66A17C55            <1> 		mov eax,[KernelName+8]		; Save initial extension
  1714 000005DB 66A3[6820]          <1> 		mov [exten_table_end],eax	; Last case == initial ext.
  1715                              <1> %else
  1716                              <1> 		mov di,KernelName
  1717                              <1> 		xor al,al
  1718                              <1> 		mov cx,FILENAME_MAX-5		; Need 4 chars + null
  1719                              <1> 		repne scasb			; Scan for final null
  1720                              <1> 		jne .no_skip
  1721                              <1> 		dec di				; Point to final null 
  1722                              <1> .no_skip:	mov [KernelExtPtr],di
  1723                              <1> %endif
  1724 000005DF BB[5820]            <1> 		mov bx,exten_table
  1725 000005E2 53                  <1> .search_loop:	push bx
  1726 000005E3 BF7455              <1>                 mov di,KernelName	      	; Search on disk
  1727 000005E6 E87609              <1>                 call searchdir
  1728 000005E9 5B                  <1> 		pop bx
  1729 000005EA 756E                <1>                 jnz kernel_good
  1730 000005EC 668B07              <1> 		mov eax,[bx]			; Try a different extension
  1731                              <1> %if IS_SYSLINUX
  1732 000005EF 66A37C55            <1> 		mov [KernelName+8],eax
  1733                              <1> %else
  1734                              <1> 		mov si,[KernelExtPtr]
  1735                              <1> 		mov [si],eax
  1736                              <1> 		mov byte [si+4],0
  1737                              <1> %endif
  1738 000005F3 83C304              <1> 		add bx,byte 4
  1739 000005F6 81FB[6820]          <1> 		cmp bx,exten_table_end
  1740 000005FA 76E6                <1> 		jna .search_loop		; allow == case (final case)
  1741                              <1> bad_kernel:     
  1742 000005FC BE7455              <1> 		mov si,KernelName
  1743 000005FF BFDB55              <1>                 mov di,KernelCName
  1744 00000602 57                  <1> 		push di
  1745 00000603 E84F0A              <1>                 call unmangle_name              ; Get human form
  1746 00000606 BE[C91C]            <1> 		mov si,err_notfound		; Complain about missing kernel
  1747 00000609 E8770E              <1> 		call cwritestr
  1748 0000060C 5E                  <1> 		pop si				; KernelCName
  1749 0000060D E8730E              <1>                 call cwritestr
  1750 00000610 BE[851F]            <1>                 mov si,crlf_msg
  1751 00000613 E93409              <1>                 jmp abort_load                  ; Ask user for clue
  1752                              <1> ;
  1753                              <1> ; bad_implicit: The user entered a nonvirtual kernel name, with "implicit 0"
  1754                              <1> ;
  1755 00000616 BE7455              <1> bad_implicit:   mov si,KernelName		; For the error message
  1756 00000619 BFDB55              <1>                 mov di,KernelCName
  1757 0000061C E8360A              <1>                 call unmangle_name
  1758 0000061F EBDB                <1>                 jmp short bad_kernel
  1759                              <1> ;
  1760                              <1> ; vk_found: We *are* using a "virtual kernel"
  1761                              <1> ;
  1762 00000621 61                  <1> vk_found:	popa
  1763 00000622 57                  <1> 		push di
  1764 00000623 BF0050              <1> 		mov di,VKernelBuf
  1765 00000626 B98000              <1> 		mov cx,vk_size >> 2
  1766 00000629 F366A5              <1> 		rep movsd
  1767 0000062C 06                  <1> 		push es				; Restore old DS
  1768 0000062D 1F                  <1> 		pop ds
  1769 0000062E 06                  <1> 		push es
  1770 0000062F 680070              <1> 		push word real_mode_seg
  1771 00000632 07                  <1> 		pop es
  1772 00000633 BF0090              <1> 		mov di,cmd_line_here
  1773 00000636 BE1850              <1> 		mov si,VKernelBuf+vk_append
  1774 00000639 8B0E1650            <1> 		mov cx,[VKernelBuf+vk_appendlen]
  1775 0000063D F3A4                <1> 		rep movsb
  1776 0000063F 893E[7420]          <1> 		mov [CmdLinePtr],di		; Where to add rest of cmd
  1777 00000643 07                  <1> 		pop es
  1778 00000644 5F                  <1>                 pop di                          ; DI -> KernelName
  1779 00000645 57                  <1> 		push di	
  1780 00000646 BE0B50              <1> 		mov si,VKernelBuf+vk_rname
  1781 00000649 B90B00              <1> 		mov cx,FILENAME_MAX		; We need ECX == CX later
  1782 0000064C F3A4                <1> 		rep movsb
  1783 0000064E 5F                  <1> 		pop di
  1784                              <1> %if IS_PXELINUX
  1785                              <1> 		mov al,[VKernelBuf+vk_ipappend]
  1786                              <1> 		mov [IPAppend],al
  1787                              <1> %endif
  1788 0000064F 31DB                <1> 		xor bx,bx			; Try only one version
  1789                              <1> 
  1790                              <1> %if IS_SYSLINUX
  1791 00000651 E97EFF              <1> 		jmp get_kernel
  1792                              <1> %else
  1793                              <1> 		; Is this a "localboot" pseudo-kernel?
  1794                              <1> 		cmp byte [VKernelBuf+vk_rname], 0
  1795                              <1> 		jne get_kernel		; No, it's real, go get it
  1796                              <1> 
  1797                              <1> 		mov ax, [VKernelBuf+vk_rname+1]
  1798                              <1> 		jmp local_boot
  1799                              <1> %endif
  1800                              <1> 
  1801                              <1> ;
  1802                              <1> ; kernel_corrupt: Called if the kernel file does not seem healthy
  1803                              <1> ;
  1804 00000654 BE[E71C]            <1> kernel_corrupt: mov si,err_notkernel
  1805 00000657 E9F008              <1>                 jmp abort_load
  1806                              <1> ;
  1807                              <1> ; This is it!  We have a name (and location on the disk)... let's load
  1808                              <1> ; that sucker!!  First we have to decide what kind of file this is; base
  1809                              <1> ; that decision on the file extension.  The following extensions are
  1810                              <1> ; recognized; case insensitive:
  1811                              <1> ;
  1812                              <1> ; .com 	- COMBOOT image
  1813                              <1> ; .cbt	- COMBOOT image
  1814                              <1> ; .c32  - COM32 image
  1815                              <1> ; .bs	- Boot sector
  1816                              <1> ; .0	- PXE bootstrap program (PXELINUX only)
  1817                              <1> ; .bin  - Boot sector
  1818                              <1> ; .bss	- Boot sector, but transfer over DOS superblock (SYSLINUX only)
  1819                              <1> ; .img  - Floppy image (ISOLINUX only)
  1820                              <1> ;
  1821                              <1> ; Anything else is assumed to be a Linux kernel.
  1822                              <1> ;
  1823                              <1> kernel_good:
  1824 0000065A 60                  <1> 		pusha
  1825 0000065B BE7455              <1> 		mov si,KernelName
  1826 0000065E BFDB55              <1> 		mov di,KernelCName
  1827 00000661 E8F109              <1> 		call unmangle_name
  1828 00000664 81EFDB55            <1> 		sub di,KernelCName
  1829 00000668 893E9E55            <1> 		mov [KernelCNameLen],di
  1830 0000066C 61                  <1> 		popa
  1831                              <1> 		
  1832                              <1> %if IS_SYSLINUX
  1833 0000066D 668B0E7B55          <1> 		mov ecx,[KernelName+7]
  1834 00000672 B12E                <1> 		mov cl,'.'
  1835                              <1> %else
  1836                              <1> 		push di
  1837                              <1> 		push ax
  1838                              <1> 		mov di,KernelName
  1839                              <1> 		xor al,al
  1840                              <1> 		mov cx,FILENAME_MAX
  1841                              <1> 		repne scasb
  1842                              <1> 		jne .one_step
  1843                              <1> 		dec di
  1844                              <1> .one_step:	mov ecx,[di-4]			; 4 bytes before end
  1845                              <1> 		pop ax
  1846                              <1> 		pop di
  1847                              <1> %endif
  1848                              <1> 
  1849                              <1> ;
  1850                              <1> ; At this point, DX:AX contains the size of the kernel, and SI contains
  1851                              <1> ; the file handle/cluster pointer.
  1852                              <1> ;
  1853 00000674 6681C900202020      <1> 		or ecx,20202000h		; Force lower case
  1854                              <1> 
  1855 0000067B 6681F92E636F6D      <1> 		cmp ecx,'.com'
  1856 00000682 0F84D903            <1> 		je is_comboot_image
  1857 00000686 6681F92E636274      <1> 		cmp ecx,'.cbt'
  1858 0000068D 0F84CE03            <1> 		je is_comboot_image
  1859 00000691 6681F92E633332      <1> 		cmp ecx,'.c32'
  1860 00000698 0F846606            <1> 		je is_com32_image
  1861                              <1> %if IS_ISOLINUX
  1862                              <1> 		cmp ecx,'.img'
  1863                              <1> 		je is_disk_image
  1864                              <1> %endif
  1865 0000069C 6681F92E627373      <1> 		cmp ecx,'.bss'
  1866 000006A3 0F841908            <1> 		je is_bss_sector
  1867 000006A7 6681F92E62696E      <1> 		cmp ecx,'.bin'
  1868 000006AE 0F840A08            <1> 		je is_bootsector
  1869                              <1> %if IS_SYSLINUX
  1870 000006B2 6681F92E627320      <1> 		cmp ecx,'.bs '
  1871 000006B9 0F84FF07            <1> 		je is_bootsector
  1872 000006BD 6681F92E302020      <1> 		cmp ecx,'.0  '
  1873 000006C4 0F84F407            <1> 		je is_bootsector
  1874                              <1> %else
  1875                              <1> 		shr ecx,8
  1876                              <1> 		cmp ecx,'.bs'
  1877                              <1> 		je is_bootsector
  1878                              <1> 		shr ecx,8
  1879                              <1> 		cmp cx,'.0'
  1880                              <1> 		je is_bootsector
  1881                              <1> %endif
  1882                              <1> 		; Otherwise Linux kernel
  1883                              <1> 
  1884                                  
  1885                                  ;
  1886                                  ; Linux kernel loading code is common.
  1887                                  ;
  1888                                  %include "runkernel.inc"
  1889                              <1> ;; $Id: runkernel.inc,v 1.10 2002/06/17 01:08:24 hpa Exp $
  1890                              <1> ;; -----------------------------------------------------------------------
  1891                              <1> ;;   
  1892                              <1> ;;   Copyright 1994-2002 H. Peter Anvin - All Rights Reserved
  1893                              <1> ;;
  1894                              <1> ;;   This program is free software; you can redistribute it and/or modify
  1895                              <1> ;;   it under the terms of the GNU General Public License as published by
  1896                              <1> ;;   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
  1897                              <1> ;;   Bostom MA 02111-1307, USA; either version 2 of the License, or
  1898                              <1> ;;   (at your option) any later version; incorporated herein by reference.
  1899                              <1> ;;
  1900                              <1> ;; -----------------------------------------------------------------------
  1901                              <1> 
  1902                              <1> ;;
  1903                              <1> ;; runkernel.inc
  1904                              <1> ;; 
  1905                              <1> ;; Common code for running a Linux kernel
  1906                              <1> ;;
  1907                              <1> 
  1908                              <1> ;
  1909                              <1> ; Hook macros, that may or may not be defined
  1910                              <1> ;
  1911                              <1> %ifndef HAVE_SPECIAL_APPEND
  1912                              <1> %macro SPECIAL_APPEND 0
  1913                              <1> %endmacro
  1914                              <1> %endif
  1915                              <1> 
  1916                              <1> %ifndef HAVE_UNLOAD_PREP
  1917                              <1> %macro UNLOAD_PREP 0
  1918                              <1> %endmacro
  1919                              <1> %endif
  1920                              <1> 
  1921                              <1> ;
  1922                              <1> ; A Linux kernel consists of three parts: boot sector, setup code, and
  1923                              <1> ; kernel code.	The boot sector is never executed when using an external
  1924                              <1> ; booting utility, but it contains some status bytes that are necessary.
  1925                              <1> ;
  1926                              <1> ; First check that our kernel is at least 1K and less than 8M (if it is
  1927                              <1> ; more than 8M, we need to change the logic for loading it anyway...)
  1928                              <1> ;
  1929                              <1> ; We used to require the kernel to be 64K or larger, but it has gotten
  1930                              <1> ; popular to use the Linux kernel format for other things, which may
  1931                              <1> ; not be so large.
  1932                              <1> ;
  1933                              <1> is_linux_kernel:
  1934 000006C8 81FA8000            <1>                 cmp dx,80h			; 8 megs
  1935 000006CC 7786                <1> 		ja kernel_corrupt
  1936 000006CE 21D2                <1> 		and dx,dx
  1937 000006D0 7507                <1> 		jnz kernel_sane
  1938 000006D2 3D0004              <1> 		cmp ax,1024			; Bootsect + 1 setup sect
  1939 000006D5 0F827BFF            <1> 		jb kernel_corrupt
  1940 000006D9 50                  <1> kernel_sane:	push ax
  1941 000006DA 52                  <1> 		push dx
  1942 000006DB 56                  <1> 		push si
  1943 000006DC BE[701F]            <1> 		mov si,loading_msg
  1944 000006DF E8A10D              <1>                 call cwritestr
  1945                              <1> ;
  1946                              <1> ; Now start transferring the kernel
  1947                              <1> ;
  1948 000006E2 680070              <1> 		push word real_mode_seg
  1949 000006E5 07                  <1> 		pop es
  1950                              <1> 
  1951 000006E6 660FB7C0            <1> 		movzx eax,ax			; Fix this by using a 32-bit
  1952 000006EA 66C1E210            <1> 		shl edx,16			; register for the kernel size
  1953 000006EE 6609D0              <1> 		or eax,edx
  1954 000006F1 66A36055            <1> 		mov [KernelSize],eax
  1955 000006F5 6631D2              <1> 		xor edx,edx
  1956 000006F8 66F7367055          <1> 		div dword [ClustSize]		; # of clusters total
  1957                              <1> 		; Round up...
  1958 000006FD 6683C2FF            <1> 		add edx,byte -1			; Sets CF if EDX >= 1
  1959 00000701 6683D000            <1> 		adc eax,byte 0			; Add 1 to EAX if CF set
  1960 00000705 66A39455            <1>                 mov [KernelClust],eax
  1961                              <1> 
  1962                              <1> ;
  1963                              <1> ; Now, if we transfer these straight, we'll hit 64K boundaries.	 Hence we
  1964                              <1> ; have to see if we're loading more than 64K, and if so, load it step by
  1965                              <1> ; step.
  1966                              <1> ;
  1967                              <1> 
  1968                              <1> ;
  1969                              <1> ; Start by loading the bootsector/setup code, to see if we need to
  1970                              <1> ; do something funky.  It should fit in the first 32K (loading 64K won't
  1971                              <1> ; work since we might have funny stuff up near the end of memory).
  1972                              <1> ; If we have larger than 32K clusters, yes, we're hosed.
  1973                              <1> ;
  1974 00000709 E82A08              <1> 		call abort_check		; Check for abort key
  1975 0000070C 668B0E6C55          <1> 		mov ecx,[ClustPerMoby]
  1976 00000711 66D1E9              <1> 		shr ecx,1			; Half a moby
  1977 00000714 663B0E9455          <1> 		cmp ecx,[KernelClust]
  1978 00000719 7605                <1> 		jna .normalkernel
  1979 0000071B 668B0E9455          <1> 		mov ecx,[KernelClust]
  1980                              <1> .normalkernel:
  1981 00000720 66290E9455          <1> 		sub [KernelClust],ecx
  1982 00000725 31DB                <1> 		xor bx,bx
  1983 00000727 5E                  <1>                 pop si                          ; Cluster pointer on stack
  1984 00000728 E8EAFB              <1> 		call getfssec
  1985 0000072B 26813EFE0155AA      <1>                 cmp word [es:bs_bootsign],0AA55h
  1986 00000732 0F851EFF            <1> 		jne kernel_corrupt		; Boot sec signature missing
  1987                              <1> 
  1988                              <1> ;
  1989                              <1> ; Save the cluster pointer for later...
  1990                              <1> ;
  1991 00000736 56                  <1> 		push si
  1992                              <1> ;
  1993                              <1> ; Get the BIOS' idea of what the size of high memory is.
  1994                              <1> ;
  1995 00000737 E88F14              <1> 		call highmemsize
  1996                              <1> ;
  1997                              <1> ; Construct the command line (append options have already been copied)
  1998                              <1> ;
  1999                              <1> construct_cmdline:
  2000 0000073A 8B3E[7420]          <1> 		mov di,[CmdLinePtr]
  2001 0000073E BE[8F20]            <1>                 mov si,boot_image        	; BOOT_IMAGE=
  2002 00000741 B90B00              <1>                 mov cx,boot_image_len
  2003 00000744 F3A4                <1>                 rep movsb
  2004 00000746 BEDB55              <1>                 mov si,KernelCName       	; Unmangled kernel name
  2005 00000749 8B0E9E55            <1>                 mov cx,[KernelCNameLen]
  2006 0000074D F3A4                <1>                 rep movsb
  2007 0000074F B020                <1>                 mov al,' '                      ; Space
  2008 00000751 AA                  <1>                 stosb
  2009                              <1> 
  2010                              <1> 		SPECIAL_APPEND			; Module-specific hook
  2011                              <1> 
  2012 00000752 8B369C55            <1>                 mov si,[CmdOptPtr]              ; Options from user input
  2013 00000756 B98100              <1> 		mov cx,(kern_cmd_len+3) >> 2
  2014 00000759 F366A5              <1> 		rep movsd
  2015                              <1> 
  2016                              <1> ;
  2017                              <1> ; Scan through the command line for anything that looks like we might be
  2018                              <1> ; interested in.  The original version of this code automatically assumed
  2019                              <1> ; the first option was BOOT_IMAGE=, but that is no longer certain.
  2020                              <1> ;
  2021 0000075C BE0090              <1> 		mov si,cmd_line_here
  2022 0000075F C606[7620]00        <1>                 mov byte [initrd_flag],0
  2023 00000764 06                  <1>                 push es				; Set DS <- real_mode_seg
  2024 00000765 1F                  <1>                 pop ds
  2025 00000766 AC                  <1> get_next_opt:   lodsb
  2026 00000767 20C0                <1> 		and al,al
  2027 00000769 0F848100            <1> 		jz cmdline_end
  2028 0000076D 3C20                <1> 		cmp al,' '
  2029 0000076F 76F5                <1> 		jbe get_next_opt
  2030 00000771 4E                  <1> 		dec si
  2031 00000772 668B04              <1>                 mov eax,[si]
  2032 00000775 663D7667613D        <1>                 cmp eax,'vga='
  2033 0000077B 7432                <1> 		je is_vga_cmd
  2034 0000077D 663D6D656D3D        <1>                 cmp eax,'mem='
  2035 00000783 7459                <1> 		je is_mem_cmd
  2036                              <1> %if IS_PXELINUX
  2037                              <1> 		cmp eax,'keep'			; Is it "keeppxe"?
  2038                              <1> 		jne .notkeep
  2039                              <1> 		cmp dword [si+3],'ppxe'
  2040                              <1> 		jne .notkeep
  2041                              <1> 		cmp byte [si+7],' '		; Must be whitespace or EOS
  2042                              <1> 		ja .notkeep
  2043                              <1> 		or byte [cs:KeepPXE],1
  2044                              <1> .notkeep:
  2045                              <1> %endif
  2046 00000785 06                  <1>                 push es                         ; Save ES -> real_mode_seg
  2047 00000786 0E                  <1>                 push cs
  2048 00000787 07                  <1>                 pop es                          ; Set ES <- normal DS
  2049 00000788 BF[961F]            <1>                 mov di,initrd_cmd
  2050 0000078B B90700              <1> 		mov cx,initrd_cmd_len
  2051 0000078E F3A6                <1> 		repe cmpsb
  2052 00000790 7514                <1>                 jne not_initrd
  2053                              <1> 
  2054 00000792 BFD055              <1> 		mov di,InitRD
  2055 00000795 56                  <1>                 push si                         ; mangle_dir mangles si
  2056 00000796 E86108              <1>                 call mangle_name                ; Mangle ramdisk name
  2057 00000799 5E                  <1>                 pop si
  2058 0000079A 26803ED05520        <1> 		cmp byte [es:InitRD],NULLFILE	; Null filename?
  2059 000007A0 260F9706[7620]      <1>                 seta byte [es:initrd_flag]	; Set flag if not
  2060 000007A6 07                  <1> not_initrd:	pop es                          ; Restore ES -> real_mode_seg
  2061 000007A7 AC                  <1> skip_this_opt:  lodsb                           ; Load from command line
  2062 000007A8 3C20                <1>                 cmp al,' '
  2063 000007AA 77FB                <1>                 ja skip_this_opt
  2064 000007AC 4E                  <1>                 dec si
  2065 000007AD EBB7                <1>                 jmp short get_next_opt
  2066                              <1> is_vga_cmd:
  2067 000007AF 83C604              <1>                 add si,4
  2068 000007B2 668B44FF            <1>                 mov eax,[si-1]
  2069 000007B6 BBFFFF              <1>                 mov bx,-1
  2070 000007B9 663D3D6E6F72        <1>                 cmp eax,'=nor'			; vga=normal
  2071 000007BF 7417                <1>                 je vc0
  2072 000007C1 4B                  <1> 		dec bx				; bx <- -2
  2073 000007C2 663D3D657874        <1>                 cmp eax,'=ext'			; vga=ext
  2074 000007C8 740E                <1>                 je vc0
  2075 000007CA 4B                  <1>                 dec bx				; bx <- -3
  2076 000007CB 663D3D61736B        <1>                 cmp eax,'=ask'			; vga=ask
  2077 000007D1 7405                <1>                 je vc0
  2078 000007D3 E88409              <1>                 call parseint                   ; vga=<number>
  2079 000007D6 72CF                <1> 		jc skip_this_opt		; Not an integer
  2080 000007D8 891EFA01            <1> vc0:		mov [bs_vidmode],bx		; Set video mode
  2081 000007DC EBC9                <1> 		jmp short skip_this_opt
  2082                              <1> is_mem_cmd:
  2083 000007DE 83C604              <1>                 add si,4
  2084 000007E1 E87609              <1>                 call parseint
  2085 000007E4 72C1                <1> 		jc skip_this_opt		; Not an integer
  2086                              <1> %if HIGHMEM_SLOP != 0
  2087                              <1> 		sub ebx,HIGHMEM_SLOP
  2088                              <1> %endif
  2089 000007E6 2E66891E5855        <1> 		mov [cs:HighMemSize],ebx
  2090 000007EC EBB9                <1> 		jmp short skip_this_opt
  2091                              <1> cmdline_end:
  2092 000007EE 0E                  <1>                 push cs                         ; Restore standard DS
  2093 000007EF 1F                  <1>                 pop ds
  2094 000007F0 81EE0090            <1> 		sub si,cmd_line_here
  2095 000007F4 8936AA55            <1> 		mov [CmdLineLen],si		; Length including final null
  2096                              <1> ;
  2097                              <1> ; Now check if we have a large kernel, which needs to be loaded high
  2098                              <1> ;
  2099 000007F8 66C7065C55FFFFFF37  <1> 		mov dword [RamdiskMax], HIGHMEM_MAX	; Default initrd limit
  2100 00000801 2666813E0202486472- <1> 		cmp dword [es:su_header],HEADER_ID	; New setup code ID
  2101 0000080A 53                  <1>
  2102 0000080B 0F85FF01            <1> 		jne old_kernel		; Old kernel, load low
  2103 0000080F 26813E06020002      <1> 		cmp word [es:su_version],0200h	; Setup code version 2.0
  2104 00000816 0F82F401            <1> 		jb old_kernel		; Old kernel, load low
  2105 0000081A 26813E06020102      <1>                 cmp word [es:su_version],0201h	; Version 2.01+?
  2106 00000821 721F                <1>                 jb new_kernel                   ; If 2.00, skip this step
  2107 00000823 26C7062402F48F      <1>                 mov word [es:su_heapend],linux_stack	; Set up the heap
  2108 0000082A 26800E110280        <1>                 or byte [es:su_loadflags],80h	; Let the kernel know we care
  2109 00000830 26813E06020302      <1> 		cmp word [es:su_version],0203h	; Version 2.03+?
  2110 00000837 7209                <1> 		jb new_kernel			; Not 2.03+
  2111 00000839 2666A12C02          <1> 		mov eax,[es:su_ramdisk_max]
  2112 0000083E 66A35C55            <1> 		mov [RamdiskMax],eax		; Set the ramdisk limit
  2113                              <1> 
  2114                              <1> ;
  2115                              <1> ; We definitely have a new-style kernel.  Let the kernel know who we are,
  2116                              <1> ; and that we are clueful
  2117                              <1> ;
  2118                              <1> new_kernel:
  2119 00000842 26C606100231        <1> 		mov byte [es:su_loader],my_id	; Show some ID
  2120 00000848 260FB606F101        <1> 		movzx ax,byte [es:bs_setupsecs]	; Variable # of setup sectors
  2121 0000084E A3A455              <1> 		mov [SetupSecs],ax
  2122                              <1> ;
  2123                              <1> ; About to load the kernel.  This is a modern kernel, so use the boot flags
  2124                              <1> ; we were provided.
  2125                              <1> ;
  2126 00000851 26A01102            <1>                 mov al,[es:su_loadflags]
  2127 00000855 A2C155              <1> 		mov [LoadFlags],al
  2128                              <1> ;
  2129                              <1> ; Load the kernel.  We always load it at 100000h even if we're supposed to
  2130                              <1> ; load it "low"; for a "low" load we copy it down to low memory right before
  2131                              <1> ; jumping to it.
  2132                              <1> ;
  2133                              <1> read_kernel:
  2134 00000858 BEDB55              <1>                 mov si,KernelCName		; Print kernel name part of
  2135 0000085B E8250C              <1>                 call cwritestr                  ; "Loading" message
  2136 0000085E BE[791F]            <1>                 mov si,dotdot_msg		; Print dots
  2137 00000861 E81F0C              <1>                 call cwritestr
  2138                              <1> 
  2139 00000864 66A15855            <1>                 mov eax,[HighMemSize]
  2140 00000868 662D00001000        <1> 		sub eax,100000h			; Load address
  2141 0000086E 663B066055          <1> 		cmp eax,[KernelSize]
  2142 00000873 0F82B100            <1> 		jb no_high_mem		; Not enough high memory
  2143                              <1> ;
  2144                              <1> ; Move the stuff beyond the setup code to high memory at 100000h
  2145                              <1> ;
  2146 00000877 660FB736A455        <1> 		movzx esi,word [SetupSecs]	; Setup sectors
  2147 0000087D 46                  <1> 		inc si				; plus 1 boot sector
  2148 0000087E C1E609              <1>                 shl si,9			; Convert to bytes
  2149 00000881 66B900800000        <1>                 mov ecx,8000h			; 32K
  2150 00000887 6629F1              <1> 		sub ecx,esi			; Number of bytes to copy
  2151 0000088A 6651                <1> 		push ecx
  2152 0000088C 6681C600000700      <1> 		add esi,(real_mode_seg << 4)	; Pointer to source
  2153 00000893 66BF00001000        <1>                 mov edi,100000h                 ; Copy to address 100000h
  2154                              <1> 
  2155 00000899 E8500E              <1>                 call bcopy			; Transfer to high memory
  2156                              <1> 
  2157                              <1> 		; On exit EDI -> where to load the rest
  2158                              <1> 
  2159 0000089C BE[7A1F]            <1>                 mov si,dot_msg			; Progress report
  2160 0000089F E8E10B              <1>                 call cwritestr
  2161 000008A2 E89106              <1>                 call abort_check
  2162                              <1> 
  2163 000008A5 6659                <1> 		pop ecx				; Number of bytes in the initial portion
  2164 000008A7 5E                  <1> 		pop si				; Restore file handle/cluster pointer
  2165 000008A8 66A16055            <1> 		mov eax,[KernelSize]
  2166 000008AC 6629C8              <1> 		sub eax,ecx			; Amount of kernel left over
  2167 000008AF 7603                <1> 		jbe high_load_done		; Zero left (tiny kernel)
  2168                              <1> 
  2169 000008B1 E82510              <1> 		call load_high			; Copy the file
  2170                              <1> 
  2171                              <1> high_load_done:
  2172 000008B4 B80070              <1>                 mov ax,real_mode_seg		; Set to real mode seg
  2173 000008B7 8EC0                <1>                 mov es,ax
  2174                              <1> 
  2175 000008B9 BE[7A1F]            <1>                 mov si,dot_msg
  2176 000008BC E8C40B              <1>                 call cwritestr
  2177                              <1> 
  2178                              <1> ;
  2179                              <1> ; Now see if we have an initial RAMdisk; if so, do requisite computation
  2180                              <1> ; We know we have a new kernel; the old_kernel code already will have objected
  2181                              <1> ; if we tried to load initrd using an old kernel
  2182                              <1> ;
  2183                              <1> load_initrd:
  2184 000008BF F606[7620]01        <1>                 test byte [initrd_flag],1
  2185 000008C4 7468                <1>                 jz nk_noinitrd
  2186 000008C6 06                  <1>                 push es                         ; ES->real_mode_seg
  2187 000008C7 1E                  <1>                 push ds
  2188 000008C8 07                  <1>                 pop es                          ; We need ES==DS
  2189 000008C9 BED055              <1>                 mov si,InitRD
  2190 000008CC BFE855              <1>                 mov di,InitRDCName
  2191 000008CF E88307              <1>                 call unmangle_name              ; Create human-readable name
  2192 000008D2 81EFE855            <1>                 sub di,InitRDCName
  2193 000008D6 893EA055            <1>                 mov [InitRDCNameLen],di
  2194 000008DA BFD055              <1>                 mov di,InitRD
  2195 000008DD E87F06              <1>                 call searchdir                  ; Look for it in directory
  2196 000008E0 07                  <1>                 pop es
  2197 000008E1 7433                <1> 		jz initrd_notthere
  2198 000008E3 26A31C02            <1> 		mov [es:su_ramdisklen1],ax	; Ram disk length
  2199 000008E7 2689161E02          <1> 		mov [es:su_ramdisklen2],dx
  2200 000008EC 668B165855          <1> 		mov edx,[HighMemSize]		; End of memory
  2201 000008F1 664A                <1> 		dec edx
  2202 000008F3 66A15C55            <1> 		mov eax,[RamdiskMax]		; Highest address allowed by kernel
  2203 000008F7 6639C2              <1> 		cmp edx,eax
  2204 000008FA 7603                <1> 		jna memsize_ok
  2205 000008FC 6689C2              <1> 		mov edx,eax			; Adjust to fit inside limit
  2206                              <1> memsize_ok:
  2207 000008FF 6642                <1> 		inc edx
  2208 00000901 31D2                <1>                 xor dx,dx			; Round down to 64K boundary
  2209 00000903 26662B161C02        <1> 		sub edx,[es:su_ramdisklen]	; Subtract size of ramdisk
  2210 00000909 31D2                <1>                 xor dx,dx			; Round down to 64K boundary
  2211 0000090B 266689161802        <1>                 mov [es:su_ramdiskat],edx	; Load address
  2212 00000911 E81501              <1> 		call loadinitrd			; Load initial ramdisk
  2213 00000914 EB18                <1> 		jmp short initrd_end
  2214                              <1> 
  2215                              <1> initrd_notthere:
  2216 00000916 BE[2F1E]            <1>                 mov si,err_noinitrd
  2217 00000919 E8670B              <1>                 call cwritestr
  2218 0000091C BEE855              <1>                 mov si,InitRDCName
  2219 0000091F E8610B              <1>                 call cwritestr
  2220 00000922 BE[851F]            <1>                 mov si,crlf_msg
  2221 00000925 E92206              <1>                 jmp abort_load
  2222                              <1> 
  2223 00000928 BE[501E]            <1> no_high_mem:    mov si,err_nohighmem		; Error routine
  2224 0000092B E91C06              <1>                 jmp abort_load
  2225                              <1> 
  2226                              <1> initrd_end:
  2227                              <1> nk_noinitrd:
  2228                              <1> ;
  2229                              <1> ; Abandon hope, ye that enter here!  We do no longer permit aborts.
  2230                              <1> ;
  2231 0000092E E80506              <1>                 call abort_check        	; Last chance!!
  2232                              <1> 
  2233 00000931 BE[651F]            <1> 		mov si,ready_msg
  2234 00000934 E84C0B              <1> 		call cwritestr
  2235                              <1> 
  2236 00000937 E83712              <1> 		call vgaclearmode		; We can't trust ourselves after this
  2237                              <1> 
  2238                              <1> 		UNLOAD_PREP			; Module-specific hook
  2239                              <1> 
  2240                              <1> ;
  2241                              <1> ; Now, if we were supposed to load "low", copy the kernel down to 10000h
  2242                              <1> ; and the real mode stuff to 90000h.  We assume that all bzImage kernels are
  2243                              <1> ; capable of starting their setup from a different address.
  2244                              <1> ;
  2245 0000093A B80070              <1> 		mov ax,real_mode_seg
  2246 0000093D 8EE0                <1> 		mov fs,ax
  2247                              <1> 
  2248                              <1> ;
  2249                              <1> ; Copy command line.  Unfortunately, the kernel boot protocol requires
  2250                              <1> ; the command line to exist in the 9xxxxh range even if the rest of the
  2251                              <1> ; setup doesn't.
  2252                              <1> ;
  2253 0000093F FA                  <1> 		cli				; In case of hooked interrupts
  2254 00000940 F606C15501          <1> 		test byte [LoadFlags],LOAD_HIGH
  2255 00000945 7415                <1> 		jz need_high_cmdline
  2256 00000947 64813E06020202      <1> 		cmp word [fs:su_version],0202h	; Support new cmdline protocol?
  2257 0000094E 720C                <1> 		jb need_high_cmdline
  2258                              <1> 		; New cmdline protocol
  2259                              <1> 		; Store 32-bit (flat) pointer to command line
  2260 00000950 6466C7062802009007- <1> 		mov dword [fs:su_cmd_line_ptr],(real_mode_seg << 4) + cmd_line_here
  2261 00000959 00                  <1>
  2262 0000095A EB6D                <1> 		jmp short in_proper_place
  2263                              <1> 
  2264                              <1> need_high_cmdline:
  2265                              <1> ;
  2266                              <1> ; Copy command line up to 90000h
  2267                              <1> ;
  2268 0000095C B80090              <1> 		mov ax,9000h
  2269 0000095F 8EC0                <1> 		mov es,ax
  2270 00000961 BE0090              <1> 		mov si,cmd_line_here
  2271 00000964 89F7                <1> 		mov di,si
  2272 00000966 64C70620003FA3      <1> 		mov [fs:kern_cmd_magic],word CMD_MAGIC ; Store magic
  2273 0000096D 64893E2200          <1> 		mov [fs:kern_cmd_offset],di	; Store pointer
  2274                              <1> 
  2275 00000972 8B0EAA55            <1> 		mov cx,[CmdLineLen]
  2276 00000976 83C103              <1> 		add cx,byte 3
  2277 00000979 C1E902              <1> 		shr cx,2			; Convert to dwords
  2278 0000097C 64F366A5            <1> 		fs rep movsd
  2279                              <1> 
  2280 00000980 0FA0                <1> 		push fs
  2281 00000982 07                  <1> 		pop es
  2282                              <1> 
  2283 00000983 F606C15501          <1> 		test byte [LoadFlags],LOAD_HIGH
  2284 00000988 753F                <1> 		jnz in_proper_place		; If high load, we're done
  2285                              <1> 
  2286                              <1> ;
  2287                              <1> ; Loading low; we can't assume it's safe to run in place.
  2288                              <1> ;
  2289                              <1> ; Copy real_mode stuff up to 90000h
  2290                              <1> ;
  2291 0000098A B80090              <1> 		mov ax,9000h
  2292 0000098D 8EC0                <1> 		mov es,ax
  2293 0000098F 8B0EA455            <1> 		mov cx,[SetupSecs]
  2294 00000993 41                  <1> 		inc cx				; Setup + boot sector
  2295 00000994 C1E107              <1> 		shl cx,7			; Sectors -> dwords
  2296 00000997 31F6                <1> 		xor si,si
  2297 00000999 31FF                <1> 		xor di,di
  2298 0000099B 64F366A5            <1> 		fs rep movsd			; Copy setup + boot sector
  2299                              <1> ;
  2300                              <1> ; Some kernels in the 1.2 ballpark but pre-bzImage have more than 4
  2301                              <1> ; setup sectors, but the boot protocol had not yet been defined.  They
  2302                              <1> ; rely on a signature to figure out if they need to copy stuff from
  2303                              <1> ; the "protected mode" kernel area.  Unfortunately, we used that area
  2304                              <1> ; as a transfer buffer, so it's going to find the signature there.
  2305                              <1> ; Hence, zero the low 32K beyond the setup area.
  2306                              <1> ;
  2307 0000099F 8B3EA455            <1> 		mov di,[SetupSecs]
  2308 000009A3 47                  <1> 		inc di				; Setup + boot sector
  2309 000009A4 B94000              <1> 		mov cx,32768/512		; Sectors/32K
  2310 000009A7 29F9                <1> 		sub cx,di			; Remaining sectors
  2311 000009A9 C1E709              <1> 		shl di,9			; Sectors -> bytes
  2312 000009AC C1E107              <1> 		shl cx,7			; Sectors -> dwords
  2313 000009AF 6631C0              <1> 		xor eax,eax
  2314 000009B2 F366AB              <1> 		rep stosd			; Clear region
  2315                              <1> ;
  2316                              <1> ; Copy the kernel down to the "low" location
  2317                              <1> ;
  2318 000009B5 668B0E6055          <1> 		mov ecx,[KernelSize]
  2319 000009BA 66BE00001000        <1> 		mov esi,100000h
  2320 000009C0 66BF00000100        <1> 		mov edi,10000h
  2321 000009C6 E8230D              <1> 		call bcopy
  2322                              <1> 
  2323                              <1> ;
  2324                              <1> ; Now everything is where it needs to be...
  2325                              <1> ;
  2326                              <1> ; When we get here, es points to the final segment, either
  2327                              <1> ; 9000h or real_mode_seg
  2328                              <1> ;
  2329                              <1> in_proper_place:
  2330                              <1> 
  2331                              <1> ;
  2332                              <1> ; If the default root device is set to FLOPPY (0000h), change to
  2333                              <1> ; /dev/fd0 (0200h)
  2334                              <1> ;
  2335 000009C9 26833EFC0100        <1> 		cmp word [es:bs_rootdev],byte 0
  2336 000009CF 7507                <1> 		jne root_not_floppy
  2337 000009D1 26C706FC010002      <1> 		mov word [es:bs_rootdev],0200h
  2338                              <1> root_not_floppy:
  2339                              <1> 
  2340                              <1> ;
  2341                              <1> ; Copy the disk table to high memory, then re-initialize the floppy
  2342                              <1> ; controller
  2343                              <1> ;
  2344                              <1> %if IS_SYSLINUX
  2345 000009D8 2E0FB5367800        <1> 		lgs si,[cs:fdctab]
  2346 000009DE BFF48F              <1> 		mov di,linux_fdctab
  2347 000009E1 B90600              <1> 		mov cx,6			; 12 bytes
  2348 000009E4 65F3A5              <1> 		gs rep movsw
  2349 000009E7 2EC7067800F48F      <1> 		mov [cs:fdctab],word linux_fdctab ; Save new floppy tab pos
  2350 000009EE 2E8C067A00          <1> 		mov [cs:fdctab+2],es
  2351                              <1> %endif
  2352                              <1> ;
  2353                              <1> ; Linux wants the floppy motor shut off before starting the kernel,
  2354                              <1> ; at least bootsect.S seems to imply so.
  2355                              <1> ;
  2356                              <1> kill_motor:
  2357 000009F3 31C0                <1> 		xor ax,ax
  2358 000009F5 31D2                <1> 		xor dx,dx
  2359 000009F7 CD13                <1> 		int 13h
  2360                              <1> 
  2361                              <1> ;
  2362                              <1> ; If we're debugging, wait for a keypress so we can read any debug messages
  2363                              <1> ;
  2364                              <1> %ifdef debug
  2365                              <1>                 xor ax,ax
  2366                              <1>                 int 16h
  2367                              <1> %endif
  2368                              <1> ;
  2369                              <1> ; Set up segment registers and the Linux real-mode stack
  2370                              <1> ; Note: es == the real mode segment
  2371                              <1> ;
  2372 000009F9 FA                  <1> 		cli
  2373 000009FA 8CC3                <1> 		mov bx,es
  2374 000009FC 8EDB                <1> 		mov ds,bx
  2375 000009FE 8EE3                <1> 		mov fs,bx
  2376 00000A00 8EEB                <1> 		mov gs,bx
  2377 00000A02 8ED3                <1> 		mov ss,bx
  2378 00000A04 BCF48F              <1> 		mov sp,linux_stack
  2379                              <1> ;
  2380                              <1> ; We're done... now RUN THAT KERNEL!!!!
  2381                              <1> ; Setup segment == real mode segment + 020h; we need to jump to offset
  2382                              <1> ; zero in the real mode segment.
  2383                              <1> ;
  2384 00000A07 83C320              <1> 		add bx,020h
  2385 00000A0A 53                  <1> 		push bx
  2386 00000A0B 6A00                <1> 		push word 0h
  2387 00000A0D CB                  <1> 		retf
  2388                              <1> 
  2389                              <1> ;
  2390                              <1> ; Load an older kernel.  Older kernels always have 4 setup sectors, can't have
  2391                              <1> ; initrd, and are always loaded low.
  2392                              <1> ;
  2393                              <1> old_kernel:
  2394 00000A0E F606[7620]01        <1>                 test byte [initrd_flag],1	; Old kernel can't have initrd
  2395 00000A13 7406                <1>                 jz load_old_kernel
  2396 00000A15 BE[9B1E]            <1>                 mov si,err_oldkernel
  2397 00000A18 E92F05              <1>                 jmp abort_load
  2398                              <1> load_old_kernel:
  2399 00000A1B C706A4550400        <1> 		mov word [SetupSecs],4		; Always 4 setup sectors
  2400 00000A21 C606C15500          <1> 		mov byte [LoadFlags],0		; Always low
  2401 00000A26 E92FFE              <1> 		jmp read_kernel
  2402                              <1> 
  2403                              <1> ;
  2404                              <1> ; Load RAM disk into high memory
  2405                              <1> ;
  2406                              <1> ; Need to be set:
  2407                              <1> ;	su_ramdiskat	- Where in memory to load
  2408                              <1> ;	su_ramdisklen	- Size of file
  2409                              <1> ;	SI		- initrd filehandle/cluster pointer
  2410                              <1> ;
  2411                              <1> loadinitrd:
  2412 00000A29 06                  <1>                 push es                         ; Save ES on entry
  2413 00000A2A B80070              <1> 		mov ax,real_mode_seg
  2414 00000A2D 8EC0                <1>                 mov es,ax
  2415 00000A2F 26668B3E1802        <1>                 mov edi,[es:su_ramdiskat]	; initrd load address
  2416 00000A35 56                  <1> 		push si
  2417 00000A36 BE[6E1F]            <1> 		mov si,crlfloading_msg		; Write "Loading "
  2418 00000A39 E8470A              <1> 		call cwritestr
  2419 00000A3C BEE855              <1>                 mov si,InitRDCName		; Write ramdisk name
  2420 00000A3F E8410A              <1>                 call cwritestr
  2421 00000A42 BE[791F]            <1>                 mov si,dotdot_msg		; Write dots
  2422 00000A45 E83B0A              <1>                 call cwritestr
  2423 00000A48 5E                  <1> 		pop si
  2424                              <1> 
  2425 00000A49 2666A11C02          <1> 		mov eax,[es:su_ramdisklen]
  2426 00000A4E E8880E              <1> 		call load_high			; Load the file
  2427                              <1> 
  2428 00000A51 E82C0A              <1> 		call crlf
  2429 00000A54 07                  <1>                 pop es                          ; Restore original ES
  2430 00000A55 C3                  <1>                 ret
  2431                                  
  2432                                  ;
  2433                                  ; COMBOOT-loading code
  2434                                  ;
  2435                                  %include "comboot.inc"
  2436                              <1> ;; $Id: comboot.inc,v 1.14 2002/10/25 16:02:28 hpa Exp $
  2437                              <1> ;; -----------------------------------------------------------------------
  2438                              <1> ;;   
  2439                              <1> ;;   Copyright 1994-2002 H. Peter Anvin - All Rights Reserved
  2440                              <1> ;;
  2441                              <1> ;;   This program is free software; you can redistribute it and/or modify
  2442                              <1> ;;   it under the terms of the GNU General Public License as published by
  2443                              <1> ;;   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
  2444                              <1> ;;   Bostom MA 02111-1307, USA; either version 2 of the License, or
  2445                              <1> ;;   (at your option) any later version; incorporated herein by reference.
  2446                              <1> ;;
  2447                              <1> ;; -----------------------------------------------------------------------
  2448                              <1> 
  2449                              <1> ;;
  2450                              <1> ;; comboot.inc
  2451                              <1> ;; 
  2452                              <1> ;; Common code for running a COMBOOT image
  2453                              <1> ;;
  2454                              <1> 
  2455                              <1> ; Parameter registers definition; this is the definition
  2456                              <1> ; of the stack frame used by INT 21h and INT 22h.
  2457                              <1> %define		P_FLAGS		word [bp+44]
  2458                              <1> %define		P_FLAGSL	byte [bp+44]
  2459                              <1> %define		P_FLAGSH	byte [bp+45]
  2460                              <1> %define		P_CS		word [bp+42]
  2461                              <1> %define		P_IP		word [bp+40]
  2462                              <1> %define		P_DS		word [bp+38]
  2463                              <1> %define		P_ES		word [bp+36]
  2464                              <1> %define		P_FS		word [bp+34]
  2465                              <1> %define		P_GS		word [bp+32]
  2466                              <1> %define		P_EAX		dword [bp+28]
  2467                              <1> %define		P_AX		word [bp+28]
  2468                              <1> %define		P_HAX		word [bp+30]
  2469                              <1> %define		P_AL		byte [bp+28]
  2470                              <1> %define		P_AH		byte [bp+29]
  2471                              <1> %define		P_ECX		dword [bp+24]
  2472                              <1> %define		P_CX		word [bp+24]
  2473                              <1> %define		P_HCX		word [bp+26]
  2474                              <1> %define		P_CL		byte [bp+24]
  2475                              <1> %define		P_CH		byte [bp+25]
  2476                              <1> %define		P_EDX		dword [bp+20]
  2477                              <1> %define		P_DX		word [bp+20]
  2478                              <1> %define		P_HDX		word [bp+22]
  2479                              <1> %define		P_DL		byte [bp+20]
  2480                              <1> %define		P_DH		byte [bp+21]
  2481                              <1> %define		P_EBX		dword [bp+16]
  2482                              <1> %define		P_BX		word [bp+16]
  2483                              <1> %define		P_HBX		word [bp+18]
  2484                              <1> %define		P_BL		byte [bp+16]
  2485                              <1> %define		P_BH		byte [bp+17]
  2486                              <1> %define		P_EBP		dword [bp+8]
  2487                              <1> %define		P_BP		word [bp+8]
  2488                              <1> %define		P_HBP		word [bp+10]
  2489                              <1> %define		P_ESI		dword [bp+4]
  2490                              <1> %define		P_SI		word [bp+4]
  2491                              <1> %define		P_HSI		word [bp+6]
  2492                              <1> %define		P_EDI		dword [bp]
  2493                              <1> %define		P_DI		word [bp]
  2494                              <1> %define		P_HDI		word [bp+2]
  2495                              <1> 
  2496                              <1> ; Looks like a COMBOOT image but too large
  2497                              <1> comboot_too_large:
  2498 00000A56 BE[EB1E]            <1> 		mov si,err_comlarge
  2499 00000A59 E8270A              <1> 		call cwritestr
  2500 00000A5C E9FDF9              <1> 		jmp enter_command
  2501                              <1> 
  2502                              <1> ;
  2503                              <1> ; Load a COMBOOT image.  A COMBOOT image is basically a DOS .COM file,
  2504                              <1> ; except that it may, of course, not contain any DOS system calls.  We
  2505                              <1> ; do, however, allow the execution of INT 20h to return to SYSLINUX.
  2506                              <1> ;
  2507                              <1> is_comboot_image:
  2508 00000A5F 21D2                <1> 		and dx,dx
  2509 00000A61 75F3                <1> 		jnz comboot_too_large
  2510 00000A63 3D00FF              <1> 		cmp ax,0ff00h		; Max size in bytes
  2511 00000A66 73EE                <1> 		jae comboot_too_large
  2512                              <1> 
  2513 00000A68 E86400              <1> 		call comboot_setup_api
  2514                              <1> 
  2515 00000A6B B90020              <1> 		mov cx,comboot_seg
  2516 00000A6E 8EC1                <1> 		mov es,cx
  2517                              <1> 
  2518 00000A70 BB0001              <1> 		mov bx,100h		; Load at <seg>:0100h
  2519                              <1> 
  2520 00000A73 8B0E6C55            <1> 		mov cx,[ClustPerMoby]	; Absolute maximum # of clusters
  2521 00000A77 E89BF8              <1> 		call getfssec
  2522                              <1> 
  2523 00000A7A 31FF                <1> 		xor di,di
  2524 00000A7C B94000              <1> 		mov cx,64		; 256 bytes (size of PSP)
  2525 00000A7F 6631C0              <1> 		xor eax,eax		; Clear PSP
  2526 00000A82 F366AB              <1> 		rep stosd
  2527                              <1> 
  2528 00000A85 26C7060000CD20      <1> 		mov word [es:0], 020CDh	; INT 20h instruction
  2529                              <1> 		; First non-free paragraph
  2530 00000A8C 26C70602000030      <1> 		mov word [es:02h], comboot_seg+1000h
  2531                              <1> 
  2532                              <1> 		; Copy the command line from high memory
  2533 00000A93 B97D00              <1> 		mov cx,125		; Max cmdline len (minus space and CR)
  2534 00000A96 8B369C55            <1> 		mov si,[CmdOptPtr]
  2535 00000A9A BF8100              <1> 		mov di,081h		; Offset in PSP for command line
  2536 00000A9D B020                <1> 		mov al,' '		; DOS command lines begin with a space
  2537 00000A9F AA                  <1> 		stosb
  2538                              <1> 
  2539 00000AA0 AC                  <1> comboot_cmd_cp:	lodsb
  2540 00000AA1 20C0                <1> 		and al,al
  2541 00000AA3 7403                <1> 		jz comboot_end_cmd
  2542 00000AA5 AA                  <1> 		stosb
  2543 00000AA6 E2F8                <1> 		loop comboot_cmd_cp
  2544 00000AA8 B00D                <1> comboot_end_cmd: mov al,0Dh		; CR after last character
  2545 00000AAA AA                  <1> 		stosb
  2546 00000AAB B07E                <1> 		mov al,126		; Include space but not CR
  2547 00000AAD 28C8                <1> 		sub al,cl
  2548 00000AAF 26A28000            <1> 		mov [es:80h], al	; Store command line length
  2549                              <1> 
  2550 00000AB3 89266455            <1> 		mov [SavedSSSP],sp
  2551 00000AB7 8C166655            <1> 		mov [SavedSSSP+2],ss	; Save away SS:SP
  2552                              <1> 
  2553 00000ABB 8CC0                <1> 		mov ax,es
  2554 00000ABD 8ED8                <1> 		mov ds,ax
  2555 00000ABF 8ED0                <1> 		mov ss,ax
  2556 00000AC1 31E4                <1> 		xor sp,sp
  2557 00000AC3 6A00                <1> 		push word 0		; Return to address 0 -> exit
  2558                              <1> 
  2559 00000AC5 EA00010020          <1> 		jmp comboot_seg:100h	; Run it
  2560                              <1> 
  2561                              <1> ; Proper return vector
  2562 00000ACA FA                  <1> comboot_return:	cli			; Don't trust anyone
  2563 00000ACB 31C0                <1> 		xor ax,ax
  2564 00000ACD EB51                <1> 		jmp comboot_exit
  2565                              <1> 
  2566                              <1> ;
  2567                              <1> ; Set up the COMBOOT API interrupt vectors.  This is also used
  2568                              <1> ; by the COM32 code.
  2569                              <1> ;
  2570                              <1> comboot_setup_api:
  2571 00000ACF BF8000              <1> 		mov di,4*0x20		; DOS interrupt vectors
  2572 00000AD2 66B8[CA0A0000]      <1> 		mov eax,comboot_return	; INT 20h = exit
  2573 00000AD8 66AB                <1> 		stosd
  2574 00000ADA B8[EE0A]            <1> 		mov ax,comboot_int21	; INT 21h = DOS-compatible syscalls
  2575 00000ADD 66AB                <1> 		stosd
  2576 00000ADF B8[CF0B]            <1> 		mov ax,comboot_int22	; INT 22h = proprietary syscalls
  2577 00000AE2 66AB                <1> 		stosd
  2578 00000AE4 B8[1C0B]            <1> 		mov ax,comboot_bogus
  2579 00000AE7 B91D00              <1> 		mov cx,29		; All remaining DOS vectors
  2580 00000AEA F366AB              <1> 		rep stosd
  2581 00000AED C3                  <1> 		ret
  2582                              <1> 
  2583                              <1> ; INT 21h: generic DOS system call
  2584 00000AEE FA                  <1> comboot_int21:	cli
  2585 00000AEF 1E                  <1> 		push ds
  2586 00000AF0 06                  <1> 		push es
  2587 00000AF1 0FA0                <1> 		push fs
  2588 00000AF3 0FA8                <1> 		push gs
  2589 00000AF5 6660                <1> 		pushad
  2590 00000AF7 FC                  <1> 		cld
  2591 00000AF8 8CCD                <1> 		mov bp,cs
  2592 00000AFA 8EDD                <1> 		mov ds,bp
  2593 00000AFC 8EC5                <1> 		mov es,bp
  2594 00000AFE 89E5                <1> 		mov bp,sp			; Set up stack frame
  2595                              <1> 
  2596 00000B00 B90A00              <1> 		mov cx,int21_count
  2597 00000B03 BE[BB0C]            <1> 		mov si,int21_table
  2598 00000B06 AC                  <1> .again:		lodsb
  2599 00000B07 3A461D              <1> 		cmp al,P_AH
  2600 00000B0A AD                  <1> 		lodsw
  2601 00000B0B E0F9                <1> 		loopne .again
  2602                              <1> 		; The last function in the list is the
  2603                              <1> 		; "no such function" function
  2604                              <1> 
  2605 00000B0D FFD0                <1> 		call ax			; Call the invoked function
  2606                              <1> comboot_resume:
  2607 00000B0F 0F92462C            <1> 		setc P_FLAGSL		; Propagate CF->error
  2608 00000B13 6661                <1> 		popad
  2609 00000B15 0FA9                <1> 		pop gs
  2610 00000B17 0FA1                <1> 		pop fs
  2611 00000B19 07                  <1> 		pop es
  2612 00000B1A 1F                  <1> 		pop ds
  2613 00000B1B CF                  <1> 		iret
  2614                              <1> 
  2615                              <1> ; Attempted to execute non-21h DOS system call
  2616 00000B1C FA                  <1> comboot_bogus:	cli			; Don't trust anyone
  2617 00000B1D B8[CD1E]            <1> 		mov ax,err_notdos
  2618                              <1> ;
  2619                              <1> ; Generic COMBOOT return to command line code
  2620                              <1> ;  AX -> message (if any)
  2621                              <1> ;  BX -> where to go next
  2622                              <1> ;
  2623                              <1> comboot_exit:
  2624 00000B20 BB[5C04]            <1> 		mov bx,enter_command	; Normal return to command prompt
  2625                              <1> comboot_exit_special:
  2626 00000B23 31D2                <1> 		xor dx,dx
  2627 00000B25 8EDA                <1> 		mov ds,dx
  2628 00000B27 8EC2                <1> 		mov es,dx
  2629 00000B29 0FB2266455          <1> 		lss sp,[SavedSSSP]
  2630 00000B2E FB                  <1> 		sti
  2631 00000B2F FC                  <1> 		cld
  2632 00000B30 21C0                <1> 		and ax,ax
  2633 00000B32 740A                <1> 		je .nomsg
  2634 00000B34 BEDB55              <1> 		mov si,KernelCName
  2635 00000B37 E84909              <1> 		call cwritestr
  2636 00000B3A 96                  <1> 		xchg si,ax
  2637 00000B3B E84509              <1> 		call cwritestr
  2638 00000B3E FFE3                <1> .nomsg:		jmp bx
  2639                              <1> 
  2640                              <1> ;
  2641                              <1> ; INT 21h system calls
  2642                              <1> ;
  2643                              <1> comboot_getkey:				; 01 = get key with echo
  2644 00000B40 E85610              <1> 		call vgashowcursor
  2645 00000B43 E86600              <1> 		call comboot_getchar
  2646 00000B46 E85610              <1> 		call vgahidecursor
  2647 00000B49 E88B04              <1> 		call writechr
  2648 00000B4C F8                  <1> 		clc
  2649 00000B4D C3                  <1> 		ret
  2650                              <1> 
  2651                              <1> comboot_writechr:			; 02 = writechr
  2652 00000B4E 8A4614              <1> 		mov al,P_DL
  2653 00000B51 E88304              <1> 		call writechr
  2654 00000B54 F8                  <1> 		clc
  2655 00000B55 C3                  <1> 		ret
  2656                              <1> 
  2657                              <1> comboot_writeserial:			; 04 = write serial port
  2658 00000B56 8A4614              <1> 		mov al,P_DL
  2659 00000B59 E88708              <1> 		call write_serial
  2660 00000B5C F8                  <1> 		clc
  2661 00000B5D C3                  <1> 		ret
  2662                              <1> 
  2663                              <1> comboot_getkeynoecho:			; 08 = get key w/o echo
  2664 00000B5E E84B00              <1> 		call comboot_getchar
  2665 00000B61 F8                  <1> 		clc
  2666 00000B62 C3                  <1> 		ret
  2667                              <1> 
  2668                              <1> comboot_writestr:			; 09 = write string
  2669 00000B63 8E4626              <1> 		mov es,P_DS
  2670 00000B66 8B7614              <1> 		mov si,P_DX
  2671 00000B69 26AC                <1> .loop:		es lodsb
  2672 00000B6B 3C24                <1> 		cmp al,'$'		; End string with $ - bizarre
  2673 00000B6D 7405                <1> 		je .done
  2674 00000B6F E86504              <1> 		call writechr
  2675 00000B72 EBF5                <1> 		jmp short .loop
  2676 00000B74 F8                  <1> .done:		clc
  2677 00000B75 C3                  <1> 		ret
  2678                              <1> 
  2679                              <1> comboot_checkkey:			; 0B = check keyboard status
  2680 00000B76 803E[F50C]00        <1> 		cmp byte [APIKeyFlag],00h
  2681 00000B7B 7503                <1> 		jnz .waiting
  2682 00000B7D E8A108              <1> 		call pollchar
  2683 00000B80 0F94C0              <1> .waiting:	setz al
  2684 00000B83 FEC8                <1> 		dec al			; AL = 0FFh if present, 0 if not
  2685 00000B85 88461C              <1> 		mov P_AL,al
  2686 00000B88 F8                  <1> 		clc
  2687 00000B89 C3                  <1> 		ret
  2688                              <1> 
  2689                              <1> comboot_checkver:			; 30 = check DOS version
  2690                              <1> 		; We return 0 in all DOS-compatible version registers,
  2691                              <1> 		; but the high part of eax-ebx-ecx-edx spell "SYSLINUX"
  2692 00000B8A 66C7461C00005359    <1> 		mov P_EAX,'SY' << 16
  2693 00000B92 66C746100000534C    <1> 		mov P_EBX,'SL' << 16
  2694 00000B9A 66C746180000494E    <1> 		mov P_ECX,'IN' << 16
  2695 00000BA2 66C7461400005558    <1> 		mov P_EDX,'UX' << 16
  2696 00000BAA F8                  <1> 		clc
  2697 00000BAB C3                  <1> 		ret
  2698                              <1> 
  2699                              <1> comboot_getchar:
  2700 00000BAC 803E[F50C]00        <1> 		cmp byte [APIKeyFlag],00h
  2701 00000BB1 7513                <1> 		jne .queued
  2702 00000BB3 E89508              <1> 		call getchar		; If not queued get input
  2703 00000BB6 20C0                <1> 		and al,al		; Function key?
  2704 00000BB8 7508                <1> 		jnz .done
  2705 00000BBA 8826[F40C]          <1> 		mov [APIKeyWait],ah	; High part of key
  2706 00000BBE FE06[F50C]          <1> 		inc byte [APIKeyFlag]	; Set flag
  2707 00000BC2 88461C              <1> .done:		mov P_AL,al
  2708 00000BC5 C3                  <1> 		ret
  2709 00000BC6 A0[F40C]            <1> .queued:	mov al,[APIKeyWait]
  2710 00000BC9 FE0E[F50C]          <1> 		dec byte [APIKeyFlag]
  2711 00000BCD EBF3                <1> 		jmp .done
  2712                              <1> 
  2713                              <1> ;
  2714                              <1> ; INT 22h - SYSLINUX-specific system calls
  2715                              <1> ;           System call number in ax
  2716                              <1> ;
  2717                              <1> comboot_int22:
  2718 00000BCF FA                  <1> 		cli
  2719 00000BD0 1E                  <1> 		push ds
  2720 00000BD1 06                  <1> 		push es
  2721 00000BD2 0FA0                <1> 		push fs
  2722 00000BD4 0FA8                <1> 		push gs
  2723 00000BD6 6660                <1> 		pushad
  2724 00000BD8 FC                  <1> 		cld
  2725 00000BD9 8CCD                <1> 		mov bp,cs
  2726 00000BDB 8EDD                <1> 		mov ds,bp
  2727 00000BDD 8EC5                <1> 		mov es,bp
  2728 00000BDF 89E5                <1> 		mov bp,sp			; Set up stack frame
  2729                              <1> 
  2730 00000BE1 83F80D              <1> 		cmp ax,int22_count
  2731 00000BE4 7202                <1> 		jb .ok
  2732 00000BE6 31C0                <1> 		xor ax,ax			; Function 0 -> unimplemented
  2733                              <1> .ok:
  2734 00000BE8 93                  <1> 		xchg ax,bx
  2735 00000BE9 01DB                <1> 		add bx,bx
  2736 00000BEB FF97[DA0C]          <1> 		call [bx+int22_table]
  2737 00000BEF E91DFF              <1> 		jmp comboot_resume		; On return
  2738                              <1> 
  2739                              <1> ;
  2740                              <1> ; INT 22h AX=0000h	Unimplemented call
  2741                              <1> ;
  2742                              <1> comapi_err:
  2743 00000BF2 F9                  <1> 		stc
  2744 00000BF3 C3                  <1> 		ret
  2745                              <1> 
  2746                              <1> ;
  2747                              <1> ; INT 22h AX=0001h	Get SYSLINUX version
  2748                              <1> ;
  2749                              <1> comapi_get_version:
  2750                              <1> 		; Number of API functions supported
  2751 00000BF4 C7461C0D00          <1> 		mov P_AX,int22_count
  2752                              <1> 		; SYSLINUX version
  2753 00000BF9 C746180002          <1> 		mov P_CX,(VER_MAJOR << 8)+VER_MINOR
  2754                              <1> 		; SYSLINUX derivative ID byte
  2755 00000BFE C746143100          <1> 		mov P_DX,my_id
  2756                              <1> 		; For future use
  2757 00000C03 8C4E10              <1> 		mov P_BX,cs	; cs == 0
  2758                              <1> 
  2759 00000C06 8C5E24              <1> 		mov P_ES,ds
  2760                              <1> 		; ES:SI -> version banner
  2761 00000C09 C74604[0002]        <1> 		mov P_SI,syslinux_banner
  2762                              <1> 		; ES:DI -> copyright string
  2763 00000C0E C74600[941C]        <1> 		mov P_DI,copyright_str
  2764                              <1> 
  2765                              <1> comapi_nop:
  2766 00000C13 F8                  <1> 		clc
  2767 00000C14 C3                  <1> 		ret
  2768                              <1> 
  2769                              <1> ;
  2770                              <1> ; INT 22h AX=0002h	Write string
  2771                              <1> ;
  2772                              <1> ; Write null-terminated string in ES:BX
  2773                              <1> ;
  2774                              <1> comapi_writestr:
  2775 00000C15 8E5E24              <1> 		mov ds,P_ES
  2776 00000C18 8B7610              <1> 		mov si,P_BX
  2777 00000C1B E848F5              <1> 		call writestr
  2778 00000C1E F8                  <1> 		clc
  2779 00000C1F C3                  <1> 		ret
  2780                              <1> 
  2781                              <1> ;
  2782                              <1> ; INT 22h AX=0003h	Run command
  2783                              <1> ;
  2784                              <1> ; Terminates the COMBOOT program and executes the command line in
  2785                              <1> ; ES:BX as if it had been entered by the user.
  2786                              <1> ;
  2787                              <1> comapi_run:
  2788 00000C20 8E5E24              <1> 		mov ds,P_ES
  2789 00000C23 8B7610              <1> 		mov si,P_BX
  2790 00000C26 BF[9C20]            <1> 		mov di,command_line
  2791                              <1> .copyloop:
  2792 00000C29 AC                  <1> 		lodsb
  2793 00000C2A AA                  <1> 		stosb
  2794 00000C2B 20C0                <1> 		and al,al
  2795 00000C2D 75FA                <1> 		jnz .copyloop
  2796 00000C2F 31C0                <1> 		xor ax,ax
  2797 00000C31 BB[7005]            <1> 		mov bx,load_kernel		; Run a new kernel
  2798 00000C34 E9ECFE              <1> 		jmp comboot_exit_special	; Terminate task, clean up
  2799                              <1> 
  2800                              <1> ;
  2801                              <1> ; INT 22h AX=0004h	Run default command		
  2802                              <1> ;
  2803                              <1> ; Terminates the COMBOOT program and executes the default command line
  2804                              <1> ; as if a timeout had happened or the user pressed <Enter>.
  2805                              <1> ;
  2806                              <1> comapi_run_default:
  2807 00000C37 BB[5605]            <1> 		mov bx,auto_boot
  2808 00000C3A E9E6FE              <1> 		jmp comboot_exit_special
  2809                              <1> 
  2810                              <1> ;
  2811                              <1> ; INT 22h AX=0005h	Force text mode
  2812                              <1> ;
  2813                              <1> ; Puts the video in standard text mode
  2814                              <1> ;
  2815                              <1> comapi_textmode:
  2816 00000C3D E8310F              <1> 		call vgaclearmode
  2817 00000C40 F8                  <1> 		clc
  2818 00000C41 C3                  <1> 		ret
  2819                              <1> 
  2820                              <1> ;
  2821                              <1> ; INT 22h AX=0006h	Open file
  2822                              <1> ;
  2823                              <1> comapi_open:
  2824 00000C42 1E                  <1> 		push ds
  2825 00000C43 8E5E24              <1> 		mov ds,P_ES
  2826 00000C46 8B7604              <1> 		mov si,P_SI
  2827 00000C49 BFD055              <1> 		mov di,InitRD
  2828 00000C4C 57                  <1> 		push di
  2829 00000C4D E8AA03              <1> 		call mangle_name
  2830 00000C50 5F                  <1> 		pop di
  2831 00000C51 1F                  <1> 		pop ds
  2832 00000C52 E80A03              <1> 		call searchdir
  2833 00000C55 740E                <1> 		jz .err
  2834 00000C57 89461C              <1> 		mov P_AX,ax
  2835 00000C5A 89561E              <1> 		mov P_HAX,dx
  2836 00000C5D A17055              <1> 		mov ax,[ClustSize]
  2837 00000C60 894618              <1> 		mov P_CX,ax
  2838 00000C63 F8                  <1> 		clc
  2839 00000C64 C3                  <1> 		ret
  2840                              <1> .err:
  2841 00000C65 F9                  <1> 		stc
  2842 00000C66 C3                  <1> 		ret
  2843                              <1> 
  2844                              <1> 
  2845                              <1> ;
  2846                              <1> ; INT 22h AX=0007h	Read file
  2847                              <1> ;
  2848                              <1> comapi_read:
  2849 00000C67 8B4610              <1> 		mov ax,P_BX
  2850 00000C6A 8B7604              <1> 		mov si,P_SI
  2851 00000C6D E8A5F6              <1> 		call getfssec
  2852 00000C70 7302                <1> 		jnc .noteof
  2853 00000C72 31F6                <1> 		xor si,si		; SI <- 0 on EOF, CF <- 0
  2854 00000C74 897604              <1> .noteof:	mov P_SI,si
  2855 00000C77 C3                  <1> 		ret
  2856                              <1> 
  2857                              <1> ;
  2858                              <1> ; INT 22h AX=0008h	Close file
  2859                              <1> ;
  2860                              <1> comapi_close:
  2861                              <1> 		; Do nothing for now.  Eventually implement
  2862                              <1> 		; an internal API for this.
  2863 00000C78 F8                  <1> 		clc
  2864 00000C79 C3                  <1> 		ret
  2865                              <1> 
  2866                              <1> ;
  2867                              <1> ; INT 22h AX=0009h	Call PXE stack
  2868                              <1> ;
  2869                              <1> %if IS_PXELINUX
  2870                              <1> comapi_pxecall:
  2871                              <1> 		mov bx,P_BX
  2872                              <1> 		mov es,P_ES
  2873                              <1> 		mov di,P_DI
  2874                              <1> 		call far [PXENVEntry]
  2875                              <1> 		mov P_AX,ax
  2876                              <1> 		clc
  2877                              <1> 		ret
  2878                              <1> %else
  2879                              <1> comapi_pxecall	equ comapi_err			; Not available
  2880                              <1> %endif
  2881                              <1> 
  2882                              <1> ;
  2883                              <1> ; INT 22h AX=000Ah	Get Derivative-Specific Info
  2884                              <1> ;
  2885                              <1> comapi_derinfo:
  2886 00000C7A C6461C31            <1> 		mov P_AL,my_id
  2887                              <1> %if IS_SYSLINUX
  2888 00000C7E A0[2400]            <1> 		mov al,[bsDriveNumber]
  2889 00000C81 884614              <1> 		mov P_DL,al
  2890 00000C84 8C4E24              <1> 		mov P_ES,cs
  2891 00000C87 C74610[E0FF]        <1> 		mov P_BX,PartInfo
  2892                              <1> %elif IS_PXELINUX
  2893                              <1> 		mov ax,[APIVer]
  2894                              <1> 		mov P_DX,ax
  2895                              <1> 		mov ax,[StrucPtr]
  2896                              <1> 		mov P_BX,ax
  2897                              <1> 		mov ax,[StrucPtr+2]
  2898                              <1> 		mov P_ES,ax
  2899                              <1> 		mov ax,[InitStack]
  2900                              <1> 		mov P_SI,ax
  2901                              <1> 		mov ax,[InitStack+2]
  2902                              <1> 		mov P_FS,ax
  2903                              <1> %elif IS_ISOLINUX
  2904                              <1> 		mov al,[DriveNo]
  2905                              <1> 		mov P_DL,al
  2906                              <1> 		mov P_ES,cs
  2907                              <1> 		mov P_BX,spec_packet
  2908                              <1> %endif
  2909 00000C8C F8                  <1> 		clc
  2910 00000C8D C3                  <1> 		ret
  2911                              <1> 
  2912                              <1> ;
  2913                              <1> ; INT 22h AX=000Bh	Get Serial Console Configuration
  2914                              <1> ;
  2915                              <1> comapi_serialcfg:
  2916 00000C8E A1[7E20]            <1> 		mov ax,[SerialPort]
  2917 00000C91 894614              <1> 		mov P_DX,ax
  2918 00000C94 A1BA55              <1> 		mov ax,[BaudDivisor]
  2919 00000C97 894618              <1> 		mov P_CX,ax
  2920 00000C9A A1BC55              <1> 		mov ax,[FlowControl]
  2921 00000C9D 08E0                <1> 		or al,ah
  2922 00000C9F 8A26BE55            <1> 		mov ah,[FlowIgnore]
  2923 00000CA3 C0EC04              <1> 		shr ah,4
  2924 00000CA6 894610              <1> 		mov P_BX,ax
  2925 00000CA9 F8                  <1> 		clc
  2926 00000CAA C3                  <1> 		ret
  2927                              <1> 
  2928                              <1> ;
  2929                              <1> ; INT 22h AX=000Ch	Perform final cleanup
  2930                              <1> ;
  2931                              <1> comapi_cleanup:
  2932                              <1> %if IS_PXELINUX
  2933                              <1> 		; Unload PXE if requested
  2934                              <1> 		test dl,3
  2935                              <1> 		setnz [KeepPXE]
  2936                              <1> 		call unload_pxe
  2937                              <1> %elif IS_SYSLINUX
  2938                              <1> 		; Restore original FDC table
  2939 00000CAB 66A1[DCFF]          <1> 		mov eax,[OrigFDCTabPtr]
  2940 00000CAF 66A37800            <1> 		mov [fdctab],eax
  2941                              <1> %endif
  2942                              <1> 		; Reset the floppy disk subsystem
  2943 00000CB3 31C0                <1> 		xor ax,ax
  2944 00000CB5 31D2                <1> 		xor dx,dx
  2945 00000CB7 CD13                <1> 		int 13h
  2946 00000CB9 F8                  <1> 		clc
  2947 00000CBA C3                  <1> 		ret
  2948                              <1> 
  2949                              <1> ;
  2950                              <1> ; This stuff should really be in the data section...
  2951                              <1> ;
  2952                              <1> %macro 		int21 2
  2953                              <1> 		db %1
  2954                              <1> 		dw %2
  2955                              <1> %endmacro
  2956                              <1> 
  2957                              <1> int21_table:
  2958                              <1> 		int21	00h, comboot_return
  2959 00000CBB 00                  <2>  db %1
  2960 00000CBC [CA0A]              <2>  dw %2
  2961                              <1> 		int21	01h, comboot_getkey
  2962 00000CBE 01                  <2>  db %1
  2963 00000CBF [400B]              <2>  dw %2
  2964                              <1> 		int21	02h, comboot_writechr
  2965 00000CC1 02                  <2>  db %1
  2966 00000CC2 [4E0B]              <2>  dw %2
  2967                              <1> 		int21	04h, comboot_writeserial
  2968 00000CC4 04                  <2>  db %1
  2969 00000CC5 [560B]              <2>  dw %2
  2970                              <1> 		int21	08h, comboot_getkey
  2971 00000CC7 08                  <2>  db %1
  2972 00000CC8 [400B]              <2>  dw %2
  2973                              <1> 		int21	09h, comboot_writestr
  2974 00000CCA 09                  <2>  db %1
  2975 00000CCB [630B]              <2>  dw %2
  2976                              <1> 		int21	0Bh, comboot_checkkey
  2977 00000CCD 0B                  <2>  db %1
  2978 00000CCE [760B]              <2>  dw %2
  2979                              <1> 		int21	30h, comboot_checkver
  2980 00000CD0 30                  <2>  db %1
  2981 00000CD1 [8A0B]              <2>  dw %2
  2982                              <1> 		int21	4Ch, comboot_return
  2983 00000CD3 4C                  <2>  db %1
  2984 00000CD4 [CA0A]              <2>  dw %2
  2985                              <1> 		int21	 -1, comboot_bogus
  2986 00000CD6 FF                  <2>  db %1
  2987 00000CD7 [1C0B]              <2>  dw %2
  2988                              <1> int21_count	equ ($-int21_table)/3
  2989                              <1> 
  2990 00000CD9 00                  <1> 		align 2, db 0
  2991                              <1> int22_table:
  2992 00000CDA [F20B]              <1> 		dw comapi_err			; 0000 unimplemented syscall
  2993 00000CDC [F40B]              <1> 		dw comapi_get_version		; 0001 get SYSLINUX version
  2994 00000CDE [150C]              <1> 		dw comapi_writestr		; 0002 write string
  2995 00000CE0 [200C]              <1> 		dw comapi_run			; 0003 run specified command
  2996 00000CE2 [370C]              <1> 		dw comapi_run_default		; 0004 run default command
  2997 00000CE4 [3D0C]              <1> 		dw comapi_textmode		; 0005 force text mode
  2998 00000CE6 [420C]              <1> 		dw comapi_open			; 0006 open file
  2999 00000CE8 [670C]              <1> 		dw comapi_read			; 0007 read file
  3000 00000CEA [780C]              <1> 		dw comapi_close			; 0008 close file
  3001 00000CEC [F20B]              <1> 		dw comapi_pxecall		; 0009 call PXE stack
  3002 00000CEE [7A0C]              <1> 		dw comapi_derinfo		; 000A derivative-specific info
  3003 00000CF0 [8E0C]              <1> 		dw comapi_serialcfg		; 000B get serial port config
  3004 00000CF2 [AB0C]              <1> 		dw comapi_cleanup		; 000C perform final cleanup
  3005                              <1> int22_count	equ ($-int22_table)/2
  3006                              <1> 
  3007 00000CF4 00                  <1> APIKeyWait	db 0
  3008 00000CF5 00                  <1> APIKeyFlag	db 0
  3009                                  %include "com32.inc"
  3010                              <1> ;; $Id: com32.inc,v 1.2 2002/06/15 05:24:25 hpa Exp $
  3011                              <1> ;; -----------------------------------------------------------------------
  3012                              <1> ;;   
  3013                              <1> ;;   Copyright 1994-2002 H. Peter Anvin - All Rights Reserved
  3014                              <1> ;;
  3015                              <1> ;;   This program is free software; you can redistribute it and/or modify
  3016                              <1> ;;   it under the terms of the GNU General Public License as published by
  3017                              <1> ;;   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
  3018                              <1> ;;   Bostom MA 02111-1307, USA; either version 2 of the License, or
  3019                              <1> ;;   (at your option) any later version; incorporated herein by reference.
  3020                              <1> ;;
  3021                              <1> ;; -----------------------------------------------------------------------
  3022                              <1> 
  3023                              <1> ;;
  3024                              <1> ;; com32.inc
  3025                              <1> ;;
  3026                              <1> ;; Common code for running a COM32 image
  3027                              <1> ;;
  3028                              <1> 
  3029                              <1> ;
  3030                              <1> ; Load a COM32 image.  A COM32 image is the 32-bit analogue to a DOS
  3031                              <1> ; .com file.  A COM32 image is loaded at address 0x101000, with %esp
  3032                              <1> ; set to the high end of usable memory.
  3033                              <1> ;
  3034                              <1> ; A COM32 image should begin with the magic bytes:
  3035                              <1> ; B8 FF 4C CD 21, which is "mov eax,0x21cd4cff" in 32-bit mode and
  3036                              <1> ; "mov ax,0x4cff; int 0x21" in 16-bit mode.  This will abort the
  3037                              <1> ; program with an error if run in 16-bit mode.
  3038                              <1> ;
  3039                              <1> pm_idt:		equ 0x100000
  3040                              <1> pm_entry:	equ 0x101000
  3041                              <1> 
  3042                              <1> 		bits 16
  3043                              <1> 		align 2
  3044                              <1> com32_pmidt:
  3045 00000CF6 0008                <1> 		dw 8*256		; Limit
  3046 00000CF8 00001000            <1> 		dd pm_idt		; Address
  3047                              <1> 
  3048                              <1> com32_rmidt:
  3049 00000CFC FFFF                <1> 		dw 0ffffh		; Limit
  3050 00000CFE 00000000            <1> 		dd 0			; Address
  3051                              <1> 
  3052                              <1> is_com32_image:
  3053 00000D02 E8C40E              <1> 		call highmemsize	; We need the high memory size...
  3054 00000D05 E8C7FD              <1> 		call comboot_setup_api	; Set up the COMBOOT-style API
  3055                              <1> 
  3056 00000D08 66BF00101000        <1> 		mov edi,pm_entry	; Load address
  3057 00000D0E 6692                <1> 		xchg eax,edx		; Gotta fix this insanity...
  3058 00000D10 66C1E010            <1> 		shl eax,16
  3059 00000D14 89D0                <1> 		mov ax,dx
  3060 00000D16 E8C00B              <1> 		call load_high
  3061 00000D19 E86407              <1> 		call crlf
  3062                              <1> 
  3063                              <1> com32_start:
  3064 00000D1C 66BB[610D0000]      <1> 		mov ebx,com32_call_start	; Where to go in PM
  3065                              <1> 
  3066                              <1> com32_enter_pm:
  3067 00000D22 FA                  <1> 		cli
  3068 00000D23 89266455            <1> 		mov [SavedSSSP],sp
  3069 00000D27 8C166655            <1> 		mov [SavedSSSP+2],ss
  3070 00000D2B FC                  <1> 		cld
  3071 00000D2C E8CA0A              <1> 		call a20_test
  3072 00000D2F 7503                <1> 		jnz .a20ok
  3073 00000D31 E8440A              <1> 		call enable_a20
  3074                              <1> 
  3075                              <1> .a20ok:
  3076 00000D34 0F0116[BC16]        <1> 		lgdt [bcopy_gdt]	; We can use the same GDT just fine
  3077 00000D39 0F011E[F60C]        <1> 		lidt [com32_pmidt]	; Set up the IDT
  3078 00000D3E 0F20C0              <1> 		mov eax,cr0
  3079 00000D41 0C01                <1> 		or al,1
  3080 00000D43 0F22C0              <1> 		mov cr0,eax		; Enter protected mode
  3081 00000D46 EA[4B0D]2000        <1> 		jmp 20h:.in_pm
  3082                              <1> 		
  3083                              <1> 		bits 32
  3084                              <1> .in_pm:
  3085 00000D4B 31C0                <1> 		xor eax,eax		; Available for future use...
  3086 00000D4D 8EE0                <1> 		mov fs,eax
  3087 00000D4F 8EE8                <1> 		mov gs,eax
  3088                              <1> 
  3089 00000D51 B028                <1> 		mov al,28h		; Set up data segments
  3090 00000D53 8EC0                <1> 		mov es,eax
  3091 00000D55 8ED8                <1> 		mov ds,eax
  3092 00000D57 8ED0                <1> 		mov ss,eax
  3093                              <1> 
  3094 00000D59 8B2568550000        <1> 		mov esp,[PMESP]		; Load protmode %esp if available
  3095 00000D5F FFE3                <1> 		jmp ebx			; Go to where we need to go
  3096                              <1> 
  3097                              <1> ;
  3098                              <1> ; This is invoked right before the actually starting the COM32
  3099                              <1> ; progam, in 32-bit mode...
  3100                              <1> ;
  3101                              <1> com32_call_start:
  3102                              <1> 		;
  3103                              <1> 		; Point the stack to the end of high memory
  3104                              <1> 		;
  3105 00000D61 678B265855          <1> 		mov esp,[word HighMemSize]
  3106                              <1> 
  3107                              <1> 		;
  3108                              <1> 		; Set up the protmode IDT and the interrupt jump buffers
  3109                              <1> 		; We set these up in the system area at 0x100000,
  3110                              <1> 		; but we could also put them beyond the stack.
  3111                              <1> 		;
  3112 00000D66 BF00001000          <1> 		mov edi,pm_idt
  3113                              <1> 
  3114                              <1> 		; Form an interrupt gate descriptor
  3115 00000D6B B800082000          <1> 		mov eax,0x00200000+((pm_idt+8*256)&0x0000ffff)
  3116 00000D70 BB00EE1000          <1> 		mov ebx,0x0000ee00+((pm_idt+8*256)&0xffff0000)
  3117 00000D75 31C9                <1> 		xor ecx,ecx
  3118 00000D77 FEC5                <1> 		inc ch				; ecx <- 256
  3119                              <1> 
  3120 00000D79 51                  <1> 		push ecx
  3121                              <1> .make_idt:
  3122 00000D7A AB                  <1> 		stosd
  3123 00000D7B 83C008              <1> 		add eax,8
  3124 00000D7E 93                  <1> 		xchg eax,ebx
  3125 00000D7F AB                  <1> 		stosd
  3126 00000D80 93                  <1> 		xchg eax,ebx
  3127 00000D81 E2F7                <1> 		loop .make_idt
  3128                              <1> 
  3129 00000D83 59                  <1> 		pop ecx
  3130                              <1> 
  3131                              <1> 		; Each entry in the interrupt jump buffer contains
  3132                              <1> 		; the following instructions:
  3133                              <1> 		;
  3134                              <1> 		; 00000000 60                pushad
  3135                              <1> 		; 00000001 B0xx              mov al,<interrupt#>
  3136                              <1> 		; 00000003 E9xxxxxxxx        jmp com32_handle_interrupt
  3137                              <1> 
  3138 00000D84 B860B000E9          <1> 		mov eax,0e900b060h
  3139 00000D89 BB[2B06F0FF]        <1> 		mov ebx,com32_handle_interrupt-(pm_idt+8*256+8)
  3140                              <1> 
  3141                              <1> .make_ijb:
  3142 00000D8E AB                  <1> 		stosd
  3143 00000D8F 284FFE              <1> 		sub [edi-2],cl			; Interrupt #
  3144 00000D92 93                  <1> 		xchg eax,ebx
  3145 00000D93 AB                  <1> 		stosd
  3146 00000D94 83E808              <1> 		sub eax,8
  3147 00000D97 93                  <1> 		xchg eax,ebx
  3148 00000D98 E2F4                <1> 		loop .make_ijb
  3149                              <1> 
  3150                              <1> 		; Now everything is set up for interrupts...
  3151                              <1> 
  3152 00000D9A 6800000100          <1> 		push dword (1 << 16)		; 64K bounce buffer
  3153 00000D9F 6800000200          <1> 		push dword (comboot_seg << 4)	; Bounce buffer address
  3154 00000DA4 68[460E0000]        <1> 		push dword com32_syscall	; Syscall entry point
  3155 00000DA9 670FB7369C55        <1> 		movzx esi,word [word CmdOptPtr]
  3156 00000DAF 56                  <1> 		push esi			; Command line pointer
  3157 00000DB0 6A04                <1> 		push dword 4			; Argument count
  3158 00000DB2 FB                  <1> 		sti				; Interrupts OK now
  3159 00000DB3 E8(00101000)        <1> 		call pm_entry			; Run the program...
  3160                              <1> 		; ... on return, fall through to com32_exit ...
  3161                              <1> 
  3162                              <1> com32_exit:
  3163 00000DB8 66BB[FD0D]          <1> 		mov bx,com32_done	; Return to command loop
  3164                              <1> 
  3165                              <1> com32_enter_rm:
  3166 00000DBC FA                  <1> 		cli
  3167 00000DBD FC                  <1> 		cld
  3168 00000DBE 892568550000        <1> 		mov [PMESP],esp		; Save exit %esp
  3169 00000DC4 31E4                <1> 		xor esp,esp		; Make sure the high bits are zero
  3170 00000DC6 EA[CD0D0000]0800    <1> 		jmp 08h:.in_pm16	; Return to 16-bit mode first
  3171                              <1> 
  3172                              <1> 		bits 16
  3173                              <1> .in_pm16:
  3174 00000DCD B81800              <1> 		mov ax,18h		; Real-mode-like segment
  3175 00000DD0 8EC0                <1> 		mov es,ax
  3176 00000DD2 8ED8                <1> 		mov ds,ax
  3177 00000DD4 8ED0                <1> 		mov ss,ax
  3178 00000DD6 8EE0                <1> 		mov fs,ax
  3179 00000DD8 8EE8                <1> 		mov gs,ax
  3180                              <1> 
  3181 00000DDA 0F011E[FC0C]        <1> 		lidt [com32_rmidt]	; Real-mode IDT (rm needs no GDT)
  3182 00000DDF 0F20C0              <1> 		mov eax,cr0
  3183 00000DE2 24FE                <1> 		and al,~1
  3184 00000DE4 0F22C0              <1> 		mov cr0,eax
  3185 00000DE7 EA[EC0D]0000        <1> 		jmp 0:.in_rm
  3186                              <1> 
  3187                              <1> .in_rm:					; Back in real mode
  3188 00000DEC 8CC8                <1> 		mov ax,cs		; Set up sane segments
  3189 00000DEE 8ED8                <1> 		mov ds,ax
  3190 00000DF0 8EC0                <1> 		mov es,ax
  3191 00000DF2 8EE0                <1> 		mov fs,ax
  3192 00000DF4 8EE8                <1> 		mov gs,ax
  3193 00000DF6 0FB2266455          <1> 		lss sp,[SavedSSSP]	; Restore stack
  3194 00000DFB FFE3                <1> 		jmp bx			; Go to whereever we need to go...
  3195                              <1> 
  3196                              <1> com32_done:
  3197 00000DFD E81B0A              <1> 		call disable_a20
  3198 00000E00 FB                  <1> 		sti
  3199 00000E01 E958F6              <1> 		jmp enter_command
  3200                              <1> 
  3201                              <1> ;
  3202                              <1> ; 16-bit support code
  3203                              <1> ;
  3204                              <1> 		bits 16
  3205                              <1> 
  3206                              <1> ;
  3207                              <1> ; 16-bit interrupt-handling code
  3208                              <1> ;
  3209                              <1> com32_int_rm:
  3210 00000E04 9C                  <1> 		pushf				; Flags on stack
  3211 00000E05 0E                  <1> 		push cs				; Return segment
  3212 00000E06 68[0C0E]            <1> 		push word .cont			; Return address
  3213 00000E09 6652                <1> 		push dword edx			; Segment:offset of IVT entry
  3214 00000E0B CB                  <1> 		retf				; Invoke IVT routine
  3215                              <1> .cont:		; ... on resume ...
  3216 00000E0C 66BB[440E0000]      <1> 		mov ebx,com32_int_resume
  3217 00000E12 E90DFF              <1> 		jmp com32_enter_pm		; Go back to PM
  3218                              <1> 
  3219                              <1> ;
  3220                              <1> ; 16-bit system call handling code
  3221                              <1> ;
  3222                              <1> com32_sys_rm:
  3223 00000E15 0FA9                <1> 		pop gs
  3224 00000E17 0FA1                <1> 		pop fs
  3225 00000E19 07                  <1> 		pop es
  3226 00000E1A 1F                  <1> 		pop ds
  3227 00000E1B 6661                <1> 		popad
  3228 00000E1D 669D                <1> 		popfd
  3229 00000E1F CB                  <1> 		retf				; Invoke routine
  3230                              <1> .return:
  3231 00000E20 669C                <1> 		pushfd
  3232 00000E22 6660                <1> 		pushad
  3233 00000E24 1E                  <1> 		push ds
  3234 00000E25 06                  <1> 		push es
  3235 00000E26 0FA0                <1> 		push fs
  3236 00000E28 0FA8                <1> 		push gs
  3237 00000E2A 66BB[920E0000]      <1> 		mov ebx,com32_sys_resume
  3238 00000E30 E9EFFE              <1> 		jmp com32_enter_pm
  3239                              <1> 
  3240                              <1> ;
  3241                              <1> ; 32-bit support code
  3242                              <1> ;
  3243                              <1> 		bits 32
  3244                              <1> 
  3245                              <1> ;
  3246                              <1> ; This is invoked on getting an interrupt in protected mode.  At
  3247                              <1> ; this point, we need to context-switch to real mode and invoke
  3248                              <1> ; the interrupt routine.
  3249                              <1> ;
  3250                              <1> ; When this gets invoked, the registers are saved on the stack and
  3251                              <1> ; AL contains the register number.
  3252                              <1> ;
  3253                              <1> com32_handle_interrupt:
  3254 00000E33 0FB6C0              <1> 		movzx eax,al
  3255 00000E36 31DB                <1> 		xor ebx,ebx		; Actually makes the code smaller
  3256 00000E38 8B1483              <1> 		mov edx,[ebx+eax*4]	; Get the segment:offset of the routine
  3257 00000E3B 66BB[040E]          <1> 		mov bx,com32_int_rm
  3258 00000E3F E978FFFFFF          <1> 		jmp com32_enter_rm	; Go to real mode
  3259                              <1> 
  3260                              <1> com32_int_resume:
  3261 00000E44 61                  <1> 		popad
  3262 00000E45 CF                  <1> 		iret
  3263                              <1> 
  3264                              <1> ;
  3265                              <1> ; Syscall invocation.  We manifest a structure on the real-mode stack,
  3266                              <1> ; containing the com32sys_t structure from <com32.h> as well as
  3267                              <1> ; the following entries (from low to high address):
  3268                              <1> ; - Target offset
  3269                              <1> ; - Target segment
  3270                              <1> ; - Return offset
  3271                              <1> ; - Return segment (== real mode cs == 0)
  3272                              <1> ; - Return flags
  3273                              <1> ;
  3274                              <1> com32_syscall:
  3275 00000E46 9C                  <1> 		pushfd			; Save IF among other things...
  3276 00000E47 60                  <1> 		pushad			; We only need to save some, but...
  3277 00000E48 FC                  <1> 		cld
  3278                              <1> 
  3279 00000E49 670FB73E6455        <1> 		movzx edi,word [word SavedSSSP]
  3280 00000E4F 670FB7066655        <1> 		movzx eax,word [word SavedSSSP+2]
  3281 00000E55 83EF36              <1> 		sub edi,54		; Allocate 54 bytes
  3282 00000E58 6667893E6455        <1> 		mov [word SavedSSSP],di
  3283 00000E5E C1E004              <1> 		shl eax,4
  3284 00000E61 01C7                <1> 		add edi,eax		; Create linear address
  3285                              <1> 
  3286 00000E63 8B74242C            <1> 		mov esi,[esp+11*4]	; Source regs
  3287 00000E67 31C9                <1> 		xor ecx,ecx
  3288 00000E69 B10B                <1> 		mov cl,11		; 44 bytes to copy
  3289 00000E6B F3A5                <1> 		rep movsd
  3290                              <1> 
  3291 00000E6D 0FB6442428          <1> 		movzx eax,byte [esp+10*4] ; Interrupt number
  3292                              <1> 		; ecx == 0 here; adding it to the EA makes the
  3293                              <1> 		; encoding smaller
  3294 00000E72 8B0481              <1> 		mov eax,[ecx+eax*4]	; Get IVT entry
  3295 00000E75 AB                  <1> 		stosd			; Save in stack frame
  3296 00000E76 B8[200E0000]        <1> 		mov eax,com32_sys_rm.return	; Return seg:offs
  3297 00000E7B AB                  <1> 		stosd			; Save in stack frame
  3298 00000E7C 8B47F4              <1> 		mov eax,[edi-12]	; Return flags
  3299 00000E7F 25D70C2000          <1> 		and eax,0x200cd7	; Mask (potentially) unsafe flags
  3300 00000E84 8947F4              <1> 		mov [edi-12],eax	; Primary flags entry
  3301 00000E87 66AB                <1> 		stosw			; Return flags
  3302                              <1> 
  3303 00000E89 66BB[150E]          <1> 		mov bx,com32_sys_rm
  3304 00000E8D E92AFFFFFF          <1> 		jmp com32_enter_rm	; Go to real mode
  3305                              <1> 
  3306                              <1> 		; On return, the 44-byte return structure is on the
  3307                              <1> 		; real-mode stack.
  3308                              <1> com32_sys_resume:
  3309 00000E92 670FB7366455        <1> 		movzx esi,word [word SavedSSSP]
  3310 00000E98 670FB7066655        <1> 		movzx eax,word [word SavedSSSP+2]
  3311 00000E9E 8B7C2430            <1> 		mov edi,[esp+12*4]	; Dest regs
  3312 00000EA2 C1E004              <1> 		shl eax,4
  3313 00000EA5 01C6                <1> 		add esi,eax		; Create linear address
  3314 00000EA7 21FF                <1> 		and edi,edi		; NULL pointer?
  3315 00000EA9 7502                <1> 		jnz .do_copy
  3316 00000EAB 89F7                <1> .no_copy:	mov edi,esi		; Do a dummy copy-to-self
  3317 00000EAD 31C9                <1> .do_copy:	xor ecx,ecx
  3318 00000EAF B10B                <1> 		mov cl,11		; 44 bytes
  3319 00000EB1 F3A5                <1> 		rep movsd		; Copy register block
  3320                              <1> 
  3321 00000EB3 67830664552C        <1> 		add dword [word SavedSSSP],44	; Remove from stack
  3322                              <1> 
  3323 00000EB9 61                  <1> 		popad
  3324 00000EBA 9D                  <1> 		popfd
  3325 00000EBB C3                  <1> 		ret			; Return to 32-bit program
  3326                              <1> 
  3327                              <1> 		bits 16
  3328                                  
  3329                                  ;
  3330                                  ; Boot sector loading code
  3331                                  ;
  3332                                  %include "bootsect.inc"
  3333                              <1> ;; $Id: bootsect.inc,v 1.7 2002/10/25 16:02:28 hpa Exp $
  3334                              <1> ;; -----------------------------------------------------------------------
  3335                              <1> ;;   
  3336                              <1> ;;   Copyright 1994-2002 H. Peter Anvin - All Rights Reserved
  3337                              <1> ;;
  3338                              <1> ;;   This program is free software; you can redistribute it and/or modify
  3339                              <1> ;;   it under the terms of the GNU General Public License as published by
  3340                              <1> ;;   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
  3341                              <1> ;;   Bostom MA 02111-1307, USA; either version 2 of the License, or
  3342                              <1> ;;   (at your option) any later version; incorporated herein by reference.
  3343                              <1> ;;
  3344                              <1> ;; -----------------------------------------------------------------------
  3345                              <1> 
  3346                              <1> ;;
  3347                              <1> ;; bootsect.inc
  3348                              <1> ;; 
  3349                              <1> ;; Load a boot sector (or other bootstrap program.)
  3350                              <1> ;;
  3351                              <1> ;; Unlike previous versions of this software, this doesn't require that
  3352                              <1> ;; the length is 512 bytes.  This allows PXE bootstraps and WinNT
  3353                              <1> ;; "CD boot sectors" to be invoked.
  3354                              <1> ;;
  3355                              <1> 
  3356                              <1> ;
  3357                              <1> ; Load a boot sector
  3358                              <1> ;
  3359                              <1> is_bootsector:
  3360                              <1> %if IS_SYSLINUX
  3361                              <1> 		; Transfer zero bytes
  3362 00000EBC 31C9                <1> 		xor cx,cx
  3363 00000EBE EB03                <1> 		jmp short load_bootsec
  3364                              <1> is_bss_sector:
  3365                              <1> 		; Transfer the superblock
  3366 00000EC0 B93300              <1> 		mov cx,superblock_len
  3367                              <1> load_bootsec:
  3368 00000EC3 51                  <1> 		push cx
  3369                              <1> %endif
  3370 00000EC4 92                  <1> 		xchg dx,ax
  3371 00000EC5 66C1E810            <1> 		shr eax,16
  3372 00000EC9 92                  <1> 		xchg dx,ax		; Now EAX = file length
  3373 00000ECA 66BF00001000        <1> 		mov edi, 100000h
  3374 00000ED0 E8060A              <1> 		call load_high
  3375 00000ED3 E8AA05              <1> 		call crlf
  3376                              <1> 
  3377                              <1> %if IS_SYSLINUX
  3378 00000ED6 59                  <1> 		pop cx
  3379                              <1> %endif
  3380                              <1> 
  3381 00000ED7 6681EF00001000      <1> 		sub edi,100000h
  3382 00000EDE 6657                <1> 		push edi		; Save length
  3383                              <1> 
  3384                              <1> %if IS_SYSLINUX
  3385 00000EE0 E313                <1> 		jcxz .not_bss
  3386                              <1> 
  3387                              <1> 		; For a BSS boot sector we have to patch.
  3388 00000EE2 66BE[0B000000]      <1> 		mov esi,superblock
  3389 00000EE8 66BF0B001000        <1> 		mov edi,100000h+(superblock-bootsec)
  3390 00000EEE 660FB7C9            <1> 		movzx ecx,cx
  3391 00000EF2 E8F707              <1> 		call bcopy
  3392                              <1> 
  3393                              <1> .not_bss:
  3394                              <1> %endif
  3395                              <1> ;
  3396                              <1> ; Prepare for shutting down
  3397                              <1> ;
  3398 00000EF5 E8790C              <1> 		call vgaclearmode
  3399 00000EF8 6631D2              <1> 		xor edx,edx
  3400 00000EFB 6631C0              <1> 		xor eax,eax
  3401                              <1> %if IS_SYSLINUX
  3402 00000EFE 8A16[2400]          <1> 		mov dl,[bsDriveNumber]
  3403                              <1> 
  3404 00000F02 BE[E0FF]            <1> 		mov si,PartInfo
  3405 00000F05 BFEE07              <1> 		mov di,800h-18		; Put partition info here
  3406 00000F08 57                  <1> 		push di
  3407 00000F09 B90800              <1> 		mov cx,8		; 16 bytes
  3408 00000F0C F3A5                <1> 		rep movsw
  3409 00000F0E 5E                  <1> 		pop si			; DS:SI points to partition info
  3410                              <1> %elif IS_ISOLINUX
  3411                              <1> 		mov dl,[DriveNo]
  3412                              <1> %elif IS_PXELINUX
  3413                              <1> 		; Close the UDP stack so the PXE stack is in a known state for
  3414                              <1> 		; the new NBP
  3415                              <1> 		call reset_pxe
  3416                              <1> %endif
  3417                              <1> 
  3418 00000F0F 6659                <1> 		pop ecx			; Byte count to copy
  3419                              <1> 
  3420 00000F11 FA                  <1> 		cli
  3421 00000F12 6631DB              <1> 		xor ebx,ebx
  3422 00000F15 8EDB                <1> 		mov ds,bx
  3423 00000F17 8EC3                <1> 		mov es,bx
  3424                              <1> %if IS_PXELINUX
  3425                              <1> 		lss sp,[InitStack]	; Reset stack to PXE original
  3426                              <1> %else
  3427 00000F19 66BC007C0000        <1> 		mov esp,7C00h
  3428 00000F1F 6660                <1> 		pushad
  3429 00000F21 669C                <1> 		pushfd
  3430 00000F23 53                  <1> 		push bx	; ds
  3431 00000F24 53                  <1> 		push bx ; es
  3432 00000F25 53                  <1> 		push bx ; fs
  3433 00000F26 53                  <1> 		push bx	; gs
  3434                              <1> %endif
  3435                              <1> 
  3436 00000F27 66BE00001000        <1> 		mov esi,100000h		; Copy from...
  3437 00000F2D 66BF007C0000        <1> 		mov edi,7C00h		; Copy to...
  3438                              <1> 
  3439 00000F33 E95409              <1> 		jmp bcopy_over_self
  3440                              <1> 
  3441                              <1> %if IS_SYSLINUX = 0
  3442                              <1> is_bss_sector:
  3443                              <1> 		mov si,err_bssimage
  3444                              <1> 		call cwritestr
  3445                              <1> 		jmp enter_command
  3446                              <1> %endif
  3447                                  
  3448                                  ;
  3449                                  ; abort_check: let the user abort with <ESC> or <Ctrl-C>
  3450                                  ;
  3451                                  abort_check:
  3452 00000F36 E8E804                  		call pollchar
  3453 00000F39 7423                    		jz ac_ret1
  3454 00000F3B 60                      		pusha
  3455 00000F3C E80C05                  		call getchar
  3456 00000F3F 3C1B                    		cmp al,27			; <ESC>
  3457 00000F41 7404                    		je ac_kill
  3458 00000F43 3C03                    		cmp al,3			; <Ctrl-C>
  3459 00000F45 7516                    		jne ac_ret2
  3460 00000F47 BE[7C1F]                ac_kill:	mov si,aborted_msg
  3461                                  
  3462                                  ;
  3463                                  ; abort_load: Called by various routines which wants to print a fatal
  3464                                  ;             error message and return to the command prompt.  Since this
  3465                                  ;             may happen at just about any stage of the boot process, assume
  3466                                  ;             our state is messed up, and just reset the segment registers
  3467                                  ;             and the stack forcibly.
  3468                                  ;
  3469                                  ;             SI    = offset (in _text) of error message to print
  3470                                  ;
  3471                                  abort_load:
  3472 00000F4A 8CC8                                    mov ax,cs                       ; Restore CS = DS = ES
  3473 00000F4C 8ED8                                    mov ds,ax
  3474 00000F4E 8EC0                                    mov es,ax
  3475 00000F50 FA                                      cli
  3476 00000F51 BC[DAFF]                                mov sp,StackBuf-2*3    		; Reset stack
  3477 00000F54 8ED0                                    mov ss,ax                       ; Just in case...
  3478 00000F56 FB                                      sti
  3479 00000F57 E82905                                  call cwritestr                  ; Expects SI -> error msg
  3480 00000F5A E9FFF4                  al_ok:          jmp enter_command               ; Return to command prompt
  3481                                  ;
  3482                                  ; End of abort_check
  3483                                  ;
  3484 00000F5D 61                      ac_ret2:	popa
  3485 00000F5E C3                      ac_ret1:	ret
  3486                                  
  3487                                  ;
  3488                                  ; searchdir: Search the root directory for a pre-mangled filename in
  3489                                  ;	     DS:DI.  This routine is similar to the one in the boot
  3490                                  ;	     sector, but is a little less Draconian when it comes to
  3491                                  ;	     error handling, plus it reads the root directory in
  3492                                  ;	     larger chunks than a sector at a time (which is probably
  3493                                  ;	     a waste of coding effort, but I like to do things right).
  3494                                  ;
  3495                                  ;	     FIXME: usually we can load the entire root dir in memory,
  3496                                  ;	     and files are usually at the beginning anyway.  It probably
  3497                                  ;	     would be worthwhile to remember if we have the first chunk
  3498                                  ;	     in memory and skip the load if that (it would speed up online
  3499                                  ;	     help, mainly.)
  3500                                  ;
  3501                                  ;	     NOTE: This file considers finding a zero-length file an
  3502                                  ;	     error.  This is so we don't have to deal with that special
  3503                                  ;	     case elsewhere in the program (most loops have the test
  3504                                  ;	     at the end).
  3505                                  ;
  3506                                  ;	     If successful:
  3507                                  ;		ZF clear
  3508                                  ;		SI	= cluster # for the first cluster
  3509                                  ;		DX:AX	= file length in bytes
  3510                                  ;	     If unsuccessful
  3511                                  ;		ZF set
  3512                                  ;
  3513                                  
  3514                                  searchdir:
  3515 00000F5F A1[1100]                		mov ax,[bsRootDirEnts]
  3516 00000F62 A33A55                  		mov [DirScanCtr],ax
  3517 00000F65 A13855                  		mov ax,[RootDirSize]
  3518 00000F68 A38855                  		mov [DirBlocksLeft],ax
  3519 00000F6B 66A13055                		mov eax,[RootDir]
  3520                                  scan_group:
  3521 00000F6F 660FB72E8855            		movzx ebp,word [DirBlocksLeft]
  3522 00000F75 21ED                    		and bp,bp
  3523 00000F77 745D                    		jz dir_return
  3524 00000F79 3B2E8E55                		cmp bp,[BufSafeSec]
  3525 00000F7D 7604                    		jna load_last
  3526 00000F7F 8B2E8E55                		mov bp,[BufSafeSec]
  3527                                  load_last:
  3528 00000F83 292E8855                		sub [DirBlocksLeft],bp
  3529 00000F87 6650                    		push eax
  3530 00000F89 A1[0B00]                		mov ax,[bsBytesPerSec]
  3531 00000F8C F7E5                    		mul bp
  3532 00000F8E 05E10F                  		add ax,trackbuf-31
  3533 00000F91 A33C55                  		mov [EndofDirSec],ax	; End of loaded
  3534 00000F94 6658                    		pop eax
  3535 00000F96 BB0010                  		mov bx,trackbuf
  3536 00000F99 E8D9F3                  		call getlinsecsr
  3537 00000F9C BE0010                  		mov si,trackbuf
  3538 00000F9F 803C00                  dir_test_name:	cmp byte [si],0		; Directory high water mark
  3539 00000FA2 7432                    		je dir_return		; Failed
  3540 00000FA4 F6440B18                                test byte [si+11],18h	; Check it really is a file
  3541 00000FA8 750B                                    jnz dir_not_this
  3542 00000FAA 57                      		push di
  3543 00000FAB 56                      		push si
  3544 00000FAC B90B00                  		mov cx,11		; Filename = 11 bytes
  3545 00000FAF F3A6                    		repe cmpsb
  3546 00000FB1 5E                      		pop si
  3547 00000FB2 5F                      		pop di
  3548 00000FB3 7414                    		je dir_success
  3549 00000FB5 83C620                  dir_not_this:   add si,byte 32
  3550 00000FB8 FF0E3A55                		dec word [DirScanCtr]
  3551 00000FBC 7418                    		jz dir_return		; Out of it...
  3552 00000FBE 3B363C55                		cmp si,[EndofDirSec]
  3553 00000FC2 72DB                    		jb dir_test_name
  3554 00000FC4 6601E8                  		add eax,ebp		; Increment linear sector number
  3555 00000FC7 EBA6                    		jmp short scan_group
  3556                                  dir_success:
  3557 00000FC9 8B441C                  		mov ax,[si+28]		; Length of file
  3558 00000FCC 8B541E                  		mov dx,[si+30]
  3559 00000FCF 8B741A                  		mov si,[si+26]		; Cluster pointer
  3560 00000FD2 89C3                    		mov bx,ax
  3561 00000FD4 09D3                    		or bx,dx		; Sets ZF iff DX:AX is zero
  3562                                  dir_return:
  3563 00000FD6 C3                      		ret
  3564                                  
  3565                                  ;
  3566                                  ; writechr:	Write a single character in AL to the console without
  3567                                  ;		mangling any registers
  3568                                  ;
  3569                                  writechr:
  3570 00000FD7 E80904                  		call write_serial	; write to serial port if needed
  3571 00000FDA 669C                    		pushfd
  3572 00000FDC 6660                    		pushad
  3573 00000FDE B40E                    		mov ah,0Eh
  3574 00000FE0 BB0700                  		mov bx,0007h		; white text on this page
  3575 00000FE3 CD10                    		int 10h
  3576 00000FE5 6661                    		popad
  3577 00000FE7 669D                    		popfd
  3578 00000FE9 C3                      		ret
  3579                                  
  3580                                  ;
  3581                                  ;
  3582                                  ; kaboom2: once everything is loaded, replace the part of kaboom
  3583                                  ;	   starting with "kaboom.patch" with this part
  3584                                  
  3585                                  kaboom2:
  3586 00000FEA BE[231F]                		mov si,err_bootfailed
  3587 00000FED E89304                  		call cwritestr
  3588 00000FF0 E85804                  		call getchar
  3589 00000FF3 E87B0B                  		call vgaclearmode
  3590 00000FF6 CD19                    		int 19h			; And try once more to boot...
  3591 00000FF8 EBFE                    .norge:		jmp short .norge	; If int 19h returned; this is the end
  3592                                  
  3593                                  ;
  3594                                  ; mangle_name: Mangle a DOS filename pointed to by DS:SI into a buffer pointed
  3595                                  ;	       to by ES:DI; ends on encountering any whitespace
  3596                                  ;
  3597                                  
  3598                                  mangle_name:
  3599 00000FFA B90B00                  		mov cx,11			; # of bytes to write
  3600                                  mn_loop:
  3601 00000FFD AC                      		lodsb
  3602 00000FFE 3C20                    		cmp al,' '			; If control or space, end
  3603 00001000 762A                    		jna mn_end
  3604 00001002 3C2E                    		cmp al,'.'			; Period -> space-fill
  3605 00001004 740C                    		je mn_is_period
  3606 00001006 3C61                    		cmp al,'a'
  3607 00001008 721F                    		jb mn_not_lower
  3608 0000100A 3C7A                    		cmp al,'z'
  3609 0000100C 770E                    		ja mn_not_uslower
  3610 0000100E 2C20                    		sub al,020h
  3611 00001010 EB17                    		jmp short mn_not_lower
  3612 00001012 B020                    mn_is_period:	mov al,' '			; We need to space-fill
  3613 00001014 83F903                  mn_period_loop: cmp cx,3			; If <= 3 characters left
  3614 00001017 76E4                    		jbe mn_loop			; Just ignore it
  3615 00001019 AA                      		stosb				; Otherwise, write a period
  3616 0000101A E2F8                    		loop mn_period_loop		; Dec CX and (always) jump
  3617 0000101C 3C81                    mn_not_uslower: cmp al,ucase_low
  3618 0000101E 7209                    		jb mn_not_lower
  3619 00001020 3CA4                    		cmp al,ucase_high
  3620 00001022 7705                    		ja mn_not_lower
  3621 00001024 BB[B00F]                		mov bx,ucase_tab-ucase_low
  3622 00001027 2ED7                                    cs xlatb
  3623 00001029 AA                      mn_not_lower:	stosb
  3624 0000102A E2D1                    		loop mn_loop			; Don't continue if too long
  3625                                  mn_end:
  3626 0000102C B020                    		mov al,' '			; Space-fill name
  3627 0000102E F3AA                    		rep stosb			; Doesn't do anything if CX=0
  3628 00001030 C3                      		ret				; Done
  3629                                  
  3630                                  ;
  3631                                  ; Upper-case table for extended characters; this is technically code page 865,
  3632                                  ; but code page 437 users will probably not miss not being able to use the
  3633                                  ; cent sign in kernel images too much :-)
  3634                                  ;
  3635                                  ; The table only covers the range 129 to 164; the rest we can deal with.
  3636                                  ;
  3637                                  ucase_low	equ 129
  3638                                  ucase_high	equ 164
  3639 00001031 9A90418E418F804545-     ucase_tab	db 154, 144, 'A', 142, 'A', 143, 128, 'EEEIII'
  3640 0000103A 45494949           
  3641 0000103E 8E8F9092924F994F55-     		db 142, 143, 144, 146, 146, 'O', 153, 'OUUY', 153, 154
  3642 00001047 5559999A           
  3643 0000104B 9D9C9D9E9F41494F55-     		db 157, 156, 157, 158, 159, 'AIOU', 165
  3644 00001054 A5                 
  3645                                  
  3646                                  ;
  3647                                  ; unmangle_name: Does the opposite of mangle_name; converts a DOS-mangled
  3648                                  ;                filename to the conventional representation.  This is needed
  3649                                  ;                for the BOOT_IMAGE= parameter for the kernel.
  3650                                  ;                NOTE: A 13-byte buffer is mandatory, even if the string is
  3651                                  ;                known to be shorter.
  3652                                  ;
  3653                                  ;                DS:SI -> input mangled file name
  3654                                  ;                ES:DI -> output buffer
  3655                                  ;
  3656                                  ;                On return, DI points to the first byte after the output name,
  3657                                  ;                which is set to a null byte.
  3658                                  ;
  3659                                  unmangle_name:
  3660 00001055 56                                      push si                 ; Save pointer to original name
  3661 00001056 B90800                                  mov cx,8
  3662 00001059 89FD                                    mov bp,di
  3663 0000105B AC                      un_copy_body:   lodsb
  3664 0000105C E82600                                  call lower_case
  3665 0000105F AA                                      stosb
  3666 00001060 3C20                                    cmp al,' '
  3667 00001062 7602                                    jbe un_cb_space
  3668 00001064 89FD                                    mov bp,di               ; Position of last nonblank+1
  3669 00001066 E2F3                    un_cb_space:    loop un_copy_body
  3670 00001068 89EF                                    mov di,bp
  3671 0000106A B02E                                    mov al,'.'              ; Don't save
  3672 0000106C AA                                      stosb
  3673 0000106D B90300                                  mov cx,3
  3674 00001070 AC                      un_copy_ext:    lodsb
  3675 00001071 E81100                                  call lower_case
  3676 00001074 AA                                      stosb
  3677 00001075 3C20                                    cmp al,' '
  3678 00001077 7602                                    jbe un_ce_space
  3679 00001079 89FD                                    mov bp,di
  3680 0000107B E2F3                    un_ce_space:    loop un_copy_ext
  3681 0000107D 89EF                                    mov di,bp
  3682 0000107F 26C60500                                mov byte [es:di], 0
  3683 00001083 5E                                      pop si
  3684 00001084 C3                                      ret
  3685                                  
  3686                                  ;
  3687                                  ; lower_case: Lower case a character in AL
  3688                                  ;
  3689                                  lower_case:
  3690 00001085 3C41                                    cmp al,'A'
  3691 00001087 7216                                    jb lc_ret
  3692 00001089 3C5A                                    cmp al,'Z'
  3693 0000108B 7703                                    ja lc_1
  3694 0000108D 0C20                                    or al,20h
  3695 0000108F C3                                      ret
  3696 00001090 3C80                    lc_1:           cmp al,lcase_low
  3697 00001092 720B                                    jb lc_ret
  3698 00001094 3CA5                                    cmp al,lcase_high
  3699 00001096 7707                                    ja lc_ret
  3700 00001098 53                                      push bx
  3701 00001099 BB[EE1B]                                mov bx,lcase_tab-lcase_low
  3702 0000109C 2ED7                                   	cs xlatb
  3703 0000109E 5B                                      pop bx
  3704 0000109F C3                      lc_ret:         ret
  3705                                  
  3706                                  ; -----------------------------------------------------------------------------
  3707                                  ;  Common modules
  3708                                  ; -----------------------------------------------------------------------------
  3709                                  
  3710                                  %include "getc.inc"		; getc et al
  3711                              <1> ;; $Id: getc.inc,v 1.3 2002/10/24 22:11:46 hpa Exp $
  3712                              <1> ;; -----------------------------------------------------------------------
  3713                              <1> ;;   
  3714                              <1> ;;   Copyright 1994-2002 H. Peter Anvin - All Rights Reserved
  3715                              <1> ;;
  3716                              <1> ;;   This program is free software; you can redistribute it and/or modify
  3717                              <1> ;;   it under the terms of the GNU General Public License as published by
  3718                              <1> ;;   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
  3719                              <1> ;;   Bostom MA 02111-1307, USA; either version 2 of the License, or
  3720                              <1> ;;   (at your option) any later version; incorporated herein by reference.
  3721                              <1> ;;
  3722                              <1> ;; -----------------------------------------------------------------------
  3723                              <1> 
  3724                              <1> ;;
  3725                              <1> ;; getc.inc
  3726                              <1> ;;
  3727                              <1> ;; Simple file handling library (open, getc, ungetc)
  3728                              <1> ;;
  3729                              <1> 
  3730                              <1> ;
  3731                              <1> ; open,getc:	Load a file a character at a time for parsing in a manner
  3732                              <1> ;		similar to the C library getc routine.	Only one simultaneous
  3733                              <1> ;		use is supported.  Note: "open" trashes the trackbuf.
  3734                              <1> ;
  3735                              <1> ;		open:	Input:	mangled filename in DS:DI
  3736                              <1> ;			Output: ZF set on file not found or zero length
  3737                              <1> ;
  3738                              <1> ;		openfd:	Input:	file handle in SI
  3739                              <1> ;			Output:	none
  3740                              <1> ;
  3741                              <1> ;		getc:	Output: CF set on end of file
  3742                              <1> ;				Character loaded in AL
  3743                              <1> ;
  3744                              <1> open:
  3745 000010A0 E8BCFE              <1> 		call searchdir
  3746 000010A3 7427                <1> 		jz open_return
  3747                              <1> openfd:
  3748 000010A5 9C                  <1> 		pushf
  3749 000010A6 A38455              <1> 		mov [FBytes1],ax
  3750 000010A9 89168655            <1> 		mov [FBytes2],dx
  3751 000010AD 03067055            <1> 		add ax,[ClustSize]
  3752 000010B1 83D200              <1> 		adc dx,byte 0
  3753 000010B4 83E801              <1> 		sub ax,byte 1
  3754 000010B7 83DA00              <1> 		sbb dx,byte 0
  3755 000010BA F7367055            <1> 		div word [ClustSize]
  3756 000010BE A39655              <1> 		mov [FClust],ax		; Number of clusters
  3757 000010C1 89369855            <1> 		mov [FNextClust],si	; Cluster pointer
  3758 000010C5 A19255              <1> 		mov ax,[EndOfGetCBuf]	; Pointer at end of buffer ->
  3759 000010C8 A39A55              <1> 		mov [FPtr],ax		;  nothing loaded yet
  3760 000010CB 9D                  <1> 		popf			; Restore no ZF
  3761 000010CC C3                  <1> open_return:	ret
  3762                              <1> 
  3763                              <1> getc:
  3764 000010CD F9                  <1> 		stc			; If we exit here -> EOF
  3765 000010CE 668B0E8455          <1> 		mov ecx,[FBytes]
  3766 000010D3 67E33B              <1> 		jecxz getc_ret
  3767 000010D6 8B369A55            <1> 		mov si,[FPtr]
  3768 000010DA 3B369255            <1> 		cmp si,[EndOfGetCBuf]
  3769 000010DE 7226                <1> 		jb getc_loaded
  3770                              <1> 		; Buffer empty -- load another set
  3771 000010E0 8B0E9655            <1> 		mov cx,[FClust]
  3772 000010E4 3B0E8C55            <1> 		cmp cx,[BufSafe]
  3773 000010E8 7604                <1> 		jna getc_oksize
  3774 000010EA 8B0E8C55            <1> 		mov cx,[BufSafe]
  3775 000010EE 290E9655            <1> getc_oksize:	sub [FClust],cx		; Reduce remaining clusters
  3776 000010F2 8B369855            <1> 		mov si,[FNextClust]
  3777 000010F6 06                  <1> 		push es			; ES may be != DS, save old ES
  3778 000010F7 1E                  <1> 		push ds
  3779 000010F8 07                  <1> 		pop es
  3780 000010F9 BB00A0              <1> 		mov bx,getcbuf
  3781 000010FC 53                  <1> 		push bx
  3782 000010FD E815F2              <1> 		call getfssec		; Load a trackbuf full of data
  3783 00001100 89369855            <1> 		mov [FNextClust],si	; Store new next pointer
  3784 00001104 5E                  <1> 		pop si			; SI -> newly loaded data
  3785 00001105 07                  <1> 		pop es			; Restore ES
  3786 00001106 AC                  <1> getc_loaded:	lodsb			; Load a byte, increment SI
  3787 00001107 89369A55            <1> 		mov [FPtr],si		; Update next byte pointer
  3788 0000110B 66FF0E8455          <1> 		dec dword [FBytes]	; Update bytes left counter
  3789 00001110 F8                  <1> 		clc			; Not EOF
  3790 00001111 C3                  <1> getc_ret:	ret
  3791                              <1> 
  3792                              <1> ;
  3793                              <1> ; ungetc:	Push a character (in AL) back into the getc buffer
  3794                              <1> ;		Note: if more than one byte is pushed back, this may cause
  3795                              <1> ;		bytes to be written below the getc buffer boundary.  If there
  3796                              <1> ;		is a risk for this to occur, the getcbuf base address should
  3797                              <1> ;		be moved up.
  3798                              <1> ;
  3799                              <1> ungetc:
  3800 00001112 8B369A55            <1> 		mov si,[FPtr]
  3801 00001116 4E                  <1> 		dec si
  3802 00001117 8804                <1> 		mov [si],al
  3803 00001119 89369A55            <1> 		mov [FPtr],si
  3804 0000111D 66FF068455          <1> 		inc dword [FBytes]
  3805 00001122 C3                  <1> 		ret
  3806                              <1> 
  3807                              <1> ;
  3808                              <1> ; skipspace:	Skip leading whitespace using "getc".  If we hit end-of-line
  3809                              <1> ;		or end-of-file, return with carry set; ZF = true of EOF
  3810                              <1> ;		ZF = false for EOLN; otherwise CF = ZF = 0.
  3811                              <1> ;
  3812                              <1> ;		Otherwise AL = first character after whitespace
  3813                              <1> ;
  3814                              <1> skipspace:
  3815 00001123 E8A7FF              <1> skipspace_loop: call getc
  3816 00001126 720D                <1> 		jc skipspace_eof
  3817 00001128 3C1A                <1> 		cmp al,1Ah			; DOS EOF
  3818 0000112A 7409                <1> 		je skipspace_eof
  3819 0000112C 3C0A                <1> 		cmp al,0Ah
  3820 0000112E 7409                <1> 		je skipspace_eoln
  3821 00001130 3C20                <1> 		cmp al,' '
  3822 00001132 76EF                <1> 		jbe skipspace_loop
  3823 00001134 C3                  <1> 		ret				; CF = ZF = 0
  3824 00001135 38C0                <1> skipspace_eof:	cmp al,al			; Set ZF
  3825 00001137 F9                  <1> 		stc				; Set CF
  3826 00001138 C3                  <1> 		ret
  3827 00001139 04FF                <1> skipspace_eoln: add al,0FFh			; Set CF, clear ZF
  3828 0000113B C3                  <1> 		ret
  3829                              <1> 
  3830                              <1> ;
  3831                              <1> ; getint:	Load an integer from the getc file.
  3832                              <1> ;		Return CF if error; otherwise return integer in EBX
  3833                              <1> ;
  3834                              <1> getint:
  3835 0000113C BFA054              <1> 		mov di,NumBuf
  3836 0000113F 81FFAF54            <1> gi_getnum:	cmp di,NumBufEnd	; Last byte in NumBuf
  3837 00001143 730F                <1> 		jae gi_loaded
  3838 00001145 57                  <1> 		push di
  3839 00001146 E884FF              <1> 		call getc
  3840 00001149 5F                  <1> 		pop di
  3841 0000114A 7208                <1> 		jc gi_loaded
  3842 0000114C AA                  <1> 		stosb
  3843 0000114D 3C2D                <1> 		cmp al,'-'
  3844 0000114F 73EE                <1> 		jnb gi_getnum
  3845 00001151 E8BEFF              <1> 		call ungetc		; Unget non-numeric
  3846 00001154 C60500              <1> gi_loaded:	mov byte [di],0
  3847 00001157 BEA054              <1> 		mov si,NumBuf
  3848                              <1> 		; Fall through to parseint
  3849                              <1> 
  3850                              <1> ;
  3851                              <1> ; parseint:	Convert an integer to a number in EBX
  3852                              <1> ;		Get characters from string in DS:SI
  3853                              <1> ;		Return CF on error
  3854                              <1> ;		DS:SI points to first character after number
  3855                              <1> ;
  3856                              <1> ;               Syntaxes accepted: [-]dec, [-]0+oct, [-]0x+hex, val+K, val+M
  3857                              <1> ;
  3858                              <1> parseint:
  3859 0000115A 6650                <1>                 push eax
  3860 0000115C 6651                <1>                 push ecx
  3861 0000115E 55                  <1> 		push bp
  3862 0000115F 6631C0              <1> 		xor eax,eax		; Current digit (keep eax == al)
  3863 00001162 6689C3              <1> 		mov ebx,eax		; Accumulator
  3864 00001165 6689D9              <1> 		mov ecx,ebx		; Base
  3865 00001168 31ED                <1>                 xor bp,bp               ; Used for negative flag
  3866 0000116A AC                  <1> pi_begin:	lodsb
  3867 0000116B 3C2D                <1> 		cmp al,'-'
  3868 0000116D 7505                <1> 		jne pi_not_minus
  3869 0000116F 83F501              <1> 		xor bp,1		; Set unary minus flag
  3870 00001172 EBF6                <1> 		jmp short pi_begin
  3871                              <1> pi_not_minus:
  3872 00001174 3C30                <1> 		cmp al,'0'
  3873 00001176 724F                <1> 		jb pi_err
  3874 00001178 7408                <1> 		je pi_octhex
  3875 0000117A 3C39                <1> 		cmp al,'9'
  3876 0000117C 7749                <1> 		ja pi_err
  3877 0000117E B10A                <1> 		mov cl,10		; Base = decimal
  3878 00001180 EB17                <1> 		jmp short pi_foundbase
  3879                              <1> pi_octhex:
  3880 00001182 AC                  <1> 		lodsb
  3881 00001183 3C30                <1> 		cmp al,'0'
  3882 00001185 7225                <1> 		jb pi_km		; Value is zero
  3883 00001187 0C20                <1> 		or al,20h		; Downcase
  3884 00001189 3C78                <1> 		cmp al,'x'
  3885 0000118B 7408                <1> 		je pi_ishex
  3886 0000118D 3C37                <1> 		cmp al,'7'
  3887 0000118F 7736                <1> 		ja pi_err
  3888 00001191 B108                <1> 		mov cl,8		; Base = octal
  3889 00001193 EB04                <1> 		jmp short pi_foundbase
  3890                              <1> pi_ishex:
  3891 00001195 B030                <1> 		mov al,'0'		; No numeric value accrued yet
  3892 00001197 B110                <1> 		mov cl,16		; Base = hex
  3893                              <1> pi_foundbase:
  3894 00001199 E83A00              <1>                 call unhexchar
  3895 0000119C 720E                <1>                 jc pi_km                ; Not a (hex) digit
  3896 0000119E 38C8                <1>                 cmp al,cl
  3897 000011A0 730A                <1> 		jae pi_km		; Invalid for base
  3898 000011A2 660FAFD9            <1> 		imul ebx,ecx		; Multiply accumulated by base
  3899 000011A6 6601C3              <1>                 add ebx,eax             ; Add current digit
  3900 000011A9 AC                  <1> 		lodsb
  3901 000011AA EBED                <1> 		jmp short pi_foundbase
  3902                              <1> pi_km:
  3903 000011AC 4E                  <1> 		dec si			; Back up to last non-numeric
  3904 000011AD AC                  <1> 		lodsb
  3905 000011AE 0C20                <1> 		or al,20h
  3906 000011B0 3C6B                <1> 		cmp al,'k'
  3907 000011B2 7416                <1> 		je pi_isk
  3908 000011B4 3C6D                <1> 		cmp al,'m'
  3909 000011B6 7418                <1> 		je pi_ism
  3910 000011B8 4E                  <1> 		dec si			; Back up
  3911 000011B9 21ED                <1> pi_fini:	and bp,bp
  3912 000011BB 7404                <1> 		jz pi_ret		; CF=0!
  3913 000011BD 66F7DB              <1> 		neg ebx			; Value was negative
  3914 000011C0 F8                  <1> pi_done:	clc
  3915 000011C1 5D                  <1> pi_ret:		pop bp
  3916 000011C2 6659                <1>                 pop ecx
  3917 000011C4 6658                <1>                 pop eax
  3918 000011C6 C3                  <1> 		ret
  3919 000011C7 F9                  <1> pi_err:		stc
  3920 000011C8 EBF7                <1> 		jmp short pi_ret
  3921 000011CA 66C1E30A            <1> pi_isk:		shl ebx,10		; x 2^10
  3922 000011CE EBF0                <1> 		jmp short pi_done
  3923 000011D0 66C1E314            <1> pi_ism:		shl ebx,20		; x 2^20
  3924 000011D4 EBEA                <1> 		jmp short pi_done
  3925                              <1> 
  3926                              <1> ;
  3927                              <1> ; unhexchar:    Convert a hexadecimal digit in AL to the equivalent number;
  3928                              <1> ;               return CF=1 if not a hex digit
  3929                              <1> ;
  3930                              <1> unhexchar:
  3931 000011D6 3C30                <1>                 cmp al,'0'
  3932 000011D8 7215                <1> 		jb uxc_ret		; If failure, CF == 1 already
  3933 000011DA 3C39                <1>                 cmp al,'9'
  3934 000011DC 7703                <1>                 ja uxc_1
  3935 000011DE 2C30                <1> 		sub al,'0'		; CF <- 0
  3936 000011E0 C3                  <1> 		ret
  3937 000011E1 0C20                <1> uxc_1:          or al,20h		; upper case -> lower case
  3938 000011E3 3C61                <1> 		cmp al,'a'
  3939 000011E5 7208                <1>                 jb uxc_ret		; If failure, CF == 1 already
  3940 000011E7 3C66                <1>                 cmp al,'f'
  3941 000011E9 7703                <1>                 ja uxc_err
  3942 000011EB 2C57                <1>                 sub al,'a'-10           ; CF <- 0
  3943 000011ED C3                  <1>                 ret
  3944 000011EE F9                  <1> uxc_err:        stc
  3945 000011EF C3                  <1> uxc_ret:	ret
  3946                              <1> 
  3947                              <1> ;
  3948                              <1> ;
  3949                              <1> ; getline:	Get a command line, converting control characters to spaces
  3950                              <1> ;               and collapsing streches to one; a space is appended to the
  3951                              <1> ;               end of the string, unless the line is empty.
  3952                              <1> ;		The line is terminated by ^J, ^Z or EOF and is written
  3953                              <1> ;		to ES:DI.  On return, DI points to first char after string.
  3954                              <1> ;		CF is set if we hit EOF.
  3955                              <1> ;
  3956                              <1> getline:
  3957 000011F0 E830FF              <1> 		call skipspace
  3958 000011F3 B201                <1>                 mov dl,1                ; Empty line -> empty string.
  3959 000011F5 742B                <1>                 jz gl_eof               ; eof
  3960 000011F7 7226                <1>                 jc gl_eoln              ; eoln
  3961 000011F9 E816FF              <1> 		call ungetc
  3962 000011FC 52                  <1> gl_fillloop:	push dx
  3963 000011FD 57                  <1> 		push di
  3964 000011FE E8CCFE              <1> 		call getc
  3965 00001201 5F                  <1> 		pop di
  3966 00001202 5A                  <1> 		pop dx
  3967 00001203 721E                <1> 		jc gl_ret		; CF set!
  3968 00001205 3C20                <1> 		cmp al,' '
  3969 00001207 7605                <1> 		jna gl_ctrl
  3970 00001209 31D2                <1> 		xor dx,dx
  3971 0000120B AA                  <1> gl_store:	stosb
  3972 0000120C EBEE                <1> 		jmp short gl_fillloop
  3973 0000120E 3C0A                <1> gl_ctrl:	cmp al,10
  3974 00001210 7411                <1> 		je gl_ret		; CF clear!
  3975 00001212 3C1A                <1> 		cmp al,26
  3976 00001214 740C                <1> 		je gl_eof
  3977 00001216 20D2                <1> 		and dl,dl
  3978 00001218 75E2                <1> 		jnz gl_fillloop		; Ignore multiple spaces
  3979 0000121A B020                <1> 		mov al,' '		; Ctrl -> space
  3980 0000121C 42                  <1> 		inc dx
  3981 0000121D EBEC                <1> 		jmp short gl_store
  3982 0000121F F8                  <1> gl_eoln:        clc                     ; End of line is not end of file
  3983 00001220 EB01                <1>                 jmp short gl_ret
  3984 00001222 F9                  <1> gl_eof:         stc
  3985 00001223 9C                  <1> gl_ret:		pushf			; We want the last char to be space!
  3986 00001224 20D2                <1> 		and dl,dl
  3987 00001226 7503                <1> 		jnz gl_xret
  3988 00001228 B020                <1> 		mov al,' '
  3989 0000122A AA                  <1> 		stosb
  3990 0000122B 9D                  <1> gl_xret:	popf
  3991 0000122C C3                  <1> 		ret
  3992                                  %include "conio.inc"		; Console I/O
  3993                              <1> ;; $Id: conio.inc,v 1.3 2002/06/11 05:48:29 hpa Exp $
  3994                              <1> ;; -----------------------------------------------------------------------
  3995                              <1> ;;   
  3996                              <1> ;;   Copyright 1994-2002 H. Peter Anvin - All Rights Reserved
  3997                              <1> ;;
  3998                              <1> ;;   This program is free software; you can redistribute it and/or modify
  3999                              <1> ;;   it under the terms of the GNU General Public License as published by
  4000                              <1> ;;   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
  4001                              <1> ;;   Bostom MA 02111-1307, USA; either version 2 of the License, or
  4002                              <1> ;;   (at your option) any later version; incorporated herein by reference.
  4003                              <1> ;;
  4004                              <1> ;; -----------------------------------------------------------------------
  4005                              <1> 
  4006                              <1> ;;
  4007                              <1> ;; conio.inc
  4008                              <1> ;;
  4009                              <1> ;; Console I/O code, except:
  4010                              <1> ;;   writechr, writestr		- module-dependent
  4011                              <1> ;;   cwritestr, crlf		- writestr.inc
  4012                              <1> ;;   writehex*			- writehex.inc
  4013                              <1> ;;
  4014                              <1> 
  4015                              <1> ;
  4016                              <1> ; loadkeys:	Load a LILO-style keymap; SI and DX:AX set by searchdir
  4017                              <1> ;
  4018                              <1> loadkeys:
  4019 0000122D 21D2                <1> 		and dx,dx			; Should be 256 bytes exactly
  4020 0000122F 751A                <1> 		jne loadkeys_ret
  4021 00001231 3D0001              <1> 		cmp ax,256
  4022 00001234 7515                <1> 		jne loadkeys_ret
  4023                              <1> 
  4024 00001236 BB0010              <1> 		mov bx,trackbuf
  4025 00001239 B90100              <1> 		mov cx,1			; 1 cluster should be >= 256 bytes
  4026 0000123C E8D6F0              <1> 		call getfssec
  4027                              <1> 
  4028 0000123F BE0010              <1> 		mov si,trackbuf
  4029 00001242 BF0053              <1> 		mov di,KbdMap
  4030 00001245 B94000              <1> 		mov cx,256 >> 2
  4031 00001248 F366A5              <1> 		rep movsd
  4032                              <1> 
  4033 0000124B C3                  <1> loadkeys_ret:	ret
  4034                              <1> 		
  4035                              <1> ;
  4036                              <1> ; get_msg_file: Load a text file and write its contents to the screen,
  4037                              <1> ;               interpreting color codes.  Is called with SI and DX:AX
  4038                              <1> ;               set by routine searchdir
  4039                              <1> ;
  4040                              <1> get_msg_file:
  4041 0000124C 06                  <1> 		push es
  4042 0000124D 66C1E210            <1> 		shl edx,16			; EDX <- DX:AX (length of file)
  4043 00001251 89C2                <1> 		mov dx,ax
  4044 00001253 B80030              <1> 		mov ax,xfer_buf_seg		; Use for temporary storage
  4045 00001256 8EC0                <1> 		mov es,ax
  4046                              <1> 
  4047 00001258 C606B45507          <1>                 mov byte [TextAttribute],07h	; Default grey on white
  4048 0000125D C606C45507          <1> 		mov byte [DisplayMask],07h	; Display text in all modes
  4049 00001262 E86001              <1> 		call msg_initvars
  4050                              <1> 
  4051 00001265 6652                <1> get_msg_chunk:  push edx			; EDX = length of file
  4052 00001267 31DB                <1> 		xor bx,bx			; == xbs_textbuf
  4053 00001269 8B0E8C55            <1> 		mov cx,[BufSafe]
  4054 0000126D E8A5F0              <1> 		call getfssec
  4055 00001270 665A                <1> 		pop edx
  4056 00001272 56                  <1> 		push si				; Save current cluster
  4057 00001273 31F6                <1> 		xor si,si			; == xbs_textbuf
  4058 00001275 8B0E9055            <1> 		mov cx,[BufSafeBytes]		; Number of bytes left in chunk
  4059                              <1> print_msg_file:
  4060 00001279 51                  <1> 		push cx
  4061 0000127A 6652                <1> 		push edx
  4062 0000127C 26AC                <1> 		es lodsb
  4063 0000127E 3C1A                <1>                 cmp al,1Ah                      ; DOS EOF?
  4064 00001280 7418                <1> 		je msg_done_pop
  4065 00001282 56                  <1> 		push si
  4066 00001283 8A0E[C81B]          <1> 		mov cl,[UsingVGA]
  4067 00001287 FEC1                <1> 		inc cl				; 01h = text mode, 02h = graphics
  4068 00001289 FF16A255            <1>                 call [NextCharJump]		; Do what shall be done
  4069 0000128D 5E                  <1> 		pop si
  4070 0000128E 665A                <1> 		pop edx
  4071 00001290 59                  <1>                 pop cx
  4072 00001291 664A                <1> 		dec edx
  4073 00001293 7408                <1> 		jz msg_done
  4074 00001295 E2E2                <1> 		loop print_msg_file
  4075 00001297 5E                  <1> 		pop si
  4076 00001298 EBCB                <1> 		jmp short get_msg_chunk
  4077                              <1> msg_done_pop:
  4078 0000129A 83C406              <1>                 add sp,byte 6			; Drop pushed EDX, CX
  4079                              <1> msg_done:
  4080 0000129D 5E                  <1> 		pop si
  4081 0000129E 07                  <1> 		pop es
  4082 0000129F C3                  <1> 		ret
  4083                              <1> msg_putchar:                                    ; Normal character
  4084 000012A0 3C0F                <1>                 cmp al,0Fh                      ; ^O = color code follows
  4085 000012A2 744E                <1>                 je msg_ctrl_o
  4086 000012A4 3C0D                <1>                 cmp al,0Dh                      ; Ignore <CR>
  4087 000012A6 7449                <1>                 je msg_ignore
  4088 000012A8 3C0A                <1>                 cmp al,0Ah                      ; <LF> = newline
  4089 000012AA 744D                <1>                 je msg_newline
  4090 000012AC 3C0C                <1>                 cmp al,0Ch                      ; <FF> = clear screen
  4091 000012AE 747E                <1>                 je msg_formfeed
  4092 000012B0 3C19                <1> 		cmp al,19h			; <EM> = return to text mode
  4093 000012B2 0F84F300            <1> 		je msg_novga
  4094 000012B6 3C18                <1> 		cmp al,18h			; <CAN> = VGA filename follows
  4095 000012B8 0F84BC00            <1> 		je msg_vga
  4096 000012BC 7306                <1> 		jnb .not_modectl
  4097 000012BE 3C10                <1> 		cmp al,10h			; 10h to 17h are mode controls
  4098 000012C0 0F831101            <1> 		jae msg_modectl
  4099                              <1> .not_modectl:
  4100                              <1> 
  4101 000012C4 E81501              <1> msg_normal:	call write_serial_displaymask	; Write to serial port
  4102 000012C7 840EC455            <1> 		test [DisplayMask],cl
  4103 000012CB 7424                <1> 		jz msg_ignore			; Not screen
  4104 000012CD 8B1EB455            <1>                 mov bx,[TextAttrBX]
  4105 000012D1 B409                <1>                 mov ah,09h                      ; Write character/attribute
  4106 000012D3 B90100              <1>                 mov cx,1                        ; One character only
  4107 000012D6 CD10                <1>                 int 10h                         ; Write to screen
  4108 000012D8 A0B655              <1>                 mov al,[CursorCol]
  4109 000012DB 40                  <1>                 inc ax
  4110 000012DC 3A06B855            <1>                 cmp al,[VidCols]
  4111 000012E0 771D                <1>                 ja msg_line_wrap		; Screen wraparound
  4112 000012E2 A2B655              <1>                 mov [CursorCol],al
  4113                              <1> 
  4114 000012E5 8A3EB555            <1> msg_gotoxy:     mov bh,[TextPage]
  4115 000012E9 8B16B655            <1>                 mov dx,[CursorDX]
  4116 000012ED B402                <1>                 mov ah,02h                      ; Set cursor position
  4117 000012EF CD10                <1>                 int 10h
  4118 000012F1 C3                  <1> msg_ignore:     ret
  4119                              <1> msg_ctrl_o:                                     ; ^O = color code follows
  4120 000012F2 C706A255[4F13]      <1>                 mov word [NextCharJump],msg_setbg
  4121 000012F8 C3                  <1>                 ret
  4122                              <1> msg_newline:                                    ; Newline char or end of line
  4123 000012F9 BE[851F]            <1> 		mov si,crlf_msg
  4124 000012FC E81001              <1> 		call write_serial_str_displaymask
  4125                              <1> msg_line_wrap:					; Screen wraparound
  4126 000012FF 840EC455            <1> 		test [DisplayMask],cl
  4127 00001303 74EC                <1> 		jz msg_ignore
  4128 00001305 C606B65500          <1>                 mov byte [CursorCol],0
  4129 0000130A A0B755              <1>                 mov al,[CursorRow]
  4130 0000130D 40                  <1>                 inc ax
  4131 0000130E 3A06B955            <1>                 cmp al,[VidRows]
  4132 00001312 7705                <1>                 ja msg_scroll
  4133 00001314 A2B755              <1>                 mov [CursorRow],al
  4134 00001317 EBCC                <1>                 jmp short msg_gotoxy
  4135 00001319 31C9                <1> msg_scroll:     xor cx,cx                       ; Upper left hand corner
  4136 0000131B 8B16B855            <1>                 mov dx,[ScreenSize]
  4137 0000131F 8836B755            <1>                 mov [CursorRow],dh		; New cursor at the bottom
  4138 00001323 8A3E[8320]          <1>                 mov bh,[ScrollAttribute]
  4139 00001327 B80106              <1>                 mov ax,0601h                    ; Scroll up one line
  4140 0000132A CD10                <1>                 int 10h
  4141 0000132C EBB7                <1>                 jmp short msg_gotoxy
  4142                              <1> msg_formfeed:                                   ; Form feed character
  4143 0000132E BE[881F]            <1> 		mov si,crff_msg
  4144 00001331 E8DB00              <1> 		call write_serial_str_displaymask
  4145 00001334 840EC455            <1> 		test [DisplayMask],cl
  4146 00001338 74B7                <1> 		jz msg_ignore
  4147 0000133A 31C9                <1>                 xor cx,cx
  4148 0000133C 890EB655            <1>                 mov [CursorDX],cx		; Upper lefthand corner
  4149 00001340 8B16B855            <1>                 mov dx,[ScreenSize]
  4150 00001344 8A3EB455            <1>                 mov bh,[TextAttribute]
  4151 00001348 B80006              <1>                 mov ax,0600h                    ; Clear screen region
  4152 0000134B CD10                <1>                 int 10h
  4153 0000134D EB96                <1>                 jmp msg_gotoxy
  4154                              <1> msg_setbg:                                      ; Color background character
  4155 0000134F E884FE              <1>                 call unhexchar
  4156 00001352 722F                <1>                 jc msg_color_bad
  4157 00001354 C0E004              <1>                 shl al,4
  4158 00001357 840EC455            <1> 		test [DisplayMask],cl
  4159 0000135B 7403                <1> 		jz .dontset
  4160 0000135D A2B455              <1>                 mov [TextAttribute],al
  4161                              <1> .dontset:
  4162 00001360 C706A255[6713]      <1>                 mov word [NextCharJump],msg_setfg
  4163 00001366 C3                  <1>                 ret
  4164                              <1> msg_setfg:                                      ; Color foreground character
  4165 00001367 E86CFE              <1>                 call unhexchar
  4166 0000136A 7217                <1>                 jc msg_color_bad
  4167 0000136C 840EC455            <1> 		test [DisplayMask],cl
  4168 00001370 7404                <1> 		jz .dontset
  4169 00001372 0806B455            <1>                 or [TextAttribute],al		; setbg set foreground to 0
  4170                              <1> .dontset:
  4171 00001376 EB10                <1> 		jmp short msg_putcharnext
  4172                              <1> msg_vga:
  4173 00001378 C706A255[8F13]      <1> 		mov word [NextCharJump],msg_filename
  4174 0000137E BF0656              <1> 		mov di, VGAFileBuf
  4175 00001381 EB21                <1> 		jmp short msg_setvgafileptr
  4176                              <1> 
  4177                              <1> msg_color_bad:
  4178 00001383 C606B45507          <1>                 mov byte [TextAttribute],07h	; Default attribute
  4179                              <1> msg_putcharnext:
  4180 00001388 C706A255[A012]      <1>                 mov word [NextCharJump],msg_putchar
  4181 0000138E C3                  <1> 		ret
  4182                              <1> 
  4183                              <1> msg_filename:					; Getting VGA filename
  4184 0000138F 3C0A                <1> 		cmp al,0Ah			; <LF> = end of filename
  4185 00001391 741B                <1> 		je msg_viewimage
  4186 00001393 3C20                <1> 		cmp al,' '
  4187 00001395 7611                <1> 		jbe msg_ret			; Ignore space/control char
  4188 00001397 8B3EB255            <1> 		mov di,[VGAFilePtr]
  4189 0000139B 81FF1356            <1> 		cmp di,VGAFileBufEnd
  4190 0000139F 7307                <1> 		jnb msg_ret
  4191 000013A1 8805                <1> 		mov [di],al			; Can't use stosb (DS:)
  4192 000013A3 47                  <1> 		inc di
  4193                              <1> msg_setvgafileptr:
  4194 000013A4 893EB255            <1> 		mov [VGAFilePtr],di
  4195 000013A8 C3                  <1> msg_ret:	ret
  4196                              <1> 
  4197                              <1> msg_novga:
  4198 000013A9 E8C507              <1> 		call vgaclearmode
  4199 000013AC EB17                <1> 		jmp short msg_initvars
  4200                              <1> 
  4201                              <1> msg_viewimage:
  4202 000013AE 06                  <1> 		push es
  4203 000013AF 1E                  <1> 		push ds
  4204 000013B0 07                  <1> 		pop es				; ES <- DS
  4205 000013B1 BE0656              <1> 		mov si,VGAFileBuf
  4206 000013B4 BF1356              <1> 		mov di,VGAFileMBuf
  4207 000013B7 57                  <1> 		push di
  4208 000013B8 E83FFC              <1> 		call mangle_name
  4209 000013BB 5F                  <1> 		pop di
  4210 000013BC E8A0FB              <1> 		call searchdir
  4211 000013BF 07                  <1> 		pop es
  4212 000013C0 74C6                <1> 		jz msg_putcharnext		; Not there
  4213 000013C2 E82606              <1> 		call vgadisplayfile
  4214                              <1> 		; Fall through
  4215                              <1> 
  4216                              <1> 		; Subroutine to initialize variables, also needed
  4217                              <1> 		; after loading a graphics file
  4218                              <1> msg_initvars:
  4219 000013C5 60                  <1>                 pusha
  4220 000013C6 8A3EB555            <1>                 mov bh,[TextPage]
  4221 000013CA B403                <1>                 mov ah,03h                      ; Read cursor position
  4222 000013CC CD10                <1>                 int 10h
  4223 000013CE 8916B655            <1>                 mov [CursorDX],dx
  4224 000013D2 61                  <1>                 popa
  4225 000013D3 EBB3                <1> 		jmp short msg_putcharnext	; Initialize state machine
  4226                              <1> 
  4227                              <1> msg_modectl:
  4228 000013D5 2407                <1> 		and al,07h
  4229 000013D7 A2C455              <1> 		mov [DisplayMask],al
  4230 000013DA EBAC                <1> 		jmp short msg_putcharnext
  4231                              <1> 
  4232                              <1> ;
  4233                              <1> ; write_serial:	If serial output is enabled, write character on serial port
  4234                              <1> ; write_serial_displaymask: d:o, but ignore if DisplayMask & 04h == 0
  4235                              <1> ;
  4236                              <1> write_serial_displaymask:
  4237 000013DC F606C45504          <1> 		test byte [DisplayMask], 04h
  4238 000013E1 742B                <1> 		jz write_serial.end
  4239                              <1> write_serial:
  4240 000013E3 669C                <1> 		pushfd
  4241 000013E5 6660                <1> 		pushad
  4242 000013E7 8B1E[7E20]          <1> 		mov bx,[SerialPort]
  4243 000013EB 21DB                <1> 		and bx,bx
  4244 000013ED 741B                <1> 		je .noserial
  4245 000013EF 50                  <1> 		push ax
  4246 000013F0 8A26BD55            <1> 		mov ah,[FlowInput]
  4247                              <1> .waitspace:
  4248                              <1> 		; Wait for space in transmit register
  4249 000013F4 8D5705              <1> 		lea dx,[bx+5]			; DX -> LSR
  4250 000013F7 EC                  <1> 		in al,dx
  4251 000013F8 A820                <1> 		test al,20h
  4252 000013FA 74F8                <1> 		jz .waitspace
  4253                              <1> 
  4254                              <1> 		; Wait for input flow control
  4255 000013FC 42                  <1> 		inc dx				; DX -> MSR
  4256 000013FD EC                  <1> 		in al,dx
  4257 000013FE 20E0                <1> 		and al,ah
  4258 00001400 38E0                <1> 		cmp al,ah
  4259 00001402 75F0                <1> 		jne .waitspace	
  4260                              <1> .no_flow:		
  4261                              <1> 
  4262 00001404 87D3                <1> 		xchg dx,bx			; DX -> THR
  4263 00001406 58                  <1> 		pop ax
  4264 00001407 E86803              <1> 		call slow_out			; Send data
  4265 0000140A 6661                <1> .noserial:	popad
  4266 0000140C 669D                <1> 		popfd
  4267 0000140E C3                  <1> .end:		ret
  4268                              <1> 
  4269                              <1> ;
  4270                              <1> ; write_serial_str: write_serial for strings
  4271                              <1> ; write_serial_str_displaymask: d:o, but ignore if DisplayMask & 04h == 0
  4272                              <1> ;
  4273                              <1> write_serial_str_displaymask:
  4274 0000140F F606C45504          <1> 		test byte [DisplayMask], 04h
  4275 00001414 740A                <1> 		jz write_serial_str.end
  4276                              <1> 
  4277                              <1> write_serial_str:
  4278 00001416 AC                  <1> .loop		lodsb
  4279 00001417 20C0                <1> 		and al,al
  4280 00001419 7405                <1> 		jz .end
  4281 0000141B E8C5FF              <1> 		call write_serial
  4282 0000141E EBF6                <1> 		jmp short .loop
  4283 00001420 C3                  <1> .end:		ret
  4284                              <1> 
  4285                              <1> ;
  4286                              <1> ; pollchar: check if we have an input character pending (ZF = 0)
  4287                              <1> ;
  4288                              <1> pollchar:
  4289 00001421 6660                <1> 		pushad
  4290 00001423 B401                <1> 		mov ah,1		; Poll keyboard
  4291 00001425 CD16                <1> 		int 16h
  4292 00001427 751F                <1> 		jnz .done		; Keyboard response
  4293 00001429 8B16[7E20]          <1> 		mov dx,[SerialPort]
  4294 0000142D 21D2                <1> 		and dx,dx
  4295 0000142F 7417                <1> 		jz .done		; No serial port -> no input
  4296 00001431 83C205              <1> 		add dx,byte 5		; DX -> LSR
  4297 00001434 EC                  <1> 		in al,dx
  4298 00001435 A801                <1> 		test al,1		; ZF = 0 if data pending
  4299 00001437 740F                <1> 		jz .done
  4300 00001439 42                  <1> 		inc dx			; DX -> MSR
  4301 0000143A 8A26BE55            <1> 		mov ah,[FlowIgnore]	; Required status bits
  4302 0000143E EC                  <1> 		in al,dx
  4303 0000143F 20E0                <1> 		and al,ah
  4304 00001441 38E0                <1> 		cmp al,ah
  4305 00001443 0F95C0              <1> 		setne al
  4306 00001446 FEC8                <1> 		dec al			; Set ZF = 0 if equal
  4307 00001448 6661                <1> .done:		popad
  4308 0000144A C3                  <1> 		ret
  4309                              <1> 
  4310                              <1> ;
  4311                              <1> ; getchar: Read a character from keyboard or serial port
  4312                              <1> ;
  4313                              <1> getchar:
  4314 0000144B B401                <1> .again:		mov ah,1		; Poll keyboard
  4315 0000144D CD16                <1> 		int 16h
  4316 0000144F 7522                <1> 		jnz .kbd		; Keyboard input?
  4317 00001451 8B1E[7E20]          <1> 		mov bx,[SerialPort]
  4318 00001455 21DB                <1> 		and bx,bx
  4319 00001457 74F2                <1> 		jz .again
  4320 00001459 8D5705              <1> 		lea dx,[bx+5]		; DX -> LSR
  4321 0000145C EC                  <1> 		in al,dx
  4322 0000145D A801                <1> 		test al,1
  4323 0000145F 74EA                <1> 		jz .again
  4324 00001461 42                  <1> 		inc dx			; DX -> MSR
  4325 00001462 8A26BE55            <1> 		mov ah,[FlowIgnore]
  4326 00001466 EC                  <1> 		in al,dx
  4327 00001467 20E0                <1> 		and al,ah
  4328 00001469 38E0                <1> 		cmp al,ah
  4329 0000146B 75DE                <1> 		jne .again
  4330 0000146D 30E4                <1> .serial:	xor ah,ah		; Avoid confusion
  4331 0000146F 87D3                <1> 		xchg dx,bx		; Data port
  4332 00001471 EC                  <1> 		in al,dx
  4333 00001472 C3                  <1> 		ret
  4334 00001473 31C0                <1> .kbd:		xor ax,ax		; Get keyboard input
  4335 00001475 CD16                <1> 		int 16h
  4336 00001477 20C0                <1> 		and al,al
  4337 00001479 7404                <1> 		jz .func_key
  4338 0000147B BB0053              <1> 		mov bx,KbdMap		; Convert character sets
  4339 0000147E D7                  <1> 		xlatb
  4340 0000147F C3                  <1> .func_key:	ret
  4341                              <1> 
  4342                              <1> %ifdef DEBUG_TRACERS
  4343                              <1> ;
  4344                              <1> ; debug hack to print a character with minimal code impact
  4345                              <1> ;
  4346                              <1> debug_tracer:	pushad
  4347                              <1> 		pushfd
  4348                              <1> 		mov bp,sp
  4349                              <1> 		mov bx,[bp+9*4]		; Get return address
  4350                              <1> 		mov al,[cs:bx]		; Get data byte
  4351                              <1> 		inc word [bp+9*4]	; Return to after data byte
  4352                              <1> 		call writechr
  4353                              <1> 		popfd
  4354                              <1> 		popad
  4355                              <1> 		ret
  4356                              <1> %endif	; DEBUG_TRACERS
  4357                                  %include "writestr.inc"		; String output
  4358                              <1> ;; $Id: writestr.inc,v 1.1 2002/04/26 22:43:29 hpa Exp $
  4359                              <1> ;; -----------------------------------------------------------------------
  4360                              <1> ;;   
  4361                              <1> ;;   Copyright 1994-2002 H. Peter Anvin - All Rights Reserved
  4362                              <1> ;;
  4363                              <1> ;;   This program is free software; you can redistribute it and/or modify
  4364                              <1> ;;   it under the terms of the GNU General Public License as published by
  4365                              <1> ;;   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
  4366                              <1> ;;   Bostom MA 02111-1307, USA; either version 2 of the License, or
  4367                              <1> ;;   (at your option) any later version; incorporated herein by reference.
  4368                              <1> ;;
  4369                              <1> ;; -----------------------------------------------------------------------
  4370                              <1> 
  4371                              <1> ;;
  4372                              <1> ;; writestr.inc
  4373                              <1> ;;
  4374                              <1> ;; Code to write a simple string.
  4375                              <1> ;;
  4376                              <1> 
  4377                              <1> ;
  4378                              <1> ; crlf: Print a newline
  4379                              <1> ;
  4380 00001480 BE[851F]            <1> crlf:		mov si,crlf_msg
  4381                              <1> 		; Fall through
  4382                              <1> 
  4383                              <1> ;
  4384                              <1> ; cwritestr: write a null-terminated string to the console, saving
  4385                              <1> ;            registers on entry.
  4386                              <1> ;
  4387                              <1> ; Note: writestr and cwritestr are distinct in SYSLINUX (only)
  4388                              <1> ;
  4389                              <1> cwritestr:
  4390 00001483 669C                <1> 		pushfd
  4391 00001485 6660                <1>                 pushad
  4392 00001487 AC                  <1> .top:		lodsb
  4393 00001488 20C0                <1> 		and al,al
  4394 0000148A 7405                <1>                 jz .end
  4395 0000148C E848FB              <1> 		call writechr
  4396 0000148F EBF6                <1>                 jmp short .top
  4397 00001491 6661                <1> .end:		popad
  4398 00001493 669D                <1> 		popfd
  4399 00001495 C3                  <1>                 ret
  4400                              <1> 
  4401                                  %include "parseconfig.inc"	; High-level config file handling
  4402                              <1> ;; $Id: parseconfig.inc,v 1.6 2002/06/17 16:10:15 hpa Exp $
  4403                              <1> ;; -----------------------------------------------------------------------
  4404                              <1> ;;   
  4405                              <1> ;;   Copyright 1994-2002 H. Peter Anvin - All Rights Reserved
  4406                              <1> ;;
  4407                              <1> ;;   This program is free software; you can redistribute it and/or modify
  4408                              <1> ;;   it under the terms of the GNU General Public License as published by
  4409                              <1> ;;   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
  4410                              <1> ;;   Bostom MA 02111-1307, USA; either version 2 of the License, or
  4411                              <1> ;;   (at your option) any later version; incorporated herein by reference.
  4412                              <1> ;;
  4413                              <1> ;; -----------------------------------------------------------------------
  4414                              <1> 
  4415                              <1> ;;
  4416                              <1> ;; parseconfig.inc
  4417                              <1> ;;
  4418                              <1> ;; Configuration file operations
  4419                              <1> ;;
  4420                              <1> 
  4421                              <1> ;
  4422                              <1> ; "default" command
  4423                              <1> ; 
  4424 00001496 BF[9D21]            <1> pc_default:	mov di,default_cmd
  4425 00001499 E854FD              <1> 		call getline
  4426 0000149C 30C0                <1> 		xor al,al
  4427 0000149E AA                  <1> 		stosb				; null-terminate
  4428 0000149F C3                  <1> 		ret
  4429                              <1> 
  4430                              <1> ;
  4431                              <1> ; "append" command
  4432                              <1> ;
  4433 000014A0 833E[7820]00        <1> pc_append:      cmp word [VKernelCtr],byte 0
  4434 000014A5 770F                <1> 		ja .vk
  4435 000014A7 BF0052              <1>                 mov di,AppendBuf
  4436 000014AA E843FD              <1> 		call getline
  4437 000014AD 81EF0052            <1>                 sub di,AppendBuf
  4438 000014B1 893E[7020]          <1> .app1:        	mov [AppendLen],di
  4439 000014B5 C3                  <1> 		ret
  4440 000014B6 BF1850              <1> .vk:		mov di,VKernelBuf+vk_append	; "append" command (vkernel)
  4441 000014B9 E834FD              <1> 		call getline
  4442 000014BC 81EF1850            <1> 		sub di,VKernelBuf+vk_append
  4443 000014C0 83FF02              <1>                 cmp di,byte 2
  4444 000014C3 7509                <1>                 jne .app2
  4445 000014C5 803E18502D          <1>                 cmp byte [VKernelBuf+vk_append],'-'
  4446 000014CA 7502                <1>                 jne .app2
  4447 000014CC 31FF                <1>                 xor di,di			; If "append -" -> null string
  4448 000014CE 893E1650            <1> .app2:		mov [VKernelBuf+vk_appendlen],di
  4449 000014D2 C3                  <1> 		ret
  4450                              <1> 
  4451                              <1> ;
  4452                              <1> ; "ipappend" command (PXELINUX only)
  4453                              <1> ;
  4454                              <1> %if IS_PXELINUX
  4455                              <1> pc_ipappend:	call getint
  4456                              <1> 		jc .err
  4457                              <1> 		and bx,bx
  4458                              <1> 		setnz bl
  4459                              <1> 		cmp word [VKernelCtr], byte 0
  4460                              <1> 		jne .vk
  4461                              <1> 		mov [IPAppend],bl
  4462                              <1> .err:		ret
  4463                              <1> .vk:		mov [VKernelBuf+vk_ipappend],bl
  4464                              <1> 		ret
  4465                              <1> %endif
  4466                              <1> 
  4467                              <1> ;
  4468                              <1> ; "localboot" command (PXELINUX, ISOLINUX)
  4469                              <1> ;
  4470                              <1> %if IS_PXELINUX || IS_ISOLINUX
  4471                              <1> pc_localboot:	call getint
  4472                              <1> 		cmp word [VKernelCtr],byte 0	; ("label" section only)
  4473                              <1> 		je .err
  4474                              <1> 		mov [VKernelBuf+vk_rname], byte 0	; Null kernel name
  4475                              <1> 		mov [VKernelBuf+vk_rname+1], bx	; Return type
  4476                              <1> .err:		ret
  4477                              <1> %endif
  4478                              <1> 
  4479                              <1> ;
  4480                              <1> ; "kernel" command
  4481 000014D3 833E[7820]00        <1> pc_kernel:	cmp word [VKernelCtr],byte 0
  4482 000014D8 740E                <1> 		je .err				; ("label" section only)
  4483 000014DA BF0010              <1> 		mov di,trackbuf
  4484 000014DD 57                  <1> 		push di
  4485 000014DE E80FFD              <1> 		call getline
  4486 000014E1 5E                  <1> 		pop si
  4487 000014E2 BF0B50              <1> 		mov di,VKernelBuf+vk_rname
  4488 000014E5 E812FB              <1> 		call mangle_name
  4489 000014E8 C3                  <1> .err:		ret
  4490                              <1> 
  4491                              <1> ;
  4492                              <1> ; "timeout" command
  4493                              <1> ;
  4494 000014E9 E850FC              <1> pc_timeout:	call getint
  4495 000014EC 720B                <1> 		jc .err
  4496 000014EE B815D2              <1> 		mov ax,0D215h			; There are approx 1.D215h
  4497 000014F1 F7E3                <1> 		mul bx				; clock ticks per 1/10 s
  4498 000014F3 01D3                <1> 		add bx,dx
  4499 000014F5 891E[7220]          <1> 		mov [KbdTimeOut],bx
  4500 000014F9 C3                  <1> .err:		ret
  4501                              <1> 
  4502                              <1> ;
  4503                              <1> ; Generic integer variable setting commands:
  4504                              <1> ; "prompt", "implicit"
  4505                              <1> ;
  4506                              <1> pc_setint16:
  4507 000014FA 50                  <1> 		push ax
  4508 000014FB E83EFC              <1> 		call getint
  4509 000014FE 5E                  <1> 		pop si
  4510 000014FF 7202                <1> 		jc .err
  4511 00001501 891C                <1> 		mov [si],bx
  4512 00001503 C3                  <1> .err:		ret
  4513                              <1> 
  4514                              <1> ;
  4515                              <1> ; Generic file-processing commands:
  4516                              <1> ; "display", "font", "kbdmap"
  4517                              <1> ;
  4518 00001504 50                  <1> pc_filecmd:	push ax				; Function to tailcall
  4519 00001505 BF0010              <1> 		mov di,trackbuf
  4520 00001508 57                  <1> 		push di
  4521 00001509 E8E4FC              <1> 		call getline
  4522 0000150C 5E                  <1> 		pop si
  4523 0000150D BFC555              <1> 		mov di,MNameBuf
  4524 00001510 57                  <1> 		push di
  4525 00001511 E8E6FA              <1> 		call mangle_name
  4526 00001514 5F                  <1> 		pop di
  4527 00001515 E847FA              <1> 		call searchdir			; tailcall
  4528 00001518 7501                <1> 		jnz .ok
  4529 0000151A 58                  <1> 		pop ax				; Drop the successor function
  4530 0000151B C3                  <1> .ok:		ret				; Tailcall if OK, error return
  4531                              <1> 
  4532                              <1> ;
  4533                              <1> ; "serial" command
  4534                              <1> ;
  4535 0000151C E81DFC              <1> pc_serial:	call getint
  4536 0000151F 7207                <1> 		jc .err
  4537 00001521 53                  <1> 		push bx				; Serial port #
  4538 00001522 E8FEFB              <1> 		call skipspace
  4539 00001525 7302                <1> 		jnc .ok
  4540 00001527 5B                  <1> 		pop bx
  4541 00001528 C3                  <1> .err:		ret
  4542                              <1> .ok:
  4543 00001529 E8E6FB              <1> 		call ungetc
  4544 0000152C E80DFC              <1> 		call getint
  4545 0000152F C706BC550000        <1> 		mov [FlowControl], word 0	; Default to no flow control
  4546 00001535 7229                <1> 		jc .nobaud
  4547                              <1> .valid_baud:	
  4548 00001537 6653                <1> 		push ebx
  4549 00001539 E8E7FB              <1> 		call skipspace
  4550 0000153C 7208                <1> 		jc .no_flow
  4551 0000153E E8D1FB              <1> 		call ungetc
  4552 00001541 E8F8FB              <1> 		call getint			; Hardware flow control?
  4553 00001544 7302                <1> 		jnc .valid_flow
  4554                              <1> .no_flow:
  4555 00001546 31DB                <1> 		xor bx,bx			; Default -> no flow control
  4556                              <1> .valid_flow:
  4557 00001548 80E70F              <1> 		and bh,0Fh			; FlowIgnore
  4558 0000154B C0E704              <1> 		shl bh,4
  4559 0000154E 883EBE55            <1> 		mov [FlowIgnore],bh
  4560 00001552 88DF                <1> 		mov bh,bl
  4561 00001554 81E303F0            <1> 		and bx,0F003h			; Valid bits
  4562 00001558 891EBC55            <1> 		mov [FlowControl],bx
  4563 0000155C 665B                <1> 		pop ebx				; Baud rate
  4564 0000155E EB06                <1> 		jmp short .parse_baud
  4565                              <1> .nobaud:
  4566 00001560 66BB80250000        <1> 		mov ebx,DEFAULT_BAUD		; No baud rate given
  4567                              <1> .parse_baud:
  4568 00001566 5F                  <1> 		pop di				; Serial port #
  4569 00001567 6683FB4B            <1> 		cmp ebx,byte 75
  4570 0000156B 72BB                <1> 		jb .err				; < 75 baud == bogus
  4571 0000156D 66B800C20100        <1> 		mov eax,BAUD_DIVISOR
  4572 00001573 6699                <1> 		cdq
  4573 00001575 66F7F3              <1> 		div ebx
  4574 00001578 A3BA55              <1> 		mov [BaudDivisor],ax
  4575 0000157B 50                  <1> 		push ax				; Baud rate divisor
  4576 0000157C 83FF03              <1> 		cmp di,3
  4577 0000157F 7706                <1> 		ja .port_is_io			; If port > 3 then port is I/O addr
  4578 00001581 D1E7                <1> 		shl di,1
  4579 00001583 8BBD0004            <1> 		mov di,[di+serial_base]		; Get the I/O port from the BIOS
  4580                              <1> .port_is_io:
  4581 00001587 893E[7E20]          <1> 		mov [SerialPort],di
  4582 0000158B 8D5503              <1> 		lea dx,[di+3]			; DX -> LCR
  4583 0000158E B083                <1> 		mov al,83h			; Enable DLAB
  4584 00001590 E8DF01              <1> 		call slow_out
  4585 00001593 58                  <1> 		pop ax				; Divisor
  4586 00001594 89FA                <1> 		mov dx,di			; DX -> LS
  4587 00001596 E8D901              <1> 		call slow_out
  4588 00001599 42                  <1> 		inc dx				; DX -> MS
  4589 0000159A 88E0                <1> 		mov al,ah
  4590 0000159C E8D301              <1> 		call slow_out
  4591 0000159F B003                <1> 		mov al,03h			; Disable DLAB
  4592 000015A1 83C202              <1> 		add dx,byte 2			; DX -> LCR
  4593 000015A4 E8CB01              <1> 		call slow_out
  4594 000015A7 EC                  <1> 		in al,dx			; Read back LCR (detect missing hw)
  4595 000015A8 3C03                <1> 		cmp al,03h			; If nothing here we'll read 00 or FF
  4596 000015AA 7520                <1> 		jne .serial_port_bad		; Assume serial port busted
  4597 000015AC 83EA02              <1> 		sub dx,byte 2			; DX -> IER
  4598 000015AF 30C0                <1> 		xor al,al			; IRQ disable
  4599 000015B1 E8BE01              <1> 		call slow_out
  4600                              <1> 
  4601 000015B4 83C203              <1> 		add dx,byte 3			; DX -> MCR
  4602 000015B7 EC                  <1> 		in al,dx
  4603 000015B8 0A06BC55            <1> 		or al,[FlowOutput]		; Assert bits
  4604 000015BC E8B301              <1> 		call slow_out
  4605                              <1> 
  4606                              <1> 		; Show some life
  4607 000015BF BE[0002]            <1> 		mov si,syslinux_banner
  4608 000015C2 E851FE              <1> 		call write_serial_str
  4609 000015C5 BE[941C]            <1> 		mov si,copyright_str
  4610 000015C8 E84BFE              <1> 		call write_serial_str
  4611 000015CB C3                  <1> 		ret
  4612                              <1> 
  4613                              <1> .serial_port_bad:
  4614 000015CC C706[7E20]0000      <1> 		mov [SerialPort], word 0
  4615 000015D2 C3                  <1> 		ret
  4616                              <1> 
  4617                              <1> ;
  4618                              <1> ; "F"-key command
  4619                              <1> ;
  4620 000015D3 50                  <1> pc_fkey:	push ax
  4621 000015D4 BF0010              <1> 		mov di,trackbuf
  4622 000015D7 57                  <1> 		push di
  4623 000015D8 E815FC              <1> 		call getline			; Get filename to display
  4624 000015DB 5E                  <1> 		pop si
  4625 000015DC 5F                  <1> 		pop di
  4626 000015DD E81AFA              <1> 		call mangle_name		; Mangle file name
  4627 000015E0 C3                  <1> 		ret
  4628                              <1> 
  4629                              <1> ;
  4630                              <1> ; "label" command
  4631                              <1> ;
  4632 000015E1 E84400              <1> pc_label:	call commit_vk			; Commit any current vkernel
  4633 000015E4 BF0010              <1> 		mov di,trackbuf			; Get virtual filename
  4634 000015E7 57                  <1> 		push di
  4635 000015E8 E805FC              <1> 		call getline
  4636 000015EB 5E                  <1> 		pop si
  4637 000015EC BF0050              <1> 		mov di,VKernelBuf+vk_vname
  4638 000015EF E808FA              <1> 		call mangle_name		; Mangle virtual name
  4639 000015F2 FF06[7820]          <1> 		inc word [VKernelCtr]		; One more vkernel
  4640 000015F6 BE0050              <1> 		mov si,VKernelBuf+vk_vname 	; By default, rname == vname
  4641 000015F9 BF0B50              <1> 		mov di,VKernelBuf+vk_rname
  4642 000015FC B90B00              <1> 		mov cx,FILENAME_MAX
  4643 000015FF F3A4                <1> 		rep movsb
  4644 00001601 BE0052              <1>                 mov si,AppendBuf         	; Default append==global append
  4645 00001604 BF1850              <1>                 mov di,VKernelBuf+vk_append
  4646 00001607 8B0E[7020]          <1>                 mov cx,[AppendLen]
  4647 0000160B 890E1650            <1>                 mov [VKernelBuf+vk_appendlen],cx
  4648 0000160F F3A4                <1>                 rep movsb
  4649                              <1> %if IS_PXELINUX					; PXELINUX only
  4650                              <1> 		mov al,[IPAppend]		; Default ipappend==global ipappend
  4651                              <1> 		mov [VKernelBuf+vk_ipappend],al
  4652                              <1> %endif
  4653 00001611 C3                  <1> 		ret
  4654                              <1> 
  4655                              <1> ;
  4656                              <1> ; "say" command
  4657                              <1> ;
  4658 00001612 BF0010              <1> pc_say:		mov di,trackbuf			; "say" command
  4659 00001615 57                  <1> 		push di
  4660 00001616 E8D7FB              <1> 		call getline
  4661 00001619 30C0                <1> 		xor al,al
  4662 0000161B AA                  <1> 		stosb				; Null-terminate
  4663 0000161C 5E                  <1> 		pop si
  4664 0000161D E846EB              <1> 		call writestr
  4665 00001620 E95DFE              <1> 		jmp crlf			; tailcall
  4666                              <1> 
  4667                              <1> ;
  4668                              <1> ; Main loop for configuration file parsing
  4669                              <1> ;
  4670                              <1> parse_config:
  4671 00001623 E83000              <1> 		call getcommand
  4672 00001626 73FB                <1>                 jnc parse_config		; If not EOF do it again
  4673                              <1> 		;
  4674                              <1> 		; The fall through to commit_vk to commit any final
  4675                              <1> 		; VKernel being read
  4676                              <1> 		;
  4677                              <1> ;
  4678                              <1> ; commit_vk: Store the current VKernelBuf into buffer segment
  4679                              <1> ;
  4680                              <1> commit_vk:
  4681 00001628 833E[7820]00        <1> 		cmp word [VKernelCtr],byte 0
  4682 0000162D 741F                <1> 		je cvk_ret			; No VKernel = return
  4683 0000162F 813E[7820]8000      <1> 		cmp word [VKernelCtr],max_vk	; Above limit?
  4684 00001635 7718                <1> 		ja cvk_overflow
  4685 00001637 8B3E[7820]          <1> 		mov di,[VKernelCtr]
  4686 0000163B 4F                  <1> 		dec di
  4687 0000163C C1E709              <1> 		shl di,vk_shift
  4688 0000163F BE0050              <1> 		mov si,VKernelBuf
  4689 00001642 B98000              <1> 		mov cx,(vk_size >> 2)
  4690 00001645 06                  <1> 		push es
  4691 00001646 680040              <1> 		push word vk_seg
  4692 00001649 07                  <1> 		pop es
  4693 0000164A F366A5              <1> 		rep movsd			; Copy to buffer segment
  4694 0000164D 07                  <1> 		pop es
  4695 0000164E C3                  <1> cvk_ret:	ret
  4696 0000164F C706[7820]8000      <1> cvk_overflow:	mov word [VKernelCtr],max_vk	; No more than max_vk, please
  4697 00001655 C3                  <1> 		ret
  4698                                  %include "parsecmd.inc"		; Low-level config file handling
  4699                              <1> ;; $Id: parsecmd.inc,v 1.5 2002/10/24 17:31:45 hpa Exp $
  4700                              <1> ;; -----------------------------------------------------------------------
  4701                              <1> ;;   
  4702                              <1> ;;   Copyright 1994-2002 H. Peter Anvin - All Rights Reserved
  4703                              <1> ;;
  4704                              <1> ;;   This program is free software; you can redistribute it and/or modify
  4705                              <1> ;;   it under the terms of the GNU General Public License as published by
  4706                              <1> ;;   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
  4707                              <1> ;;   Bostom MA 02111-1307, USA; either version 2 of the License, or
  4708                              <1> ;;   (at your option) any later version; incorporated herein by reference.
  4709                              <1> ;;
  4710                              <1> ;; -----------------------------------------------------------------------
  4711                              <1> 
  4712                              <1> ;;
  4713                              <1> ;; parsecmd.inc
  4714                              <1> ;;
  4715                              <1> ;; Command line parser code
  4716                              <1> ;;
  4717                              <1> 
  4718                              <1> ; -------------------------------------------------------------------------
  4719                              <1> ;  getcommand:	Get a keyword from the current "getc" file and match it
  4720                              <1> ;		against a list of keywords (keywd_table).  Each entry in
  4721                              <1> ;		that table should have the following form:
  4722                              <1> ;		<32 bit hash value> <16 bit handler offset>
  4723                              <1> ;
  4724                              <1> ;               The handler is called, and upon return this function
  4725                              <1> ;               returns with CF = 0.  On EOF, this function returns
  4726                              <1> ;		with CF = 1.
  4727                              <1> ; -------------------------------------------------------------------------
  4728                              <1> 
  4729                              <1> getcommand:
  4730                              <1> .find:
  4731 00001656 E8CAFA              <1> 		call skipspace		; Skip leading whitespace
  4732 00001659 7451                <1> 		jz .eof			; End of file
  4733 0000165B 72F9                <1> 		jc .find		; End of line: try again
  4734 0000165D 3C30                <1> 		cmp al,'0'		; Skip comment line
  4735 0000165F 724D                <1> 		jb .skipline
  4736                              <1> 
  4737 00001661 0C20                <1> 		or al,20h		; Convert to lower case
  4738 00001663 660FB6D8            <1> 		movzx ebx,al		; Hash for a one-char keyword
  4739                              <1> .read_loop:
  4740 00001667 6653                <1> 		push ebx
  4741 00001669 E861FA              <1> 		call getc
  4742 0000166C 665B                <1> 		pop ebx
  4743 0000166E 3C20                <1> 		cmp al,' '		; Whitespace
  4744 00001670 760A                <1> 		jbe .done
  4745 00001672 0C20                <1> 		or al,20h
  4746 00001674 66C1C305            <1> 		rol ebx,5
  4747 00001678 30C3                <1> 		xor bl,al
  4748 0000167A EBEB                <1> 		jmp short .read_loop
  4749 0000167C E893FA              <1> .done:		call ungetc
  4750 0000167F E8A1FA              <1> 		call skipspace
  4751 00001682 7428                <1> 		jz .eof
  4752 00001684 7219                <1> 		jc .noparm
  4753 00001686 E889FA              <1> 		call ungetc		; Return nonwhitespace char to buf
  4754 00001689 BE[A01F]            <1> 		mov si,keywd_table
  4755 0000168C B91700              <1> 		mov cx,keywd_count
  4756                              <1> .table_search:
  4757 0000168F 66AD                <1> 		lodsd
  4758 00001691 6639C3              <1> 		cmp ebx,eax
  4759 00001694 7411                <1> 		je .found_keywd
  4760 00001696 66AD                <1> 		lodsd			; Skip entrypoint/argument
  4761 00001698 E2F5                <1> 		loop .table_search
  4762                              <1> 
  4763                              <1> 		; Otherwise unrecognized keyword
  4764 0000169A BE[E71D]            <1> 		mov si,err_badcfg
  4765 0000169D EB03                <1> 		jmp short .error
  4766                              <1> 
  4767                              <1> 		; No parameter
  4768                              <1> .noparm:
  4769 0000169F BE[0A1E]            <1> 		mov si,err_noparm
  4770                              <1> .error:
  4771 000016A2 E8DEFD              <1> 		call cwritestr
  4772 000016A5 EBAF                <1> 		jmp short .find
  4773                              <1> 
  4774 000016A7 AD                  <1> .found_keywd:	lodsw			; Load argument into ax
  4775 000016A8 FF14                <1> 		call [si]
  4776 000016AA F8                  <1> 		clc
  4777 000016AB C3                  <1> 		ret
  4778                              <1> 
  4779 000016AC F9                  <1> .eof:		stc
  4780 000016AD C3                  <1> 		ret
  4781                              <1> 
  4782 000016AE 3C0A                <1> .skipline:	cmp al,10		; Search for LF
  4783 000016B0 74A4                <1> 		je .find
  4784 000016B2 E818FA              <1> 		call getc
  4785 000016B5 72F5                <1> 		jc .eof
  4786 000016B7 EBF5                <1> 		jmp short .skipline
  4787                                  %include "bcopy32.inc"		; 32-bit bcopy
  4788                              <1> ;; $Id: bcopy32.inc,v 1.6 2002/06/11 05:48:29 hpa Exp $
  4789                              <1> ;; -----------------------------------------------------------------------
  4790                              <1> ;;   
  4791                              <1> ;;   Copyright 1994-2002 H. Peter Anvin - All Rights Reserved
  4792                              <1> ;;
  4793                              <1> ;;   This program is free software; you can redistribute it and/or modify
  4794                              <1> ;;   it under the terms of the GNU General Public License as published by
  4795                              <1> ;;   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
  4796                              <1> ;;   Bostom MA 02111-1307, USA; either version 2 of the License, or
  4797                              <1> ;;   (at your option) any later version; incorporated herein by reference.
  4798                              <1> ;;
  4799                              <1> ;; -----------------------------------------------------------------------
  4800                              <1> 
  4801                              <1> ;;
  4802                              <1> ;; bcopy32.inc
  4803                              <1> ;; 
  4804                              <1> ;; 32-bit bcopy routine for real mode
  4805                              <1> ;;
  4806                              <1> 
  4807                              <1> ;
  4808                              <1> ; 32-bit bcopy routine for real mode
  4809                              <1> ;
  4810                              <1> ; We enter protected mode, set up a flat 32-bit environment, run rep movsd
  4811                              <1> ; and then exit.  IMPORTANT: This code assumes cs == 0.
  4812                              <1> ;
  4813                              <1> ; This code is probably excessively anal-retentive in its handling of
  4814                              <1> ; segments, but this stuff is painful enough as it is without having to rely
  4815                              <1> ; on everything happening "as it ought to."
  4816                              <1> ;
  4817                              <1> ; IMPORTANT: This code must be capable of operating when copied to the
  4818                              <1> ; trackbuf area (1000h).  The routine bcopy_over_self handles this mode
  4819                              <1> ; of operation, including any necessary adjustments.
  4820                              <1> ;
  4821 000016B9 90<rept>            <1> 		align 4
  4822                              <1> __bcopy_start:
  4823                              <1> 
  4824 000016BC 2F00                <1> bcopy_gdt:	dw bcopy_gdt_size-1	; Null descriptor - contains GDT
  4825 000016BE [BC160000]          <1> .adj1:		dd bcopy_gdt		; pointer for LGDT instruction
  4826 000016C2 0000                <1> 		dw 0
  4827 000016C4 FFFF0000            <1> 		dd 0000ffffh		; Code segment, use16, readable,
  4828 000016C8 009B0000            <1> 		dd 00009b00h		; present, dpl 0, cover 64K
  4829 000016CC FFFF0000            <1> 		dd 0000ffffh		; Data segment, use16, read/write,
  4830 000016D0 00938F00            <1> 		dd 008f9300h		; present, dpl 0, cover all 4G
  4831 000016D4 FFFF0000            <1> 		dd 0000ffffh		; Data segment, use16, read/write,
  4832 000016D8 00930000            <1> 		dd 00009300h		; present, dpl 0, cover 64K
  4833                              <1> 		; The rest are used for COM32 only
  4834 000016DC FFFF0000            <1> 		dd 0000ffffh		; Code segment, use32, readable,
  4835 000016E0 009BCF00            <1> 		dd 00cf9b00h		; present, dpl 0, cover all 4G
  4836 000016E4 FFFF0000            <1> 		dd 0000ffffh		; Data segment, use32, read/write,
  4837 000016E8 0093CF00            <1> 		dd 00cf9300h		; present, dpl 0, cover all 4G
  4838                              <1> bcopy_gdt_size:	equ $-bcopy_gdt
  4839                              <1> 
  4840                              <1> ;
  4841                              <1> ; bcopy:
  4842                              <1> ;	32-bit copy
  4843                              <1> ;
  4844                              <1> ; Inputs:
  4845                              <1> ;	ESI	- source pointer
  4846                              <1> ;	EDI	- target pointer
  4847                              <1> ;	ECX	- byte count
  4848                              <1> ;	DF	- zero
  4849                              <1> ;
  4850                              <1> ; Outputs:
  4851                              <1> ;	ESI	- first byte after source
  4852                              <1> ;	EDI	- first byte after target
  4853                              <1> ;	ECX	- zero
  4854                              <1> ;
  4855 000016EC 6650                <1> bcopy:		push eax
  4856 000016EE 9C                  <1> 		pushf			; Saves, among others, the IF flag
  4857 000016EF 0FA8                <1> 		push gs
  4858 000016F1 0FA0                <1> 		push fs
  4859 000016F3 1E                  <1> 		push ds
  4860 000016F4 06                  <1> 		push es
  4861 000016F5 2E89266455          <1> 		mov [cs:SavedSSSP],sp
  4862 000016FA 2E8C166655          <1> 		mov [cs:SavedSSSP+2],ss
  4863                              <1> 
  4864 000016FF FA                  <1> 		cli
  4865 00001700 E87500              <1> 		call enable_a20
  4866                              <1> 
  4867 00001703 662E0F0116[BC16]    <1> .adj2:		o32 lgdt [cs:bcopy_gdt]
  4868 0000170A 0F20C0              <1> 		mov eax,cr0
  4869 0000170D 0C01                <1> 		or al,1
  4870 0000170F 0F22C0              <1> 		mov cr0,eax		; Enter protected mode
  4871 00001712 EA[1717]0800        <1> .adj3a:		jmp 08h:.in_pm
  4872                              <1> 
  4873 00001717 B81000              <1> .in_pm:		mov ax,10h		; Data segment selector
  4874 0000171A 8EC0                <1> 		mov es,ax
  4875 0000171C 8ED8                <1> 		mov ds,ax
  4876                              <1> 
  4877 0000171E B018                <1> 		mov al,18h		; "Real-mode-like" data segment
  4878 00001720 8ED0                <1> 		mov ss,ax
  4879 00001722 8EE0                <1> 		mov fs,ax
  4880 00001724 8EE8                <1> 		mov gs,ax	
  4881                              <1> 
  4882 00001726 88C8                <1> 		mov al,cl		; Save low bits
  4883 00001728 66C1E902            <1> 		shr ecx,2		; Convert to dwords
  4884 0000172C 67F366A5            <1> 		a32 rep movsd		; Do our business
  4885                              <1> 		; At this point ecx == 0
  4886                              <1> 
  4887 00001730 88C1                <1> 		mov cl,al		; Copy any fractional dword
  4888 00001732 80E103              <1> 		and cl,3
  4889 00001735 67F3A4              <1> 		a32 rep movsb
  4890                              <1> 
  4891 00001738 B018                <1> 		mov al,18h		; "Real-mode-like" data segment
  4892 0000173A 8EC0                <1> 		mov es,ax
  4893 0000173C 8ED8                <1> 		mov ds,ax
  4894                              <1> 
  4895 0000173E 0F20C0              <1> 		mov eax,cr0
  4896 00001741 24FE                <1> 		and al,~1
  4897 00001743 0F22C0              <1> 		mov cr0,eax		; Disable protected mode
  4898 00001746 EA[4B17]0000        <1> .adj3b:		jmp 0:.in_rm
  4899                              <1> 
  4900                              <1> .in_rm:		; Back in real mode
  4901 0000174B 2E0FB2266455        <1> 		lss sp,[cs:SavedSSSP]
  4902 00001751 07                  <1> 		pop es
  4903 00001752 1F                  <1> 		pop ds
  4904 00001753 0FA1                <1> 		pop fs
  4905 00001755 0FA9                <1> 		pop gs
  4906 00001757 E8C100              <1> 		call disable_a20
  4907                              <1> 
  4908 0000175A 9D                  <1> 		popf			; Re-enables interrupts
  4909 0000175B 6658                <1> 		pop eax
  4910 0000175D C3                  <1> 		ret
  4911                              <1> 
  4912                              <1> ;
  4913                              <1> ; Routines to enable and disable (yuck) A20.  These routines are gathered
  4914                              <1> ; from tips from a couple of sources, including the Linux kernel and
  4915                              <1> ; http://www.x86.org/.  The need for the delay to be as large as given here
  4916                              <1> ; is indicated by Donnie Barnes of RedHat, the problematic system being an
  4917                              <1> ; IBM ThinkPad 760EL.
  4918                              <1> ;
  4919                              <1> ; We typically toggle A20 twice for every 64K transferred.
  4920                              <1> ; 
  4921                              <1> %define	io_delay	call _io_delay
  4922                              <1> %define IO_DELAY_PORT	80h		; Invalid port (we hope!)
  4923                              <1> %define disable_wait 	32		; How long to wait for a disable
  4924                              <1> 
  4925                              <1> %define A20_DUNNO	0		; A20 type unknown
  4926                              <1> %define A20_NONE	1		; A20 always on?
  4927                              <1> %define A20_BIOS	2		; A20 BIOS enable
  4928                              <1> %define A20_KBC		3		; A20 through KBC
  4929                              <1> %define A20_FAST	4		; A20 through port 92h
  4930                              <1> 
  4931                              <1> 		align 2
  4932 0000175E [8C17][8C17][9717]- <1> A20List		dw a20_dunno, a20_none, a20_bios, a20_kbc, a20_fast
  4933 00001764 [A917][CF17]        <1>
  4934 00001768 [5718][5718][2918]- <1> A20DList	dw a20d_dunno, a20d_none, a20d_bios, a20d_kbc, a20d_fast
  4935 0000176E [3A18][3218]        <1>
  4936                              <1> a20_adjust_cnt	equ ($-A20List)/2
  4937                              <1> 
  4938 00001772 EE                  <1> slow_out:	out dx, al		; Fall through
  4939                              <1> 
  4940 00001773 E680                <1> _io_delay:	out IO_DELAY_PORT,al
  4941 00001775 E680                <1> 		out IO_DELAY_PORT,al
  4942 00001777 C3                  <1> 		ret
  4943                              <1> 
  4944                              <1> enable_a20:
  4945 00001778 6660                <1> 		pushad
  4946 0000177A 2EC606C255FF        <1> 		mov byte [cs:A20Tries],255 ; Times to try to make this work
  4947                              <1> 
  4948                              <1> try_enable_a20:
  4949                              <1> ;
  4950                              <1> ; Flush the caches
  4951                              <1> ;
  4952                              <1> %if DO_WBINVD
  4953                              <1> 		call try_wbinvd
  4954                              <1> %endif
  4955                              <1> 
  4956                              <1> ;
  4957                              <1> ; If the A20 type is known, jump straight to type
  4958                              <1> ;
  4959 00001780 2E8B2EA855          <1> 		mov bp,[cs:A20Type]
  4960 00001785 01ED                <1> 		add bp,bp			; Convert to word offset
  4961 00001787 2EFFA6[5E17]        <1> .adj4:		jmp word [cs:bp+A20List]
  4962                              <1> 
  4963                              <1> ;
  4964                              <1> ; First, see if we are on a system with no A20 gate
  4965                              <1> ;
  4966                              <1> a20_dunno:
  4967                              <1> a20_none:
  4968 0000178C 2EC606A85501        <1> 		mov byte [cs:A20Type], A20_NONE
  4969 00001792 E86400              <1> 		call a20_test
  4970 00001795 755F                <1> 		jnz a20_done
  4971                              <1> 
  4972                              <1> ;
  4973                              <1> ; Next, try the BIOS (INT 15h AX=2401h)
  4974                              <1> ;
  4975                              <1> a20_bios:
  4976 00001797 2EC606A85502        <1> 		mov byte [cs:A20Type], A20_BIOS
  4977 0000179D B80124              <1> 		mov ax,2401h
  4978 000017A0 9C                  <1> 		pushf				; Some BIOSes muck with IF
  4979 000017A1 CD15                <1> 		int 15h
  4980 000017A3 9D                  <1> 		popf
  4981                              <1> 
  4982 000017A4 E85200              <1> 		call a20_test
  4983 000017A7 754D                <1> 		jnz a20_done
  4984                              <1> 
  4985                              <1> ;
  4986                              <1> ; Enable the keyboard controller A20 gate
  4987                              <1> ;
  4988                              <1> a20_kbc:
  4989 000017A9 B201                <1> 		mov dl, 1			; Allow early exit
  4990 000017AB E8AE00              <1> 		call empty_8042
  4991 000017AE 7546                <1> 		jnz a20_done			; A20 live, no need to use KBC
  4992                              <1> 
  4993 000017B0 2EC606A85503        <1> 		mov byte [cs:A20Type], A20_KBC	; Starting KBC command sequence
  4994                              <1> 
  4995 000017B6 B0D1                <1> 		mov al,0D1h			; Command write
  4996 000017B8 E664                <1> 		out 064h, al
  4997 000017BA E89D00              <1> 		call empty_8042_uncond
  4998                              <1> 
  4999 000017BD B0DF                <1> 		mov al,0DFh			; A20 on
  5000 000017BF E660                <1> 		out 060h, al
  5001 000017C1 E89600              <1> 		call empty_8042_uncond
  5002                              <1> 
  5003                              <1> 		; Verify that A20 actually is enabled.  Do that by
  5004                              <1> 		; observing a word in low memory and the same word in
  5005                              <1> 		; the HMA until they are no longer coherent.  Note that
  5006                              <1> 		; we don't do the same check in the disable case, because
  5007                              <1> 		; we don't want to *require* A20 masking (SYSLINUX should
  5008                              <1> 		; work fine without it, if the BIOS does.)
  5009 000017C4 51                  <1> .kbc_wait:	push cx
  5010 000017C5 31C9                <1> 		xor cx,cx
  5011                              <1> .kbc_wait_loop:
  5012 000017C7 E82F00              <1> 		call a20_test
  5013 000017CA 7529                <1> 		jnz a20_done_pop
  5014 000017CC E2F9                <1> 		loop .kbc_wait_loop
  5015                              <1> 
  5016 000017CE 59                  <1> 		pop cx
  5017                              <1> ;
  5018                              <1> ; Running out of options here.  Final attempt: enable the "fast A20 gate"
  5019                              <1> ;
  5020                              <1> a20_fast:
  5021 000017CF 2EC606A85504        <1> 		mov byte [cs:A20Type], A20_FAST	; Haven't used the KBC yet
  5022 000017D5 E492                <1> 		in al, 092h
  5023 000017D7 0C02                <1> 		or al,02h
  5024 000017D9 24FE                <1> 		and al,~01h			; Don't accidentally reset the machine!
  5025 000017DB E692                <1> 		out 092h, al
  5026                              <1> 
  5027 000017DD 51                  <1> .fast_wait:	push cx
  5028 000017DE 31C9                <1> 		xor cx,cx
  5029                              <1> .fast_wait_loop:
  5030 000017E0 E81600              <1> 		call a20_test
  5031 000017E3 7510                <1> 		jnz a20_done_pop
  5032 000017E5 E2F9                <1> 		loop .fast_wait_loop
  5033                              <1> 
  5034 000017E7 59                  <1> 		pop cx
  5035                              <1> 
  5036                              <1> ;
  5037                              <1> ; Oh bugger.  A20 is not responding.  Try frobbing it again; eventually give up
  5038                              <1> ; and report failure to the user.
  5039                              <1> ;
  5040                              <1> 
  5041                              <1> 
  5042 000017E8 2EFE0EC255          <1> 		dec byte [cs:A20Tries]
  5043 000017ED 7591                <1> 		jnz try_enable_a20
  5044                              <1> 
  5045 000017EF BE[061F]            <1> 		mov si, err_a20
  5046 000017F2 E955F7              <1> 		jmp abort_load
  5047                              <1> ;
  5048                              <1> ; A20 unmasked, proceed...
  5049                              <1> ;
  5050 000017F5 59                  <1> a20_done_pop:	pop cx
  5051 000017F6 6661                <1> a20_done:	popad
  5052 000017F8 C3                  <1> 		ret
  5053                              <1> 
  5054                              <1> ;
  5055                              <1> ; This routine tests if A20 is enabled (ZF = 0).  This routine
  5056                              <1> ; must not destroy any register contents.
  5057                              <1> ;
  5058                              <1> a20_test:
  5059 000017F9 06                  <1> 		push es
  5060 000017FA 51                  <1> 		push cx
  5061 000017FB 50                  <1> 		push ax
  5062 000017FC B9FFFF              <1> 		mov cx,0FFFFh		; HMA = segment 0FFFFh
  5063 000017FF 8EC1                <1> 		mov es,cx
  5064 00001801 B92000              <1> 		mov cx,32		; Loop count
  5065 00001804 2EA1A655            <1> 		mov ax,[cs:A20Test]
  5066 00001808 40                  <1> .a20_wait:	inc ax
  5067 00001809 2EA3A655            <1> 		mov [cs:A20Test],ax
  5068 0000180D E863FF              <1> 		io_delay		; Serialize, and fix delay
  5069 00001810 263B06B655          <1> 		cmp ax,[es:A20Test+10h]
  5070 00001815 E1F1                <1> 		loopz .a20_wait
  5071 00001817 58                  <1> .a20_done:	pop ax
  5072 00001818 59                  <1> 		pop cx
  5073 00001819 07                  <1> 		pop es
  5074 0000181A C3                  <1> 		ret
  5075                              <1> 
  5076                              <1> disable_a20:
  5077 0000181B 6660                <1> 		pushad
  5078                              <1> ;
  5079                              <1> ; Flush the caches
  5080                              <1> ;
  5081                              <1> %if DO_WBINVD
  5082                              <1> 		call try_wbinvd
  5083                              <1> %endif
  5084                              <1> 
  5085 0000181D 2E8B2EA855          <1> 		mov bp,[cs:A20Type]
  5086 00001822 01ED                <1> 		add bp,bp			; Convert to word offset
  5087 00001824 2EFFA6[6817]        <1> .adj5:		jmp word [cs:bp+A20DList]
  5088                              <1> 
  5089                              <1> a20d_bios:
  5090 00001829 B80024              <1> 		mov ax,2400h
  5091 0000182C 9C                  <1> 		pushf				; Some BIOSes muck with IF
  5092 0000182D CD15                <1> 		int 15h
  5093 0000182F 9D                  <1> 		popf
  5094 00001830 EB19                <1> 		jmp short a20d_snooze
  5095                              <1> 
  5096                              <1> ;
  5097                              <1> ; Disable the "fast A20 gate"
  5098                              <1> ;
  5099                              <1> a20d_fast:
  5100 00001832 E492                <1> 		in al, 092h
  5101 00001834 24FC                <1> 		and al,~03h
  5102 00001836 E692                <1> 		out 092h, al
  5103 00001838 EB11                <1> 		jmp short a20d_snooze
  5104                              <1> 
  5105                              <1> ;
  5106                              <1> ; Disable the keyboard controller A20 gate
  5107                              <1> ;
  5108                              <1> a20d_kbc:
  5109 0000183A E81D00              <1> 		call empty_8042_uncond
  5110 0000183D B0D1                <1> 		mov al,0D1h
  5111 0000183F E664                <1> 		out 064h, al		; Command write
  5112 00001841 E81600              <1> 		call empty_8042_uncond
  5113 00001844 B0DD                <1> 		mov al,0DDh		; A20 off
  5114 00001846 E660                <1> 		out 060h, al
  5115 00001848 E80F00              <1> 		call empty_8042_uncond
  5116                              <1> 		; Wait a bit for it to take effect
  5117                              <1> a20d_snooze:
  5118 0000184B 51                  <1> 		push cx
  5119 0000184C B92000              <1> 		mov cx, disable_wait
  5120 0000184F E8A7FF              <1> .delayloop:	call a20_test
  5121 00001852 7402                <1> 		jz .disabled
  5122 00001854 E2F9                <1> 		loop .delayloop
  5123 00001856 59                  <1> .disabled:	pop cx
  5124                              <1> a20d_dunno:
  5125                              <1> a20d_none:
  5126 00001857 6661                <1> 		popad
  5127 00001859 C3                  <1> 		ret
  5128                              <1> 
  5129                              <1> ;
  5130                              <1> ; Routine to empty the 8042 KBC controller.  If dl != 0
  5131                              <1> ; then we will test A20 in the loop and exit if A20 is
  5132                              <1> ; suddenly enabled.
  5133                              <1> ;
  5134                              <1> empty_8042_uncond:
  5135 0000185A 30D2                <1> 		xor dl,dl
  5136                              <1> empty_8042:
  5137 0000185C E89AFF              <1> 		call a20_test
  5138 0000185F 7404                <1> 		jz .a20_on
  5139 00001861 20D2                <1> 		and dl,dl
  5140 00001863 7517                <1> 		jnz .done
  5141 00001865 E80BFF              <1> .a20_on:	io_delay
  5142 00001868 E464                <1> 		in al, 064h		; Status port
  5143 0000186A A801                <1> 		test al,1
  5144 0000186C 7407                <1> 		jz .no_output
  5145 0000186E E802FF              <1> 		io_delay
  5146 00001871 E460                <1> 		in al, 060h		; Read input
  5147 00001873 EBE7                <1> 		jmp short empty_8042
  5148                              <1> .no_output:
  5149 00001875 A802                <1> 		test al,2
  5150 00001877 75E3                <1> 		jnz empty_8042
  5151 00001879 E8F7FE              <1> 		io_delay
  5152 0000187C C3                  <1> .done:		ret	
  5153                              <1> 
  5154                              <1> ;
  5155                              <1> ; Execute a WBINVD instruction if possible on this CPU
  5156                              <1> ;
  5157                              <1> %if DO_WBINVD
  5158                              <1> try_wbinvd:
  5159                              <1> 		wbinvd
  5160                              <1> 		ret
  5161                              <1> %endif
  5162                              <1> 
  5163                              <1> ;
  5164                              <1> ; bcopy_over_self:
  5165                              <1> ;
  5166                              <1> ; This routine is used to copy large blocks of code on top of
  5167                              <1> ; conventional memory (to 0:7c00).  We therefore have to move
  5168                              <1> ; necessary code into the trackbuf area before doing the copy,
  5169                              <1> ; and do adjustments to anything except BSS area references.
  5170                              <1> ;
  5171                              <1> ; After performing the copy, this routine resets the stack and
  5172                              <1> ; jumps to 0:7c00.
  5173                              <1> ;
  5174                              <1> ; IMPORTANT: This routine does not canonicalize the stack or the
  5175                              <1> ; SS register.  That is the responsibility of the caller.
  5176                              <1> ;
  5177                              <1> ; Inputs:
  5178                              <1> ;	ESI, EDI, ECX	- same as bcopy
  5179                              <1> ;	On stack	- initial state (ad, fd, ds, es, fs, gs)
  5180                              <1> ;
  5181                              <1> %define ADJUST	(__bcopy_start - trackbuf)
  5182                              <1> 
  5183 0000187D 90                  <1> 		align 2
  5184 0000187E 0210                <1> adjlist		dw bcopy_gdt.adj1 - ADJUST
  5185 00001880 4C10                <1> 		dw bcopy.adj2 + 5 - ADJUST
  5186 00001882 5710                <1> 		dw bcopy.adj3a + 1 - ADJUST
  5187 00001884 8B10                <1> 		dw bcopy.adj3b + 1 - ADJUST
  5188 00001886 CE10                <1> 		dw try_enable_a20.adj4 + 3 - ADJUST
  5189 00001888 6B11                <1> 		dw disable_a20.adj5 + 3 - ADJUST
  5190                              <1> adjlist_cnt	equ ($-adjlist)/2
  5191                              <1> 
  5192                              <1> bcopy_over_self:
  5193 0000188A 6656                <1> 		push esi	
  5194 0000188C 6657                <1> 		push edi
  5195 0000188E 6651                <1> 		push ecx
  5196                              <1> 
  5197 00001890 31DB                <1> 		xor bx,bx
  5198 00001892 8EC3                <1> 		mov es,bx
  5199 00001894 8EDB                <1> 		mov ds,bx
  5200                              <1> 
  5201 00001896 BE[BC16]            <1> 		mov si,__bcopy_start
  5202 00001899 BF0010              <1> 		mov di,trackbuf
  5203 0000189C B98800              <1> 		mov cx,(__bcopy_end - __bcopy_start + 3) >> 2
  5204 0000189F F366A5              <1> 		rep movsd
  5205                              <1> 
  5206 000018A2 BEA210              <1> 		mov si,A20List - ADJUST
  5207 000018A5 B90A00              <1> 		mov cx,a20_adjust_cnt
  5208                              <1> .adjust1:
  5209 000018A8 812C[BC06]          <1> 		sub word [si], ADJUST
  5210 000018AC 46                  <1> 		inc si
  5211 000018AD 46                  <1> 		inc si
  5212 000018AE E2F8                <1> 		loop .adjust1
  5213                              <1> 
  5214 000018B0 BE[7E18]            <1> 		mov si, adjlist
  5215 000018B3 B90600              <1> 		mov cx, adjlist_cnt
  5216                              <1> .adjust2:
  5217 000018B6 AD                  <1> 		lodsw
  5218 000018B7 97                  <1> 		xchg di,ax
  5219 000018B8 812D[BC06]          <1> 		sub word [di], ADJUST
  5220 000018BC E2F8                <1> 		loop .adjust2
  5221                              <1> 
  5222 000018BE E9(0512)            <1> 		jmp .next-ADJUST
  5223                              <1> .next:
  5224 000018C1 6659                <1> 		pop ecx
  5225 000018C3 665F                <1> 		pop edi
  5226 000018C5 665E                <1> 		pop esi
  5227 000018C7 E822FE              <1> 		call bcopy
  5228                              <1> 		
  5229 000018CA 0FA9                <1> 		pop gs
  5230 000018CC 0FA1                <1> 		pop fs
  5231 000018CE 07                  <1> 		pop es
  5232 000018CF 1F                  <1> 		pop ds
  5233 000018D0 669D                <1> 		popfd
  5234 000018D2 6661                <1> 		popad
  5235 000018D4 EA007C0000          <1> 		jmp 0:7c00h
  5236                              <1> __bcopy_end:
  5237                                  %include "loadhigh.inc"		; Load a file into high memory
  5238                              <1> ;; $Id: loadhigh.inc,v 1.3 2002/06/01 07:51:40 hpa Exp $
  5239                              <1> ;; -----------------------------------------------------------------------
  5240                              <1> ;;   
  5241                              <1> ;;   Copyright 1994-2002 H. Peter Anvin - All Rights Reserved
  5242                              <1> ;;
  5243                              <1> ;;   This program is free software; you can redistribute it and/or modify
  5244                              <1> ;;   it under the terms of the GNU General Public License as published by
  5245                              <1> ;;   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
  5246                              <1> ;;   Bostom MA 02111-1307, USA; either version 2 of the License, or
  5247                              <1> ;;   (at your option) any later version; incorporated herein by reference.
  5248                              <1> ;;
  5249                              <1> ;; -----------------------------------------------------------------------
  5250                              <1> 
  5251                              <1> ;;
  5252                              <1> ;; loadhigh.inc
  5253                              <1> ;; 
  5254                              <1> ;; Load a file into high memory
  5255                              <1> ;;
  5256                              <1> 
  5257                              <1> ;
  5258                              <1> ; load_high:	loads (the remainder of) a file into high memory.
  5259                              <1> ;		This routine prints dots for each 64K transferred, and
  5260                              <1> ;		calls abort_check periodically.
  5261                              <1> ; 
  5262                              <1> ;		The xfer_buf_seg is used as a bounce buffer.
  5263                              <1> ;
  5264                              <1> ;		The input address (EDI) should be dword aligned, and the final
  5265                              <1> ;		dword written is padded with zeroes if necessary.
  5266                              <1> ;
  5267                              <1> ; Inputs:	SI  = file handle/cluster pointer
  5268                              <1> ;		EDI = target address in high memory
  5269                              <1> ;		EAX = size of remaining file in bytes
  5270                              <1> ;
  5271                              <1> ; Outputs:	SI  = file handle/cluster pointer
  5272                              <1> ;		EDI = first untouched address (not including padding)
  5273                              <1> ;
  5274                              <1> load_high:
  5275 000018D9 06                  <1> 		push es
  5276                              <1> 
  5277 000018DA BB0030              <1> 		mov bx,xfer_buf_seg
  5278 000018DD 8EC3                <1> 		mov es,bx
  5279                              <1> 
  5280                              <1> .read_loop:
  5281 000018DF 21F6                <1> 		and si,si			; If SI == 0 then we have end of file
  5282 000018E1 7467                <1> 		jz .eof
  5283 000018E3 56                  <1> 		push si
  5284 000018E4 BE[7A1F]            <1> 		mov si,dot_msg
  5285 000018E7 E899FB              <1> 		call cwritestr
  5286 000018EA 5E                  <1> 		pop si
  5287 000018EB E848F6              <1> 		call abort_check
  5288                              <1> 
  5289 000018EE 6650                <1> 		push eax			; <A> Total bytes to transfer
  5290 000018F0 663D00000100        <1> 		cmp eax,(1 << 16)		; Max 64K in one transfer
  5291 000018F6 7606                <1> 		jna .size_ok
  5292 000018F8 66B800000100        <1> 		mov eax,(1 << 16)
  5293                              <1> .size_ok:
  5294 000018FE 6631D2              <1> 		xor edx,edx
  5295 00001901 6650                <1> 		push eax			; <B> Bytes transferred this chunk
  5296 00001903 66F7367055          <1> 		div dword [ClustSize]		; Convert to clusters
  5297                              <1> 		; Round up...
  5298 00001908 6683C2FF            <1> 		add edx,byte -1			; Sets CF if EDX >= 1
  5299 0000190C 6683D000            <1> 		adc eax,byte 0			; Add 1 to EAX if CF set
  5300                              <1> 
  5301                              <1> 		; Now (e)ax contains the number of clusters to get
  5302 00001910 6657                <1> 		push edi			; <C> Target buffer
  5303 00001912 89C1                <1> 		mov cx,ax
  5304 00001914 31DB                <1> 		xor bx,bx			; ES:0
  5305 00001916 E8FCE9              <1> 		call getfssec			; Load the data into xfer_buf_seg
  5306 00001919 665F                <1> 		pop edi				; <C> Target buffer
  5307 0000191B 6659                <1> 		pop ecx				; <B> Byte count this round
  5308 0000191D 6651                <1> 		push ecx			; <B> Byte count this round 
  5309 0000191F 6657                <1> 		push edi			; <C> Target buffer
  5310                              <1> .fix_slop:
  5311 00001921 F6C103              <1> 		test cl,3
  5312 00001924 7409                <1> 		jz .noslop
  5313                              <1> 		; The last dword fractional - pad with zeroes
  5314                              <1> 		; Zero-padding is critical for multi-file initramfs.
  5315 00001926 2667C60100          <1> 		mov byte [es:ecx],0
  5316 0000192B 6641                <1> 		inc ecx
  5317 0000192D EBF2                <1> 		jmp short .fix_slop
  5318                              <1> .noslop:
  5319 0000192F 6656                <1> 		push esi			; <D> File handle/cluster pointer
  5320 00001931 66BE00000300        <1> 		mov esi,(xfer_buf_seg << 4)	; Source address
  5321 00001937 E8B2FD              <1> 		call bcopy			; Copy to high memory
  5322 0000193A 665E                <1> 		pop esi				; <D> File handle/cluster pointer
  5323 0000193C 665F                <1> 		pop edi				; <C> Target buffer
  5324 0000193E 6659                <1> 		pop ecx				; <B> Byte count this round
  5325 00001940 6658                <1> 		pop eax				; <A> Total bytes to transfer
  5326 00001942 6601CF              <1> 		add edi,ecx
  5327 00001945 6629C8              <1> 		sub eax,ecx
  5328 00001948 7595                <1> 		jnz .read_loop			; More to read...
  5329                              <1> 		
  5330                              <1> .eof:
  5331 0000194A 07                  <1> 		pop es
  5332 0000194B C3                  <1> 		ret
  5333                              <1> 
  5334                                  %include "font.inc"		; VGA font stuff
  5335                              <1> ;; $Id: font.inc,v 1.1 2002/04/26 22:17:52 hpa Exp $
  5336                              <1> ;; -----------------------------------------------------------------------
  5337                              <1> ;;   
  5338                              <1> ;;   Copyright 1994-2002 H. Peter Anvin - All Rights Reserved
  5339                              <1> ;;
  5340                              <1> ;;   This program is free software; you can redistribute it and/or modify
  5341                              <1> ;;   it under the terms of the GNU General Public License as published by
  5342                              <1> ;;   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
  5343                              <1> ;;   Bostom MA 02111-1307, USA; either version 2 of the License, or
  5344                              <1> ;;   (at your option) any later version; incorporated herein by reference.
  5345                              <1> ;;
  5346                              <1> ;; -----------------------------------------------------------------------
  5347                              <1> 
  5348                              <1> ;;
  5349                              <1> ;; font.inc
  5350                              <1> ;;
  5351                              <1> ;; VGA font handling code
  5352                              <1> ;;
  5353                              <1> 
  5354                              <1> ;
  5355                              <1> ; loadfont:	Load a .psf font file and install it onto the VGA console
  5356                              <1> ;		(if we're not on a VGA screen then ignore.)  It is called with
  5357                              <1> ;		SI and DX:AX set by routine searchdir
  5358                              <1> ;
  5359                              <1> loadfont:
  5360 0000194C BB0010              <1> 		mov bx,trackbuf			; The trackbuf is >= 16K; the part
  5361 0000194F 8B0E8C55            <1> 		mov cx,[BufSafe]		; of a PSF file we care about is no
  5362 00001953 E8BFE9              <1> 		call getfssec			; more than 8K+4 bytes
  5363                              <1> 
  5364 00001956 A10010              <1> 		mov ax,[trackbuf]		; Magic number
  5365 00001959 3D3604              <1> 		cmp ax,0436h
  5366 0000195C 7560                <1> 		jne lf_ret
  5367                              <1> 
  5368 0000195E A00210              <1> 		mov al,[trackbuf+2]		; File mode
  5369 00001961 3C05                <1> 		cmp al,5			; Font modes 0-5 supported
  5370 00001963 7759                <1> 		ja lf_ret
  5371                              <1> 
  5372 00001965 8A3E0310            <1> 		mov bh,byte [trackbuf+3]	; Height of font
  5373 00001969 80FF02              <1> 		cmp bh,2			; VGA minimum
  5374 0000196C 7250                <1> 		jb lf_ret
  5375 0000196E 80FF20              <1> 		cmp bh,32			; VGA maximum
  5376 00001971 774B                <1> 		ja lf_ret
  5377                              <1> 
  5378                              <1> 		; Copy to font buffer
  5379 00001973 BE0410              <1> 		mov si,trackbuf+4		; Start of font data
  5380 00001976 883E[8020]          <1> 		mov [VGAFontSize],bh
  5381 0000197A BF00E0              <1> 		mov di,vgafontbuf
  5382 0000197D B90008              <1> 		mov cx,(32*256) >> 2		; Maximum size
  5383 00001980 F366A5              <1> 		rep movsd
  5384                              <1> 
  5385 00001983 C606[8220]01        <1> 		mov [UserFont], byte 1		; Set font flag
  5386                              <1> 
  5387                              <1> 		; Fall through to use_font
  5388                              <1> 
  5389                              <1> ;
  5390                              <1> ; use_font:
  5391                              <1> ; 	This routine activates whatever font happens to be in the
  5392                              <1> ;	vgafontbuf, and updates the adjust_screen data.
  5393                              <1> ;       Must be called with CS = DS = ES
  5394                              <1> ;
  5395                              <1> use_font:
  5396 00001988 F606[8220]01        <1> 		test [UserFont], byte 1		; Are we using a user-specified font?
  5397 0000198D 7441                <1> 		jz adjust_screen		; If not, just do the normal stuff
  5398                              <1> 
  5399 0000198F BD00E0              <1> 		mov bp,vgafontbuf
  5400 00001992 8A3E[8020]          <1> 		mov bh,[VGAFontSize]
  5401                              <1> 
  5402 00001996 30DB                <1> 		xor bl,bl			; Needed by both INT 10h calls
  5403 00001998 803E[C81B]01        <1> 		cmp [UsingVGA], byte 1		; Are we in graphics mode?
  5404 0000199D 7520                <1> 		jne .text
  5405                              <1> 
  5406                              <1> .graphics:
  5407 0000199F 31C9                <1> 		xor cx,cx
  5408 000019A1 88F9                <1> 		mov cl,bh			; CX = bytes/character
  5409 000019A3 B8E001              <1> 		mov ax,480
  5410 000019A6 F6F1                <1> 		div cl				; Compute char rows per screen
  5411 000019A8 88C2                <1> 		mov dl,al
  5412 000019AA FEC8                <1> 		dec al
  5413 000019AC A2B955              <1> 		mov [VidRows],al
  5414 000019AF B82111              <1> 		mov ax,1121h			; Set user character table
  5415 000019B2 CD10                <1> 		int 10h
  5416 000019B4 C606B8554F          <1> 		mov [VidCols], byte 79		; Always 80 bytes/line
  5417 000019B9 C606B55500          <1> 		mov [TextPage], byte 0		; Always page 0
  5418 000019BE C3                  <1> .lf_ret:	ret				; No need to call adjust_screen
  5419                              <1> 
  5420                              <1> .text:
  5421 000019BF B90001              <1> 		mov cx,256
  5422 000019C2 31D2                <1> 		xor dx,dx
  5423 000019C4 B81011              <1> 		mov ax,1110h
  5424 000019C7 CD10                <1> 		int 10h				; Load into VGA RAM
  5425                              <1> 
  5426 000019C9 30DB                <1> 		xor bl,bl
  5427 000019CB B80311              <1> 		mov ax,1103h			; Select page 0
  5428 000019CE CD10                <1> 		int 10h
  5429                              <1> 
  5430                              <1> 		; Fall through to adjust_screen
  5431                              <1> 
  5432                              <1> lf_ret		equ use_font.lf_ret
  5433                              <1> 
  5434                              <1> ;
  5435                              <1> ; adjust_screen: Set the internal variables associated with the screen size.
  5436                              <1> ;		This is a subroutine in case we're loading a custom font.
  5437                              <1> ;
  5438                              <1> adjust_screen:
  5439 000019D0 A08404              <1>                 mov al,[BIOS_vidrows]
  5440 000019D3 20C0                <1>                 and al,al
  5441 000019D5 7502                <1>                 jnz vidrows_ok
  5442 000019D7 B018                <1>                 mov al,24                       ; No vidrows in BIOS, assume 25
  5443                              <1> 						; (Remember: vidrows == rows-1)
  5444 000019D9 A2B955              <1> vidrows_ok:	mov [VidRows],al
  5445 000019DC B40F                <1>                 mov ah,0fh
  5446 000019DE CD10                <1>                 int 10h                         ; Read video state
  5447 000019E0 883EB555            <1>                 mov [TextPage],bh
  5448 000019E4 FECC                <1>                 dec ah                          ; Store count-1 (same as rows)
  5449 000019E6 8826B855            <1>                 mov [VidCols],ah
  5450 000019EA C3                  <1> 		ret
  5451                              <1> 
  5452                                  %include "graphics.inc"		; VGA graphics
  5453                              <1> ;; $Id: graphics.inc,v 1.2 2002/06/10 18:32:42 hpa Exp $
  5454                              <1> ;; -----------------------------------------------------------------------
  5455                              <1> ;;   
  5456                              <1> ;;   Copyright 1994-2002 H. Peter Anvin - All Rights Reserved
  5457                              <1> ;;
  5458                              <1> ;;   This program is free software; you can redistribute it and/or modify
  5459                              <1> ;;   it under the terms of the GNU General Public License as published by
  5460                              <1> ;;   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
  5461                              <1> ;;   Bostom MA 02111-1307, USA; either version 2 of the License, or
  5462                              <1> ;;   (at your option) any later version; incorporated herein by reference.
  5463                              <1> ;;
  5464                              <1> ;; -----------------------------------------------------------------------
  5465                              <1> 
  5466                              <1> ; ----------------------------------------------------------------------------
  5467                              <1> ;  VGA splash screen code
  5468                              <1> ; ----------------------------------------------------------------------------
  5469                              <1> 
  5470                              <1> ;
  5471                              <1> ; vgadisplayfile:
  5472                              <1> ;	Display a graphical splash screen.
  5473                              <1> ;
  5474                              <1> ; Input:
  5475                              <1> ;
  5476                              <1> ; SI	= cluster/socket pointer
  5477                              <1> ;
  5478                              <1> vgadisplayfile:
  5479 000019EB 8936B055            <1> 		mov [VGACluster],si
  5480 000019EF 06                  <1> 		push es
  5481                              <1> 
  5482                              <1> 		; This is a cheap and easy way to make sure the screen is
  5483                              <1> 		; cleared in case we were in graphics mode already
  5484 000019F0 E87E01              <1> 		call vgaclearmode
  5485 000019F3 E84D01              <1> 		call vgasetmode
  5486 000019F6 7514                <1> 		jnz .error_nz
  5487                              <1> 
  5488                              <1> .graphalready:
  5489 000019F8 B80030              <1> 		mov ax,xfer_buf_seg		; Use as temporary storage
  5490 000019FB 8EC0                <1> 		mov es,ax
  5491 000019FD 8EE0                <1> 		mov fs,ax
  5492                              <1> 
  5493 000019FF E8F300              <1> 		call vgagetchunk		; Get the first chunk
  5494                              <1> 
  5495                              <1> 		; The header WILL be in the first chunk.
  5496 00001A02 2666813E00403DF313- <1> 		cmp dword [es:xbs_vgabuf],0x1413f33d	; Magic number
  5497 00001A0B 14                  <1>
  5498 00001A0C 757D                <1> .error_nz:	jne .error
  5499 00001A0E 26A10440            <1> 		mov ax,[es:xbs_vgabuf+4]
  5500 00001A12 A3AC55              <1> 		mov [GraphXSize],ax
  5501                              <1> 
  5502 00001A15 BA0840              <1> 		mov dx,xbs_vgabuf+8		; Color map offset
  5503 00001A18 B81210              <1> 		mov ax,1012h			; Set RGB registers
  5504 00001A1B 31DB                <1> 		xor bx,bx			; First register number
  5505 00001A1D B91000              <1> 		mov cx,16			; 16 registers
  5506 00001A20 CD10                <1> 		int 10h
  5507                              <1> 	
  5508                              <1> .movecursor:
  5509 00001A22 26A10640            <1> 		mov ax,[es:xbs_vgabuf+6]	; Number of pixel rows
  5510 00001A26 8B16[8020]          <1> 		mov dx,[VGAFontSize]
  5511 00001A2A 01D0                <1> 		add ax,dx
  5512 00001A2C 48                  <1> 		dec ax
  5513 00001A2D F6F2                <1> 		div dl
  5514 00001A2F 31D2                <1> 		xor dx,dx			; Set column to 0
  5515 00001A31 3A06B955            <1> 		cmp al,[VidRows]
  5516 00001A35 7205                <1> 		jb .rowsok
  5517 00001A37 A0B955              <1> 		mov al,[VidRows]
  5518 00001A3A FEC8                <1> 		dec al
  5519                              <1> .rowsok:
  5520 00001A3C 88C6                <1> 		mov dh,al
  5521 00001A3E B402                <1> 		mov ah,2
  5522 00001A40 31DB                <1> 		xor bx,bx
  5523 00001A42 CD10                <1> 		int 10h				; Set cursor below image
  5524                              <1> 
  5525 00001A44 268B0E0640          <1> 		mov cx,[es:xbs_vgabuf+6]	; Number of graphics rows
  5526                              <1> 
  5527 00001A49 BE3840              <1> 		mov si,xbs_vgabuf+8+3*16	; Beginning of pixel data
  5528 00001A4C C706AE550000        <1> 		mov word [VGAPos],0
  5529                              <1> 
  5530                              <1> .drawpixelrow:
  5531 00001A52 51                  <1> 		push cx
  5532 00001A53 8B0EAC55            <1> 		mov cx,[GraphXSize]
  5533 00001A57 BF0080              <1> 		mov di,xbs_vgatmpbuf		; Row buffer
  5534 00001A5A E83000              <1> 		call rledecode			; Decode one row
  5535 00001A5D 56                  <1> 		push si
  5536 00001A5E BE0080              <1> 		mov si,xbs_vgatmpbuf
  5537 00001A61 89F7                <1> 		mov di,si
  5538 00001A63 033EAC55            <1> 		add di,[GraphXSize]
  5539 00001A67 B9A000              <1> 		mov cx,640/4
  5540 00001A6A 6631C0              <1> 		xor eax,eax
  5541 00001A6D F366AB              <1> 		rep stosd			; Clear rest of row
  5542 00001A70 BF00A0              <1> 		mov di,0A000h			; VGA segment
  5543 00001A73 8EC7                <1> 		mov es,di
  5544 00001A75 8B3EAE55            <1> 		mov di,[VGAPos]
  5545 00001A79 BD8002              <1> 		mov bp,640
  5546 00001A7C E89500              <1> 		call packedpixel2vga
  5547 00001A7F 8306AE5550          <1> 		add word [VGAPos],byte 80	; Advance to next pixel row
  5548 00001A84 0FA0                <1> 		push fs
  5549 00001A86 07                  <1> 		pop es
  5550 00001A87 5E                  <1> 		pop si
  5551 00001A88 59                  <1> 		pop cx
  5552 00001A89 E2C7                <1> 		loop .drawpixelrow
  5553                              <1> 
  5554                              <1> .error:
  5555 00001A8B 07                  <1> 		pop es
  5556 00001A8C C3                  <1> 		ret
  5557                              <1> 
  5558                              <1> ;
  5559                              <1> ; rledecode:
  5560                              <1> ;	Decode a pixel row in RLE16 format.
  5561                              <1> ;
  5562                              <1> ; FS:SI	-> input
  5563                              <1> ; CX -> pixel count
  5564                              <1> ; ES:DI -> output (packed pixel)
  5565                              <1> ;
  5566                              <1> rledecode:
  5567 00001A8D 66D1E6              <1> 		shl esi,1		; Nybble pointer
  5568 00001A90 30D2                <1> 		xor dl,dl		; Last pixel
  5569                              <1> .loop:
  5570 00001A92 E83E00              <1> 		call .getnybble
  5571 00001A95 38D0                <1> 		cmp al,dl
  5572 00001A97 740D                <1> 		je .run			; Start of run sequence
  5573 00001A99 AA                  <1> 		stosb
  5574 00001A9A 88C2                <1> 		mov dl,al
  5575 00001A9C 49                  <1> 		dec cx
  5576 00001A9D 75F3                <1> 		jnz .loop
  5577                              <1> .done:
  5578 00001A9F 66D1EE              <1> 		shr esi,1
  5579 00001AA2 83D600              <1> 		adc si,byte 0
  5580 00001AA5 C3                  <1> 		ret
  5581                              <1> .run:
  5582 00001AA6 31DB                <1> 		xor bx,bx
  5583 00001AA8 E82800              <1> 		call .getnybble
  5584 00001AAB 20C0                <1> 		and al,al
  5585 00001AAD 7410                <1> 		jz .longrun
  5586 00001AAF 88C3                <1> 		mov bl,al
  5587                              <1> .dorun:
  5588 00001AB1 51                  <1> 		push cx
  5589 00001AB2 89D9                <1> 		mov cx,bx
  5590 00001AB4 88D0                <1> 		mov al,dl
  5591 00001AB6 F3AA                <1> 		rep stosb
  5592 00001AB8 59                  <1> 		pop cx
  5593 00001AB9 29D9                <1> 		sub cx,bx
  5594 00001ABB 77D5                <1> 		ja .loop
  5595 00001ABD EBE0                <1> 		jmp short .done
  5596                              <1> .longrun:
  5597 00001ABF E81100              <1> 		call .getnybble
  5598 00001AC2 88C4                <1> 		mov ah,al
  5599 00001AC4 E80C00              <1> 		call .getnybble
  5600 00001AC7 C0E004              <1> 		shl al,4
  5601 00001ACA 08E0                <1> 		or al,ah
  5602 00001ACC 88C3                <1> 		mov bl,al
  5603 00001ACE 83C310              <1> 		add bx,16
  5604 00001AD1 EBDE                <1> 		jmp short .dorun
  5605                              <1> .getnybble:
  5606 00001AD3 66D1EE              <1> 		shr esi,1
  5607 00001AD6 64AC                <1> 		fs lodsb
  5608 00001AD8 7208                <1> 		jc .high
  5609 00001ADA 4E                  <1> 		dec si
  5610 00001ADB 240F                <1> 		and al,0Fh
  5611 00001ADD F9                  <1> 		stc
  5612 00001ADE 66D1D6              <1> 		rcl esi,1
  5613 00001AE1 C3                  <1> 		ret
  5614                              <1> .high:
  5615 00001AE2 C0E804              <1> 		shr al,4
  5616 00001AE5 81FE0080            <1> 		cmp si,xbs_vgabuf+trackbufsize	; Chunk overrun
  5617 00001AE9 7206                <1> 		jb .nonewchunk
  5618 00001AEB E80700              <1> 		call vgagetchunk
  5619 00001AEE BE0040              <1> 		mov si,xbs_vgabuf		; Start at beginning of buffer
  5620                              <1> .nonewchunk:
  5621 00001AF1 66D1E6              <1> 		shl esi,1
  5622 00001AF4 C3                  <1> 		ret
  5623                              <1> 
  5624                              <1> ;
  5625                              <1> ; vgagetchunk:
  5626                              <1> ;	Get a new trackbufsize chunk of VGA image data
  5627                              <1> ;
  5628                              <1> ; On input, ES is assumed to point to the buffer segment.
  5629                              <1> ;
  5630                              <1> vgagetchunk:
  5631 00001AF5 6660                <1> 		pushad
  5632 00001AF7 8B36B055            <1> 		mov si,[VGACluster]
  5633 00001AFB 21F6                <1> 		and si,si
  5634 00001AFD 7412                <1> 		jz .eof				; EOF overrun, not much to do...
  5635                              <1> 
  5636 00001AFF 8B0E8C55            <1> 		mov cx,[BufSafe]		; One trackbuf worth of data
  5637 00001B03 BB0040              <1> 		mov bx,xbs_vgabuf
  5638 00001B06 E80CE8              <1> 		call getfssec
  5639                              <1> 
  5640 00001B09 7302                <1> 		jnc .noteof
  5641 00001B0B 31F6                <1> 		xor si,si
  5642 00001B0D 8936B055            <1> .noteof:	mov [VGACluster],si
  5643                              <1> 
  5644 00001B11 6661                <1> .eof:		popad
  5645 00001B13 C3                  <1> 		ret
  5646                              <1> 
  5647                              <1> ;
  5648                              <1> ; packedpixel2vga:
  5649                              <1> ;	Convert packed-pixel to VGA bitplanes
  5650                              <1> ;
  5651                              <1> ; FS:SI -> packed pixel string
  5652                              <1> ; BP    -> pixel count (multiple of 8)
  5653                              <1> ; ES:DI -> output
  5654                              <1> ;
  5655                              <1> packedpixel2vga:
  5656 00001B14 BAC403              <1> 		mov dx,3C4h	; VGA Sequencer Register select port
  5657 00001B17 B002                <1> 		mov al,2	; Sequencer mask
  5658 00001B19 EE                  <1> 		out dx,al	; Select the sequencer mask
  5659 00001B1A 42                  <1> 		inc dx		; VGA Sequencer Register data port
  5660 00001B1B B001                <1> 		mov al,1
  5661 00001B1D 88C3                <1> 		mov bl,al
  5662                              <1> .planeloop:
  5663 00001B1F 60                  <1> 		pusha
  5664 00001B20 EE                  <1> 		out dx,al
  5665                              <1> .loop1:
  5666 00001B21 B90800              <1> 		mov cx,8
  5667                              <1> .loop2:
  5668 00001B24 87CB                <1> 		xchg cx,bx
  5669 00001B26 64AC                <1> 		fs lodsb
  5670 00001B28 D2E8                <1> 		shr al,cl
  5671 00001B2A D0D5                <1> 		rcl ch,1	; VGA is bigendian.  Sigh.
  5672 00001B2C 87CB                <1> 		xchg cx,bx
  5673 00001B2E E2F4                <1> 		loop .loop2
  5674 00001B30 88F8                <1> 		mov al,bh
  5675 00001B32 AA                  <1> 		stosb
  5676 00001B33 83ED08              <1> 		sub bp,byte 8
  5677 00001B36 77E9                <1> 		ja .loop1
  5678 00001B38 61                  <1> 		popa
  5679 00001B39 FEC3                <1> 		inc bl
  5680 00001B3B D0E0                <1> 		shl al,1
  5681 00001B3D 80FB04              <1> 		cmp bl,4
  5682 00001B40 76DD                <1> 		jbe .planeloop
  5683 00001B42 C3                  <1> 		ret
  5684                              <1> 
  5685                              <1> ;
  5686                              <1> ; vgasetmode:
  5687                              <1> ;	Enable VGA graphics, if possible; return ZF=1 on success
  5688                              <1> ;	DS must be set to the base segment; ES is set to DS.
  5689                              <1> ;
  5690                              <1> vgasetmode:
  5691 00001B43 1E                  <1> 		push ds
  5692 00001B44 07                  <1> 		pop es
  5693 00001B45 B8001A              <1> 		mov ax,1A00h		; Get video card and monitor
  5694 00001B48 31DB                <1> 		xor bx,bx
  5695 00001B4A CD10                <1> 		int 10h
  5696 00001B4C 80EB07              <1> 		sub bl, 7		; BL=07h and BL=08h OK
  5697 00001B4F 80FB01              <1> 		cmp bl, 1
  5698 00001B52 771C                <1> 		ja .error		; ZF=0
  5699                              <1> ;		mov bx,TextColorReg
  5700                              <1> ;		mov dx,1009h		; Read color registers
  5701                              <1> ;		int 10h
  5702 00001B54 B81200              <1> 		mov ax,0012h		; Set mode = 640x480 VGA 16 colors
  5703 00001B57 CD10                <1> 		int 10h
  5704 00001B59 BA[B71B]            <1> 		mov dx,linear_color
  5705 00001B5C B80210              <1> 		mov ax,1002h		; Write color registers
  5706 00001B5F CD10                <1> 		int 10h
  5707 00001B61 C606[C81B]01        <1> 		mov [UsingVGA], byte 1
  5708                              <1> 
  5709 00001B66 E81FFE              <1> 		call use_font		; Set graphics font/data
  5710 00001B69 C606[8320]00        <1> 		mov byte [ScrollAttribute], 00h
  5711                              <1> 
  5712 00001B6E 31C0                <1> 		xor ax,ax		; Set ZF
  5713                              <1> .error:
  5714 00001B70 C3                  <1> 		ret
  5715                              <1> 
  5716                              <1> ;
  5717                              <1> ; vgaclearmode:
  5718                              <1> ;	Disable VGA graphics.  It is not safe to assume any value
  5719                              <1> ;	for DS or ES.
  5720                              <1> ;
  5721                              <1> vgaclearmode:
  5722 00001B71 1E                  <1> 		push ds
  5723 00001B72 06                  <1> 		push es
  5724 00001B73 6660                <1> 		pushad
  5725 00001B75 8CC8                <1> 		mov ax,cs
  5726 00001B77 8ED8                <1> 		mov ds,ax
  5727 00001B79 8EC0                <1> 		mov es,ax
  5728 00001B7B 803E[C81B]01        <1> 		cmp [UsingVGA], byte 1
  5729 00001B80 7512                <1> 		jne .done
  5730 00001B82 B80300              <1> 		mov ax,0003h		; Return to normal video mode
  5731 00001B85 CD10                <1> 		int 10h
  5732                              <1> ;		mov dx,TextColorReg	; Restore color registers
  5733                              <1> ;		mov ax,1002h
  5734                              <1> ;		int 10h
  5735 00001B87 C606[C81B]00        <1> 		mov [UsingVGA], byte 0
  5736                              <1> 
  5737 00001B8C E8F9FD              <1> 		call use_font		; Restore text font/data
  5738 00001B8F C606[8320]07        <1> 		mov byte [ScrollAttribute], 07h
  5739                              <1> .done:
  5740 00001B94 6661                <1> 		popad
  5741 00001B96 07                  <1> 		pop es
  5742 00001B97 1F                  <1> 		pop ds
  5743 00001B98 C3                  <1> 		ret
  5744                              <1> 
  5745                              <1> ;
  5746                              <1> ; vgashowcursor/vgahidecursor:
  5747                              <1> ;	If VGA graphics is enabled, draw a cursor/clear a cursor
  5748                              <1> ;
  5749                              <1> vgashowcursor:
  5750 00001B99 6660                <1> 		pushad
  5751 00001B9B B05F                <1> 		mov al,'_'
  5752 00001B9D EB04                <1> 		jmp short vgacursorcommon
  5753                              <1> vgahidecursor:
  5754 00001B9F 6660                <1> 		pushad
  5755 00001BA1 B020                <1> 		mov al,' '
  5756                              <1> vgacursorcommon:
  5757 00001BA3 803E[C81B]01        <1> 		cmp [UsingVGA], byte 1
  5758 00001BA8 750A                <1> 		jne .done
  5759 00001BAA B409                <1> 		mov ah,09h
  5760 00001BAC BB0700              <1> 		mov bx,0007h
  5761 00001BAF B90100              <1> 		mov cx,1
  5762 00001BB2 CD10                <1> 		int 10h
  5763                              <1> .done:
  5764 00001BB4 6661                <1> 		popad
  5765 00001BB6 C3                  <1> 		ret
  5766                              <1> 
  5767                              <1> 
  5768                              <1> 		; Map colors to consecutive DAC registers
  5769 00001BB7 000102030405060708- <1> linear_color	db 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0
  5770 00001BC0 090A0B0C0D0E0F00    <1>
  5771 00001BC8 00                  <1> UsingVGA	db 0
  5772                              <1> 
  5773                                  %include "highmem.inc"		; High memory sizing
  5774                              <1> ;; $Id: highmem.inc,v 1.1 2002/06/11 05:48:29 hpa Exp $
  5775                              <1> ;; -----------------------------------------------------------------------
  5776                              <1> ;;   
  5777                              <1> ;;   Copyright 1994-2002 H. Peter Anvin - All Rights Reserved
  5778                              <1> ;;
  5779                              <1> ;;   This program is free software; you can redistribute it and/or modify
  5780                              <1> ;;   it under the terms of the GNU General Public License as published by
  5781                              <1> ;;   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
  5782                              <1> ;;   Bostom MA 02111-1307, USA; either version 2 of the License, or
  5783                              <1> ;;   (at your option) any later version; incorporated herein by reference.
  5784                              <1> ;;
  5785                              <1> ;; -----------------------------------------------------------------------
  5786                              <1> 
  5787                              <1> ;;
  5788                              <1> ;; highmem.inc
  5789                              <1> ;; 
  5790                              <1> ;; Probe for the size of high memory.  This can be overridden by a
  5791                              <1> ;; mem= command on the command line while booting a new kernel.
  5792                              <1> ;;
  5793                              <1> 
  5794                              <1> ;
  5795                              <1> ; This is set up as a subroutine; it will set up the global variable
  5796                              <1> ; HighMemSize.  All registers are preserved.  Assumes DS == CS.
  5797                              <1> ;
  5798                              <1> highmemsize:
  5799 00001BC9 06                  <1> 		push es
  5800 00001BCA 6660                <1> 		pushad
  5801                              <1> 
  5802                              <1> ;
  5803                              <1> ; First, try INT 15:E820 (get BIOS memory map)
  5804                              <1> ;
  5805                              <1> get_e820:
  5806 00001BCC 6631DB              <1> 		xor ebx,ebx			; Start with first record
  5807 00001BCF 8EC3                <1> 		mov es,bx			; Need ES = DS = 0 for now
  5808 00001BD1 EB05                <1> 		jmp short .do_e820		; Skip "at end" check first time!
  5809 00001BD3 6621DB              <1> .int_loop:	and ebx,ebx			; If we're back at beginning...
  5810 00001BD6 7456                <1> 		jz no_e820			; ... bail; nothing found
  5811 00001BD8 66B820E80000        <1> .do_e820:	mov eax,0000E820h
  5812 00001BDE 66BA50414D53        <1> 		mov edx,534D4150h		; "SMAP" backwards
  5813 00001BE4 6631C9              <1> 		xor ecx,ecx
  5814 00001BE7 B114                <1> 		mov cl,20			; ECX <- 20
  5815 00001BE9 BF4055              <1> 		mov di,E820Buf
  5816 00001BEC CD15                <1> 		int 15h
  5817 00001BEE 723E                <1> 		jc no_e820
  5818 00001BF0 663D50414D53        <1> 		cmp eax,534D4150h
  5819 00001BF6 7536                <1> 		jne no_e820
  5820                              <1> ;
  5821                              <1> ; Look for a memory block starting at <= 1 MB and continuing upward
  5822                              <1> ;
  5823 00001BF8 66833E445500        <1> 		cmp dword [E820Buf+4], byte 0
  5824 00001BFE 77D3                <1> 		ja .int_loop			; Start >= 4 GB?
  5825 00001C00 66BA00001000        <1> 		mov edx, (1 << 20)
  5826 00001C06 662B164055          <1> 		sub edx, [E820Buf]
  5827 00001C0B 72C6                <1> 		jb .int_loop			; Start >= 1 MB?
  5828 00001C0D F9                  <1> 		stc
  5829 00001C0E 6619C0              <1> 		sbb eax,eax			; eax <- 0xFFFFFFFF
  5830 00001C11 66833E4C5500        <1> 		cmp dword [E820Buf+12], byte 0
  5831 00001C17 7704                <1> 		ja .huge			; Size >= 4 GB
  5832 00001C19 66A14855            <1> 		mov eax, [E820Buf+8]
  5833 00001C1D 6629D0              <1> .huge:		sub eax, edx			; Adjust size to start at 1 MB
  5834 00001C20 76B1                <1> 		jbe .int_loop			; Completely below 1 MB?
  5835                              <1> 
  5836                              <1> 		; Now EAX contains the size of memory 1 MB...up
  5837 00001C22 66833E505501        <1> 		cmp dword [E820Buf+16], byte 1
  5838 00001C28 0F852402            <1> 		jne near err_nohighmem		; High memory isn't usable memory!!!!
  5839                              <1> 
  5840                              <1> 		; We're good!
  5841 00001C2C EB32                <1> 		jmp short got_highmem_add1mb	; Still need to add low 1 MB
  5842                              <1> 
  5843                              <1> ;
  5844                              <1> ; INT 15:E820 failed.  Try INT 15:E801.
  5845                              <1> ;
  5846                              <1> no_e820:
  5847 00001C2E B801E8              <1> 		mov ax,0e801h			; Query high memory (semi-recent)
  5848 00001C31 CD15                <1> 		int 15h
  5849 00001C33 7215                <1> 		jc no_e801
  5850 00001C35 3D003C              <1> 		cmp ax,3c00h
  5851 00001C38 7710                <1> 		ja no_e801			; > 3C00h something's wrong with this call
  5852 00001C3A 721A                <1> 		jb e801_hole			; If memory hole we can only use low part
  5853                              <1> 
  5854 00001C3C 89D8                <1> 		mov ax,bx
  5855 00001C3E 66C1E010            <1> 		shl eax,16			; 64K chunks
  5856 00001C42 660500000001        <1> 		add eax,(16 << 20)		; Add first 16M
  5857 00001C48 EB1C                <1> 		jmp short got_highmem				
  5858                              <1> 
  5859                              <1> ;
  5860                              <1> ; INT 15:E801 failed.  Try INT 15:88.
  5861                              <1> ;
  5862                              <1> no_e801:
  5863 00001C4A B488                <1> 		mov ah,88h			; Query high memory (oldest)
  5864 00001C4C CD15                <1> 		int 15h
  5865 00001C4E 3D0038              <1> 		cmp ax,14*1024			; Don't trust memory >15M
  5866 00001C51 7603                <1> 		jna e801_hole
  5867 00001C53 B80038              <1> 		mov ax,14*1024
  5868                              <1> e801_hole:
  5869 00001C56 6625FFFF0000        <1> 		and eax,0ffffh
  5870 00001C5C 66C1E00A            <1> 		shl eax,10			; Convert from kilobytes
  5871                              <1> got_highmem_add1mb:
  5872 00001C60 660500001000        <1> 		add eax,(1 << 20)		; First megabyte
  5873                              <1> got_highmem:
  5874                              <1> %if HIGHMEM_SLOP != 0
  5875                              <1> 		sub eax,HIGHMEM_SLOP
  5876                              <1> %endif
  5877 00001C66 66A35855            <1> 		mov [HighMemSize],eax
  5878 00001C6A 6661                <1> 		popad
  5879 00001C6C 07                  <1> 		pop es
  5880 00001C6D C3                  <1> 		ret				; Done!
  5881                                  
  5882                                  ; -----------------------------------------------------------------------------
  5883                                  ;  Begin data section
  5884                                  ; -----------------------------------------------------------------------------
  5885                                  
  5886                                  CR		equ 13		; Carriage Return
  5887                                  LF		equ 10		; Line Feed
  5888                                  FF		equ 12		; Form Feed
  5889                                  BS		equ  8		; Backspace
  5890                                  
  5891                                  ;
  5892                                  ; Lower-case table for codepage 865
  5893                                  ;
  5894                                  lcase_low       equ 128
  5895                                  lcase_high      equ 165
  5896 00001C6E 878182838485868788-     lcase_tab       db 135, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138
  5897 00001C77 898A               
  5898 00001C79 8B8C8D848682919193-                     db 139, 140, 141, 132, 134, 130, 145, 145, 147, 148, 149
  5899 00001C82 9495               
  5900 00001C84 96979894819B9C9B9E-                     db 150, 151, 152, 148, 129, 155, 156, 155, 158, 159, 160
  5901 00001C8D 9FA0               
  5902 00001C8F A1A2A3A4A4                              db 161, 162, 163, 164, 164
  5903                                  
  5904 00001C94 20436F707972696768-     copyright_str   db ' Copyright (C) 1994-', year, ' H. Peter Anvin'
  5905 00001C9D 742028432920313939-
  5906 00001CA6 342D3230303220482E-
  5907 00001CAF 20506574657220416E-
  5908 00001CB8 76696E             
  5909 00001CBB 0D0A00                  		db CR, LF, 0
  5910 00001CBE 626F6F743A2000          boot_prompt	db 'boot: ', 0
  5911 00001CC5 08200800                wipe_char	db BS, ' ', BS, 0
  5912 00001CC9 436F756C64206E6F74-     err_notfound	db 'Could not find kernel image: ',0
  5913 00001CD2 2066696E64206B6572-
  5914 00001CDB 6E656C20696D616765-
  5915 00001CE4 3A2000             
  5916 00001CE7 0D0A496E76616C6964-     err_notkernel	db CR, LF, 'Invalid or corrupt kernel image.', CR, LF, 0
  5917 00001CF0 206F7220636F727275-
  5918 00001CF9 7074206B65726E656C-
  5919 00001D02 20696D6167652E0D0A-
  5920 00001D0B 00                 
  5921 00001D0C 497420617070656172-     err_noram	db 'It appears your computer has less than 488K of low ("DOS")'
  5922 00001D15 7320796F757220636F-
  5923 00001D1E 6D7075746572206861-
  5924 00001D27 73206C657373207468-
  5925 00001D30 616E203438384B206F-
  5926 00001D39 66206C6F7720282244-
  5927 00001D42 4F532229           
  5928 00001D46 0D0A                    		db CR, LF
  5929 00001D48 52414D2E20204C696E-     		db 'RAM.  Linux needs at least this amount to boot.  If you get'
  5930 00001D51 7578206E6565647320-
  5931 00001D5A 6174206C6561737420-
  5932 00001D63 7468697320616D6F75-
  5933 00001D6C 6E7420746F20626F6F-
  5934 00001D75 742E2020496620796F-
  5935 00001D7E 7520676574         
  5936 00001D83 0D0A                    		db CR, LF
  5937 00001D85 74686973206D657373-     		db 'this message in error, hold down the Ctrl key while'
  5938 00001D8E 61676520696E206572-
  5939 00001D97 726F722C20686F6C64-
  5940 00001DA0 20646F776E20746865-
  5941 00001DA9 204374726C206B6579-
  5942 00001DB2 207768696C65       
  5943 00001DB8 0D0A                    		db CR, LF
  5944 00001DBA 626F6F74696E672C20-     		db 'booting, and I will take your word for it.', CR, LF, 0
  5945 00001DC3 616E6420492077696C-
  5946 00001DCC 6C2074616B6520796F-
  5947 00001DD5 757220776F72642066-
  5948 00001DDE 6F722069742E0D0A00 
  5949 00001DE7 556E6B6E6F776E206B-     err_badcfg      db 'Unknown keyword in syslinux.cfg.', CR, LF, 0
  5950 00001DF0 6579776F726420696E-
  5951 00001DF9 207379736C696E7578-
  5952 00001E02 2E6366672E0D0A00   
  5953 00001E0A 4D697373696E672070-     err_noparm      db 'Missing parameter in syslinux.cfg.', CR, LF, 0
  5954 00001E13 6172616D6574657220-
  5955 00001E1C 696E207379736C696E-
  5956 00001E25 75782E6366672E0D0A-
  5957 00001E2E 00                 
  5958 00001E2F 0D0A436F756C64206E-     err_noinitrd    db CR, LF, 'Could not find ramdisk image: ', 0
  5959 00001E38 6F742066696E642072-
  5960 00001E41 616D6469736B20696D-
  5961 00001E4A 6167653A2000       
  5962 00001E50 4E6F7420656E6F7567-     err_nohighmem   db 'Not enough memory to load specified kernel.', CR, LF, 0
  5963 00001E59 68206D656D6F727920-
  5964 00001E62 746F206C6F61642073-
  5965 00001E6B 706563696669656420-
  5966 00001E74 6B65726E656C2E0D0A-
  5967 00001E7D 00                 
  5968 00001E7E 0D0A4B65726E656C20-     err_highload    db CR, LF, 'Kernel transfer failure.', CR, LF, 0
  5969 00001E87 7472616E7366657220-
  5970 00001E90 6661696C7572652E0D-
  5971 00001E99 0A00               
  5972 00001E9B 43616E6E6F74206C6F-     err_oldkernel   db 'Cannot load a ramdisk with an old kernel image.'
  5973 00001EA4 616420612072616D64-
  5974 00001EAD 69736B207769746820-
  5975 00001EB6 616E206F6C64206B65-
  5976 00001EBF 726E656C20696D6167-
  5977 00001EC8 652E               
  5978 00001ECA 0D0A00                                  db CR, LF, 0
  5979 00001ECD 3A20617474656D7074-     err_notdos	db ': attempted DOS system call', CR, LF, 0
  5980 00001ED6 656420444F53207379-
  5981 00001EDF 7374656D2063616C6C-
  5982 00001EE8 0D0A00             
  5983 00001EEB 434F4D424F4F542069-     err_comlarge	db 'COMBOOT image too large.', CR, LF, 0
  5984 00001EF4 6D61676520746F6F20-
  5985 00001EFD 6C617267652E0D0A00 
  5986 00001F06 0D0A41323020676174-     err_a20		db CR, LF, 'A20 gate not responding!', CR, LF, 0
  5987 00001F0F 65206E6F7420726573-
  5988 00001F18 706F6E64696E67210D-
  5989 00001F21 0A00               
  5990 00001F23 0D0A426F6F74206661-     err_bootfailed	db CR, LF, 'Boot failed: please change disks and press '
  5991 00001F2C 696C65643A20706C65-
  5992 00001F35 617365206368616E67-
  5993 00001F3E 65206469736B732061-
  5994 00001F47 6E6420707265737320 
  5995 00001F50 61206B657920746F20-     		db 'a key to continue.', CR, LF, 0
  5996 00001F59 636F6E74696E75652E-
  5997 00001F62 0D0A00             
  5998 00001F65 52656164792E0D0A00      ready_msg	db 'Ready.', CR, LF, 0
  5999 00001F6E 0D0A                    crlfloading_msg	db CR, LF
  6000 00001F70 4C6F6164696E672000      loading_msg     db 'Loading ', 0
  6001 00001F79 2E                      dotdot_msg      db '.'
  6002 00001F7A 2E00                    dot_msg         db '.', 0
  6003 00001F7C 2061626F727465642E      aborted_msg	db ' aborted.'			; Fall through to crlf_msg!
  6004 00001F85 0D0A                    crlf_msg	db CR, LF
  6005 00001F87 00                      null_msg	db 0
  6006 00001F88 0D0C00                  crff_msg	db CR, FF, 0
  6007 00001F8B 5359534C494E555843-     syslinux_cfg	db 'SYSLINUXCFG'
  6008 00001F94 4647               
  6009                                  ;
  6010                                  ; Command line options we'd like to take a look at
  6011                                  ;
  6012                                  ; mem= and vga= are handled as normal 32-bit integer values
  6013 00001F96 696E697472643D          initrd_cmd	db 'initrd='
  6014                                  initrd_cmd_len	equ 7
  6015                                  
  6016                                  ;
  6017                                  ; Config file keyword table
  6018                                  ;
  6019                                  %include "keywords.inc"
  6020                              <1> ;; $Id: keywords.inc,v 1.3 2002/04/30 03:33:27 hpa Exp $
  6021                              <1> ;; -----------------------------------------------------------------------
  6022                              <1> ;;   
  6023                              <1> ;;   Copyright 1994-2002 H. Peter Anvin - All Rights Reserved
  6024                              <1> ;;
  6025                              <1> ;;   This program is free software; you can redistribute it and/or modify
  6026                              <1> ;;   it under the terms of the GNU General Public License as published by
  6027                              <1> ;;   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
  6028                              <1> ;;   Bostom MA 02111-1307, USA; either version 2 of the License, or
  6029                              <1> ;;   (at your option) any later version; incorporated herein by reference.
  6030                              <1> ;;
  6031                              <1> ;; -----------------------------------------------------------------------
  6032                              <1> 
  6033                              <1> ;;
  6034                              <1> ;; keywords.inc
  6035                              <1> ;;
  6036                              <1> ;; Common header file for the handling of keyword hash and macros
  6037                              <1> ;;
  6038                              <1> 
  6039                              <1> %ifndef DEPEND		; Generated file
  6040                              <1> %include "kwdhash.gen"
  6041                              <2> hash_append             equ 0xc53999a4
  6042                              <2> hash_default            equ 0xcc5159ed
  6043                              <2> hash_display            equ 0xd509bc40
  6044                              <2> hash_font               equ 0x0032b1b4
  6045                              <2> hash_implicit           equ 0xa6f50207
  6046                              <2> hash_ipappend           equ 0xc5399af0
  6047                              <2> hash_kbdmap             equ 0xd013b850
  6048                              <2> hash_kernel             equ 0xd068b4cc
  6049                              <2> hash_label              equ 0x06f104cc
  6050                              <2> hash_localboot          equ 0x04f0def4
  6051                              <2> hash_prompt             equ 0xe7163a74
  6052                              <2> hash_say                equ 0x0001c059
  6053                              <2> hash_serial             equ 0xe068a84c
  6054                              <2> hash_timeout            equ 0xd4e332c9
  6055                              <2> hash_f0                 equ 0x00000cf0
  6056                              <2> hash_f1                 equ 0x00000cf1
  6057                              <2> hash_f2                 equ 0x00000cf2
  6058                              <2> hash_f3                 equ 0x00000cf3
  6059                              <2> hash_f4                 equ 0x00000cf4
  6060                              <2> hash_f5                 equ 0x00000cf5
  6061                              <2> hash_f6                 equ 0x00000cf6
  6062                              <2> hash_f7                 equ 0x00000cf7
  6063                              <2> hash_f8                 equ 0x00000cf8
  6064                              <2> hash_f9                 equ 0x00000cf9
  6065                              <2> hash_f10                equ 0x00019e10
  6066                              <2> hash_f11                equ 0x00019e11
  6067                              <2> hash_f12                equ 0x00019e12
  6068                              <1> %endif
  6069                              <1> 
  6070                              <1> %macro keyword 2
  6071                              <1> 	dd hash_%1	; Hash value
  6072                              <1> 	dw 0		; No argument
  6073                              <1> 	dw %2		; Entrypoint
  6074                              <1> %endmacro
  6075                              <1> 
  6076                              <1> %macro keyword 3
  6077                              <1> 	dd hash_%1	; Hash value
  6078                              <1> 	dw %3		; 16-bit argument
  6079                              <1> 	dw %2		; Entrypoint
  6080                              <1> %endmacro
  6081                              <1> 
  6082                              <1> %macro keyword 4
  6083                              <1> 	dd hash_%1	; Hash value
  6084                              <1> 	db %3, %4	; 2 8-bit arguments
  6085                              <1> 	dw %2		; Entrypoint
  6086                              <1> %endmacro
  6087                              <1> 
  6088                              <1> keywd_size	equ 8	; Bytes per keyword
  6089                              <1> 
  6090 00001F9D 00<rept>            <1> 		align 4, db 0
  6091                              <1> 
  6092                              <1> keywd_table:
  6093                              <1> 		keyword append,    pc_append
  6094 00001FA0 A49939C5            <2>  dd hash_%1
  6095 00001FA4 0000                <2>  dw 0
  6096 00001FA6 [A014]              <2>  dw %2
  6097                              <1> 		keyword default,   pc_default
  6098 00001FA8 ED5951CC            <2>  dd hash_%1
  6099 00001FAC 0000                <2>  dw 0
  6100 00001FAE [9614]              <2>  dw %2
  6101                              <1> 		keyword display,   pc_filecmd,  get_msg_file
  6102 00001FB0 40BC09D5            <2>  dd hash_%1
  6103 00001FB4 [4C12]              <2>  dw %3
  6104 00001FB6 [0415]              <2>  dw %2
  6105                              <1> 		keyword font,      pc_filecmd,  loadfont
  6106 00001FB8 B4B13200            <2>  dd hash_%1
  6107 00001FBC [4C19]              <2>  dw %3
  6108 00001FBE [0415]              <2>  dw %2
  6109                              <1> 		keyword implicit,  pc_setint16, AllowImplicit
  6110 00001FC0 0702F5A6            <2>  dd hash_%1
  6111 00001FC4 [7C20]              <2>  dw %3
  6112 00001FC6 [FA14]              <2>  dw %2
  6113                              <1> 		keyword kbdmap,    pc_filecmd,  loadkeys
  6114 00001FC8 50B813D0            <2>  dd hash_%1
  6115 00001FCC [2D12]              <2>  dw %3
  6116 00001FCE [0415]              <2>  dw %2
  6117                              <1> 		keyword kernel,    pc_kernel
  6118 00001FD0 CCB468D0            <2>  dd hash_%1
  6119 00001FD4 0000                <2>  dw 0
  6120 00001FD6 [D314]              <2>  dw %2
  6121                              <1> 		keyword label,     pc_label
  6122 00001FD8 CC04F106            <2>  dd hash_%1
  6123 00001FDC 0000                <2>  dw 0
  6124 00001FDE [E115]              <2>  dw %2
  6125                              <1> 		keyword prompt,    pc_setint16, ForcePrompt
  6126 00001FE0 743A16E7            <2>  dd hash_%1
  6127 00001FE4 [7A20]              <2>  dw %3
  6128 00001FE6 [FA14]              <2>  dw %2
  6129                              <1> 		keyword say,       pc_say
  6130 00001FE8 59C00100            <2>  dd hash_%1
  6131 00001FEC 0000                <2>  dw 0
  6132 00001FEE [1216]              <2>  dw %2
  6133                              <1> 		keyword serial,    pc_serial
  6134 00001FF0 4CA868E0            <2>  dd hash_%1
  6135 00001FF4 0000                <2>  dw 0
  6136 00001FF6 [1C15]              <2>  dw %2
  6137                              <1> 		keyword timeout,   pc_timeout
  6138 00001FF8 C932E3D4            <2>  dd hash_%1
  6139 00001FFC 0000                <2>  dw 0
  6140 00001FFE [E914]              <2>  dw %2
  6141                              <1> 		keyword f1,        pc_fkey,     FKeyName+(0<<FILENAME_MAX_LG2)
  6142 00002000 F10C0000            <2>  dd hash_%1
  6143 00002004 0054                <2>  dw %3
  6144 00002006 [D315]              <2>  dw %2
  6145                              <1> 		keyword f2,        pc_fkey,     FKeyName+(1<<FILENAME_MAX_LG2)
  6146 00002008 F20C0000            <2>  dd hash_%1
  6147 0000200C 1054                <2>  dw %3
  6148 0000200E [D315]              <2>  dw %2
  6149                              <1> 		keyword f3,        pc_fkey,     FKeyName+(2<<FILENAME_MAX_LG2)
  6150 00002010 F30C0000            <2>  dd hash_%1
  6151 00002014 2054                <2>  dw %3
  6152 00002016 [D315]              <2>  dw %2
  6153                              <1> 		keyword f4,        pc_fkey,     FKeyName+(3<<FILENAME_MAX_LG2)
  6154 00002018 F40C0000            <2>  dd hash_%1
  6155 0000201C 3054                <2>  dw %3
  6156 0000201E [D315]              <2>  dw %2
  6157                              <1> 		keyword f5,        pc_fkey,     FKeyName+(4<<FILENAME_MAX_LG2)
  6158 00002020 F50C0000            <2>  dd hash_%1
  6159 00002024 4054                <2>  dw %3
  6160 00002026 [D315]              <2>  dw %2
  6161                              <1> 		keyword f6,        pc_fkey,     FKeyName+(5<<FILENAME_MAX_LG2)
  6162 00002028 F60C0000            <2>  dd hash_%1
  6163 0000202C 5054                <2>  dw %3
  6164 0000202E [D315]              <2>  dw %2
  6165                              <1> 		keyword f7,        pc_fkey,     FKeyName+(6<<FILENAME_MAX_LG2)
  6166 00002030 F70C0000            <2>  dd hash_%1
  6167 00002034 6054                <2>  dw %3
  6168 00002036 [D315]              <2>  dw %2
  6169                              <1> 		keyword f8,        pc_fkey,     FKeyName+(7<<FILENAME_MAX_LG2)
  6170 00002038 F80C0000            <2>  dd hash_%1
  6171 0000203C 7054                <2>  dw %3
  6172 0000203E [D315]              <2>  dw %2
  6173                              <1> 		keyword f9,        pc_fkey,     FKeyName+(8<<FILENAME_MAX_LG2)
  6174 00002040 F90C0000            <2>  dd hash_%1
  6175 00002044 8054                <2>  dw %3
  6176 00002046 [D315]              <2>  dw %2
  6177                              <1> 		keyword f10,       pc_fkey,     FKeyName+(9<<FILENAME_MAX_LG2)
  6178 00002048 109E0100            <2>  dd hash_%1
  6179 0000204C 9054                <2>  dw %3
  6180 0000204E [D315]              <2>  dw %2
  6181                              <1> 		keyword f0,        pc_fkey,     FKeyName+(9<<FILENAME_MAX_LG2)
  6182 00002050 F00C0000            <2>  dd hash_%1
  6183 00002054 9054                <2>  dw %3
  6184 00002056 [D315]              <2>  dw %2
  6185                              <1> %if IS_PXELINUX
  6186                              <1> 		keyword ipappend,  pc_ipappend
  6187                              <1> %endif
  6188                              <1> %if IS_PXELINUX || IS_ISOLINUX
  6189                              <1> 		keyword localboot, pc_localboot
  6190                              <1> %endif
  6191                              <1> 
  6192                              <1> keywd_count	equ ($-keywd_table)/keywd_size
  6193                              <1> 
  6194                                  
  6195                                  ;
  6196                                  ; Extensions to search for (in *forward* order).
  6197                                  ;
  6198 00002058 43425400                exten_table:	db 'CBT',0		; COMBOOT (specific)
  6199 0000205C 42535300                		db 'BSS',0		; Boot Sector (add superblock)
  6200 00002060 42532000                		db 'BS ',0		; Boot Sector 
  6201 00002064 434F4D00                		db 'COM',0		; COMBOOT (same as DOS)
  6202                                  exten_table_end:
  6203 00002068 0000000000000000        		dd 0, 0			; Need 8 null bytes here
  6204                                  
  6205                                  ;
  6206                                  ; Misc initialized (data) variables
  6207                                  ;
  6208                                  %ifdef debug				; This code for debugging only
  6209                                  debug_magic	dw 0D00Dh		; Debug code sentinel
  6210                                  %endif
  6211 00002070 0000                    AppendLen       dw 0                    ; Bytes in append= command
  6212 00002072 0000                    KbdTimeOut      dw 0                    ; Keyboard timeout (if any)
  6213 00002074 0090                    CmdLinePtr	dw cmd_line_here	; Command line advancing pointer
  6214                                  initrd_flag	equ $
  6215 00002076 0000                    initrd_ptr	dw 0			; Initial ramdisk pointer/flag
  6216 00002078 0000                    VKernelCtr	dw 0			; Number of registered vkernels
  6217 0000207A 0000                    ForcePrompt	dw 0			; Force prompt
  6218 0000207C 0100                    AllowImplicit   dw 1                    ; Allow implicit kernels
  6219 0000207E 0000                    SerialPort	dw 0			; Serial port base (or 0 for no serial port)
  6220 00002080 1000                    VGAFontSize	dw 16			; Defaults to 16 byte font
  6221 00002082 00                      UserFont	db 0			; Using a user-specified font
  6222 00002083 07                      ScrollAttribute	db 07h			; White on black (for text mode)
  6223                                  ;
  6224                                  ; Stuff for the command line; we do some trickery here with equ to avoid
  6225                                  ; tons of zeros appended to our file and wasting space
  6226                                  ;
  6227 00002084 6C696E757820617574-     linuxauto_cmd	db 'linux auto',0
  6228 0000208D 6F00               
  6229                                  linuxauto_len   equ $-linuxauto_cmd
  6230 0000208F 424F4F545F494D4147-     boot_image      db 'BOOT_IMAGE='
  6231 00002098 453D               
  6232                                  boot_image_len  equ $-boot_image
  6233 0000209A 00<rept>                                align 4, db 0		; For the good of REP MOVSD
  6234                                  command_line	equ $
  6235                                  default_cmd	equ $+(max_cmd_len+2)
  6236                                  ldlinux_end	equ default_cmd+(max_cmd_len+1)
  6237                                  kern_cmd_len    equ ldlinux_end-command_line
  6238                                  ldlinux_len	equ ldlinux_end-ldlinux_magic
  6239                                  ;
  6240                                  ; Put the getcbuf right after the code, aligned on a sector boundary
  6241                                  ;
  6242                                  end_of_code	equ (ldlinux_end-bootsec)+7C00h
  6243                                  getcbuf		equ (end_of_code + 511) & 0FE00h
  6244                                  
  6245                                  ; VGA font buffer at the end of memory (so loading a font works even
  6246                                  ; in graphics mode.)
  6247                                  vgafontbuf	equ 0E000h
  6248                                  
  6249                                  ; This is a compile-time assert that we didn't run out of space
  6250                                  %ifndef DEPEND
  6251                                  %if (getcbuf+trackbufsize) > vgafontbuf
  6252                                  %error "Out of memory, better reorganize something..."
  6253                                  %endif
  6254                                  %endif
