Flashing Libreboot, blob free booting and why hardware security is hard – Part two
Overview
Part two; Flashing Libreboot.
In this post, we will be walking through GPIO pin manipulation to unlock all the Intel Flash Descriptor regions via software and defeating any other protections in place.
No external flashing hardware or disassembly needed!
Flashing Libreboot
Now that we have the ROM's built, it's time to flash them.
You will recall one of the reasons we used the E6400 is that we can make use of internal flashing vs the need for external hardware to flash the machine.
This is made possible by some very amazing work by Nicholas Chin where he has detailed a tool he wrote to set various GPIO pins that he manipulates via memory mapping to set certain bits into a desired state to enable the flash to be unlocked.
Unlock the flash
First we need to build the unlock tool, run the following commands:
# cd util/e6400-flash-unlock
# make
NOTE the following steps must be run as root.
Next, we need to run the utility the first time to override the Flash Descriptor permissions:
# ./e6400_flash_unlock
Flash Descriptor Override enabled. Shut down now. The EC will auto-boot the system and set the override.
Upon boot, re-run this utility to unlock flash.
#
On the E6400, the GPIO pin HDA\_DOCK\_EN/GPIO33
if pulled low on boot will enable full R/W to all the Intel Flash descriptor regions.
This pin is connected to the embedded controller on the E6400. So this script manipulate the EC to pull the GPIO pin low on reboot!
However… There is more needed…
Intel has another layer of protection called the BIOS Lock Enable
(BLE).
Dell has set this to 1
so we can not change the setting of BIOS Write Enable
(BIOSWE) to enable writing to the flash.
Once the BLE is set to 1
it can not be disabled, ouch now what?
Let's reboot and see.
Next, Issue a shutdown command, and your laptop will automatically power on after it shuts down.
Next, we run the tool again to disable the generation of System Management Interrupts via setting the Global SMI Enable
bit.
# ./e6400_flash_unlock
SMIs disabled. Internal flashing should work now.
After flashing, re-run this utility to enable SMIs.
(shutdown is buggy when SMIs are disabled)
#
What happens here is a showcase of why complex systems are hard.
In this case Dell forgot to set the SMI\_LOCK
bit (Unset/set to 0), this will give us the ability to toggle the GBL\_SMI\_EN
bit enabling us to disable SMI (System Management Interrupt) and thus finally bypassing all protections to write to the entire flash.
If the SMI\_LOCK
bit was set to 1
the following manipulation would not be possible. Also, the SMI\_LOCK
bit can NOT be changed once set.
We need to disable SMI generation so that the processor will not enter SMM (Systems Management Mode), in this mode the processor reads code from the BIOS, part of that code checks the BIOSWE
bit, once SMM is done running its code it sets the BIOSWE
bit and hands back to the Operating System with the BIOSWE
bit set to 1
.
Thus, we need to prevent the system issuing SMI so that SMM code is never executed. Giving us all the access we need and all protections disabled, the entire flash is now ours for the taking.
Now we can read and write to all flash regions, as you can see(The following output is taken from running the flashrom tool):
FREG0: Flash Descriptor region (0x00000000-0x00000fff) is read-write.
FREG1: BIOS region (0x00260000-0x003fffff) is read-write.
FREG2: Management Engine region (0x0000b000-0x0025ffff) is read-write.
FREG3: Gigabit Ethernet region (0x00001000-0x00002fff) is read-write.
FREG4: Platform Data region (0x00003000-0x0000afff) is read-write.
Now that all regions are unlocked and all protections are disabled, we can take a full backup/dump of the entire flash.
You can use this image to restore the original Dell BIOS.
Take a backup by running the following:
# flashrom -p internal -r -dell-original-bios-backup.rom
If everything went as expected, you should see the following as the last few lines of the command output:
Reading flash... done.
#
Save this image on a USB stick or some other media.
Next, it's finally time to flash Coreboot. Issue the following command:
flashrom -p internal -w /home/build/lbmk/bin/e6400_4mb/seabios_e6400_4mb_libgfxinit_corebootfb.rom
You may need to change the path to your Coreboot ROM image, in the above command.
If that went well, you will see the following last few lines from the flashrom tool:
Reading old flash chip contents... done.
Erasing and writing flash chip... Erase/write done.
Verifying flash... VERIFIED.
#
Now that we have a backup and have flashed our new libre ROM, it's time to re-enable the global SMI bit.
To do that, just re-run the unlock tool:
# ./e6400_flash_unlock
SMIs enabled, you can now shutdown the system.
#
You can now reboot into your freshly flashed Coreboot ROM.
You can use this tool as many times as you like to unlock the flash and update images, just use the same sequence as listed above.
Furthermore, you can now install your choice of Linux(or BSD) to the machine.
After installing, you can see the DMI information contains details about Coreboot(obtained via dmidecode):
Handle 0x0000, DMI type 0, 26 bytes
BIOS Information
Vendor: coreboot
Version: 4.20-1013-g3145b430ea6c
Release Date: 09/04/2023
ROM Size: 4 MB
Characteristics:
PCI is supported
PC Card (PCMCIA) is supported
BIOS is upgradeable
Selectable boot is supported
ACPI is supported
Targeted content distribution is supported
BIOS Revision: 4.20
Firmware Revision: 0.0
Nice, we finally have a backdoor free, fully open source boot stack compiled from source and installed.
Grub resolution
If you notice that GRUB seems stuck in 640x480
resolution.
You need to set the GRUB gfxmode to 1366x768x32
.
For Debian, edit the /etc/default/grub
and set GRUB_GFXMODE
.
Then run update-grub
.
Other distributions are out of scope.