Wednesday, April 25, 2007

Homeless in the 21st Century

It's now the interim period between the end of my NASA internship and the beginning of my summer research fellowship. I find myself - once again - homeless, while I wait for my housing to become available for the next semester.

As a college student, this happens to me three times a year; the transitions of the fall, spring, and summer semesters drive also the availability of housing for college students. Whether it be the dorm kicking everyone out for two weeks between semesters, or campus apartments unwilling to extend a summer lease past August 9th when I can't move into fall housing until August 23rd, the gaps between semesters are not a vacation but a hardship for those of us who don't have anywhere else to go during those times. My parents would be willing to take me in, but they have such a small house that there isn't a bed for me to sleep on there. So in the interim weeks between semesters I become a modern gypsy, taking my car from place to place and staying with friends until my welcome runs out.

This semester is not too bad. One of my professors has kindly allowed me the use of his spare room, and we get along well. I am experiencing no physical hardship - only the mental anguish of trying to define home and coming up empty-handed. I have been provided a house to stay in, and hospitality, but it is not my home. In my heart, home is with my fiancee Melissa, but neither of us has our own place. Last semester, Melissa's week consisted of bouncing from Weatherford, to Edmond, to Norman, depending on where she needed to be for college or work. When we are married we'll have a home together, but for now we make do as best we can.

I drove to Weatherford today, but my professor happened to be out, and I felt funny about going into his house alone. So I picked somewhere far away and drove there until he would get back. It's times like this that my car means more to me than just transportation. It represents freedom, and a much needed piece of the familiar in unfamiliar lands. As long as I am rushing 78 mph down an unending stretch of freeway at least I am somewhere, doing something, which is infinitely better than nothing, nowhere.

Friday, April 20, 2007

Gun Threat in the NASA Building I Work In!

Hot on the heels of the VT shooting, everyone is on edge. Now there has been a report of a gunman at the building I work in on the Johnson Space Center!

On Friday mornings I do a teleconference meeting from home. Today the conference ran late and made me late coming in to work. I was just about to head down to the Johnson Space Center to go in to building 44 to get the paperwork I need to check out, when I got a call from a coworker. He said there was a man with a gun and security is on lock down!

I don't really have much more information than that yet, and what more I have heard so far is unconfirmed so I will not start any rumors with it. But it's just crazy; I mean, I work there! Let me tell you that Building 44 is not the place I would have in a million years expected to see this happen. It's been the most stress-free work place I've seen, and I can't imagine what would push someone over the edge.

Update: They have helicopters showing the building on the news on CNN. Unreal.

Last Day of My NASA Internship

It's been a busy week since my last blog entry. Fear not, dear reader(s), I have not abandoned you. I'll have more time to write next week, including some entries about how my internship went. And will they ask me to come back? I'll find out next fall.

Friday, April 13, 2007

Reading: Zero

My sister mailed me the book Zero: The Biography of a Dangerous Idea. The book has already used four of my favorite words, and that's just the title! Zero is my favorite number; I like biographies, and I like dangerous ideas best of all. I can't wait to start reading it.

Thanks Rose!

Start Your Own OS Project in 30 Minutes

Have you ever dreamed of writing your own operating system? The first step is to get a kernel loaded. It's easier than you think. I'll show you how.

If you took an operating systems course in college, unless you went somewhere like Berkeley or Vrije in Amersterdam, it's likely that there was not a professor in your whole university who knew how to write an OS kernel from scratch and get it to boot by itself. Look, they're only human, ok? - most programmers wouldn't know how to do it. But it also means you came away from that class vaguely dissatisfied. Because if you take an operating systems class and never write your own simple kernel, it's like taking a driver's-ed course without ever getting to sit behind the wheel.

It's time we changed how we teach operating systems. Let's get started.

The first hurdle to overcome is getting the BIOS to boot your code. There are 512
bytes of code at the beginning of a disk, which the BIOS loads and executes. This is called the boot sector, and it is the responsibility of this incredibly tiny program to load other code and finally the actual kernel.

