Freeing the BIOS: Memory Init

Librem 13Intel has not published their Firmware Support Package for 5th-Gen Intel Processors yet, such as the Haswell-ULT and Broadwell CPUs. In order to ship Coreboot on the Librem 13 on time, the alternative is to achieve interoperability with the memory and PCH init code from the proprietary BIOS.

Background

The default for coreboot is to use the FSP binary blob for recent Intel CPUs. Vladimir Serbinenko and Damien Zammit have freed the memory init code for Sandy Bridge and some Ivy Bridge CPUs. Our goal is to eventually free the memory init code for 5th-Gen CPUs.

When Intel releases the FSP, we can use that. In the meantime, here is a guide to memory init for 5th-Gen Intel CPUs.

Cache As RAM

inteldieshotWhen an Intel CPU first boots, the memory controller is not set yet. The first part of coreboot, known as the ROM stage, must avoid saving any variables or using any stack. Cache as RAM gets coreboot to the next stage. This is sort of a hack: first the MSRs are configured and the cache lines are filled with zeros as if there were memory present, then Cache Disable in CR0 is set and cleared without invalidating cache with INVD. Proprietary BIOSes use the same trick. With Cache as RAM, regular C code can run.

Memory Init

After setting GPU and PCH BARs, coreboot can proceed to initialize actual memory. The Librem 13 v1 has DDR3L DRAM. Here is the “MemoryInit” PEI Module and NbPei PEIM that do the memory init for the Librem 13 v1: Memoryinit.zip

The FSP will contain essentially the same code (perhaps with minor bugfixes) packaged so that coreboot can call into it. Studying either binary blob should give the same information.

Caveat: The sequence of operations used by the proprietary BIOS for memory init is not a guarantee it will work flawlessly for coreboot. Vladimir Serbinenko and Damien Zammit have already encountered inconsistent behavior with their efforts. However, Purism is committed to freeing the BIOS, and this is the first step.

Free Software Tools To Dump a PEIM

PEI Modules are in PE format, also used by Windows .exe files. The primary difference between the two is that Windows .exe files use .dlls while PEI Modules use PPIs (PEI Module-to-PEI Module Interfaces); PEIMs are statically linked.

The assembler source code of NbPei.peim looks like this:

$ radare2 NbPei.peim
[0x00000438]> pD
   ;-- entry0:
   0x0438    56             push esi
   0x0439    8b74240c       mov esi, dword [esp + 0xc]
   0x043d    e802000000     call 0x444 ;first_fn1
   0x0442    5e             pop esi
   0x0443    c3             ret

first_fn1:
   0x0444    55             push ebp
   0x0445    8bec           mov ebp, esp
   0x0447    51             push ecx
   0x0448    8b06           mov eax, dword [esi]
   0x044a    53             push ebx
; Here is the first EFI system reference
   0x044b    8b5864         mov ebx, dword [eax + 0x64]
   0x044e    57             push edi
   0x044f    33ff           xor edi, edi
   0x0451    57             push edi
   0x0452    57             push edi
   0x0453    57             push edi
   0x0454    6801800600     push 0x68001
   0x0459    6a01           push 1
   0x045b    56             push esi
; Another EFI system reference
   0x045c    ff5058         call dword [eax + 0x58]
   0x045f    8b06           mov eax, dword [esi]
   0x0461    8d4dfc         lea ecx, [ebp - 4]
   0x0464    51             push ecx
   0x0465    6a10           push 0x10
   0x0467    6a06           push 6
   0x0469    56             push esi
   0x046a    897dfc         mov dword [ebp - 4], edi
; Another EFI system reference
   0x046d    ff5034         call dword [eax + 0x34]
   0x0470    83c428         add esp, 0x28
   0x0473    85c0           test eax, eax

This is a great place to introduce you to radare2, partially licensed under GPLv3. It does not seem like anyone has attempted to disassemble a PEIM with radare before, but IDA Scripts exist to resolve the constants into EFI System Table symbolic names.

That’s the next step, then: automatically resolve the constants into EFI System Table symbols and other tooling to automate radare.

Conclusions

The memory init code is a significant step toward successfully booting a fully Free Software laptop. As the code for 5th-gen Intel CPUs has not been released, all we have right now are binary blobs. If you have suggestions regarding our approach please contact us.