On Thu, Jan 30, 2025 at 02:06:07PM +0530, Harsha Vardhan V M wrote:
> 
> 
> 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.

Probably <vendor> should be a string, and based on that call the
appropriate SoC handler.

-- 
Tom

Attachment: signature.asc
Description: PGP signature

Reply via email to