Low Level Hard Disk Operations

Published by +Tsehp March 2000
Courtesy of Immortal-Descendants

WARNING
Do not read this or attempt to apply the concepts reported in this essay if you fit into any of these categories;
  1. You are feeling tired or drowsy
  2. Drunk or Stoned or generally suffering the effects of chemical abuse (including too much caffeine)
  3. Lacking in brains
  4. You have a weak constitution, this material is not for the faint hearted.
  5. You have linux UP and running on your system, you probably don't need this essay as Linux probably has enough utils to do all this and most of this stuff should be non-issues
If at the end of the essay you aren't sure then I would advise that you leave well alone, you may be able to blag it to your friends but when the chips are down you do not want to mess up your disk.

Introduction
Well now that I have warned you I probably ought to explain what this essay is about. As I have used computers more and more I have become familiar with them, even accustomed, now I know what ails them and how to cure it. And so onto the ailment, a knackered hard disk, and not just any knackered hard disk, one who's mbr record has been messed up. Their seems to be a lot of solutions for if you accidentally format you hard disk or delete your work (unless it was valuable of course), there are however no real ways of fixing the even lower level problem of boot records on large hard disks, or at least not that I have come accross. What happens if you manage to leave your MBR in an inconsistent state after using Fdisk or Partion Magic? The likely hood is they won't want to associate themselves with it ever again, after all who likes to admit their failures? Well I will attempt to explain how to fix some of these problems and just what is wrong in some cases as I have still yet to fix them myself.
I would also like to note that although all the misadventures with my hard disks happened when some-one was attempting to use partion magic and/or install linux I hold no grudges against them, in fact both products are highly valued by me, I love the safety that partion magic allows. Being able to see what you are doing and do all the neat things like moving partitions is great, I have never had a problem with it my self and I don't know how it is possible to mess up using it. I also like linux, I have 95 for games, and presently for DVD's, and Linux for work - it's the bussiness.

 


Tools needed :
If you do actually need to apply the techniques then you will need the items in the folowing list, read the essay all the way through first. Check whether your problem is actually of the type that I describe here, hard disks always like to find new and interesting ways to fail so just because it doesn't boot doesn't mean that it's the mbr that has gone kaput.

 

 


What went wrong?
First I shall try to explain where it all went wrong, the reason why I have learnt the little I know about this subject. In my case it was all due to my brother attempting to install linux on various machines, mine first (whilst I was away) and then his own. In order to install an o/s like linux you need to sort yourself out with a partition for the root file system, say a gig or so for the main stuff. Now some how the first time my brother tried this on MY machine he managed to delete 75% of the partitions I had set-up, there was already room enough partitioned off but he was convinced he had to use fdisk and so my HD bit the dust (well almost). The second time, after having been convinced of the folly of using fdisk by a concerned brother he decided to use partion magic's o/s wizard. Some how he managed to get the tool to leave his HD in an inconsistent state with a reported partion that started 50gig past the end of the HD and was about 500G long, perhaps I exagurate but either way Partion Magic wouldn't even start up and fdisk was it's usual responsive self. The other problem that I have had is with removing Linux, I removed a linux installation from my machine and reformatted the partion to FAT, this was all fine until I must have overwritten the few sectors that make up the LILO boot program that would have been left on the HD. Oops, no more boot up for my machine, instead it hung after displaying just the LI of LILO :(
Now there is some good news and bad news, I can fix two of the problems, I just haven't figured out the last one yet.

 

A brief explanation of the structure of modern hard disks
Since hard disks have become so large and IDE and the original file-systems like FAT were not designed for HD's this large a solution had to be found to allow the Hard Disks to be accessed while not making all the existing software obsolete. The way that hard disks have always been accessed by operating systems has always been through int 13h on intel architectures. If you have a look at the functions for disk access they take 3 bytes to specify the sector to read/modify. Head/sector/track - 3 bytes gives a range of 0 - 16777215 sectors, with each sector holding 512 bytes this allows 8589934080 bytes, or 388607.5k - 8191Mb - 7.9Gb.

 
Now I didn't do this arithemetic originally, I hadn't really thought about this limitation despite having 10Gb Hd's in my machine. If you start off using the standard int 13 calls to read the boot sector then you will get the boot sector for your C drive, expecting a Master Boot Record alarm bells started ringing. How the hell do I access my MBR if int 13 doesn't work? At this point I figured the best way to find out was to look at something that must be able to access it - fdisk. After unpacking it I dissasembled and just had a look through the source, I didn't know where to look so I started looking for familiar signs. Starting with a search of int 13h I noticed a call to a function 41h, I didn't recognise this so I had a look in the interrupt list[1].

