CS 111 Fall 2009
prepared by: Stefano Emiliozzi, Jason Wang, ChiaCheng Liu
OS Goals: What doe we want an OS to do? What is the big picture?
However, problems can arise according to various issues
e.g. performance vs. simplicity:
Bubble sort => Quick sort (trade in simplicity for performance)
Sample scenario:
A paranoid Professor "A" will want to submit a paper and like to make sure if the word count will be accepted. Also, professor want to ensure the security of the paper.
Here is the specification(provided by customer):
As software engineers, we should ask for more specific details about the program:
Q1: How to handle error?
A1: Output a “?” .
Q2: What is the definition of words?
A2:
Word can contain [A-Za-z]+.
Q3: What is the machine we use?
A3:
32-bit x86 architecture, VGA output, 1 gigabyte of RAM
Q4: What is the future plan or change you might want to have?
A4: The program should be expandable in the future. e.g. it might be implemented as a full word processor eventually.
Hard disk considerations:
Hard disk - Disk controller - Bus - CPU
Disc Controller commands
In x86 machine, the little endian is used.
Why?
Little endian |
|
|||
[ | 21 | 67] | <-16 bits machine | |
[00 | 00 | 21 | 67] | <- 32 bits machine |
1003 | 1002 | 1001 | 1000 | <- address |
Big endian | ||||
[21 | 67 | ] | <-16 bits machine | |
[00 | 00 | 21 | 67] | <- 32 bits machine |
1003 | 1002 | 1001 | 1000 | <- address |
Under the little endian, the data will not be messed up if the machine is switched from 16 bits to 32 bits.
x86 Boot Procedure:
A small portion of the RAM (Random Access Memory) is marked as read-only and it maintains its status in case of power outage. Such portion is called ROM, acronym for Read Only Memory.
In such area is stored the BIOS, (Basic Input Output System) which can be considered the first program to be loaded and executed. Its basic tasks are:
Due to its special nature, it is often referred as firmware.
Upon its execution, it looks for hard drives and when it finds the main one, copies 512 bytes of data from the Boot Sector 0 (known as Master Boot Record) into the RAM, thus writes in the Program Counter register (PC) the starting memory address of the data just copied. We remind here that the x86 architecture we are using for this example relies on the Little Endian notation which means that the LSB (Lowest Significant Byte) is at the lowest memory address. For the sake of clarity, if we suppose a memory with increasing addresses form right to left and the store of the following value, 0x01020304,
we would have (supposing a byte addressing):
Master Boot Record (MBR)
The Master Boot Record is an "OS independent" sector, which resides at position 0 of hard disks. Its less significant two bytes are the signature, which tells us if the sector it’s actually a MBR, by checking if they are equal to 0x55,0xAA. In the MBR, there are 64bytes which contain the partition table. For each partition in the hard disk, there is one entry in the partition table – the information stored are:
The rest of the MBR (446 bytes) contains OS dependant code (x86 in our case) which scans the partition table, looking for a bootable partition. To some extents it mimics the BIOS behavior on a different level.
Once the partition has been found, the program looks for the Volume Boot Record (VBR), which is an OS dependant sector that contains information about the operating system it is meant to load. At this point the program in the MBR loads the 512 bytes of the VBR into memory and updates the program counter to the start address of the data. The code contained in the VBR, takes care of loading the OS kernel into the memory, allowing the system to finally boot. This kind of procedure is often regarded as Chained Loading.
OS Code:
At this point we are ready to implement some basic functions of our limited OS:
void wait_until_ready(void) { while (inb(0x1F7) & 0xC0) != 0x40) //the most significant bits must be 01 continue; } |
Implementation of the busy waiting function, for dealing with the disk controller
int read_ide_sector(int s, char *a) { wait_until_ready(); //waits for the disk to be ready outb(0x1F2, 1); //prepares to read 1 sector outb(0x1F3, s & 0xFF); //initializes the sector offset outb(0x1F4, (s >> 8) & 0xFF); outb(0x1F5, (s >> 16) & 0xFF); outb(0x1F6, (s >> 24) & 0xFF); outb(0x1F7, 0x20); //sends the read command wait_for_ready(); //waits for data to be ready insl(0x1F0, a, 128); //copies 512 bytes (128 words of 32bit each)to //the location pointed by a return 0; //no error checking } |
Function that actually reads one sector for the disk
// this is our VBR program, assuming that we have to read 19 sectors // Note that sector 0 is the VBR for(i = 1; i < 20; i++) read_ide_sector(i, (0x100000 + (i-1)*512); goto 0x100000; //this is not real C instruction, but the semantic is to //update the Program Counter to the Address 0x100000 |
Our VBR Program
int main(void) { unsigned int nword = 0; bool in_word = false; for (int s=50000;;s++) { char buf[512]; //reading buffer read_ide_sector(s, buf); // read one sector for (int j = 0; j < sizeof buff; j++) { if (!buf[j]){ //any more data? write_out(nwords);//prints the result return 0; } bool this_alpha = isalpha((unsigned char) buf[j]); // cast is needed //because buf[j] is the the range[-128..127] while isalpha accepts //values in the range[0..255] nwords += ~inword & this_alpha; in_word = this_alpha;//updates the marker variable } } }
|
Our Main Program
void write_out(int n) { uint16_t *p=(uint16_t *)0xB8014; //pointer to the video memory do { *p--=’0’+n%10+(7<<8); //writes in gray, an ascii character from right to left } while(n) // n = 0 is the termination condition }
|
Function that prints on the screen
Let’s make some final considerations. First of all the function read_ide_sector is a primitive one and it should be used that several components (BIOS, MBR program, VBR program, BootLoader, Applications). A good strategy for avoiding multiple copies of the same function could be to use only the copy that resides in the BIOS. For the sake of performance, what happens in most cases is that everyone that needs direct access to disk re-write that function.
Secondly, if we analyze our small operating system with respect to the OS Goals we defined at the beginning of the lesson, we sadly conclude that the only achievement we made was probably the security.