Subversion Repositories Kolibri OS

Rev

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

  1. ; Copyright (c) 2008-2009, diamond
  2. ; All rights reserved.
  3. ;
  4. ; Redistribution and use in source and binary forms, with or without
  5. ; modification, are permitted provided that the following conditions are met:
  6. ;       * Redistributions of source code must retain the above copyright
  7. ;       notice, this list of conditions and the following disclaimer.
  8. ;       * Redistributions in binary form must reproduce the above copyright
  9. ;       notice, this list of conditions and the following disclaimer in the
  10. ;       documentation and/or other materials provided with the distribution.
  11. ;       * Neither the name of the <organization> nor the
  12. ;       names of its contributors may be used to endorse or promote products
  13. ;       derived from this software without specific prior written permission.
  14. ;
  15. ; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka <Lrz> ''AS IS'' AND ANY
  16. ; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  17. ; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  18. ; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
  19. ; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  20. ; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  21. ; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  22. ; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  23. ; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  24. ; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. ;*****************************************************************************
  26.  
  27. use_lba = 0
  28.         org     0x7C00
  29.         jmp     start
  30.         nop
  31. ; FAT parameters, BPB
  32. ; note: they can be changed at install, replaced with real values
  33. ; these settings are for most typical 1.44M floppies
  34.                 db      'KOLIBRI '      ; BS_OEMName, ignored
  35.                 dw      200h            ; BPB_BytsPerSec
  36. BPB_SecsPerClus db      1
  37. BPB_RsvdSecCnt  dw      1
  38. BPB_NumFATs     db      2
  39. BPB_RootEntCnt  dw      0xE0
  40.                 dw      2880            ; BPB_TotSec16
  41.                 db      0xF0            ; BPB_Media
  42. BPB_FATSz16     dw      9
  43. BPB_SecPerTrk   dw      18
  44. BPB_NumHeads    dw      2
  45. BPB_HiddSec     dd      0
  46.                 dd      0               ; BPB_TotSec32
  47. BS_DrvNum       db      0
  48.                 db      0               ; BS_Reserved1
  49.                 db      ')'             ; BS_BootSig
  50.                 dd      12344321h       ; BS_VolID
  51. filename:
  52.                 db      'KORD.OS    '   ; BS_VolLab
  53.                 db      'FAT12   '      ; BS_FilSysType
  54. ; Used memory map:
  55. ;       8000:0000 - current directory
  56. ;       9000:0000 - root directory data [cached]
  57. start:
  58.         xor     ax, ax
  59.         mov     ss, ax
  60.         mov     sp, 0x7C00
  61.         mov     ds, ax
  62.         mov     bp, sp
  63.         cld
  64.         sti
  65.         mov     [bp+BS_DrvNum-0x7C00], dl
  66. if use_lba
  67.         mov     ah, 41h
  68.         mov     bx, 55AAh
  69.         int     13h
  70.         mov     si, aNoLBA
  71.         jc      err_
  72.         cmp     bx, 0AA55h
  73.         jnz     err_
  74.         test    cx, 1
  75.         jz      err_
  76. else
  77.         mov     ah, 8
  78.         int     13h
  79.         jc      @f              ; on error, assume that BPB geometry is valid
  80.         mov     al, dh
  81.         mov     ah, 0
  82.         inc     ax
  83.         mov     [bp+BPB_NumHeads-0x7C00], ax
  84.         and     cx, 3Fh
  85.         mov     [bp+BPB_SecPerTrk-0x7C00], cx
  86. @@:
  87. end if
  88. ; get FAT parameters
  89.         xor     bx, bx
  90.         mov     al, [bp+BPB_NumFATs-0x7C00]
  91.         mov     ah, 0
  92.         mul     [bp+BPB_FATSz16-0x7C00]
  93.         add     ax, [bp+BPB_RsvdSecCnt-0x7C00]
  94.         adc     dx, bx
  95.         push    dx
  96.         push    ax      ; root directory start = dword [bp-4]
  97.         mov     cx, [bp+BPB_RootEntCnt-0x7C00]
  98.         add     cx, 0xF
  99.         rcr     cx, 1
  100.         shr     cx, 3   ; cx = size of root directory in sectors
  101.         add     ax, cx
  102.         adc     dx, bx
  103.         push    dx
  104.         push    ax      ; data start = dword [bp-8]
  105. ; load start of root directory (no more than 0x2000 bytes = 0x10 sectors)
  106.         cmp     cx, 0x10
  107.         jb      @f
  108.         mov     cx, 0x10
  109. @@:
  110.         mov     ax, [bp-4]
  111.         mov     dx, [bp-2]
  112.         push    0x9000
  113.         pop     es
  114.         call    read_sectors
  115.         add     word [bp-4], cx         ; dword [bp-4] = start of non-cached root data
  116.         adc     word [bp-2], bx
  117. ; load kordldr.f12
  118.         mov     si, main_loader
  119.         call    lookup_in_root_dir
  120.         jc      noloader
  121.         test    byte [es:di+11], 10h    ; directory?
  122.         jz      kordldr_ok
  123. noloader:
  124.         mov     si, aLoaderNotFound
  125. err_:
  126.         call    out_string
  127.         mov     si, aPressAnyKey
  128.         call    out_string
  129.         xor     ax, ax
  130.         int     16h
  131.         int     18h
  132.         jmp     $
  133. kordldr_ok:
  134.         mov     ax, [es:di+26]          ; get file cluster
  135.         mov     bx, 0x7E00
  136.         xor     cx, cx
  137.         mov     es, cx
  138.         sub     ax, 2
  139.         jc      noloader
  140.         push    bx      ; save return address: bx = 7E00
  141.         mov     cl, [bp+BPB_SecsPerClus-0x7C00]
  142.         mul     cx
  143. ; fall through - 'ret' in read_sectors will return to 7E00
  144.  
  145. read_sectors2:
  146. ; same as read_sectors, but dx:ax is relative to start of data
  147.         add     ax, [bp-8]
  148.         adc     dx, [bp-6]
  149. read_sectors:
  150. ; ss:bp = 0:7C00
  151. ; es:bx = pointer to data
  152. ; dx:ax = first sector
  153. ; cx = number of sectors
  154.         pusha
  155.         add     ax, word [bp+BPB_HiddSec-0x7C00]
  156.         adc     dx, word [bp+BPB_HiddSec+2-0x7C00]
  157. if use_lba
  158.         push    ds
  159. do_read_sectors:
  160.         push    ax
  161.         push    cx
  162.         push    dx
  163.         cmp     cx, 0x7F
  164.         jbe     @f
  165.         mov     cx, 0x7F
  166. @@:
  167. ; create disk address packet on the stack
  168. ; dq starting LBA
  169.         push    0
  170.         push    0
  171.         push    dx
  172.         push    ax
  173. ; dd buffer
  174.         push    es
  175.         push    bx
  176. ; dw number of blocks to transfer (no more than 0x7F)
  177.         push    cx
  178. ; dw packet size in bytes
  179.         push    10h
  180. ; issue BIOS call
  181.         push    ss
  182.         pop     ds
  183.         mov     si, sp
  184.         mov     dl, [bp+BS_DrvNum-0x7C00]
  185.         mov     ah, 42h
  186.         int     13h
  187.         mov     si, aReadError
  188.         jc      err_
  189. ; restore stack
  190.         add     sp, 10h
  191. ; increase current sector & buffer; decrease number of sectors
  192.         mov     si, cx
  193.         mov     ax, es
  194.         shl     cx, 5
  195.         add     ax, cx
  196.         mov     es, ax
  197.         pop     dx
  198.         pop     cx
  199.         pop     ax
  200.         add     ax, si
  201.         adc     dx, 0
  202.         sub     cx, si
  203.         jnz     do_read_sectors
  204.         pop     ds
  205.         popa
  206.         ret
  207. else
  208. do_read_sectors:
  209.         pusha
  210.         pop     di
  211.         push    bx
  212.  
  213. ; (dword in dx:ax) / (SectorsPerTrack) -> (dword in dx:ax), remainder bx
  214.         mov     si, ax
  215.         xchg    ax, dx
  216.         xor     dx, dx
  217.         div     [bp+BPB_SecPerTrk-0x7C00]
  218.         push    ax
  219.         mov     ax, si
  220.         div     [bp+BPB_SecPerTrk-0x7C00]
  221.         mov     bx, dx          ; bx=sector-1
  222.         pop     dx
  223.  
  224. ; (dword in dx:ax) / (NumHeads) -> (word in ax), remainder dx
  225.         div     [bp+BPB_NumHeads-0x7C00]
  226.  
  227. ; number of sectors: read no more than to end of track
  228.         push    bx
  229.         sub     bx, [bp+BPB_SecPerTrk-0x7C00]
  230.         neg     bx
  231.         cmp     cx, bx
  232.         jbe     @f
  233.         mov     cx, bx
  234. @@:
  235.         pop     bx
  236.  
  237.         inc     bx
  238. ; now ax=track, dl=head, dh=0, cl=number of sectors, ch=0, bl=sector; convert to int13 format
  239.         mov     di, cx
  240.         mov     dh, dl
  241.         mov     dl, [bp+BS_DrvNum-0x7C00]
  242.         shl     ah, 6
  243.         mov     ch, al
  244.         mov     al, cl
  245.         mov     cl, bl
  246.         or      cl, ah
  247.         pop     bx
  248.         mov     si, 3
  249.         mov     ah, 2
  250. @@:
  251.         push    ax
  252.         int     13h
  253.         jnc     @f
  254.         xor     ax, ax
  255.         int     13h     ; reset drive
  256.         pop     ax
  257.         dec     si
  258.         jnz     @b
  259.         mov     si, aReadError
  260.         jmp     err_
  261. @@:
  262.         pop     ax
  263.         mov     ax, es
  264.         mov     cx, di
  265.         shl     cx, 5
  266.         add     ax, cx
  267.         mov     es, ax
  268.         push    di
  269.         popa
  270.         add     ax, di
  271.         adc     dx, 0
  272.         sub     cx, di
  273.         jnz     do_read_sectors
  274.         popa
  275.         ret
  276. end if
  277.  
  278. scan_for_filename:
  279. ; in: ds:si -> 11-bytes FAT name
  280. ; in: es:0 -> part of directory data
  281. ; in: cx = number of entries
  282. ; out: if found: CF=0, ZF=1, es:di -> directory entry
  283. ; out: if not found, but continue required: CF=1 and ZF=0
  284. ; out: if not found and zero item reached: CF=1 and ZF=1
  285.         xor     di, di
  286.         push    cx
  287. sloop:
  288.         cmp     byte [es:di], 0
  289.         jz      snotfound
  290.         test    byte [es:di+11], 8      ; volume label?
  291.         jnz     scont                   ; ignore volume labels
  292.         pusha
  293.         mov     cx, 11
  294.         repz    cmpsb
  295.         popa
  296.         jz      sdone
  297. scont:
  298.         add     di, 0x20
  299.         loop    sloop
  300.         inc     cx      ; clear ZF flag
  301. snotfound:
  302.         stc
  303. sdone:
  304.         pop     cx
  305. lrdret:
  306.         ret
  307.  
  308. lookup_in_root_dir:
  309. ; ss:bp = 0:7C00
  310. ; in: ds:si -> 11-bytes FAT name
  311. ; out: if found: CF=0, es:di -> directory entry
  312. ; out: if not found: CF=1
  313.         mov     cx, [bp+BPB_RootEntCnt-0x7C00]
  314.         push    cx
  315. ; first, look in root directory cache
  316.         push    0x9000
  317.         pop     es
  318.         test    ch, ch
  319.         jz      @f
  320.         mov     cx, 0x100
  321. @@:
  322.         mov     ax, [bp-4]
  323.         mov     dx, [bp-2]      ; dx:ax = starting sector of not cached data of root directory
  324. lrdloop:
  325.         call    scan_for_filename
  326.         pop     bx
  327.         jz      lrdret
  328.         sub     bx, cx
  329.         mov     cx, bx
  330.         stc
  331.         jz      lrdret
  332. ; read no more than 0x10000 bytes, or 0x10000/0x20 = 0x800 entries
  333.         push    cx
  334.         cmp     ch, 0x8
  335.         jb      @f
  336.         mov     cx, 0x800
  337. @@:
  338.         push    0x8000
  339.         pop     es
  340.         push    cx
  341.         push    es
  342.         xor     bx, bx
  343.         add     cx, 0xF
  344.         shr     cx, 4
  345.         call    read_sectors
  346.         pop     es
  347.         add     ax, cx
  348.         adc     dx, bx
  349.         pop     cx
  350.         jmp     lrdloop
  351.  
  352. out_string:
  353. ; in: ds:si -> ASCIIZ string
  354.         lodsb
  355.         test    al, al
  356.         jz      lrdret
  357.         mov     ah, 0Eh
  358.         mov     bx, 7
  359.         int     10h
  360.         jmp     out_string
  361.  
  362. aReadError      db      'Read error',0
  363. if use_lba
  364. aNoLBA          db      'The drive does not support LBA!',0
  365. end if
  366. aLoaderNotFound db      'Loader not found',0
  367. aPressAnyKey    db      13,10,'Press any key...',13,10,0
  368. main_loader     db      'KORDLDR F1X'
  369.  
  370. if use_lba
  371.         db      0       ; make bootsector 512 bytes in length
  372. end if
  373.  
  374. ; bootsector signature
  375.         dw      0xAA55
  376.  
  377. ; display offsets of all procedures used by kordldr.f12.asm
  378. macro show [procedure]
  379. {
  380.         bits = 16
  381.         display `procedure,' = '
  382.         repeat bits/4
  383.                 d = '0' + procedure shr (bits - %*4) and 0Fh
  384.                 if d > '9'
  385.                         d = d + 'A'-'9'-1
  386.                 end if
  387.                 display d
  388.         end repeat
  389.         display 13,10
  390. }
  391.  
  392. show read_sectors, read_sectors2, lookup_in_root_dir, scan_for_filename, err_, noloader
  393.