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

Harsha Vardhan V M h-vm at ti.com
Thu Jan 30 09:36:07 CET 2025



On 29/01/25 03:52, Tom Rini wrote:
> On Mon, Jan 27, 2025 at 04:22:36PM +0530, Harsha Vardhan V M wrote:
>>
>>
>> On 25/01/25 00:59, Tom Rini wrote:
>>> On Fri, Jan 24, 2025 at 02:31:15PM +0530, Harsha Vardhan V M wrote:
>>>>
>>>>
>>>> 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.
>>>
>>> This I guess is my confusion. If we can't abstract cmd_dek.c and the
>>> underlying i.MX specific parts to be supported in "fuse writebuff ..."
>>> what is the non-K3 (or better still, non-TI) abstraction for what you're
>>> proposing?
>>>
>> Hi Tom,
>> There are two types of fuse programming flows;
>> a) Where the fuse layout is known to U-Boot -> fuse cmd options support this
>> flow today
>> b) Where fuse cmd is abstracted from U-Boot -> needs a co-processor to proxy
>> the programming
>>
>> For b) the fuse layout is virtualized via a "vendor-specific" structure
>> which is generated offline (typically with GUI tools) and then loaded to
>> memory from a file on SD card . This pointer would then be relayed to Co
>> processor as a IPC call...
>>
>> So, whats common b/w cmd_dek.c and TI's fuse cmd -> loading opaque struct to
>> memory and then passing it to Secure co-processor along with one or more
>> command identifiers which will serve as hint for such secure co-processor.
>> "fuse writebuff" tries to abstract essentially this: take a cmd_id and file
>> pointer from fuse cmd and pass to it Vendor specific backend. I know its not
>> a lot but frontend tools used to flash the devices can still make the most
>> of it with simple vendor neutral abstractions than needing to know custom
>> command for each vendor.
>>
>> What cannot be abstracted is:
>> a) struct of the file,
>> b) common definition of command Id
>> c) IPC mechanisms
>>
>> Unfortunately all the above 3 are tightly coupled to co-processor on the
>> other end which most likely is immutable for most SoCs...
> 
> So what I'm missing is why we can't have "fusebuf" as the top level
> command, or "fuse writebuf <vendor> <address>" and then yes, leave the
> vendor specific parts to each vendor to implement?
> 

Hi Tom,

The "fuse writebuff <vendor> <address>" option sounds good to me. I'd 
like to understand how you are envisioning the <vendor> parameter to be 
used in this context and how the backend should handle it. Would 
appreciate your thoughts on this.

Thanks,
Harsha


More information about the U-Boot mailing list