Int 13h - function 41h turns out to be a check for the int 13 extensions, The next functions are the actual extended read and write functions, they allow the access of large hard disks. The original int 13 calls seem to be overriden by the os and made to access the partitions as if they were individual hard disks while these extended functions are the genuine article, providing the real read and write capability.
Now I've explained how we actually find the real hard disk under all confusion, the way that hard disks are partioned would be useful. Each hard disk has a Master Boot Record. This is the sector that is loaded by the BIOS when the machine starts up, just as the boot sectors of disks always have been, it's just that the MBR looks for another boot sector to load. Their should be one primary partition where the primary operating system will probably be located. After that there will be extended boot sectors referencing other boot sectors. The structure is like a tree, with actual boot sectors of the partitions as the leaves and the extended boot sectors as the branches, each allowing up to 4 way branches.

I have pasted in the structure of the boot sectors from the interrupt list, I don't think I can put it any better. I have abbreviated the operating system indicator to the most common o/s's.

 

Format of hard disk master boot sector:
Offset	Size	Description	(Table 00650)
 00h 446 BYTEs	Master bootstrap loader code
1BEh 16 BYTEs	partition record for partition 1 (see #00651)
1CEh 16 BYTEs	partition record for partition 2
1DEh 16 BYTEs	partition record for partition 3
1EEh 16 BYTEs	partition record for partition 4
1FEh	WORD	signature, AA55h indicates valid boot block

Format of partition record:
Offset	Size	Description	(Table 00651)
 00h	BYTE	boot indicator (80h = active partition)
 01h	BYTE	partition start head
 02h	BYTE	partition start sector (bits 0-5)
 03h	BYTE	partition start track (bits 8,9 in bits 6,7 of sector)
 04h	BYTE	operating system indicator (see #00652)
 05h	BYTE	partition end head
 06h	BYTE	partition end sector (bits 0-5)
 07h	BYTE	partition end track (bits 8,9 in bits 6,7 of sector)
 08h	DWORD	sectors preceding partition
 0Ch	DWORD	length of partition in sectors
SeeAlso: #00650

(Table 00652)
Values for operating system indicator:
 00h	empty partition-table entry
 01h	DOS 12-bit FAT
 04h	DOS 16-bit FAT (up to 32M)
 05h	DOS 3.3+ extended partition
 06h	DOS 3.31+ Large File System (16-bit FAT, over 32M)
 07h	OS/2 HPFS
 07h	Windows NT NTFS
 08h	OS/2 (v1.0-1.3 only)
 82h	Linux Swap partition
 83h	Linux native file system (ext2fs/xiafs)

 

Now we know what the boot record should look like, and we know how to read it we should be able to do just that. There is also a problem with the information in the MBR, it would appear that when they designed MBR's it was also pre large hard disks. There are again only 3 bytes for the sector again. According to the messages generated by Partion Info these are filled with place holders, the main problem is I'm not sure where it is figuring out the real values from. The 'sectors preceding partition' does however allow us to figure out where the partition is, so it shouldn't matter too much so long as you don't need to actually create a new partition by hand.

Just grab the noddy readMb program from the bottom of this page if you can't be bothered to create your own. Load the MBR and have a look at it in your fave hex viewer (UE does it for me). The first partition record entry should be okay, that is the one for your primary partition and should have the boot indicator set, it will probably be one of the other records that is screwed up. If you did manage to find a copy of partition info, it is freely distirbutable after all, then run that. Partion Info will help to collaborate the information you should be seeing in your mbr. The other program at the end of the essay is to write an MBR, use it with extreme caution. I would recommend you only keep the source on your hard disk and don't leave the executable lying around, it shouldn't work while an os is up but I shouldn't risk it. Remember to create a back up of the sector you are going to change before you do. If you haven't made the correct change you should at least be able to return the system back to it's previous state by just re-writing the old sector back. In order to run the program you will need a DOS boot up disk (just creating a system disk from 95 will do). Copy the program over and the sector to write and then reboot. Run the program and that is it.

Solving problem 1 - boot record in an inconsistent state.
When Partion Magic left the hard disk in an inconsistent state all that it did was leave a garbage entry in the MBR. All that I did was looked at the MBR and remove the offending entry, blanking it out with 0's. Save the new sector and write the sector to the hard disk, it's as simple as that.

Solving problem 2 - LILO boot sectors gone when partition reformatted to FAT
This one isn't quite as simple, you need to get hold of an already working MBR from something like 95. Then all you need to do is merge the code from the working MBR with the data from your MBR.

 
If you dissasemble your sector you will see that the start is all code. In the case of a 95 mbr it just looks through the partion records for a record with the boot indicator and loads that boot sector into memory and executes it. Linux on the other hand loads in about 5 sectors from it's partition and executes them, this allows all the extra 'multi-boot' functionality of the LILO loader, it was also why my HD no longer booted.

Here is a sample from my HD, I have messed up sector data at the bottom although you should be able to see the basic structure and possibly even use this as the template for what you use for recovering your own HD.

 

0000  33 C0 8E D0 BC 00 7C FB-50 07 50 1F FC BE 1B 7C
0010  BF 1B 06 50 57 B9 E5 01-F3 A4 CB BE BE 07 B1 04
0020  38 2C 7C 09 75 15 83 C6-10 E2 F5 CD 18 8B 14 8B
0030  EE 83 C6 10 49 74 16 38-2C 74 F6 BE 10 07 4E AC
0040  3C 00 74 FA BB 07 00 B4-0E CD 10 EB F2 89 46 25
0050  96 8A 46 04 B4 06 3C 0E-74 11 B4 0B 3C 0C 74 05
0060  3A C4 75 2B 40 C6 46 25-06 75 24 BB AA 55 50 B4
0070  41 CD 13 58 72 16 81 FB-55 AA 75 10 F6 C1 01 74
0080  0B 8A E0 88 56 24 C7 06-A1 06 EB 1E 88 66 04 BF
0090  0A 00 B8 01 02 8B DC 33-C9 83 FF 05 7F 03 8B 4E
00A0  25 03 4E 02 CD 13 72 29-BE 46 07 81 3E FE 7D 55
00B0  AA 74 5A 83 EF 05 7F DA-85 F6 75 83 BE 27 07 EB
00C0  8A 98 91 52 99 03 46 08-13 56 0A E8 12 00 5A EB
00D0  D5 4F 74 E4 33 C0 CD 13-EB B8 00 00 80 30 29 11
00E0  56 33 F6 56 56 52 50 06-53 51 BE 10 00 56 8B F4
00F0  50 52 B8 00 42 8A 56 24-CD 13 5A 58 8D 64 10 72
0100  0A 40 75 01 42 80 C7 02-E2 F7 F8 5E C3 EB 74 49
0110  6E 76 61 6C 69 64 20 70-61 72 74 69 74 69 6F 6E
0120  20 74 61 62 6C 65 00 45-72 72 6F 72 20 6C 6F 61
0130  64 69 6E 67 20 6F 70 65-72 61 74 69 6E 67 20 73
0140  79 73 74 65 6D 00 4D 69-73 73 69 6E 67 20 6F 70
0150  65 72 61 74 69 6E 67 20-73 79 73 74 65 6D 00 00
; I think you should be able to cut here, you then take
; the data from your hd and place it at the bottom.
0160  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00
0170  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00
0180  00 00 00 8B FC 1E 57 8B-F5 CB 00 00 00 00 00 00
0190  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00
01A0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00
01B0  00 00 00 00 00 00 00 00-25 1D 50 F0 00 00 80 01 ; the first partition record starts here at the 80
01C0  01 00 06 7F 7F 7A 3F 00-00 00 __ __ __ 00 00 00
01D0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00
01E0  __ __ 05 7F FF __ __ __-__ 00 00 __ __ 00 00 00
01F0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 55 AA

 

I'm afraid I've forgotten the exact cut off point but you should be able to figure that out reasonably by trial and error or by checking out the code of the sector. The bits that I have blanked are definately not important to you, I just don't really want any more information about my HD out there than needs to be.

Solving problem 3 - Deleted partitions
This should be possible, I still haven't gotten around to figuring it out though. The basic principle is similar to undeleting files, no program deletes anything anymore than it has to. Dos FDisk certainly just removes the entry from the referencing partition record. If you delete your overall extended partition then only your MBR will be altered - the actual partion record for the extended partion record will still be there completely unaltered. In order to 'undelete' the partition all you need to do is put the entry back in, this is dead easy if you know all the values for the partion record, if you don't then you are in the same situation as me. I still haven't gotten around to figuring out what to put there. The boot and os indicators are simple, it's just all the stuff for head/track/cylinder and the other stuff. While I know about the place holders I haven't figured out how to get all the information to put in the MBR for the real info. There are a couple of approaches to figuring this out that I have thought of;

Pretty much any of these should work but I haven't had time to look into it recently, if any-one knows the answer or can do the investigation I will be most interested to hear from you. If I figure it out I will write another essay on how to recover lost partitions, finding the 'lost' records is actually relatively simple due to the standard 55 aa signature and a little math, I just need the numbers to fill in the partion record with to complete it.

 

 


References
  1. Ralph Brown's interrupt list
  2. Wrox Master Class Assembly Language
  3. Pation Magic's Partion Info - distributable free!

 

 


Little utils
These are very noddy asm files that can be compiled with a86 with no alteration. They are hard coded to hard disk 0 at present.

 

 

;---- readMB.asm ----
jmp start

   noExtension db 'Int 13 extensions not found',10,13,'$'
   sector db 512 dup (0)
   extensions db 'Int 13 extensions found',10,13,'$'
   cannotRead db 'Error reading boot sector',10,13,'$'

   fileName db 'sector.dat',0

; disk address packet ;;;;;;

   diskAddressPacket db 10h
   db 0
   blocksToTransfer dw 0
   transferBuffer dd 0
   startblock db 8 dup (0)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;


start:
   
   ; int 13 extensions - installation check
   
   mov ah,41h
   mov bx,55aah
   mov dl,80h
   int 13h
   
   jc extensionsNotAvail
   ; bx should be aa55h if installed
   
   cmp bx,0aa55h
   jnz extensionsNotAvail
   
   
   ; just tell user that they are found and we are proceeding
   
   mov ah,9
   mov dx,offset extensions
   int 21h

   ; set up the address packet
   
   mov blocksToTransfer,1
   mov ax,cs
   mov [offset transferBuffer+2], ax
   mov dx,offset sector
   mov [offset transferBuffer], dx
      
   ; extended read
   
   mov ah,42h
   mov dl,80h
   mov si,offset diskAddressPacket
   int 13h
   
   jc errorReading
   
   ; create file sector.dat
   
   mov ah,3ch
   mov dx,offset fileName
   mov cx,0
   int 21h
   
   ; write the sector to it
   
   mov bx,ax
   mov dx,offset sector
   mov cx,512
   mov ah,40h
   int 21h
   
   ; close it
   
   mov ah,3eh
   int 21h
   
   ; exit
   
   mov ax,4c00h
   int 21h
   
   
extensionsNotAvail:
   mov ah,9
   mov dx,offset noExtension
   int 21h
   mov ax,4c01h
   int 21h
   
errorReading:
   mov ah,9
   mov dx,offset cannotRead
   int 21h
   mov ax,4c01h
   int 21h
   
; --- writeMB.asm ---

jmp start

   noExtension db 'Int 13 extensions not found',10,13,'$'
   sector db 512 dup (0)
   extensions db 'Int 13 extensions found',10,13,'$'
   cannotRead db 'Error reading boot sector',10,13,'$'

   fileName db 'new.mbs',0

; disk address packet ;;;;;;

   diskAddressPacket db 10h
   db 0
   blocksToTransfer dw 0
   transferBuffer dd 0
   startblock db 8 dup (0)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;


start:
   
   ; int 13 extensions - installation check
   
   mov ah,41h
   mov bx,55aah
   mov dl,81h
   int 13h
   
   jc extensionsNotAvail
   ; bx should be aa55h if installed
   
   cmp bx,0aa55h
   jnz extensionsNotAvail
   
   
   ; just tell user that they are found and we are proceeding
   
   mov ah,9
   mov dx,offset extensions
   int 21h

   ; open file new.mbs (read only)
   
   mov ax,3d00h
   mov dx,offset fileName
   mov cx,0
   int 21h
   
   ; write the sector to it
   
   mov bx,ax
   mov dx,offset sector
   mov cx,512
   mov ah,3fh
   int 21h
   
   ; close it
   
   mov ah,3eh
   int 21h


   ; set up the address packet
   
   mov blocksToTransfer,1
   mov ax,cs
   mov [offset transferBuffer+2], ax
   mov dx,offset sector
   mov [offset transferBuffer], dx
      
   ; extended read
   
   mov ah,43h
   mov al,0
   mov dl,81h
   mov si,offset diskAddressPacket
   int 13h
   
   jc errorReading
   
   
   ; exit
   
   mov ax,4c00h
   int 21h
   
   
extensionsNotAvail:
   mov ah,9
   mov dx,offset noExtension
   int 21h
   mov ax,4c01h
   int 21h
   
errorReading:
   mov ah,9
   mov dx,offset cannotRead
   int 21h
   mov ax,4c01h
   int 21h
   
; ---- the end.


 

Comments and suggestions can be emailed to me at fboyjoe@hotmail.com