[EXTERNAL] Re: Proposal for a New Command to U-Boot Fuse Programming

Harsha Vardhan V M h-vm at ti.com
Fri Jan 24 10:01:15 CET 2025



On 22/01/25 22:52, Tom Rini wrote:
> On Fri, Jan 10, 2025 at 11:12:47AM +0530, Harsha Vardhan V M wrote:
>>
>>
>> On 07/01/25 03:53, Tom Rini wrote:
>>> On Mon, Jan 06, 2025 at 12:06:25PM +0530, Harsha Vardhan V M wrote:
>>>
>>>> I would like to propose a new command for U-Boot's fuse programming
>>>> functionality to address the challenges posed by the current implementation.
>>>> While the existing fuse prog command works well for programming individual
>>>> fuse values, it becomes cumbersome especially when dealing with large-scale
>>>> programming requirements.
>>>>
>>>> Current Command: fuse prog [-y] <bank> <word> <hexval> [<hexval>...]
>>>>
>>>> This command programs one or more fuse words starting from a specific <bank>
>>>> and <word> with the hex values given as input.
>>>>
>>>> While functional, it lacks the efficiency and robustness needed for
>>>> programming a significant number of fuses or handling structured fuse
>>>> configuration data. Repeatedly specifying values for each fuse bank and word
>>>> is not only time-consuming but also prone to errors during manual input or
>>>> scripting. This approach does not leverage the ability to process
>>>> pre-structured data in memory. For users with complex programming needs, the
>>>> current method becomes an obstacle rather than a tool.
>>>>
>>>> Proposed Command: fuse writebuff
>>>
>>> It would be good to provide some documentation links to the fuses that
>>> you're wanting to deal with. What we have now works on a number of
>>> diverse SoCs, even if for some cases it might be best to write a
>>> script that's run rather than copy/paste things live. Any sort of new
>>> mechanism needs to get feedback from users at other semiconductor
>>> vendors to make sure it's generic enough for everyones needs. Thanks.
>>>
>>
>> Hi Tom and Simon,
>>
>> The buffer is not a text file. It is a structure in memory. The buffer is
>> structured to contain all necessary information for the fuse programming
>> process. This can include metadata, fuse programming data etc. The exact
>> structure of the buffer can determined by the command_id, which provides
>> flexibility for supporting different use cases. The memory buffer is
>> typically prepared in user-space code or a script and loaded in memory
>> before invoking the fuse writebuff command. It is not stored as a text file
>> or any other file format, as the command operates directly on memory
>> addresses.
>>
>> Example of a buffer:
>>
>> struct fuse_buffer {
>>      struct fuse_mpkh smpkh;
>>      struct fuse_msv msv;
>>      struct fuse_key_cnt key_cnt;
>>      u8 buffer_hash[64];
>> };
>>
>> This fuse_buffer struct will be loaded in memory containing all the
>> necessary information for fuse programming.
>>
>> struct fuse_mpkh {
>>      u8 mpkh[64]; // public key hash
>>      u8 bch[8];
>>      u32 attributes; // read-protect, write-protect, override, active flag
>>      u32 reserved[2];
>> };
>> struct fuse_msv {
>>      u32 msv_with_bch; //model specific value
>>      u32 attributes;
>>      u32 reserved[2];
>> };
>> struct fuse_key_cnt {
>>      u32 key_cnt; //key count
>>      u32 attributes;
>>      u32 reserved[2];
>> };
>>
>> -> eFUSE layout is abstract and isn't public as its programming and layout
>> itself is security sensitive (it has authentication and decryption keys
>> etc). So, fuse prog doesn't work as there is no "banks/offset" here.
>> -> Platform Security Core running Secure SW exposes APIs through which these
>> Keys and its attributes can be programmed. Whole content maybe encrypted for
>> enhanced security on unsecure factory floor.
>> -> There is a definite order in which these fields needs to be programmed.
>>
>> Its possible to break the struct into 32bit values and send them across but
>> we would end up with ~30 odd fuse prog cmds which is inefficient and error
>> prone.
>> It would be hard on secure core to also ensure correctness of operations
>> against all sorts of silly errors (such of accidentally skipping a word or
>> mess up ordering) which can render Silicon unusable.
>>
>> So passing a opaque pointer with a command_id to Secure core is all that
>> fuse cmd needs to do which is what writebuff supports.
>>
>> This can be extended to any vendor; It's just an opaque pointer handoff. I
>> see at least one other vendor do it in custom way:
>> arch/arm/mach-imx/cmd_dek.c which could benefit from this new cmd fuse
>> writebuff.
>>
>> Here’s how the fuse writebuff command works in a typical flow:
>> 1. Buffer Preparation: Vendors or developers create a complete buffer (e.g.,
>> key.bin) containing all fuse programming data using vendor-specific scripts
>> or tools and copied to SD card.
>> 2. The buffer is loaded into memory using commands like:
>> fatload mmc 1 0x80000000 key.bin
>> 3. The fuse writebuff command passes the memory address (0x80000000) and
>> command_id to the secure core:
>> fuse writebuff <command_id> 0x80000000
>> 4. The secure core receives the memory address as a pointer and validates,
>> interprets it based on the command_id and then programs the fuses.
> 
> To summarize what we talked about on a call, I would like to see either:
> 1) Work with arch/arm/mach-imx/cmd_dek.c and use that as the base of
> some new generic command that deals with SoC-specific fuse
> configurations that are handled via security processor.
Hi Tom,

1) I have looked at arch/arm/mach-imx/cmd_dek.c. The underlying 
implementation data structure is very specific to the vendor and how iMX 
devices are configured. The other vendors would also differ in their 
structures and SoC-specific fuse configurations, so I don't see a way to 
use this cmd_dek.c as the base and then abstract, create a new command 
out of it.

> OR
> 2) Create a new command (that should be in cmd/ti/) for handling the K3
> fuses, if we cannot make something abstract enough to handle this
> concept on multiple vendors while having any sort of useful code re-use.

2) In this case, I would like to add the fuse writebuff command for TI’s 
K3 architecture in cmd/ti/k3_fuse.c. And the command will look like

fuse writebuff <command_id> <addr>

However, I would still like to place the fuse writebuff command in 
cmd/fuse.c as a generic interface because the parameters command_id and 
an opaque pointer handoff provides a mechanism for the secure core to 
interpret buffers differently based on vendor or use case.

Thanks,
Harsha


More information about the U-Boot mailing list