My first intention was to write one of these boot sector programs, because it would be a way to get code running on the machine completely by itself. There is just enough space in 512 bytes to write a very simple program. But that doesn't sound very useful, and besides, it's been done before.

So I wanted to contribute something new. Besides my idea of putting a toy operating system in the boot sector not being original, there is already a perfectly good boot loader program available. It's called GRUB. Why not put GRUB in your boot sector instead of custom code, and use GRUB to bootstrap your prototype OS? Suddenly what would have been weeks slogging through nasty bootstrap code isn't necessary. Things are looking up.

GRUB stands for GRand Unified Bootloader. If you dual-boot Linux and Windows, you may know GRUB can load your favorite operating systems, but did you know there's another reason it's called Unified? The people who developed GRUB looked at all these operating systems floating around; they all need many of the same things to happen as they boot, but each implements their own proprietary boot loader. They said, "What if there were a universal standard for booting an operating system? Then we could write one really good boot loader that would suffice for any operating system." They did.

What they came up with was the Multiboot Specification. It's a magic header that you include in a program to tell GRUB the information it needs to know to load your kernel. GRUB is smart enough to read a file system, so you don't even have to place your kernel in specific sectors or make some kind of wacky system file. Instead, all you have to do is compile a program as you would normally, and you can place the ordinary program file in any directory on the disk.

In an article I read recently, Julio Vidal describes how he made NetBSD Multiboot-Compliant. The article includes a detailed description of the boot process, and is an interesting read all around. Most importantly for us, though, the article links to some example code, from the GRUB documentation, which shows how to make a minimal kernel that is multiboot-compliant.

You can find that example code here: http://cvs.savannah.gnu.org/viewcvs/grub/grub/docs/#dirlist

Don't worry, you don't need all the files listed on that page - just three of them. You need boot.S, kernel.c, and multiboot.h. In order to illustrate the proof of concept (that, once loaded, I can run any code I want), I made a slight modification to the files which simply displays my own custom message after the kernel boots. You may want to work with the modified version in order to see where to put your own code, and because it is the version I used for these instructions, although the unmodified files should work too. You can get them from my downloads page: boot.S | kernel.c | multiboot.h

Now that you have the code, you need to compile it. For this, you will need to be running Linux. You'll also need Linux for the later steps involving GRUB, so you might as well get it now if you don't have it already. I recommend Ubuntu. Ubuntu comes on a Live CD, so you can run it from the CD without even having to install it. You can also install Ubutunu on an external hard drive or even a USB memory stick. (I will be posting another blog entry soon explaining how I did that.)

Compiling the code is the second major hurdle to cross. Most C programs link in libraries for things such as I/O and debugging. These C libraries in turn depend on an OS, or more specifically, they rely on making calls to the kernel of an OS. Well hold on a minute - we haven't got a kernel yet; that's what we're trying to make. Not only can we not rely on the the standard libraries, we have to make sure the compiler doesn't sneak external references in anyway (which it will try to do if you let it). So we have to use special compiler options to force the compiler to generate code that stands alone and has no external dependencies.

Open a terminal in Linux and type:
cd /whatever/directory/you/have/the/code/in

Then use this command (all on one line) to compile it:
gcc boot.S kernel.c -o mbs-kernel -ffreestanding -nostdlib -nostartfiles -fno-stack-protector

Explanation:

  • -o mbs-kernel: names the output file
  • -ffreestanding: means the resulting program should have no dependencies
  • -nostdlib: tells the linker not to bring in the C standard library, which won't work in the kernel
  • -nostartfiles: tells the linker not to bring in any C startup code
  • -fno-stack-protector: is a fix for the error "undefined reference to '__stack_chk_fail'"

This produces the file "mbs-kernel" which contains our new kernel.

You may need to be root to do the rest of the steps. To switch to superuser mode so that you can run all the commands, type:

sudo su

...and provide the root password when it asks.

Next we need to install grub to a floppy disk so that we can boot from it. It is possible to use a USB key instead, but I haven't figured out how to do that yet. So we'll use a floppy disk for this example.*

