In this homework, you are going to be writing a FAT filesystem driver that will run run on the bare metal (not inside Linux). Since it's running on the bare metal, you can't call any C library routines (printf, etc.) unless you write them yourself. If you need to print stuff out, you can use the terminal driver you wrote in Homework 2.
A filesystem is a set of data structures that live on the hard disk. We use these data structures to keep track of where information is stored on disk. By itself, the disk only allows us to write data in sectors, which are units of 512 bytes. The filesystem provides abstractions like files and directories so we can keep track of information in a more structured way. Filesystems allow us to do things like:
- Read and write arbitrary amounts of data to the hard disk (instead in 512 byte sectors)
- Name the data that we save (using a file name)
- Organize data by type (using directories)
Filesystems are normally implemented inside the kernel. This means that the filesystem driver runs in privileged CPU mode, so it can use privileged instructions if necessary.
The filesystem driver is expected to provide (at least) three APIs which can be called by user-level code:
open
: Finds the inode corresponding to a file on the disk.read
: Reads data from the file into memory.write
: Writes data from memory into the file.
The FS driver would also normally contain some initialization function that would be called by the operating system when the computer boots up before any files are opened. This init function sets up the data structures that will be used repetitively. For example, it would probably read the FAT table off of the disk into memory once and use that FAT table for every file access.
The filesystem driver does not directly access the disk. It calls some other APIs in the kernel to perform disk reads and writes. There are many different interfaces that connect the CPU to a disk: ATA, SATA, SCSI, SD/MMC, USB, etc. Each one has its own driver that lives in the kernel and provides an API to the filesystem driver that allows the filesystem to read and write sectors.
In this homework assignment, I have provided you with a disk driver (ide.s
)
that can read and write from the drive. Your job is to write a filesystem driver
that reads the data structures on the drive to open and read files. You will not
be implementing the write
syscall in this homework.
The code you will be writing in this homework RUNS IN KERNEL MODE. It has to run in qemu. Don't try to run your code in Linux. It won't work.
This directory contains a shell project for you to start from. All of your
source code should live in the src
directory. You'll need to create some
extra files:
fatfs.c
/fatfs.h
: These should contain the source code for your FAT FS driver.term.c
: (optional) Source code from the terminal driver you wrote in Homework 2. You can use this to print out messages in the code you'll be writing.main.c
should contain yourmain()
function, which should callfat_init()
,fat_open()
andfat_read()
, implemented infatfs.c
. A basic demonstration would be to just read the contents of a text file and print them to the screen.
Every file you add to the src
directory needs to be added to the OBJS
list
in the Makefile
.
Compile your code by typing make
at the command line. This will generate a
disk image (called disk.img
) that is bootable by qemu. The disk image that is
generated by the Makefile
will have Grub installed as the bootloader (just
like your Linux VM) with one partition formatted as a FAT 12 filesystem. That
partition will contain your kernel binary, which will be loaded by Grub when
qemu starts. If you want to see the files in your disk image, type make mountroot
at the command line. This will mount your rootfs in the /mnt/disk/
directory, allowing you to view the files on your filesystem and add new files.
When you're done looking around, type make umountroot
before trying to compile
again.
The code that you write for this assignment will be running as the operating
system kernel. When qemu
starts up, it will load Grub from your disk image,
and Grub will load your kernel into memory and start running it. Your kernel
will be running in the CPU's supervisor mode, which gives it unrestricted access
to the CPU.
For technical details of how the FAT filesystem is implemented, please see Wikipedia's article Design of the FAT file system.