Subversion Repositories Kolibri OS

Rev

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