Open a terminal and type the following command:
grub --batch --device-map=/dev/null <<EOF

The above command starts GRUB in batch mode. Insert a formatted floppy disk and type these commands to install GRUB to it:

device (fd0) /dev/fd0
root (fd0)
setup (fd0)
quit
EOF

If you are using a USB external floppy (what I was using), then the device will be different. In that case, do not type the above, but use this set of commands instead:

device (fd0) /dev/sdb
root (fd0)
setup (fd0)
quit
EOF

USB floppy drive devices show up as /dev/sda, /dev/sdb, etc. Mine was sdb because I also have an internal SATA hard drive, and that occupies /dev/sda, so the floppy became /dev/sdb. If you have an ordinary IDE hard drive, then a USB floppy might be /dev/sda. How can you tell which one is your floppy disk? What I did was I used the Gnome file manager to mount the floppy disk (by double clicking its icon). Once I could see the contents of the floppy disk in the GUI file manager, I knew it had to be mounted. Then I opened up a terminal and typed:

mount -l

That's a lowercase "el". It caused mount to list all the mounted file systems - I looked at the one that matched where my floppy was mounted and the device given was the device I used for grub. However, if I recall, the drive has to actually be not mounted for the GRUB install to work. So after you mount the disk to find out its device file, be sure to right-click on it in the file manager and select "unmount" before you attempt to do the GRUB install.

Now that we have GRUB installed, we need to put our compiled kernel onto the disk. Use the file manager to mount the floppy drive and copy the file mbs-kernel to the /boot directory of the floppy disk.

*Note: If you already have GRUB on your hard drive, you don't necessarily have to have a boot floppy at all for this exercise. If you are comfortable with the idea of changing the boot configuration of your computer, you can safely skip the GRUB floppy install steps above, and place your homemade kernel directly in your /boot directory on your hard drive next to your Linux kernel. When you boot, you can choose whether to load Linux or your own kernel.

The last step is to modify the menu.lst file to make an entry for your kernel. If you have put your kernel on a floppy disk, you should be able to go to /boot/grub and double click on menu.lst in the file manager, which will open up gedit and let you edit the file. If you are going to run the kernel off your hard drive, you will find that gedit cannot save menu.lst if you opened it by double clicking. This is just a security precaution by Linux - the file manager didn't run gedit as root when you double clicked the file, so it can't write to it to save your changes. No matter - you can easily start gedit from the superuser prompt, and then it will have root priviledges. Just type:

gedit /boot/grub/menu.lst

Or, if you're back at the $ prompt instead of #, type:

sudo gedit /boot/grub/menu.lst

Menu.lst is simply a script that GRUB reads to know what boot menu options to show and how to execute them. At the very bottom of the file, if you are using a floppy, add the lines:

title Multiboot Kernel Example
root (fd0)
kernel /boot/mbs-kernel

If you want to boot your kernel directly from your hard drive, put the file mbs-kernel into your /boot directory on your hard drive, and add this to the bottom of your menu.lst file in /boot/grub/menu.lst:

title Multiboot Kernel Example
root (hd0)
kernel /boot/mbs-kernel

Once you have prepared the disk, reboot your computer. If you are booting from a floppy, make sure your BIOS is set to be able to boot from the floppy drive. Some computers have a key you can press to get a boot menu and choose manually. GRUB should start up when the computer boots. Choose the Multiboot Kernel Example, and GRUB will start your kernel. If you were successful, you should see either:
  1. A screen full of gobbledygook if you booted the default GNU example code
  2. A friendly message if you booted my version
If you get a message from GRUB that says "Error 28: Selected item cannot fit into memory," that error message is badly worded. It really means, "Default load address is too high." I got the error on a machine with 32 MB of RAM, but not on one with 256 MB. This problem could be fixed by instructing GCC to compile the program for a lower memory address. Anyone know how to do that?

In any case, as soon as you get the kernel to boot, you should immediately boot back into Linux, delete my code changes, and add your own code instead. This is your kernel.

