UCLA CS111 Operating System, by Professor Paul Eggert

Lecture 2. Abstraction and bootstraping

By Yicheng Yang & Zai Chen

Oct.2th

Reality

Now Suppose we have a paranoid professor, who suspects that his operating system may have a security breach, that someone else may have left a backdoor in the system, to steal his paper proposals! 

Now a normal person would just use another computer, but the paranoid professor believes whoever placed this backdoor in the first place must have placed some part his "dark" code into the source code of Linux operating system, so that all the computer running Linux may be exploited!

Still, our professor needs to submit a proposal tomorrow and he now needs a program that count the number of words in the proposal. What can our lovely professor do?

- Disconnect from Internet. (He is safe for now, but what if the malware simply reports back next time when the computer is online?)

- Disable relevant drivers. (He really doen't want to do that......)

- He can tell the OS to ignore some of the unreasonable requests. 

- He can use some cryptographic approach! He can encrypt the file, when it's being examined, the file is decrypted one character by one character, count the number, and 

- The FINAL approach! We are not going to use an operating system.

 

The Standalone Program

We are going to write a standalone program, that does not need an operating system to function.

We can accomplish that by writing a program that does the the word count for us, compile the program and save the machine code into our drive. When we press the Power button, a certain sector* (named MBR, we will discuss it below) on the drive will direct us to the booting location, in this case, our machine code stored on the disk, thus executing the word count.

*A hard drive is usually divided into a large number of sectors, each of which has a size of 512-byte. In fact, for convenience, memory is also divided into sectors of same size.

How to turn on a computer?

Traditionally speaking (when we are not writing this kind of crazy standalone program), we are booting from the operating system. In that case, when we press the Power button, the first sector on a hard drive (typically labeled sector 0) will be copied from disk to DRAM(Dynamic Random-Access Memory, or "Memory"). Let's assume the location in memory that we store content from sector 0 is 0x7000.

 

Diagram of the disk:
------------------------------------------------------------------------------------------------
|    MBR    | ... ... ... | loader | word count | file ... ... ... ... | EOF | ... ... ... ... ... |
-------------------------------------------------------------------------------------------------

 

The sector 0 on a hard disk is called an MBR, short for "Master Boot Record". It has 512 bytes, with the last two bytes ending with 0x55AA, a specific signature field that memory will recognize as "bootable"(We will be more on that later). It's also called a "bootloader", it's OS agnostic, meaning that any OS can recognize it. The first 446 bytes are machine code instructions to locate the booting location. The next 64 bytes are sectored into 4 smaller, 16-bytes units, they store several information about partition:

1. the status of partition(whether or not they are bootable, )

2. partition type

3. starting sector of the partition

4. size of the partition (i.e. number of sections)

 

MBR (Master Boot Record):
inside sector 0:
-----------------------------------------------------------------------
| ... Code for bootloader ... | 16 | 16 | 16 | 16 | 0x55AA |
-----------------------------------------------------------------------
                                                         ^                ^
                                                       type        boot signature
                                                      status
                                                 start sector
                                                       size

 

There is also a certain part of DRAM that will never be emptied, they are called ROM (or "firmware"). When powered on, the instruction pointer will be set at the starting location of ROM. It stores the Basic Input/Output System (BIOS) which does the following when computer starts: 1. test computer's hardware; 2. check for status of devices; 3. look for bootable device.

 

Diagram of the DRAM:
-------------------------------------------------------------
| ... ... | word count | ... ... | ... ... ... ROM ... ... ...|
-------------------------------------------------------------

When the instruction from ROM is searching over the memory for the signature field, recall that we copied sector 0 of the hard drive to 0x7000. So the BIOS knows there's a bootable device, and boot from the location specified by the bootloader (in the first 446 bytes). 

So, in this case, we can store our program loader in the first 446 bytes of MBR, the loader will then tell us where to look for our program in the drive. We are then directed to that location and execute the machine code we placed there in the first place. Boom! We are done!

We managed to build a computer that displays the number of words in the file when we power it on!

No OS! We are completely secure!

Below are some of the sample code we had in class, about the bootloader and our word counter program.

 
Sample Code
 
Bootloader:
 
for (i = 0xc000; i <= 0xc058; i++)
    read_ide_sector(i, 0x100000 + (i - 0xc000) * 512);
goto *0x100000; // this line sets the EIP to 0x100000
// this is not a standard C command, but can be achieved in some extension of C.
 
void wait_for_ready()
{
    while((inb(0x1f7) & 0xc0) != 0x40) // wait for the disk controller to be ready.
    continue;
}
 
void read_ide_sector(int s, int a)
{
    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); // instruction to read sectors
 
    wait_for_ready();
 
    insl(0x1f0, a, 512/4);
}
 
========================================================================================================================================================
 
Word Count:
 
#include<stdbool.h>
#include<ctype.h>
 
void main(void)
{
    int nwords = 0;
    bool inword = 0;
    int s = 0x10000;
    for(;;)
    {
        char buf[512];
        read_ide_sector(s++, (int)buf);
        for(int j=0; j<512; j++)
        {
        if(buf[j] == '\377')
        {
            writeout(nwords);
            return;
        }
        bool alpha = isalpha((unsign char) buf[j]);
        nwords += alpha & ~inword;
        inword = alpha;
        }
    }
}
 
void write out (int n)
{
        uint16_t p = (uint16_t) 0xb8014;
        while (n)
        {
        *p-- = '0' + n % 10;
        n /= 10;
        }
}