mmio trace for fun and no-profit

I’m not sure what got me interested in assembly language as a nerdy high-schooler. It could have been the growing interest in computer graphics, at a time when you had to use assembly to get decent performance out of the machine. I remember learning tricks from much smarter people than myself, such as how to set a 256×256 pixel video mode so that you could address any pixel without ever needing to multiply. Not that you would use a multiply anyway since you can always use shifts and adds.

I suspect, however, that part of what spurred me on was an interest in reverse-engineering, specifically to crack games. You would start BattleChess, say, and it would ask you for some move from some historical chess game in a big book before letting you play. This was to ensure that if you copied the game, that you at least also photocopied your friend’s manual. [For the record, while I cracked a few games, I never released any such cracks. More from being l4m3 than any teenage sense of ethics. I did, however, release instructions for patching the video game “Home Alone” so that you could never die. I may have been the only person on the planet to play that one all the way through.]

In order to crack a game, first you would load up SoftICE, a killer software debugger that would let you debug almost anything. It would let you set breakpoints on interrupts so step one was to put a breakpoint on ‘int 10h’. Interrupt 0x10 was a call into the video BIOS for setting up the video card. Back in the DOS days, it was the first thing every graphical program (and therefore game) did, because you started out in text mode and had to go into VGA mode. The BIOS would know how to load all the registers for that particular card; you just had to say “put me in 320×200 mode, now, thanks!” and that was via the assembly command “int 10h”.

After SoftICE caught the interrupt, the screen would switch back from VGA mode into a text mode listing of assembly instructions and raw machine code hex values. I don’t think I knew what all these meant at first, but I understood ‘call’ and ‘jmp’, and everything else I quickly learned from a text file describing the x86 instruction set architecture. So cracking then became a matter of just single stepping through all of these instructions, and waiting for BattleChess to get to the part where it asks you the question. Then, you start paying attention, looking for the assembly equivalent of “Is the answer right? If so, goto game! Else goto nasty message!” Some of these were harder than others, but generally it looked something like:

mov ax, ds:[43ac]
mov cx, ds:[3401]
cmp ax, cx
jnz 0027

You could step through it, type the wrong answer, then watch it jump to instruction number 27 which then printed out the nasty message. Then you could try again, and this time modify the code while you’re in the debugger. For example, change the jnz 0027 to a few no-ops (instructions that do nothing). Type in the wrong answer, and now it keeps on going to the game. Bingo, the game is cracked! SoftICE was such a nice debugger that I even used it for C debugging until I finally moved off of that whole DOS thing.

Anyway, I’ll never be a Jon Johansen, but that interest in reversing stuff has stuck with me. I think that figuring out how the Karma worked, which involved many hours of pouring over hex dumps trying to come up with the pattern, was much more fun than coding the driver. Particularly when the “ah-hah!” moments would strike. Incidentally, coding the driver was/is still fun, probably more so than actually using the device.

This little walk down memory lane was inspired by the recent entrance of mmio-trace into my zone of consciousness. I’m not sure who used this first, but the Nouveau project has been using the utility for some time to reverse-engineer the NVidia video cards so that Linux can gain decent open source drivers. My laptop luckily has an Intel based video card, but it does have an Atheros wireless chip which also has a binary blob. There’s currently an effort to produce a reverse-engineered driver for it as well. In my case, the new driver almost worked, but I needed to come up with some other details, so I tried out mmio-trace.

PCI cards are configured by register writes, but the driver generally has to program it to get it going. The BIOS can’t do that work for us any more. So the OS maps a region of memory that the driver can just write into, which then all gets converted magically into writes into the PCI device’s register file. Thus, MMIO=”Memory Mapped IO”, and mmio-trace does what it sounds like. Using it is rather painless, you first ‘hook’ a module you want to capture, modprobe mmiotrace, then load the hooked module. All writes to PCI config space get captured into a debugfs file that you then run through a user-space filter. The end result is a nice report of all of the reads and writes to the registers of the PCI device. Very neat!

Oh, the driver maintainer already knew about the issue and confirmed my proposed change so hopefully by 2.6.26 ath5k will support my Macbook.

I hate you, Sun.

Is it too much to ask of a compiler that if it decides to blare warnings at you for no reason at all, that you can turn the !@#$ thing off? In a move that rivals the stupidity of certain gcc warnings, we have this:

[javac] file: java:519: warning: com.sun.rowset.CachedRowSetImpl is Sun proprietary API and may be removed in a future release

Well, hey that’s a nice heads-up to give me 600 times when compiling our tree. Let me go find the non-com.sun equivalent of that. Oh wait, there isn’t one! And, the freaking javadoc even tells you to do it that way. Okay, well, maybe @SuppressWarnings({"deprecation"}) will work? Nope, haha! Sigh. Time for a wrapper script.

Request of persons who wish to write a better javac: can I have plugins that let me muck with the AST? Custom static checking would be nice…

Gave One Got One


00025.jpg
Originally uploaded by bluesterror

I just received my OLPC from the “Give One Get One” program. For the uninitiated, this is the program that aims to send $100 ($200) laptops to children in undeveloped nations.

