How to rename the volume label of partition

In this post, I write about my first writing experience on the hard disk using the INT 13H.
This one is the last post of a series which began with "Learning how to write on the hard disk with INT 13H" and finds here the conclusion where you can read about the development of the final procedure volume_rename.
Let me say that, after all the learning and the training done with the other posts until here, it is now time to go back to school and pass the exam, which consists in renaming the volume label of the hard disk.

The design phase

I prepared for you the file "volume_rename.npp" in the DOWNLOAD AREA so that you can read the program and build it for yourself, meanwhile in the post, I would like to describe the logic with the use of the flow charts.

Fig. A - Memory organization of volume_rename
Fig. A - Memory organization of volume_rename

In Fig. A you can see the memory organization of volume_rename which is similar to the one of the space shuttle (see Fig. A of the post "Design and build the space shuttle") except for the fact that I decided to dedicate considerably less RAM space for the read/write buffer. I decided to add this extra complication in order to enhance my learning experience. In the case of the space shuttle, I used a read/write buffer in RAM that was big enough to contain the ROOT directory all at once, but I wanted to learn how to handle a buffer in RAM that was smaller than the total block of data (the ROOT folder in this case) that I wanted to examine. The first problem that I considered was the determination of the best size for the RAM buffer when I had to read from and write to the hard disk. I realized that INT 13H reads and writes crunches of data of certain size (bytes per logic block, or bytes per sector: BPB_BytsPerSec) so my smallest RAM buffer had to be at least as big as the biggest BPB_BytsPerSec1. Then I considered another important crunch of data: the cluster. A cluster is a group of consecutive sectors (or logic blocks) that can be up to 32 KBytes big. Had I to reserve a RAM buffer as big as the largest cluster? I thought that it was not necessary. The cluster was (and is) an artificial grouping created by the file system and I didn't have to read a cluster all at once because I could have read portions of it. The same is not true for the size of the logic block (or sector: BPB_BytsPerSec) which depends on the real hardware and it has to be accessed all at once. My conclusion was that the minimum RAM buffer for reading and writing operations had to be at least as big as the largest logic block (or sector): 4096 Bytes.

Fig. B - Full overview of volume_rename
Fig. B - Full overview of volume_rename

In Fig. B, I present you the full overview of the program volume_rename. On the top left corner, you find the entry point immediately followed by the exit sequence of the procedure. These two components are one after the other in the address space. The program goes from the entry point to the central block with a right and downward arrow. I used such graphic symbolism to indicate that the jump goes toward higher address in memory from where it comes. Instead, I used left and upward arrows to symbolize the jumps that go backwards in memory from where they come.
The central block of the program reads the ROOT directory in RAM and scans it looking for the original volume label: the one that I want to rename. This part of the program is more complex than strictly required because I wanted to experiment and learn how to read a ROOT folder using a RAM buffer which was smaller than the ROOT.
The last block, in the bottom right corner, does the actual job.

Fig. C - Scan ROOT
Fig. C - Scan ROOT

In Fig. C, I present you the central block that scans the ROOT looking for the volume label entry. In the beginning, I calculated how many logic blocks were fitting inside the buffer in RAM (BUFF_SIZE_BLK = 4096 / BPB_BytsPerSec). Then I computed the Logic Block Address (LBA) of the beginning of ROOT on the disk (LBA_RW_START). I took the source values for the calculation from the BIOS Parameter Block (BPB) that I knew was still in RAM embedded in the space shuttle relocated at address 0x07A00. I didn't blindly take the values from the BPB in RAM, but I supposed that something could have been wrong, so I performed plausibility check on the read values before using them for the computation of BUFF_SIZE_BLK and LBA_RW_START. For that case, I prepared the first error detection and exit condition.
If everything was ok, the program continued and set the total number of entries in the ROOT directory (ROOT_Entries_Count), which I used to detect the end of the ROOT. Immediately after this block, the program entered the loop used for the search of the volume label. Looking carefully, you will recognize that I searched the volume label using two nested loops: the outer one took care of updating the portion of ROOT in RAM; the inner one took care of the actual search.

Fig. D - User interface and rename
Fig. D - User interface and rename

In Fig. D, you see the last part of the program. I decided to display the label of the volume found and ask the user if he/she wanted to proceed with the rename. I thought that in case I did something wrong in the program and the same had detected something different from the volume label (false detection), it was a good idea to let display on screen what volume_rename had actually found before renaming it. Suppose that it was a false detection, then probably some of the eleven bytes were not displayable on the screen as ASCII. For this reason, I programmed a replacement of any bytes outside the displayable range of the standard ASCII2 with the character "?" and, at the same time, I displayed the hexadecimal version of the string in addition to the ASCII one.
In my intention, this had to work as the last checkpoint before writing on the hard disk. When I decided which symbols to use for the user feedback, I imagined to use "Y" and "N", but I immediately realized that I had a german keyboard layout (where "Y" and "Z" are swapped compared to the US layout) and, probably, the BIOS had a US layout so the use of letters was not good. Thinking of a general approach, I considered that the numbers are the only keys that are probably always the same on any keyboard layout, so I decided to rely on numbers rather than on letters and I used "0" and "1" for my simple user feedback.

