mirror of
https://github.com/KolibriOS/kolibrios.git
synced 2024-12-21 06:12:34 +03:00
2518ed40a1
1)update 2)create v86 process git-svn-id: svn://kolibrios.org@4923 a494cfbc-eb01-0410-851d-a64ba20cac60
1425 lines
42 KiB
PHP
1425 lines
42 KiB
PHP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
;; ;;
|
||
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
|
||
;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;;
|
||
;; Distributed under terms of the GNU General Public License ;;
|
||
;; ;;
|
||
;; BOOTCODE.INC ;;
|
||
;; ;;
|
||
;; KolibriOS 16-bit loader, ;;
|
||
;; based on bootcode for MenuetOS ;;
|
||
;; ;;
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
|
||
$Revision: 4291 $
|
||
|
||
|
||
;==========================================================================
|
||
;
|
||
; 16 BIT FUNCTIONS
|
||
;
|
||
;==========================================================================
|
||
|
||
|
||
putchar:
|
||
; in: al=character
|
||
mov ah, 0Eh
|
||
mov bh, 0
|
||
int 10h
|
||
ret
|
||
|
||
print:
|
||
; in: si->string
|
||
mov al, 186
|
||
call putchar
|
||
mov al, ' '
|
||
call putchar
|
||
|
||
printplain:
|
||
; in: si->string
|
||
pusha
|
||
lodsb
|
||
@@:
|
||
call putchar
|
||
lodsb
|
||
test al, al
|
||
jnz @b
|
||
popa
|
||
ret
|
||
|
||
getkey: ; Use BIOS INT 16h to read a key from the keyboard
|
||
; get number in range [bl,bh] (bl,bh in ['0'..'9'])
|
||
; in: bx=range
|
||
; out: ax=digit (1..9, 10 for 0)
|
||
mov ah, 0 ; If 'int 16h' is called with 'ah' equal to zero, the BIOS will not return control to the caller
|
||
int 16h ; until a key is available in the system type ahead buffer. On return, 'al' contains the ASCII
|
||
cmp al, 27 ; code for the key read from the buffer and 'ah' contains the keyboard scan code. (27=>ESC)
|
||
jz @f ; If ESC is pressed, return (user doesn't want to change any value).
|
||
cmp al, bl ; Compare 'al' (ASCII code of key pressed) with 'bl' (lowest accepted char from the range).
|
||
jb getkey ; ASCII code is below lowest accepted value => continue waiting for another key.
|
||
cmp al, bh ; Compare 'al' (ASCII code of key pressed) with 'bh' (highest accepted char from the range).
|
||
ja getkey ; ASCII code is above highest accepted value => continue waiting for another key.
|
||
push ax ; If the pressed key is in the accepted range, save it on the stack and echo to screen.
|
||
call putchar
|
||
pop ax
|
||
and ax, 0Fh ; Convert ASCII code to number: '1'->1, '2'->2, etc. 0Fh=1111b.
|
||
jnz @f ; ASCII code for '0' is 48 (110000b). (110000b AND 1111b) = 0
|
||
mov al, 10 ; So if key '0' was entered, return 10 in 'ax'
|
||
@@:
|
||
ret
|
||
|
||
setcursor:
|
||
; in: dl=column, dh=row
|
||
mov ah, 2
|
||
mov bh, 0
|
||
int 10h
|
||
ret
|
||
|
||
macro _setcursor row,column
|
||
{
|
||
mov dx, row*256 + column
|
||
call setcursor
|
||
}
|
||
|
||
macro _ask_question question,range,variable_to_set
|
||
{
|
||
_setcursor 16,0
|
||
mov si, question ; Print the question
|
||
call print
|
||
mov bx, range ; range accepted for answer
|
||
call getkey
|
||
cmp al, 27 ; If ESC was pressed, do not change the value
|
||
jz .esc_pressed
|
||
mov [variable_to_set], al
|
||
}
|
||
|
||
boot_read_floppy:
|
||
push si
|
||
xor si, si
|
||
mov ah, 2 ; read
|
||
@@:
|
||
push ax
|
||
int 0x13
|
||
pop ax
|
||
jnc @f
|
||
inc si
|
||
cmp si, 10
|
||
jb @b
|
||
sayerr_badsect:
|
||
mov si, badsect
|
||
sayerr_plain:
|
||
call printplain
|
||
jmp $
|
||
@@:
|
||
pop si
|
||
ret
|
||
|
||
; convert abs. sector number (AX) to BIOS T:H:S
|
||
; sector number = (abs.sector%BPB_SecPerTrk)+1
|
||
; pre.track number = (abs.sector/BPB_SecPerTrk)
|
||
; head number = pre.track number%BPB_NumHeads
|
||
; track number = pre.track number/BPB_NumHeads
|
||
; Return: cl - sector number
|
||
; ch - track number
|
||
; dl - drive number (0 = a:)
|
||
; dh - head number
|
||
conv_abs_to_THS:
|
||
push bx
|
||
mov bx, word [BPB_SecPerTrk]
|
||
xor dx, dx
|
||
div bx
|
||
inc dx
|
||
mov cl, dl ; cl = sector number
|
||
mov bx, word [BPB_NumHeads]
|
||
xor dx, dx
|
||
div bx
|
||
; !!!!!!! ax = track number, dx = head number
|
||
mov ch, al ; ch=track number
|
||
xchg dh, dl ; dh=head number
|
||
mov dl, 0 ; dl=0 (drive 0 (a:))
|
||
pop bx
|
||
retn
|
||
; needed variables
|
||
BPB_SecPerTrk dw 0 ; sectors per track
|
||
BPB_NumHeads dw 0 ; number of heads
|
||
BPB_FATSz16 dw 0 ; size of FAT
|
||
BPB_RootEntCnt dw 0 ; count of root dir. entries
|
||
BPB_BytsPerSec dw 0 ; bytes per sector
|
||
BPB_RsvdSecCnt dw 0 ; number of reserved sectors
|
||
BPB_TotSec16 dw 0 ; count of the sectors on the volume
|
||
BPB_SecPerClus db 0 ; number of sectors per cluster
|
||
BPB_NumFATs db 0 ; number of FAT tables
|
||
abs_sector_adj dw 0 ; adjustment to make abs. sector number
|
||
end_of_FAT dw 0 ; end of FAT table
|
||
FirstDataSector dw 0 ; begin of data
|
||
|
||
;=========================================================================
|
||
;
|
||
; 16 BIT CODE
|
||
;
|
||
;=========================================================================
|
||
|
||
include 'bootvesa.inc' ;Include source for boot vesa
|
||
if defined extended_primary_loader
|
||
include 'parsers.inc'
|
||
end if
|
||
|
||
start_of_code:
|
||
|
||
if defined extended_primary_loader
|
||
; save data from primary loader
|
||
mov word [cs:bootcallback], si
|
||
mov word [cs:bootcallback+2], ds
|
||
push cs
|
||
pop ds
|
||
mov [bootdevice], ax
|
||
mov [bootfs], bx
|
||
|
||
; set up stack
|
||
mov ax, 3000h
|
||
mov ss, ax
|
||
mov sp, 0EC00h
|
||
|
||
; try to load configuration file
|
||
mov ax, 1
|
||
mov di, config_file_struct
|
||
call [bootcallback]
|
||
cld
|
||
push cs
|
||
pop es
|
||
; bx=0 - ok, bx=1 - part of file loaded, assume this is ok
|
||
cmp bx, 1
|
||
ja .config_bad
|
||
; configuration file was loaded, parse
|
||
; if length is too big, use first 0FFFFh bytes
|
||
test dx, dx
|
||
jz @f
|
||
mov ax, 0FFFFh
|
||
@@:
|
||
; ds:si will be pointer to current data, dx = limit
|
||
xchg ax, dx
|
||
push 4000h
|
||
pop ds
|
||
xor si, si
|
||
.parse_loop:
|
||
; skip spaces
|
||
cmp si, dx
|
||
jae .parse_done
|
||
lodsb
|
||
cmp al, ' '
|
||
jbe .parse_loop
|
||
dec si
|
||
; loop over all possible configuration values
|
||
mov bx, config_file_variables
|
||
.find_variant:
|
||
; get length
|
||
mov cx, [es:bx]
|
||
; zero length = end of list
|
||
jecxz .find_newline
|
||
; skip over length
|
||
inc bx
|
||
inc bx
|
||
mov di, bx
|
||
; skip over string
|
||
add bx, cx
|
||
; test whether we have at least cx symbols left
|
||
mov ax, cx
|
||
add ax, si
|
||
jc .next_variant1
|
||
cmp ax, dx
|
||
jae .next_variant1
|
||
; save current position
|
||
push si
|
||
; compare strings
|
||
repz cmpsb
|
||
jnz .next_variant2
|
||
; strings are equal; look for "=" with possible spaces before and after
|
||
@@:
|
||
cmp si, dx
|
||
jae .next_variant2
|
||
lodsb
|
||
cmp al, ' '
|
||
jbe @b
|
||
cmp al, '='
|
||
jnz .next_variant2
|
||
; ok, we found the true variant
|
||
; ignore saved position on the stack
|
||
pop ax
|
||
; call the parser
|
||
call word [es:bx]
|
||
; line parsed, find next
|
||
.find_newline:
|
||
cmp si, dx
|
||
jae .parse_done
|
||
lodsb
|
||
cmp al, 13
|
||
jz .parse_loop
|
||
cmp al, 10
|
||
jz .parse_loop
|
||
jmp .find_newline
|
||
.next_variant2:
|
||
; continue to the next variant, restoring current position
|
||
pop si
|
||
.next_variant1:
|
||
; continue to the next variant
|
||
; skip over the parser
|
||
inc bx
|
||
inc bx
|
||
jmp .find_variant
|
||
.parse_done:
|
||
.config_bad:
|
||
|
||
; set up segment registers
|
||
push cs
|
||
pop ds
|
||
else
|
||
cld
|
||
; \begin{diamond}[02.12.2005]
|
||
; if bootloader sets ax = 'KL', then ds:si points to loader block
|
||
cmp ax, 'KL'
|
||
jnz @f
|
||
mov word [cs:cfgmanager.loader_block], si
|
||
mov word [cs:cfgmanager.loader_block+2], ds
|
||
@@:
|
||
; \end{diamond}[02.12.2005]
|
||
|
||
; if bootloader sets cx = 'HA' and dx = 'RD', then bx contains identifier of source hard disk
|
||
; (see comment to bx_from_load)
|
||
cmp cx, 'HA'
|
||
jnz no_hd_load
|
||
cmp dx, 'RD'
|
||
jnz no_hd_load
|
||
mov word [cs:bx_from_load], bx ; {SPraid}[13.03.2007]
|
||
no_hd_load:
|
||
|
||
; set up stack
|
||
mov ax, 3000h
|
||
mov ss, ax
|
||
mov sp, 0EC00h
|
||
; set up segment registers
|
||
push cs
|
||
pop ds
|
||
push cs
|
||
pop es
|
||
end if
|
||
|
||
; set videomode
|
||
mov ax, 3
|
||
int 0x10
|
||
|
||
if lang eq ru
|
||
; Load & set russian VGA font (RU.INC)
|
||
mov bp, RU_FNT1 ; RU_FNT1 - First part
|
||
mov bx, 1000h ; 768 bytes
|
||
mov cx, 30h ; 48 symbols
|
||
mov dx, 80h ; 128 - position of first symbol
|
||
mov ax, 1100h
|
||
int 10h
|
||
|
||
mov bp, RU_FNT2 ; RU_FNT2 -Second part
|
||
mov bx, 1000h ; 512 bytes
|
||
mov cx, 20h ; 32 symbols
|
||
mov dx, 0E0h ; 224 - position of first symbol
|
||
mov ax, 1100h
|
||
int 10h
|
||
; End set VGA russian font
|
||
else if lang eq et
|
||
mov bp, ET_FNT ; ET_FNT1
|
||
mov bx, 1000h ;
|
||
mov cx, 255 ; 256 symbols
|
||
xor dx, dx ; 0 - position of first symbol
|
||
mov ax, 1100h
|
||
int 10h
|
||
end if
|
||
|
||
; draw frames
|
||
push 0xb800
|
||
pop es
|
||
xor di, di
|
||
mov ah, 1*16+15
|
||
|
||
; draw top
|
||
mov si, d80x25_top
|
||
mov cx, d80x25_top_num * 80
|
||
@@:
|
||
lodsb
|
||
stosw
|
||
loop @b
|
||
; draw spaces
|
||
mov si, space_msg
|
||
mov dx, 25 - d80x25_top_num - d80x25_bottom_num
|
||
dfl1:
|
||
push si
|
||
mov cx, 80
|
||
@@:
|
||
lodsb
|
||
stosw
|
||
loop @b
|
||
pop si
|
||
dec dx
|
||
jnz dfl1
|
||
; draw bottom
|
||
mov si, d80x25_bottom
|
||
mov cx, d80x25_bottom_num * 80
|
||
@@:
|
||
lodsb
|
||
stosw
|
||
loop @b
|
||
|
||
mov byte [space_msg+80], 0 ; now space_msg is null terminated
|
||
|
||
_setcursor d80x25_top_num,0
|
||
|
||
|
||
; TEST FOR 386+
|
||
|
||
mov bx, 0x4000
|
||
pushf
|
||
pop ax
|
||
mov dx, ax
|
||
xor ax, bx
|
||
push ax
|
||
popf
|
||
pushf
|
||
pop ax
|
||
and ax, bx
|
||
and dx, bx
|
||
cmp ax, dx
|
||
jnz cpugood
|
||
mov si, not386
|
||
sayerr:
|
||
call print
|
||
jmp $
|
||
cpugood:
|
||
|
||
push 0
|
||
popf
|
||
sti
|
||
|
||
; set up esp
|
||
movzx esp, sp
|
||
|
||
push 0
|
||
pop es
|
||
|
||
mov al, 0xf6 ; Сброс клавиатуры, разрешить сканирование
|
||
out 0x60, al
|
||
xor cx, cx
|
||
wait_loop: ; variant 2
|
||
; reading state of port of 8042 controller
|
||
in al, 64h
|
||
and al, 00000010b ; ready flag
|
||
; wait until 8042 controller is ready
|
||
loopnz wait_loop
|
||
|
||
;;;/diamond today 5.02.2008
|
||
; set keyboard typematic rate & delay
|
||
mov al, 0xf3
|
||
out 0x60, al
|
||
xor cx, cx
|
||
@@:
|
||
in al, 64h
|
||
test al, 2
|
||
loopnz @b
|
||
mov al, 0
|
||
out 0x60, al
|
||
xor cx, cx
|
||
@@:
|
||
in al, 64h
|
||
test al, 2
|
||
loopnz @b
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
; --------------- APM ---------------------
|
||
and word [es:BOOT_APM_VERSION], 0 ; ver = 0.0 (APM not found)
|
||
mov ax, 0x5300
|
||
xor bx, bx
|
||
int 0x15
|
||
jc apm_end ; APM not found
|
||
test cx, 2
|
||
jz apm_end ; APM 32-bit protected-mode interface not supported
|
||
mov [es:BOOT_APM_VERSION], ax ; Save APM Version
|
||
mov [es:BOOT_APM_FLAGS], cx ; Save APM flags
|
||
|
||
; Write APM ver ----
|
||
and ax, 0xf0f
|
||
add ax, '00'
|
||
mov si, msg_apm
|
||
mov [si + 5], ah
|
||
mov [si + 7], al
|
||
_setcursor 0, 3
|
||
call printplain
|
||
; ------------------
|
||
|
||
mov ax, 0x5304 ; Disconnect interface
|
||
xor bx, bx
|
||
int 0x15
|
||
mov ax, 0x5303 ; Connect 32 bit mode interface
|
||
xor bx, bx
|
||
int 0x15
|
||
|
||
mov [es:BOOT_APM_ENTRY], ebx
|
||
mov [es:BOOT_APM_CODE_32], ax
|
||
mov [es:BOOT_APM_CODE_16], cx
|
||
mov [es:BOOT_APM_DATA_16], dx
|
||
|
||
apm_end:
|
||
_setcursor d80x25_top_num, 0
|
||
|
||
if ~ defined extended_primary_loader
|
||
;CHECK current of code
|
||
cmp [cfgmanager.loader_block], -1
|
||
jz noloaderblock
|
||
les bx, [cfgmanager.loader_block]
|
||
cmp byte [es:bx], 1
|
||
mov si, loader_block_error
|
||
jnz sayerr
|
||
push 0
|
||
pop es
|
||
end if
|
||
|
||
noloaderblock:
|
||
; DISPLAY VESA INFORMATION
|
||
call print_vesa_info
|
||
call calc_vmodes_table
|
||
call check_first_parm ;check and enable cursor_pos
|
||
|
||
; \begin{diamond}[30.11.2005]
|
||
cfgmanager:
|
||
; settings:
|
||
; a) preboot_graph = graphical mode
|
||
; preboot_gprobe = probe this mode?
|
||
; b) preboot_biosdisk = use BIOS disks through V86 emulation? // (earlier was: preboot_dma = use DMA access?)
|
||
; c) preboot_debug = duplicates kernel debug output to the screen // (earlier was: preboot_vrrm = use VRR?)
|
||
; // VRR is an obsolete functionality, used only with CRT monitors: increase display frequency by reducing screen resolution
|
||
; d) preboot_launcher = start the first app (right now it's LAUNCHER) after kernel is loaded?
|
||
; e) preboot_device = from where to boot?
|
||
|
||
; determine default settings
|
||
if ~ defined extended_primary_loader
|
||
mov [.bSettingsChanged], 0
|
||
end if
|
||
|
||
;.preboot_gr_end:
|
||
mov di, preboot_device
|
||
; if image in memory is present and [preboot_device] is uninitialized,
|
||
; set it to use this preloaded image
|
||
cmp byte [di], 0
|
||
jnz .preboot_device_inited
|
||
if defined extended_primary_loader
|
||
inc byte [di]
|
||
cmp byte [bootdevice], 'f' ; floppy?
|
||
jz .preboot_device_inited
|
||
inc byte [di]
|
||
else
|
||
cmp [.loader_block], -1
|
||
jz @f
|
||
les bx, [.loader_block]
|
||
test byte [es:bx+1], 1
|
||
jz @f
|
||
mov byte [di], 3
|
||
jmp .preboot_device_inited
|
||
@@:
|
||
; otherwise, set [preboot_device] to 1 (default value - boot from floppy)
|
||
mov byte [di], 1
|
||
end if
|
||
.preboot_device_inited:
|
||
; following 4 lines set variables to 1 if its current value is 0
|
||
cmp byte [di+preboot_dma-preboot_device], 1
|
||
adc byte [di+preboot_dma-preboot_device], 0
|
||
cmp byte [di+preboot_launcher-preboot_device], 1 ; Start LAUNCHER by default
|
||
adc byte [di+preboot_launcher-preboot_device], 0
|
||
; cmp byte [di+preboot_biosdisk-preboot_device], 1
|
||
; adc byte [di+preboot_biosdisk-preboot_device], 0
|
||
;; default value for VRR is OFF
|
||
; cmp byte [di+preboot_vrrm-preboot_device], 0
|
||
; jnz @f
|
||
; mov byte [di+preboot_vrrm-preboot_device], 2
|
||
;@@:
|
||
; notify user
|
||
_setcursor 5,2
|
||
|
||
mov si, linef
|
||
call printplain
|
||
mov si, start_msg
|
||
call print
|
||
mov si, time_msg
|
||
call print
|
||
; get start time
|
||
call .gettime
|
||
mov [.starttime], eax
|
||
mov word [.timer], .newtimer
|
||
mov word [.timer+2], cs
|
||
.printcfg:
|
||
|
||
_setcursor 9,0
|
||
mov si, current_cfg_msg
|
||
call print
|
||
mov si, curvideo_msg
|
||
call print
|
||
|
||
call draw_current_vmode
|
||
|
||
mov si, usebd_msg
|
||
cmp [preboot_biosdisk], 1
|
||
call .say_on_off
|
||
; mov si, vrrm_msg
|
||
; cmp [preboot_vrrm], 1
|
||
; call .say_on_off
|
||
mov si, debug_mode_msg
|
||
cmp [preboot_debug], 1
|
||
call .say_on_off
|
||
mov si, launcher_msg
|
||
cmp [preboot_launcher], 1
|
||
call .say_on_off
|
||
mov si, preboot_device_msg
|
||
call print
|
||
mov al, [preboot_device]
|
||
if defined extended_primary_loader
|
||
and eax, 3
|
||
else
|
||
and eax, 7
|
||
end if
|
||
mov si, [preboot_device_msgs+eax*2]
|
||
call printplain
|
||
.show_remarks:
|
||
; show remarks in gray color
|
||
mov di, ((21-num_remarks)*80 + 2)*2
|
||
push 0xB800
|
||
pop es
|
||
mov cx, num_remarks
|
||
mov si, remarks
|
||
.write_remarks:
|
||
lodsw
|
||
push si
|
||
xchg ax, si
|
||
mov ah, 1*16+7 ; background: blue (1), foreground: gray (7)
|
||
push di
|
||
.write_remark:
|
||
lodsb
|
||
test al, al
|
||
jz @f
|
||
stosw
|
||
jmp .write_remark
|
||
@@:
|
||
pop di
|
||
pop si
|
||
add di, 80*2
|
||
loop .write_remarks
|
||
.wait:
|
||
_setcursor 25,0 ; out of screen
|
||
; set timer interrupt handler
|
||
cli
|
||
push 0
|
||
pop es
|
||
push dword [es:8*4]
|
||
pop dword [.oldtimer]
|
||
push dword [.timer]
|
||
pop dword [es:8*4]
|
||
; mov eax, [es:8*4]
|
||
; mov [.oldtimer], eax
|
||
; mov eax, [.timer]
|
||
; mov [es:8*4], eax
|
||
sti
|
||
; wait for keypressed
|
||
xor ax, ax
|
||
int 16h
|
||
push ax
|
||
; restore timer interrupt
|
||
; push 0
|
||
; pop es
|
||
mov eax, [.oldtimer]
|
||
mov [es:8*4], eax
|
||
mov [.timer], eax
|
||
|
||
_setcursor 7,0
|
||
mov si, space_msg
|
||
call printplain
|
||
; clear remarks and restore normal attributes
|
||
push es
|
||
mov di, ((21-num_remarks)*80 + 2)*2
|
||
push 0xB800
|
||
pop es
|
||
mov cx, num_remarks
|
||
mov ax, ' ' + (1*16 + 15)*100h
|
||
@@:
|
||
push cx
|
||
mov cx, 76
|
||
rep stosw
|
||
pop cx
|
||
add di, 4*2
|
||
loop @b
|
||
pop es
|
||
pop ax
|
||
; switch on key
|
||
cmp al, 13
|
||
jz .continue
|
||
or al, 20h
|
||
cmp al, 'a' ; select graphical mode
|
||
jz .change_a
|
||
cmp al, 'q' ; Trick to make 'A' key on azerty keyboard work
|
||
je .change_a
|
||
cmp al, 'b' ; use BIOS disks? // (selecting YES will make BIOS disks visible as /bd)
|
||
jz .change_b
|
||
cmp al, 'c' ; load kernel in debug mode? // (earlier was: use VRR?)
|
||
jz .change_c
|
||
cmp al, 'd' ; start launcher after kernel is loaded?
|
||
jz .change_d
|
||
cmp al, 'e' ; select boot origin
|
||
jnz .show_remarks
|
||
; e) preboot_device = from where to boot?
|
||
if defined extended_primary_loader
|
||
_ask_question bdev,'12',preboot_device ; range accepted for answer: 1-2
|
||
else
|
||
_ask_question bdev,'14',preboot_device ; range accepted for answer: 1-4
|
||
end if
|
||
_setcursor 14,0
|
||
|
||
.d:
|
||
if ~ defined extended_primary_loader
|
||
mov [.bSettingsChanged], 1
|
||
end if
|
||
.esc_pressed:
|
||
call clear_vmodes_table ;clear vmodes_table
|
||
jmp .printcfg
|
||
|
||
.change_a:
|
||
call clear_vmodes_table ;clear vmodes_table
|
||
|
||
mov si, word [cursor_pos]
|
||
mov word [cursor_pos_old], si
|
||
.loops:
|
||
call draw_vmodes_table
|
||
_setcursor 25,0 ; out of screen
|
||
xor ax, ax
|
||
int 0x16
|
||
; call clear_table_cursor ;clear current position of cursor
|
||
|
||
mov si, word [cursor_pos]
|
||
|
||
cmp al, 27 ; If ESC was pressed, do not change the value
|
||
jnz @f ; Just exit the resolution selection box
|
||
|
||
mov si, word [cursor_pos_old]
|
||
mov word [cursor_pos], si
|
||
jmp .esc_pressed
|
||
@@:
|
||
cmp ah, 0x48;x,0x48E0 ; up
|
||
jne .down
|
||
cmp si, modes_table
|
||
jbe .loops
|
||
sub word [cursor_pos], size_of_step
|
||
jmp .loops
|
||
|
||
.down:
|
||
cmp ah, 0x50;x,0x50E0 ; down
|
||
jne .pgup
|
||
cmp word[es:si+10], -1
|
||
je .loops
|
||
add word [cursor_pos], size_of_step
|
||
jmp .loops
|
||
|
||
.pgup:
|
||
cmp ah, 0x49 ; page up
|
||
jne .pgdn
|
||
sub si, size_of_step*long_v_table
|
||
cmp si, modes_table
|
||
jae @f
|
||
mov si, modes_table
|
||
@@:
|
||
mov word [cursor_pos], si
|
||
mov si, word [home_cursor]
|
||
sub si, size_of_step*long_v_table
|
||
cmp si, modes_table
|
||
jae @f
|
||
mov si, modes_table
|
||
@@:
|
||
mov word [home_cursor], si
|
||
jmp .loops
|
||
|
||
.pgdn:
|
||
cmp ah, 0x51 ; page down
|
||
jne .enter
|
||
mov ax, [end_cursor]
|
||
add si, size_of_step*long_v_table
|
||
cmp si, ax
|
||
jb @f
|
||
mov si, ax
|
||
sub si, size_of_step
|
||
@@:
|
||
mov word [cursor_pos], si
|
||
mov si, word [home_cursor]
|
||
sub ax, size_of_step*long_v_table
|
||
add si, size_of_step*long_v_table
|
||
cmp si, ax
|
||
jb @f
|
||
mov si, ax
|
||
@@:
|
||
mov word [home_cursor], si
|
||
jmp .loops
|
||
|
||
.enter:
|
||
cmp al, 0x0D;x,0x1C0D ; enter
|
||
jne .loops
|
||
push word [cursor_pos]
|
||
pop bp
|
||
push word [es:bp]
|
||
pop word [x_save]
|
||
push word [es:bp+2]
|
||
pop word [y_save]
|
||
push word [es:bp+6]
|
||
pop word [number_vm]
|
||
mov word [preboot_graph], bp ;save choose
|
||
|
||
jmp .d
|
||
|
||
.change_b: ; b) preboot_biosdisk = use BIOS disks through V86 emulation?
|
||
; _setcursor 16,0
|
||
; mov si, ask_dma // (earlier was: preboot_dma = use DMA access?)
|
||
; call print
|
||
; mov bx, '13' ; range accepted for answer: 1-3
|
||
; call getkey
|
||
; mov [preboot_dma], al
|
||
_ask_question ask_bd,'12',preboot_biosdisk ; range accepted for answer: 1-2
|
||
_setcursor 11,0
|
||
jmp .d
|
||
;.change_c: ; // VRR is an obsolete functionality, used only with CRT monitors
|
||
; _setcursor 16,0
|
||
; mov si, vrrmprint
|
||
; call print
|
||
; mov bx, '12' ; range accepted for answer: 1-2
|
||
; call getkey
|
||
; mov [preboot_vrrm], al
|
||
; _setcursor 12,0
|
||
; jmp .d
|
||
.change_c: ; c) preboot_debug = duplicates kernel debug output to the screen
|
||
_ask_question ask_debug,'12',preboot_debug ; range accepted for answer: 1-2
|
||
_setcursor 12,0
|
||
jmp .d
|
||
.change_d: ; d) preboot_launcher = start the first app (right now it's LAUNCHER) after kernel is loaded?
|
||
_ask_question ask_launcher,'12',preboot_launcher ; range accepted for answer: 1-2
|
||
_setcursor 13,0
|
||
jmp .d
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
.say_on_off:
|
||
pushf
|
||
call print
|
||
mov si, on_msg
|
||
popf
|
||
jz @f
|
||
mov si, off_msg
|
||
@@:
|
||
jmp printplain
|
||
; novesa and vervesa strings are not used at the moment of executing this code
|
||
virtual at novesa
|
||
.oldtimer dd ?
|
||
.starttime dd ?
|
||
if ~ defined extended_primary_loader
|
||
.bSettingsChanged db ?
|
||
end if
|
||
.timer dd ?
|
||
end virtual
|
||
if ~ defined extended_primary_loader
|
||
.loader_block dd -1
|
||
end if
|
||
.gettime:
|
||
mov ah, 0
|
||
int 1Ah
|
||
xchg ax, cx
|
||
shl eax, 10h
|
||
xchg ax, dx
|
||
ret
|
||
.newtimer:
|
||
push ds
|
||
push cs
|
||
pop ds
|
||
pushf
|
||
call [.oldtimer]
|
||
pushad
|
||
call .gettime
|
||
sub eax, [.starttime]
|
||
if defined extended_primary_loader
|
||
sub ax, [preboot_timeout]
|
||
else
|
||
sub ax, 18*5
|
||
end if
|
||
jae .timergo
|
||
neg ax
|
||
add ax, 18-1
|
||
mov bx, 18
|
||
xor dx, dx
|
||
div bx
|
||
if lang eq ru
|
||
; подождите 5 секунд, 4/3/2 секунды, 1 секунду
|
||
cmp al, 5
|
||
mov cl, ' '
|
||
jae @f
|
||
cmp al, 1
|
||
mov cl, 0xE3 ; 'у' in cp866
|
||
jz @f
|
||
mov cl, 0xEB ; 'ы' in cp866
|
||
@@:
|
||
mov [time_str+9], cl
|
||
else if lang eq et
|
||
cmp al, 1
|
||
ja @f
|
||
mov byte [time_str+9], ' '
|
||
mov byte [time_str+10], ' '
|
||
@@:
|
||
else if lang eq sp
|
||
; esperar 5/4/3/2 segundos, 1 segundo
|
||
cmp al, 1
|
||
mov cl, 's'
|
||
ja @f
|
||
mov cl, ' '
|
||
@@:
|
||
mov [time_str+10], cl
|
||
else
|
||
; wait 5/4/3/2 seconds, 1 second
|
||
cmp al, 1
|
||
mov cl, 's'
|
||
ja @f
|
||
mov cl, ' '
|
||
@@:
|
||
mov [time_str+9], cl
|
||
end if
|
||
add al, '0'
|
||
mov [time_str+1], al
|
||
mov si, time_msg
|
||
_setcursor 7,0
|
||
call print
|
||
_setcursor 25,0
|
||
popad
|
||
pop ds
|
||
iret
|
||
.timergo:
|
||
push 0
|
||
pop es
|
||
mov eax, [.oldtimer]
|
||
mov [es:8*4], eax
|
||
mov sp, 0EC00h
|
||
.continue:
|
||
sti
|
||
_setcursor 6,0
|
||
mov si, space_msg
|
||
call printplain
|
||
call printplain
|
||
_setcursor 6,0
|
||
mov si, loading_msg
|
||
call print
|
||
_setcursor 16,0
|
||
if ~ defined extended_primary_loader
|
||
cmp [.bSettingsChanged], 0
|
||
jz .load
|
||
cmp [.loader_block], -1
|
||
jz .load
|
||
les bx, [.loader_block]
|
||
mov eax, [es:bx+3]
|
||
push ds
|
||
pop es
|
||
test eax, eax
|
||
jz .load
|
||
push eax
|
||
mov si, save_quest
|
||
call print
|
||
.waityn:
|
||
mov ah, 0
|
||
int 16h
|
||
or al, 20h
|
||
cmp al, 'n'
|
||
jz .loadc
|
||
if lang eq sp
|
||
cmp al, 's'
|
||
else
|
||
cmp al, 'y'
|
||
end if
|
||
jnz .waityn
|
||
call putchar
|
||
mov byte [space_msg+80], 186
|
||
|
||
pop eax
|
||
push cs
|
||
push .cont
|
||
push eax
|
||
retf ;call back
|
||
.loadc:
|
||
pop eax
|
||
.cont:
|
||
push cs
|
||
pop ds
|
||
mov si, space_msg
|
||
mov byte [si+80], 0
|
||
_setcursor 16,0
|
||
call printplain
|
||
_setcursor 16,0
|
||
.load:
|
||
end if
|
||
; \end{diamond}[02.12.2005]
|
||
|
||
; ASK GRAPHICS MODE
|
||
|
||
call set_vmode
|
||
|
||
; GRAPHICS ACCELERATION
|
||
; force yes
|
||
mov [es:BOOT_MTRR], byte 1
|
||
|
||
; DMA ACCESS TO HD
|
||
|
||
mov al, [preboot_dma]
|
||
mov [es:BOOT_DMA], al
|
||
|
||
;; VRR_M USE
|
||
;
|
||
; mov al,[preboot_vrrm]
|
||
; mov [es:BOOT_VRR], al ;// 0x9030
|
||
|
||
; Set kernel DEBUG mode - if nonzero, duplicates debug output to the screen.
|
||
mov al, [preboot_debug]
|
||
mov [es:BOOT_DEBUG_PRINT], al ;// 0x901E
|
||
|
||
; Start the first app (right now it's LAUNCHER) after kernel is loaded?
|
||
mov al, [preboot_launcher]
|
||
mov [es:BOOT_LAUNCHER_START], al ;// 0x901D
|
||
|
||
; BOOT DEVICE
|
||
|
||
mov al, [preboot_device]
|
||
dec al
|
||
mov [boot_dev], al
|
||
|
||
; GET MEMORY MAP
|
||
include '../detect/biosmem.inc'
|
||
|
||
; READ DISKETTE TO MEMORY
|
||
|
||
cmp [boot_dev], 0
|
||
jne no_sys_on_floppy
|
||
mov si, diskload
|
||
call print
|
||
xor ax, ax ; reset drive
|
||
xor dx, dx
|
||
int 0x13
|
||
; do we boot from CD-ROM?
|
||
mov ah, 41h
|
||
mov bx, 55AAh
|
||
xor dx, dx
|
||
int 0x13
|
||
jc .nocd
|
||
cmp bx, 0AA55h
|
||
jnz .nocd
|
||
mov ah, 48h
|
||
push ds
|
||
push es
|
||
pop ds
|
||
mov si, 0xa000
|
||
mov word [si], 30
|
||
int 0x13
|
||
pop ds
|
||
jc .nocd
|
||
push ds
|
||
lds si, [es:si+26]
|
||
test byte [ds:si+10], 40h
|
||
pop ds
|
||
jz .nocd
|
||
; yes - read all floppy by 18 sectors
|
||
|
||
; TODO: !!!! read only first sector and set variables !!!!!
|
||
; ...
|
||
; TODO: !!! then read flippy image track by track
|
||
|
||
mov cx, 0x0001 ; startcyl,startsector
|
||
.a1:
|
||
push cx dx
|
||
mov al, 18
|
||
mov bx, 0xa000
|
||
call boot_read_floppy
|
||
mov si, movedesc
|
||
push es
|
||
push ds
|
||
pop es
|
||
mov cx, 256*18
|
||
mov ah, 0x87
|
||
int 0x15
|
||
pop es
|
||
pop dx cx
|
||
test ah, ah
|
||
jnz sayerr_floppy
|
||
add dword [si+8*3+2], 512*18
|
||
inc dh
|
||
cmp dh, 2
|
||
jnz .a1
|
||
mov dh, 0
|
||
inc ch
|
||
cmp ch, 80
|
||
jae ok_sys_on_floppy
|
||
pusha
|
||
mov al, ch
|
||
shr ch, 2
|
||
add al, ch
|
||
aam
|
||
xchg al, ah
|
||
add ax, '00'
|
||
mov si, pros
|
||
mov [si], ax
|
||
call printplain
|
||
popa
|
||
jmp .a1
|
||
.nocd:
|
||
; no - read only used sectors from floppy
|
||
; now load floppy image to memory
|
||
; at first load boot sector and first FAT table
|
||
|
||
; read only first sector and fill variables
|
||
mov cx, 0x0001 ; first logical sector
|
||
xor dx, dx ; head = 0, drive = 0 (a:)
|
||
mov al, 1 ; read one sector
|
||
mov bx, 0xB000 ; es:bx -> data area
|
||
call boot_read_floppy
|
||
; fill the necessary parameters to work with a floppy
|
||
mov ax, word [es:bx+24]
|
||
mov word [BPB_SecPerTrk], ax
|
||
mov ax, word [es:bx+26]
|
||
mov word [BPB_NumHeads], ax
|
||
mov ax, word [es:bx+17]
|
||
mov word [BPB_RootEntCnt], ax
|
||
mov ax, word [es:bx+14]
|
||
mov word [BPB_RsvdSecCnt], ax
|
||
mov ax, word [es:bx+19]
|
||
mov word [BPB_TotSec16], ax
|
||
mov al, byte [es:bx+13]
|
||
mov byte [BPB_SecPerClus], al
|
||
mov al, byte [es:bx+16]
|
||
mov byte [BPB_NumFATs], al
|
||
;<Lrz> 18.11.2008
|
||
mov ax, word [es:bx+22]
|
||
mov word [BPB_FATSz16], ax
|
||
mov cx, word [es:bx+11]
|
||
mov word [BPB_BytsPerSec], cx
|
||
|
||
; count of clusters in FAT12 ((size_of_FAT*2)/3)
|
||
; mov ax, word [BPB_FATSz16]
|
||
; mov cx, word [BPB_BytsPerSec]
|
||
;end <Lrz> 18.11.2008
|
||
xor dx, dx
|
||
mul cx
|
||
shl ax, 1
|
||
mov cx, 3
|
||
div cx ; now ax - number of clusters in FAT12
|
||
mov word [end_of_FAT], ax
|
||
|
||
; load first FAT table
|
||
mov cx, 0x0002 ; startcyl,startsector ; TODO!!!!!
|
||
xor dx, dx ; starthead,drive
|
||
mov al, byte [BPB_FATSz16] ; no of sectors to read
|
||
add bx, word [BPB_BytsPerSec] ; es:bx -> data area
|
||
call boot_read_floppy
|
||
mov bx, 0xB000
|
||
|
||
; and copy them to extended memory
|
||
mov si, movedesc
|
||
mov [si+8*2+3], bh ; from
|
||
|
||
mov ax, word [BPB_BytsPerSec]
|
||
shr ax, 1 ; words per sector
|
||
mov cx, word [BPB_RsvdSecCnt]
|
||
add cx, word [BPB_FATSz16]
|
||
mul cx
|
||
push ax ; save to stack count of words in boot+FAT
|
||
xchg ax, cx
|
||
|
||
push es
|
||
push ds
|
||
pop es
|
||
mov ah, 0x87
|
||
int 0x15
|
||
pop es
|
||
test ah, ah
|
||
jz @f
|
||
sayerr_floppy:
|
||
mov dx, 0x3f2
|
||
mov al, 0
|
||
out dx, al
|
||
sayerr_memmove:
|
||
mov si, memmovefailed
|
||
jmp sayerr_plain
|
||
@@:
|
||
pop ax ; restore from stack count of words in boot+FAT
|
||
shl ax, 1 ; make bytes count from count of words
|
||
and eax, 0ffffh
|
||
add dword [si+8*3+2], eax
|
||
|
||
; copy first FAT to second copy
|
||
; TODO: BPB_NumFATs !!!!!
|
||
add bx, word [BPB_BytsPerSec] ; !!! TODO: may be need multiply by BPB_RsvdSecCnt !!!
|
||
mov byte [si+8*2+3], bh ; bx - begin of FAT
|
||
|
||
mov ax, word [BPB_BytsPerSec]
|
||
shr ax, 1 ; words per sector
|
||
mov cx, word [BPB_FATSz16]
|
||
mul cx
|
||
mov cx, ax ; cx - count of words in FAT
|
||
|
||
push es
|
||
push ds
|
||
pop es
|
||
mov ah, 0x87
|
||
int 0x15
|
||
pop es
|
||
test ah, ah
|
||
jnz sayerr_floppy
|
||
|
||
mov ax, cx
|
||
shl ax, 1
|
||
and eax, 0ffffh ; ax - count of bytes in FAT
|
||
add dword [si+8*3+2], eax
|
||
|
||
; reading RootDir
|
||
; TODO: BPB_NumFATs
|
||
add bx, ax
|
||
add bx, 100h
|
||
and bx, 0ff00h ; bx - place in buffer to write RootDir
|
||
push bx
|
||
|
||
mov bx, word [BPB_BytsPerSec]
|
||
shr bx, 5 ; divide bx by 32
|
||
mov ax, word [BPB_RootEntCnt]
|
||
xor dx, dx
|
||
div bx
|
||
push ax ; ax - count of RootDir sectors
|
||
|
||
mov ax, word [BPB_FATSz16]
|
||
xor cx, cx
|
||
mov cl, byte [BPB_NumFATs]
|
||
mul cx
|
||
add ax, word [BPB_RsvdSecCnt] ; ax - first sector of RootDir
|
||
|
||
mov word [FirstDataSector], ax
|
||
pop bx
|
||
push bx
|
||
add word [FirstDataSector], bx ; Begin of data region of floppy
|
||
|
||
; read RootDir
|
||
call conv_abs_to_THS
|
||
pop ax
|
||
pop bx ; place in buffer to write
|
||
push ax
|
||
call boot_read_floppy ; read RootDir into buffer
|
||
; copy RootDir
|
||
mov byte [si+8*2+3], bh ; from buffer
|
||
pop ax ; ax = count of RootDir sectors
|
||
mov cx, word [BPB_BytsPerSec]
|
||
mul cx
|
||
shr ax, 1
|
||
mov cx, ax ; count of words to copy
|
||
push es
|
||
push ds
|
||
pop es
|
||
mov ah, 0x87
|
||
int 0x15
|
||
pop es
|
||
|
||
mov ax, cx
|
||
shl ax, 1
|
||
and eax, 0ffffh ; ax - count of bytes in RootDir
|
||
add dword [si+8*3+2], eax ; add count of bytes copied
|
||
|
||
; Reading data clusters from floppy
|
||
mov byte [si+8*2+3], bh
|
||
push bx
|
||
|
||
mov di, 2 ; First data cluster
|
||
.read_loop:
|
||
mov bx, di
|
||
shr bx, 1 ; bx+di = di*1.5
|
||
jnc .even
|
||
test word [es:bx+di+0xB200], 0xFFF0 ; TODO: may not be 0xB200 !!!
|
||
jmp @f
|
||
.even:
|
||
test word [es:bx+di+0xB200], 0xFFF ; TODO: may not be 0xB200 !!!
|
||
|
||
@@:
|
||
jz .skip
|
||
; read cluster di
|
||
;.read:
|
||
;conv cluster di to abs. sector ax
|
||
; ax = (N-2) * BPB_SecPerClus + FirstDataSector
|
||
mov ax, di
|
||
sub ax, 2
|
||
xor bx, bx
|
||
mov bl, byte [BPB_SecPerClus]
|
||
mul bx
|
||
add ax, word [FirstDataSector]
|
||
call conv_abs_to_THS
|
||
pop bx
|
||
push bx
|
||
mov al, byte [BPB_SecPerClus] ; number of sectors in cluster
|
||
call boot_read_floppy
|
||
push es
|
||
push ds
|
||
pop es
|
||
pusha
|
||
;
|
||
mov ax, word [BPB_BytsPerSec]
|
||
xor cx, cx
|
||
mov cl, byte [BPB_SecPerClus]
|
||
mul cx
|
||
shr ax, 1 ; ax = (BPB_BytsPerSec * BPB_SecPerClus)/2
|
||
mov cx, ax ; number of words to copy (count words in cluster)
|
||
;
|
||
mov ah, 0x87
|
||
int 0x15 ; copy data
|
||
test ah, ah
|
||
popa
|
||
pop es
|
||
jnz sayerr_floppy
|
||
; skip cluster di
|
||
.skip:
|
||
mov ax, word [BPB_BytsPerSec]
|
||
xor cx, cx
|
||
mov cl, byte [BPB_SecPerClus]
|
||
mul cx
|
||
and eax, 0ffffh ; ax - count of bytes in cluster
|
||
add dword [si+8*3+2], eax
|
||
|
||
mov ax, word [end_of_FAT] ; max cluster number
|
||
pusha
|
||
; draw percentage
|
||
; total clusters: ax
|
||
; read clusters: di
|
||
xchg ax, di
|
||
mov cx, 100
|
||
mul cx
|
||
div di
|
||
aam
|
||
xchg al, ah
|
||
add ax, '00'
|
||
mov si, pros
|
||
cmp [si], ax
|
||
jz @f
|
||
mov [si], ax
|
||
call printplain
|
||
@@:
|
||
popa
|
||
inc di
|
||
cmp di, word [end_of_FAT] ; max number of cluster
|
||
jnz .read_loop
|
||
pop bx ; clear stack
|
||
|
||
ok_sys_on_floppy:
|
||
mov si, backspace2
|
||
call printplain
|
||
mov si, okt
|
||
call printplain
|
||
no_sys_on_floppy:
|
||
xor ax, ax ; reset drive
|
||
xor dx, dx
|
||
int 0x13
|
||
mov dx, 0x3f2 ; floppy motor off
|
||
mov al, 0
|
||
out dx, al
|
||
|
||
if defined extended_primary_loader
|
||
cmp [boot_dev], 1
|
||
jne no_sys_from_primary
|
||
; load kolibri.img using callback from primary loader
|
||
and word [movedesc + 24 + 2], 0
|
||
mov byte [movedesc + 24 + 4], 10h
|
||
; read in blocks of 64K until file is fully loaded
|
||
mov ax, 1
|
||
.repeat:
|
||
mov di, image_file_struct
|
||
call [bootcallback]
|
||
push cs
|
||
pop ds
|
||
push cs
|
||
pop es
|
||
cmp bx, 1
|
||
ja sayerr_badsect
|
||
push bx
|
||
mov si, movedesc
|
||
and word [si + 16 + 2], 0
|
||
mov byte [si + 16 + 4], 4
|
||
mov ah, 87h
|
||
mov cx, 8000h
|
||
int 15h
|
||
pop bx
|
||
test ah, ah
|
||
jnz sayerr_memmove
|
||
inc byte [si + 24 + 4]
|
||
test bx, bx
|
||
jz no_sys_from_primary
|
||
mov ax, 2
|
||
jmp .repeat
|
||
no_sys_from_primary:
|
||
end if
|
||
|
||
; SET GRAPHICS
|
||
|
||
xor ax, ax
|
||
mov es, ax
|
||
|
||
mov ax, [es:BOOT_VESA_MODE] ; vga & 320x200
|
||
mov bx, ax
|
||
cmp ax, 0x13
|
||
je setgr
|
||
cmp ax, 0x12
|
||
je setgr
|
||
mov ax, 0x4f02 ; Vesa
|
||
setgr:
|
||
int 0x10
|
||
test ah, ah
|
||
mov si, fatalsel
|
||
jnz v_mode_error
|
||
; set mode 0x12 graphics registers:
|
||
cmp bx, 0x12
|
||
jne gmok2
|
||
|
||
mov al, 0x05
|
||
mov dx, 0x03ce
|
||
push dx
|
||
out dx, al ; select GDC mode register
|
||
mov al, 0x02
|
||
inc dx
|
||
out dx, al ; set write mode 2
|
||
|
||
mov al, 0x02
|
||
mov dx, 0x03c4
|
||
out dx, al ; select VGA sequencer map mask register
|
||
mov al, 0x0f
|
||
inc dx
|
||
out dx, al ; set mask for all planes 0-3
|
||
|
||
mov al, 0x08
|
||
pop dx
|
||
out dx, al ; select GDC bit mask register
|
||
; for writes to 0x03cf
|
||
gmok2:
|
||
push ds
|
||
pop es
|
||
|
||
sidt [cs:old_ints_h]
|
||
|
||
cli ; disable all irqs
|
||
mov al, 255 ; mask all irqs
|
||
out 0xa1, al
|
||
out 0x21, al
|
||
l.5:
|
||
in al, 0x64 ; Enable A20
|
||
test al, 2
|
||
jnz l.5
|
||
mov al, 0xD1
|
||
out 0x64, al
|
||
l.6:
|
||
in al, 0x64
|
||
test al, 2
|
||
jnz l.6
|
||
mov al, 0xDF
|
||
out 0x60, al
|
||
l.7:
|
||
in al, 0x64
|
||
test al, 2
|
||
jnz l.7
|
||
mov al, 0xFF
|
||
out 0x64, al
|
||
|