Tuesday May 02, 2006
Solaris on EFI (iMac) First, I'd like to point out that Solaris already runs on iMac
with BootCamp (see blog by
Jan Setje-Eilers).
What I'm talking about is getting Solaris booted from EFI without
legacy BIOS emulation. To start with, we need Intel's EFI toolkit.
With instructions from web search, it was straightforward to
get an EFI shell and run sample applications.
Gnuefi and Elilo
The next step was to run my own EFI application that can bootstrap
Solaris. To do that, I needed to compile my own EFI executable
and I didn't want to setup a Windows environment. Naturally, I
picked the gnuefi. At first, I downloaded gnu-efi-3.0a, but it didn't
compile on my Linux environment. After some web surfing, I found some
related postings. Eventually, I moved to gnu-efi-3.0c, which
worked fine.
Now I was ready to tackle Solaris specific issues. The first choice
I needed to make was whether to have EFI load Solaris directly or
via an intermediate efi program. After some experiments,
it became clear to me that the EFI execution format should be kept
out of Solaris, to make OS more independent of firmware and to
avoid legal issues related to using gnuefi to compile Solaris
binaries. So I decided to use elilo to load the Solaris multiboot
and ramdisk. The code changes are pretty straightforward. I added
a "multiboot" loader to elilo, making sure it's run before
"plain" elf loader. On the Solaris side, I modified multiboot
to disable BIOS calls, console I/O (yikes!), and modified the
kernel to use pci probe mechanism 1.
Console I/O?
So far so good. But what about console I/O?! Solaris only supports
vga/keyboard and isa serial ports as console devices. The iMac has
neither (truly legacy free). The first step was to cheat a little
bit. I modified elilo not to call ExitBootServices() so I could
get some early output in Solaris multiboot program using EFI
SimpleText service. It took me a while to figure out that SimpleText
stops working if IDT is reloaded or paging is enabled. After pulling
all the tricks I could think of, I still wasn't able to get the
Solaris banner out on the screen, pretty discouraging for a couple
of week's work.
Now I turned my attention of UGA, the EFI's replacement for VGA.
The EFI toolkit document refers to a Microsoft webpage describing
how to use UGA inside an OS kernel, but the webpage is nowhere to
be found. Then I found a Linux paper by Matthew Tolentino describing
a UGA implementation in Linux kernel. It was exactly what I was
looking for, but the amount of work of daunting. I sent email to
the author to see if the code was, by any chance, released (preferrably
under a BSD-like license), but it was not to be.
So I can't use the screen and I don't have a serial port. What else?
It happened that we have a contact at Apple who informed us that
the ICH7 chipset supports a USB debug controller port. This sounded
promising, but I wasn't able to find any debug device I can buy.
However, this gave me an idea. I could get a USB to serial cable
and redirect the Solaris console to the USB serial device. Although
the device doesn't work early in boot, I can still boot the system
up if the kernel "just worked".
I bought a USB serial cable from Walmart. The cable is made by
IOGear based on Prolific PL2303 chipset. There happens to be
a Solaris driver for it (usbsprl). I modified the Solaris consconfig_dacf
module to work with USB serial device and tried it on a PC that already
runs Solaris, the device worked fine. I was very happy and proceeded
to set up the software and hardware on the iMac. After elilo
printed the expected text on screen, I sat there, waiting anxious
waiting for output on the other end of the serial line... nothing
happened. The machine seems to have hung.
Desperation
I wasn't ready give up, not yet anyway. Since the machine appeared
to be hung, I tried some "blind" debugging. To do so, I inserted
a call to reset() in the kernel startup code to see if the reset
actually happens. By changing the location of the reset() call,
I might be able to find out when things went wrong.
I was pleasantly surprised to find that the kernel was running
fine, but the usb controller failed to attach, hence no console
output. My suspicion naturally fell on interrupt controller
programming and ACPI processing.
Checking the ACPI info, I noticed that iMac's ACPI memory region is
at 8F000 which the ACPICA (Solaris uses intel's ACPICA) expects it
to be between E0000 and FFFFF. Naturally, I modified ACPICA to
scan 8EFFF, but it didn't work. After consulting is ACPI experts
(Dana Myers and David Chieu), I decide to make a last ditch effort
to override the ACPI table. Jan has a second iMac running BootCamp
(legacy BIOS emulation). I captured the ACPI tables from BootCamp
and added them to the Solaris image (see blog by
David Chieu )
and tried booting again, it still didn't work.
At this point, I was ready to give up. Hopefully, the next ia32
platform with EFI will have VGA or serial port. There was one last
gleamer of hope, that is to workaround the interrupt issue by
running USB controller in polled mode. I went to our USB expert,
Artem Kachitchkin, who patiently offered some suggestions. I
modified uhci and ehci not to add interrupt handlers. Instead,
launch a kernel thread to call interrupt handlers every millisec.
With this change, I was finally able to get console output on
the iMac!
EFI, UGA, and USB debug device
It has been quite an experience to get Solaris up on EFI and
much work still lies ahead. Overall, I like the overall EFI
capability. The EFI shell appears more capable than the OpenBoot
Firmware on sparc. The UGA stuff is questionable at best; being
part of the BootService (instead of RunTime service), it's
pretty much useless for OS booting. The USB debug controller
sounds like a good idea, if debug hardware becomes available.
I hope other ia32 platforms with EFI firmware can keep some legacy
stuff around so that individual OS developers can work on them.
( May 02 2006, 12:00:00 PM PDT )
Permalink