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

1092 lines
31 KiB
NASM

DOSSEG
.MODEL LARGE
include disk.inc
include partit.inc
.DATA
extrn _x86BootCode:far
.DATA?
extrn PartitionList:dword
extrn PartitionListCount:word
.CODE
ASSUME ds:NOTHING
extrn _malloc:far
extrn _free:far
extrn _qsort:far
extrn _ReadDisk:far
extrn _WriteDisk:far
extrn _GetDiskInfoByHandle:far
.386
;++
;
; INT
; _far
; MakePartitionAtStartOfDisk(
; IN HDISK DiskHandle,
; OUT FPVOID SectorBuffer,
; IN ULONG MinimumSectorCount,
; IN UINT PartitionClass,
; IN BYTE SystemId OPTIONAL
; );
;
; Routine Description:
;
; This routine makes a new primary partition of at least
; a given number of sectors. The partition may be larger
; to keep it aligned on the proper cyl/track boundary.
;
; Only int13 disk units are supported.
;
; Arguments:
;
; DiskHandle - supplies a disk handle as returned by OpenDisk().
;
; SectorBuffer - supplies a pointer to a buffer suitable for use
; for i/o of a single sector. This buffer must not
; cross a DMA boundary, but the caller is responsible
; for ensuring this.
;
; MinimumSectorCount - supplies the minimum number of sectors
; that the partition should contain.
;
; PartitionClass - supplies a value indicating what class of system id
; should be used for the partition.
;
; PARTCLASS_FAT - creates a type 1, 4, or 6, or e partition
; depending on size and availability of xint13
; services for the drive.
;
; PARTCLASS_FAT32 - creates a type b or c partition depending
; on availability of xint13 services for the drive.
;
; PARTCLASS_NTFS - creates a type 7 partition.
;
; PARTCLASS_OTHER - create a partition whose type is given by
; the SystemId parameter.
;
; SystemId - if PartitionClass is PARTCLASS_OTHER, supplies the
; system id for the partition. Ignored otherwise.
;
; Return Value:
;
; Partition id of newly created partition, or -1 if failure.
;
;--
DiskHandle equ dword ptr [bp+6]
DiskHandlel equ word ptr [bp+6]
DiskHandleh equ word ptr [bp+8]
SectorBuffer equ dword ptr [bp+10]
SectorBufferl equ word ptr [bp+10]
SectorBufferh equ word ptr [bp+12]
MinimumSectorCount equ dword ptr [bp+14]
MinimumSectorCountl equ word ptr [bp+14]
MinimumSectorCounth equ word ptr [bp+16]
PartitionClass equ word ptr [bp+18]
SystemId equ byte ptr [bp+20]
ExtSecCnth equ word ptr [bp-2]
ExtSecCntl equ word ptr [bp-4]
ExtSecCnt equ dword ptr [bp-4]
Cylinders equ word ptr [bp-6]
Heads equ word ptr [bp-8]
SectorsPerTrack equ byte ptr [bp-9]
Int13UnitNumber equ byte ptr [bp-10]
SectorsPerCylinder equ word ptr [bp-12]
DiskSizeh equ word ptr [bp-14]
DiskSizel equ word ptr [bp-16]
DiskSize equ dword ptr [bp-16]
DiskId equ word ptr [bp-18]
Tableh equ word ptr [bp-20]
Tablel equ word ptr [bp-22]
Table equ dword ptr [bp-22]
FreeStarth equ word ptr [bp-24]
FreeStartl equ word ptr [bp-26]
FreeStart equ dword ptr [bp-26]
START_AND_SIZE STRUC
PartStartl dw ?
PartStarth dw ?
PartSizel dw ?
PartSizeh dw ?
START_AND_SIZE ENDS
public _MakePartitionAtStartOfDisk
_MakePartitionAtStartOfDisk proc far
push bp
mov bp,sp
sub sp,26
push ds
push es
push bx
push si
push di
;
; Get disk info. This also makes sure the handle is open,
; calculates the number of sectors we can address on the disk,
; and the number of sectors in a cylinder.
;
call near ptr pGetDiskValues
jnc @f
mov ax,0ffffh
jc done2
;
; Allocate a buffer for our table.
; Make sure ds addresses DGROUP for crt
;
@@: push ds
push DGROUP
pop ds
push 5 * SIZE START_AND_SIZE
call _malloc
add sp,2
pop ds
mov cx,ax
or cx,dx
jnz @f
dec ax ; ax = -1 for error return
jmp done2
@@: mov Tableh,dx
mov Tablel,ax
;
; Read sector 0 of the disk.
;
push SectorBuffer
push 1
push 0
push 0
push DiskHandle
call _ReadDisk
add sp,14
cmp ax,0
jne @f
dec ax
jmp done1 ; ax = -1 for error exit
;
; Make sure the MBR is valid.
;
@@: lds si,SectorBuffer
cmp word ptr [si+510],0aa55h
je @f
mov ax,0ffffh
jmp done1
;
; Zero out the start/offset table.
;
@@: les di,Table ; es:di -> local start/size table
mov ax,0
mov cx,4*(SIZE START_AND_SIZE)
cld
rep stosb
;
; Build the start/offset table.
;
mov cx,4 ; cx = loop count
add si,1beh ; ds:si -> start of partition table
mov di,Tablel ; es:di -> local start/size table
nextent:
cmp byte ptr [si+4],0
jnz @f
add si,16
loop nextent
jmp short chkfull
@@: add si,8 ; ds:si -> relative sector field
movsw ; start low
movsw ; start high
movsw ; count low
movsw ; count high
inc al ; remember number of used entries
loop nextent
;
; See if the partition table is full.
;
chkfull:
cmp al,4
jne @f
mov ax,0ffffh
je done1
;
; Sort the local start/size table. Before calling crt
; make sure ds addresses DGROUP.
;
@@: push ds
push DGROUP
pop ds
push ax ; save table length
push SEG CompareStartSize
push OFFSET CompareStartSize ; compare routine pointer
push SIZE START_AND_SIZE ; size of each element
push ax ; number of elements to sort
push Table ; array of elements to sort
call _qsort
add sp,12
pop bx ; restore table length
pop ds
;
; Put a "fence" entry at the end of the table
; for space at the end of the disk.
;
mov al,SIZE START_AND_SIZE
mul bl ; ax = byte offset to fence entry
inc bl ; account for fence entry
les di,Table
add di,ax ; es:di -> fence entry
mov ax,DiskSizel
mov es:[di].PartStartl,ax
mov ax,DiskSizeh
mov es:[di].PartStarth,ax
mov es:[di].PartSizel,1
mov es:[di].PartSizeh,0
;
; Initialize for loop. The first space starts on the first sector
; of the second head.
;
mov al,SectorsPerTrack
cbw
mov FreeStartl,ax
mov FreeStarth,0
mov cl,bl
xor ch,ch ; cx = # entries in table
les di,Table ; es:di -> start/offset table
jmp short aligned1
;
; Get the start of the partition and align to cylinder boundary
;
nextspace:
mov dx,FreeStarth
mov ax,FreeStartl ; dx:ax = start of free space
div SectorsPerCylinder ; dx = sector within cylinder
cmp dx,0 ; already aligned?
jz aligned1 ; yes
mov bx,SectorsPerCylinder
sub bx,dx ; bx = adjustment to next boundary
add FreeStartl,bx
adc FreeStarth,0 ; FreeStart now aligned
aligned1:
mov dx,es:[di].PartStarth
mov ax,es:[di].PartStartl ; dx:ax = start of partition
sub ax,FreeStartl
sbb dx,FreeStarth ; dx:ax = size of free space
push ax
push dx
;
; Now make sure the end of the free space is aligned.
;
add ax,FreeStartl
adc dx,FreeStarth ; dx:ax = first sector past free space
div SectorsPerCylinder ; dx = sector within cylinder (may be 0)
mov bx,dx
pop dx
pop ax ; dx:ax = size of free space
sub ax,bx
sbb dx,0 ; dx:ax = size of aligned free space
js nextspace1 ; just in case
;
; Check the free space to see if it's large enough.
;
cmp dx,MinimumSectorCounth
ja makepart ; it's large enough
jb nextspace1
cmp ax,MinimumSectorCountl
jae makepart
nextspace1:
mov ax,es:[di].PartStartl
add ax,es:[di].PartSizel
mov FreeStartl,ax
mov ax,es:[di].PartStarth
adc ax,es:[di].PartSizeh
mov FreeStarth,ax ; next space is after this partition
add di,SIZE START_AND_SIZE ; point at next table entry
loop nextspace
mov ax,cx ; no room, set ax for error return
dec ax
jmp done1
;
; If we get here, we've found a free space that will work
; for our partition.
;
; FreeStart has the start of the free space.
;
makepart:
mov ax,FreeStartl
add ax,MinimumSectorCountl
mov dx,FreeStarth
adc dx,MinimumSectorCounth
div SectorsPerCylinder ; dx = sector within cylinder
cmp dx,0 ; aligned already?
jz @f ; yes
mov bx,SectorsPerCylinder
sub bx,dx ; bx = adjustment to next cyl boundary
add MinimumSectorCountl,bx
adc MinimumSectorCounth,0
;
; Now MinimumSectorCount has the actual sector count.
; Find a free table entry. We know there is one or else
; we'd have errored out a while ago.
;
@@: lds si,SectorBuffer
add si,1beh ; ds:si -> partition table
@@: cmp byte ptr [si+4],0
jz makepart1
add si,16
jmp short @b
makepart1:
mov ax,FreeStartl
mov dx,FreeStarth
mov [si+8],ax
mov [si+10],dx
add si,1
call pMakeCHS
mov ax,MinimumSectorCountl
mov dx,MinimumSectorCounth
mov [si+11],ax
mov [si+13],dx
add ax,FreeStartl
adc dx,FreeStarth
sub ax,1
sbb dx,0
add si,4
call pMakeCHS ; al = xint13 required flag
sub si,1 ; ds:si -> system id byte
;
; Figure out the partition id.
; al is xint13 required flag
;
mov dx,PartitionClass
mov ah,SystemId
call pDetermineSystemId
mov [si],al ; store away system id
sub si,4 ; ds:si -> partition table entry
call pNewPartitionRecord
cmp ax,0ffffh
je done1 ; error, bail now
;
; Phew. Write out the master boot sector.
;
push ax ; save partition id
push SectorBuffer
push 1
push 0
push 0
push DiskHandle
call _WriteDisk
add sp,14 ; ax set for return
pop dx ; dx = partition id
cmp ax,0 ; error?
jne @f ; no
dec ax ; ax = -1 for error return
jmp short done1
@@: mov ax,dx ; ax = partition id for return
done1:
push ax
push Table
push DGROUP
pop ds ; address DGROUP for crt
call _free
add sp,4
pop ax
done2:
pop di
pop si
pop bx
pop es
pop ds
leave
retf
_MakePartitionAtStartOfDisk endp
Comparand1 equ dword ptr [bp+6]
Comparand2 equ dword ptr [bp+10]
CompareStartSize proc far
push bp
mov bp,sp
push ds
push es
push di
push si
lds si,Comparand1
les di,Comparand2
mov dx,es:[di].PartStarth
mov ax,es:[di].PartStartl
cmp [si].PartStarth,dx
jb less1
ja greater1
cmp [si].PartStartl,ax
jb less1
ja greater1
xor ax,ax
jmp short compdone
less1:
mov ax,0ffffh
jmp short compdone
greater1:
mov ax,1
compdone:
pop si
pop di
pop es
pop ds
leave
retf
CompareStartSize endp
;++
;
; INT
; _far
; MakePartitionAtEndOfEmptyDisk(
; IN HDISK DiskHandle,
; OUT FPVOID SectorBuffer,
; IN ULONG MinimumSectorCount,
; IN BOOL NewMasterBootCode
; );
;
; Routine Description:
;
; This routine creates an partition at the very end of a disk.
; The disk MUST be completely empty. If no valid MBR exists,
; one will be created.
;
; The partition will be made active.
;
; Arguments:
;
; DiskHandle - supplies handle to open disk, from OpenDisk().
;
; SectorBuffer - supplies a pointer to a buffer suitable for use
; for i/o of a single sector. This buffer must not
; cross a DMA boundary, but the caller is responsible
; for ensuring this.
;
; MinimumSectorCount - supplies minimum number of sectors
; for the partition. The actual size may be larger
; to account for rounding, etc.
;
; This routine does NOT properly deal with partitions
; that start on cylinder 0 or are larger than the size
; of the disk! The caller must ensure that these cases
; do not occur.
;
; NewMasterBootCode - if non-0, then new master boot code will
; be written regardless of the current state of the MBR.
;
; Return Value:
;
; Partition id of newly created partition.
; -1 means failure
;
;--
DiskHandle equ dword ptr [bp+6]
DiskHandlel equ word ptr [bp+6]
DiskHandleh equ word ptr [bp+8]
SectorBuffer equ dword ptr [bp+10]
SectorBufferl equ word ptr [bp+10]
SectorBufferh equ word ptr [bp+12]
MinimumSectorCount equ dword ptr [bp+14]
MinimumSectorCountl equ word ptr [bp+14]
MinimumSectorCounth equ word ptr [bp+16]
NewMasterBootCode equ word ptr [bp+18]
ExtSecCnth equ word ptr [bp-2]
ExtSecCntl equ word ptr [bp-4]
ExtSecCnt equ dword ptr [bp-4]
Cylinders equ word ptr [bp-6]
Heads equ word ptr [bp-8]
SectorsPerTrack equ byte ptr [bp-9]
Int13UnitNumber equ byte ptr [bp-10]
SectorsPerCylinder equ word ptr [bp-12]
DiskSizeh equ word ptr [bp-14]
DiskSizel equ word ptr [bp-16]
DiskSize equ dword ptr [bp-16]
DiskId equ word ptr [bp-18]
public _MakePartitionAtEndOfEmptyDisk
_MakePartitionAtEndOfEmptyDisk proc far
push bp
mov bp,sp
sub sp,18
push ds
push es
push bx
push si
push di
;
; Get disk info. This also makes sure the handle is open,
; calculates the number of sectors we can address on the disk,
; and the number of sectors in a cylinder.
;
call near ptr pGetDiskValues
jnc @f
mov ax,0ffffh
jc mpaod_4
@@:
;
; Read the mbr.
;
push SectorBuffer
push 1
push 0
push 0
push DiskHandle
call _ReadDisk
add sp,14
cmp ax,0
jne @f
dec ax ; ax = -1 for error return
jmp mpaod_4
;
; Check the mbr. If not valid, make it valid.
;
@@: les di,SectorBuffer
cmp NewMasterBootCode,0
jnz makembr ; caller wants new master boot code
cmp byte ptr es:[di+510],055h
jne makembr
cmp byte ptr es:[di+511],0aah
je mbrok
makembr:
mov byte ptr es:[di+510],055h
mov byte ptr es:[di+511],0aah
mov si,offset DGROUP:_x86BootCode
mov cx,1b8h/2 ; don't overwrite NTFT sig or table
rep movsw
mbrok:
;
; Make sure all entries are empty.
;
lds si,SectorBuffer
add si,1beh
mov cx,0
mov ax,cx
dec ax ; ax = -1
cmp [si+04h],cl
jnz mpaod_4
cmp [si+14h],cl
jnz mpaod_4
cmp [si+24h],cl
jnz mpaod_4
cmp [si+34h],cl
jnz mpaod_4
;
; Calculate the starting sector. We don't worry about aligning
; the end sector because in the conventional int13 case we
; calculated the disk size based on cylinder count, which means
; it is guaranteed to be aligned; in the xint13 case CHS isn't
; even relevent and in any case there won't be any partitions
; on the disk after this one.
;
mov ax,DiskSizel
sub ax,MinimumSectorCountl
mov dx,DiskSizeh
sbb dx,MinimumSectorCounth ; dx:ax = start sector of partition
mov [si+8],ax
mov [si+10],dx ; save in partition table
div SectorsPerCylinder ; ax = cyl, dx = sector within cyl
sub [si+8],dx ; note: dx is zero if already aligned
sbb [si+10],cx ; partition table has aligned start
mov ax,MinimumSectorCountl
add ax,dx ; grow to account for alignment
mov [si+12],ax
mov ax,MinimumSectorCounth
adc ax,cx
mov [si+14],ax ; put adjusted size in partition table
;
; Make the partition active.
;
mov byte ptr [si],80h
;
; Fill in CHS values for the partition
;
mov ax,[si+8]
mov dx,[si+10] ; dx:ax = start sector
inc si ; ds:si -> start CHS in part table
call pMakeCHS
mov ax,[si+7]
add ax,[si+11]
mov dx,[si+9]
adc dx,[si+13]
sub ax,1
sbb dx,0 ; dx:ax = last sector
add si,4 ; ds:si -> end CHS in part table
call pMakeCHS ; al = overflow flag
;
; Figure out the system id.
; al is xint13 required flag
;
mov dx,PARTCLASS_FAT
call pDetermineSystemId
mov [si-1],al ; store away system id
;
; Build a partition record for this guy and add to list.
;
sub si,5 ; ds:si -> partition table entry
call pNewPartitionRecord
cmp ax,0ffffh
je mpaod_4 ; error, ax set for return
;
; The mbr is ready, write it out.
;
push ax
push SectorBuffer
push 1
push 0
push 0
push DiskHandle
call _WriteDisk
add sp,14
mov dx,ax
pop ax ; ax = partition id
cmp dx,0 ; write error?
jnz mpaod_4 ; no, ax = partition id for exit
mov ax,0ffffh ; set ax for error return
mpaod_4:
pop di
pop si
pop bx
pop es
pop ds
leave
retf
_MakePartitionAtEndOfEmptyDisk endp
;++
;
; INT
; _far
; ReinitializePartitionTable(
; IN HDISK DiskHandle,
; OUT FPVOID SectorBuffer
; );
;
; Routine Description:
;
; This routine wipes a disk completely clean by clearning
; the partition table and writing new boot code.
;
; NOTE: after this routine, partition ids may change!
;
; Arguments:
;
; DiskHandle - supplies handle to open disk, from OpenDisk().
;
; SectorBuffer - supplies a pointer to a buffer suitable for use
; for i/o of a single sector. This buffer must not
; cross a DMA boundary, but the caller is responsible
; for ensuring this.
;
; Return Value:
;
; The new number of total partitions, -1 if error
;
;--
DiskHandle equ dword ptr [bp+6]
SectorBuffer equ dword ptr [bp+10]
public _ReinitializePartitionTable
_ReinitializePartitionTable proc far
push bp
mov bp,sp
push ds
push es
push si
push di
pushf
;
; This is very simple. Move template boot code
; into the sector buffer and write it out.
;
les di,SectorBuffer
push DGROUP
pop ds
mov si,OFFSET DGROUP:_x86BootCode
mov cx,512/2
cld
rep movsw
push SectorBuffer
push 1
push 0
push 0
push DiskHandle
call _WriteDisk
add sp,14
cmp ax,0
jnz rpt2
dec ax ; ax = -1 for return
jmp short rpt8
;
; Now go through the partition list, removing all entries that were
; on this disk.
;
rpt2:
les di,DiskHandle
mov bx,es:[di].DiskInfoDiskId ; bx = id of disk we're wiping
mov dx,[PartitionListCount]
mov si,OFFSET DGROUP:PartitionList ; ds:si = &PartitionList
.errnz PartInfoNext
rpt3:
mov cx,[si].PartInfoNextl
or cx,[si].PartInfoNexth
jz rpt5 ; done
les di,[si].PartInfoNext ; es:di -> current, ds:si -> prev
cmp es:[di].PartInfoDiskId,bx ; partition on disk we wiped?
jne rpt4 ; no
dec dx ; one fewer total partitions
mov ax,es:[di].PartInfoNextl
mov [si].PartInfoNextl,ax
mov ax,es:[di].PartInfoNexth
mov [si].PartInfoNexth,ax ; prev->next = current->next
push bx
push ds
push DGROUP
pop ds ; make sure we're addressing DGROUP
push es
push di
call _free ; free(current)
add sp,4
pop ds
pop bx ; restore disk id
jmp short rpt3
rpt4: mov ax,es
mov ds,ax
mov si,di ; prev = current
jmp short rpt3
rpt5:
push DGROUP
pop ds
mov [PartitionListCount],dx ; save new count
mov ax,dx ; ax = return value
;
; Now reassign partition ids so they are contiguous.
;
mov si,OFFSET DGROUP:PartitionList
rpt6: mov cx,[si].PartInfoNextl
or cx,[si].PartInfoNexth
jz rpt8
dec dx
lds si,[si].PartInfoNext
mov [si].PartInfoDiskId,dx
jmp short rpt6
rpt8:
popf
pop di
pop si
pop es
pop ds
leave
retf
_ReinitializePartitionTable endp
;
; dx:ax = sector to translate
; ds:si -> CHS bytes
;
pMakeCHS proc near
div SectorsPerCylinder ; ax = cylinder, dx = sector in cyl
cmp ax,Cylinders ; overflow?
jb chsok ; no, continue
push 1 ; overflow flag
mov ax,Cylinders
dec ax ; store max cylinder in table
jmp short chs1
chsok:
push 0 ; no overflow flag
chs1: mov cx,ax
xchg cl,ch
shl cl,6
;
; small divide is acceptable here since head is 1-255, sector is
; 1-63 (and thus max sector within cyl is (63*256)-1).
;
mov ax,dx
div SectorsPerTrack ; al = head, ah = sector
inc ah ; sector is 1-based
or cl,ah ; cx has cyl/sector in int13 format
storechs:
mov [si+1],cx ; store in partition table entry
mov [si],al ; store head in partition table entry
pop ax ; return overflow flag
ret
pMakeCHS endp
;
; ds:si -> partition table entry with lba and sysid fields filled in
; preserves none
; returns new part ordinal or -1
;
pNewPartitionRecord proc near
;
; Allocate a new partition record
;
push ds
push si
push DGROUP
pop ds
mov si,OFFSET DGROUP:PartitionListCount
push [si] ; save count for later
inc word ptr [si]
push SIZE PART_INFO
call _malloc
add sp,2
pop bx ; restore partition count
pop si
pop ds ; ds:si -> partition table entry
mov cx,ax
or cx,dx
jnz @f ; malloc ok
mov ax,0ffffh
jz npr_done ; return failure
@@: push bx
mov cx,DGROUP
mov es,cx
mov di,OFFSET DGROUP:PartitionList ; es:di = &PartitionList
.errnz PartInfoNext
mov cx,es:[di] ; get current head of list in bx:cx
mov bx,es:[di+2]
mov es:[di],ax
mov es:[di+2],dx ; insert new record at head of list
mov es,dx
mov di,ax ; es:di -> new record
mov es:[di].PartInfoNextl,cx
mov es:[di].PartInfoNexth,bx
mov ax,DiskId
mov es:[di].PartInfoDiskId,ax
pop ax ; partition ordinal, also return val
mov es:[di].PartInfoOrdinal,ax
mov cx,[si+8]
mov es:[di].PartInfoStartSectorl,cx
mov cx,[si+10]
mov es:[di].PartInfoStartSectorh,cx
mov cx,[si+12]
mov es:[di].PartInfoSectorCountl,cx
mov cx,[si+14]
mov es:[di].PartInfoSectorCounth,cx
mov cl,[si+4]
mov es:[di].PartInfoSystemId,cl
;
; Indicate partition not open
;
mov es:[di].PartInfoPartOpen,0
mov es:[di].PartInfoDiskHandlel,0
mov es:[di].PartInfoDiskHandleh,0
npr_done:
ret
pNewPartitionRecord endp
;
; No params, nested in top-level routines above
;
pGetDiskValues proc near
;
; Get disk info. This also makes sure the handle is open.
;
push ss
lea bx,DiskId
push bx
push ss
lea bx,ExtSecCnt
push bx
push ss
lea bx,Cylinders
push bx
push ss
lea bx,Heads
push bx
push ss
lea bx,SectorsPerTrack
push bx
push ss
lea bx,Int13UnitNumber
push bx
push DiskHandle
call _GetDiskInfoByHandle
add sp,28
cmp ax,0
jnz @f
stc
ret
;
; Calculate the number of sectors we can address on the disk.
; Also precalculate the number of sectors in a cylinder.
;
@@: mov al,SectorsPerTrack
cbw
mul Heads ; ax = sectors per cylinder, dx = 0
mov SectorsPerCylinder,ax
cmp ExtSecCntl,dx
jnz usexcnt
cmp ExtSecCnth,dx
jnz usexcnt
mul Cylinders ; dx:ax = sectors on disk
jmp short storsize
usexcnt:
mov dx,ExtSecCnth
mov ax,ExtSecCntl
storsize:
mov DiskSizeh,dx
mov DiskSizel,ax
clc
gv3: ret
pGetDiskValues endp
;
; No params, nested in top-level routines above
; al = xint13 required flag
; dx = partition class
; ah = sysid if unknown class
;
; returns system id in al
;
pDetermineSystemId proc near
cmp dx,PARTCLASS_FAT
jne tryfat32
cmp al,0
je @f
mov al,0eh ; type e = fat xint13
jmp short gotsysid
@@: cmp MinimumSectorCounth,0
jne bigfat
cmp MinimumSectorCountl,32680
jb fat12
mov al,4 ; type 4 = fat16
jmp short gotsysid
fat12: mov al,1 ; type 1 = fat12
jmp short gotsysid
bigfat: mov al,6 ; type 6 = huge fat
jmp short gotsysid
tryfat32:
cmp dx,PARTCLASS_FAT32
jne tryntfs
cmp al,0
jne @f
mov al,0bh ; type b = fat32 non-xint13
jmp short gotsysid
@@: mov al,0ch ; type c = fat32 xint13
jmp short gotsysid
tryntfs:
cmp dx,PARTCLASS_NTFS
jne othersys
mov al,7 ; type 7 = ntfs
jmp short gotsysid
othersys:
mov al,ah
gotsysid:
ret
pDetermineSystemId endp
end