With the c module loaded, we can parse the fat16 structure. What we are going to do in the loader
is we are going to find the kernel file and user program. Once we find them, we will load them in the memory
and then we transfer the control to the kernel.
So the file module in the loader includes two basic functions, search file and read file.
OK, let's get started.
As you can see, this is the general structure of fat16 format.
We have bpb bios parameter block, file allocation tables,
root directory and data sections.
The bios parameter block includes information such as bytes per sector, sectors per cluster,
total sectors, etc.
The file allocation table is used to locate the clusters. In the fat16 system,
the cluster is the basic allocation unit which is a set of consecutive sectors.
The sectors per cluster in the BPB will give us this info.
Now let's move to the file allocation table, this table contains the chains of links for a file,
that is, the value in the table indicates the next cluster number. Then you use that value as an index to
find the value in the table which will give you the next cluster number.
To find all the clusters of a file, you continue the process until you reach the end of the file.
The number of the file allocation tables we have in the image is usually 2.
We can get this info in the bios parameter block as well.
The next section is root directory which follows the file allocation tables. We can calculate the size of root directory
with the info in bios parameter block.
In the root directory section, we have root directory entries with each one being 32 bytes.
And these entries represent the files we have in the root directory of the fat16 partition.
If we have files and folders in the root directory, we will see them stored as directory entries here
.
The data section stores the data of the files and folders. If we have subfolders,
the files and folders within the subfolders will be stored as directory entries in the data section.
So the root directory section, as its name implies, stores the files and folders in the root directory.
What we are going to do next is we are going to inspect the fat16 image so that we can see
how to find a file manually.
First off, we mount os image. So we open osfmount
and choose os.img.
Then we uncheck read only drive, because we want to add files in this image and then we click mount.
As you can see right now, the os image is empty.
So here we add the loader folder and kernel.bin file.
Now, we dismount this partition.
So we click dismount.
OK, now we can open the image with hex editor.
If you use Linux or Mac OS, you can inspect the image with hexdump command.
Alright, this is what we got in the hex editor. The first 512 bytes are the mbr code we wrote in the previous videos.
The next few sectors are the loader file
we wrote in the last lecture.
Ok, let’s find the fat16 partition. In the partition entry, we retrieve the starting lba here,
which is 3f 00 00 00.
The data stored in the little-endian order.
So the starting lba is 3f.
We multiply it by 512 which produces the result 7e00.
This is the address of the fat partition.
So we go to
7e00
Now let’s interpret the data with the bios parameter block info. The oem name is free dos 4.1.
The bytes per sector is 200 in hexadecimal which is 512 in decimal.
The sectors per cluster is 4, so each cluster is 2kb. And we have 1 sector reserved.
The next field shows the number of fat tables we have, 2 fat tables in this case.
The root entries represent the number of entries we have in the root directory section,
which is 512 in this example.
The total sectors indicate the number of sectors in this partition. Here we have value 0.
So if it is 0, we will use extended sectors
located at the offset 20.
As you can see, the total sectors is 31f11.
Let's move on.
The media descriptor is f8 which means it’s a fixed media.
The sectors per fat table indicates the number of sectors for a file allocation table,
so we have c8 sectors for each fat table.
OK, we skip the sectors per track and head.
Then we get to hidden sectors which represent how many sectors we have before the partition.
Remember we got the value 3f in the lba field of partition entry.
The value is equal to what we have in this field.
We have talked about the extended sectors. The next field we care about is label. Since we format the partition with the label os,
here we can see os in this field.
The last one is system type. We got fat16 in this field.
OK, with all the information in the bpb, we can locate the fat allocation table
and root directory section. We start off with fat allocation table. To locate the table,
we use the value in the reserved sectors which represent the number of sectors we have
starting from the bpb to the file allocation table.
In this case, we have 1.
So the allocation table is at the next sector.
As you can see, this is the start of fat allocation table. In the fat16 system,
we use 16-bit value for the cluster number.
And note that the first two value are reserved.
Therefore, we start with the third entry in the fat table. We will see how to use this table in a minute.
Following the fat tables, we have root directory section.
To locate the section,
we need the start address of fat table and the size of fat tables. In the bios parameter block,
we know that we have 2 fat tables and each table occupies c8 sectors.
So we add the size of fat tables c8*2 to the start of the fat table
which is sector 1,
we get result 191 sectors.
Then we multiply it by 512, the size is 32200 in hexadecimal
.
This is the offset from the start of the partition. So we add 7e00 to the result.
The root directory section should be at this location. We go to
3a000.
As you can see, we have a couple of root directory entries here. Since each entry is 32 bytes,
we have three entries.
The first one is for the volume label,
we named it os when we format the partition. The next entry is kernel.bin file
and the last one is loader folder we added ourselves.
Ok let’s take a look at the entry structure. In the offset 0,
we have file name which is 8 bytes.
The extension name is stored in the next three bytes.
The label has no extension name. So we only got os. The next entry contains file name and extension name.
Let’s continue. The next byte stores the file attributes. Bit 3 means volume id. So we have 8 in the first entry
.
Bit 4 indicates folder, so we have hexadecimal value 10 in the loader entry.
and we know that loader is a folder. Bit 5 represents archive,
We have 20 in the second entry.
So kernel.bin is a file.
Then we get 10 bytes data reserved. Let’s move on. The next four bytes are for the date and time.
We won’t interpret the data and time in our system.
Let's continue. The starting cluster is the info we need to locate the file data in the data section.
It’s two bytes data. The last 4 bytes are used to store the file size.
Alright,
that's it for the directory entries.
Let’s see how to find the file data with the entry.
To do it, we use the starting cluster, 2 in this case.
and you can see this is the file size and the result is file size in bytes.
Note that the starting cluster number for the data section is 2.
Therefore, we will subtract 2 from the starting cluster of the entry to get the correct number.
In this example, it’s 0 which is the start of the data section.
The data section follows the root directory section.
We have calculated the address of root directory section which is 3a000 in this example
.
The size of root directory section is the number of entries * 32
.
We know that we have 512 entries in the bios parameter block,
so the size of the section is 512*32
equals 4000 in hexadecimal.
We add it to 3a000 and address is 3e000.
And this is the address we are looking for.
So we go to
3e000
You can see we have lots of data here.
We get one cluster of data for this file, which is 2kb of data, how do we find the following
data since the size of the file is more than 2kb?
To do it, we find the next cluster using fat table. Remember the starting cluster number is 2.
So we use 2 as an index to locate the item in the table. T
So let's go back to the fat table.
You can see at the index 2 of the table, we get index 3, then we use 3 as an index into this table
.
and we get the value 4.
Next we use 4 as an index to do the same process.
As you see, in this example, we get consecutive numbers. We continue doing it until we reach the end of the sectors
which is the value ffff.
now we collect all the clusters for the file data.
And all the data is stored in these clusters.
To get the data using the clusters, we use the formula, as we have talked about,
the start address of data section + the cluster number – 2 and then times the size of the cluster.
If you like, you can check the data in those clusters.
As for the subfolders, the data of the subfolders is the 32-byte directory entries
as we saw in the root directory section.
The difference is that they are stored in the data section. For example, in the root directory entry,
we have one folder loader. The file size is 0
if this is a directory.
And the starting cluster is c.
ok we use the formula to locate its data. the data section plus the cluster number c – 2
times the size of clusters.
The data section is at 3e000 and we add it to the result 5000 in hexadecimal.
So we go to
43000.
Now you can see we have 13 entries build.h debug.c etc, which are the files in the loader folder.
Also we have 2 more entries.
The . and ..
The . is pointing to itself. And .. is pointing to its parent directory.
Alright, that’s it for inspecting the image.
In the next video, we will start building the file module.
See you in the next lecture.