First thoughts are that this is a cool little laptop. It is very light. The screen is small but has decent resolution, in the 800×600 range. The processor is an AMD Geode 400 mHZ, it’s got a gig of flash for storage, and 256 megs of RAM. It seems a tad sluggish for a machine with those specs (similar specs to my firewall at home which runs X fine), but not so slow that you couldn’t get used to it.

The UI is neat, running on top of Linux and I understand mostly written in python. There’s a video recording app (did I mention the thing has a camera?), word processor, browser. There’s a little python IDE with some sample programs (basic math, print Pascal’s triangle and Fibonacci numbers, etc). And a terminal where you discover that the device has vim installed but no gcc. C programmers everywhere cry.

All in all, it’s probably not going to work for anyone who already has a laptop, or any adult for that matter without using a USB keyboard since the keys are so small (mine is eventually going to my nephews). But I think if I got this at age 6, it would spark my imagination as much or more than the C=64. I think we’ll see a lot of computer professionals emerging from these countries in 20 years.

(A few more pics at flickr.)

Vista-ed

I got my first look at Vista with Angeline’s new Thinkpad. So far, it’s not looking too good.

I’m a slacker

I was thumbing through Joel Spolsky’s new book on hiring talented programmers at the bookstore the other day. He asserts in the first chapters that great programmers are ten times more productive than bad ones. Could that be true? I played around with git today to generate statistics to see how it looks on our refactoring project this year:

user    commits   files changed  LOC added  LOC deleted         
dev0:       453            4258     +81538      -100344
dev1:       152            2297     +54462       -45343
dev2:       104             550     +24779       -17475
dev3:        82             250      +6465        -7852
dev4:        73             209      +3920        -2782
dev5:        56             208      +5158       -10049
dev6:        24             116      +3297        -7823

Wow. Of course KLOC isn’t everything, but take it on faith that dev4 causes more problems than he solves (dev5,6 were only on the project a short time), and that dev0 is the most awesome programmer that writes on this blog. And I thought surfing the web 7 hours a day was too much…

Wake up!

Dear Windows,

If you feel the need to download printer drivers at 3 AM, please don’t announce it by playing cutesy chimes. People are trying to sleep ya know? That goes double if the chime is just to announce a prompt to ask you if you want to search for updated printer drivers.

In other news, I’ve been using git at work a lot lately. There’s a steep learning curve and it took three tries to convince me that git is better than (version control of the day), but once I grokked it, I was hooked. So many hours have been lost waiting for subversion to show commit logs or perform commits. Also, I’m going back and forth to my laptop without being able to connect the latter to the network, so git-bundle and git-svn are much better than my previous solution of extensive use of patch(1). Branching and merging is so easy that I invent excuses to do them.

sed

Sometimes I look at a long Unix pipeline and think, “I should do this in perl.” Other times, it is, “I bet I can do this all in sed.” So, here’s how to print just the lines of a file following a successful match in sed:

sed -n ':s; /^regexp$/{b l}; n; b s; :l; p; n; b l' file.txt

Lazyweb, is there a shorter way?

Brian K

Last Monday I attended an ACM lecture featuring Brian “Zapp” Kernighan, coiner of the name “Unix,” the ‘K’ in awk, as well as the ‘K’ in K&R. The gray-haired professor reminisced about the golden days sitting across from Ken Thompson’s and Dennis Ritchie’s desk (Ritchie is a slob of the first order). The salient points: make software more simple, avoid the second system effect (as in Multics), and find a small group of talented guys and start a revolution (probably not in operating systems). In other words, a pretty good summary of The Mythical Man Month.

A bunch of nerds got him to sign their copies of The C Programming Language. It was sad.

Hacking ReplayTV

A few weeks ago someone contacted me regarding my OMFS filesystem driver for the Rio Karma. His interest is in getting it working for ReplayTV to do who knows what. This is coming a bit full circle, as I discovered long ago that the RK and RTV use the same proprietary filesystem, and indeed the ReplayTV hackers of yore had documented nearly everything there is to know about the FS, without which I would’ve been lost writing the Linux kernel driver in the first place. Of course, there are some differences in the way the two devices do their thing.

I don’t own an RTV, but I like a challenge so I asked him to send me a dump of the first gig of the disk. One look and it is the crack-headedest thing I’ve seen in some time: somewhere along the way, their block layer must’ve moved from a big-endian to little-endian platform, without changing the code. OMFS is a 64-bit FS but the RTV block layer apparently works on 32 bits, so for example the 64-bit value 0x8877665544332211 gets written to disk as 0x5566778811223344. And it’s not just the metadata: *everything* is swapped. Filenames look like “tusCzimo..re” instead of “Customizer”. File data blocks are all swapped. Very odd.

Well, for a time I’ve been wanting to experiment with OMFS written in FUSE, so I took my userspace routines from omfsprogs and in the space of an hour or two had a read-only FUSE-based OMFS that did the necessary byte swapping to work with Replay’s file system.

The payoff is the text file that RTV developers apparently used in their version control process. I give you: ReplayTV “Token Haiku” (after the jump).
Continue reading “Hacking ReplayTV”