On Annoying Startup Chimes

I like my MacBook well enough, but it certainly does have its share of issues. One such bile-inspiring misfeature is that it sees fit to loudly blare its “I’m a Mac!” chime every time you turn the thing on. According to those in the know, this is actually a feature to let you know the computer started properly. Hmm, I see a big Apple logo, screen is on, I think it’s started. So, Mr. Computer, how about making the big ugly noise when you know it isn’t working instead, and save us the ear strain the other 99.9% of the time? Did they really think no one would want to use the laptop in, say, a library, or a classroom?

The bonus of this brain-o is that older Macs gave you the ability to hold down the mute key while booting to temporarily turn off the sound, a useful feature abandoned for the Intel Macs. Also, plugging something into the headphone jack doesn’t work, because “the headphone jack isn’t available at boot time.” (Why? I can still see it there!) Apple actually recommends, and I’m not making this up, that you “fix” it by remembering to mute your audio every time you shut down your computer. Some people have even written little daemon programs for OSX to do that for you. Amazing.

Of course, the fanboys rationalize this crazy behavior in predictably nonsensical ways: “You should always use sleep instead of turning off your computer” or “I like the sound because it lets people know I’m using a Mac.”

As it happens, the boot noise volume is configured by an NVRAM variable, which seems to be synced with the volume control at shutdown time. Setting it to 0x80 turns off the boot chime. Why 0x80, I do not know, but I stole this very useful information from some mailing list post and can attest that it works.

Here’s how I think this variable was born in Cupertino:

    Engineer 1: This noise is driving me mad, can't we turn it off?
    Engineer 2: Sure, we'll just put a switch in NVRAM.  That way, only the
                users have to deal with it.
    Marketing: Some users, probably miserable Windows lovers all, are whining
               about our awesome boot noise feature.  What should we tell them?
    Engineer 2: Just tell them to mute the audio when they turn it off.
                Heh heh.

So, here are some solutions: you can use the nvram program in OSX as in my previous link. And I’m sure you could, with proper EFI support in Linux (CONFIG_EFI_VARS), do a similar thing from Linux. But I am presently missing the EFI kit and I hate booting OSX, so here’s my other, much more insane way of fixing this problem.

You need:

  1. a Mac with rEFIt already installed
  2. a USB key with a [V]FAT partition

Procedure:

  1. Plug in the USB drive and turn on the machine.
  2. At the rEFIt boot screen, cursor down to the EFI shell. This will start a shell in the firmware reminiscent of the heydey of MS-DOS 3.0, when edlin was king of the text editors.
  3. Type ‘help -b’ to get your bearings.
  4. Get the current audio level via:
    Shell> dmpstore SystemAudioVolume
  5. Now, figure out where your FAT partition got mounted. Useful commands include ‘map’ and ‘ls’ (mine was on fs3):

    Shell> map -b
    Shell> ls fs3:
  6. Use dmpstore to save the NVRAM variable to a file.
  7. Shell> dmpstore SystemAudioVolume -s fs3:volume.txt

  8. Use the built-in hex editor to change the last byte from the value in step 4 to 0x80. Yes, rEFIt has a built-in hex editor!
  9. Shell> hexedit fs3:volume.txt

  10. Now load the new value, check it, and reboot.
  11. Shell> dmpstore SystemAudioVolume -l fs3:volume.txt
    Shell> dmpstore SystemAudioVolume
    Shell> reset

That’s it! It should be gone for good, until you somehow enable it again. When that happens, you can pop the key back in, and redo step 8 with the volume.txt file you remembered to not delete.

Hmm, on second thought, maybe it is easier to just use the sysfs files.

wl12xx merged

commit 00d8979d598d5461a06d800c779f15e03888d9d8
Author: Kalle Valo 
Date:   Wed Apr 29 23:33:31 2009 +0300

    wl12xx: add driver

    wl12xx is a driver for TI wl1251 802.11 chipset designed for embedded
    devices, supporting both SDIO and SPI busses. Currently the driver
    supports only SPI. Adding support 1253 (the 5 GHz version) should be
    relatively easy. More information here:

    http://focus.ti.com/general/docs/wtbu/wtbuproductcontent.tsp?contentId=4711

    (Collapsed original sequence of pre-merge patches into single commit for
    initial merge. -- JWL)

    Signed-off-by: Kalle Valo 
    Signed-off-by: Bob Copeland 
    Signed-off-by: John W. Linville 

Hooray, wl12xx is now in wireless-testing! As the commit log states, SDIO support isn’t there yet, because I haven’t written it yet. Well, I wrote some of it, but nothing worth even compile-testing yet.

As for the Android itself, I bought a snazzy serial breakout board for the phone so now I can do some real work on it. It works just fine with screen(1) as the terminal program.

