Sunday, December 14, 2008

Saturday, December 13, 2008

Generally, the wisdom is...

Generally, the wisdom when you say, "I need a foo" for some common value of foo is to not write your own, but instead use a preexisting one.

But we would like to offer some new wisdom. The first step, we believe, when you want an IP stack is to burn lwIP to the fucking ground.

Friday, December 12, 2008


Jacob and I had a mini-sprint this afternoon, and figured out some things about keyboards, magic numbers, i8042s, UNGET commands (which make life easier), keyboard performance, linking VNC into the keyboard routines, and grub crashes. Major progress has been made in almost all of those areas, except for the magic numbers area, in which more magic is there.

Tomorrow: differential updates for better user performance while running X, and text console framebuffer emulation. ... and P3 style files.

Tonight: sleep.

Code, as always, is in git.

Sunday, December 7, 2008

Big changes

Big news recently. A week or so ago, Jacob got the VNC/RFB server talking to a client. Performance wasn't great, but we had output. Now, we've done two things that make a huge difference in terms of performance:

  • The network driver no longer waits for packets to finish getting sent or received, and queues up packets as needed, like modern network drivers do. We actually use the full capabilities of the card's bus-master DMA interface, and boy howdy does it pay off; we actually get ping performance in the 'as expected' region, where all pings are handled essentially under 64msec.

  • The big win, though, came from something very silly -- turning on the cache! You're supposed to keep SMRAM cacheless when you're outside of SMM, so that the user cannot get in your way and fill your cache with bogons (and hence have you crash in SMM). But if you want performance, you need to turn it on when you get in SMM. Finally, we can actually get the blazing fast speed that our 1GHz P3 promises. This brought us from about 3 minutes per frame to 15 seconds per frame; and the network driver performance improvements are incrementally helping that.

This is very exciting. VNCviewer now claims that we get good enough throughput to request hextile encoding (instead of ZRLE encoding) -- it thinks we're getting 4.5MByte/sec from the machine. Of course, we haven't implemented hextile (or ZRLE), but... It may be time to declare this performance fun to have come to an end, at least until we get mouse and keyboard support implemented.

Tuesday, November 25, 2008

Framebuffer access

OK, we now have unaccelerated access to the framebuffer. Maybe DMA soon if I have time. j4cbo is making good progress on RFB. In the interim, here's a picture for you, showing the venerable test phrase given to bootstrap all graphic demos that I've produced to date:

As usual, code is in Git.

Saturday, November 22, 2008

* *
* The video arbitration routines calculate some "magic" numbers. Fixes *
* the snow seen when accessing the framebuffer without it. *
* It just works (I hope). *
* *

-- linux/drivers/video/nvidia/nv_hw.c

Monday, November 3, 2008


We've started work on getting lwIP integrated in, but discovered that our old putting-everything-in-ASEG scheme doesn't really work with the amount of code and data we have now. So of course, we're going to use paging in SMM to spread the code across both ASEG and TSEG. As of tonight, the basic procedure of enabling paging works, but trying to read or write video RAM causes the system to hang. We're getting closer, though...

Monday, October 6, 2008

Sunday, October 5, 2008

3c905: transmitting!

It turns out that we'd overlooked something about the northbridge's SMM handling: the memory controller blocks PCI DMA access to the SMM segments just like it prevents the CPU from reaching them. This explains why sending packets was failing before; at some point shortly after sending the first packet, the network card would attempt to access the no-longer-open frame descriptor, and be told "no!"

Now that we've set Tseg to be open all the time, packet sending works reliably under both Linux and Pebbles, and the PCI bothering code still does what it's supposed to. The next step is to start sending out screen dumps...

This brought up an interesting race condition. Suppose we have some device that we set up to repeatedly attempt to DMA our code into SMM. Most of the time, this will fail. However, at some point, an SMI will occur (and if not, we can enable some more traps); if the DMA happens to occur while the northbridge is in SMM, then shazam...

This driver would receive 0 style points if I were grading it

Magic constants abound ... even when they're #defined previously. Comments like:
        /** failed after RETRY attempts **/
outputf("Failed to send after %d retries", retries);
Not just bad indentation (i.e., not what I want), but inconsistent indentation. Committing code, too, that you know to be wrong:
            /** I don't know what MII MAC only mode is!!! **/

