-
Notifications
You must be signed in to change notification settings - Fork 2
18. IDE Hard Disk Driver
Starting from this chapter, we will start designing and implementing the next big part of an OS kernel: the storage stack. A significant amount of input/output work of an OS is from/to external storage devices, such as tapes, floppy disks, hard disk drives, and solid-state drives. Being able to store data on persistent media inside these devices and fetch them back across poweroffs brings persistence into the system.
The support for persistence is crucial in any computer system. The OS code itself must be stored on a storage device and be loaded into main memory at booting. User program binaries are stored, waiting to be loaded and executed. Useful user programs (and the system itself) will likely need to save data or state across poweroffs and failures. Without persistence, the system could only do transient things on volatile data.
We now start building layers of a typical storage stack in this and the next few chapters to enable persistence in Hux.
Scan through them before going forth:
- I/O Devices chapter of the OSTEP book: concepts of I/O, what is a storage stack ✭
- Hard Disk Drives (HDD) chapter of the OSTEP book: internals of a hard disk device ✭
- ATA PIO Mode details: basic IDE driver without DMA
- IDE disk driver implementation of xv6
The collection of components that bridge read/write operations with storage device requests is often called the storage stack. People call it a software stack because it tends to be clearly layered, similar to the network stack (though this is not necessarily true in modern OSes).
A storage stack typically consists of the following layers, from top to bottom:
FIGURE TODO
- I/O-related system calls, e.g.,
read()
,write()
, etc. - Virtual file system (VFS) layer that provides a unified interface for file systems, e.g.,
vfs_open()
,vfs_read()
, etc. - Actual file systems implementations, e.g., Ext2/3/4, XFS, BtrFS, FAT, NTFS, etc.
- (possible) A general block device interface layer
- Block device drivers for various kinds of storage devices, on various types of connections, and with various types of hardware protocols
- Physical storage devices, perhaps with in-device controllers
In Hux, we will pick/implement a beginner-level solution at each layer bottom-up. Let's begin by writing a basic device driver for classic (parallel) ATA hard disks (also referred to as IDE disks).
For our small Hux kernel, the entire OS kernel is compiled into a single binary and packed with a mature bootloader, GRUB, into a CD-ROM image. GRUB itself implements basic I/O support for loading an OS kernel image, which means that we don't need to worry about a "chicken-or-egg" problem at booting. Our storage stack will assume that the OS has been fully loaded.
For a modular kernel or microkernel, it faces the problem that it needs to load modules from a disk, but the code for allowing disk access (disk drivers, file system, etc.) are within those modules. The solution is to include a small initialization ramdisk (initrd) in the kernel image to be used at early boot time, which provides a basic disk driver for loading modules. After storage modules have been loaded, the kernel switches to use the complete storage stack.
TODO
TODO
This should produce a terminal window as the following after booting up:
Current repo structure:
hux-kernel
├── Makefile
TODO
Guanzhou Jose Hu @ 2021