windows-nt/Source/XPSP1/NT/base/ntsetup/mpk/iolib/partio.asm
2020-09-26 16:20:57 +08:00

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