Matthew Garrett ([personal profile] mjg59) wrote,
@ 2011-05-25 11:45 am UTC
  • Previous Entry
  • Add to Memories
  • Tell someone about this!
  • Next Entry
Entry tags:advogato, fedora
I wrote about some EFI implementation issues I'd seen on Macs a while back. Shortly afterwards we started seeing approximately identical bugs on some Intel reference platforms, and fixing it actually became more of a priority.

The fundamental problem is the same. We take the EFI memory map, identify the virtual addresses of the regions that will be required for runtime (mapping them into virtual address space if needed) and then call the firmware's SetVirtualAddressMap() implementation in order to let the firmware convert all its pointers. Sadly it seems that some firmware implementations call into sections of boot services code to do this, which is unfortunate because we've already taken that back to use as RAM. So, given that this is clearly against the spec, how does it ever work?

The tediously dull version is that Linux typically calls SetVirtualAddressMap() in the kernel, and everyone else does it in their bootloaders. The bootloader hasn't set up NX bits or anything, so it just happens to work there. We could just do it in the bootloader in Linux, but that makes doing things like kernel address space randomisation trickier, so it's not the favoured approach. So, instead, we can probably just reserve those ranges until after we've switched to virtual mode, and make sure the pages are executable. This ought to land in 2.6.40, or whatever it ends up being called.

(The alternative approach, of just never transitioning to physical mode, turns out to mysteriously fail on various machines. Calls to SetVariable() just give errors. We just don't know)

That still leaves the problem of SetVariable() on the test Mac trying to access a random address. That one turned out to be easier. There's 2MB of flash at the top of physical address space, and this was being presented as being broken into four separate EFI regions. While physically contiguous, Linux was mapping these to discontiguous virtual addresses. Apple's firmware appeared to assume that a pointer into one region could just be incremented into another. So because it's still easier to change the kernel than change Apple, 2.6.39 merges these regions to ensure they're contiguous.

Remaining problems include some machines seemingly not booting if they have 4GB of RAM or more and this Apple failing to communicate with its panel over the eDP auxchannel. Anyone got any idea how to dump the bios compatibility module out of a running EFI session?


(Read 9 comments) - (Post a new comment)
(Flat) (Top-level comments only)

ignore BIOS^wEFI


(Anonymous)
2011-05-26 03:09 am UTC (link)
Is there a way you can ignore the firmware altogether? Seems like working around bugs in BIOS and EFI implementations is a losing game.

(Reply to this)  (Thread


Re: ignore BIOS^wEFI


[personal profile] mjg59
2011-05-26 12:32 pm UTC (link)
We could target the hardware directly, but that would mean a separate kernel for every single different machine. Probably not practical.

(Reply to this)  (Thread from start)  (Parent)  (Thread


Re: ignore BIOS^wEFI


(Anonymous)
2011-05-26 01:41 pm UTC (link)
I don't really get this. Linux and Windows have been bypassing the BIOS ever since 32-bit kernels appeared, yet the same kernel appears to work on every piece of hardware.

Are you implying that x86 hardware vendors are heading towards the same segmentation as in the ARM world, using EFI as a "we're still compatible" excuse? Sadly, it wouldn't even surprise me. But it would motivate me to invest heavily in companies supporting coreboot, such as AMD.

(Reply to this)  (Thread from start)  (Parent)  (Thread


Re: ignore BIOS^wEFI


[personal profile] mjg59
2011-05-26 01:56 pm UTC (link)
We're completely unable to run on x86 without the BIOS. We depend on it for the initial memory map, which we need in order not to tread on bits of address space that contain magic hardware. It provides the ACPI tables that we need in order to manage various bits of hardware at runtime. It gives us the information about the video hardware that's necessary in order to know which outputs are present and what the hardware can be clocked at.

The only thing EFI adds is some additional runtime services. The only one of those we actually need is the ability to set nvram variables. If we didn't have EFI we'd need to know the location of the flash and we'd need to know the internal storage format, and that's not something that's standardised.

(Reply to this)  (Thread from start)  (Parent



(Read 9 comments) - (Post a new comment)
(Flat) (Top-level comments only)