; BPB_DPB.INC -- Data structures for the BPB (BIOS Parameter Block) and ; the DPB (Disk Parameter Block). Compiled by: ; James R. Webster 113 Riverview Drive Lafollette, TN 37766 ; Free for anyone to use! EMAIL: jwebste3@bellsouth.net ; ; include bpb_dpb.inc ;Insert this line at the top of your .ASM file, ; ; but after "include macro.inc". .xlist ;Turn off list-file generation. ;---------------------------------------------------------------------------- ; The below is the BPB (BIOS Parameter Block) struc from a disks Boot Sector, ; sector 0. ; ; BPB_NOTES 1. Offsets 00h - 17h = All versions of DOS. ; 2. Offset 18h - 1Dh = Began with DOS v3.0. ; 3. Offset 1Ch = Expanded to a dword value in DOS v4.0. ; 4. Offset 20h = Began with DOS v4.0. If the word value at ; offset 13h is 0, the total number of logical disk sectors ; is in this dword value. This value includes # hidden sectors! ; 5. Offsets 24h - 3Dh = Began with DOS v4.0. ;---------------------------------------------------------------------------- ;Offset bpb struc ;------ ;Declare BPB struc. bpb_jmp db 3 dup (?) ; 00 ;3 byte jump to boot code. bpb_oem db 8 dup (?) ; 03 ;OEM signature (ASCII string). bpb_bps dw ? ; 0B ;Bytes per sector. bpb_spc db ? ; 0D ;Sectors per cluster. bpb_rs0 dw ? ; 0E ;Number of reserved sectors starting at 0. bpb_nf db ? ; 10 ;Number of FATs (File Allocation Table's). bpb_rde dw ? ; 11 ;Max number of Root Dir Entries allowed. bpb_ns dw ? ; 13 ;Total number of logical disk sectors. bpb_mdb db ? ; 15 ;Media Descriptor byte. bpb_spf dw ? ; 16 ;Sectors per FAT. bpb_spt dw ? ; 18 ;Sectors per track. bpb_nh dw ? ; 1A ;Number of heads. bpb_nhs dw ? ; 1C ;Number of hidden sectors. bpb_nhs_hi dw ? ; 1E ;Number of hidden sectors, high word. v4.0+. bpb_ns4 dd ? ; 20 ;Total number of logical disk sectors if ; value at offset 13h = 0. DOS v4.0 or > ! bpb_dsktype db 2 dup (?); 24 ;FDD = 00,00. HDD = 80,00. DOS v4.0+ bpb_extbios db ? ; 26 ;If = 29h, Extended BIOS present. DOS v4.0+ bpb_ser_no dw ? ; 27 ;Volume Serial Number, low word. DOS v4.0+ bpb_ser_nohi dw ? ; 29 ;Volume Serial Number, high word. DOS v4.0+ bpb_vol_sig db 11 dup (?); 2B ;Volume Signature (aka LABEL). DOS v4.0+ bpb_FATtype db 8 dup (?); 36 ;"FAT12 " or "FAT16 ". DOS v4.0+ bpb ends ;---------------------------------------------------------------------------- ; The below are the DPB (Disk Parameter Block) struc's that are initialized ; by the operating system (the kernal). They may be accessed by INT 21h, ; Function 32h. Example: ; mov ah,32h ;Get DPB for specified drive. ; xor dh,dh ;DH = 0. ; mov dl,disk_drive_no ;Start with default/requested drive. ; inc dl ;0 = default, 1 = A, 2 = B, etc. ; int 21h ;Returns: DS:BX pointer. ; As far as I know, this is compatiable through DOS v7.x. ; ; DPB_NOTE #1 All versions of DOS are identical up to this point. ; v4.0 changed this value from a "byte" to a "word". ; Causing the remaining values to be offset by 1 extra byte. ; DPB_NOTE #2 FF = Disk has not been accessed. 00 = Disk has been accessed. ; DPB_NOTE #3 v2.xx = Starting cluster number of current dir. ; v3.xx and above = Starting cluster # in search for free space. ; DPB_NOTE #4 v2.xx = 64 bytes long. Current directory name (ASCIIZ string). ; v3.xx and above = Unknown. Always FFFF. ;---------------------------------------------------------------------------- ;Offset dpb2 struc ;------ ;Declare DPB struc for v2.xx dpb_drv db ? ; 00 ;Drive number (0 = A, 1 = B, etc.). dpb_udn db ? ; 01 ;Unit number within device driver. dpb_bps dw ? ; 02 ;Bytes per sector. dpb_spc db ? ; 04 ;Sectors per cluster -1. dpb_lb2 db ? ; 05 ;Log base 2 of the cluster size. dpb_rs0 dw ? ; 06 ;Number of reserved sectors starting at 0. dpb_nf db ? ; 08 ;Number of FATs (File Allocation Table's). dpb_rde dw ? ; 09 ;Max number of Root Dir Entries allowed. dpb_dss dw ? ; 0B ;Data sector start (0 based). dpb_lcn dw ? ; 0D ;Last cluster number. dpb_spf db ? ; 0F ;Sectors per FAT. See DPB_NOTE #1. dpb_rds dw ? ; 10 ;Sector where Root Directory starts. dpb_adh dd ? ; 12 ;Address of device header. dpb_mdb db ? ; 16 ;Media Descriptor byte. dpb_aib db ? ; 17 ;Access indicator byte. See DPB_NOTE #2. dpb_ndpb dd ? ; 18 ;Address of next DPB. FFFF:FFFF = Last DPB. dpb_sccd dw ? ; 1C ;Starting cluster number of current dir. ; See DPB_NOTE #3. dpb_cd db ? ; 1E ;64 bytes long. Current directory name dpb2 ends ; (ASCIIZ string). See DPB_NOTE #4. ;Offset dpb3 struc ;------ ;Declare DPB struc for v3.xx dpb_drv3 db ? ; 00 ;Drive number (0 = A, 1 = B, etc.). dpb_udn3 db ? ; 01 ;Unit number within device driver. dpb_bps3 dw ? ; 02 ;Bytes per sector. dpb_spc3 db ? ; 04 ;Sectors per cluster -1. dpb_lb23 db ? ; 05 ;Log base 2 of the cluster size. dpb_rs03 dw ? ; 06 ;Number of reserved sectors starting at 0. dpb_nf3 db ? ; 08 ;Number of FATs (File Allocation Table's). dpb_rde3 dw ? ; 09 ;Max number of Root Dir Entries allowed. dpb_dss3 dw ? ; 0B ;Data sector start (0 based). dpb_lcn3 dw ? ; 0D ;Last cluster number. dpb_spf3 db ? ; 0F ;Sectors per FAT. See DPB_NOTE #1. dpb_rds3 dw ? ; 10 ;Sector where Root Directory starts. dpb_adh3 dd ? ; 12 ;Address of device header. dpb_mdb3 db ? ; 16 ;Media Descriptor byte. dpb_aib3 db ? ; 17 ;Access indicator byte. See DPB_NOTE #2. dpb_ndpb3 dd ? ; 18 ;Address of next DPB. FFFF:FFFF = Last DPB. dpb_nfc3 dw ? ; 1C ;Starting cluster number in search for free ; space. See DPB_NOTE #3. dpb_unk3 dw ? ; 1E ;Unknown. Always FFFF. See DPB_NOTE #4. dpb3 ends ;Offset dpb4 struc ;------ ;Declare DPB struc for v4.xx thru v7.x dpb_drv4 db ? ; 00 ;Drive number (0 = A, 1 = B, etc.). dpb_udn4 db ? ; 01 ;Unit number within device driver. dpb_bps4 dw ? ; 02 ;Bytes per sector. dpb_spc4 db ? ; 04 ;Sectors per cluster -1. dpb_lb24 db ? ; 05 ;Log base 2 of the cluster size. dpb_rs04 dw ? ; 06 ;Number of reserved sectors starting at 0. dpb_nf4 db ? ; 08 ;Number of FATs (File Allocation Table's). dpb_rde4 dw ? ; 09 ;Max number of Root Dir Entries allowed. dpb_dss4 dw ? ; 0B ;Data sector start (0 based). dpb_lcn4 dw ? ; 0D ;Last cluster number. dpb_spf4 dw ? ; 0F ;Sectors per FAT. See DPB_NOTE #1. dpb_rds4 dw ? ; 11 ;Sector where Root Directory starts. dpb_adh4 dd ? ; 13 ;Address of device header. dpb_mdb4 db ? ; 17 ;Media Descriptor byte. dpb_aib4 db ? ; 18 ;Access indicator byte. See DPB_NOTE #2. dpb_ndpb4 dd ? ; 19 ;Address of next DPB. FFFF:FFFF = Last DPB. dpb_nfc4 dw ? ; 1D ;Starting cluster number in search for free ; space. See DPB_NOTE #3. dpb_unk4 dw ? ; 1F ;Unknown. Always FFFF. See DPB_NOTE #4. dpb4 ends .list ;End of BPB_DPB.INC file. comment \ The below is from some of my code. Will give an idea of how to calculate. May want to move this portion to another file! ;--------------------------------------------------------------------; ; This procedure reads the DPB (Disk Parameter Block) for the ; ; default or specified drive. Compatiable to DOS v7.xx ; ; ; ; Callers: READ_BPB ; ; Reads: DOS_MAJOR ; ; Writes: DPB_DRIVE_NUMBER, SECTORS_PER_CLUSTER, NUMBER_OF_FATS, ; ; MEDIA_DESCRIPTOR_BYTE, FAT_BIT_TYPE, BYTES_PER_SECTOR, ; ; RES_SECTORS_AT_0, SECTORS_PER_FAT, FAT_NO1_START, ; ; FAT_NO2_START, ROOT_DIR_START, ROOT_DIR_ENTRIES_MAX, ; ; DIR_ENTRIES_PER_SECTOR, NO_ROOT_DIR_SECTORS, ; ; DATA_SECTOR_START, LAST_CLUSTER_NO, NEXT_FREE_CLUSTER, ; ; MAX_SECTOR_HIGH, MAX_SECTOR_LOW, FAT_SECTOR_CALC1/2, ; ; NEXT_DPB_SEG, NEXT_DPB_OFFS, BAD/EOF_CLUSTER_MARKING ; ; On entry: DL = specified drive to read (00h = A, 01h = B, etc.). ; ;--------------------------------------------------------------------; read_dpb proc pushad pushr ;"Undocumented" mov ah,32h ;Get DPB for specified drive. inc dl ;0 = default, 1 = A, 2 = B, etc. int 21h ;Returns: DS:BX pointer. mov dx,ds ;DX = segment address. pop ds ;Restore our data segment. nop mov es,dx ;ES:BX = pointer to requested DPB. nop ;--Read and save the default values.--------------------------------------- mov ax,es:[bx.dpb_bps] ;AX = bytes per sector. mov bytes_per_sector,ax ;Store it. xor ah,ah mov al,es:[bx.dpb_spc] ;AL = sectors per cluster -1. inc ax ;Make 1 based. mov sectors_per_cluster,ax ;Store it. mov ax,es:[bx.dpb_rs0] ;AX = reserved sectors @ 0. mov res_sectors_at_0,ax ;Store it. mov al,es:[bx.dpb_nf] ;AL = number of FATs. mov number_of_fats,al ;Store it. mov ax,es:[bx.dpb_rde] ;AX = # root directory entries. mov root_dir_entries_max,ax ;Store it. mov ax,es:[bx.dpb_dss] ;AX = data sector start. mov data_sector_start,ax ;Store it. mov ax,es:[bx.dpb_lcn] ;AX = last cluster number. mov last_cluster_no,ax ;Store it. cmp dos_major,4 ;Heres where 4.xx changes the jae read_dpb_4xx ; offset values. xor ah,ah ;AH = 0. mov al,es:[bx.dpb_spf] ;AL = sectors per FAT. mov sectors_per_fat,ax ;Store it as a word value! mov ax,es:[bx.dpb_rds] ;AX = sector # of root dir start. mov root_dir_start,ax ;Store it. mov al,es:[bx.dpb_mdb] ;AL = media descriptor byte. mov media_descriptor_byte,al ;Store it. jmps cont_read_dpb ;And jump to continue. read_dpb_4xx: mov ax,es:[bx.dpb_spf4] ;AX = sectors per FAT. mov sectors_per_fat,ax ;Store it. mov ax,es:[bx.dpb_rds4] ;AX = sector # of root dir start. mov root_dir_start,ax ;Store it. mov al,es:[bx.dpb_mdb4] ;AL = media descriptor byte. mov media_descriptor_byte,al ;Store it. ;--Now calculate some other important values.------------------------------ cont_read_dpb: mov ax,last_cluster_no ;AX = last cluster number. mov fat_bit_type,12d ;Assume a 12-bit FAT. mov bad_cluster_marking,0ff7h mov eof_cluster_marking,0fffh mov fat_sector_calc1,2 ;Used by INIT_FAT_SECTOR. mov fat_sector_calc2,3 cmp last_cluster_no,0ff6h ;12-bit FAT supports a maximum jbe end_dpb_fat_check ; of 4086d (0FF6h) clusters. mov fat_bit_type,16d ;If > 4086d, its a 16-bit FAT. mov bad_cluster_marking,0fff7h mov eof_cluster_marking,0ffffh mov fat_sector_calc1,1 ;Used by INIT_FAT_SECTOR. mov fat_sector_calc2,2 end_dpb_fat_check: dec ax ;Make 1 based. xor dx,dx ;DX = 0. mov cx,sectors_per_cluster ;CX = sectors per cluster. cmp cx,1 ;One sector per cluster ? je dpb_one_spc mul cx ;DX:AX = AX * CX. dpb_one_spc: mov cx,data_sector_start ;CX = data sector start. dec cx ;Make 0 based -1. xor bx,bx ;BX = 0. add ax,cx ;Add the low word values. adc dx,bx ;Add with carry the high words. mov max_sector_low,ax ;Store the last sector number mov max_sector_high,dx ; (0 based). mov ax,res_sectors_at_0 ;AX = reserved sectors @ 0. mov fat_no1_start,ax ;AX = FAT #1 sector start (0 based). cmp number_of_fats,1 ;Only 1 FAT ? je dpb_one_fat ;If so, jump. add ax,sectors_per_fat ;Compute FAT #2 sector start. dpb_one_fat: mov fat_no2_start,ax ;Store FAT #2 sector start (0 based). mov ax,data_sector_start ;AX = first data sector. mov bx,root_dir_start ;BX = first root directory sector. sub ax,bx ;AX = number of root dir sectors. mov no_root_dir_sectors,ax ;Store it. mov ax,bytes_per_sector ;AX = total bytes per one sector. shrr ax,5 ;Div AX by 32 bytes @ root dir entry. mov dir_entries_per_sector,ax ;Store it. exit_read_dpb: clc ;Clear the carry flag, valid drive. pop es popad ret read_dpb endp \