$Revision$ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; ;; Copyright (C) KolibriOS team 2004-2007. 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 ;; ;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;========================================================================== ; ; 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 cmp al, 0 jnz @b popa ret getkey: ; 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 int 16h cmp al, bl jb getkey cmp al, bh ja getkey push ax call putchar pop ax and ax, 0Fh jnz @f mov al, 10 @@: 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 } 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 mov si, badsect sayerr_plain: call printplain jmp $ @@: pop si ret ;========================================================================= ; ; 16 BIT CODE ; ;========================================================================= start_of_code: cld ; \begin{diamond}[02.12.2005] 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] cmp cx,'HA' ; по регистрам определяется загрузка с винта jnz no_hd_load cmp dx,'RD' jnz no_hd_load mov word [bx_from_load], bx ; {SPraid}[13.03.2007] jmp load_next no_hd_load: mov word [bx_from_load], 'r1' ; if work with floppy load_next: ; set up stack mov ax, 3000h mov ss, ax mov sp, 0EC00h ; set up segment registers push cs pop ds push cs pop es ; 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 mov dx,0h ; 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 cx, 25 - d80x25_top_num - d80x25_bottom_num dfl1: push cx push si mov cx, 80 @@: lodsb stosw loop @b pop si pop cx loop 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 and word [es:0x9031], 0 ; \begin{Mario79} ; find HDD IDE DMA PCI device ; check for PCI BIOS mov ax, 0xB101 int 0x1A jc .nopci cmp edx, 'PCI ' jnz .nopci ; find PCI class code ; class 1 = mass storage ; subclass 1 = IDE controller ; a) class 1, subclass 1, programming interface 0x80 mov ax, 0xB103 mov ecx, 1*10000h + 1*100h + 0x80 mov si, 0 ; device index = 0 int 0x1A jnc .found ; b) class 1, subclass 1, programming interface 0x8A mov ax, 0xB103 mov ecx, 1*10000h + 1*100h + 0x8A mov si, 0 ; device index = 0 int 0x1A jnc .found ; c) class 1, subclass 1, programming interface 0x85 mov ax, 0xB103 mov ecx, 1*10000h + 1*100h + 0x85 mov si, 0 int 0x1A jc .nopci .found: ; get memory base mov ax, 0xB10A mov di, 0x20 ; memory base is config register at 0x20 int 0x1A jc .nopci and cx, 0xFFF0 ; clear address decode type mov [es:0x9031], cx .nopci: ; \end{Mario79} 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 ; --------------- APM --------------------- push 0 pop es mov word [es : 0x9044], 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 : 0x9044], ax ; Save APM Version mov [es : 0x9046], 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 push 0 pop es mov [es:0x9040], ebx mov [es:0x9050], ax mov [es:0x9052], cx mov [es:0x9054], dx apm_end: _setcursor d80x25_top_num, 0 ; DISPLAY VESA INFORMATION push 0 pop es mov ax,0x4f00 mov di,0xa000 int 0x10 cmp ax,0x004f mov si, novesa jnz @f mov bx, word [es:di+0x12] shl ebx,16 mov [es:0x9050], ebx mov ax,[es:di+4] add ax,'0'*256+'0' mov si,vervesa mov [si+vervesa_off], ah mov [si+vervesa_off+2], al @@: call print ; \begin{diamond}[30.11.2005] cfgmanager: ; settings: ; a) preboot_graph = graphical mode ; preboot_gprobe = probe this mode? ; b) preboot_dma_write = use DMA write? ; c) preboot_vrrm = use VRR? ; d) preboot_device = from what boot? mov di, preboot_graph ; check bootloader block cmp [.loader_block], -1 jz .noloaderblock les bx, [.loader_block] cmp byte [es:bx], 1 mov si, loader_block_error jnz sayerr test byte [es:bx+1], 1 jz @f ; image in memory present cmp [di+preboot_device-preboot_graph], 0 jnz @f mov [di+preboot_device-preboot_graph], 3 @@: .noloaderblock: ; determine default settings mov [.bSettingsChanged], 0 cmp byte [di], 0 jnz .preboot_gr_end mov [di+preboot_gprobe-preboot_graph], 0 mov al, [vervesa+vervesa_off] cmp al, 'x' jz .novesa cmp al, '1' jz .vesa12 mov [di+preboot_gprobe-preboot_graph], 2 mov al, 3 jmp @f .vesa12: mov al, 7 jmp @f .novesa: mov al, 10 @@: mov [di], al .preboot_gr_end: cmp [di+preboot_dma_write-preboot_graph], 1 adc [di+preboot_dma_write-preboot_graph], 0 cmp [di+preboot_vrrm-preboot_graph], 1 adc [di+preboot_vrrm-preboot_graph], 0 cmp [di+preboot_device-preboot_graph], 1 adc [di+preboot_device-preboot_graph], 0 ; notify user mov si, linef call print 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 mov al, [preboot_graph] cmp al, 8 ja .pnovesa mov dl, al and eax, 3 mov si, [modes_msg+eax*2] call printplain mov si, modevesa20 cmp dl, 4 jbe @f mov si, modevesa12 @@: call printplain cmp dl, 4 ja .x mov si, probeno_msg cmp [preboot_gprobe], 2 jnz @f mov si, probeok_msg @@: call printplain .x: jmp .c .pnovesa: cmp al, 9 mov si, mode9 jz @b mov si, mode10 jmp @b .c: mov si, linef call printplain mov si, dma_msg cmp [preboot_dma_write], 1 call .say_on_off mov si, vrrm_msg cmp [preboot_vrrm], 1 call .say_on_off mov si, preboot_device_msg call print mov al, [preboot_device] and eax, 3 mov si, [preboot_device_msgs+eax*2] call printplain .wait: _setcursor 25,0 ; out of screen ; set timer interrupt handler cli push 0 pop es mov eax, [es:8*4] mov [.oldtimer], eax mov eax, [.timer] mov [es:8*4], eax sti ; wait for keypressed mov ah, 0 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 pop ax ; switch on key cmp al, 13 jz .continue or al, 20h cmp al, 'a' jz .change_a cmp al, 'b' jz .change_b cmp al, 'c' jz .change_c cmp al, 'd' jnz .wait _setcursor 15,0 mov si,bdev call print mov bx,'13' call getkey mov [preboot_device], al _setcursor 13,0 .d: mov [.bSettingsChanged], 1 mov si, space_msg call printplain _setcursor 15,0 mov cx, 6 @@: call printplain loop @b jmp .printcfg .change_a: _setcursor 15,0 mov si, gr_mode call printplain mov bx, '09' call getkey mov [preboot_graph], al cmp al, 4 ja @f mov si, probetext call printplain mov bx, '12' call getkey mov [preboot_gprobe], al @@: _setcursor 10,0 jmp .d .change_b: _setcursor 15,0 mov si, ask_dma call print mov bx, '12' call getkey mov [preboot_dma_write], al _setcursor 11,0 jmp .d .change_c: _setcursor 15,0 mov si, vrrmprint call print mov bx, '12' call getkey mov [preboot_vrrm], al _setcursor 12,0 jmp .d .say_on_off: pushf call print mov si, on_msg popf jz @f mov si, off_msg @@: call printplain ret ; novesa and vervesa strings are not used at the moment of executing this code virtual at novesa .oldtimer dd ? .starttime dd ? .bSettingsChanged db ? .timer dd ? end virtual .loader_block dd -1 .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] sub ax, 18*5 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, 'г' jz @f mov cl, 'л' @@: mov [time_str+9], cl else if lang eq et cmp al, 1 ja @f mov [time_str+9], ' ' mov [time_str+10],' ' @@: 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 15,0 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 cmp al, 'y' jnz .waityn call putchar mov byte [space_msg+80], 186 pop eax push cs push .cont push eax retf .loadc: pop eax .cont: push cs pop ds mov si, space_msg mov byte [si+80], 0 _setcursor 15,0 call printplain _setcursor 15,0 .load: ; \end{diamond}[02.12.2005] ; ASK GRAPHICS MODE movzx ax, [preboot_graph] push 0 pop es ; address is gr_table+6*(ax-1) add ax, ax lea si, [gr_table + eax + eax*2 - 6] mov bx,[si+0] mov cx,[si+2] mov dx,[si+4] cmp al, 9*2 mov al, 32 ; BPP jb @f mov [es:0x9000], al mov dword [es:0x9018], 0xFFFFFFFF; 0x800000 @@: mov [es:0x9008],bx mov [es:0x900A],cx mov [es:0x900C],dx test bh, bh jz nov ; USE DEFAULTS OR PROBE ; bx - mode : cx - x size : dx - y size cmp [preboot_gprobe], 1 jz noprobe mov bx,0x100 newprobe: inc bx cmp bx,0x17f mov si,prnotfnd jz sayerr probemore: push cx mov ax,0x4f01 mov cx,bx and cx,0xfff mov di,0xa000 int 0x10 pop cx test byte [es:di], 80h ; lfb? jz newprobe cmp [es:di+0x12], cx ; x size? jnz newprobe cmp [es:di+0x14], dx ; y size? jnz newprobe cmp byte [es:di+0x19], 32 ;24 jb newprobe ; add bx,0100000000000000b or bh, 40h mov [es:0x9008],bx noprobe: ; FIND VESA 2.0 LFB & BPP mov ax,0x4f01 mov cx,bx and cx,0xfff mov di,0xa000 int 0x10 ; LFB mov eax,[es:di+0x28] mov [es:0x9018],eax ; ---- vbe voodoo BytesPerLine equ 0x10 mov ax, [es:di+BytesPerLine] mov [es:0x9001],ax ; BPP mov al,byte [es:di+0x19] mov [es:0x9000],al nov: cmp al,24 mov si,bt24 jz bppl cmp al,32 mov si,bt32 jz bppl mov si,btns jmp sayerr bppl: call print ; FIND VESA 1.2 PM BANK SWITCH ADDRESS push es mov ax,0x4f0A xor bx, bx int 0x10 xor eax,eax mov ax,es shl eax,4 movzx ebx,di add eax,ebx mov bx,[es:di] add eax,ebx pop es mov [es:0x9014],eax ; GRAPHICS ACCELERATION ; force yes mov [es:0x901C], byte 1 ; DMA WRITE mov al, [preboot_dma_write] mov [es:0x901F],al ; VRR_M USE mov al,[preboot_vrrm] mov [es:0x9030],al mov [es:0x901E],byte 1 ; BOOT DEVICE mov al, [preboot_device] dec al mov [boot_dev],al ; 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 ; now load floppy image to memory ; at first load boot sector and first FAT table mov cx, 0x0001 ; startcyl,startsector xor dx, dx ; starthead,drive mov al, 1+9 ; no of sectors to read mov bx, 0xB000 ; es:bx -> data area call boot_read_floppy ; and copy them to extended memory mov si, movedesc mov [si+8*2+3], bh push es push ds pop es mov cx, 256*10 mov ah, 0x87 int 0x15 test ah, ah jz @f sayerr_floppy: mov dx, 0x3f2 mov al, 0 out dx, al mov si, memmovefailed jmp sayerr_plain @@: add dword [si+8*3+2], 512*10 ; copy FAT to second copy mov byte [si+8*2+3], 0xB2 mov cx, 256*9 mov ah, 0x87 int 0x15 pop es test ah, ah jnz sayerr_floppy add dword [si+8*3+2], 512*9 ; calculate total number of sectors to read mov ax, 1+9+14 ; boot+FAT+root mov di, 0xB203 .calc_loop: test word [es:di], 0xFFF jz @f inc ax @@: test word [es:di+1], 0xFFF0 jz @f inc ax @@: add di, 3 cmp di, 0xB200+1440*3 jb .calc_loop push ax mov bp, 1+9 ; already read sectors ; now read rest mov byte [si+8*2+3], 0xA0 mov di, 2-14 ; absolute sector-31 mov cx, 0x0002 ; cylinder=0, sector=2 mov dx, 0x0100 ; head=1, disk=0 .read_loop: ; determine whether sector must be read cmp di, 2 jl .read mov bx, di shr bx, 1 jnc .even test word [es:bx+di+0xB200], 0xFFF0 jmp @f .even: test word [es:bx+di+0xB200], 0xFFF @@: jz .skip .read: mov bx, 0xA000 mov al, 1 ; 1 sector call boot_read_floppy inc bp push es push ds pop es pusha mov cx, 256 mov ah, 0x87 int 0x15 test ah, ah popa pop es jnz sayerr_floppy .skip: add dword [si+8*3+2], 512 inc cx cmp cl, 19 jnz @f mov cl, 1 inc dh cmp dh, 2 jnz @f mov dh, 0 inc ch @@: pop ax push ax pusha ; draw percentage ; total sectors: ax ; read sectors: bp xchg ax, bp mov cx, 100 mul cx div bp 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, 2880-31 jnz .read_loop ; mov cx, 0x0001 ; startcyl,startsector ; xor dx, dx ; starthead,drive ; push word 80*2 ; read no of sect ; reads: ; pusha ; xor si,si ; newread: ; mov bx,0xa000 ; es:bx -> data area ; mov ax,0x0200+18 ; read, no of sectors to read ; int 0x13 ; test ah, ah ; jz goodread ; inc si ; cmp si,10 ; jnz newread ; mov si,badsect-0x10000 ;sayerr_plain: ; call printplain ; jmp $ ; goodread: ; ; move -> 1mb ; mov si,movedesc-0x10000 ; push es ; push ds ; pop es ; mov cx,256*18 ; mov ah,0x87 ; int 0x15 ; pop es ; ; test ah,ah ; was the move successfull ? ; je goodmove ; mov dx,0x3f2 ; floppy motor off ; mov al,0 ; out dx,al ; mov si,memmovefailed-0x10000 ; jmp sayerr_plain ; goodmove: ; ; add dword [movedesc-0x10000+0x18+2], 512*18 ; popa ; inc dh ; cmp dh,2 ; jnz bb2 ; mov dh,0 ; inc ch ; pusha ; print prosentage ; mov si,pros-0x10000 ; shr ch, 2 ; mov al, '5' ; test ch, 1 ; jnz @f ; mov al, '0' ;@@: ; mov [si+1], al ; shr ch, 1 ; add ch, '0' ; mov [si], ch ; call printplain ; popa ; bb2: ; pop ax ; dec ax ; push ax ; jnz reads ; readdone: ; pop ax 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 ; SET GRAPHICS xor ax, ax mov es, ax mov ax,[es:0x9008] ; 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 sayerr ; 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