I have successfully enabled the firmware TPM (fTPM) within the J4105 on my ODROID-H2 (rev. B), with my OS interacting with the TPM 2.0 pseudo-device. Although my use-cases are around remote attestation, given the recent Windows 11 announcement I expect there would be at least one other person wanting this functionality too so I figured I'd sit down and write this up with screenshots and all.
If any ODROID staff are reading: I have no idea how much control you have over hiding/revealing items in the AMI/Aptio BIOS UI, but if you can, can you please reveal the
Advanced > Trusted Computing
menu? It's the Security Device Support
menu item within it that I changed from Disable to Enable to get this working -- no other changes were needed as the defaults for all other settings are already perfect. The menu contains other useful settings such as TPM clearing operations, hence the request for that menu specifically.---------------------------------------------------------------------------------------------------------------------------
Right-o, here we go. I've broken this post up into two sections:
- The first section contains steps on how to enable it (aka "just tell me how to do it already").
- The second section is how I discovered what bits to flip in order to get it working. I've included the second section because I am, and any sane person should be, always wary whenever a stranger on the Internet tells them to flip raw, unlabelled bits in SPI FLASH using a tool they've never heard of before.
To be clear, this approach doesn't mutate/mod the BIOS ROM, but instead mutates a byte within one of the UEFI Variables in NVRAM used to store the settings you see in the BIOS UI. This gives the best of both worlds: running a stock, signed, official BIOS ROM from the OEM, and having TPM 2.0 functionality enabled persistently (until the next BIOS upgrade or BIOS config is wiped). In other words, the BIOS UI would change the same byte in the same UEFI Variable to the same value had the menu item not been hidden.
There is one downside to all of this: since all TPM sections are needlessly hidden in the BIOS UI, toggling options such as issuing a TPM Clear operation or forcing TPM 1.2 mode are only possible using the same technique: discovering which byte offset in which UEFI Variable to toggle and to toggle it accordingly. You're very much on your own if you need to go down this path.
---------------------------------------------------------------------------------------------------------------------------
How to Enable TPM 2.0
Disclaimer: Changing BIOS settings in this way is very risky, and depends on your competence, board revision, BIOS version, and the angle of the sun when you look outside. I am not responsible for anything you do -- be it following instructions here or with life in general. These instructions are only for people who have done this before and know what they're doing, or for people that were planning on binning their ODROID-H2 anyway and are happy to try bricking it before doing so. Seriously, if you feel uncomfortable, concerned or anxious about changing BIOS settings in this way, you should instead wait for an official BIOS ROM containing TPM 2.0 support; don't let your impatience make life hard(er).
These instructions work on my ODROID-H2 Rev. B board running GLK-SF BIOS version 1.22. I have not tested this on any other board revisions or BIOS versions, including all GLK-ESF versions. If there's sufficient demand I'm happy to try out different GLK-SF BIOS versions on my Rev. B board. I'll also edit/update this post if anyone attempts this on their H2+ board (or with any GLK-ESF versions with H2 Net Card) as I don't own any.
For those with GLK-ESF ROMs, or those wanting to use a non-1.22 GLK-SF ROM, the process should be very similar with a potentially different byte offset in the same or different UEFI Variable in the NVRAM. Have a read through the second section below to discover this for yourself with your downloaded ROM. The steps below assume the ODROID-H2 board is a Rev. B model running GLK-SF BIOS version 1.22.
- Follow the official ODROID BIOS update steps to prepare a USB thumb drive with GLK-SF BIOS version 1.22. The EFI Shell is what's actually needed here, not any BIOS ROMs, and since the ODROID folks provide it in their ROMs, it's just the safest and most convenient way to get it.
- Download the RU 5.20.0328 tool from its official website, and copy the
RU.EFI
file onto the USB thumb drive in the root directory. James, the tool's creator, always posts each ZIP file's password alongside its URL at the bottom of every release/blog post, so just read the ending properly and you can't miss it. - Reboot into the BIOS UI, and note the BIOS type (GLK-SF or GLK-ESF) and the version number installed (eg. 1.22). Head over to the
Save & Exit
tab andRestore Defaults
, thenSave Changes and Reset
. - Reboot back into the BIOS UI and head over to the
Save & Exit
tab, and force the next boot to be from the USB thumb drive using theBoot Override
section at the bottom. - If you're not already on GLK-SF 1.22, now's the time to follow the official BIOS update steps to do so. Don't continue on until you've finished the BIOS update process to 1.22, including the power-cycle step at the end. Boot back into the USB thumb drive's EFI shell and continue on to the next step.
- Run
RU.EFI
from the EFI shell. One note about RU: it sometimes hangs randomly. I've tested this walkthrough many times before posting, and about 50% of the time the RU binary hangs at random points. This isn't anything to fear since it doesn't write or mutate anything about your system until you tell it to. If it hangs, don't sweat and simply reboot back into the EFI shell and try again. For what it's worth, I've tried versions 5.28.0397 and 5.20.0328 and found that the latter was more reliable, hence why I'm recommending it. Your mileage may vary. I'd be interested to know if anyone noticed any differences with an Ethernet cable plugged/unplugged.
- Within the RU tool, press
ALT+C
to open the Config menu at the top, and navigate toUEFI Variable
. This was the most frequent place that RU hung for me.
- Scroll down the laundry list of UEFI Variables until you find one called
Setup
whose GUID starts withEC87D643
and open it up. There are two called Setup - triple check you've selected the one with the right GUID.
- Confirm that you've opened the right item -- at the top it should report the
Size
to be0x0631
bytes.
- The byte to change is at offset
0xE
; that's the first row, second from the right. It should read00
. Type01
and press ENTER to finish editing. Double check the surrounding bytes are unmodified, with only0xE
being changed from00
to01
.
- Press CTRL+W to save, and ensure the RU tool doesn't display any error messages.
- You can now unplug the USB thumb drive and power cycle your machine. Allow it to boot up in whichever OS you have installed.
- For Linux installations, run
dmesg | grep -i tpm
to confirm that Linux can now see the TPM. You can also runtpm2_getrandom 20
to have the TPM generate random bytes for you; this is the simplest way to make the TPM actually do something and thereby confirm that it works. - For Windows installations, I'll leave it to someone else to provide validation steps.
---------------------------------------------------------------------------------------------------------------------------
Discovery and Repro Steps
The steps below reveal both hidden BIOS UI menu items and the NVRAM storage locations of their values as human-readable EFI bytecode.
- Download the UEFITool from LongSoft's github repo. You can compile it yourself from source if you want, but the pre-built binaries contain GUID->Text mappings that makes life easier later on in the process.
- Download the Universal-IFR-Extractor from LongSoft's github repo. For Windows folks, it'd be easier to grab a pre-built binary, but for Linux folks it's easier to build it from source with
g++ -I. -o ifr-extractor main-cli.cpp UEFI.cpp EFI.cpp
. - Download whichever of the official ODROID BIOS ROMs, and extract the
bios.bin
file within. - Open UEFITool and load the
bios.bin
file. - Within the tool, search for the
899407D7-99FE-43D8-9A21-79EC328CAC21
File, select thePE32 image section
section within it, right-click and Extract body. The screenshot below is from the GLK-SF 1.22bios.bin
file.
- Close UEFITool, and run the IFR extractor to generate the output file. (eg.
ifr-extractor setup.bin setup.ifr
or whatever the name of your IFR's executable is). - Grab a coffee or a beer, and get ready to sit down and do some light reading of translated-for-humans EFI bytecode.
- Search through the IFR file for
Security Device Support
. You'll notice there's aSuppress If True
statement before it: anyone familiar with coding will recognise this as the classicif (0) {...}
trick. No matter what, this BIOS UI menu item, and many others above and below, will never see the light of day. - Observe the
VarStore
andVarOffset
for theSecurity Device Support
menu item. On the GLK-SF 1.22 versionVarStore
is0x1
, andVarOffset
is0xE
. The EFI bytecode breakdown also shows thatDisabled
is the default option and has Value0x00
, whilstEnabled
has value0x01
. TheSize
for this menu item is only one byte, so we don't need to worry about endianness.Code: Select all
One Of: Security Device Support, VarStoreInfo (VarOffset/VarName): 0xE, VarStore: 0x1, QuestionId: 0x22, Size: 1, Min: 0x0, Max 0x1, Step: 0x0 {05 91 75 04 97 04 22 00 01 00 0E 00 10 10 00 01 00} One Of Option: Disable, Value (8 bit): 0x0 (default) {09 07 7D 04 30 00 00} One Of Option: Enable, Value (8 bit): 0x1 {09 07 7C 04 00 00 01} End One Of {29 02}
- The
VarStore
value isn't enough on its own though; UEFI Variables are stored as GUIDs, not as integers. Scroll up towards the top of the IFR dump and look for theVarStore
mapping for1
and note down the GUID. On GLK-SF 1.22 the GUID isEC87D643-EBA4-4BB5-A1E5-3F3E36B20DA9
and is0x631
bytes in size.Code: Select all
VarStore: VarStoreId: 0x1 [EC87D643-EBA4-4BB5-A1E5-3F3E36B20DA9], Size: 0x631, Name: Setup {24 1C 43 D6 87 EC A4 EB B5 4B A1 E5 3F 3E 36 B2 0D A9 01 00 31 06 53 65 74 75 70 00}
- Now we have the UEFI Variable GUID (
EC87D643-EBA4-4BB5-A1E5-3F3E36B20DA9
), the byte offset (0x000E
), and the value to change it to (0x01
). - At this point you can now refer to the first section above: open up the RU tool, navigate to UEFI Variables, and be on the lookout for the GUID that corresponds to your
VarStore
, skip to the offset given inVarOffset
and change it to the desired value. - I've been able to successfully flip some other hidden menu items in this way (such as TPM Clear), but am not going to write a walk-through for each and every hidden menu item; I'd rather the see the ODROID folks reveal these benign and safe menu items.
Edit #1: Fixed up some formatting and grammar to make life easier for non-English readers.