Skip to content

18. IDE Hard Disk Driver

Jose edited this page Aug 10, 2021 · 14 revisions

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.

Main References of This Chapter

Scan through them before going forth:

The Storage Stack

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.

ATA Port I/O (PIO) Mode

TODO

Progress So Far

TODO

This should produce a terminal window as the following after booting up:

Current repo structure:

hux-kernel
├── Makefile
TODO