Darwin's Theories Blog

New Theories for a New Time

Convincing a Mac Mini to auto-boot on power-up

2015-04-11
I recently went to install a Mac Mini at a remote location. The Intel-based Mac Mini is a small, low-power, full-function AMD64 machines. But first, I ran into one problem. And it's a known problem with older Mac Minis: they don't power up when power is applied. Somebody "thunk different", indeed.

Because of this power-up issue, if you install one at a remote location and there's a power failure, you have to hike or drive out all that way just to press a button. Good exercise, maybe, but not so good if it's -40 out.

There is a well-known solution on other *Nix OSes, noted at several web sites such as https://www.mythic-beasts.com/support/servers/colo/macmini.

They suggest several variations of this command for different MacMini models, e.g., setpci -s 00:03.0 0x7b.b=19

This means: on PCI device at 0:3:0, at offset 0x7b, write one byte as 0x19.

Now setpci is a linux-ism, but it's included in an OpenBSD port named pciutils. So I installed the pciutils package to try to do things "by the book", and tried the various options. All failed.

$ sudo lspci | grep LPC        
00:03.0 ISA bridge: NVIDIA Corporation MCP79 LPC Bridge (rev b3) 
$ sudo setpci -s 00:03.0 0x7b.b=0x19   
setpci: obsd_write: ioctl(PCIOCWRITE) failed 
$ sudo setpci -s 0:03.0 0xa4.b=0       
setpci: obsd_write: ioctl(PCIOCWRITE) failed 
$ sudo setpci -s 0:3.0 0x7b.b=0x20  
setpci: obsd_write: ioctl(PCIOCWRITE) failed 
nsysMAC$ sudo setpci -G -s 00:03.0 0x7b.b=19 
Trying method 8......using /dev/pci...OK 
Decided to use obsd-device 
Scanning bus 00 for devices... 
Scanning bus 01 for devices... 
Scanning bus 02 for devices... 
Scanning bus 03 for devices... 
Scanning bus 04 for devices... 
setpci: obsd_write: ioctl(PCIOCWRITE) failed 
$  

While pondering what to do next, and asking a few people, I got one response to an email which suggested that:

> iirc, the "best" option would be to install macosx, switch the 
> value from the software, and then reinstall OpenBSD. 

Unfortunately, the "think different" BD (brain-damage or BIOS damage) is redoubled by the fact that, even if you do manage to get the correct bits set, and your machine boots when you apply power, this bit setting is deliberately erased after the machine reboots! So if you do get a fix, you have be very sure you run it right after reboot, every single time.

In looking at the man page for pci(4), you can easily learn that, in our PCI support, the PCIOCREAD ioctl will only write words, not bytes. In looking at pciutils source code ("make extract patch" is your friend), it has not been updated to take account of this. Time to blow the dust off my C coding skills and cobble something together.

Cue sounds of much typing and some unintelligible (or maybe just unrepeatable) verbalizations.

Reading that same manpage you will not, however, learn the other vital piece of information you need. It turns out that on OpenBSD when you open /dev/pci for output (needed to write to PCI space), unlike nearly every other device on nearly every POSIX-oriented OS, where opening it depends on the device file's permissions, you cannot open the PCI device for output unless you have permission *and also* either are in securelevel 0 or have enabled the X windows apterture driver (sysctl machdep.allowaperture). This restriction makes sense, but it is not documented anyplace. I don't know about you but I don't normally do development in securelevel 0. And since this is a headless machine, I never enabled X support so the aperture thing wasn't enabled.

So. Just enable the aperture driver and the program starts working. My Mac Mini now reboots reliably after power is reapplied.

BTW, this reasonable but completely undocumented and somewhat-counter-intuitive behaviour is not documented in the OpenBSD man pages, and my patch to pci.4 to document it was rebuffed by the project's leadership. Instead I'm releasing my quick-hack program and thus documenting it in the code.

Now writing to PCI space from userland is not something to be encouraged, for obvious security reasons, and in fact the OpenBSD kernel guys have been trying to eliminate it. As long as X needs it, we can keep using our Mac Mini's remotely, because it turns out PCI writing is the only way to repair this BIOS brain-damage, other than writing a special device driver or sysctl or some other kernel code (I usually put on the barbecue mitts when it's suggested that I write kernel code), or switching to another BSD variant or to Linux, which I'm obviously not anxious to do.

If you have a Mac Mini "3,1" (aka "late 2009", part code 2336), the program should work for you. For any other Intel Mac Mini, the address and offset will need some juggling (see the link above). The current version doesn't even check (yet) that you're on the right model, so that should be added too. The program is up on github, so please feel free to add teh checkz and also to add support for other models (based on the documentation in the first link in this posting), sending me a patch or a pull request.

Before I tell you the URL, I must #include <stddisclaim.h>: USE AT OWN RISK.

There. You've been warned. The program is at https://github.com/IanDarwin/macsetautoboot.