817 lines
19 KiB
NASM
817 lines
19 KiB
NASM
|
|
DOSSEG
|
|
.MODEL LARGE
|
|
|
|
include partit.inc
|
|
|
|
.DATA?
|
|
public PartitionList
|
|
PartitionList dd ?
|
|
public PartitionListCount
|
|
PartitionListCount dw ?
|
|
|
|
.CODE
|
|
ASSUME ds:NOTHING
|
|
|
|
extrn _InitializeDiskList:far
|
|
extrn _OpenDisk:far
|
|
extrn _CloseDisk:far
|
|
extrn _ReadDisk:far
|
|
extrn _WriteDisk:far
|
|
extrn _malloc:far
|
|
extrn _free:far
|
|
|
|
.386
|
|
|
|
;++
|
|
;
|
|
; UINT
|
|
; _far
|
|
; InitializePartitionList(
|
|
; VOID
|
|
; );
|
|
;
|
|
; Routine Description:
|
|
;
|
|
; This routine initializes internal data structures necessary so that
|
|
; other partition-related routines in this module can be called.
|
|
;
|
|
; All int13 disks are enumerated to find all primary and extended
|
|
; partitions. A data structure is build for each partition/logical drive
|
|
; and relevent information is saved away.
|
|
;
|
|
; Arguments:
|
|
;
|
|
; None.
|
|
;
|
|
; Return Value:
|
|
;
|
|
; Total count of all partitions on all disks that we can deal with.
|
|
; 0 if an error occurs.
|
|
;
|
|
;--
|
|
|
|
SectorBufferh equ word ptr [bp-2]
|
|
SectorBufferl equ word ptr [bp-4]
|
|
CurrentSectorh equ word ptr [bp-6]
|
|
CurrentSectorl equ word ptr [bp-8]
|
|
NextSectorh equ word ptr [bp-10]
|
|
NextSectorl equ word ptr [bp-12]
|
|
ExtStarth equ word ptr [bp-14]
|
|
ExtStartl equ word ptr [bp-16]
|
|
DiskHandleh equ word ptr [bp-18]
|
|
DiskHandlel equ word ptr [bp-20]
|
|
PartCount equ word ptr [bp-22]
|
|
InMbr equ byte ptr [bp-24]
|
|
|
|
|
|
public _InitializePartitionList
|
|
_InitializePartitionList proc far
|
|
|
|
push bp
|
|
mov bp,sp
|
|
sub sp,24
|
|
|
|
push ds
|
|
push es
|
|
push bx
|
|
push si
|
|
push di
|
|
|
|
mov PartCount,0
|
|
|
|
;
|
|
; Allocate a sector buffer. Note that we havn'e overwritten ds
|
|
; so it is addressing _DATA, which is required by the crt.
|
|
;
|
|
push 512
|
|
call _malloc
|
|
add sp,2
|
|
mov cx,ax
|
|
or cx,dx
|
|
jz exit ; ax already 0 for error exit
|
|
mov SectorBufferl,ax
|
|
mov SectorBufferh,dx
|
|
|
|
;
|
|
; _InitializeDiskList could return 0 in case of
|
|
; failure but the code below will then simply execute
|
|
; zero iterations of its loop.
|
|
;
|
|
call _InitializeDiskList
|
|
mov si,ax ; si is limit of disk ids
|
|
mov di,0 ; di is current disk id
|
|
|
|
nextdisk:
|
|
cmp si,di
|
|
je done
|
|
|
|
;
|
|
; Open this disk.
|
|
;
|
|
push di
|
|
call _OpenDisk
|
|
add sp,2
|
|
mov cx,ax
|
|
or cx,dx
|
|
jz exit ; open failed, bail out
|
|
mov DiskHandlel,ax
|
|
mov DiskHandleh,dx ; save disk handle
|
|
|
|
;
|
|
; Read partition table for this disk
|
|
;
|
|
xor ax,ax
|
|
mov NextSectorl,ax
|
|
mov NextSectorh,ax
|
|
mov ExtStartl,ax
|
|
mov ExtStarth,ax
|
|
mov InMbr,1
|
|
|
|
nextptable:
|
|
;
|
|
; Read current mbr/ebr
|
|
;
|
|
push SectorBufferh
|
|
push SectorBufferl
|
|
push 1
|
|
mov ax,NextSectorh
|
|
mov CurrentSectorh,ax
|
|
push ax
|
|
mov ax,NextSectorl
|
|
mov CurrentSectorl,ax
|
|
push ax
|
|
push DiskHandleh
|
|
push DiskHandlel
|
|
call _ReadDisk
|
|
add sp,14
|
|
cmp ax,0
|
|
jz exit ; ax already 0 for error exit
|
|
|
|
mov NextSectorl,0
|
|
mov NextSectorh,0
|
|
|
|
mov bx,SectorBufferl
|
|
add bx,1beh
|
|
mov ax,SectorBufferh
|
|
mov es,ax ; es:bx -> first partition table entry
|
|
mov cx,4
|
|
nextent:
|
|
cmp byte ptr es:[bx+4],0
|
|
jz nextent1 ; unused entry
|
|
cmp byte ptr es:[bx+4],5
|
|
je gotlink
|
|
cmp byte ptr es:[bx+4],0fh
|
|
jnz gotentry
|
|
gotlink:
|
|
;
|
|
; Link-type partition, track next ebr location
|
|
;
|
|
mov ax,ExtStartl
|
|
add ax,es:[bx+8]
|
|
mov NextSectorl,ax
|
|
mov ax,ExtStarth
|
|
adc ax,es:[bx+10]
|
|
mov NextSectorh,ax
|
|
|
|
cmp InMbr,1
|
|
jne nextent1
|
|
|
|
mov ax,es:[bx+8]
|
|
mov ExtStartl,ax
|
|
mov ax,es:[bx+10]
|
|
mov ExtStarth,ax
|
|
|
|
jmp nextent1
|
|
|
|
gotentry:
|
|
mov ax,CurrentSectorl
|
|
add ax,es:[bx+8]
|
|
mov dx,CurrentSectorh
|
|
adc dx,es:[bx+10]
|
|
|
|
push cx
|
|
push bx
|
|
push es
|
|
|
|
;
|
|
; Before calling crt ensure that ds addresses _DATA
|
|
;
|
|
push ds
|
|
mov ax,DGROUP
|
|
mov ds,ax
|
|
push SIZE PART_INFO
|
|
call _malloc
|
|
add sp,2
|
|
pop ds
|
|
|
|
pop es
|
|
pop bx
|
|
|
|
mov cx,ax
|
|
or cx,dx
|
|
pop cx ; does not affect flags
|
|
jz exit ; ax already 0 for error exit
|
|
|
|
push si
|
|
push ds
|
|
mov ds,dx
|
|
mov si,ax ; ds:si -> new partition record
|
|
|
|
mov ax,PartCount
|
|
mov [si].PartInfoOrdinal,ax
|
|
inc PartCount
|
|
|
|
mov ax,CurrentSectorl
|
|
add ax,es:[bx+8]
|
|
mov [si].PartInfoStartSectorl,ax
|
|
mov ax,CurrentSectorh
|
|
adc ax,es:[bx+10]
|
|
mov [si].PartInfoStartSectorh,ax
|
|
|
|
mov ax,es:[bx+12]
|
|
mov [si].PartInfoSectorCountl,ax
|
|
mov ax,es:[bx+14]
|
|
mov [si].PartInfoSectorCounth,ax
|
|
|
|
mov al,es:[bx+4]
|
|
mov [si].PartInfoSystemId,al
|
|
|
|
mov [si].PartInfoDiskId,di
|
|
|
|
mov [si].PartInfoPartOpen,0
|
|
mov [si].PartInfoDiskHandlel,0
|
|
mov [si].PartInfoDiskHandleh,0
|
|
|
|
;
|
|
; Insert at head of linked list
|
|
;
|
|
push es
|
|
push di
|
|
|
|
mov ax,DGROUP
|
|
mov es,ax
|
|
mov di,OFFSET DGROUP:[PartitionList] ; es:di = &PartitionList
|
|
|
|
mov ax,es:[di]
|
|
mov [si].PartInfoNextl,ax
|
|
mov ax,es:[di+2]
|
|
mov [si].PartInfoNexth,ax ; Record->Next = PartitionList
|
|
|
|
mov es:[di],si
|
|
mov es:[di+2],dx ; PartitionList = Record
|
|
|
|
pop di
|
|
pop es
|
|
|
|
pop ds
|
|
pop si ; restore int13 unit limit
|
|
|
|
nextent1:
|
|
add bx,16
|
|
dec cx
|
|
jz @f
|
|
jmp nextent
|
|
@@:
|
|
mov InMbr,0
|
|
|
|
;
|
|
; If we found a link entry, follow it. Otherwise we're done
|
|
; with this disk.
|
|
;
|
|
cmp NextSectorl,0
|
|
jnz nextptable
|
|
cmp NextSectorh,0
|
|
jnz nextptable
|
|
|
|
push DiskHandleh
|
|
push DiskHandlel
|
|
call _CloseDisk
|
|
add sp,4
|
|
|
|
inc di
|
|
jmp nextdisk
|
|
|
|
done:
|
|
push DGROUP
|
|
pop ds ; address DGROUP for crt
|
|
push SectorBufferh
|
|
push SectorBufferl
|
|
call _free
|
|
add sp,4
|
|
mov ax,PartCount
|
|
|
|
mov si,OFFSET DGROUP:PartitionListCount
|
|
mov [si],ax ; save count in global var
|
|
|
|
exit:
|
|
pop di
|
|
pop si
|
|
pop bx
|
|
pop es
|
|
pop ds
|
|
|
|
leave
|
|
retf
|
|
|
|
_InitializePartitionList endp
|
|
|
|
|
|
|
|
;++
|
|
;
|
|
; BOOL
|
|
; _far
|
|
; GetPartitionInfoById(
|
|
; IN UINT PartitionId,
|
|
; IN UINT Reserved,
|
|
; OUT FPUINT DiskId,
|
|
; OUT FPBYTE SystemId,
|
|
; OUT FPULONG StartSector,
|
|
; OUT FPULONG SectorCount
|
|
; );
|
|
;
|
|
; BOOL
|
|
; _far
|
|
; GetPartitionInfoByHandle(
|
|
; IN HPARTITION PartitionHandle,
|
|
; OUT FPUINT DiskId,
|
|
; OUT FPBYTE SystemId,
|
|
; OUT FPULONG StartSector,
|
|
; OUT FPULONG SectorCount
|
|
; );
|
|
;
|
|
; Routine Description:
|
|
;
|
|
; These routines retrieve information about a particular partition,
|
|
; either by an ordinal id (range: 0 - n-1 where n is the value returned
|
|
; by InitializePartitionList()), or by a handle returned from
|
|
; OpenPartition().
|
|
;
|
|
; Arguments:
|
|
;
|
|
; PartitionId/PartitionHandle - supplies ordinal id or handle that
|
|
; identifies the partition whose information is of interest.
|
|
;
|
|
; Reserved - unused.
|
|
;
|
|
; DiskId - receives the disk id of the disk where the partition is.
|
|
;
|
|
; SystemId - receives the system id of the partition from the
|
|
; partition table, if known, or 0 if not.
|
|
;
|
|
; StartSector - recieves the absolute physical start sector on the
|
|
; drive where the partition lives.
|
|
;
|
|
; SectorCount - recieves the number of sectors in the partition.
|
|
;
|
|
; Return Value:
|
|
;
|
|
; 0 - failure
|
|
; non-0 - success and caller's variables filled in
|
|
;
|
|
;--
|
|
|
|
PartitionId equ word ptr [bp+6]
|
|
PartitionHandle equ dword ptr [bp+6]
|
|
DiskId equ dword ptr [bp+10]
|
|
SystemId equ dword ptr [bp+14]
|
|
StartSector equ dword ptr [bp+18]
|
|
SectorCount equ dword ptr [bp+22]
|
|
|
|
public _GetPartitionInfoById
|
|
_GetPartitionInfoById proc far
|
|
|
|
push bp
|
|
mov bp,sp
|
|
|
|
push ds
|
|
push es
|
|
push si
|
|
push di
|
|
|
|
;
|
|
; Locate the partition record for the requested partition.
|
|
; The far pointer comes back in dx:si and ds:si.
|
|
;
|
|
mov ax,PartitionId
|
|
call far ptr pLocatePartitionRecord
|
|
cmp dx,0
|
|
jnz get_p_id
|
|
cmp si,0
|
|
jz error1
|
|
|
|
;
|
|
; Transfer the relevent fields to the caller's variables.
|
|
;
|
|
get_p_id:
|
|
les di,DiskId
|
|
mov ax,[si].PartInfoDiskId
|
|
mov es:[di],ax
|
|
|
|
les di,SystemId
|
|
mov al,[si].PartInfoSystemId
|
|
mov es:[di],al
|
|
|
|
les di,StartSector
|
|
mov ax,[si].PartInfoStartSectorl
|
|
mov es:[di],ax
|
|
mov ax,[si].PartInfoStartSectorh
|
|
mov es:[di+2],ax
|
|
|
|
les di,SectorCount
|
|
mov ax,[si].PartInfoSectorCountl
|
|
mov es:[di],ax
|
|
mov ax,[si].PartInfoSectorCounth
|
|
mov es:[di+2],ax
|
|
|
|
mov ax,1
|
|
jmp short exit1
|
|
|
|
error1:
|
|
xor ax,ax
|
|
|
|
exit1:
|
|
pop di
|
|
pop si
|
|
pop es
|
|
pop ds
|
|
|
|
leave
|
|
retf
|
|
|
|
_GetPartitionInfoById endp
|
|
|
|
|
|
public _GetPartitionInfoByHandle
|
|
_GetPartitionInfoByHandle label far
|
|
|
|
push bp
|
|
mov bp,sp
|
|
|
|
push ds
|
|
push es
|
|
push si
|
|
push di
|
|
|
|
;
|
|
; Make sure it's open, if not give error.
|
|
;
|
|
lds si,PartitionHandle
|
|
cmp [si].PartInfoPartOpen,0
|
|
jne short get_p_id
|
|
je error1
|
|
|
|
|
|
;++
|
|
;
|
|
; HPARTITION
|
|
; _far
|
|
; OpenPartition(
|
|
; IN UINT PartitionId
|
|
; );
|
|
;
|
|
; Routine Description:
|
|
;
|
|
; This routine 'opens' a partition so that subsequent io may be
|
|
; performed on it.
|
|
;
|
|
; Note that a partition can be open only once at a time.
|
|
;
|
|
; Note that this routine also opens the underlying disk.
|
|
; Disks can be opened only once at a time, thus this routine will
|
|
; fail if the disk is already open.
|
|
;
|
|
; Arguments:
|
|
;
|
|
; PartitionId - supplies an ordinal value identifying the partition.
|
|
; Valid range is 0 - n-1, where n is the number returned
|
|
; from InitializePartitionList().
|
|
;
|
|
; Return Value:
|
|
;
|
|
; If successful, returns a value to be used as a handle to the
|
|
; partition for subsequent i/o with other routines in this module.
|
|
; If failure, returns 0.
|
|
;
|
|
;--
|
|
PartitionId equ word ptr [bp+6]
|
|
|
|
public _OpenPartition
|
|
_OpenPartition proc far
|
|
|
|
push bp
|
|
mov bp,sp
|
|
|
|
push ds
|
|
push si
|
|
|
|
;
|
|
; Locate the partition record for the requested partition.
|
|
; The far pointer comes back in dx:si and ds:si.
|
|
;
|
|
mov ax,PartitionId
|
|
call far ptr pLocatePartitionRecord
|
|
mov cx,si
|
|
or cx,dx
|
|
jnz @f
|
|
mov ax,cx ; dx:ax = 0
|
|
jz o_p_3
|
|
|
|
;
|
|
; Make sure the partition is not already open.
|
|
;
|
|
@@: cmp [si].PartInfoPartOpen,0
|
|
je @f
|
|
mov ax,0
|
|
mov dx,ax
|
|
jne o_p_3
|
|
|
|
;
|
|
; Open the underlying disk.
|
|
;
|
|
@@: push [si].PartInfoDiskId
|
|
call _OpenDisk
|
|
add sp,2
|
|
mov cx,ax
|
|
or cx,dx
|
|
jz o_p_3
|
|
|
|
;
|
|
; Remember disk handle, that the partition is open,
|
|
; and return the pointer to the partition record as the handle.
|
|
;
|
|
mov [si].PartInfoDiskHandlel,ax
|
|
mov [si].PartInfoDiskHandleh,dx
|
|
|
|
inc [si].PartInfoPartOpen
|
|
|
|
mov dx,ds
|
|
mov ax,si
|
|
|
|
o_p_3:
|
|
pop si
|
|
pop ds
|
|
|
|
leave
|
|
retf
|
|
|
|
_OpenPartition endp
|
|
|
|
|
|
;++
|
|
;
|
|
; VOID
|
|
; _far
|
|
; ClosePartition(
|
|
; IN HPARTITION PartitionHandle
|
|
; );
|
|
;
|
|
; Routine Description:
|
|
;
|
|
; This routine 'closes' a partition previously opened by
|
|
; OpenPartition.
|
|
;
|
|
; This routine also releases its handle to the disk that
|
|
; contains the partition.
|
|
;
|
|
; Arguments:
|
|
;
|
|
; PartitionHandle - supplies a handle previously returned by
|
|
; OpenPartition().
|
|
;
|
|
; Return Value:
|
|
;
|
|
; None.
|
|
;
|
|
;--
|
|
PartitionHandle equ dword ptr [bp+6]
|
|
|
|
public _ClosePartition
|
|
_ClosePartition proc far
|
|
|
|
push bp
|
|
mov bp,sp
|
|
|
|
push ds
|
|
push si
|
|
|
|
;
|
|
; If not open, nothing to do.
|
|
;
|
|
lds si,PartitionHandle
|
|
cmp [si].PartInfoPartOpen,0
|
|
je c_p_3
|
|
|
|
;
|
|
; Close the disk.
|
|
;
|
|
push [si].PartInfoDiskHandleh
|
|
push [si].PartInfoDiskHandlel
|
|
call _CloseDisk
|
|
add sp,4
|
|
|
|
;
|
|
; Indicate partition closed
|
|
;
|
|
mov cx,0
|
|
mov [si].PartInfoPartOpen,cl
|
|
mov [si].PartInfoDiskHandlel,cx
|
|
mov [si].PartInfoDiskHandleh,cx
|
|
|
|
c_p_3:
|
|
pop si
|
|
pop ds
|
|
leave
|
|
retf
|
|
|
|
_ClosePartition endp
|
|
|
|
|
|
;++
|
|
;
|
|
; BOOL
|
|
; _far
|
|
; ReadPartition(
|
|
; IN HPARTITION PartitionHandle,
|
|
; IN ULONG StartSector,
|
|
; IN BYTE SectorCount,
|
|
; OUT FPVOID Buffer
|
|
; );
|
|
;
|
|
; BOOL
|
|
; _far
|
|
; WritePartition(
|
|
; IN HPARTITION PartitionHandle,
|
|
; IN ULONG StartSector,
|
|
; IN BYTE SectorCount,
|
|
; IN FPVOID Buffer
|
|
; );
|
|
;
|
|
; Routine Description:
|
|
;
|
|
; These routines read from or write to a partition previously opened by
|
|
; OpenPartition. I/Os use the proper method for the disk,
|
|
; ie, int13, xint13, etc. This routine also ensures that
|
|
; I/O doesn't cross a track boundary.
|
|
;
|
|
; This routine does NOT however, worry about DMA boundaries.
|
|
; The caller must take care of this.
|
|
;
|
|
; Arguments:
|
|
;
|
|
; StartSector - supplies the 0-based sector relative to the start
|
|
; of the partition where I/O is to start.
|
|
;
|
|
; SectorCount - supplies the number of sectors to be transferred.
|
|
;
|
|
; Return Value:
|
|
;
|
|
; 0 - failure
|
|
; non-0 - success
|
|
;
|
|
;--
|
|
|
|
PartitionHandle equ dword ptr [bp+6]
|
|
StartSector equ dword ptr [bp+10]
|
|
StartSectorl equ word ptr [bp+10]
|
|
StartSectorh equ word ptr [bp+12]
|
|
SectorCount equ [bp+14]
|
|
Buffer equ dword ptr [bp+16]
|
|
Bufferh equ word ptr [bp+18]
|
|
|
|
IoRoutine equ dword ptr [bp-4]
|
|
IoRoutinel equ word ptr [bp-4]
|
|
IoRoutineh equ word ptr [bp-2]
|
|
|
|
public _ReadPartition
|
|
_ReadPartition label far
|
|
|
|
mov dx,SEG _ReadDisk
|
|
mov ax,OFFSET _ReadDisk
|
|
jmp short PartitionIo
|
|
|
|
public _WritePartition
|
|
_WritePartition label far
|
|
|
|
mov dx,SEG _WriteDisk
|
|
mov ax,OFFSET _WriteDisk
|
|
|
|
PartitionIo proc far
|
|
|
|
push bp
|
|
mov bp,sp
|
|
sub sp,4
|
|
|
|
push ds
|
|
push es
|
|
push bx
|
|
push si
|
|
push di
|
|
|
|
;
|
|
; The partition handle is actually a far pointer to
|
|
; the partition data record. Make sure it's open.
|
|
;
|
|
lds si,PartitionHandle ; ds:si -> partition record
|
|
cmp [si].PartInfoPartOpen,0
|
|
jne @f
|
|
xor ax,ax
|
|
jmp short iodone
|
|
|
|
;
|
|
; Store the i/o routine pointer, passed to us in dx:ax.
|
|
;
|
|
@@: mov IoRoutineh,dx
|
|
mov IoRoutinel,ax
|
|
|
|
;
|
|
; Adjust the start sector to be disk-based instead of
|
|
; partition-based.
|
|
;
|
|
mov ax,[si].PartInfoStartSectorl
|
|
add StartSectorl,ax
|
|
mov ax,[si].PartInfoStartSectorh
|
|
adc StartSectorh,ax ; StartSector is physical sector#
|
|
|
|
;
|
|
; Call the disk routine to do the read.
|
|
;
|
|
push Buffer
|
|
push SectorCount
|
|
push StartSector
|
|
push [si].PartInfoDiskHandleh
|
|
push [si].PartInfoDiskHandlel
|
|
call IoRoutine
|
|
add sp,14
|
|
|
|
iodone:
|
|
pop di
|
|
pop si
|
|
pop bx
|
|
pop es
|
|
pop ds
|
|
|
|
leave
|
|
retf
|
|
|
|
PartitionIo endp
|
|
|
|
;++
|
|
;
|
|
; PVOID
|
|
; _far
|
|
; pLocatePartitionRecord(
|
|
; IN UINT PartitionId
|
|
; );
|
|
;
|
|
; Routine Description:
|
|
;
|
|
;
|
|
; Internal routine.
|
|
;
|
|
; This routine locates a partition record in the linked list
|
|
; of all partition records as prepared by InitializePartitionList().
|
|
;
|
|
; Arguments:
|
|
;
|
|
; PartitionId - supplies an ordinal value identifying the partition.
|
|
; Valid range is 0 - n-1, where n is the number returned
|
|
; from InitializePartitionList().
|
|
;
|
|
; This parameter is passed in ax, not on the stack.
|
|
;
|
|
; Return Value:
|
|
;
|
|
; NULL if record not located.
|
|
; Otherwise fills ds:si and dx:si with a far pointer to the
|
|
; partition record.
|
|
;
|
|
;--
|
|
pLocatePartitionRecord proc far
|
|
|
|
mov dx,DGROUP
|
|
mov ds,dx
|
|
mov si,OFFSET PartitionList ; ds:si = &PartitionList
|
|
|
|
;
|
|
; Note that this code depends on the link field in the
|
|
; partition record structure being first!
|
|
;
|
|
.errnz PartInfoNext
|
|
lpr_loop:
|
|
lds si,[si].PartInfoNext
|
|
mov dx,ds
|
|
cmp dx,0
|
|
jz lpr_done ; end of list, we're done
|
|
cmp [si].PartInfoOrdinal,ax
|
|
jz lpr_done
|
|
jmp short lpr_loop
|
|
|
|
lpr_done:
|
|
ret
|
|
|
|
pLocatePartitionRecord endp
|
|
|
|
end
|