Also, I solved the problem with booting: apparently the init program for 2.6.25 doesn’t work with 2.6.27 — when I put my own compiled init in the initramfs, everything mounted fine. The input devices now do not work, but I suspect it’s just a difference in paths and that an upgrade to 1.5 userland will fix all of that.

Closer

I was in fact wrong that my self-compiled android kernels weren’t booting — they were. But they do fail somewhere in init:. Unfortunately, when you boot the phone, you don’t have any idea why it fails because there’s no console by default. It would’ve been a lot easier to see this if I had a serial cable, but I did finally remember that I could use fbcon with the smallest font and CONFIG_PRINTK_DELAY to see the messages scroll by. And so now I see the problem:

A N D R O I D
init: Unable to open persistent property directory /data/property errno: 2
init: cannot find '/system/bin/sh', disabling 'console'
init: cannot find '/system/bin/servicemanager', disabling 'servicemanager'
...

Obviously, the init script can’t mount the mtd partitions, despite the partition tables being successfully probed at start and my having yaffs2 built-in. Oh well, at least now I have a direction to start debugging.

The 2.6.25 branch of the msm tree, incidentally, works fine with the stock initrd and userland, but who wants such an old kernel? Oh, and I changed my bootup logo to a shiny Tux instead of the default robot. “Android isn’t Linux” indeed.

Manual git-svn clone

I finally decided to do something about the five independent git trees I had on my hard drive at work. The problem is they are all really branches of the same subversion repository, and moving patches back and forth between them meant I had added them all as git remotes to each other. The meta problem is that we didn’t always branch off of the same trunk directory, from back when we were drinking the “just snapshots of directories” subversion kool-aid, so git svn clone doesn’t do the right thing for our branches.

The ideal setup is one where I have a git branch for each subversion branch all in one tree, and git svn dcommit will go to the right place. As it turns out, this isn’t too hard to achieve, but requires a lot of waiting around when building the repository. You just manually add different svn-remote sections to your .git/config, then run git svn fetch for each one:

$ cat .git/config
[...]
[svn-remote "svn"]
url = svn+ssh://server/svn/trunk/
fetch = :refs/remotes/git-svn
[svn-remote "svn-bar"]
url = svn+ssh://server/svn/branches/foo/bar
fetch = :refs/remotes/git-svn-bar
[...]
$ git svn fetch
$ git svn fetch svn-bar
$ git checkout -b bar svn-bar

Now ‘bar’ is a branch tracking the directory in branches/foo/bar, master is your normal trunk line of development, and git svn dcommit just works. Having 8 years of history in a 400 meg local tree is pretty nice.

Emulator

The Android source code includes at least two ARM sub-architectures in their kernel tree. The one actually used on the G1 hardware is derived from the Qualcomm MSM machine type, at least part of which is in the mainline. Then there is “goldfish,” which appears to be just a pseudo machine used only for the emulator. While I haven’t had a lot of success with the MSM stuff booting on the phone so far, building the emulator kernel is not too hard once you know where to look:

# get the MSM specific tree.
# You don't really need it but might as
# well grab both up front into the same git repo.
$ git clone git://android.git.kernel.org/kernel/msm.git msm
$ cd msm

# also grab the common one for emulator target and check it out
$ git remote add common git://android.git.kernel.org/kernel/common.git
$ git fetch common
$ git checkout -b goldfish common/android-goldfish-2.6.27

$ cat <<_EOM >make-arm.sh
#! /bin/bash

# I use the codesourcery toolchain
XGCC=/opt/xgcc
PATH="$XGCC/arm-2008q3/bin/:$PATH" make ARCH=arm CROSS_COMPILE=arm-none-eabi- "$@"
_EOM

$ chmod 755 make-arm.sh
$ ./make-arm.sh goldfish_defconfig
$ ./make-arm.sh

Now the emulator can be run with something like:

$ export ANDROID_PRODUCT_OUT=`/bin/pwd`/out/target/product/dream
$ emulator -verbose -show-kernel -kernel msm/arch/arm/boot/zImage

2.6.30 preview

Now that Linux 2.6.29 just went out the door, here’s what I have prepared for 2.6.30 in the wireless arena. Of note, mac80211 now has suspend/resume support so a lot of nasty hacks in the drivers can go away. Most of the rest is just bug fixes, some of them for panics and soft lockups.

The work I’m excited about this week is scheduled for 2.6.31 — we extracted a bunch of ath9k regulatory infrastructure into a common module that all of the Atheros drivers (including the new ar9170) will use. This is the first step in getting a lot of that common code into a library. Hooray! Also Nick has some great improvements to the RF stuff queued up, so the driver is behaving much better.

