Flashing Libreboot, blob free booting and why hardware security is hard – Part two
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!
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.
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\_ENbit enabling us to disable SMI (System Management Interrupt) and thus finally bypassing all protections to write to the entire flash.
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
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.
If you notice that GRUB seems stuck in
You need to set the GRUB gfxmode to
For Debian, edit the
/etc/default/grub and set
Other distributions are out of scope.