2 /* second.S - LILO second stage boot loader */
3 Copyright 1992-1998 Werner Almesberger.
4 Copyright 1999-2006 John Coffman.
7 Licensed under the terms contained in the file 'COPYING' in the
14 /*#define DELL_DIRTY_HACK*/
22 get common.s /* as86 "include" will bypass the CPP */
28 #define KEYTABLE Keytable
29 #define PARMLINE Parmline
31 #define DEBUG_INITRD 0
43 #endif /* VERSION_MINOR */
46 /* The following is set to 1 to enable map file writing */
49 # if VERSION_MINOR>=90
58 #if DEBUG_NEW==0 && !(WR_ENABLE&1)
59 #error "Retail version should have WR_ENABLE=1"
62 /* if compiling READONLY, then WR_ENABLE should never be used */
69 #define CHECK_FS_VERBOSE 0
70 #define BEG_FS call fs_check
77 #define BEG_FS db 0x1e,0x2e,0x8e,0x1e,0x02,0x00
85 /* get rid of the following to revert to old int 0x15/fn 0x88 mem scheme */
86 #define HIGHMEM_MAX 0x38000000
88 LOADSEG = SYSSEG ; max kernel = 1024 sectors
90 #define UI_MAGIC 0xff /* take input from keyboard */
93 STAGE_MENU = STAGE_FLAG_MENU
100 STAGE_BITMAP = STAGE_FLAG_BMP4
109 STAGE_SERIAL = STAGE_FLAG_SERIAL
124 #if NO_FS || DEBUG_NEW
127 # define CHECK_FS call fs_check
138 ! Boot device parameters. They are set by the installer.
141 version: .word VERSION
144 stage: .word STAGE_SECOND|STAGE_SERIAL|STAGE_MENU|STAGE_BITMAP
146 port: .byte 0 ; COM port (0 = unused, 1 = COM1, etc.)
147 sparam: .byte 0 ; serial port parameters (0 = unused)
149 timout: .word 0 ; input timeout
150 delay: .word 0 ; boot delay
151 ms_len: .word 0 ; initial greeting message
154 kt_cx: .word 0 ; keyboard translation table
158 flag2: .byte 0 ; second stage specific flags
161 ! GDT for "high" loading
165 gdt: ; space for BIOS
168 .word 0xffff ; no limits
170 .word LOADSEG>>4 ; start: 0x10000
171 .byte 0x93 ; permissions
172 .word 0 ; padding for 80286 mode :-(
174 .word 0xffff ; no limits
175 .word 0 ; start - filled in by user
177 .byte 0x93 ; permissions
178 .word 0 ; padding for 80286 mode :-(
182 start: cld ; only CLD in the code; there is no STD
185 pop fs ; address parameters from here
187 #if NO_FS || DEBUG_NEW
189 mov firstseg,ds ; save DS here
193 mov [init_dx],dx ; save DX passed in from first.S
195 int 0x12 ; get memory available
198 sub ax,#EBDA_EXTRA ; allocate extra EBDA
200 shl ax,#6 ; convert to paragraphs
202 mov es,ax ; destination address
208 mov cx,#max_secondary/2 ; count of words to move
211 add di,#BSSstart-max_secondary
217 retf ; branch to continue address
220 #ifdef DELL_DIRTY_HACK
221 ;;; push dx ; preserve DX (already saved)
222 mov ax,#0x1200 ; enable video (VGA)
223 mov bl,#0x36 ; (probably a nop on EGA or MDA)
224 int 0x10 ; video call
226 ;;; pop dx ; restore DX on Dell geforce nVidia card
231 call serial_setup ; set up the COM port, if any
235 mov cx,#32 ; drain type-ahead buffer ?
236 drkbd: mov ah,#1 ; is a key pressed ?
238 jz comcom ; no -> done
239 xor ah,ah ; get the key
246 mov al,#0x4c ; display an 'L'
248 push #0 ; get pointer to disk parameter table in DS:SI
250 lds si,[0x78] ; 0x78 = 4*0x1E
252 cmp byte ptr (si+4),#9 ; okay ?
253 ja dskok ; yes -> do not patch
255 push cs ; get pointer to new area in ES:DI
258 mov cx,#6 ; copy 12 bytes
261 seg es ; patch number of sectors
263 mov byte ptr (di-8),#18
265 mov byte ptr (di-8),#LCF_XL_SECS
275 seg cs ; clear the break flag
276 mov byte ptr break,#0
278 call instto ; get timer interrupt
280 ;;; jmp restrt ; get going
282 ! Restart here after a boot error
284 restrt: mov bx,cs ; adjust segment registers
288 sub bx,#MAX_SETUPSECS*0x20+0x20 ; segment for setup code &
293 mov bx,cx ; BX is the smaller segment #
295 mov word ptr [map],#MAP
296 mov [initseg],bx ; set up INITSEG (was 0x9000)
298 mov [setupseg],cx ; set up SETUPSEG (was 0x9020)
300 sub cx,bx ; subtract [initseg]
301 shl cx,#4 ; get stack size
302 mov ss,bx ; must lock with move to SP below
303 mov sp,cx ; data on the stack)
329 SEG_FS ; external parameters ?
330 mov ax,[EX_OFF+6] ; DH:DL as passed to first.S
334 mov ax,[init_dx] ; DX into second Stage
337 #ifdef LCF_NOKEYBOARD
351 .ascii "Registers at startup of first stage loader:\n"
352 .ascii " AX BX CX DX SI DI BP DS ES\n"
358 SEG_FS ; external parameters ?
359 mov ax,[EX_OFF-2-4] ; AX
361 SEG_FS ; external parameters ?
362 mov ax,[EX_OFF-8-4] ; BX
364 SEG_FS ; external parameters ?
365 mov ax,[EX_OFF-4-4] ; CX
367 SEG_FS ; external parameters ?
368 mov ax,[EX_OFF-6-4] ; DX
370 SEG_FS ; external parameters ?
371 mov ax,[EX_OFF-14-4] ; SI
373 SEG_FS ; external parameters ?
374 mov ax,[EX_OFF-16-4] ; DI
376 SEG_FS ; external parameters ?
377 mov ax,[EX_OFF-12-4] ; BP
379 SEG_FS ; external parameters ?
380 mov ax,[EX_OFF-18+16] ; DS
382 SEG_FS ; external parameters ?
383 mov ax,[EX_OFF-20+16] ; ES
392 cmp dword [sig],#EX_MAG_HL ; "LILO"
394 cmp dword [mcmdbeg+6],#0x4547414d ; "MAGE" from BOOT_IMAGE
396 cmp BYTE [stage],#STAGE_SECOND
399 cmp WORD [version],#VERSION
401 crshbrn2: jne crshbrn
402 mov [cmdbeg],#acmdbeg ; probably unattended boot
404 mov di,#devmap ; place to store the device map
406 mov ah,[init_dx] ; AH is physical device
409 mov al,[par1_secondary+0+SSDIFF] ; map device logical
412 mov ax,[init_dx] ; AH is flags & device, AL is physical device
414 and ax,#DEV_MASK_asm<<8 | DEV_MASK_asm ; mask to pure device codes
420 call wout ; TT entry, maybe
424 stosw ; set up the translation from map -> boot
432 mov eax,[par1_mapstamp]
434 cmp eax,[par2_mapstamp]
437 call kt_read ; read the KEYTABLE
442 mov si,#KEYTABLE+256+mt_descr
450 jc near fdnok ; error -> retry
451 add bh,#2 ; increment address
452 cmp si,#KEYTABLE+256+mt_descr+sa_size*MAX_DESCR_SECS_asm
455 mov si,#DESCR ; compute a checksum of the descriptor table
456 mov di,#SECTOR_SIZE*MAX_DESCR_SECS-4
458 push dword #CRC_POLY1
476 mov bx,#msg_sigerr ; signature not found
478 zzz: hlt ; wait for interrupt
479 jmp zzz ; sit here forever
490 .ascii "Descriptor checksum okay\n"
495 ; remove those items that have "vmdisable", if virtual boot
498 mov di,#DESCR0 ; point at first descriptor
500 test byte ptr [id_name](di),#0xFF ; test for NUL name
502 test word ptr [id_flags](di),#FLAG_VMDISABLE
511 test byte ptr [id_name](di),#0xFF
523 #ifdef LCF_NOKEYBOARD
524 ; remove those items that have "nokbdisable", if nokeyboard boot
527 mov di,#DESCR0 ; point at first descriptor
529 test byte ptr [id_name](di),#0xFF ; test for NUL name
531 test word ptr [id_flags](di),#FLAG_NOKBDISABLE
540 test byte ptr [id_name](di),#0xFF
553 #if defined(MENU) || defined(BITMAP)
554 xor bx,bx ; defaults are all zero
555 mov [dimage],bx ; set default image to boot
556 mov [abs_cx],bx ; upper left of scroll area
557 ; means screen is not cleared
563 SEG_FS ; get possible FLAG_NOBD
564 or byte ptr [par1_prompt+SSDIFF],al
572 mov cx,mt_dflcmd+KEYTABLE+256 ;DFCMD_OFF
574 mov dx,mt_dflcmd+2+KEYTABLE+256
576 mov al,mt_dflcmd+4+KEYTABLE+256
579 jc fdnok ; error -> retry
581 cmp word ptr (bx),#DC_MAGIC ; okay ?
582 jne bdcmag ; no -> do not write
584 mov word ptr (bx),#DC_MGOFF ; erase the magic number
585 call cmd_write ; write out the command line
587 ; 22.6.2 -- removed, because this is worse that the first
599 bdcmag: mov byte ptr (bx+2),#0 ; disable the command line
603 xor ax,ax ; reset FDC
609 ! List all known boot images
611 list: mov byte ptr (bx),#0 ; set EOL marker
614 inc word [suppress] ; suppress console output
616 mov si,#DESCR0 ; list all images
618 xor dl,dl ; DL counts the images
619 lloop: testb (si),#0xff ; done ?
621 mov bx,si ; display the name
623 add si,#MAX_IMAGE_NAME+4
624 inc dl ; count the image
625 test dl,#3 ; inside line -> go on
628 jmp imgdne ; next image
629 fill: push bx ; fill with spaces
636 imgdne: add si,#id_size-MAX_IMAGE_NAME-4
637 loop lloop ; next image
638 ldone: test dl,#3 ; already at BOL ?
639 jz atbol ; yes -> no CRLF
647 ! Ready to process user input
649 dokay: mov bx,#ospc ; display 'O '
651 /* ifdef HIGHMEM_MAX */
653 mov dword ptr [hma],eax
655 mov ospc,al ; disable the message
656 mov word ptr vgaovr,#VGA_NOCOVR ; disable VGA override
659 xchg ax,par2_delay ;DSC_OFF-8+SSDIFF
661 or old_del,ax ; remember delay
662 mov nodfl,#iloop ; interactive prompt if falling through
663 #ifdef LCF_NOKEYBOARD
664 call kbtest ; keyboard present?
667 ; no PC keyboard on the system, is there a serial port in use?
668 cmp byte ptr [par2_port],#0
669 jz skip_prompt ; no serial keyboard either
671 jnc skip_prompt ; skip check for prompt if no keyboard
676 SEG_FS ; enter boot prompt ?
677 test byte ptr par1_prompt+SSDIFF,#FLAG_PROMPT ;DSC_OFF+15+SSDIFF,#0
679 jnz extp ; yes -> check for external parameters
681 mov nodfl,#bfirst ; boot first image if falling through
682 call waitsh ; wait for a shifting key
683 jc iloop ; key pressed -> enter interactive mode
685 ! Check for external parameters
688 SEG_FS ; external parameters ?
689 cmp byte ptr EX_OFF+6,#EX_DL_MAG
691 jne noex ; no -> go on
694 mov bl,EX_OFF+7 ; get drive
696 mov byte ptr EX_OFF+6,bl ; clear flag
697 SEG_FS ; load the signature pointer
701 cmp dword ptr (bx),#EX_MAG_HL ; "LILO"
702 jne noex ; no -> go on
705 mov si,EX_OFF+4 ; pointer to the command line
708 cmp byte ptr (si),#0 ; empty ?
709 je iloop ; yes -> enter interactive mode
710 jmp niloop ; enter non-interactive mode
712 ! No external parameters after timeout -> boot first image
714 noex: push cs ; restore ES
716 mov si,#DFLCMD+2 ; default command line ?
718 jne niloop ; yes -> use it
719 mov ax,nodfl ; no idea how to tell as86 to do jmp (addr) :-(
720 jmp ax ; fall through
723 ; Command input processor
726 #if defined(MENU) || defined(BITMAP)
732 ;; SEG_FS ; message disabled ?
733 cmp word ptr par2_msg_len,#0 ;MSG_OFF+SSDIFF,#0
735 je nomsg ; yes -> skip this
738 ;SEG_FS ; load the message file
739 mov cx,mt_msg+KEYTABLE+256 ;MSG_OFF+SSDIFF+2
741 mov dx,mt_msg+2+KEYTABLE+256
743 mov al,mt_msg+4+KEYTABLE+256
749 xor bx,bx ; set the terminating NUL and disable further
751 xchg bx,par2_msg_len ;MSG_OFF+SSDIFF
756 xor bx,bx ; display the message
759 push cs ; restore segment registers
763 nomsg: push cs ; disable external parameters
766 mov cmdbeg,#acmdbeg ; probably unattended boot
767 mov si,#usrinpm ; interactive mode
768 niloop: ; ES may point to external params
769 mov bx,#msg_p ; display boot prompt
771 mov bx,#cmdline ; move cursor to the end of the line
774 jz cledne ; yes -> go on
775 push bx ; display the character
780 cledne: mov byte ptr prechr,#32 ; character before command line is a space
784 input: seg es ; interactive mode ?
785 cmp byte ptr (si),#UI_MAGIC
786 je kbinp ; yes -> get keyboard input
787 seg es ; get non-interactive input
799 mov cx,#brto ; get a key
802 cmp byte [abs_cx+1],#0
803 je noNull ; skip cursor keys after Tab
805 #if defined(MENU) || defined(BITMAP)
806 cmp al,#0xE0 ; extended keyboard
809 toNull: je near null ; cursor control
812 noNull: or al,al ; keyboard NUL input?
813 je input ; yes, skip Keyboard NUL
814 ; stored command line NUL is handled differently
816 gotinp: cmp al,#9 ; TAB ?
817 je tolist ; yes -> list images
819 je tolist ; yes -> list images
821 je nul ; yes -> go on
823 je todelch ; yes -> erase one character
827 je todelch ; yes -> erase one character
828 ja input ; non-printable -> ignore it
830 je todell ; yes -> erase the line
832 je todell ; yes -> erase the line
833 cmp al,#32 ; ignore non-printable characters except space
835 ja noblnk ; no space -> go on
836 cmp (bx-1),al ; second space in a row ?
837 je input ; yes -> ignore it
838 noblnk: cmp bx,#cmdline+CL_LENGTH-1 ; at end of buffer ?
839 je input ; yes -> ignore
840 xor ah,ah ; cmdline is always NUL terminated
841 mov (bx),ax ; store in the buffer
842 inc bx ; increment pointer
845 #if defined(MENU) || defined(BITMAP)
847 call find_image ; we want the side effect of the hilite
851 cmp bx,#cmdline+1 ; first character ?
852 jne input ; no -> next input
853 #ifdef LCF_IGNORECASE
854 call upcase ; convert to upper case
856 mov cx,#IMAGES ; check if we have a single-key entry
859 sklp: test word ptr (di+id_flags),#FLAG_SINGLE ; single-key entry ?
860 jz sknext ; no -> try next
861 mov al,(di) ; get first character
862 #ifdef LCF_IGNORECASE
863 call upcase ; convert to upper case
865 cmp al,ah ; do we have a match ?
866 jne sknext ; no -> try next
867 cmp byte ptr (di+1),#0 ; at end ?
868 je cr ; yes -> run it
869 sknext: add di,#id_size ; test next entry
871 br input ; done -> get more input
873 todelch:br delch ; ...
874 todell: br delline ; ...
876 ! End of input, process the command line
878 nul: push bx ; automatic boot - wait for timeout
882 jnc crnul ; no key pressed -> continue
883 mov bx,#msg_int ; interrupted -> display a message
885 mov byte ptr cmdline,#0 ; clear the command line
886 br iloop ; return to interactive prompt
889 ;;22.7 mov word par2_timeout,#0xffff ; kill timeout
891 push ax ; HP TTRC boot fail workaround.
892 mov ax, #3 ; 2000/10 <yumoto@jpn.hp.com>
893 call setto ; reload timer
895 test byte ptr timeout,#1 ; timed out ?
896 jz short_wait ; No, remain loop..
899 mov cmdbeg,#mcmdbeg ; probably manual boot
902 mov byte ptr break,#0 ; clear the break flag
904 push cs ; set ES to CS
908 mov si,#cmdline ; copy command line to save buffer
910 mov byte ptr dolock,#0 ; disable locking
912 cpsav: lodsb ; copy one byte
915 jnz cpsav ; no -> go on
917 cmp bx,#cmdline ; empty line ?
918 je notrspc ; yes -> boot first image
919 cmp byte ptr (bx-1),#32 ; trailing space ?
920 jne notrspc ; no -> go on
921 dec bx ; remove the space
923 notrspc:mov si,#cmdline ; scan the command line for "vga=", "kbd=",
924 mov di,si ; "lock" or "mem="
929 cmp dword ptr (si),#0x64626f6e ; "nobd"
931 cmp byte (si+4),#32 ; terminated with SP or NUL?
934 SEG_FS ; enter boot prompt ?
935 or byte ptr par1_prompt+SSDIFF,#FLAG_NOBD ; suppress BIOS data collection
937 jmp vskwd ; skip word
940 cmp dword ptr (si),#0x3d616776 ; "vga="
942 call setvga ; set VGA mode
943 jc near iloop ; error -> get next command
944 jmp vskdb ; proceed by discarding last blank
946 cmp dword ptr (si),#0x3d64626b ; "kbd="
948 call putkbd ; pre-load keyboard buffer
949 jmp vskdb ; proceed by discarding last blank
951 cmp dword ptr (si),#0x6b636f6c ; "lock"
953 cmp byte (si+4),#32 ; space?
955 mov byte ptr dolock,#1 ; enable locking
956 vskwd: add si,#4 ; skip word
957 vskdb: dec di ; discard last blank
961 cmp dword ptr (si),#0x3d647269 ; "ird="
963 cmp dword ptr (si),#0x3d6d656d ; "mem="
966 call getmem ; get the user-provided memory limit
968 lodsb ; copy one byte
971 je chkvga ; yes -> look for options again
973 jnz vsknb ; no -> go on
974 call crlf ; write CR/LF
975 cmp di,#cmdline+1 ; empty line ?
976 emptyl: je bfirst ; yes -> boot first image
977 jmp bcmd ; boot the specified image
979 ! Find the boot image and start it
983 jc near boot ; eureka, it was found
985 mov bx,#msg_nf ; not found -> display a message
987 br iloop ; get more input
989 ! Delete one character
991 delch: cmp bx,#cmdline ; at the beginning ?
992 je toinput ; yes -> do nothing
993 dec bx ; move the pointer
994 push bx ; display[B BS,SPC,BS
997 #if defined(MENU) || defined(BITMAP)
1000 mov byte (bx),#0 ; NUL terminate the line
1008 #if defined(LCF_VIRTUAL) || defined(LCF_NOKEYBOARD)
1021 toinput:br input ; go on
1023 ! Delete the entire line
1026 #if !defined(MENU) && !defined(BITMAP)
1027 cmp bx,#cmdline ; done ?
1028 je toinput ; yes -> go on
1029 push bx ; display BS,SPC,BS
1033 dec bx ; move the pointer
1034 jmp delline ; next one
1037 push bx ; delch will do a pop
1042 ! Boot first after timeout
1044 brto: call crlf ; display a CRLF
1047 ! Boot the first image
1049 bfirst: mov byte ptr lkcbuf,#0 ; clear default
1050 cmp byte ptr cmdline,#0 ; is there a default ?
1051 jne bcmd ; yes -> boot that image
1053 mov bx,#DESCR0 ; boot the first image
1055 #if defined(LCF_VIRTUAL) && defined(LCF_NOKEYBOARD)
1056 xor ax,ax ; mask = 0
1058 jnc brfrst0v ; not virtual
1059 mov ax,#FLAG_VMDEFAULT
1063 mov ax,#FLAG_NOKBDEFAULT
1067 brfrst1: test word ptr (bx+id_flags),ax
1072 mov bx,#DESCR0 ; restore default
1077 jnc brfrst3 ; not virtual, boot BX
1080 brfrst1: test word ptr (bx+id_flags),#FLAG_VMDEFAULT
1085 mov bx,#DESCR0 ; restore default
1087 #endif /* LCF_VIRTUAL */
1088 #ifdef LCF_NOKEYBOARD
1090 jc brfrst3k ; not virtual, boot BX
1093 brfrst1k: test word ptr (bx+id_flags),#FLAG_NOKBDEFAULT
1098 mov bx,#DESCR0 ; restore default
1100 #endif /* LCF_NOKEYBOARD */
1102 #endif /* if !both */
1104 mov si,bx ; copy the name to the command line
1106 bfcpl: lodsb ; copy one character
1110 jnz bfcpl ; no -> next one
1112 ! Boot the image BX points to (with password check)
1115 mov word par2_timeout,#0xffff ; kill timeout (22.7)
1116 mov si,#cmdline ; locate start of options
1119 je optfnd ; yes -> no options
1120 cmp al,#32 ; space ?
1121 jne locopt ; no -> continue searching
1122 cmp byte ptr (si),#0 ; followed by NUL ?
1123 jne optfnd ; no -> go on
1124 mov byte ptr (si-1),#0 ; discard trailing space
1125 optfnd: dec si ; adjust pointer
1126 mov options,si ; store pointer for later use
1129 test word ptr [id_flags](bx),#FLAG_RETAIN ; keep bitmap?
1131 xor ax,ax ; time out immediately
1132 call waitsh ; check for break (Shift, Alt, ScrollLock,...)
1141 test word ptr [id_flags](bx),#FLAG_VMWARN
1143 call vmtest ; 'vmwarn' there, is it actually virt. boot
1145 ; VMWARN set, and is virtual boot, so issue comment
1148 mov word ptr par2_timeout,#0xffff ; cancel timeout
1151 push bx ; save image descriptor ptr
1154 mov cx,#vmwto ; timeout exit
1158 cmp al,#0x20 ; compare to Space
1159 jb boot3 ; no echo if ctrl char
1164 pop bx ; restore image descriptor ptr
1165 cmp al,#0x79 ; y is yes
1167 cmp al,#0x59 ; Y is yes
1175 test byte ptr (bx+id_flags),#FLAG_PASSWORD ; use a password
1176 jz toboot ; no -> boot
1177 test byte ptr (bx+id_flags),#FLAG_RESTR ; restricted ?
1178 jz dopw ; no -> get the password
1179 cmp byte ptr (si),#0 ; are there any options ?
1180 jne dopw ; yes -> password required
1181 toboot: br doboot ; ...
1183 #if defined(CRC_PASSWORDS) || defined(SHS_PASSWORDS)
1184 push bx ; save the image descriptor
1187 mov word ptr par2_timeout,#0xffff ; cancel timeout
1189 mov bx,#msg_pw ; display a prompt
1193 mov bp,sp ; save SP in BP
1194 sub sp,#CL_LENGTH ; allocate space for PW string
1195 mov si,sp ; si points at string
1196 xor di,di ; di counts characters
1209 mov cx,#pwtime ; get timeout exit
1213 je pwcr ; yes -> handle it
1215 je pwdell ; yes -> erase line
1219 je pwdelch ; yes -> erase one character
1222 ja pwloop ; ignore other non-printable characters
1226 cmp di,#CL_LENGTH ; check for buffer overflow
1227 jae pwloop ; ingnore further input
1229 mov (si),al ; store char in buffer
1232 mov al,#42 ; echo '*'
1234 jmp pwloop ; loop back for more
1255 xor cx,cx ; signal okay
1256 pwtime: ; CX != 0 if enter here
1260 sub si,di ; point SI at start of buffer
1263 #if !defined(SHS_PASSWORDS)
1264 mov bx,(bp+2) ; restore image descriptor pointer
1266 pop es ; ES:SI points at char string
1269 push dword #CRC_POLY1
1286 cmp eax,(bx+id_password_crc)
1290 ; insert other checks in here
1292 push dword #CRC_POLY2
1294 cmp eax,(bx+id_password_crc+4)
1299 push dword #CRC_POLY3
1301 cmp eax,(bx+id_password_crc+8)
1306 push dword #CRC_POLY4
1308 cmp eax,(bx+id_password_crc+12)
1313 push dword #CRC_POLY5
1315 cmp eax,(bx+id_password_crc+16)
1318 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1319 dec cx ; signal all okay
1320 #else /* SHS_PASSWORDS */
1322 ; SS:SI is the password string
1328 mov bx,(bp+2) ; restore image descriptor pointer
1329 lea di,(bx+id_password_crc)
1331 mov cx,#MAX_PW_CRC*4
1336 pop si ; restore buffer ptr
1337 pop di ; clear stack
1341 je pwcleanup ; CX will be 0
1343 #endif /* !defined(SHS_PASSWORDS) */
1350 rep ; wipe out password in memory
1353 pop es ; restore the saved ES
1358 or cx,cx ; test CX==0 means all okay
1363 push bx ; save the image descriptor
1364 lea si,(bx+MAX_IMAGE_NAME+1) ; get a pointer to the password string
1365 mov bx,#msg_pw ; display a prompt
1367 pwagain:xor cl,cl ; CL counts characters after a mismatch
1368 pwloop: push cx ; get a key
1373 je pwcr ; yes -> handle it
1375 je pwdell ; yes -> erase line
1379 je pwdelch ; yes -> erase one character
1382 ja pwloop ; ignore other non-printable characters
1385 or cl,cl ; counting bad input ?
1386 jnz pwbad ; yes -> do it
1387 cmp al,(si) ; correct input ?
1388 je pwgood ; yes -> go on
1389 pwbad: inc cl ; count error
1390 jnz pwgood ; no overflow -> go on
1392 jmp pwcr ; terminate input
1393 pwgood: inc si ; good character -> go on
1395 pwdell: pop si ; reset the pointer
1397 add si,#MAX_IMAGE_NAME+1
1398 jmp pwagain ; get password again
1399 pwdelch:pop bx ; at the beginning of the line ?
1401 add bx,#MAX_IMAGE_NAME+1
1403 je pwloop ; yes -> ignore it
1404 dec si ; remove one character
1406 jnc pwloop ; no underflow -> go on
1408 jmp pwloop ; next character
1409 pwtime: pop cx ; drop CX ...
1410 mov cl,#1 ; ... and fail
1412 pop bx ; restore the image descriptor
1413 or cl,cl ; no errors ?
1414 jnz pwfail ; no -> fail
1415 cmp byte ptr (si),#0 ; at end ?
1416 je doboot ; yes -> continue booting
1417 #endif /* CRC_PASSWORDS */
1419 pwfail: mov bx,#msg_pf ; display an error message
1421 br iloop ; get next input
1423 ! Boot the image BX points to
1425 doboot: mov byte ptr prechr,#61 ; switch to equal sign
1426 push bx ; save image descr
1427 mov bx,#msg_l ; say hi
1429 pop bx ; display the image name
1435 add si,#id_start ; form address
1437 ; Now load the kernel sectors
1439 mov word ptr (gdt+0x1b),ax ; set GDT to "load low"
1440 mov byte ptr (gdt+0x1f),al
1441 mov moff,ax ; map is not loaded yet
1443 lodsw ; address of the first map sector
1457 mov bx,[map] ; load the first map sector
1463 mov bx,#DFLCMD ; load the default command line
1466 mov cx,mt_dflcmd+KEYTABLE+256
1468 mov dx,mt_dflcmd+2+KEYTABLE+256
1470 mov al,mt_dflcmd+4+KEYTABLE+256
1473 push word ptr (DFLCMD) ; push magic number
1474 mov bx,#DFLCMD ; load the fallback sector
1476 pop ax ; valid magic number ?
1477 #ifndef LCF_READONLY
1479 je dclok ; yes -> can write
1481 jne nofbck ; invalid -> must not write
1482 dclok: mov bx,#DFLCMD ; fallback data present ?
1483 cmp word ptr (bx),#DC_MAGIC
1484 jne nofbck ; no -> go on
1485 call cmd_write ; write out the command line
1492 mov bx,#DFLCMD ; load the options sector
1494 mov si,cmdbeg ; copy non-options part of command line
1496 mov cx,#CL_LENGTH-1 ; max number of characters to copy
1502 cmp si,options ; at beginning of options ?
1504 je cpnodn ; yes -> go on
1505 movsb ; copy one byte
1506 loop cpnocl ; next one
1507 jmp cpovfl ; signal overflow
1511 pop ax ; get saved pointer
1512 pop si ; get saved descriptor
1524 mov si,#DFLCMD ; constant options ?
1525 cmp byte ptr (si),#0
1526 je nocopt ; no -> go on
1527 mov al,#32 ; add a space
1529 dec cx ; count character
1533 cmp dword ptr (si),#0x3d647269 ; "ird="
1535 cmp dword ptr (si),#0x3d6d656d ; "mem="
1538 call getmem ; get the user-provided memory limit
1540 lodsb ; fetch next byte
1541 cmp al,#32 ; space ?
1542 je cpcodsp ; yes -> discard it
1543 cpcolp: or al,al ; NUL ?
1544 jz cpcodn ; yes -> done
1546 dec cx ; count character
1548 cmp al,#32 ; a space ?
1549 je cpcodsp ; yes -> discard next
1550 lodsb ; get next byte
1554 cmp byte ptr (di-1),#32 ; last was space ?
1555 jne nocopt ; no -> go on
1558 nocopt: mov si,options ; append variable options
1559 cpvalp: lodsb ; copy one byte
1563 loop cpvalp ; count and loop back
1564 cpovfl: mov (di),cl ; CX is zero
1566 dec cx ; count 1 more character
1573 mov bx,#msg_pl ; parameter line message
1586 mov es,[initseg] ; load the original boot sector
1587 xor bx,bx ; load now
1590 lodsw ; get flags bit map
1591 xchg bx,ax ; move to BX
1592 lodsw ; copy parameters ... VGA mode ... (done)
1593 cmp word ptr vgaovr,#VGA_NOCOVR ; VGA mode not overridden on
1595 je vganorm ; no -> go on
1596 mov ax,vgaovr ; use that value
1598 vganorm:test bx,#FLAG_VGA
1601 mov [VGA_SET],ax ; magic offset in the boot sector
1602 novga: push bx ; use flags (BX) later
1603 test bx,#FLAG_LOCK ; ... lock target ?
1604 jnz lockit ; yup -> do it
1605 cmp byte ptr dolock,#0 ; did user ask to lock new target ?
1606 je nolock ; no -> go on
1608 #ifndef LCF_READONLY
1609 mov bx,#lkwbuf ; save the command line
1610 mov word (bx),#DC_MAGIC ;
1616 call cmd_write ; write out the command line
1631 mov cl,#SETUPSECS ; default is to load four sectors
1633 mov es,[setupseg] ; load the setup codes
1636 mov ax,cx ; number of sectors to AX
1637 shl ax,#5 ; convert to paragraphs (9-4)
1640 add bx,#STACK>>4 ; allow for stack space in paragraphs
1644 mov bx,#msg_mem ; we are very short on memory
1650 xor bx,bx ; other operating system)
1660 test bx,#FLAG_MODKRN ; "modern" kernel ?
1661 jz loadlow ; no -> avoid all patching and such
1662 seg es ; set loader version
1663 mov byte ptr (16),#LOADER_VERSION
1665 test bx,#FLAG_LOADHI ; load kernel high
1669 mov ax,word ptr (20+1) ; get start address 00 1000 00
1672 mov al,byte ptr (20+3) ; get hi-byte of address
1676 seg es ; version >= 1 ?
1677 cmp word ptr (6),#NEW_HDR_VERSION
1678 jbe noheap ; no -> do not patch heap
1680 sub ax,[initseg] ; find no. of paragraphs available
1682 add ax,#SLA_SIZE_DYN
1684 mov word ptr (36),ax
1685 seg es ; patch flags
1686 or byte ptr (17),#LFLAG_USE_HEAP
1688 pop si ; restore pointer to DESCR to load
1694 call load_initrd ; load the initrd & patch header
1702 or ax,bx ; load low ?
1704 je loadlow ; yes -> do it
1705 xor ax,ax ; GDT is already set up ...
1714 call lfile ; load the system ...
1715 jmp launch2 ; ... and run it
1723 call loadfile ; load the system
1729 push #SYSSEG ; load a file at SYSSEG:0000
1735 ! Load one sector. Issue an error at EOF.
1737 load1: call loadit ; load the sector
1738 mov bx,#msg_eof ; we only get here at EOF
1742 loadit: call load ; load it
1743 pop ax ; drop return address of load1
1746 ! Load one sector. Start the system at EOF.
1748 loadopt:call loadit ; load the sector
1751 ! Load one sequence of sectors. Leave outer function at EOF.
1753 load: push es ; save ES:BX
1755 lfetch: mov si,moff ; get map offset
1757 mov cx,(bx+si) ; get address
1761 jnz noteof ; no -> go on
1764 pop bx ; restore ES:BX
1766 pop ax ; pop return address
1767 ret ; return to outer function
1768 noteof: add si,#sa_size ; increment pointer
1770 cmp si,#SECTOR_SIZE - sa_size + 1 ; page end ?
1773 mov moff,#0 ; reset pointer
1777 mov bl,hinib ; this might get clobbered
1778 push bx ; so save it
1779 mov bx,[map] ; load map page
1781 pop ax ; restore the hi-nibble
1784 mov al,#0x2e ; print a dot
1786 jmp lfetch ; try again
1791 ; terminate emulation if CD boot
1792 test byte ptr [par2_flag2],#FLAG2_EL_TORITO ; a CD?
1794 mov si,#Map ; empty command packet
1795 mov byte ptr (si),#0x13 ; size of command packet
1796 mov ax,#0x4b00 ; terminate emulation
1797 ;;;; mov dl,al ; DL is 0
1798 mov dl,[init_dx] ; terminate boot device
1802 call menu_exit ; make the menu area vanish
1804 call crlf ; display a CRLF
1806 /* 'outb' was removed in 22.5.5; but the HW stop is required by some BIOSs */
1807 mov dx,#0x3f2 ; stop the floppy motor
1811 int 0x13 ; reset the FDC (AH=0)
1813 mov es,[initseg] ; adjust segment registers
1814 mov di,#PARMLINE ; set parameter line offset
1815 mov ax,cs ; find where we are loaded
1816 sub ax,[initseg] ; find no. of paragraphs available
1817 shl ax,4 ; convert para. to bytes
1820 cmp dword ptr CL_HEADER_ID,#0x53726448 ; "HdrS" (reversed)
1821 je chkver ; go check header version
1824 ! it must be the chain loader
1828 SEG_FS ; suppress BIOS data collection
1829 or byte ptr par1_prompt+SSDIFF,#FLAG_NOBD ; suppress BIOS data collection
1832 ; ES:DI will point at param line (chain.b)
1834 mov ds,[setupseg] ; point at chain loader(?) header
1835 ; DS points at chain loader
1836 cmp dword [parC_signature],#EX_MAG_HL ;
1838 cmp word [parC_stage],#STAGE_CHAIN
1840 cmp word [parC_version],#VERSION
1842 mov dx,[parC_drive] ; get drive
1843 ;;; call map_device ; map drive -- uses CS to address "devmap"
1844 mov [parC_drive],dl ; store mapped drive
1845 mov [parC_devmap],#devmap ; save our drive mapping
1846 mov [parC_devmap+2],cs ; our DS register
1851 mov dx,[EX_OFF+6] ; pass DX from first stage
1862 mov bh,[gdt+0x1f] ; check for kernel/initrd conflict
1864 mov bx,[gdt+0x1b] ; form kernel final load address
1866 mov eax,[rdbeg] ; initrd beg address (0 if none)
1879 mov ax,CL_HDRS_VERSION
1886 cmp word ptr CL_HDRS_VERSION,#NEW_VERSION ; check for
1887 ; new cmdline protocol
1890 ! and now the new protocol
1892 mov ax,es ; form long address
1893 movzx edx,ax ; zero extend segment part to EDX
1894 movzx edi,di ; zero extend offset
1895 shl edx,4 ; make segment into address
1896 add edx,edi ; form long absolute address
1898 mov CL_POINTER,edx ; and pass the address
1907 ! the old command line passing protocol
1911 mov CL_MAGIC_ADDR,#CL_MAGIC ; set magic number
1913 mov word ptr CL_OFFSET,di
1917 mov al,#0x3A ; issue colon
1937 start_setup: ; kernel boot comes here
1946 #ifdef LCF_NOKEYBOARD
1949 mov bx,#msg_no_keyboard
1958 SEG_FS ; suppress BIOS data collection?
1959 test byte ptr par1_prompt+SSDIFF,#FLAG_NOBD ; suppress?
1967 #ifndef LCF_READONLY
1968 or byte ptr [KEYTABLE+256+mt_flag],#FLAG_NOBD ; suppress
1977 mov ah,#2 ; get keyboard flags
1979 and al,#0x70 ; Caps, Num, Scroll Lock flags
1981 je near zzz ; fail with all 3 on
1986 mov dx,[EX_OFF+6] ; pass in DX from first stage
1990 call is_prev_mapper ; is there a previous mapper
1993 mov word (di),#0 ; sterilize it
1995 pop es ; and restore ES
2001 #ifndef LCF_READONLY
2002 ; if the BIOS data collection was successful, do not suppress it on future boots
2003 and byte ptr [KEYTABLE+256+mt_flag],#~FLAG_NOBD ; no suppress
2006 #endif /* ifdef LCF_BDATA */
2008 start_setup2: ; chain loader boot comes here
2010 call pause ; last chance to use the timer
2012 mov ax,#1500/55 ; about 1.5 second
2013 call setto ; set timeout
2014 vpaus1: test byte ptr timeout,#-1
2017 call remto ; free timer interrupt
2019 push es ; is initseg
2020 pop ds ; DS = 0x9000 (initseg)
2028 add sp,#SETUP_STACK_DYN ; increase stack size over this code
2029 if ~*&1 ; align to an odd memory location
2032 jmpi 0,SETUPSEG ; segment part is a variable
2033 setupseg = *-2 ; setupseg is filled in now
2034 initseg: .word INITSEG
2037 ! Load one sector (called from load)
2039 doload: pop bx ; restore ES:BX
2042 ! Load a sequence of sectors, possibly moving into "high memory" (> 1 MB)
2045 xread: push ax ; ES == 0 ?
2049 jz rdhigh ; yes -> read into high memory
2055 rdhigh: push bx ; okay - DS:BX points to GDT in this case
2056 mov bx,#LOADSEG ; adjust ES:BX
2059 call sread ; load the sector(s)
2061 pop bx ; get pointer to GDT
2062 push ax ; just in case ...
2065 mov si,bx ; turn ES:SI into pointer to GDT
2068 xor cx,cx ; number of words to move
2096 push bx ; do the transfer. (save BX, CX and SI because
2097 push cx ; we are paranoid)
2099 mov ah,#0x87 ; Move Extended Memory Block
2104 jc badmov ; failed ...
2105 pop ax ; check the GDT
2106 cmp ah,[gdt+0x1f] ; catch a BIOS that does not handle 386
2108 jne badmov+1 ; AH error code will be hi byte of address
2109 shr cx,#8-1 ; convert words to bytes/256
2110 sub ax,ax ; put ES back to 0
2113 mov es,ax ; put ES back to 0
2119 badmov: pop bx ; discard GDT
2120 push ax ; save the error code
2121 mov bx,#msg_bm ; tell the user ...
2122 jmp reset ; (standard procedure calls say & bout)
2124 ! Load a sequence of sectors
2126 sread: push bx ; save registers
2130 mov di,ax ; save AL return count
2131 jc rerror ; error -> complain
2132 pop dx ; restore registers
2135 shl ax,8 ; convert sectors to bytes
2137 jc dowrap ; loaded an entire segment -> advance ES
2139 jnc nowrap ; same segment -> go on
2140 dowrap: mov ax,es ; move ES
2144 mov ax,di ; restore the block count in AL
2147 ! Read error - try a second time and give up if that fails too
2151 mov bx,#msg_re ; say something
2153 pop ax ; display the error code
2157 mov moff,#0 ; restore initial state
2169 ! Convert character in AL to upper case
2171 upcase: cmp al,#0x61 ; lower case character ? ('a')
2172 jb nolower ; no -> go on
2175 sub al,#0x20 ; convert to upper case
2181 mov ax,#3200/55 ; delay 3+ seconds
2183 delay1: test byte ptr timeout,#-1
2188 mov ah,#0x86 ; delay in microseconds
2189 mov cx,#5<<4 ; 3 seconds; forget DX
2199 ! display a double word, pushed into the stack
2205 mov ax,(bp+6) ; get high order
2207 mov ax,(bp+4) ; get low order
2214 ! display a space, followed by a word in AX
2220 ; and fall into wout
2222 ! Display a hexadecimal word/byte/nibble
2228 ; must fall into bout
2231 bout: push ax ; save byte
2232 shr al,#4 ; display upper nibble
2235 nout: and al,#0x0F ; lower nible only
2236 daa ; smaller conversion routine
2238 adc al,#0x40 ; AL is hex char [0..9A..F]
2239 jmp display ; display it
2241 ! part of the 'say' routine
2242 ! actual entry point is below at 'say:'
2246 jne nonl ; no -> go on
2247 mov al,#13 ; display a CRLF
2252 jne nocls ; no -> go on
2254 call menu_form_feed ; simulate a FF
2257 cmp BYTE [abs_cx+1],#0 ; graphic screen on?
2261 mov ah,#0xf ; clear the local screen
2267 tosnext: jmp snext ; next character
2268 nocls: call display ; display, tty-style
2271 ! fall into say ; process next character
2273 ! Display a NUL-terminated string on the console
2275 say: mov al,(bx) ; get byte
2277 jnz say_loop ; not the end
2283 crlf: mov al,#13 ; CR
2289 ! Display one character on the console
2294 #ifndef LCF_NOSERIAL
2297 #if defined(MENU) || defined(BITMAP)
2299 cmp word [suppress],#0
2310 cmp byte [abs_cx+1],#0 ; is special scrolling in effect?
2311 je goshowit ; jump if no special handling
2312 call mn_getcursor ; get cursor pos. in DX
2314 cmp al,#8 ; is it BS
2316 or dl,dl ; at col. 0?
2318 ; must simulate a BS
2319 mov dl,[mn_max_row_col] ; move to EOL
2320 mov al,#0x0a ; change to LF
2321 dec dh ; back up first of two lines
2322 jmp scroll_set ; set new cursor pos. & ring BEL
2325 cmp al,#0x0a ; test for LF / NL
2327 cmp dh,[mn_max_row_col+1] ; bottom row
2330 cmp al,#0x20 ; printing char?
2332 cmp dx,[mn_max_row_col] ; bottom corner
2337 mov ax,#0x601 ; scroll up 1 line
2340 mov dx,[mn_max_row_col]
2341 int 0x10 ; do the scroll
2345 call mn_setcursor ; set cursor up 1 row
2353 ;;; xor bh,bh ; display on screen
2354 mov bx,#7 ; set color for TEXT interface
2363 #ifndef LCF_NOSERIAL
2364 serdisp:push dx ; wait for space in the send buffer
2372 test al,#0x10 ; break -> set break flag
2375 mov byte ptr break,#1
2376 nobrk: test al,#0x20 ; ready to send ?
2377 jz serwait ; no -> wait
2378 sub dx,#5 ; send the character
2381 serret: pop dx ; done
2385 ! Get a key (CX = timeout exit)
2388 ;; SEG_FS ; set the timeout
2389 mov ax,par2_timeout ;DSC_OFF-10+SSDIFF
2392 gwtkey: mov ah,#1 ; is a key pressed ?
2394 jnz gotkey ; yes -> get it
2395 #ifndef LCF_NOSERIAL
2396 mov dx,slbase ; using a serial port ?
2398 jz gnokey ; no -> wait
2399 add dx,#5 ; character ready ?
2402 jz gnokey ; no -> wait
2405 and al,#0x7f ; strip 8th bit
2406 jnz gotch ; ignore NULs
2409 #if defined(MENU) || defined(BITMAP)
2411 cmp byte [abs_cx+1],#0
2417 test byte ptr timeout,#1 ; timed out ?
2418 jz gwtkey ; no -> wait
2419 pop ax ; discard return address
2420 jmp cx ; jump to timeout handler
2421 gotkey: xor ah,ah ; read a key
2423 push bx ; keyboard translation (preserve BX)
2430 SEG_FS ; always enter prompt ?
2431 test byte ptr par1_prompt+SSDIFF,#FLAG_PROMPT
2433 jz noosht ; yes -> do not disable timeout
2436 test byte ptr par2_flag2,#FLAG2_UNATTENDED
2438 mov word ptr par2_timeout,#0xffff
2443 ! Shift wait loop (AX = timeout, returns CY set if interrupred)
2445 waitsh: call setto ; set timeout
2446 actlp: mov ah,#2 ; get shift keys
2448 #if defined(LCF_VIRTUAL) && DEBUG_NEW
2449 and al,#0x1f ; anything set ? (except NumLock or CapsLock)
2451 and al,#0x5f ; anything set ? (except NumLock)
2453 jnz shpress ; yes -> return with CY set
2455 mov ah,#1 ; get status
2457 jnz shpress ; key pressed
2459 #ifndef LCF_NOSERIAL
2460 mov dx,slbase ; using a serial port ?
2462 jz acnosp ; no -> go on
2463 cmp byte ptr break,#0 ; break received ?
2464 jnz shpress ; yes -> return with CY set
2465 add dx,#5 ; check for pending break
2468 jnz shpress ; break received -> return with CY set
2470 acnosp: test byte ptr timeout,#1 ; timed out ?
2471 jz actlp ; no -> wait
2474 shpress:stc ; set carry
2479 instto: push ds ; install the timeout handler
2484 mov eax,[0x1c*4] ; get the old vector
2486 mov [int1c_l],eax ; save H & L parts
2487 mov [0x1c*4],#tick ; install new vector
2493 remto: push es ; remove the interrupt handler
2497 mov eax,[int1c_l] ; restore the old vector
2499 mov [0x1c*4],eax ; **
2503 ! AX = ticks, 0xffff = no timeout
2505 setto: or ax,ax ; time out immediately ?
2506 jz toimmed ; yes -> do it
2507 cli ; set timeout value
2509 mov byte ptr timeout,#0 ; clear timed-out flag
2512 toimmed:mov byte ptr timeout,#0xff ; set the timed-out flag
2515 tick: pushf ; save flags
2516 seg cs ; no timeout ?
2517 cmp word ptr cntdown,#0xffff
2518 je notzro ; yes -> go on
2519 seg cs ; decrement counter
2520 dec word ptr cntdown
2521 jnz notzro ; not zero -> go on
2522 seg cs ; set timeout flag
2523 mov byte ptr timeout,#0xff
2526 push dword [int1c_l]
2527 iret ; continue with old interrupt
2531 ;; SEG_FS ; load the keyboard translation table
2532 mov cx,par2_keytab ;MSG_OFF+SSDIFF+7
2534 mov dx,par2_keytab+2 ;MSG_OFF+SSDIFF+9
2536 mov al,par2_keytab+4 ;MSG_OFF+SSDIFF+11
2541 #ifndef LCF_READONLY
2543 ! Sector write; used for the keytable only
2549 call kt_set ; set for KEYTABLE i/o
2552 SEG_FS ; BIOS data collection worked before?
2553 test byte ptr par1_prompt+SSDIFF,#FLAG_BD_OKAY
2557 test byte ptr [par2_flag2],#FLAG2_EL_TORITO ; a CD?
2565 ! Sector write; used for the stored command line only
2570 mov cx,mt_dflcmd+KEYTABLE+256
2572 mov dx,mt_dflcmd+2+KEYTABLE+256
2574 mov al,mt_dflcmd+4+KEYTABLE+256
2578 ; General sector write
2581 #ifdef FLAG_RAID_NOWRITE
2584 test byte ptr par1_prompt+SSDIFF,#FLAG_RAID_NOWRITE ; no writes?
2586 jnz cwok ; jump if no writing allowed
2590 test byte ptr par1_prompt+SSDIFF,#FLAG_RAID ; is it a RAID write
2594 mov byte ptr (dsk_wrflag),#WR_ENABLE ; flag write operation
2596 mov byte ptr (dsk_wrflag),#0 ; flag read operation
2598 jnc cwok ; no error - return
2601 cmp ah,#3 ; write protect error
2603 push ax ; save error code in AH
2607 mov al,ah ; error code
2609 call crlf ; leave space
2612 mov bx,#msg_wrerr3 ; write protect
2616 stc ; flag error JRC
2626 test dl,#RAID_REL_FLAG ; relocation called for?
2628 mov ah,#0x99 ; flag error
2632 mov si,[rmask] ; get raid physical device mask
2633 cwrm = LINEAR_FLAG|LBA32_FLAG|LBA32_NOCOUNT|RAID_REL_FLAG|0X80
2634 and dl,#cwrm ; save flags, set device to 80
2639 mov byte ptr (dsk_wrflag),#WR_ENABLE ; flag write operation
2640 call cread_physical ; read the PHYSICAL device #
2641 mov byte ptr (dsk_wrflag),#0 ; flag read operation
2645 or si,si ; clears the carry
2649 ;;; clc ; signal no error
2652 cwr_cnt: .byte 0 ; device code count
2653 cwr_flags: .byte 0 ; saved flags
2657 kt_read: ; KEYTABLE read
2658 call kt_set ; set for KEYTABLE i/o
2661 mov si,#KEYTABLE ; compute a checksum of the keytable
2662 mov di,#SECTOR_SIZE - 8 ; skip the last 4+4 bytes
2663 push dword #CRC_POLY1
2677 ! enter with AL, CX, DX, ES, BX set for read
2680 cread: ; entry point for mapped device r/w
2681 call map_device ; DL (logical) -> DL (physical)
2683 cread_physical: ; same entry, device is not mapped
2685 test dl,#LINEAR_FLAG|LBA32_FLAG
2688 push ax ;save the count
2689 mov ah,#2 ;read command
2690 call dsk_do_rw ; int 0x13 with retries
2691 pop cx ;Carry Set means error on read
2692 mov al,cl ;count in AL, error code in AH
2696 mov ah,hinib ;will be zero for LINEAR
2697 xchg al,dh ;AX is possible address
2698 test dl,#LBA32_FLAG ;test for LBA32/LINEAR *****
2699 jz lnread ;pure LINEAR *****
2700 test dl,#LBA32_NOCOUNT
2702 mov ah,dh ;former count is really hi-nibble
2704 mov dh,#1 ;set count to 1
2706 xchg di,ax ;hi-address to DI
2707 mov al,dh ;count to AL
2709 test dl,#RAID_REL_FLAG ; ******
2710 jz ln_do_read ; ******
2712 call translate ; in volume.S
2716 mov al,cl ;count returned in AL, error code in AH
2717 ret ;Carry Set means error on read
2720 ; vmtest -- return Carry=1 if in virtual (VMware) mode
2721 ; return Carry=0 if in real mode
2725 pushad ; save all extended registers
2727 rcr al,1 ; PE bit in AL to Carry
2728 jc vm_ret ; exit if virtual mode
2730 mov ah,#2 ; get keyboard flags
2732 and al,#0x50 ; Caps, Scroll Lock flags
2734 je vm_vir ; Caps only means virtual boot simulated
2737 ; If no vmdefault, vmdisable, or vmwarn keywords were used, then we do not
2738 ; care about virtual mode. Do not touch the hardware, and always return
2741 test byte ptr [par2_flag2],#FLAG2_VIRTUAL ; any vmXXX keywords?
2742 jz vm_ret ; TEST clears the carry, always
2744 ; VMware(R) test for virtual mode
2746 mov eax,#0x564D5868 ; EAX: in = 'VMXh' out = version
2747 xor ebx,ebx ; EBX: out = 'VMXh' under vmware
2749 mov dx,#0x5658 ; DX: in = 'VX'
2750 mov ecx,#10 ; ECX: in = VMXGetVersion
2752 cmp ebx,edi ; test for vmware
2753 clc ; NOT vmware if Carry==0
2754 jne vm_ret ; not vmware
2756 inc eax ; carry is not affected by INC
2757 jz vm_ret ; invalid version number == 0xFFFFFFFF
2760 stc ; signal virtual mode
2762 vm_ret: popad ; restore all the extended registers
2765 #else /* LCF_SUSPEND changes the interpretation of "virtual" */
2768 test byte ptr [vm_cache],#0xFF ; test cached value
2771 mov byte ptr [vm_cache],#2 ; not virtual
2775 mov bx,#MAP ; use this buffer
2776 mov cx,#1 ; sector 1
2777 mov dx,#0x80 ; dos C: drive
2778 mov al,cl ; 1 sector
2780 jc vm_ret ; not virtual if error
2782 mov cx,#PARTITION_ENTRIES ; count 4 PT entries
2783 lea bx,[PART_TABLE_OFFSET](bx) ; first partition entry
2785 test byte ptr (bx),#0x80 ; active
2787 cmp byte ptr (bx+4),#LCF_SUSPEND ; suspend partition
2789 mov byte ptr [vm_cache],#1 ; suspend is active
2791 lea bx,[PARTITION_ENTRY](bx) ; bump pointer
2795 mov al,[vm_cache] ; get cached value
2802 .byte 0 ; 0=unknown, 1=virtual, 2=non-virtual
2804 #endif /* LCF_SUSPEND */
2805 #endif /* LCF_VIRTUAL */
2809 ; kbtest -- return Carry=1 if IBM PC/AT keyboard is present
2810 ; -- return Carry=0 if no IBM keyboard is present
2815 ; If neither nokbdefault nor nokbdisable was used, we do not touch
2816 ; the keyboard hardware. Always report Carry=1 (keyboard present).
2818 test byte ptr [par2_flag2],#FLAG2_NOKBD
2824 call say ; tell about keyboard test
2828 cli ; added 5/17/2006
2829 mov al,#0xee ; echo command
2831 wait_kbd_ctrl_ready:
2834 jz wait_kbd_ctrl_ready ; read status port while it is not ready
2836 sti ; added 5/17/2006
2837 xor al,#0xee ; XOR clears the carry
2839 ; if we got the same byte, the keyboard is attached
2842 mov ah,#2 ; get keyboard flags
2844 and al,#0x20 ; Num Lock flag
2845 jz kbtest9 ; AND cleared the carry
2848 stc ; flag keyboard present
2852 #endif /* LCF_NOKEYBOARD */
2856 ; crc32 -- calculate CRC-32 checksum
2859 ; push dword #POLYNOMIAL
2861 ; ES:SI char string pointer
2862 ; DI count of characters
2866 ; CRC-32 is returned in EAX or DX:AX
2867 ; the arguments are popped from the stack
2878 xor eax,eax ; initialize CRC
2879 dec eax ; EAX = 0xFFFFFFFF
2884 mov cx,#8 ; count 8 bits
2886 mov bl,(si) ; get next character
2888 crc32b: shl bx,#1 ; get hi bit of char in BH
2889 shl eax,#1 ; shift hi bit out of CRC
2890 adc bh,#0 ; add carry to BH
2891 shr bh,#1 ; put bit in carry
2892 jnc crc32c ; skip the xor
2893 xor eax,(bp+4) ; xor in the polynomial
2895 loop crc32b ; loop back for 8 bits
2899 not eax ; finialize CRC
2909 /* ifdef HIGHMEM_MAX */
2910 ; enter with BX == Ramdisk size (in 4k pages)
2913 push bx ; save Ramdisk size in pages
2914 mov eax,[hma] ; user specified?
2916 #ifdef LCF_INITRDLOW
2918 #else /* ifndef LCF_INITRDLOW */
2919 jnz near rd_have_hma
2922 test byte ptr par1_prompt+SSDIFF,#FLAG_LARGEMEM
2926 ; try the E820 memory map first
2927 xor edx,edx ; flag nothing found
2928 xor esi,esi ; flag size==0
2930 ;jmp e8go ; circumvented due to BIOS problems
2931 br no_e801 ; skip to backup plan
2932 e8go2: or ebx,ebx ; test for end
2934 e8go: push edx ; save best prospect
2936 mov edx,#0x534d4150 ;'SMAP'
2939 int 0x15 ; get memory map
2940 pop edx ; restore what we have found so far
2942 cmp eax,#0x534d4150 ;'SMAP'
2947 mov eax,memmap ; get start
2948 mov ecx,memmap+4 ; get high part
2949 cmp word memmap+16,#1 ; available?
2950 jne e8no1 ; go on to next
2953 cmp eax,#0x100000 ; compare to 1Mb
2955 add eax,memmap+8 ; get final address
2957 shrd eax,ecx,#10 ; convert to 1k blocks (legacy)
2958 cmp eax,#4*1024 ; compare to 4Mb
2960 xchg eax,edx ; save in edx
2963 e8no1: shrd eax,ecx,#10 ; convert to 1k blocks
2964 cmp eax,#1024 ; compare to 1Mb
2965 jb e8go2 ; loop if too small
2966 cmp eax,edx ; check against HMA
2968 xchg eax,edx ; compensate for buggy BIOS
2969 jmp e8go2 ; remember in EDX & loop
2971 cmp word memmap+16,#1 ; available?
2973 mov eax,memmap+4 ; hi part of start
2974 shrd memmap,eax,#10 ; convert start to 1k
2975 mov eax,memmap+12 ; hi part of size
2976 shrd memmap+8,eax,#10 ; convert to 1k
2977 cmp dword memmap,#1024 ; below 1M
2978 jb e8go2 ; below 1M, no interest
2979 cmp esi,memmap+8 ; check size
2980 ja e8go2 ; want largest
2981 mov edx,memmap ; start (in 1k)
2982 mov esi,memmap+8 ; size (in 1k)
2983 add edx,esi ; HMA in 1k
2986 e8go5: or edx,edx ; find anything?
2991 ; above failed, try the older E801 block count interface
2992 xor cx,cx ; some BIOSs are buggy
2994 mov ax,#0xe801 ; call
3007 shl ebx,#6 ; convert 64k to 1k
3009 cmp eax,ebx ; compare sizes
3011 add ebx,ecx ; add in 16M
3012 mov eax,ebx ; and use this value
3015 add eax,#1024 ; add 1M
3016 cmp eax,ecx ; is it 16M
3018 add eax,ebx ; add in ebx
3020 #endif /* ifndef LCF_INITRDLOW */
3022 ; above two methods failed, try the old 0x88 function
3023 mov ah,#0x88 ; get count of extended memory blocks
3025 movzx eax,ax ; extend to dword
3026 add eax,#1024 ; add in base 1M
3028 rd_have_hma: ; have the HMA / 1k in EAX
3031 shl eax,10 ; convert to address
3034 call dout ; pops its argument
3039 mov ebx,#15*1024 ; 15Mb
3040 cmp eax,ebx ; compare to 15M
3041 jbe rd_use_eax ; use lower value
3044 test byte ptr par1_prompt+SSDIFF,#FLAG_LARGEMEM
3047 xchg eax,ebx ; limit to 15Mb
3049 mov ebx,#HIGHMEM_MAX/1024
3050 #ifdef NEW3_HDR_VERSION
3052 mov ds,[initseg] ; load the original boot sector
3053 cmp word ptr [CL_HDRS_VERSION],#NEW3_HDR_VERSION
3055 mov ebx,[CL_RAMDISK_MAX]
3069 shr ebx,#10 ; divide by 1024
3073 #endif /* ifdef NEW3_HDR_VERSION */
3077 xchg eax,ebx ; must use the smaller
3079 pop bx ; get size in pages
3080 shr eax,2 ; convert to pages
3081 movzx ebx,bx ; zero high part of size
3082 sub eax,ebx ; start address of ramdisk to EAX
3084 cmp dword ptr [hma],#0x180000/1024 ; 1.5Mb
3086 cmp dword ptr [hma],#0xF00000/1024 ; 15Mb
3088 mov eax,[hma] ; HMA is initrd start
3093 cmp eax,#256 ; we probably need more than 1M for the
3094 ja rd_okay ; kernel to be useful ...
3095 mov bx,#msg_rd ; complain
3096 ;;; call say ; is at zz
3099 cmp eax,#4*256 ; Ramdisk loaded below 4Mb
3100 jae rd_okay ; kernel to be useful ...
3101 mov bx,#msg_rd4M ; complain
3105 shl eax,4 ; shift (12-8) -> 4
3106 mov [rdbeg+1],ax ; set up beginning address
3107 mov [gdt+0x1b],ax ; set the GDT for the moves
3108 shr eax,16 ; get hi-byte of address
3109 mov [rdbeg+3],al ; set rest of address
3110 mov [gdt+0x1f],al ; and in the GDT, too
3112 /* endif / ifdef HIGHMEM_MAX */
3115 /* enter with SI pointing to DESCRIPTOR
3118 SI - points at the descriptor
3123 mov word ptr [map],#MAP2
3126 mov ax,(si+id_flags) ; get FLAG_TOOBIG, if any
3127 #if FLAG_LARGEMEM!=FLAG_TOOBIG
3128 # error "FLAG_LARGEMEM and FLAG_TOOBIG must be equal"
3130 and al,#FLAG_TOOBIG ; separate flag
3133 or byte ptr par1_prompt+SSDIFF, al ; set FLAG_LARGEMEM
3135 add si,#id_rd_size ; point at ramdisk size long
3136 ! take care of the RAM disk first
3138 mov (rdbeg),eax ; clear address
3140 mov (rdszl),eax ; set rdszl+rdszh
3141 add eax,#4095 ; round up &
3142 shr eax,#12 ; convert to pages
3143 xchg bx,ax ; copy to BX
3144 lodsw ; address of the first map sector
3149 or bx,bx ; no RAM disk ?
3150 jz noramd ; yes -> skip it 2
3152 push si ; save SI, ES, and BX (RD size)
3155 mov bx,[map] ; load the first map sector
3162 /* ifdef HIGHMEM_MAX */
3166 cmp dword ptr (rdbeg),#0
3167 je nordpt ; no -> no need to patch header for that
3170 push dword (rdbeg) ; print RAM disk address
3176 mov es,[setupseg] ; load the setup codes
3177 mov eax,(rdbeg) ; get RAM disk start address
3179 mov (24),eax ; store in header
3182 mov (28),eax ; set RAM disk size
3184 push #0 ; ES=0 is our secret code to load via GDT
3187 call lfile ; load it
3189 mov al,#0x20 ; print a space
3192 pop es ; restore ES and SI
3199 #ifndef LCF_NOSERIAL
3200 serLI: .byte 13,10,0x4c,0x49 ; cr,lf,"LI"
3202 BAUD_BASE = 115200 ; divisor == 1
3204 .byte BAUD_BASE / 19200 ; must be same as bsect.c table
3205 .byte BAUD_BASE / 38400
3206 .byte BAUD_BASE / 57600
3207 .byte BAUD_BASE / 115200
3208 .byte BAUD_BASE / 2400
3209 .byte BAUD_BASE / 2400
3210 .byte BAUD_BASE / 2400
3211 .byte BAUD_BASE / 2400
3213 ; serial_setup -- do the setup for the serial line communications
3215 ; No registers are saved
3220 mov dx,par2_port ; use a COM port ?
3221 ; watch out, loads par2_ser_param
3224 js nocom ; no -> go on
3225 xor ax,ax ; initialize the serial port
3231 ;;; or al,#0x06 ; stop bits = 2, nbits = 7 or 8
3232 ; this OR is not needed yet (21.7)
3233 int 0x14 ; Communications Port INIT
3241 mov dx,(bx) ; get the port address from the BIOS
3246 pop bx ; special baud rate test -- was AX
3248 test bl,#0x04 ; stop bits == 2?
3249 cli ; do not disturb any code below
3250 jz stdbps ; standard BPS
3252 shr bx,#5 ; index divisor array
3256 spcbps: ; CLI: do not disturb ...
3257 push dx ; save base address
3258 add dx,#3 ; enable divisor latch access
3262 pop dx ; set new divisor
3269 inc dx ; disable divisor latch access
3274 pop dx ; restore base address
3276 stdbps: ; CLI: redundant if fell in from above
3278 add dx,#4 ; address Modem Control Reg.
3281 or al,#3 ; turn on DTR and RTS
3283 mov al,#3 ; turn on DTR and RTS
3289 mov cx,#32 ; drain the queue (if any)
3292 add dx,#5 ; clear the status register
3295 ; send "\r\nLI" to the serial port
3307 #endif /* LCF_NOSERIAL */
3311 #ifdef SHS_PASSWORDS
3316 #define SECOND_STAGE_LOADER
3318 #undef SECOND_STAGE_LOADER
3321 #include "biosdata.S"
3323 #if defined(MENU) || defined(BITMAP) || DEBUG_NEW
3333 #include "vesainfo.h"
3334 #include "display4.S"
3337 ! Put tokens into keyboard buffer
3339 putkbd: add si,#4 ; skip over "kbd="
3341 xor ax,ax ; set ES to zero
3343 pknext: lodsb ; get next byte
3345 jz pkdone ; yes -> done
3346 cmp al,#32 ; blank ?
3347 jne pkrd ; no -> read scan code
3348 pkdone: dec si ; return last character
3351 pkrd: xor cx,cx ; clear accumulator
3352 pkrdlp: cmp al,#97 ; lower case character ?
3353 jb pknol ; no -> go on
3354 sub al,#32 ; make upper case
3355 pknol: sub al,#48 ; normalize
3357 jb pkok ; no -> okay
3359 jb pksyn ; yes -> syntax error
3362 jae pksyn ; yes -> syntax error
3363 pkok: shl cx,1 ; shift CX
3364 jc pksyn ; carry means trouble
3371 add cl,al ; put in lowest nibble
3372 lodsb ; get next byte
3374 jz pkend ; yes -> at end
3375 cmp al,#32 ; space ?
3376 je pkend ; yes -> at end
3377 cmp al,#44 ; comma ?
3378 je pkmore ; yes -> end of token
3379 jmp pkrdlp ; token continues
3380 pksyn: mov bx,#msg_pks ; complain
3382 pkfls: lodsb ; flush to end of option
3388 pkend: call pkput ; store token
3389 jmp pkdone ; ... and return
3390 pkmore: call pkput ; store token
3391 jmp pknext ; handle next token
3392 pkput: seg es ; get buffer pointer
3395 add dx,#2 ; increment it
3396 cmp dx,#KBHIGH ; (wrap around end)
3399 pknadj: seg es ; buffer full ?
3401 je pkfull ; yes -> error
3402 seg es ; store scan code
3404 seg es ; store new pointer
3407 pkfull: mov bx,#msg_pkf ; complain
3409 pop ax ; discard return address
3414 setvga: add si,#4 ; skip over "vga="
3416 mov bx,#vgatab ; scan VGA table
3417 svgatb: pop si ; get pointer to option value
3419 mov cx,(bx) ; get VGA code
3421 jz vganum ; yes -> must be numeric
3422 inc bx ; compare the strings
3425 call upcase ; (case-insensitive)
3429 jnz vgamore ; no -> go on
3430 or al,al ; at end of line ?
3431 jz vgafnd ; yes -> found it
3432 cmp al,#32 ; space ?
3433 je vgafnd ; yes -> found it
3434 jmp svgatb ; try next entry otherwise
3436 je vgacmp ; equal -> next character
3437 vgaskp: mov al,(bx) ; skip to end of reference string
3441 jmp svgatb ; try next entry
3442 vgafnd: pop ax ; drop SI
3444 vgaput: dec si ; read last character again
3445 vgaput1: mov vgaovr,cx ; set VGA mode
3449 vganum: pop si ; get SI
3460 test byte ptr (si),#0xff ; no value ?
3461 jz vgaerr ; yes -> error
3462 vgadig: lodsb ; get the next character
3464 jz vgaput ; yes -> done
3467 cmp al,#48 ; is it a digit ? (0x30=48="0")
3468 jb vgaerr ; no -> error
3469 cmp al,#57 ; 57=0x39="9"
3471 sub al,#48 ; cx = cx*10+al-'0'
3474 jnc vgadig ; next one
3477 vgaerr: mov bx,#msg_v ; display an error message
3479 /* ifdef HIGHMEM_MAX */
3481 mov dword ptr [hma],eax
3483 stc ; return an error
3504 ! get numeric string suffixed with "KkMmGg"
3510 call strtoull ; get number in DX:AX
3511 jc gmthis2 ; signal conversion error
3513 mov bl,(si) ; get next character
3514 or bl,#0x20 ; convert to lower case
3515 cmp bl,#0x6b ; 'K' or 'k' ?
3516 je gmthis ; yes -> do not change
3518 mov cx,#20 ; divide or multiply by 2^20
3519 cmp bl,#0x67 ; 'G' or 'g' ?
3522 mov cx,#10 ; divide or multiply by 2^10
3523 cmp bl,#0x6d ; 'M' or 'm' ?
3527 dec si ; will increment later
3530 shr eax,cl ; shift by CL
3534 shl eax,1 ; shift by 1 each time
3535 jc gmvbig ; very big if overflow
3536 loop gmmull ; ten times
3538 ! exit with no error
3542 clc ; signal no error
3544 mov bl,(si) ; next character to BL
3555 pop cx ; restore register
3559 mov eax,#HIGHMEM_MAX/1024
3566 push si ; save SI for copying
3567 add si,#4 ; advance to number?
3569 jc gmcopy ; error, just copy it
3571 cmp bl,#0x40 ; is it '@'
3573 ! <size>@<start> format (2.4 kernels)
3574 push eax ; save size
3577 pop edx ; restore size
3579 cmp eax,#1024 ; start : 1meg
3580 ja gmcopy ; just copy if above
3581 add eax,edx ; EAX = hma/1024
3582 cmp eax,#2048 ; high : 2meg
3586 cmp bl,#0x20 ; NUL or SPACE
3590 jne gmcopy ; allow <size>#<start> and <size>$<start>
3592 cmp dword ptr [hma],#0 ; set already?
3594 mov dword ptr [hma],eax ; set it
3602 mov bx,#msg_me ; numeric conversion error
3606 strtoull: ; numeric conversion to EAX
3613 strtoul: /* string to unsigned long in DX:AX */
3616 mov cx,#10 ; default radix is decimal
3617 cmp byte ptr (si),#0x39
3618 ja s2lbad ; error if > '9'
3619 cmp byte ptr (si),#0x30 ; == '0'?
3620 jb s2lbad ; error if < '0'
3624 dec cx ; assume octal : CX = 8
3626 cmp byte ptr (si),#0x58 ; == 'X'?
3628 cmp byte ptr (si),#0x78 ; == 'x'?
3630 s2lhex: add cx,cx ; it is hexadecimal
3634 mov bl,(si) ; get next character
3636 or bl,#0x20 ; convert to lower case
3637 sub bl,#0x30 ; - '0'
3639 cmp bl,cl ; compare to radix
3641 add bl,#0x30-0x61+10
3642 cmp bl,cl ; compare to radix
3645 push dx ; save high order
3646 mul cx ; multiply by radix
3648 adc dx,#0 ; carry possible only in radix 10
3672 ; if there is something on the command line
3673 ; return the image number it selects
3678 ; If nothing selected:
3681 ; If an image is selected:
3682 ; (fuzzy selection or exact selection)
3685 ; BX==pointer to descriptor
3689 ; The selected image is hi-lited if the menu is displayed
3696 mov cx,#IMAGES ; test all names
3698 xor bx,bx ; clear BX
3703 test byte ptr (si),#0xFF ; null descriptor at end
3707 mov al,(si) ; get next character in descr
3709 #ifdef LCF_IGNORECASE
3713 mov al,(di) ; get next char in cmdline
3715 #ifdef LCF_IGNORECASE
3718 or al,al ; NUL in command line
3720 cmp al,#32 ; SPACE in command line
3723 ; have partial match, set BX conditionally
3725 or ah,ah ; NUL in descriptor name
3726 jz fi_found ; EXACT match found
3728 test byte ptr par2_flag2,#FLAG2_UNATTENDED ; (22.7)
3729 jnz fi_skipn ; no partial match if unattended
3732 jnz fi_skipn ; already set
3735 jmp fi_skipn ; go to next
3738 cmp al,ah ; character equal ?
3739 je fi_nextc ; compare next character
3741 ; advance to next descriptor
3744 add si,#id_size ; test next name
3750 or bx,bx ; fuzzy match?
3753 #if defined(MENU) || defined(BITMAP)
3755 call lowlite ; no match, nothing hi-lited
3756 ;;; mov word [dimage],#0
3758 xor ax,ax ; clears the carry
3766 pop bx ; BX is matched descriptor
3773 #if defined(MENU) || defined(BITMAP)
3776 cmp byte [abs_cx+1],#0 ; see if menu is displayed
3792 ; check that nobody has changed the FS register
3799 ; oops, somebody changed it !!!
3804 sub ax,#3 ; length of call
3806 mov bx,#msg_fs_changed
3809 #if CHECK_FS_VERBOSE
3827 .ascii " <- loc where FS is clobbered\n"
3829 #if CHECK_FS_VERBOSE
3831 .ascii " <- FS okay\n"
3838 msg_p: .ascii "boot: "
3841 msg_l: .ascii "Loading "
3844 msg_bc: .ascii "BIOS data check "
3847 msg_s: .ascii "successful\n"
3850 msg_by: .ascii "bypassed\n"
3857 msg_nf: .ascii "No such image. [Tab] shows a list."
3861 .ascii "O - Timestamp mismatch\n"
3865 .ascii "O - Descriptor checksum error\n"
3869 .ascii "O - Keytable read/checksum error\n"
3873 .ascii "Kernel and Initrd memory conflict\n"
3877 .ascii "O - Signature not found\n"
3881 .ascii "vga/mem= requires a numeric value"
3884 msg_wrerr: .ascii "\nMap file write; BIOS error code = 0x"
3887 msg_wrerr3: .ascii "\nMap file: WRITE PROTECT\n"
3891 msg_mem: .ascii "EBDA is big; kernel setup stack overlaps LILO second stage"
3897 .ascii "WARNING: Booting in Virtual environment\n"
3898 .ascii "Do you wish to continue? [y/n] "
3906 msg_pl: .ascii "\nParameter line = "
3908 #ifdef LCF_NOKEYBOARD
3910 .ascii "**PC/AT Keyboard test**\n"
3914 #if defined(LCF_VIRTUAL) || defined(LCF_NOKEYBOARD)
3916 .ascii "Performing REAL MODE boot\n"
3921 .ascii "Performing VIRTUAL MODE boot\n"
3924 #ifdef LCF_NOKEYBOARD
3926 .ascii "Performing NO KEYBOARD DEFAULT boot\n"
3932 .ascii "\nINIT SETUP CODE SS:SP EX_OFF_DX 2ndDX\n"
3935 msg_low: .ascii " low"
3938 msg_high: .ascii " high"
3941 hdr1: .ascii "\nHeader 0x"
3944 hdr2: .ascii " cmdline at "
3947 hdr4: .ascii " length = 0x"
3950 hdr3: .ascii "\nRamdisk_max "
3953 nohdrs: .ascii "\nNo cmdline passed"
3957 .ascii "RAM disk loaded at: "
3960 msg_hma: .ascii " is the HMA\n"
3963 msg_gk: .ascii " returned by 'get_K'\n"
3969 .ascii "*Interrupted*"
3973 .ascii "Unexpected EOF"
3976 msg_pw: .ascii "Password: "
3979 msg_pf: .ascii "Sorry."
3983 .ascii "Valid vga values are ASK, NORMAL, EXTENDED or a "
3984 .ascii "decimal number."
3988 .ascii "Invalid hexadecimal number. - Ignoring remaining items."
3992 .ascii "Keyboard buffer is full. - Ignoring remaining items."
3996 .ascii "Block move error 0x"
4001 .ascii "Not enough memory for RAM disk"
4005 .ascii "Initial ramdisk loads below 4Mb; "
4006 .ascii "kernel overwrite is possible."
4016 .ascii SA(VERSION_MAJOR)
4018 .ascii SA(VERSION_MINOR)
4026 stepa: .ascii " RAM disk,"
4028 step0: .ascii " map page,"
4030 step0b: .ascii " fallback,"
4032 step1: .ascii " options,"
4034 step1b: .ascii " fallback,"
4036 step2: .ascii " boot,"
4038 step3: .ascii " setup,"
4040 step4: .ascii " system "
4054 mov_ar: .ascii " -> "
4056 mov_sz: .ascii ", words "
4064 #if defined(MENU) || defined(BITMAP)
4065 suppress:.word 0 ; suppress console output (MUST be word)
4067 hinib: .byte 0 ; hi-nibble of address
4069 moff: .word 0 ; map offset
4070 map: .word MAP ; map to use
4072 cntdown:.word 0 ; count-down
4073 timeout:.byte 0 ; timed out
4077 int1c_l:.word 0 ; old timer interrupt
4080 old_del:.word 0 ; delay before booting
4082 nodfl: .word 0 ; action if no defaults are present
4084 #ifndef LCF_NOSERIAL
4085 slbase: .word 0 ; serial port base (or 0 if unused)
4086 break: .byte 0 ; break received flag
4089 usrinpm:.byte UI_MAGIC
4094 rdbeg: .word 0,0 ; RAM dist begin address (dword)
4096 rdszl: .word 0 ; RAM disk size
4099 vgaovr: .word 0 ; VGA mode overwrite
4101 /* ifdef HIGHMEM_MAX */
4102 hma: .word 0,0 ; Highest Memory Address
4103 memmap: .word 0,0,0,0,0,0,0,0,0,0
4105 dskprm: .word 0,0,0,0,0,0
4107 .even ; control alignment from here down
4108 acmdbeg:.ascii "auto "
4109 mcmdbeg:.ascii "BOOT_IMAGE"
4110 prechr: .byte 32 ; space: guard double blank supression
4111 ; equal sign: variable assignment
4115 _line = cmdline+CL_LENGTH ; must be 640 bytes long
4120 lkwbuf = cmdline+CL_LENGTH+2 ; this is a word
4122 theend2 = lkcbuf+CL_LENGTH ; lkcbuf is 256
4124 the_end1 = theend+511
4125 theends = the_end1/512
4132 /* the older version 21 layout */
4133 Map = max_secondary + SECTOR_SIZE
4134 Dflcmd = Map + SECTOR_SIZE
4136 Descr = Dflcmd + SECTOR_SIZE
4137 Keytable = Descr + SECTOR_SIZE*MAX_DESCR_SECS_asm
4138 ParmBSS = Keytable + SECTOR_SIZE
4140 /* a possible 22.5.6 layout puts the descriptors last */
4141 Map = max_secondary + SECTOR_SIZE
4142 Dflcmd = Map + SECTOR_SIZE
4144 Keytable = Dflcmd + SECTOR_SIZE
4145 Descr = Keytable + SECTOR_SIZE
4146 ParmBSS = Descr + SECTOR_SIZE*MAX_DESCR_SECS_asm
4149 #if COMMAND_LINE_SIZE > 256
4151 Parmline = BSSstart + SECTOR_SIZE
4154 BSSstart = Parmline + CL_LENGTH
4157 !************************************
4159 ! moved from volume.S
4164 #ifdef SHS_PASSWORDS
4170 BSSsize = BSSend-BSSstart
4173 Dataend = Parmline + SECTOR_SIZE