Bob Copeland (29):
      ath5k: support LEDs on Acer Aspire One netbook
      ath5k: fix off-by-one in gpio checks
      mac80211: document return codes from ops callbacks
      ath5k: fix bf->skb==NULL panic in ath5k_tasklet_rx
      mac80211: add suspend/resume callbacks
      ath5k: remove stop/start calls from within suspend/resume
      ath5k: remove unused led_off parameter
      ath5k: use short preamble when possible
      ath5k: honor the RTS/CTS bits
      mac80211: change workqueue back to non-freezeable
      mac80211: flush workqueue a second time in suspend()
      ath9k: remove write-only current_rd_inuse
      ath9k: save a few calls to ath9k_regd_get_eepromRD
      ath9k: convert isWwrSKU macro into C code
      ath9k: remove ath9k_regd_get_rd()
      ath9k: remove prototype for ath9k_regd_get_current_country
      ath9k: move common regulatory code out of if() branches
      ath5k: don't mask off interrupt bits
      ath5k: use spin_lock_irqsave for beacon lock
      ath5k: move beacon processing to a tasklet
      ath5k: compute rts/cts duration after computing full pktlen
      ath9k: fix 802.11g conformance test limit typo
      ath5k: extract LED code into a separate file
      ath5k: use a table for LED parameters
      ath5k: update LED table with reported devices
      ath5k: disable MIB interrupts
      ath5k: remove dummy PCI "retry timeout" fix
      ath5k: warn and correct rate for unknown hw rate indexes
      ath5k: properly drop packets from ops->tx

Upstream Last

Building a booting kernel for Android using their own code still eludes me. I guess it would help if I knew anything at all about the ARM platform, as I have no idea what I am doing. Still, the code dump fails the “anyone should be able to build it” test rather strongly, judging from posts on the android mailing lists.

Build problems aside, the more egregious failure of the Android open source project is the lack of the “upstream first” mentality. Most Linux software providers follow this strategy to a large extent, which is simply: any patch that goes in my distribution should go to the mainline kernel first. The benefits are obvious: no need to maintain a fork forever, and everyone gets the goods as soon as possible. Even if the patch only serves the developer’s own interests, upstreaming it often has the benefit of vetting the interfaces and producing more universal APIs (the wakelocks discussion that followed the code dump is an example of this done backwards).

Google, however, sadly took the other road: get the product out the door, then worry about pushing bits upstream when we get a chance. The problem is “when we get a chance” never, ever happens, and there’s no motivation to push changes upstream when your product has shipped and it’s now forever in deep maintenance mode. That job of upstreaming is left to the community.

So far there’s no real indication (apart from the userland stuff) that you actually can build the G1 kernel and userland from the code dump. Google engineers are unclear whether everything on the phone is in the codebase (clearly some proprietary bits are not). Meanwhile they have their own fork of qemu, their own fork of the kernel, their own fork of webkit, and so on.

I suppose we should not fault Google too hard: after all, some code is better than no code at all. And if they want to maintain forks of .* forever, that is clearly their prerogative. However, had they worked more closely with the community at the start, the Android platform would be stronger today. They might already have a decent wireless driver, for example.

Fit to be TIed

The Android G1 phone uses the TI 1251 for Wifi.   This is pretty useful for when you need an internet connection for the laptop and there are no alternatives: you can bridge the wifi and the 3G connection and then connect to the wifi device using ad-hoc mode.  However, I normally keep the wireless off because it sucks down battery like mad.

But Kalle Valo from Nokia is working on a driver for the chip called wl12xx, and he is putting a lot of effort into making sure it uses power conservatively (presumably some future version of the Nokia internet tablets will be using this device).  This driver is SPI, whereas the G1 uses the same chip in SDIO mode.  So I started writing the SDIO port for the driver — hopefully it will be ready when wl12xx is included in mainline.

The TI reference code that actually runs on the G1 is, sorry to say, total crap.  It registers an interrupt handler that printk()s a static string.  It has unbalanced sdio_claim_host() calls.  And from a code style standpoint, well, there is none.  I suspect Valo’s driver will be a big step up if and when it can run on the Android.

Oh, and Google’s open source tree for the Android hasn’t built all weekend.  Great job!

Backup re-revisited

I’ve reconsidered using git as my backup choice du jour. The main problem (and feature) of using git was having a checked out repo in my home directory. I found I was forever worried, given my admittedly horrid muscle memory habit of doing ‘git reset –hard’ periodically inside source trees, that I’d accidentally do it from the wrong directory and lose any recent work. Luckily, I never did that.

Two obvious solutions: don’t use a checkout in the home directory, instead using rsync to the repo; or use a wrapper/custom command name for the git-as-backup program to avoid accidents. Well, I went with the third option: use rdiff-backup like a normal person. It’s packaged by Fedora and Debian, so I only needed a small tweak to my backup scripts to make that happen every night. And someone wrote a FUSE filesystem (archfs) to mount the backups as normal directories, so there’s no real loss of convenience under this scheme.

My RPM database is now corrupted. Just in time.

sizeof()

Renaming your class variables to shorter names reduces your EJB network footprint. Finally, those people who said that removing vowels from variable names improved performance are vindicated! Ok, well they were correct already in Javascript, but that doesn’t count.