Subversion Repositories Kolibri OS

Rev

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. ; in: ss:bp = 0:dat
  28. ; in: es:bx = address to load file
  29. ; in: ds:si -> ASCIIZ name
  30. ; in: cx = limit in sectors
  31. ; out: bx = status: bx=0 - ok, bx=1 - file is too big, only part of file has been loaded, bx=2 - file not found
  32. ; out: dx:ax = file size (0xFFFFFFFF if file not found)
  33. load_file_fat:
  34.         mov     eax, [bp + root_clus - dat]
  35.         mov     [bp + cur_obj - dat], root_string
  36.         push    es
  37.         push    bx
  38.         push    cx
  39. .parse_dir_loop:
  40. ; convert name to FAT name
  41.         push    [bp + cur_obj - dat]
  42.         push    ax
  43.         mov     [bp + cur_obj - dat], si
  44.         push    ss
  45.         pop     es
  46. ; convert ASCIIZ filename to FAT name
  47.         mov     di, fat_filename
  48.         push    di
  49.         mov     cx, 8+3
  50.         mov     al, ' '
  51.         rep     stosb
  52.         pop     di
  53.         mov     cl, 8   ; 8 symbols per name
  54.         mov     bl, 1
  55. .nameloop:
  56.         lodsb
  57.         test    al, al
  58.         jz      .namedone
  59.         cmp     al, '/'
  60.         jz      .namedone
  61.         cmp     al, '.'
  62.         jz      .namedot
  63.         dec     cx
  64.         js      .badname
  65.         cmp     al, 'a'
  66.         jb      @f
  67.         cmp     al, 'z'
  68.         ja      @f
  69.         sub     al, 'a'-'A'
  70. @@:
  71.         stosb
  72.         jmp     .nameloop
  73. .namedot:
  74.         inc     bx
  75.         jp      .badname
  76.         add     di, cx
  77.         mov     cl, 3
  78.         jmp     .nameloop
  79. .badname:
  80.         mov     si, badname_msg
  81.         jmp     find_error_si
  82. .namedone:
  83. ; scan directory
  84.         pop     ax      ; eax = cluster of directory
  85.                         ; high word of eax is preserved by operations above
  86.         push    ds
  87.         push    si
  88. ; read a folder sector-by-sector and scan
  89. ; first, try to use the cache
  90.         push    ss
  91.         pop     ds
  92.         mov     bx, -2
  93.         mov     cx, [bp + rootcache_size - dat]
  94.         cmp     [bp + root_clus - dat], eax
  95.         jz      .lookcache_root
  96.         mov     di, foldcache_mark
  97.         xor     bx, bx
  98.         mov     cx, [bp + cachelimit - dat]
  99. @@:
  100.         lea     si, [di+bx]
  101.         mov     edx, dword [foldcache_clus+si-foldcache_mark+bx]
  102.         cmp     edx, eax
  103.         jz      .cacheok
  104.         test    edx, edx
  105.         jz      .cacheadd       ; the cache has place for new entry
  106.         inc     bx
  107.         inc     bx
  108.         dec     cx
  109.         js      @b
  110. ; the folder is not present in the cache, so add it
  111. ; the cache is full; find the oldest entry and replace it with the new one
  112.         mov     bx, -2
  113.         mov     dx, [bp + cachelimit - dat]
  114. @@:
  115.         inc     bx
  116.         inc     bx
  117.         cmp     word [di+bx], dx        ; marks have values 0 through [cachelimit]
  118.         jnz     @b
  119. .cacheadd:
  120.         or      word [di+bx], 0xFFFF    ; very big value, it will be changed soon
  121.         and     [foldcache_size+di-foldcache_mark+bx], 0        ; no folder items yet
  122.         lea     si, [di+bx]
  123.         mov     dword [foldcache_clus+si-foldcache_mark+bx], eax
  124. .cacheok:
  125. ; update cache marks
  126.         mov     dx, [di+bx]
  127.         mov     cx, [foldcache_size+di-foldcache_mark+bx]
  128.         mov     di, [bp + cachelimit - dat]
  129.         add     di, di
  130. .cacheupdate:
  131.         cmp     [foldcache_mark+di], dx
  132.         adc     [foldcache_mark+di], 0
  133.         dec     di
  134.         dec     di
  135.         jns     .cacheupdate
  136.         and     [foldcache_mark+bx], 0
  137. ; done, bx contains (position in cache)*2
  138. .lookcache_root:
  139. ; bx = (position in cache)*2 for non-root folders; bx = -2 for root folder
  140.         ;mov    dx, bx
  141.         ;shl    dx, 8
  142.         ;add    dx, 0x9200
  143.         lea     dx, [bx + 0x92]
  144.         xchg    dl, dh
  145.         mov     ds, dx
  146.         mov     si, fat_filename        ; ss:si -> filename in FAT style
  147.         call    fat_scan_for_filename
  148.         jz      .lookup_done
  149. ; cache miss, read folder data from disk
  150. ; we are reading parent directory, it can result in disk read errors; restore [cur_obj]
  151.         mov     di, sp
  152.         mov     bx, [bp + cur_obj - dat]
  153.         xchg    bx, [ss:di+4]
  154.         mov     [bp + cur_obj - dat], bx
  155.         mov     bx, cx
  156.         add     bx, 0xF
  157.         shr     bx, 4
  158.         shl     cx, 5
  159.         mov     di, cx          ; es:di -> free space in cache entry
  160. ; external loop: scan clusters
  161. .folder_next_cluster:
  162. ; internal loop: scan sectors in cluster
  163.         movzx   ecx, byte [ss:0x320D]   ; BPB_SecPerClus
  164.         push    eax
  165. ; FAT12/16 root - special handling
  166.         test    eax, eax
  167.         jnz     .folder_notroot
  168.         mov     cx, [ss:0x3211]         ; BPB_RootEntCnt
  169.         mov     dx, cx
  170.         add     cx, 0xF
  171.         rcr     cx, 1
  172.         shr     cx, 3
  173.         mov     eax, [bp + root_start - dat]
  174.         jmp     .folder_next_sector
  175. .folder_notroot:
  176.         mul     ecx
  177.         add     eax, [bp + data_start - dat]
  178. .folder_next_sector:
  179.         sub     dx, 0x10
  180. ; skip first bx sectors
  181.         dec     bx
  182.         jns     .folder_skip_sector
  183.         push    cx
  184.         push    es di
  185.         push    0x8000
  186.         pop     es
  187.         xor     bx, bx
  188.         mov     cx, 1
  189.         push    es
  190.         call    read
  191.         jc      ..found_disk_error
  192. ; copy data to the cache...
  193.         pop     ds
  194.         pop     di es
  195.         cmp     di, 0x2000      ; ...if there is free space, of course
  196.         jae     @f
  197.         pusha
  198.         mov     cx, 0x100
  199.         xor     si, si
  200.         rep     movsw
  201.         mov     di, es
  202.         shr     di, 8
  203.         cmp     di, 0x90
  204.         jz      .update_rootcache_size
  205.         add     [ss:foldcache_size+di-0x92], 0x10       ; 0x10 new entries in the cache
  206.         jmp     .updated_cachesize
  207. .update_rootcache_size:
  208.         mov     cl, 0x10
  209.         cmp     cx, dx
  210.         jb      @f
  211.         mov     cx, dx
  212. @@:
  213.         add     [bp + rootcache_size - dat], cx
  214. .updated_cachesize:
  215.         popa
  216. @@:
  217.         push    es
  218.         mov     cl, 0x10        ; ch=0 at this point
  219.         cmp     cx, dx
  220.         jb      @f
  221.         mov     cx, dx
  222. @@:
  223.         call    fat_scan_for_filename
  224.         pop     es
  225.         pop     cx
  226.         jz      .lookup_done_pop
  227. .folder_skip_sector:
  228.         inc     eax
  229.         loop    .folder_next_sector
  230.         pop     eax     ; eax = current cluster
  231.         test    eax, eax
  232.         jz      @f
  233.         call    [bp + get_next_cluster_ptr - dat]
  234.         jc      .folder_next_cluster
  235. @@:
  236.         stc
  237.         push    eax
  238. .lookup_done_pop:
  239.         pop     eax
  240. .lookup_done:
  241.         pop     si
  242. ; CF=1 <=> failed
  243.         jnc     .found
  244.         pop     ds
  245.         pop     [bp + cur_obj - dat]
  246.         mov     si, error_not_found
  247.         jmp     find_error_si
  248. .found:
  249.         mov     eax, [di+20-2]
  250.         mov     edx, [di+28]
  251.         mov     ax, [di+26]     ; get cluster
  252.         test    byte [di+11], 10h       ; directory?
  253.         pop     ds
  254.         pop     [bp + cur_obj - dat]    ; forget old [cur_obj]
  255.         jz      .regular_file
  256.         cmp     byte [si-1], 0
  257.         jnz     .parse_dir_loop
  258. ..directory_error:
  259.         mov     si, directory_string
  260.         jmp     find_error_si
  261. .regular_file:
  262.         cmp     byte [si-1], 0
  263.         jz      @f
  264. ..notdir_error:
  265.         mov     si, notdir_string
  266.         jmp     find_error_si
  267. @@:
  268. ; ok, we have found a regular file and the caller requested it
  269. ; parse FAT chunk
  270.         push    ss
  271.         pop     es
  272.         push    ss
  273.         pop     ds
  274.         mov     di, 0x4005
  275.         mov     byte [di-5], 1  ; non-resident attribute
  276.         mov     dword [di-4], 1
  277.         stosd
  278.         pop     cx
  279.         push    cx
  280. .parsefat:
  281.         call    [bp + get_next_cluster_ptr - dat]
  282.         jnc     .done
  283.         mov     esi, [di-8]
  284.         add     esi, [di-4]
  285.         cmp     eax, esi
  286.         jz      .contc
  287.         mov     dword [di], 1
  288.         scasd
  289.         stosd
  290.         jmp     @f
  291. .contc:
  292.         inc     dword [di-8]
  293. @@:
  294.         sub     cl, [0x320D]
  295.         sbb     ch, 0
  296.         ja      .parsefat
  297. .done:
  298.         xor     eax, eax
  299.         stosd
  300.         mov     si, 0x4000
  301. load_file_common_end:
  302.         xor     ecx, ecx
  303.         pop     cx
  304.         pop     bx
  305.         pop     es
  306.         mov     [bp + filesize - dat], edx
  307.         mov     [bp + sectors_read - dat], ecx
  308.         add     edx, 0x1FF
  309.         shr     edx, 9
  310.         mov     [bp + filesize_sectors - dat], edx
  311.         cmp     edx, ecx
  312.         seta    al
  313.         mov     ah, 0
  314.         push    ax
  315.         call    read_file_chunk
  316. continue_load_common_end:
  317.         mov     [bp + cur_chunk_ptr - dat], si
  318.         pop     bx
  319.         mov     ax, word [bp + filesize - dat]
  320.         mov     dx, word [bp + filesize+2 - dat]
  321.         jnc     @f
  322.         mov     bl, 3   ; read error
  323. @@:
  324.         ret
  325.  
  326. continue_load_file:
  327. ; es:bx -> buffer for output, ecx = cx = number of sectors
  328.         mov     si, [bp + cur_chunk_ptr - dat]
  329.         push    ecx
  330.         add     ecx, [bp + sectors_read - dat]
  331.         mov     [bp + sectors_read - dat], ecx
  332.         cmp     [bp + filesize_sectors - dat], ecx
  333.         pop     ecx
  334.         seta    al
  335.         mov     ah, 0
  336.         push    ax
  337.         push    continue_load_common_end
  338.         push    ss
  339.         pop     ds
  340.         cmp     [bp + cur_chunk_resident - dat], ah
  341.         jnz     .nonresident
  342. .resident:
  343.         mov     ax, word [bp + num_sectors - dat]
  344.         jmp     read_file_chunk.resident.continue
  345. .nonresident:
  346.         mov     eax, [bp + cur_cluster - dat]
  347.         mov     edx, [bp + num_sectors - dat]
  348.         add     eax, [bp + cur_delta - dat]
  349.         jmp     read_file_chunk.nonresident.continue
  350.  
  351. fat_scan_for_filename:
  352. ; in: ss:si -> 11-bytes FAT name
  353. ; in: ds:0 -> part of directory data
  354. ; in: cx = number of entries
  355. ; out: if found: CF=0, ZF=1, es:di -> directory entry
  356. ; out: if not found, but continue required: CF=1 and ZF=0
  357. ; out: if not found and zero item reached: CF=1 and ZF=1
  358.         push    ds
  359.         pop     es
  360.         xor     di, di
  361.         push    cx
  362.         jcxz    .noent
  363. .loop:
  364.         cmp     byte [di], 0
  365.         jz      .notfound
  366.         test    byte [di+11], 8         ; volume label?
  367.         jnz     .cont                   ; ignore volume labels
  368.         pusha
  369.         mov     cx, 11
  370.         repz    cmps byte [ss:si], byte [es:di]
  371.         popa
  372.         jz      .done
  373. .cont:
  374.         add     di, 0x20
  375.         loop    .loop
  376. .noent:
  377.         inc     cx      ; clear ZF flag
  378. .notfound:
  379.         stc
  380. .done:
  381.         pop     cx
  382.         ret
  383.  
  384. fat12_get_next_cluster:
  385. ; in: ax = cluster (high word of eax is zero)
  386. ; out: if there is next cluster: CF=1, ax = next cluster
  387. ; out: if there is no next cluster: CF=0
  388.         push    si
  389.         push    ds
  390.         push    0x6000
  391.         pop     ds
  392.         mov     si, ax
  393.         shr     si, 1
  394.         add     si, ax
  395.         test    al, 1
  396.         lodsw
  397.         jz      @f
  398.         shr     ax, 4
  399. @@:
  400.         and     ax, 0xFFF
  401.         cmp     ax, 0xFF7
  402.         pop     ds si
  403.         ret
  404.  
  405. fat16_get_next_cluster:
  406. ; in: ax = cluster (high word of eax is zero)
  407. ; out: if there is next cluster: CF=1, ax = next cluster
  408. ; out: if there is no next cluster: CF=0
  409. ; each sector contains 200h bytes = 100h FAT entries
  410. ; so ah = # of sector, al = offset in sector
  411.         push    si
  412.         mov     si, ax
  413.         shr     si, 8
  414. ; calculate segment for this sector of FAT table
  415. ; base for FAT table is 6000:0000, so the sector #si has to be loaded to (60000 + 200*si)
  416. ; segment = 6000 + 20*si, offset = 0
  417.         push    es
  418.         push    si
  419.         shl     si, 5
  420.         add     si, 0x6000
  421.         mov     es, si
  422.         pop     si
  423.         cmp     byte [ss:0x3400+si], 0  ; sector already loaded?
  424.         jnz     .noread
  425. ; load corresponding sector, try all FATs if disk read error detected
  426.         pusha
  427.         movzx   di, byte [ss:0x3210]    ; BPB_NumFATs
  428.         xor     bx, bx
  429.         mov     ax, [ss:0x320E]         ; BPB_RsvdSecCnt
  430.         xor     dx, dx
  431.         add     ax, si
  432.         adc     dx, bx
  433. @@:
  434.         push    es
  435.         push    dx ax
  436.         pop     eax
  437.         mov     cx, 1   ; read 1 sector
  438.         call    read
  439.         pop     es
  440.         jnc     @f
  441.         add     ax, [ss:0x3216]         ; BPB_FATSz16
  442.         adc     dx, bx
  443.         dec     di
  444.         jnz     @b
  445. ..found_disk_error:
  446.         mov     si, disk_error_msg
  447.         jmp     find_error_si
  448. @@:
  449.         popa
  450. .noread:
  451.         mov     si, ax
  452.         and     si, 0xFF
  453.         add     si, si
  454.         mov     ax, [es:si]
  455.         pop     es
  456.         cmp     ax, 0xFFF7
  457.         pop     si
  458.         ret
  459.  
  460. fat32_get_next_cluster:
  461. ; in: eax = cluster
  462. ; out: if there is next cluster: CF=1, eax = next cluster
  463. ; out: if there is no next cluster: CF=0
  464.         push    di
  465.         push    ax
  466.         shr     eax, 7
  467. ; eax = FAT sector number; look in cache
  468.         push    si
  469.         mov     si, cache1head
  470.         call    cache_lookup
  471.         pop     si
  472.         jnc     .noread
  473. ; read FAT, try all FATs if disk read error detected
  474.         push    es
  475.         pushad
  476.         movzx   edx, word [ss:0x320E]   ; BPB_RsvdSecCnt
  477.         add     eax, edx
  478.         movzx   si, byte [ss:0x3210]    ; BPB_NumFATs
  479. @@:
  480.         lea     cx, [di - 0x3400 + (0x6000 shr (9-3))]
  481.         shl     cx, 9-3
  482.         mov     es, cx
  483.         xor     bx, bx
  484.         mov     cx, 1
  485.         call    read
  486.         jnc     @f
  487.         add     eax, [ss:0x3224]        ; BPB_FATSz32
  488.         dec     si
  489.         jnz     @b
  490.         jmp     ..found_disk_error
  491. @@:
  492.         popad
  493.         pop     es
  494. .noread:
  495. ; get requested item
  496.         lea     ax, [di - 0x3400 + (0x6000 shr (9-3))]
  497.         pop     di
  498.         and     di, 0x7F
  499.         shl     di, 2
  500.         shl     ax, 9-3
  501.         push    ds
  502.         mov     ds, ax
  503.         and     byte [di+3], 0x0F
  504.         mov     eax, [di]
  505.         pop     ds
  506.         pop     di
  507.         ;and    eax, 0x0FFFFFFF
  508.         cmp     eax, 0x0FFFFFF7
  509.         ret
  510.