If you want to go further, here are some resources:

http://www.cs.utah.edu/flux/oskit/
http://www.osdev.org/wiki/Main_Page

Remember, you are starting with a blank slate. You won't have a filesystem driver, I/O, anything, until you put them into your OS. You are starting at the bare metal. One way of looking at it is that you have nothing holding up your code.

Another way of looking at it, is that you have nothing holding you back.

Happy hacking.

Thursday, April 12, 2007

Now I Have a Home Page Too!

Come see it at: http://system.windows.codeslinger.googlepages.com/home

This blog meets most of my needs, but I'm finding more and more cases where it just isn't enough. For instance, I want to include source code file downloads with some of my articles, and there isn't an easy way to do that through Blogspot. Fear not; my new web site does not replace this blog. I will be using my home page and the blog together.

I had been thinking about making a home page for quite a while now, and went to look for a paid web host tonight. I was just thinking, man, I wish Google did homepages too. That's when I stumbled upon http://pages.google.com/. Wow! My main concern when looking for a web host had been finding a site I can trust, and in that category Google definitely fits the bill! Since I already have a Google account, I had a page already waiting for me.

You really have to see the AJAX web page editor Google has come up with. It blew me away - working with it is like working on a Macintosh. Who needs the Windows desktop when javascript applications running in your browser have now surpassed traditional desktop apps in quality of service?

Anyhow, take a look. I'll have to warn you, I don't really "get" web design. So I will be keeping the site clean and simple to cover up the fact that I don't know how to do fancy. In the movie Walk the Line, when June Carter asked him how they get such a steady sound, Johnny Cash's character just looks sheepish and says: "Well, we'd play faster if we could."

Wednesday, April 11, 2007

NASA Procedures: In Case of Emergency, Save the Icecream

Working at NASA has been a great experience for me. It is an engineer's paradise. It is also - I might remind you - a government operation. If you've been in the military or civil service, you'll understand what I mean; in a government job, normal rules of logic and common sense are still there, but they undergo a bit of a twist, like light passing too close to a black hole. I'm not saying it's good or bad. All I'm saying is that things can get rather amusing sometimes.

We have a very high-tech Coke machine in the building I work in. It has a glass front so that you can watch what it does. Instead of just dropping your coke down a chute like a normal Coke machine, this machine has a conveyor belt that moves up and down like an elevator. In order to retrieve your beverage, the machine first moves the conveyor up to the "floor" that your drink is on. The bottle (which is stored upright) is pushed onto the conveyor. Then the conveyor belt moves the bottle sideways until it gets to the end of the belt where it enters - would you believe - a chute. It's fascinating to watch when it works, but the machine is often out of order. You see, the chute is only wide enough to accept an upright bottle coming off the conveyor. The entire machine was built on the assumption that the upright bottles would never fall over. Once a bottle does fall over (which is inevitable) the machine cannot get it off the conveyor belt, and other people's purchases pile up behind it. The Coca-Cola service man has to be called every time a bottle falls over on the conveyor.

No longer a dispenser of beverages, today the Rube Goldberg Coke machine stood there, with it's conveyor jammed with bottles, as an ironic monument to overengineering. A warning, if you will, to anyone who might forget the K.I.S.S. principle.

I joked about this with one of the NASA oldtimers I work with, and he followed it up with an interesting anecdote. That's nothing, he said. A while ago we used to have an upright ice cream machine. Any time the power went out, the ice cream bars inside would melt, and gallons of vanilla ice cream would drain to the bottom of the machine and out the hole in the front. It made a terrible mess in the hallway. Eventually, something was done about it:

The building I work in is packed with radio and computer equipment, so you can well imagine that any loss of electrical power is a big deal, as equipment has to be shut down properly if possible. For this reason, we have a written procedure that is followed when loss of power is imminent, to ensure that every important piece of equipment is taken care of.

I have it on good authority that, for many years, step one of the emergency power loss procedure read:
  1. Call the Bluebell Icecream company.