Subversion Repositories Kolibri OS

Rev

Rev 3797 | Rev 3989 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
  4. ;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa      ;;
  5. ;; Distributed under terms of the GNU General Public License    ;;
  6. ;;                                                              ;;
  7. ;;  BOOTCODE.INC                                                ;;
  8. ;;                                                              ;;
  9. ;;  KolibriOS 16-bit loader,                                    ;;
  10. ;;                        based on bootcode for MenuetOS        ;;
  11. ;;                                                              ;;
  12. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  13.  
  14. $Revision: 3964 $
  15.  
  16.  
  17. ;==========================================================================
  18. ;
  19. ;                           16 BIT FUNCTIONS
  20. ;
  21. ;==========================================================================
  22.  
  23.  
  24. putchar:
  25. ; in: al=character
  26.         mov     ah, 0Eh
  27.         mov     bh, 0
  28.         int     10h
  29.         ret
  30.  
  31. print:
  32. ; in: si->string
  33.         mov     al, 186
  34.         call    putchar
  35.         mov     al, ' '
  36.         call    putchar
  37.  
  38. printplain:
  39. ; in: si->string
  40.         pusha
  41.         lodsb
  42. @@:
  43.         call    putchar
  44.         lodsb
  45.         test    al, al
  46.         jnz     @b
  47.         popa
  48.         ret
  49.  
  50. getkey:                         ; Use BIOS INT 16h to read a key from the keyboard
  51. ; get number in range [bl,bh] (bl,bh in ['0'..'9'])
  52. ; in: bx=range
  53. ; out: ax=digit (1..9, 10 for 0)
  54.         mov     ah, 0           ; If 'int 16h' is called with 'ah' equal to zero, the BIOS will not return control
  55.         int     16h             ; to the caller until a key is available in the system type ahead buffer. On return,
  56.         cmp     al, bl          ; 'al' contains the ASCII code for the key read from the buffer and 'ah' contains
  57.         jb      getkey          ; the keyboard scan code. Here we compare 'al' with the range of accepted characters.
  58.         cmp     al, bh          ; If the key pressed is not in the range, continue waiting for another key.
  59.         ja      getkey
  60.         push    ax              ; If the pressed key is in the accepted range, save it on the stack and echo to screen.
  61.         call    putchar
  62.         pop     ax
  63.         and     ax, 0Fh         ; ASCII code for '0' is 48 (110000b). 0F4=1111b. (110000b AND 1111b) = 0
  64.         jnz     @f              ; So if key '0' was entered, return 10 in 'ax'
  65.         mov     al, 10
  66. @@:
  67.         ret
  68.  
  69. setcursor:
  70. ; in: dl=column, dh=row
  71.         mov     ah, 2
  72.         mov     bh, 0
  73.         int     10h
  74.         ret
  75.  
  76. macro _setcursor row,column
  77. {
  78.         mov     dx, row*256 + column
  79.         call    setcursor
  80. }
  81.  
  82. boot_read_floppy:
  83.         push    si
  84.         xor     si, si
  85.         mov     ah, 2   ; read
  86. @@:
  87.         push    ax
  88.         int     0x13
  89.         pop     ax
  90.         jnc     @f
  91.         inc     si
  92.         cmp     si, 10
  93.         jb      @b
  94. sayerr_badsect:
  95.         mov     si, badsect
  96. sayerr_plain:
  97.         call    printplain
  98.         jmp     $
  99. @@:
  100.         pop     si
  101.         ret
  102.  
  103. ; convert abs. sector number (AX) to BIOS T:H:S
  104. ; sector number = (abs.sector%BPB_SecPerTrk)+1
  105. ; pre.track number = (abs.sector/BPB_SecPerTrk)
  106. ; head number = pre.track number%BPB_NumHeads
  107. ; track number = pre.track number/BPB_NumHeads
  108. ; Return: cl - sector number
  109. ;         ch - track number
  110. ;         dl - drive number (0 = a:)
  111. ;         dh - head number
  112. conv_abs_to_THS:
  113.         push    bx
  114.         mov     bx, word [BPB_SecPerTrk]
  115.         xor     dx, dx
  116.         div     bx
  117.         inc     dx
  118.         mov     cl, dl                          ; cl = sector number
  119.         mov     bx, word [BPB_NumHeads]
  120.         xor     dx, dx
  121.         div     bx
  122.         ; !!!!!!! ax = track number, dx = head number
  123.         mov     ch, al                          ; ch=track number
  124.         xchg    dh, dl                          ; dh=head number
  125.         mov     dl, 0                           ; dl=0 (drive 0 (a:))
  126.         pop     bx
  127.         retn
  128. ; needed variables
  129. BPB_SecPerTrk   dw      0                       ; sectors per track
  130. BPB_NumHeads    dw      0                       ; number of heads
  131. BPB_FATSz16     dw      0                       ; size of FAT
  132. BPB_RootEntCnt  dw      0                       ; count of root dir. entries
  133. BPB_BytsPerSec  dw      0                       ; bytes per sector
  134. BPB_RsvdSecCnt  dw      0                       ; number of reserved sectors
  135. BPB_TotSec16    dw      0                       ; count of the sectors on the volume
  136. BPB_SecPerClus  db      0                       ; number of sectors per cluster
  137. BPB_NumFATs     db      0                       ; number of FAT tables
  138. abs_sector_adj  dw      0                       ; adjustment to make abs. sector number
  139. end_of_FAT      dw      0                       ; end of FAT table
  140. FirstDataSector dw      0                       ; begin of data
  141.  
  142. ;=========================================================================
  143. ;
  144. ;                           16 BIT CODE
  145. ;
  146. ;=========================================================================
  147.  
  148. include 'bootvesa.inc'                 ;Include source for boot vesa
  149. if defined extended_primary_loader
  150. include 'parsers.inc'
  151. end if
  152.  
  153. start_of_code:
  154.  
  155. if defined extended_primary_loader
  156. ; save data from primary loader
  157.         mov     word [cs:bootcallback], si
  158.         mov     word [cs:bootcallback+2], ds
  159.         push    cs
  160.         pop     ds
  161.         mov     [bootdevice], ax
  162.         mov     [bootfs], bx
  163.  
  164. ; set up stack
  165.         mov     ax, 3000h
  166.         mov     ss, ax
  167.         mov     sp, 0EC00h
  168.  
  169. ; try to load configuration file
  170.         mov     ax, 1
  171.         mov     di, config_file_struct
  172.         call    [bootcallback]
  173.         cld
  174.         push    cs
  175.         pop     es
  176. ; bx=0 - ok, bx=1 - part of file loaded, assume this is ok
  177.         cmp     bx, 1
  178.         ja      .config_bad
  179. ; configuration file was loaded, parse
  180. ; if length is too big, use first 0FFFFh bytes
  181.         test    dx, dx
  182.         jz      @f
  183.         mov     ax, 0FFFFh
  184. @@:
  185. ; ds:si will be pointer to current data, dx = limit
  186.         xchg    ax, dx
  187.         push    4000h
  188.         pop     ds
  189.         xor     si, si
  190. .parse_loop:
  191. ; skip spaces
  192.         cmp     si, dx
  193.         jae     .parse_done
  194.         lodsb
  195.         cmp     al, ' '
  196.         jbe     .parse_loop
  197.         dec     si
  198. ; loop over all possible configuration values
  199.         mov     bx, config_file_variables
  200. .find_variant:
  201. ; get length
  202.         mov     cx, [es:bx]
  203. ; zero length = end of list
  204.         jecxz   .find_newline
  205. ; skip over length
  206.         inc     bx
  207.         inc     bx
  208.         mov     di, bx
  209. ; skip over string
  210.         add     bx, cx
  211. ; test whether we have at least cx symbols left
  212.         mov     ax, cx
  213.         add     ax, si
  214.         jc      .next_variant1
  215.         cmp     ax, dx
  216.         jae     .next_variant1
  217. ; save current position
  218.         push    si
  219. ; compare strings
  220.         repz cmpsb
  221.         jnz     .next_variant2
  222. ; strings are equal; look for "=" with possible spaces before and after
  223. @@:
  224.         cmp     si, dx
  225.         jae     .next_variant2
  226.         lodsb
  227.         cmp     al, ' '
  228.         jbe     @b
  229.         cmp     al, '='
  230.         jnz     .next_variant2
  231. ; ok, we found the true variant
  232. ; ignore saved position on the stack
  233.         pop     ax
  234. ; call the parser
  235.         call    word [es:bx]
  236. ; line parsed, find next
  237. .find_newline:
  238.         cmp     si, dx
  239.         jae     .parse_done
  240.         lodsb
  241.         cmp     al, 13
  242.         jz      .parse_loop
  243.         cmp     al, 10
  244.         jz      .parse_loop
  245.         jmp     .find_newline
  246. .next_variant2:
  247. ; continue to the next variant, restoring current position
  248.         pop     si
  249. .next_variant1:
  250. ; continue to the next variant
  251. ; skip over the parser
  252.         inc     bx
  253.         inc     bx
  254.         jmp     .find_variant
  255. .parse_done:
  256. .config_bad:
  257.  
  258. ; set up segment registers
  259.         push    cs
  260.         pop     ds
  261. else
  262.         cld
  263. ; \begin{diamond}[02.12.2005]
  264. ; if bootloader sets ax = 'KL', then ds:si points to loader block
  265.         cmp     ax, 'KL'
  266.         jnz     @f
  267.         mov     word [cs:cfgmanager.loader_block], si
  268.         mov     word [cs:cfgmanager.loader_block+2], ds
  269. @@:
  270. ; \end{diamond}[02.12.2005]
  271.  
  272. ; if bootloader sets cx = 'HA' and dx = 'RD', then bx contains identifier of source hard disk
  273. ; (see comment to bx_from_load)
  274.         cmp     cx, 'HA'
  275.         jnz     no_hd_load
  276.         cmp     dx, 'RD'
  277.         jnz     no_hd_load
  278.         mov     word [cs:bx_from_load], bx              ; {SPraid}[13.03.2007]
  279. no_hd_load:
  280.  
  281. ; set up stack
  282.         mov     ax, 3000h
  283.         mov     ss, ax
  284.         mov     sp, 0EC00h
  285. ; set up segment registers
  286.         push    cs
  287.         pop     ds
  288.         push    cs
  289.         pop     es
  290. end if
  291.  
  292. ; set videomode
  293.         mov     ax, 3
  294.         int     0x10
  295.  
  296. if lang eq ru
  297.  ; Load & set russian VGA font (RU.INC)
  298.         mov     bp, RU_FNT1             ; RU_FNT1 - First part
  299.         mov     bx, 1000h               ; 768 bytes
  300.         mov     cx, 30h                 ; 48 symbols
  301.         mov     dx, 80h                 ; 128 - position of first symbol
  302.         mov     ax, 1100h
  303.         int     10h
  304.  
  305.         mov     bp, RU_FNT2             ; RU_FNT2 -Second part
  306.         mov     bx, 1000h               ; 512 bytes
  307.         mov     cx, 20h                 ; 32 symbols
  308.         mov     dx, 0E0h                ; 224 - position of first symbol
  309.         mov     ax, 1100h
  310.         int     10h
  311.  ; End set VGA russian font
  312. else if lang eq et
  313.         mov     bp, ET_FNT              ; ET_FNT1
  314.         mov     bx, 1000h               ;
  315.         mov     cx, 255                 ; 256 symbols
  316.         xor     dx, dx                  ; 0 - position of first symbol
  317.         mov     ax, 1100h
  318.         int     10h
  319. end if
  320.  
  321. ; draw frames
  322.         push    0xb800
  323.         pop     es
  324.         xor     di, di
  325.         mov     ah, 1*16+15
  326.  
  327. ; draw top
  328.         mov     si, d80x25_top
  329.         mov     cx, d80x25_top_num * 80
  330. @@:
  331.         lodsb
  332.         stosw
  333.         loop    @b
  334. ; draw spaces
  335.         mov     si, space_msg
  336.         mov     dx, 25 - d80x25_top_num - d80x25_bottom_num
  337. dfl1:
  338.         push    si
  339.         mov     cx, 80
  340. @@:
  341.         lodsb
  342.         stosw
  343.         loop    @b
  344.         pop     si
  345.         dec     dx
  346.         jnz     dfl1
  347. ; draw bottom
  348.         mov     si, d80x25_bottom
  349.         mov     cx, d80x25_bottom_num * 80
  350. @@:
  351.         lodsb
  352.         stosw
  353.         loop    @b
  354.  
  355.         mov     byte [space_msg+80], 0    ; now space_msg is null terminated
  356.  
  357.         _setcursor d80x25_top_num,0
  358.  
  359.  
  360. ; TEST FOR 386+
  361.  
  362.         mov     bx, 0x4000
  363.         pushf
  364.         pop     ax
  365.         mov     dx, ax
  366.         xor     ax, bx
  367.         push    ax
  368.         popf
  369.         pushf
  370.         pop     ax
  371.         and     ax, bx
  372.         and     dx, bx
  373.         cmp     ax, dx
  374.         jnz     cpugood
  375.         mov     si, not386
  376. sayerr:
  377.         call    print
  378.         jmp     $
  379.      cpugood:
  380.  
  381.         push    0
  382.         popf
  383.         sti
  384.  
  385. ; set up esp
  386.         movzx   esp, sp
  387.  
  388.         push    0
  389.         pop     es
  390.         xor     ax, ax
  391.         and     word [es:BOOT_IDE_BASE_ADDR], ax        ;0
  392.         and     word [es:BOOT_IDE_BAR0_16], ax  ;0
  393.         and     word [es:BOOT_IDE_BAR1_16], ax  ;0
  394.         and     word [es:BOOT_IDE_BAR2_16], ax  ;0
  395.         and     word [es:BOOT_IDE_BAR3_16], ax  ;0
  396. ; \begin{Mario79}
  397. ; find HDD IDE DMA PCI device
  398. ; check for PCI BIOS
  399.         mov     ax, 0xB101
  400.         int     0x1A
  401.         jc      .nopci
  402.         cmp     edx, 'PCI '
  403.         jnz     .nopci
  404. ; find PCI class code
  405. ; class 1 = mass storage
  406. ; subclass 1 = IDE controller
  407. ; a) class 1, subclass 1, programming interface 0x80
  408. ; This is a Parallel IDE Controller which uses IRQs 14 and 15.
  409.         mov     ax, 0xB103
  410.         mov     ecx, 1*10000h + 1*100h + 0x80
  411.         mov     [es:BOOT_IDE_PI_16], cx
  412.         xor     si, si  ; device index = 0
  413.         int     0x1A
  414.         jnc     .found_1 ; Parallel IDE Controller
  415. ; b) class 1, subclass 1, programming interface 0x8f
  416.         mov     ax, 0xB103
  417.         mov     ecx, 1*10000h + 1*100h + 0x8f
  418.         mov     [es:BOOT_IDE_PI_16], cx
  419.         xor     si, si  ; device index = 0
  420.         int     0x1A
  421.         jnc     .found
  422. ; c) class 1, subclass 1, programming interface 0x85
  423.         mov     ax, 0xB103
  424.         mov     ecx, 1*10000h + 1*100h + 0x85
  425.         mov     [es:BOOT_IDE_PI_16], cx
  426.         xor     si, si  ; device index = 0
  427.         int     0x1A
  428.         jnc     .found
  429. ; d) class 1, subclass 1, programming interface 0x8A
  430. ; This is a Parallel IDE Controller which uses IRQs 14 and 15.
  431.         mov     ax, 0xB103
  432.         mov     ecx, 1*10000h + 1*100h + 0x8A
  433.         mov     [es:BOOT_IDE_PI_16], cx
  434.         xor     si, si  ; device index = 0
  435.         int     0x1A
  436.         jnc     .found ; Parallel IDE Controller
  437. ; Controller not found!
  438.         xor     ax, ax
  439.         mov     [es:BOOT_IDE_PI_16], ax
  440.         jmp     .nopci
  441. ;--------------------------------------
  442. .found_1:
  443. ; get memory base BAR4
  444.         mov     ax, 0xB10A
  445.         mov     di, 0x20        ; memory base is config register at 0x20
  446.         push    cx
  447.         int     0x1A
  448.         jc      .no_BAR4        ;.nopci
  449.         and     cx, 0xFFFC      ; clear address decode type
  450.         mov     [es:BOOT_IDE_BASE_ADDR], cx
  451. .no_BAR4:
  452.         pop     cx
  453. ;--------------------------------------
  454. .found:
  455. ; get Interrupt Line
  456.         mov     ax, 0xB10A
  457.         mov     di, 0x3c        ; memory base is config register at 0x3c
  458.         push    cx
  459.         int     0x1A
  460.         jc      .no_Interrupt        ;.nopci
  461.  
  462.         mov     [es:BOOT_IDE_INTERR_16], cx
  463. .no_Interrupt:
  464.         pop     cx
  465. ;--------------------------------------
  466. ; get memory base BAR0
  467.         mov     ax, 0xB10A
  468.         mov     di, 0x10        ; memory base is config register at 0x10
  469.         push    cx
  470.         int     0x1A
  471.         jc      .no_BAR0        ;.nopci
  472.  
  473.         mov     [es:BOOT_IDE_BAR0_16], cx
  474. .no_BAR0:
  475.         pop     cx
  476. ;--------------------------------------
  477. ; get memory base BAR1
  478.         mov     ax, 0xB10A
  479.         mov     di, 0x14        ; memory base is config register at 0x14
  480.         push    cx
  481.         int     0x1A
  482.         jc      .no_BAR1        ;.nopci
  483.  
  484.         mov     [es:BOOT_IDE_BAR1_16], cx
  485. .no_BAR1:
  486.         pop     cx
  487. ;--------------------------------------
  488. ; get memory base BAR2
  489.         mov     ax, 0xB10A
  490.         mov     di, 0x18        ; memory base is config register at 0x18
  491.         push    cx
  492.         int     0x1A
  493.         jc      .no_BAR2        ;.nopci
  494.  
  495.         mov     [es:BOOT_IDE_BAR2_16], cx
  496. .no_BAR2:
  497.         pop     cx
  498. ;--------------------------------------
  499. ; get memory base BAR3
  500.         mov     ax, 0xB10A
  501.         mov     di, 0x1C        ; memory base is config register at 0x1c
  502.         push    cx
  503.         int     0x1A
  504.         jc      .no_BAR3        ;.nopci
  505.  
  506.         mov     [es:BOOT_IDE_BAR3_16], cx
  507. .no_BAR3:
  508.         pop     cx
  509. ;--------------------------------------
  510. .nopci:
  511. ; \end{Mario79}
  512.  
  513.         mov     al, 0xf6        ; Сброс клавиатуры, разрешить сканирование
  514.         out     0x60, al
  515.         xor     cx, cx
  516. wait_loop:       ; variant 2
  517. ; reading state of port of 8042 controller
  518.         in      al, 64h
  519.         and     al, 00000010b  ; ready flag
  520. ; wait until 8042 controller is ready
  521.         loopnz  wait_loop
  522.  
  523. ;;;/diamond today   5.02.2008
  524. ; set keyboard typematic rate & delay
  525.         mov     al, 0xf3
  526.         out     0x60, al
  527.         xor     cx, cx
  528. @@:
  529.         in      al, 64h
  530.         test    al, 2
  531.         loopnz  @b
  532.         mov     al, 0
  533.         out     0x60, al
  534.         xor     cx, cx
  535. @@:
  536.         in      al, 64h
  537.         test    al, 2
  538.         loopnz  @b
  539. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  540. ; --------------- APM ---------------------
  541.         and     word [es:BOOT_APM_VERSION], 0     ; ver = 0.0 (APM not found)
  542.         mov     ax, 0x5300
  543.         xor     bx, bx
  544.         int     0x15
  545.         jc      apm_end                 ; APM not found
  546.         test    cx, 2
  547.         jz      apm_end                 ; APM 32-bit protected-mode interface not supported
  548.         mov     [es:BOOT_APM_VERSION], ax         ; Save APM Version
  549.         mov     [es:BOOT_APM_FLAGS], cx           ; Save APM flags
  550.  
  551.         ; Write APM ver ----
  552.         and     ax, 0xf0f
  553.         add     ax, '00'
  554.         mov     si, msg_apm
  555.         mov     [si + 5], ah
  556.         mov     [si + 7], al
  557.         _setcursor 0, 3
  558.         call    printplain
  559.         ; ------------------
  560.  
  561.         mov     ax, 0x5304              ; Disconnect interface
  562.         xor     bx, bx
  563.         int     0x15
  564.         mov     ax, 0x5303              ; Connect 32 bit mode interface
  565.         xor     bx, bx
  566.         int     0x15
  567.  
  568.         mov     [es:BOOT_APM_ENTRY], ebx
  569.         mov     [es:BOOT_APM_CODE_32], ax
  570.         mov     [es:BOOT_APM_CODE_16], cx
  571.         mov     [es:BOOT_APM_DATA_16], dx
  572.  
  573. apm_end:
  574.         _setcursor d80x25_top_num, 0
  575.  
  576. if ~ defined extended_primary_loader
  577. ;CHECK current of code
  578.         cmp     [cfgmanager.loader_block], -1
  579.         jz      noloaderblock
  580.         les     bx, [cfgmanager.loader_block]
  581.         cmp     byte [es:bx], 1
  582.         mov     si, loader_block_error
  583.         jnz     sayerr
  584.         push    0
  585.         pop     es
  586. end if
  587.  
  588. noloaderblock:
  589. ; DISPLAY VESA INFORMATION
  590.         call    print_vesa_info
  591.         call    calc_vmodes_table
  592.         call    check_first_parm   ;check and enable cursor_pos
  593.  
  594. ; \begin{diamond}[30.11.2005]
  595. cfgmanager:
  596. ; settings:
  597. ; a) preboot_graph = graphical mode
  598. ;    preboot_gprobe = probe this mode?
  599. ; b) preboot_biosdisk  = use BIOS disks through V86 emulation? // (earlier was: preboot_dma  = use DMA access?)
  600. ; c) preboot_debug = duplicates kernel debug output to the screen // (earlier was: preboot_vrrm = use VRR?)
  601. ;    // VRR is an obsolete functionality, used only with CRT monitors: increase display frequency by reducing screen resolution
  602. ; d) preboot_launcher = start the first app (right now it's LAUNCHER) after kernel is loaded?
  603. ; e) preboot_device = from where to boot?
  604.  
  605. ; determine default settings
  606. if ~ defined extended_primary_loader
  607.         mov     [.bSettingsChanged], 0
  608. end if
  609.  
  610. ;.preboot_gr_end:
  611.         mov     di, preboot_device
  612. ; if image in memory is present and [preboot_device] is uninitialized,
  613. ; set it to use this preloaded image
  614.         cmp     byte [di], 0
  615.         jnz     .preboot_device_inited
  616. if defined extended_primary_loader
  617.         inc     byte [di]
  618.         cmp     byte [bootdevice], 'f' ; floppy?
  619.         jz      .preboot_device_inited
  620.         inc     byte [di]
  621. else
  622.         cmp     [.loader_block], -1
  623.         jz      @f
  624.         les     bx, [.loader_block]
  625.         test    byte [es:bx+1], 1
  626.         jz      @f
  627.         mov     byte [di], 3
  628.         jmp     .preboot_device_inited
  629. @@:
  630. ; otherwise, set [preboot_device] to 1 (default value - boot from floppy)
  631.         mov     byte [di], 1
  632. end if
  633. .preboot_device_inited:
  634. ; following 4 lines set variables to 1 if its current value is 0
  635.         cmp     byte [di+preboot_dma-preboot_device], 1
  636.         adc     byte [di+preboot_dma-preboot_device], 0
  637.         cmp     byte [di+preboot_launcher-preboot_device], 1        ; Start LAUNCHER by default
  638.         adc     byte [di+preboot_launcher-preboot_device], 0        
  639. ;        cmp     byte [di+preboot_biosdisk-preboot_device], 1
  640. ;        adc     byte [di+preboot_biosdisk-preboot_device], 0
  641. ;; default value for VRR is OFF
  642. ;        cmp     byte [di+preboot_vrrm-preboot_device], 0
  643. ;        jnz    @f
  644. ;        mov    byte [di+preboot_vrrm-preboot_device], 2
  645. ;@@:
  646. ; notify user
  647.         _setcursor 5,2
  648.  
  649.         mov     si, linef
  650.         call    printplain
  651.         mov     si, start_msg
  652.         call    print
  653.         mov     si, time_msg
  654.         call    print
  655. ; get start time
  656.         call    .gettime
  657.         mov     [.starttime], eax
  658.         mov     word [.timer], .newtimer
  659.         mov     word [.timer+2], cs
  660. .printcfg:
  661.  
  662.         _setcursor 9,0
  663.         mov     si, current_cfg_msg
  664.         call    print
  665.         mov     si, curvideo_msg
  666.         call    print
  667.  
  668.         call    draw_current_vmode
  669.  
  670.         mov     si, usebd_msg
  671.         cmp     [preboot_biosdisk], 1
  672.         call    .say_on_off
  673. ;        mov     si, vrrm_msg
  674. ;        cmp     [preboot_vrrm], 1
  675. ;        call    .say_on_off
  676.         mov     si, debug_mode_msg
  677.         cmp     [preboot_debug], 1
  678.         call    .say_on_off
  679.         mov     si, launcher_msg
  680.         cmp     [preboot_launcher], 1
  681.         call    .say_on_off
  682.         mov     si, preboot_device_msg
  683.         call    print
  684.         mov     al, [preboot_device]
  685. if defined extended_primary_loader
  686.         and     eax, 3
  687. else
  688.         and     eax, 7
  689. end if
  690.         mov     si, [preboot_device_msgs+eax*2]
  691.         call    printplain
  692. .show_remarks:
  693. ; show remarks in gray color
  694.         mov     di, ((21-num_remarks)*80 + 2)*2
  695.         push    0xB800
  696.         pop     es
  697.         mov     cx, num_remarks
  698.         mov     si, remarks
  699. .write_remarks:
  700.         lodsw
  701.         push    si
  702.         xchg    ax, si
  703.         mov     ah, 1*16+7      ; background: blue (1), foreground: gray (7)
  704.         push    di
  705. .write_remark:
  706.         lodsb
  707.         test    al, al
  708.         jz      @f
  709.         stosw
  710.         jmp     .write_remark
  711. @@:
  712.         pop     di
  713.         pop     si
  714.         add     di, 80*2
  715.         loop    .write_remarks
  716. .wait:
  717.         _setcursor 25,0         ; out of screen
  718. ; set timer interrupt handler
  719.         cli
  720.         push    0
  721.         pop     es
  722.         push    dword [es:8*4]
  723.         pop     dword [.oldtimer]
  724.         push    dword [.timer]
  725.         pop     dword [es:8*4]
  726. ;        mov     eax, [es:8*4]
  727. ;        mov     [.oldtimer], eax
  728. ;        mov     eax, [.timer]
  729. ;        mov     [es:8*4], eax
  730.         sti
  731. ; wait for keypressed
  732.         xor     ax, ax
  733.         int     16h
  734.         push    ax
  735. ; restore timer interrupt
  736. ;        push    0
  737. ;        pop     es
  738.         mov     eax, [.oldtimer]
  739.         mov     [es:8*4], eax
  740.         mov     [.timer], eax
  741.  
  742.         _setcursor 7,0
  743.         mov     si, space_msg
  744.         call    printplain
  745. ; clear remarks and restore normal attributes
  746.         push    es
  747.         mov     di, ((21-num_remarks)*80 + 2)*2
  748.         push    0xB800
  749.         pop     es
  750.         mov     cx, num_remarks
  751.         mov     ax, ' ' + (1*16 + 15)*100h
  752. @@:
  753.         push    cx
  754.         mov     cx, 76
  755.         rep stosw
  756.         pop     cx
  757.         add     di, 4*2
  758.         loop    @b
  759.         pop     es
  760.         pop     ax
  761. ; switch on key
  762.         cmp     al, 13
  763.         jz      .continue
  764.         or      al, 20h
  765.         cmp     al, 'a'         ; select graphical mode
  766.         jz      .change_a
  767.         cmp     al, 'q'         ; Trick to make 'A' key on azerty keyboard work
  768.         je      .change_a
  769.         cmp     al, 'b'         ; use BIOS disks? // (selecting YES will make BIOS disks visible as /bd)
  770.         jz      .change_b
  771.         cmp     al, 'c'         ; load kernel in debug mode?  // (earlier was: use VRR?)
  772.         jz      .change_c
  773.         cmp     al, 'd'         ; start launcher after kernel is loaded?
  774.         jz      .change_d
  775.         cmp     al, 'e'         ; select boot origin
  776.         jnz     .show_remarks
  777. ; e) preboot_device = from where to boot?
  778.         _setcursor 16,0
  779.         mov     si, bdev
  780.         call    print
  781. if defined extended_primary_loader
  782.         mov     bx, '12'        ; range accepted for answer: 1-2
  783. else
  784.         mov     bx, '14'        ; range accepted for answer: 1-4
  785. end if
  786.         call    getkey
  787.         mov     [preboot_device], al
  788.         _setcursor 14,0
  789. .d:
  790. if ~ defined extended_primary_loader
  791.         mov     [.bSettingsChanged], 1
  792. end if
  793.         call    clear_vmodes_table             ;clear vmodes_table
  794.         jmp     .printcfg
  795. .change_a:
  796.         call    clear_vmodes_table             ;clear vmodes_table
  797. .loops:
  798.         call    draw_vmodes_table
  799.         _setcursor 25,0         ; out of screen
  800.         xor     ax, ax
  801.         int     0x16
  802. ;        call    clear_table_cursor             ;clear current position of cursor
  803.  
  804.         mov     si, word [cursor_pos]
  805.  
  806.         cmp     ah, 0x48;x,0x48E0               ; up
  807.         jne     .down
  808.         cmp     si, modes_table
  809.         jbe     .loops
  810.         sub     word [cursor_pos], size_of_step
  811.         jmp     .loops
  812.  
  813. .down:
  814.         cmp     ah, 0x50;x,0x50E0               ; down
  815.         jne     .pgup
  816.         cmp     word[es:si+10], -1
  817.         je      .loops
  818.         add     word [cursor_pos], size_of_step
  819.         jmp     .loops
  820.  
  821. .pgup:
  822.         cmp     ah, 0x49                ; page up
  823.         jne     .pgdn
  824.         sub     si, size_of_step*long_v_table
  825.         cmp     si, modes_table
  826.         jae     @f
  827.         mov     si, modes_table
  828. @@:
  829.         mov     word [cursor_pos], si
  830.         mov     si, word [home_cursor]
  831.         sub     si, size_of_step*long_v_table
  832.         cmp     si, modes_table
  833.         jae     @f
  834.         mov     si, modes_table
  835. @@:
  836.         mov     word [home_cursor], si
  837.         jmp     .loops
  838.  
  839. .pgdn:
  840.         cmp     ah, 0x51                ; page down
  841.         jne     .enter
  842.         mov     ax, [end_cursor]
  843.         add     si, size_of_step*long_v_table
  844.         cmp     si, ax
  845.         jb      @f
  846.         mov     si, ax
  847.         sub     si, size_of_step
  848. @@:
  849.         mov     word [cursor_pos], si
  850.         mov     si, word [home_cursor]
  851.         sub     ax, size_of_step*long_v_table
  852.         add     si, size_of_step*long_v_table
  853.         cmp     si, ax
  854.         jb      @f
  855.         mov     si, ax
  856. @@:
  857.         mov     word [home_cursor], si
  858.         jmp     .loops
  859.  
  860. .enter:
  861.         cmp     al, 0x0D;x,0x1C0D               ; enter
  862.         jne     .loops
  863.         push    word [cursor_pos]
  864.         pop     bp
  865.         push    word [es:bp]
  866.         pop     word [x_save]
  867.         push    word [es:bp+2]
  868.         pop     word [y_save]
  869.         push    word [es:bp+6]
  870.         pop     word [number_vm]
  871.         mov     word [preboot_graph], bp          ;save choose
  872.        
  873.         jmp     .d
  874.  
  875. .change_b:                      ; b) preboot_biosdisk  = use BIOS disks through V86 emulation?
  876.         _setcursor 16,0
  877. ;        mov     si, ask_dma    // (earlier was: preboot_dma  = use DMA access?)
  878. ;        call    print
  879. ;        mov     bx, '13'       ; range accepted for answer: 1-3
  880. ;        call    getkey
  881. ;        mov     [preboot_dma], al
  882.         mov     si, ask_bd
  883.         call    print
  884.         mov     bx, '12'        ; range accepted for answer: 1-2
  885.         call    getkey
  886.         mov     [preboot_biosdisk], al
  887.         _setcursor 11,0
  888.         jmp     .d
  889. ;.change_c:                     ; //  VRR is an obsolete functionality, used only with CRT monitors
  890. ;        _setcursor 16,0
  891. ;        mov     si, vrrmprint
  892. ;        call    print
  893. ;        mov     bx, '12'       ; range accepted for answer: 1-2
  894. ;        call    getkey
  895. ;        mov     [preboot_vrrm], al
  896. ;        _setcursor 12,0
  897. ;        jmp     .d
  898. .change_c:                      ; c) preboot_debug = duplicates kernel debug output to the screen
  899.         _setcursor 16,0
  900.         mov     si, ask_debug
  901.         call    print
  902.         mov     bx, '12'        ; range accepted for answer: 1-2
  903.         call    getkey
  904.         mov     [preboot_debug], al
  905.         _setcursor 12,0
  906.         jmp     .d
  907. .change_d:                      ; d) preboot_launcher = start the first app (right now it's LAUNCHER) after kernel is loaded?
  908.         _setcursor 16,0
  909.         mov     si, ask_launcher
  910.         call    print
  911.         mov     bx, '12'        ; range accepted for answer: 1-2
  912.         call    getkey
  913.         mov     [preboot_launcher], al
  914.         _setcursor 13,0
  915.         jmp     .d
  916. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  917. .say_on_off:
  918.         pushf
  919.         call    print
  920.         mov     si, on_msg
  921.         popf
  922.         jz      @f
  923.         mov     si, off_msg
  924. @@:
  925.         jmp     printplain
  926. ; novesa and vervesa strings are not used at the moment of executing this code
  927. virtual at novesa
  928. .oldtimer dd ?
  929. .starttime dd ?
  930. if ~ defined extended_primary_loader
  931. .bSettingsChanged db ?
  932. end if
  933. .timer dd ?
  934. end virtual
  935. if ~ defined extended_primary_loader
  936. .loader_block dd -1
  937. end if
  938. .gettime:
  939.         mov     ah, 0
  940.         int     1Ah
  941.         xchg    ax, cx
  942.         shl     eax, 10h
  943.         xchg    ax, dx
  944.         ret
  945. .newtimer:
  946.         push    ds
  947.         push    cs
  948.         pop     ds
  949.         pushf
  950.         call    [.oldtimer]
  951.         pushad
  952.         call    .gettime
  953.         sub     eax, [.starttime]
  954. if defined extended_primary_loader
  955.         sub     ax, [preboot_timeout]
  956. else
  957.         sub     ax, 18*5
  958. end if
  959.         jae     .timergo
  960.         neg     ax
  961.         add     ax, 18-1
  962.         mov     bx, 18
  963.         xor     dx, dx
  964.         div     bx
  965. if lang eq ru
  966. ; подождите 5 секунд, 4/3/2 секунды, 1 секунду
  967.         cmp     al, 5
  968.         mov     cl, ' '
  969.         jae     @f
  970.         cmp     al, 1
  971.         mov     cl, 0xE3 ; 'у' in cp866
  972.         jz      @f
  973.         mov     cl, 0xEB ; 'ы' in cp866
  974. @@:
  975.         mov     [time_str+9], cl
  976. else if lang eq et
  977.         cmp     al, 1
  978.         ja      @f
  979.         mov     byte [time_str+9], ' '
  980.         mov     byte [time_str+10], ' '
  981. @@:
  982. else if lang eq sp
  983. ; esperar 5/4/3/2 segundos, 1 segundo
  984.         cmp     al, 1
  985.         mov     cl, 's'
  986.         ja      @f
  987.         mov     cl, ' '
  988. @@:
  989.         mov     [time_str+10], cl
  990. else
  991. ; wait 5/4/3/2 seconds, 1 second
  992.         cmp     al, 1
  993.         mov     cl, 's'
  994.         ja      @f
  995.         mov     cl, ' '
  996. @@:
  997.         mov     [time_str+9], cl
  998. end if
  999.         add     al, '0'
  1000.         mov     [time_str+1], al
  1001.         mov     si, time_msg
  1002.         _setcursor 7,0
  1003.         call    print
  1004.         _setcursor 25,0
  1005.         popad
  1006.         pop     ds
  1007.         iret
  1008. .timergo:
  1009.         push    0
  1010.         pop     es
  1011.         mov     eax, [.oldtimer]
  1012.         mov     [es:8*4], eax
  1013.         mov     sp, 0EC00h
  1014. .continue:
  1015.         sti
  1016.         _setcursor 6,0
  1017.         mov     si, space_msg
  1018.         call    printplain
  1019.         call    printplain
  1020.         _setcursor 6,0
  1021.         mov     si, loading_msg
  1022.         call    print
  1023.         _setcursor 16,0
  1024. if ~ defined extended_primary_loader
  1025.         cmp     [.bSettingsChanged], 0
  1026.         jz      .load
  1027.         cmp     [.loader_block], -1
  1028.         jz      .load
  1029.         les     bx, [.loader_block]
  1030.         mov     eax, [es:bx+3]
  1031.         push    ds
  1032.         pop     es
  1033.         test    eax, eax
  1034.         jz      .load
  1035.         push    eax
  1036.         mov     si, save_quest
  1037.         call    print
  1038. .waityn:
  1039.         mov     ah, 0
  1040.         int     16h
  1041.         or      al, 20h
  1042.         cmp     al, 'n'
  1043.         jz      .loadc
  1044.         if lang eq sp
  1045.         cmp     al, 's'
  1046.         else
  1047.         cmp     al, 'y'
  1048.         end if
  1049.         jnz     .waityn
  1050.         call    putchar
  1051.         mov     byte [space_msg+80], 186
  1052.  
  1053.         pop     eax
  1054.         push    cs
  1055.         push    .cont
  1056.         push    eax
  1057.         retf                          ;call back
  1058. .loadc:
  1059.         pop     eax
  1060. .cont:
  1061.         push    cs
  1062.         pop     ds
  1063.         mov     si, space_msg
  1064.         mov     byte [si+80], 0
  1065.         _setcursor 16,0
  1066.         call    printplain
  1067.         _setcursor 16,0
  1068. .load:
  1069. end if
  1070. ; \end{diamond}[02.12.2005]
  1071.  
  1072. ; ASK GRAPHICS MODE
  1073.  
  1074.         call    set_vmode
  1075.  
  1076. ; GRAPHICS ACCELERATION
  1077. ; force yes
  1078.         mov     [es:BOOT_MTRR], byte 1
  1079.  
  1080. ; DMA ACCESS TO HD
  1081.  
  1082.         mov     al, [preboot_dma]
  1083.         mov     [es:BOOT_DMA], al
  1084.  
  1085. ;; VRR_M USE
  1086. ;
  1087. ;        mov     al,[preboot_vrrm]
  1088. ;        mov     [es:BOOT_VRR], al              ;// 0x9030
  1089.  
  1090. ; Set kernel DEBUG mode - if nonzero, duplicates debug output to the screen.
  1091.         mov     al, [preboot_debug]
  1092.         mov     [es:BOOT_DEBUG_PRINT], al       ;// 0x901E
  1093.  
  1094. ; Start the first app (right now it's LAUNCHER) after kernel is loaded?
  1095.         mov     al, [preboot_launcher]
  1096.         mov     [es:BOOT_LAUNCHER_START], al    ;// 0x901D        
  1097.  
  1098. ; BOOT DEVICE
  1099.  
  1100.         mov     al, [preboot_device]
  1101.         dec     al
  1102.         mov     [boot_dev], al
  1103.  
  1104. ; GET MEMORY MAP
  1105. include '../detect/biosmem.inc'
  1106.  
  1107. ; READ DISKETTE TO MEMORY
  1108.  
  1109.         cmp     [boot_dev], 0
  1110.         jne     no_sys_on_floppy
  1111.         mov     si, diskload
  1112.         call    print
  1113.         xor     ax, ax            ; reset drive
  1114.         xor     dx, dx
  1115.         int     0x13
  1116. ; do we boot from CD-ROM?
  1117.         mov     ah, 41h
  1118.         mov     bx, 55AAh
  1119.         xor     dx, dx
  1120.         int     0x13
  1121.         jc      .nocd
  1122.         cmp     bx, 0AA55h
  1123.         jnz     .nocd
  1124.         mov     ah, 48h
  1125.         push    ds
  1126.         push    es
  1127.         pop     ds
  1128.         mov     si, 0xa000
  1129.         mov     word [si], 30
  1130.         int     0x13
  1131.         pop     ds
  1132.         jc      .nocd
  1133.         push    ds
  1134.         lds     si, [es:si+26]
  1135.         test    byte [ds:si+10], 40h
  1136.         pop     ds
  1137.         jz      .nocd
  1138. ; yes - read all floppy by 18 sectors
  1139.  
  1140. ; TODO: !!!! read only first sector and set variables !!!!!
  1141. ; ...
  1142. ; TODO: !!! then read flippy image track by track
  1143.        
  1144.         mov     cx, 0x0001      ; startcyl,startsector
  1145. .a1:
  1146.         push    cx dx
  1147.         mov     al, 18
  1148.         mov     bx, 0xa000
  1149.         call    boot_read_floppy
  1150.         mov     si, movedesc
  1151.         push    es
  1152.         push    ds
  1153.         pop     es
  1154.         mov     cx, 256*18
  1155.         mov     ah, 0x87
  1156.         int     0x15
  1157.         pop     es
  1158.         pop     dx cx
  1159.         test    ah, ah
  1160.         jnz     sayerr_floppy
  1161.         add     dword [si+8*3+2], 512*18
  1162.         inc     dh
  1163.         cmp     dh, 2
  1164.         jnz     .a1
  1165.         mov     dh, 0
  1166.         inc     ch
  1167.         cmp     ch, 80
  1168.         jae     ok_sys_on_floppy
  1169.         pusha
  1170.         mov     al, ch
  1171.         shr     ch, 2
  1172.         add     al, ch
  1173.         aam
  1174.         xchg    al, ah
  1175.         add     ax, '00'
  1176.         mov     si, pros
  1177.         mov     [si], ax
  1178.         call    printplain
  1179.         popa
  1180.         jmp     .a1
  1181. .nocd:
  1182. ; no - read only used sectors from floppy
  1183. ; now load floppy image to memory
  1184. ; at first load boot sector and first FAT table
  1185.  
  1186. ; read only first sector and fill variables
  1187.         mov     cx, 0x0001      ; first logical sector
  1188.         xor     dx, dx          ; head = 0, drive = 0 (a:)
  1189.         mov     al, 1           ; read one sector
  1190.         mov     bx, 0xB000      ; es:bx -> data area
  1191.         call    boot_read_floppy
  1192. ; fill the necessary parameters to work with a floppy
  1193.         mov     ax, word [es:bx+24]
  1194.         mov     word [BPB_SecPerTrk], ax
  1195.         mov     ax, word [es:bx+26]
  1196.         mov     word [BPB_NumHeads], ax
  1197.         mov     ax, word [es:bx+17]
  1198.         mov     word [BPB_RootEntCnt], ax
  1199.         mov     ax, word [es:bx+14]
  1200.         mov     word [BPB_RsvdSecCnt], ax
  1201.         mov     ax, word [es:bx+19]
  1202.         mov     word [BPB_TotSec16], ax
  1203.         mov     al, byte [es:bx+13]
  1204.         mov     byte [BPB_SecPerClus], al
  1205.         mov     al, byte [es:bx+16]
  1206.         mov     byte [BPB_NumFATs], al
  1207. ;<Lrz> 18.11.2008
  1208.         mov     ax, word [es:bx+22]
  1209.         mov     word [BPB_FATSz16], ax
  1210.         mov     cx, word [es:bx+11]
  1211.         mov     word [BPB_BytsPerSec], cx
  1212.  
  1213. ; count of clusters in FAT12 ((size_of_FAT*2)/3)
  1214. ;        mov     ax, word [BPB_FATSz16]
  1215. ;        mov     cx, word [BPB_BytsPerSec]
  1216. ;end <Lrz> 18.11.2008
  1217.         xor     dx, dx
  1218.         mul     cx
  1219.         shl     ax, 1
  1220.         mov     cx, 3
  1221.         div     cx              ; now ax - number of clusters in FAT12
  1222.         mov     word [end_of_FAT], ax
  1223.  
  1224. ; load first FAT table
  1225.         mov     cx, 0x0002      ; startcyl,startsector          ; TODO!!!!!
  1226.         xor     dx, dx          ; starthead,drive
  1227.         mov     al, byte [BPB_FATSz16]     ; no of sectors to read
  1228.         add     bx, word [BPB_BytsPerSec]  ; es:bx -> data area
  1229.         call    boot_read_floppy
  1230.         mov     bx, 0xB000
  1231.  
  1232. ; and copy them to extended memory
  1233.         mov     si, movedesc
  1234.         mov     [si+8*2+3], bh          ; from
  1235.        
  1236.         mov     ax, word [BPB_BytsPerSec]
  1237.         shr     ax, 1                   ; words per sector
  1238.         mov     cx, word [BPB_RsvdSecCnt]
  1239.         add     cx, word [BPB_FATSz16]
  1240.         mul     cx
  1241.         push    ax                      ; save to stack count of words in boot+FAT
  1242.         xchg    ax, cx
  1243.        
  1244.         push    es
  1245.         push    ds
  1246.         pop     es
  1247.         mov     ah, 0x87
  1248.         int     0x15
  1249.         pop     es
  1250.         test    ah, ah
  1251.         jz      @f
  1252. sayerr_floppy:
  1253.         mov     dx, 0x3f2
  1254.         mov     al, 0
  1255.         out     dx, al
  1256. sayerr_memmove:
  1257.         mov     si, memmovefailed
  1258.         jmp     sayerr_plain
  1259. @@:
  1260.         pop     ax                      ; restore from stack count of words in boot+FAT
  1261.         shl     ax, 1                   ; make bytes count from count of words
  1262.         and     eax, 0ffffh
  1263.         add     dword [si+8*3+2], eax
  1264.  
  1265. ; copy first FAT to second copy
  1266. ; TODO: BPB_NumFATs !!!!!
  1267.         add     bx, word [BPB_BytsPerSec]       ; !!! TODO: may be need multiply by BPB_RsvdSecCnt !!!
  1268.         mov     byte [si+8*2+3], bh     ; bx - begin of FAT
  1269.        
  1270.         mov     ax, word [BPB_BytsPerSec]
  1271.         shr     ax, 1                   ; words per sector
  1272.         mov     cx, word [BPB_FATSz16]
  1273.         mul     cx
  1274.         mov     cx, ax                  ; cx - count of words in FAT
  1275.  
  1276.         push    es
  1277.         push    ds
  1278.         pop     es
  1279.         mov     ah, 0x87
  1280.         int     0x15
  1281.         pop     es
  1282.         test    ah, ah
  1283.         jnz     sayerr_floppy
  1284.        
  1285.         mov     ax, cx
  1286.         shl     ax, 1
  1287.         and     eax, 0ffffh             ; ax - count of bytes in FAT
  1288.         add     dword [si+8*3+2], eax
  1289.        
  1290. ; reading RootDir
  1291. ; TODO: BPB_NumFATs
  1292.         add     bx, ax
  1293.         add     bx, 100h
  1294.         and     bx, 0ff00h                      ; bx - place in buffer to write RootDir
  1295.         push    bx
  1296.  
  1297.         mov     bx, word [BPB_BytsPerSec]
  1298.         shr     bx, 5                           ; divide bx by 32
  1299.         mov     ax, word [BPB_RootEntCnt]
  1300.         xor     dx, dx
  1301.         div     bx
  1302.         push    ax                              ; ax - count of RootDir sectors
  1303.  
  1304.         mov     ax, word [BPB_FATSz16]
  1305.         xor     cx, cx
  1306.         mov     cl, byte [BPB_NumFATs]
  1307.         mul     cx
  1308.         add     ax, word [BPB_RsvdSecCnt]       ; ax - first sector of RootDir
  1309.  
  1310.         mov     word [FirstDataSector], ax
  1311.         pop     bx
  1312.         push    bx
  1313.         add     word [FirstDataSector], bx      ; Begin of data region of floppy
  1314.        
  1315. ; read RootDir
  1316.         call    conv_abs_to_THS
  1317.         pop     ax
  1318.         pop     bx                              ; place in buffer to write
  1319.         push    ax
  1320.         call    boot_read_floppy                ; read RootDir into buffer
  1321. ; copy RootDir
  1322.         mov     byte [si+8*2+3], bh             ; from buffer
  1323.         pop     ax                              ; ax = count of RootDir sectors
  1324.         mov     cx, word [BPB_BytsPerSec]
  1325.         mul     cx
  1326.         shr     ax, 1
  1327.         mov     cx, ax                          ; count of words to copy
  1328.         push    es
  1329.         push    ds
  1330.         pop     es
  1331.         mov     ah, 0x87
  1332.         int     0x15
  1333.         pop     es
  1334.  
  1335.         mov     ax, cx
  1336.         shl     ax, 1
  1337.         and     eax, 0ffffh             ; ax - count of bytes in RootDir
  1338.         add     dword [si+8*3+2], eax   ; add count of bytes copied
  1339.  
  1340. ; Reading data clusters from floppy
  1341.         mov     byte [si+8*2+3], bh
  1342.         push    bx
  1343.  
  1344.         mov     di, 2                   ; First data cluster
  1345. .read_loop:
  1346.         mov     bx, di
  1347.         shr     bx, 1                   ; bx+di = di*1.5
  1348.         jnc     .even
  1349.         test    word [es:bx+di+0xB200], 0xFFF0  ; TODO: may not be 0xB200 !!!
  1350.         jmp     @f
  1351. .even:
  1352.         test    word [es:bx+di+0xB200], 0xFFF   ; TODO: may not be 0xB200 !!!
  1353.  
  1354. @@:
  1355.         jz      .skip
  1356. ; read cluster di
  1357. ;.read:
  1358.         ;conv cluster di to abs. sector ax
  1359.         ; ax = (N-2) * BPB_SecPerClus + FirstDataSector
  1360.         mov     ax, di
  1361.         sub     ax, 2
  1362.         xor     bx, bx
  1363.         mov     bl, byte [BPB_SecPerClus]
  1364.         mul     bx
  1365.         add     ax, word [FirstDataSector]
  1366.         call    conv_abs_to_THS
  1367.         pop     bx
  1368.         push    bx
  1369.         mov     al, byte [BPB_SecPerClus]       ; number of sectors in cluster
  1370.         call    boot_read_floppy
  1371.         push    es
  1372.         push    ds
  1373.         pop     es
  1374.         pusha
  1375. ;
  1376.         mov     ax, word [BPB_BytsPerSec]
  1377.         xor     cx, cx
  1378.         mov     cl, byte [BPB_SecPerClus]
  1379.         mul     cx
  1380.         shr     ax, 1                           ; ax = (BPB_BytsPerSec * BPB_SecPerClus)/2
  1381.         mov     cx, ax                          ; number of words to copy (count words in cluster)
  1382. ;
  1383.         mov     ah, 0x87
  1384.         int     0x15                            ; copy data
  1385.         test    ah, ah
  1386.         popa
  1387.         pop     es
  1388.         jnz     sayerr_floppy
  1389. ; skip cluster di
  1390. .skip:
  1391.         mov     ax, word [BPB_BytsPerSec]
  1392.         xor     cx, cx
  1393.         mov     cl, byte [BPB_SecPerClus]
  1394.         mul     cx
  1395.         and     eax, 0ffffh             ; ax - count of bytes in cluster
  1396.         add     dword [si+8*3+2], eax
  1397.  
  1398.         mov     ax, word [end_of_FAT]   ; max cluster number
  1399.         pusha
  1400. ; draw percentage
  1401. ; total clusters: ax
  1402. ; read clusters: di
  1403.         xchg    ax, di
  1404.         mov     cx, 100
  1405.         mul     cx
  1406.         div     di
  1407.         aam
  1408.         xchg    al, ah
  1409.         add     ax, '00'
  1410.         mov     si, pros
  1411.         cmp     [si], ax
  1412.         jz      @f
  1413.         mov     [si], ax
  1414.         call    printplain
  1415. @@:
  1416.         popa
  1417.         inc     di
  1418.         cmp     di, word [end_of_FAT]   ; max number of cluster
  1419.         jnz     .read_loop
  1420.         pop     bx                      ; clear stack
  1421.  
  1422. ok_sys_on_floppy:
  1423.         mov     si, backspace2
  1424.         call    printplain
  1425.         mov     si, okt
  1426.         call    printplain
  1427. no_sys_on_floppy:
  1428.         xor     ax, ax          ; reset drive
  1429.         xor     dx, dx
  1430.         int     0x13
  1431.         mov     dx, 0x3f2       ; floppy motor off
  1432.         mov     al, 0
  1433.         out     dx, al
  1434.  
  1435. if defined extended_primary_loader
  1436.         cmp     [boot_dev], 1
  1437.         jne     no_sys_from_primary
  1438. ; load kolibri.img using callback from primary loader
  1439.         and     word [movedesc + 24 + 2], 0
  1440.         mov     byte [movedesc + 24 + 4], 10h
  1441. ; read in blocks of 64K until file is fully loaded
  1442.         mov     ax, 1
  1443. .repeat:
  1444.         mov     di, image_file_struct
  1445.         call    [bootcallback]
  1446.         push    cs
  1447.         pop     ds
  1448.         push    cs
  1449.         pop     es
  1450.         cmp     bx, 1
  1451.         ja      sayerr_badsect
  1452.         push    bx
  1453.         mov     si, movedesc
  1454.         and     word [si + 16 + 2], 0
  1455.         mov     byte [si + 16 + 4], 4
  1456.         mov     ah, 87h
  1457.         mov     cx, 8000h
  1458.         int     15h
  1459.         pop     bx
  1460.         test    ah, ah
  1461.         jnz     sayerr_memmove
  1462.         inc     byte [si + 24 + 4]
  1463.         test    bx, bx
  1464.         jz      no_sys_from_primary
  1465.         mov     ax, 2
  1466.         jmp     .repeat
  1467. no_sys_from_primary:
  1468. end if
  1469.  
  1470. ; SET GRAPHICS
  1471.  
  1472.         xor     ax, ax
  1473.         mov     es, ax
  1474.  
  1475.         mov     ax, [es:BOOT_VESA_MODE]         ; vga & 320x200
  1476.         mov     bx, ax
  1477.         cmp     ax, 0x13
  1478.         je      setgr
  1479.         cmp     ax, 0x12
  1480.         je      setgr
  1481.         mov     ax, 0x4f02              ; Vesa
  1482. setgr:
  1483.         int     0x10
  1484.         test    ah, ah
  1485.         mov     si, fatalsel
  1486.         jnz     v_mode_error
  1487. ; set mode 0x12 graphics registers:
  1488.         cmp     bx, 0x12
  1489.         jne     gmok2
  1490.  
  1491.         mov     al, 0x05
  1492.         mov     dx, 0x03ce
  1493.         push    dx
  1494.         out     dx, al      ; select GDC mode register
  1495.         mov     al, 0x02
  1496.         inc     dx
  1497.         out     dx, al      ; set write mode 2
  1498.  
  1499.         mov     al, 0x02
  1500.         mov     dx, 0x03c4
  1501.         out     dx, al      ; select VGA sequencer map mask register
  1502.         mov     al, 0x0f
  1503.         inc     dx
  1504.         out     dx, al      ; set mask for all planes 0-3
  1505.  
  1506.         mov     al, 0x08
  1507.         pop     dx
  1508.         out     dx, al      ; select GDC bit mask register
  1509.                            ; for writes to 0x03cf
  1510. gmok2:
  1511.         push    ds
  1512.         pop     es
  1513.