Lecture 2 Scribe Notes
Abstractions and Bootstrapping
What would happen if we had no Operating System?
Example Problem: English professor needs to count the words in a file.
Constraints:
Paranoia – Use only our own code*
We want it to consume few resources
Simplest User Interface (UI) – power on to run
*Except for firmware. We trust Dell has supplied quality code.
Machine Specs:
Dell Desktop x86
1 GB RAM
200 GB SATA Disk Drive
File Format:
ASCII text file
Each line terminated by a newline byte
A word is composed from a sequence of letters, a-z and/or A-Z
Data is contiguous on disk
Possible Future Extensions:
Word Processor
Editor
Printing
Output Format:
Power on to use. Immediately display word count.
Problem: RAM is initialized to 0's after power on. How does our program get loaded onto RAM to get run?
What we want:
Solution: Use Programmable Read Only Memory (PROM) because after a program is loaded to PROM once, it will remain there after power off.
So what could we do with PROM?
Load our program to PROM
Would work, but if we ever want to change the code, we'd have to take apart the hardware of PROM to reprogram it
Use Dell's firmware on PROM, which is a program that will eventually load our program
Bootstrapping/BIOS
“Pull oneself over a fence by one's bootstraps.” - Teddy Roosevelt
Program in PROM needs to get our program off the disk and into main memory. This program is the Basic I/O System (BIOS).
BIOS:
Tests system (hardware checks).
Looks for devices.
Find one that is bootable. Usually, this is the Master Boot Record (MBR), identified by the 2 bytes, 0xaa55.
The MBR is some code located on a sector of the disk, followed by a partition table
Each entry of Partition Table (4 for historical reasons)
Status of partition (e.g. bootable?)
Start (index of starting sector)
Size (# of sectors)
Type (e.g. swap portion, Windows boot, etc.)
The MBR is operating system agnostic, meaning it works no matter what operating system you are booting.
Due to sector size constraints (512 bytes), the MBR only contains a small program (too small to do anything useful), so its job is to find another bootable partition
After selecting a bootable partition from the partition table, it reads the first sector of that partition, which is the Volume Boot Record (VBR)
Set the IP to the start of VBR
The VBR is operating system-specific
Read MBR to address 0x7c00 of main memory.
Set instruction pointer (IP) to 0x7c00.
Programmed I/O
Special I/O x86 instructions
Read function
Wait for disk controller to become ready by checking register 0x1f7
Store # of sectors into register 0x1f2
Store sector offset into registers 0x1f3-6
Store READ into 0x1f7
Wait for ready from disk controller
Get results into CPU
Store into RAM
void read_sector (int s, char* a) {
// s: sector #
// a: RAM address
while((inb(0x1f7) & 0xc0) != 0x40) { // 0xc0: 11000000 0x40: 01000000
continue;
}
wait_for_ready();
outb(0x1f2, 1);
outb(0x1f3, s & 0xff);
outb(0x1f4, (s>>8) & 0xff);
outb(0x1f5, (s>>16) & 0xff);
outb(0x1f6, (s>>24) & 0xff);
outb(0x1f7, 0x20);
wait_for_ready();
insl(0x1f0, a, 128); // insl reads 128 32-bit words from register 0x1f0 to a
}
And finally, our Word Count Program:
int main (void) {
// Word Count Program
int words = 0;
bool inword = false;
int s = 0x100000;
for ( ; ; s++) {
char buf [512];
read_sector(s, buf);
for (int j = 0; j < 512; j++) {
if (buf [j] == '\0') {
words += inword;
writeout (words);
return;
}
bool thisalpha = isalpha ( (unsigned char) buf [j]);
words += inword & ~thisalpha; // This yields 1 when we cross a word boundary
}
}
}
void writeout (int n) {
// Print to screen
char* screen = 0xb8000 + (25*80*2/2);
do {
*--screen = (n % 10) + '\0';
*--screen = 7; // grey on black
} while ( (n /= 10) != 0);
}