The manufacturing phase

According to my opinion, everything we humans create goes thru three steps: born of an idea (or design phase), realization of that idea (or manufacturing phase) and finally check that the realized implementation behaves as expected when it was just an idea in our mind (test phase). Creation of software is no different. I have shown you already the design phase in the previous paragraph but I am not going to show you the manufacturing phase in the post. Instead of that, I uploaded the file "volume_rename.npp" in the DOWNLOAD AREA in such a way that you can also practice with your manupfacturing phase, rather than just reading in the post about my manufacturing phase. However, I decided to have this paragraph here in the post just to make it clear that this phase does exist even if I didn't described it in all details.

The test phase

Fig. E - Original volume label before rename
Fig. E - Original volume label before rename

In Fig. E, you see that I started with the volume label equal to "TEST".

Fig. F - Detection of volume label and exit w/o rename
Fig. F - Detection of volume label and exit w/o rename

In Fig. F, you see that volume_rename detected the volume label correctly and I pressed "0" to exit without renaming. After that I rebooted and I wanted to rename but it didn't go as I originally expected.

Fig. G - Write error
Fig. G - Write error

In Fig. G, you see the write error that occurred when I called RW_LBA. I originally developed RW_LBA to be a torchlight helping me if any problem occurred and indeed it accomplished what I designed it for. Reading the message on the screen, I had an indication that the function call with AX = 0x4302 was probably not supported and, in fact, looking again in the "Ralf Brown Interrupt List" (Fig. H) I knew that the write with verifying was definitively not supported by the BIOS of my IBM T413.

Fig. H - Extract from the Ralf Brown Interrupt List
Fig. H - Extract from the Ralf Brown Interrupt List

Once I understood that I hadn't any write with verify, I changed the RW_LBA to make it use a simple write (AX = 0x4300).

Fig. I - RW_LBA returns an invalid function call
Fig. I - RW_LBA returns an invalid function call

In Fig. I, you see that I forgot to change the call that volume_rename made to RW_LBA, and I got back on screen the proper error message telling me where the problem was. Once more, I was happy with the way RW_LBA was helping me during the test of volume_rename.

Fig. J - Rename attempt
Fig. J - Rename attempt

After fixing all the details again (or at least I thought that I did it for all the details...) I run volume_rename and I got the feedback on the screen telling me that everything was ok (Fig. J). You can imagine, how much I was surprised to reboot in Windows XP and see again the same situation as in Fig. E. I scratched my head and I triple checked the program until I found the problem. I have already mentioned how painful it was to develop programs directly in DEBUG.EXE: every time I needed to do just a small adjustment in the code, this was immediately resulting in some shift (usually one up to tree bytes) in address space that forced me to control all addresses every time from the beginning to the end of the program. When I adjusted the code introducing the changes mentioned before, I controlled all addresses, but I missed one small address fix. The consequence was that the program wrote the string "GOOD RENAME" outside the RAM buffer so that once INT 13H wrote the RAM buffer back on the hard disk, it was exactly unchanged.

Fig. K - GOOD RENAME from within Windows XP
Fig. K - GOOD RENAME from within Windows XP

In the end, I made it to rename the volume label of my partition using the INT 13H for writing on the hard disk. I was really happy, once I saw it in windows XP (Fig. K) and I wanted to double-check it with volume_rename again (Fig. L).

Fig. L - GOOD RENAME from within volume_rename
Fig. L - GOOD RENAME from within volume_rename

I hope that you have found my experience, written in this post, somehow helpful for you, in which case I would be very happy for the help I may have given. Talking about me, I was happy because this was again a small step but in the right direction for my self-learning journey.



  1. Read BPB_BytsPerSec at page 9 of the "Microsoft Extensible Firmware Initiative FAT32 File System Specification". [click back]
  2. As far as I know, the standard displayable ASCII range includes the bytes that go from 0x20 to 0x7E. If you think that the bytes from 0x80 to 0xFF are also displayable then you are not considering that the range from 0x80 to 0xFF is not standard ASCII (so the displayed symbol depends on the selected character set). In conclusion, the subset of standard ASCII (from 0x00 to 0x7F) AND displayable ASCII has a range from 0x20 to 0x7E. [click back]
  3. In the post "Test INT 13H for the second time", I checked which version of the Extended Disk Drive was installed on my BIOS, and I supposed that it included the write with verify. But I was very surprised here to discover that the write with verify (AX = 0x4302) was not supported indeed. [click back]

<PREV.  -  ALL  -  NEXT>

Comments