2014-01-09

2014-01-09 USB ... En Garde!

In order to get my OS onto some real hardware for further tests, I've decided to revisit an old enemy, USB.  Before now I have used PXE network booting to get various monolithic test kernels onto hardware for some real world testing, and at least one of my previous test kernels had a UDP based filesystem that it could use to load files from a network server.  Whilst I could use the same approach for the Octopus kernel, I would like to crack the USB nut to be able to use USB Mass Storage devices.  I quite like the idea of having a flash drive that I can plug into almost any machine and boot my OS.

I have looked at USB before, but I have always found a very large amount of USB documentation and specification (much of it only relevant if you're creating USB hardware), and very small amount of good USB example code.  While I appreciate the point that developers shouldn't implement something they don't understand and that asking for example code is a big no-no, a small amount of actual implementation answers a significant number of questions that new developers may have, provides a codebase full of keywords that can be researched in the (significant) documentation, and also gives a working baseline implementation that can be tweaked and experimented with to explore the interface and help debug their own implementation.

All that aside, I had no specific goal to achieve by investigating USB before and many reasons to investigate other things, so the specification documents were filed away under "tl;dr".



Anyway, before we can actually get down to some proper USB implementation, I'll need a system on which to test.  For this purpose, I have set up one of my machines, an Acer Aspire Revo R3700, and dug out a random 4GB USB2.0 flash drive.

Up until now I've been using the Bochs emulator to test the Octopus kernel so far.  My Bochs configuration has two hard drives, the first is a small image file onto which I installed Grub (Grub Legacy), the second is a VVFAT-type hard drive where Bochs takes the contents of a folder on the host OS and emulates a FAT partition which contains those files.  The configuration file for Grub then loads the kernel from the second hard drive.  Grub Legacy has to be installed onto an image-type hard drive because it has to know exactly which blocks contain the rest of its code.

I copied the Grub hard drive image onto the key and this worked beautifully on the Revo, and I set up a second partition on the key by editing the partition table entries (1337 H4XX!).  Unfortunately, it appears as if Windows doesn't fully support partitions on a USB flash drive (no idea why).  It reads the partition table correctly, and handles the first partition correctly, but none of the others show up.

A LOT more tinkering later and I have a 1GB partition on the USB drive with GRUB installed, a copy of my kernel, Windows recognises it, and the Revo boots from it.  (I know it's 4Gb key, but I REALLY don't need that much space yet.)  It's worth noting that the reason it boots is because the BIOS has the capability to load from a USB mass storage device, but as soon as I enter protected mode (which Grub does for me) and the BIOS interrupts are no longer available, I'm on my own.

With this set up in place, I can compile a new version of the kernel in NetBeans, copy the output file onto the USB drive, put it into the Revo, and boot the new changes.  It's a bit more cumbersome than the PXE booting I've used before, but should work on most modern machines without needing a network cable and a second machine to run the TFTP server.

Now to actually start writing the USB driver ...

No comments:

Post a Comment