The LBA to CHS Conversion Formula

Materials:
Working complete PC
Blank Diskette
Student Diskette, "New Boot A Ver 2.0+"
Student CD-ROM, "Room 6359"
Objectives:
The student will become familiar with:
use the formula to verify the MBR partition table(s)
use the formulas to calculate the positions of file system sectors,
use the formulas to calculate the sizes of file system structures.
Competency:
The student will learn how to use the CHS-to-LBA sector coordinate conversion formulas for the purposes of data recovery including making calculations of the positions of key sectors listed within the partition table for the purposes of verifying it as well as being able to locate and load key sectors into DEBUG and being able to calculate the sizes of key structures including the FATs and the root directory.

    Preparation

  1. Boot to the student CD-ROM and GHOST in DOS. Accept the size offered (2GB) and restart the machine when prompted. Reboot to the CD-ROM a second time. Change into the Q:\DISKS directory and create a DOS 6.22 version bootable diskette with the command: "LOADDSKF 3C90XCLI.DSK B:" Remember that the physical diskette drive has been assigned drive letter B: by the bootable CD-ROM. The diskette being restored here is a DOS Client for a Novell bindery (NetWare 3.12) server used in NET2. It is however, a bootable DOS 6.22 diskette with many commands included particularly DEBUG.EXE.

  2. Change to the Q:\BIN directory and copy XMSDSK.EXE to the floppy. Copy DEVICE.COM to the floppy. Change to the floppy and rename the file CONFIG.SYS to CONFIG.OLD to prevent its execution. Remove the student CD-ROM and reboot to the floppy.

  3. Launch HIMEM.SYS manually using the DEVICE.COM command like this: "DEVICE HIMEM.SYS /V" DEVICE.COM is software not a part of DOS. It will NOT capitalize automatically like DOS will so be SURE that any switches sent to drivers are capitalized at the command line.

  4. Launch the RAM drive like this: "XMSDSK 8192 D: /Y /T" This sets up an 8MB RAM drive at the top of RAM and assigns it drive letter D.

  5. Change to the D: drive and set the path to the floppy: "path=A:\" Now launch DEBUG and proceed with the exercise below.

  6. Procedures

  7. The DEBUG LOAD command only reads COOKED sectors as opposed to RAW sectors. In our language a RAW sector is read AS IS by BIOS off of the disk. A COOKED sector is located and retrieved or written using the drive's file system. In the event that the drive's file system has been compromised then it is impossible to access COOKED sectors. They must be accessed RAW, directly by their geometric coordinate.

  8. The basic INT 13h interface that we use in DEBUG requires the CHS geometric coordinate for the sector being read. The LBA calls to the INT 13h interface are far too complex to be implemented from simple DEBUG scripts and too impractical for us to use. Because of this, two questions immediately arise: How can LBA addresses be converted to CHS (and vice versa)? And how can sectors be read that are beyond the CHS coordinate limits?

  9. The formula for converting from LBA to CHS will be examined in this exercise.

    LBA-to-CHS Formula
    
       LBA  
     (TH X TS)   = C, R1
    
       R1  
      (TS)   = H, R2
    
      R2 + 1  = S
    
    Where:
    LBA = the sector's LBA address to be converted
    C = the sector's Cylinder#
    TH = the Total Heads of the hard drive according to the BIOS translation in effect
    TS = the Total Sectors/Track of the hard drive
    H = the sector's Head#
    S = the sector's Sector#
    R1, R2 = integer remainder's of the divisions
    
  10. First load the hard drive's MBR into DEBUG's RAM workspace using the procedures developed in the Read the MBR with DEBUG module. This module also describes where the partition tables are located within the MBR and the layout of the partition tables. Display the bottom half of the MBR on screen and locate the first partition table:

    -d 200 2ff
    242C:0200  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
    242C:0210  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
    242C:0220  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
    242C:0230  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
    242C:0240  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
    242C:0250  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
    242C:0260  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
    242C:0270  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
    242C:0280  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
    242C:0290  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
    242C:02A0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
    242C:02B0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 80 01   ................
    242C:02C0  01 00 06 FE 7F 04 3F 00-00 00 86 FA 3F 00 00 00   ......?.....?...
    242C:02D0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
    242C:02E0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
    242C:02F0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 55 AA   ..............U.
    -_
    
  11. Chart the fields of the partition table as discussed in the Read the MBR with DEBUG module:

    Offset Size Value
    00h 1 byte 80
    01h 1 byte 01
    02h 1 byte 01
    03h 1 byte 00
    04h 1 byte 06
    05h 1 byte FE
    06h 1 byte 7F
    07h 1 byte 04
    08h 4 bytes 3F 00 00 00
    0Ch 4 bytes 86 FA 3F 00

  12. The full analysis of this partition table is discussed in the CHS-to-LBA Conversion Formula module. What is important here is to recognize the starting sector's address given within the table as: Cylinder=0, Head=1, Sector=1.

  13. Based on the procedures developed in the INT 13h module load the first sector of the partition into the RAM workspace BUT this time load 16 sectors instead of just one. Because more than one sector is being loaded the program code must reside at offset 100h and the sectors must be loaded into offset 200h. Otherwise, the sectors would overwrite the program code itself during its execution and lock up the PC:

    -a 100
    242C:0100 mov ax, 210
    242C:0103 mov bx, 200
    242C:0106 mov cx, 1
    242C:0109 mov dx, 180
    242C:010C int 13
    242C:010E int 3
    242C:010F (press [Enter] here to exit the assembler)
    -g=100
    AX=0001  BX=0200  CX=0001  DX=0180  SP=FFEE  BP=0000  SI=0000  DI=0000  
    DS=242C  ES=242C  SS=242C  CS=242C  IP=030E   NV UP EI PL ZR NA PE NC 
    242C:010E CC            INT	3                                  
    -_
    
    
  14. Notice the first instruction is mov ax, 210. This means read (02) sixteen sectors (10 hexadecimal). And the offset specified in the second instruction is 200, not 100. Note the g=100 command. Be careful and aware of where you are placing your program code, it is easy to get confused and execute from the wrong offset which will immediately lock up the PC and force you to reboot and start all over again.

  15. The sixteen sectors starting with the first sector of the partition are loaded into RAM at offset 200. The first sector is the DOS Boot Record. Display the top half on screen and notice the plain ASCII text "file system signature" of "MSDOS5.0" and below this the file system type "FAT16". The first three bytes of this sector are a machine language jump instruction to jump over the area that holds these pieces of data. The top of the sector holding these and many other pieces of data that describe the internal layout of the partition is called the Drive Parameter Block. The next major exercise will be the DPB layout followed by a deep analysis of it.

  16. Display the bootom half of the DBR on screen. Notice the error messages and the boot signature. In most cases the first File Allocation Table starts in the sector that immediately follows the DBR sector. In some cases it does not but in the classroom image it does. Display the top half of the second sector in RAM on screen. Remember that the top half of the DBR is displayed with "d 200 2ff" and the bottom half with "d 300 3ff" therefore the top half of the next sector would be shown on screen with "d 400 4ff":

    -d 400 4ff
    
  17. You will get used to the appearance of the FAT16 file allocation table, nothing else looks quite like it. The same is true of the FAT32 file allocation tables, in fact they look even more like a FAT than the FAT16 ones do. Since each FAT entry is 16-bits long or two bytes, then the first two bytes (the "F8 FF" at the top are FAT entry #0. The next two bytes (the "FF FF") are FAT entry #1. These are not actually used in the sense that they are not associated with actual data clusters within the partition. The first byte of entry #0, the "F8", is actually a media descriptor and means "this FAT is located on a hard drive."

  18. Since we know the size of the partition in sectors to be 4,192,902 sectors. Multiply this by 512 = 2,146,765,824 bytes. It is the largest possible FAT16 partition meaning it will have 32KB clusters. Divide the size by 32KB: 2,146,765,824 / 32768 = 65,514. This is the number of clusters in the partition. Since each one gets a 2 byte entry in the FAT, multiply by 2 = 131,028. This is the size of each FAT in bytes. Divide this by 512 = 255.9140625 which must be rounded up = 256. This is the number of sectors each FAT occupies on this partition. Since the first FAT starts at the sector following the DBR which is the sector at C=0, H=1, S=2, and it is 256 sectors long, then the starting sector of the second FAT can be calculated using LBA coordinates like this:

    
    (C x TH x TS) + (H x TS) + (S - 1) = LBA
    
    (0 x 255 x 63) + (1 x 63) + (2 - 1) = 64
    
    
  19. The start sector of the FAT is located at LBA sector address 64. Adding the total size in sectors of the FAT to it will point to the sector that immediately follows it as alluded to by the structure size formula introduced in the CHS-to-LBA Conversion Formula module. The sector that immediately follows the first FAT is the first sector of the second FAT. 64 + 256 = 320. This is the LBA address of the first sector of the second FAT. Now convert it to CHS so that the INT 13h script can be written to read it into RAM

    320 / (255x63) = C=0, R1=320
    320 / 63 = C=5, R2=5
    5 + 1 = S=6
    
    
  20. So the CHS address of the sector whose LBA address is 320 is: Cylinder=0, Head=5, Sector=6 according to the LBA-to-CHS formula. Write the code to load the sixteen sectors starting at this sector into RAM and execute it:

    -a 100
    242C:0100 mov ax, 210
    242C:0103 mov bx, 200
    242C:0106 mov cx, 6
    242C:0109 mov dx, 580
    242C:010C int 13
    242C:010E int 3
    242C:010F (press [Enter] here to exit the assembler)
    -g=100
    AX=0001  BX=0200  CX=0006  DX=0580  SP=FFEE  BP=0000  SI=0000  DI=0000  
    DS=242C  ES=242C  SS=242C  CS=242C  IP=030E   NV UP EI PL ZR NA PE NC 
    242C:010E CC            INT	3                                  
    -_
    
    
  21. Search the sectors for the value "F8 FF FF FF" hexadecimal (the first four bytes of the other FAT, since this is an exact duplicate it should also start with these four bytes) The sectors occupy RAM from where to where? There are 16 of them starting at offset 200h in DEBUG RAM workspace. Each is 200h bytes in size multiply 10h x 200h = 2000h the size of the sixteen sectors in RAM. They start at 200h not 00h, so add this to the size of 2000h + 200h = 2200h and this is the byte that follows them in RAM:

    -s 200 2200 F8 FF FF FF
    242C:0200
    -_
    
    
  22. Clearly the match is at the exact offset 0200h in RAM, the start of the first sector loaded into RAM, the expected sector is in fact the starting sector of the second FAT. Display it on screen with the "d 200 2ff" command to verify this fact.

  23. Now add 256 to the address of the LBA address of the starting sector of the second FAT: 320 + 256 = 576. This is the LBA address of the sector that immediately follows it. With FAT16 partitions, this is the first sector of the root directory. Convert LBA sector #576 to CHS:

    576 / (255x63) = C=0, R1=576
    576 / 63 = H=9, R2=9
    9 + 1 = S=10 (0Ah)
    
    
  24. Write the code to load sixteen sectors starting with this sector and execute it:

    -a 100
    242C:0100 mov ax, 210
    242C:0103 mov bx, 200
    242C:0106 mov cx, 0A
    242C:0109 mov dx, 980
    242C:010C int 13
    242C:010E int 3
    242C:010F (press [Enter] here to exit the assembler)
    -g=100
    AX=0001  BX=0200  CX=000A  DX=0980  SP=FFEE  BP=0000  SI=0000  DI=0000  
    DS=242C  ES=242C  SS=242C  CS=242C  IP=030E   NV UP EI PL ZR NA PE NC 
    242C:010E CC            INT	3                                  
    -_
    
    
  25. Search for the root directory entry for IO.SYS:

    -s 200 2200 "IO      SYS" (six spaces)
    242C:0200
    -_
    
    
  26. It is the first entry of the first sector that was loaded, it is exactly the starting sector of the root as predicted. Display the top half of the sector on screen with "d 200 2ff" to verify this fact.

  27. In the next exercise the structure of the DBR will be examined in detail.

Back to Page Top

Copyright©2000-2006 Brian Robinson ALL RIGHTS RESERVED