The Linux driver, mind you, isn't much better:
/*  Update statistics.
Unlike with the EL3 we need not worry about interrupts changing
the window setting from underneath us, but we must still guard
against a race condition with a StatsUpdate interrupt updating the
table. This is done by checking that the ASM (!) code generated uses
atomic updates with '+='.

By the end of this, this driver will be mostly completely rewritten. And that's fine with me.

3c905 status

After a few embarassing bugs, I have the network card initializing for me, and giving me its MAC address:
returned 0x2a
NetWatch running
Probing PCI device: 3c905c-tpo
3c90x: Picked I/O address ec00
EEPROM adr 00, data 00b0 d097 bcac 9200
EEPROM adr 04, data 00ca 0000 0000 6d50
EEPROM adr 08, data 2940 0000 00b0 d097
EEPROM adr 0c, data bcac 0020 0000 00aa
MAC Address = 00:b0:d0:97:bc:ac
Connectors present:
10Base-T / 100Base-TX
found 3c90x, hopefully!

I also have it transmitting packets; it manages to squeeze two packets down the wire before it hangs up and never talks to me again (and worse, sits in an infinite loop in system management mode). These sorts of hangs were pretty damn hard to diagnose last time I did this sort of stuff; hopefully I'll not be in too big trouble here.

It occurs to me that I might want better logging for my outputs; a serial logger might be nice. Maybe we should get a USB serial dongle to go with the 412mac, which is currently acting as a nice companion box that runs tcpdump, etc.

Thursday, October 2, 2008

Good news!

I just got new pictures of the Dacia Sandero!

The even better news is that we found a 3c905 driver that we can pretty much just fully grab, since it has a couple of interesting features -- in particular, it's BSD-compatible (yes!), it's polling-driven (yes!), it's not Linux (yes!), and it doesn't use malloc() (yes!).

So, uh, Thanks Etherboot. Thetherboot. Here is the driver that we plan to grab, anyway; we'll see what happens tonight.

Friday, September 26, 2008

Presentation uploaded

The presentation given in lecture is now accessible from the web:

NetWatch lecture slides

Many changes

Many changes were made tonight, with quite a few exciting new bits of functionality. But, before I go into detail on any of those, let me start off with this:

[    3.193058] e100: eth0: e100_probe: addr 0xfbfff000, irq 10, MAC addr 00:02:b3:36:7d:72
[ 3.193229] 3c59x 0000:02:0c.0: enabling device (0000 -> 0003)
[ 3.193300] PCI: Found IRQ 11 for device 0000:02:0c.0
[ 3.193386] 3c59x: Donald Becker and others.
[ 3.193451] 0000:02:0c.0: 3Com PCI 3c905C Tornado at e0814000.
[ 3.314350] *** EEPROM MAC address is invalid.
[ 3.314411] 3c59x: vortex_probe1 fails. Returns -22
[ 3.314479] 3c59x: probe of 0000:02:0c.0 failed with error -22

We have, indeed, successfully bothered the 3c905 network card to cause it to go away and get off our bus. It wasn't the cleanest solution, but it did work. It turns out that if you set the BARs on a card to garbage, Linux will set them to non-garbage on card probe, and since we can't trap on 0xCF8/0xCFC accesses, those were *two* of the methods that we planned to use to bother this card gone. But, Linux will surely listen to you if you ask often enough; so, we asked the card every 64msec to stop responding to requests. This creates a race; it had better be the case that Linux does PCI enumeration more than 64msec before it loads the 3c905 driver, or else we will be hosed.

I'm not sure if there is a clean way to do this; suggestions would be appreciated. This works, at least, for the time being.

There were many more things that happened tonight, though. In particular:

  • SMI handlers now have enable routines -- instead of poking the hardware directly, you can smi_register_handler(...); smi_enable_event(...);. Much cleaner code, much more portable.
  • Structured packet support was added. If you put some magic values in the registers, then poke the GBL_RLS (BIOS request) bit on the southbridge like an ACPI handler would do, then you can make requests of NetWatch. You can even give it a logical address, and it'll do lookups just as if it were the kernel! Blame Jacob for that... ;)
  • We can now scan and probe devices on the PCI bus, with a relatively abstract method.
  • Output routines were unified -- now instead of deciding whether to call puts or dolog, you can call the function pointers output and its formatted friend, outputf and you'll get the Right Thing no matter whether you are in the loader or the aseg code itself.

The code is now much cleaner, and more extensible. Look forward to lwIP coming this weekend, or at least a small network driver.

Sunday, September 21, 2008

quick thought

Also, we need to unify logging. Having dolog() from some contexts, and sprintf()/puts() from others is not so cool. Also, we need to figure out a way to split the build environments out, and put object files in the right places for the right build environments -- right now, there are three build environments (Linux, grubload, and in-SMM, with grubload being very similar to in-SMM, but for the bigger console). A full unified build system that would allow you to 'make' from the root would be cool too.

Much-needed dirty work

Okay, some much needed dirty work has been done. I moved a bunch of logic out to smi.c, and put together a lot of defines in reg-82801b.h as created from Intel's documentation. There are a few subregisters that need to be trawled, and I need to work out a system to register interest in a type of event, and have a callback for it.

Of note also is that we now have 'printf' and 'dologf', which should eliminate disgusting blocks of code like this:
                strcpy(s, "READxxxxxxxxxxxxxxxx");
tohex(s+4, cts);
b = inb(cts & 0xFFFF);
tohex(s+12, b);

To be replaced with:
                b = inb(cts & 0xFFFF);
dologf("READ: %08x (%02x)", cts, b);

This gives much cleaner code, and much cleaner output, too!

I'm undecided on this whole 'no magic number' business again. On one hand, things like this: return pci_read32(0, 31, 0, 0x40) & 0xFF80; do look pretty magic and hard to maintain; indeed, it has even been the source of a bug, since '31' was originally typoed as '21'! But on the other hand, replacing with named constants is pretty ugly too; my RSI is acting up just thinking about this: return pci_read32(ICH2_LPC_BUS, ICH2_LPC_DEV, ICH2_LPC_FN, ICH2_LPC_PCI_PMBASE) & ICH2_PMBASE_MASK;. Yikes.

So I guess the next step after this stuff gets cleaned up is to start trying to hide the NIC. Since PCI interception doesn't work, I guess we get to turn off the BARs, and hope that Linux does not turn them back on for us. We shall see...

Saturday, September 13, 2008

Good news and bad news

The good news is that we now know how to trap on arbitrary I/O reads/writes. We successfully have it wired up such that when you press escape, and when the OS goes to read the escape key, the system reboots, which is great fun for annoying vi users. We have both the 'special' traps (keyboard/mouse) and normal traps (arbitrary I/O ports) working.

Now, the bad news is that 32-bit accesses to the PCI config I/O ports 0xCF8/0xCFC are caught by the memory controller hub (MCH), which comes before the ICH, and that means that we can't trap on those accesses. So, we can't get in the way there, which kind of sucks. I was trying to get in the way by trapping on the IO ports allocated to the 3c905, but it turns out that's also bound to memory mapped regions; I think that if we intercept PCI before Linux starts and deconfigure the BARs for the MMIO registers on the 3c905, then we can force it to use the I/O ports (and subsequently force Linux not to see them). Perhaps better, we could just deconfigure both BARs and only configure them when we're in the SMM handler and we want to talk to the card... hmmm...

Thursday, September 11, 2008

Pre-sleep updates

  • System now boots with Jacob's ELF loader, and returns with my real mode code to reboot into grub, and can do full Linux boot process with SMM monitor.

  • SMM monitor currently breaks ACPI, because it is used for APM ports (0xB2/B3) -- can we fake it well enough, or do we have to chain the old one? (ewww)

  • We have a log console for debug messages that shows up at the top right of the screen

So, both "immediate todos" are complete. Now need new immediate todos... to be discussed tomorrow if we have time. Refactoring is imminent.

The git repository is now publicly accessible: NetWatch git

Photo of the day:

Linux running

Wednesday, September 10, 2008

Status update

Current status as of first update:

  • We can open up aseg and write to it on our test machine, ainfvec (ICH2).

  • We can trigger and retrigger SMIs on ainfvec.

  • We have working aseg code that writes to video memory from C space.

  • We have PCI write skeletons for Linux and raw I/O.

  • We have a working ELF loader that 'raw loads' ELFs into memory from inside Linux.

  • We have a multiboot kernel that can be loaded from GRUB, using Joshua's p1 console.c. Does nothing more than print parameters and spin.

  • Build system surely needs work.

  • Modularity need work.

Immediate todos:
  • Get grubload to return to GRUB later.

  • Load ELF/SMM code from grubload.

Later todos relating to current code:
  • Refactor machine specific/northbridge specific code into users of a PCI module.

  • Have PCI code scan bus and enumerate cards.

Code available:
git clone