Installing Linux on a Compact Flash Card
I tend to favor purpose-built appliances — devices that “do one thing, and do it well.” So I have a few Linux-based appliances that live in closets and under desks, humming and blinking away. Most of these boot from flash disks, and have been for some time.
Here’s an old entry from my notes for the retro crowd, when IDE and Compact Flash were relevant tech. Enjoy!
Compact Flash cards are electrically and logically compatible with ATA (IDE), so if you’re using a motherboard that supports IDE, a simple passive adapter is all that’s needed to make it appear as an ordinary hard disk to Linux. Usually.
In reality, the card’s support for UDMA modes can vary, and not all CF-to-IDE adapters properly patch the pins on the cable to the necessary pins on the card. As a result, sometimes UDMA operations fail, causing a flurry of spurious error messages and painfully slow I/O.
There are a few ways to fix this, with varying degrees of ease and collateral damage:
Disable UDMA for that device in the BIOS. Or use a card that does not (attempt to) support UDMA. Linux should recognize the lack of hardware support and disable DMA for that device. Note: Should.
If you’re using the legacy IDE kernel drivers (that is, IDE devices are enumerated as /dev/hdx), add the ide=nodma option to the kernel boot parameters.
This is kind of a ‘big hammer’ approach, and will disable DMA for all IDE devices, increasing CPU overhead and thus reducing performance. So if you have other IDE devices, this is probably not your first pick.
If your kernel has a (more recent, but still old) IDE driver, it may support granular (per-channel, or better yet, per-device) options.
Try ide_core.nodma=x.y, where x is the IDE channel, and y is the device on that channel, both starting at 0.
I.e., you would use 0.0 for primary master, 0.1 for primary slave, or 1.1 for secondary slave.
If you’re using the libata kernel drivers (which enumerates all disks as /dev/sdx regardless of type) you would instead use libata.dma=x.
The value x is a bitmapped flag, where:
- 0 disables all DMA
- 1 enables DMA for PATA and SATA hard disks
- 2 enables DMA for CD-ROMs
- 4 enables DMA for Compact Flash cards.
Thus, a value of 3 (that is, 1 + 2) will enable DMA for hard disks and CD-ROMs, but not Compact Flash cards. Exactly what you want.
Finally, if you’re really hard core, find the DMA blacklist in your kernel sources and manually add your device’s ID to the list.
For libata, this can be found in /usr/src/linux/drivers/ata/libata-core.c.
Look for the array definition below, and add a line like the one shown:
static const struct ata_blacklist_entry ata_device_blacklist [] = {
...
{ "BIOS CF ID Goes Here", NULL, ATA_HORKAGE_NODMA },
...
}
You’ll need the exact ID your card uses (the one that shows up at boot time, in the BIOS, or from hdparm, etc.), then look around at similar entries to make sure you’re following the pattern.
Finally, recompile your kernel, reboot, and see if that does the trick. If not, check the ID — it may be padded with spaces, for example.
In reality, given the declining popularity of Compact Flash, there are probably better options. You can also find flash modules that plug in to the IDE or SATA port directly, although they’re relatively rare and usually designed for the industrial market, you’ll pay more for the novelty.
So why bother? I dunno. Because you can, I guess.
Coping with frequent writes
Flash memory, of course, has limited write cycles, so it helps to manage the services that write to disk frequently — particularly syslog.
The easiest way to do this, if you have a little extra memory, is to set up a RAM disk and log there:
mount -t tmpfs -o size=100m tmpfs /var/log
Of course, you’ll probably want to add this to /etc/fstab so it’s there when the syslog daemon starts. And adjust the size parameter to taste.
As the name implies, the contents won’t survive a reboot. If you care, you can configure the syslog daemon, or logrotate, to copy them to persistent storage at some point.
Alternatively, forward syslog events to an external host instead. If this isn’t for home use, definitely do that. That’s another article though.