Build sector-oriented getfssec routine
authorhpa <hpa>
Thu, 16 Dec 2004 05:19:54 +0000 (05:19 +0000)
committerhpa <hpa>
Thu, 16 Dec 2004 05:19:54 +0000 (05:19 +0000)
ldlinux.asm

index 905d336..79d668c 100644 (file)
@@ -1268,70 +1268,81 @@ lc_1:           cmp al,lcase_low
 lc_ret:         ret
 
 ;
-; getfssec: Get multiple sectors from a file
+; getfssec_edx: Get multiple sectors from a file
 ;
 ;      This routine makes sure the subtransfers do not cross a 64K boundary,
 ;      and will correct the situation if it does, UNLESS *sectors* cross
 ;      64K boundaries.
 ;
 ;      ES:BX   -> Buffer
-;      SI      -> Pointer to structure:
-;                 0 - dword - Starting cluster number (2-based)
-;                 4 - word  - Sector number within cluster
-;                 8 - dword - Absolute sector number
+;      EDX     -> Current sector number
 ;      CX      -> Sector count (0FFFFh = until end of file)
 ;                  Must not exceed the ES segment
-;      Returns CF=1 on EOF
+;      Returns EDX=0, CF=1 on EOF (not necessarily error)
+;      All arguments are advanced to reflect data read.
 ;
-getfssec:
-.getfragment:  xor ebp,ebp                     ; Fragment sector count
-               mov edi,[si]
-               lea eax,[edi-2]
-               ; mov eax,ebx
-               ; sub eax,2
-               ; jc .isrootdir                 ; Use cluster 1 for the root directory
-               mul dword [SecPerClust]
-               add eax,[DataArea]
-               sub bp,[si+4]                   ; Sectors already read
-.getseccnt:                                    ; See if we can read > 1 clust
-               add bp,[SecPerClust]
-               cmp cx,bp
-               jna .endfragment                ; Done?
-               lea eax,[edi+1]
-               call nextcluster
-               jc .eof                         ; At EOF?
-               cmp eax,edi                     ; Is file continuous?
-               je .getseccnt                   ; Yes, we can get
-.endfragment:  clc                             ; Not at EOF
-.eof:          pushf                           ; Remember EOF or not
-               push si
-               push cx
-.getchunk:
+getfssec_edx:
+               push ebp
                push eax
-               mov ax,es                       ; Check for 64K boundaries.
+.getfragment:
+               xor ebp,ebp                     ; Fragment sector count
+.getseccnt:
+               inc bp
+               dec cx
+               jz .do_read
+               mov ax,es
                shl ax,4
-               add ax,bx
-               xor dx,dx
-               neg ax
-               setz dl                         ; DX <- 1 if full 64K segment
-               div word [bsBytesPerSec]        ; How many sectors fit?
-               mov si,bp
-               sub si,ax                       ; Compute remaining sectors
-               jbe .lastchunk
-               mov bp,ax
-               pop eax
+               add ax,bx                       ; Now DI = how far into 64K block we are
+               neg ax                          ; Bytes left in 64K block
+               shr ax,9                        ; Sectors left in 64K block
+               cmp bp,ax
+               jnb .do_read                    ; Unless there is at least 1 more sector room...
+               lea eax,[edx+1]                 ; Linearly next sector
+               call nextsector
+               jc .do_read
+               cmp edx,eax
+               jz .getseccnt
+
+.do_read:
+               mov eax,edx
                call getlinsecsr
-               add eax,ebp                     ; EBP<31:16> == 0
-               mov bp,si                       ; Remaining sector count
-               jmp short .getchunk
-.lastchunk:    pop eax
-               call getlinsec
-               pop cx
-               pop si
-               popf
-               jcxz .return                    ; If we hit the count limit
-               jnc .getfragment                ; If we didn't hit EOF
-.return:       ret
+               lea eax,[eax+ebp-1]             ; This is the last sector actually read
+               shl bp,9
+               add bx,bp                       ; Adjust buffer pointer
+               call nextsector
+               jc .eof
+               mov edx,eax
+               and cx,cx
+               jnz .getfragment
+.done:
+               pop eax
+               pop ebp
+               ret
+
+.eof:
+               xor edx,edx
+               stc
+               jmp .done
+
+;
+; getfssec: Get multiple sectors from a file
+;
+;      Same as above, except SI is a pointer to a dword with the current sector.
+;
+;      ES:BX   -> Buffer
+;      DS:SI   -> Pointer to current sector number
+;      CX      -> Sector count (0FFFFh = until end of file)
+;                  Must not exceed the ES segment
+;      Returns CF=1 on EOF (not necessarily error)
+;      All arguments are advanced to reflect data read.
+;
+getfssec:
+               push edx
+               mov edx,[si]
+               call getfssec_edx
+               mov [si],edx
+               pop edx
+               ret
 
 ;
 ; nextcluster: Advance a cluster pointer in EDI to the next cluster
@@ -1417,6 +1428,61 @@ nextcluster_fat28:
                ret
 
 ;
+; nextsector:  Given a sector in EAX on input, return the next sector
+;              of the same filesystem object, which may be the root
+;                      directory or a cluster chain.  Returns  EOF.
+;
+;              Assumes CS == DS.
+;
+nextsector:
+               push edi
+               push edx
+               mov edx,[DataArea]
+               mov edi,eax
+               sub edi,edx
+               jae .isdata
+
+               ; Root directory
+               inc eax
+               cmp eax,edx
+               cmc
+               jmp .done
+
+.isdata:
+               not edi
+               test edi,[ClustMask]
+               jz .endcluster
+
+               ; It's not the final sector in a cluster
+               inc eax
+               jmp .done
+
+.endcluster:
+               push gs                 ; nextcluster trashes gs
+               push cx
+               not edi
+               mov cl,[ClustShift]
+               shr edi,cl
+               add edi,2
+
+               ; Now EDI contains the cluster number
+               call nextcluster
+               cmc
+               jc .exit                ; There isn't anything else...
+
+               ; New cluster number now in EDI
+               sub edi,2
+               shl edi,cl              ; CF <- 0, unless something is very wrong
+               lea eax,[edi+edx]
+.exit:
+               pop cx
+               pop gs
+.done:
+               pop edx
+               pop edi
+               ret
+
+;
 ; getfatsector: Check for a particular sector (in EAX) in the FAT cache,
 ;              and return a pointer in GS:SI, loading it if needed.
 ;