Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. ; KolibriOS bootloader
  2. ; this code has been written by diamond in 2005,2006 specially for KolibriOS
  3.  
  4. ; this code is loaded by ntldr to 0D00:0000
  5. ; and by io.sys from config.sys to xxxx:0100
  6. ; and by bootmgr in vista to 0000:7C00
  7.         format  binary
  8.         use16
  9.  
  10.         org     0xD000
  11.  
  12. ; entry point for 9x booting
  13.         call    @f
  14. ;       db      'd' xor 'i' xor 'a' xor 'm' xor 'o' xor 'n' xor 'd'
  15.         db      'NTFS'
  16.  
  17. ; file offset +7
  18. ; may be changed by installator
  19. boot_drive      db      80h
  20. partition_start dd      -1
  21. imgnameofs      dw      menuet_img_name
  22.  
  23. @@:
  24.         pop     si
  25.         sub     si, 3
  26.         cmp     si, 7C00h
  27.         jz      boot_vista
  28.         mov     si, load_question + 100h - 0D000h
  29.         call    out_string
  30.         mov     si, answer + 100h - 0D000h
  31. xxy:    mov     ah, 0
  32.         int     16h
  33.         or      al, 20h
  34.         mov     [si], al
  35.         cmp     al, 'y'
  36.         jz      xxz
  37.         cmp     al, 'n'
  38.         jnz     xxy
  39. ; continue load Windows
  40. ;       call    out_string
  41. ;       ret
  42. out_string:
  43.         lodsb
  44.         test    al, al
  45.         jz      .xxx
  46.         mov     ah, 0Eh
  47.         mov     bx, 7
  48.         int     10h
  49.         jmp     out_string
  50. .xxx:   ret
  51. xxz:
  52. ; boot KolibriOS
  53.         call    out_string
  54.         push    0
  55.         pop     ds
  56.         mov     word [4], new01handler + 100h - 0D000h
  57.         mov     [6], cs
  58.         pushf
  59.         pop     ax
  60.         or      ah, 1
  61.         push    ax
  62.         popf
  63. ;       int     19h
  64. ;       pushf           ; there will be no iret
  65.         call    far [19h*4]
  66. xxt:
  67. ; TF has been cleared when entered new01handler
  68. ;       pushf
  69. ;       pop     ax
  70. ;       and     ah, not 1
  71. ;       push    ax
  72. ;       popf
  73.         push    0
  74.         pop     ds
  75.         cmp     word [8*4+2], 0F000h
  76.         jz      @f
  77.         les     bx, [8*4]
  78.         mov     eax, [es:bx+1]
  79.         mov     [8*4], eax
  80. @@:
  81.         mov     si, 100h
  82. boot_vista:
  83.         xor     di, di
  84.         push    cs
  85.         pop     ds
  86.         push    0D00h
  87.         pop     es
  88.         mov     cx, 2000h/2
  89.         rep     movsw
  90.         jmp     0D00h:0256h
  91.  
  92. new01handler:
  93. ; [sp]=ip, [sp+2]=cs, [sp+4]=flags
  94.         push    bp
  95.         mov     bp, sp
  96.         push    bx
  97.         push    ds
  98.         lds     bx, [bp+2]
  99.         cmp     word [bx], 19cdh
  100.         jz      xxt
  101.         pop     ds
  102.         pop     bx
  103.         pop     bp
  104.         iret
  105.  
  106. relative_read:
  107.         add     eax, [partition_start]
  108.  
  109. ; read from hard disk
  110. ; drive_size must be already initialized
  111. ; in: eax = absolute sector
  112. ;     cx = number of sectors
  113. ;     es:bx -> buffer
  114. read:
  115.         pushad
  116.         cmp     eax, [drive_size]
  117.         jb      .old_style
  118.         xor     dx, dx
  119. ; new style - LBA, function 42
  120.         cmp     [has_lba], dl
  121.         jz      disk_error
  122. ; allocate disk address packet on the stack
  123. ; qword +8: absolute block number
  124.         push    dx
  125.         push    dx
  126. ;       push    dword 0         ; dword +C is high dword
  127.         push    eax             ; dword +8 is low dword
  128. ; dword +4: buffer address
  129.         push    es              ; word +6 is segment
  130.         push    bx              ; word +4 is offset
  131. ; word +2: number of blocks = 1
  132.         push    1
  133. ; word +0: size of packet = 10h
  134.         push    10h
  135. ; now pair ss:sp contain address of disk address packet
  136. .patch1:
  137.         mov     ax, 4200h
  138.         mov     dl, [boot_drive]
  139.         mov     si, sp
  140.         push    ds
  141.         push    ss
  142.         pop     ds
  143.         int     13h
  144.         pop     ds
  145.         lea     sp, [si+10h]
  146. .end:
  147.         popad
  148.         jc      disk_error
  149.         add     bx, 200h
  150.         inc     eax
  151.         dec     cx
  152.         jnz     read
  153.         ret
  154. .old_style:
  155. ; old style - CHS, function 2
  156. ; convert absolute sector in eax to cylinder-head-sector coordinates
  157. ; calculate sector
  158.         xor     edx, edx
  159.         movzx   ecx, [sectors]
  160.         div     ecx
  161. ; sectors are counted from 1
  162.         inc     dl
  163.         mov     cl, dl          ; low 6 bits of cl = sector number
  164. ; calculate head number
  165. ;       shld    edx, eax, 10h   ; convert eax to dx:ax
  166.         push    eax
  167.         pop     ax
  168.         pop     dx
  169.         div     [heads]
  170.         mov     dh, dl          ; dh = head
  171.         mov     ch, al          ; ch = low 8 bits of cylinder
  172.         shl     ah, 6
  173.         or      cl, ah          ; high 2 bits of cl = high 2 bits of cylinder
  174. .patch2:
  175.         mov     ax, 201h        ; function 2, al=1 - number of sectors
  176.         mov     dl, [boot_drive]
  177.         int     13h
  178.         jmp     .end
  179.  
  180. disk_error:
  181.         mov     si, disk_error_msg
  182.         call    out_string
  183.         jmp     $
  184.  
  185. answer  db      ?
  186.         db      13,10
  187. has_lba db      0
  188.  
  189. disk_error_msg  db      'Disk read error!',0
  190. start_msg       db      2,' KolibriOS bootloader, running on ',0
  191. errfs_msg       db      'unknown filesystem, cannot continue',0
  192. fat16_msg       db      'FAT12/FAT16 - unsupported',13,10,0
  193. fat32_msg       db      'FAT32',13,10,0
  194. ntfs_msg        db      'NTFS',13,10,0
  195. error_msg       db      'Error'
  196. colon           db      ': ',0
  197. mft_string      db      'MFT',0
  198. root_string     db      '\',0
  199. noindex_string  db      '$INDEX_ROOT not found',0
  200. invalid_read_request_string db 'cannot read attribute',0
  201. nodata_string   db      '$DATA '
  202. notfound_string db      'not found',0
  203. directory_string db     'is a directory',0
  204. notdir_string   db      'not a directory',0
  205. fragmented_string db    'too fragmented file',0
  206. bad_cluster_string db   'bad cluster',0
  207. exmem_string    db      'extended memory error',0
  208.  
  209. load_question   db      'Load KolibriOS? [y/n]: ',0
  210.  
  211.         repeat  0D256h - $
  212.                 db      1
  213.         end     repeat
  214.  
  215. start:
  216.         xor     ax, ax
  217.         mov     ds, ax
  218.         mov     es, ax
  219. ; our stack is 4Kb-2b!!! (0xFFE)
  220.         mov     ss, ax
  221.         mov     esp, 0FFFEh
  222.         cld
  223.         sti
  224. ; calculate drive size
  225.         mov     dl, [boot_drive]
  226.         mov     ah, 8   ; 8 = get drive parameters
  227.         int     13h
  228. ; now: CF is set on error;
  229. ; ch = low 8 bits of maximum cylinder number
  230. ; cl : low 6 bits makes maximum sector number, high 2 bits are high 2 bits of maximum cylinder number
  231. ; dh = maximum head number
  232.         jnc     @f
  233.         mov     cx, -1
  234.         mov     dh, cl
  235. @@:
  236.         movzx   ax, dh
  237.         inc     ax
  238. ; ax = number of heads
  239.         mov     [heads], ax
  240.         mov     dl, cl
  241.         and     dx, 3Fh
  242. ; dx = number of sectors
  243. ; (note that sectors are counted from 1, and maximum sector number = number of sectors)
  244.         mov     [sectors], dx
  245.         mul     dx
  246.         xchg    cl, ch
  247.         shr     ch, 6
  248.         inc     cx
  249. ; cx = number of cylinders
  250.         mov     [cyls], cx
  251.         mul     cx
  252.         mov     word [drive_size], ax
  253.         mov     word [drive_size+2], dx
  254. ; this drive supports LBA?
  255.         mov     dl, [boot_drive]
  256.         mov     ah, 41h
  257.         mov     bx, 55AAh
  258.         int     13h
  259.         jc      .no_lba
  260.         cmp     bx, 0AA55h
  261.         jnz     .no_lba
  262.         test    cl, 1
  263.         jz      .no_lba
  264.         inc     [has_lba]
  265. .no_lba:
  266. ; say hi to user
  267.         mov     si, start_msg
  268.         call    out_string
  269.         mov     eax, [partition_start]
  270.         cmp     eax, -1
  271.         jnz     @f
  272. ; now read first sector to determine file system type
  273. ; first sector of disk is MBR sector
  274.         xor     eax, eax
  275.         mov     cx, 1
  276.         mov     bx, 500h
  277.         call    read
  278.         mov     eax, [6C6h]     ; first disk
  279.         mov     [partition_start], eax
  280. @@:
  281.         mov     cx, 1
  282.         mov     bx, 500h
  283.         call    read
  284.         movzx   ax, byte [50Dh]
  285.         mov     [sect_per_clust], ax
  286. ; determine file system
  287.         cmp     dword [536h], 'FAT1'
  288.         jz      fat1x
  289.         cmp     dword [552h], 'FAT3'
  290.         jz      fat32
  291.         cmp     dword [503h], 'NTFS'
  292.         jz      ntfs
  293. ;       mov     si, errfs_msg           ; already is
  294.         call    out_string
  295.         jmp     $
  296. fat1x:
  297.         mov     si, fat16_msg
  298.         call    out_string
  299.         jmp     $
  300. fat32:
  301.         mov     si, fat32_msg
  302.         call    out_string
  303.         movzx   eax, word [50Bh]        ; bytes_per_sect
  304.         movzx   ebx, byte [50Dh]        ; sects_per_clust
  305.         mul     ebx
  306.         mov     [cluster_size], eax
  307.         movzx   ebx, word [50Eh]        ; reserved_sect
  308.         mov     [fat_start], ebx
  309.         movzx   eax, byte [510h]        ; num_fats
  310.         mul     dword [524h]            ; sect_fat
  311.         add     eax, ebx
  312. ; cluster 2 begins from sector eax
  313.         movzx   ebx, byte [50Dh]        ; sects_per_clust
  314.         sub     eax, ebx
  315.         sub     eax, ebx
  316.         mov     [data_start], eax
  317. ; parse image name
  318.         mov     eax, [52Ch]     ; root_cluster
  319.         mov     [cur_obj], root_string
  320. .parsedir:
  321.         push    ax
  322.         mov     si, [imgnameofs]
  323.         push    si
  324. @@:
  325.         lodsb
  326.         cmp     al, '\'
  327.         jz      @f
  328.         cmp     al, 0
  329.         jnz     @b
  330. @@:
  331.         xchg    ax, [esp+2]
  332.         mov     byte [si-1], 0
  333.         mov     [imgnameofs], si
  334.         call    fat32_parse_dir
  335.         pop     cx
  336.         test    cl, cl
  337.         jz      .end
  338.         test    byte [di+0Bh], 10h
  339.         mov     si, notdir_string
  340.         jz      find_error_si
  341.         jmp     .parsedir
  342. .end:
  343.         test    byte [di+0Bh], 10h
  344.         mov     si, directory_string
  345.         jnz     find_error_si
  346. ; parse FAT chunk
  347. ; runlist at 2000:0000
  348.         mov     di, 5
  349.         push    2000h
  350.         pop     es
  351.         mov     byte [es:di-5], 1       ; of course, non-resident
  352.         mov     dword [es:di-4], 1
  353.         stosd
  354. .parsefat:
  355.         push    es
  356.         push    ds
  357.         pop     es
  358.         call    next_cluster
  359.         pop     es
  360.         jnc     .done
  361.         mov     ecx, [es:di-8]
  362.         add     ecx, [es:di-4]
  363.         cmp     eax, ecx
  364.         jz      .contc
  365.         mov     dword [es:di], 1
  366.         scasd
  367.         stosd
  368.         jmp     .parsefat
  369. .contc:
  370.         inc     dword [es:di-8]
  371.         jmp     .parsefat
  372. .done:
  373.         xor     eax, eax
  374.         stosd
  375.         jmp     read_img_file
  376.  
  377. ntfs:
  378.         mov     si, ntfs_msg
  379.         call    out_string
  380.         movzx   eax, word [50Bh]        ; bpb_bytes_per_sect
  381.         push    eax
  382.         movzx   ebx, byte [50Dh]        ; bpb_sects_per_clust
  383.         mul     ebx
  384.         mov     [cluster_size], eax
  385.         mov     [data_start], 0
  386.         mov     ecx, [540h]             ; frs_size
  387.         cmp     cl, 0
  388.         jg      .1
  389.         neg     cl
  390.         xor     eax, eax
  391.         inc     eax
  392.         shl     eax, cl
  393.         jmp     .2
  394. .1:
  395.         mul     ecx
  396. .2:
  397.         mov     [frs_size], eax
  398.         pop     ebx
  399.         xor     edx, edx
  400.         div     ebx
  401.         mov     [frs_sectors], ax
  402. ; read first MFT record - description of MFT itself
  403.         mov     [cur_obj], mft_string
  404.         movzx   eax, byte [50Dh]        ; bpb_sects_per_clust
  405.         mul     dword [530h]            ; mft_cluster
  406.         mov     cx, [frs_sectors]
  407.         mov     bx, 4000h
  408.         mov     di, bx
  409.         push    bx
  410.         call    relative_read
  411.         call    restore_usa
  412. ; scan for unnamed $DATA attribute
  413.         pop     di
  414.         mov     ax, 80h         ; $DATA
  415.         mov     bx, 700h
  416.         call    load_attr
  417.         mov     si, nodata_string
  418.         jc      find_error_si
  419.         mov     [free], bx
  420. ; load menuet.img
  421. ; parse image name
  422.         mov     eax, 5          ; root cluster
  423.         mov     [cur_obj], root_string
  424. .parsedir:
  425.         push    ax
  426.         mov     si, [imgnameofs]
  427.         push    si
  428. @@:
  429.         lodsb
  430.         cmp     al, '\'
  431.         jz      @f
  432.         cmp     al, 0
  433.         jnz     @b
  434. @@:
  435.         xchg    ax, [esp+2]
  436.         mov     byte [si-1], 0
  437.         mov     [imgnameofs], si
  438.         call    ntfs_parse_dir
  439.         pop     cx
  440.         test    cl, cl
  441.         jnz     .parsedir
  442. read_img_file:
  443.         xor     si, si
  444.         push    es
  445.         pop     fs
  446. ; yes! Now read file to 0x100000
  447.         lods byte [fs:si]
  448.         cmp     al, 0   ; assume nonresident attr
  449.         mov     si, invalid_read_request_string
  450.         jz      find_error_si
  451.         mov     si, 1
  452.         xor     edi, edi
  453. ; read buffer to 1000:0000 and move it to extended memory
  454.         push    1000h
  455.         pop     es
  456.         xor     bx, bx
  457. .img_read_block:
  458.         lods dword [fs:si]              ; eax=length
  459.         xchg    eax, ecx
  460.         jecxz   .img_read_done
  461.         lods dword [fs:si]              ; eax=disk cluster
  462. .img_read_cluster:
  463.         pushad
  464. ; read part of file
  465.         movzx   ecx, byte [50Dh]
  466.         mul     ecx
  467.         add     eax, [data_start]
  468.         call    relative_read
  469. ; move it to extended memory
  470.         mov     ah, 87h
  471.         mov     ecx, [cluster_size]
  472.         push    ecx
  473.         shr     cx, 1
  474.         mov     si, movedesc
  475.         push    es
  476.         push    ds
  477.         pop     es
  478.         int     15h
  479.         pop     es
  480.         test    ah, ah
  481.         mov     si, exmem_string
  482.         jnz     find_error_si
  483.         pop     ecx
  484.         add     [dest_addr], ecx
  485.         popad
  486.         inc     eax
  487.         loop    .img_read_cluster
  488.         jmp     .img_read_block
  489. .img_read_done:
  490. ; menuet.img loaded; now load kernel.mnt
  491. load_kernel:
  492.         push    ds
  493.         pop     es
  494.         mov     [cur_obj], kernel_mnt_name
  495. ; read boot sector
  496.         xor     eax, eax
  497.         mov     bx, 500h
  498.         mov     cx, 1
  499.         call    read_img
  500. ; init vars
  501.         mov     ax, [50Eh]      ; reserved_sect
  502.         add     ax, [51Ch]      ; hidden
  503.         mov     word [fat_start], ax
  504.         xchg    ax, bx
  505.         movzx   ax, byte [510h]         ; num_fats
  506.         mul     word [516h]             ; fat_length
  507.         add     ax, bx
  508. ; read root dir
  509.         mov     bx, 700h
  510.         mov     cx, [511h]      ; dir_entries
  511.         add     cx, 0Fh
  512.         shr     cx, 4
  513.         call    read_img
  514.         add     ax, cx
  515.         mov     [img_data_start], ax
  516.         shl     cx, 9
  517.         mov     di, bx
  518.         add     bx, cx
  519.         mov     byte [bx], 0
  520. .scan_loop:
  521.         cmp     byte [di], 0
  522.         mov     si, notfound_string
  523.         jz      find_error_si
  524.         mov     si, kernel_mnt_name
  525.         call    fat_compare_name
  526.         jz      .found
  527.         and     di, not 1Fh
  528.         add     di, 20h
  529.         jmp     .scan_loop
  530. .found:
  531.         and     di, not 1Fh
  532.         mov     si, directory_string
  533.         test    byte [di+0Bh], 10h
  534.         jnz     find_error_si
  535. ; found, now load it to 1000h:0000h
  536.         mov     ax, [di+1Ah]
  537. ; first cluster of kernel.mnt in ax
  538. ; translate it to sector on disk in menuet.img
  539.         push    ax
  540.         dec     ax
  541.         dec     ax
  542.         movzx   cx, byte [50Dh]
  543.         mul     cx
  544.         add     ax, [img_data_start]
  545. ; now ax is sector in menuet.img
  546.         mov     [kernel_mnt_in_img], ax
  547.         div     [sect_per_clust]
  548. ; now ax is cluster in menuet.img and
  549. ; dx is offset from the beginning of cluster
  550.         movzx   eax, ax
  551.         push    2000h
  552.         pop     ds
  553.         mov     si, 1
  554. .scani:
  555.         sub     eax, [si]
  556.         jb      .scanidone
  557. ; sanity check
  558.         cmp     dword [si], 0
  559.         push    invalid_read_request_string
  560.         jz      find_error_sp
  561.         pop     cx
  562. ; next chunk
  563.         add     si, 8
  564.         jmp     .scani
  565. .scanidone:
  566.         add     eax, [si]       ; undo last subtract
  567.         add     eax, [si+4]     ; get cluster
  568.         push    0
  569.         pop     ds
  570.         movzx   ecx, [sect_per_clust]
  571.         push    dx
  572.         mul     ecx             ; get sector
  573.         pop     dx
  574.         movzx   edx, dx
  575.         add     eax, edx
  576.         add     eax, [data_start]
  577.         mov     [kernel_mnt_1st], eax
  578.         pop     ax
  579.         push    1000h
  580.         pop     es
  581. .read_loop:
  582.         push    ax
  583.         xor     bx, bx
  584.         call    img_read_cluster
  585.         shl     cx, 9-4
  586.         mov     ax, es
  587.         add     ax, cx
  588.         mov     es, ax
  589.         pop     ax
  590.         call    img_next_cluster
  591.         jc      .read_loop
  592.         mov     ax, 'KL'
  593.         mov     si, loader_block
  594.         jmp     1000h:0000h
  595.  
  596. img_next_cluster:
  597.         mov     bx, 700h
  598.         push    ax
  599.         shr     ax, 1
  600.         add     ax, [esp]
  601.         mov     dx, ax
  602.         shr     ax, 9
  603.         add     ax, word [fat_start]
  604.         mov     cx, 2
  605.         push    es
  606.         push    ds
  607.         pop     es
  608.         call    read_img
  609.         pop     es
  610.         and     dx, 1FFh
  611.         add     bx, dx
  612.         mov     ax, [bx]
  613.         pop     cx
  614.         test    cx, 1
  615.         jz      .1
  616.         shr     ax, 4
  617. .1:
  618.         and     ax, 0FFFh
  619.         mov     si, bad_cluster_string
  620.         cmp     ax, 0FF7h
  621.         jz      find_error_si
  622.         ret
  623. img_read_cluster:
  624.         dec     ax
  625.         dec     ax
  626.         movzx   cx, byte [50Dh] ; sects_per_clust
  627.         mul     cx
  628.         add     ax, [img_data_start]
  629.         movzx   eax, ax
  630. ;       call    read_img
  631. ;       ret
  632. read_img:
  633. ; in: ax = sector, es:bx->buffer, cx=length in sectors
  634.         pushad
  635.         movzx   ebx, bx
  636.         mov     si, movedesc
  637.         shl     eax, 9
  638.         add     eax, 93100000h
  639.         mov     dword [si+sou_addr-movedesc], eax
  640.         mov     eax, 9300000h
  641.         mov     ax, es
  642.         shl     eax, 4
  643.         add     eax, ebx
  644.         mov     [si+dest_addr-movedesc], eax
  645.         mov     ah, 87h
  646.         shl     cx, 8   ; mul 200h/2
  647.         push    es
  648.         push    0
  649.         pop     es
  650.         int     15h
  651.         pop     es
  652.         cmp     ah, 0
  653.         mov     si, exmem_string
  654.         jnz     find_error_si
  655.         popad
  656.         ret
  657.  
  658. movedesc:
  659.         times 16 db 0
  660. ; source
  661.         dw      0xFFFF          ; segment length
  662. sou_addr dw     0000h           ; linear address
  663.         db      1               ; linear address
  664.         db      93h             ; access rights
  665.         dw      0
  666. ; destination
  667.         dw      0xFFFF          ; segment length
  668. dest_addr dd    93100000h       ; high byte contains access rights
  669.                                 ; three low bytes contains linear address (updated when reading)
  670.         dw      0
  671.         times 32 db 0
  672.  
  673. find_error_si:
  674.         push    si
  675. find_error_sp:
  676.         mov     si, error_msg
  677.         call    out_string
  678.         mov     si, [cur_obj]
  679.         call    out_string
  680.         mov     si, colon
  681.         call    out_string
  682.         pop     si
  683.         call    out_string
  684.         jmp     $
  685.  
  686. file_not_found:
  687.         mov     si, [esp+2]
  688.         mov     [cur_obj], si
  689.         push    notfound_string
  690.         jmp     find_error_sp
  691.  
  692.         include 'fat32.inc'
  693.         include 'ntfs.inc'
  694.  
  695. write1st:
  696. ; callback from kernel.mnt
  697. ; write first sector of kernel.mnt from 1000:0000 back to disk
  698.         push    cs
  699.         pop     ds
  700.         push    cs
  701.         pop     es
  702. ; sanity check
  703.         mov     bx, 500h
  704.         mov     si, bx
  705.         mov     cx, 1
  706.         push    cx
  707.         mov     eax, [kernel_mnt_1st]
  708.         push    eax
  709.         call    relative_read
  710.         push    1000h
  711.         pop     es
  712.         xor     di, di
  713.         mov     cx, 8
  714.         repz    cmpsw
  715.         mov     si, data_error_msg
  716.         jnz     find_error_si
  717. ; ok, now write back to disk
  718.         or      byte [read.patch1+2], 1
  719.         or      byte [read.patch2+2], 1
  720.         xor     bx, bx
  721.         pop     eax
  722.         pop     cx
  723.         call    relative_read
  724.         and     byte [read.patch1+1], not 1
  725.         and     byte [read.patch2+2], not 2
  726. ; and to image in memory (probably this may be done by kernel.mnt itself?)
  727.         mov     dword [sou_addr], 93010000h
  728.         movzx   eax, [kernel_mnt_in_img]
  729.         shl     eax, 9
  730.         add     eax, 93100000h
  731.         mov     dword [dest_addr], eax
  732.         mov     si, movedesc
  733.         push    ds
  734.         pop     es
  735.         mov     ah, 87h
  736.         mov     cx, 100h
  737.         int     15h
  738.         cmp     ah, 0
  739.         mov     si, exmem_string
  740.         jnz     find_error_si
  741.         retf
  742.  
  743. loader_block:
  744.         db      1       ; version
  745.         dw      1       ; flags - image is loaded
  746.         dw      write1st        ; offset
  747.         dw      0               ; segment
  748.  
  749. fat_cur_sector dd -1
  750.  
  751. data_error_msg db       'data error',0
  752.  
  753. ; -----------------------------------------------
  754. ; ------------------ Settings -------------------
  755. ; -----------------------------------------------
  756.  
  757. ; must be in lowercase, see ntfs_parse_dir.scan, fat32_parse_dir.scan
  758. kernel_mnt_name         db      'kernel.mnt',0
  759.  
  760. ; will be initialized by installer
  761. menuet_img_name         rb      300
  762.  
  763. ; uninitialized data follows
  764. drive_size              dd      ?       ; in sectors
  765. heads                   dw      ?
  766. sectors                 dw      ?
  767. cyls                    dw      ?
  768. free                    dw      ?
  769. cur_obj                 dw      ?
  770. data_start              dd      ?
  771. img_data_start          dw      ?
  772. sect_per_clust          dw      ?
  773. kernel_mnt_in_img       dw      ?
  774. kernel_mnt_1st          dd      ?
  775. ; NTFS data
  776. cluster_size            dd      ?       ; in bytes
  777. frs_size                dd      ?       ; in bytes
  778. frs_sectors             dw      ?       ; in sectors
  779. mft_data_attr           dw      ?
  780. index_root              dw      ?
  781. index_alloc             dw      ?
  782. ofs                     dw      ?
  783. dir                     dw      ?
  784. ; FAT32 data
  785. fat_start               dd      ?
  786. cur_cluster             dd      ?
  787.