Subversion Repositories Kolibri OS

Rev

Rev 10051 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

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