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