Hi Cédric, Thank you for your comments and suggestions. I’ll start by reviewing the changes in commit ebc29e1beab0. At the moment, I don’t have another example of a device that is accessed through an external bus, but I’ll look into it and see what I can find.
Best Regards, Kane > -----Original Message----- > From: Cédric Le Goater <c...@kaod.org> > Sent: Monday, April 7, 2025 5:55 PM > To: Kane Chen <kane_c...@aspeedtech.com>; Philippe Mathieu-Daudé > <phi...@linaro.org>; Peter Maydell <peter.mayd...@linaro.org>; Steven Lee > <steven_...@aspeedtech.com>; Troy Lee <leet...@gmail.com>; Jamin Lin > <jamin_...@aspeedtech.com>; Andrew Jeffery > <and...@codeconstruct.com.au>; Joel Stanley <j...@jms.id.au>; open > list:ASPEED BMCs <qemu-...@nongnu.org>; open list:All patches CC here > <qemu-devel@nongnu.org>; qemu-block <qemu-bl...@nongnu.org>; Markus > Armbruster <arm...@redhat.com> > Cc: Troy Lee <troy_...@aspeedtech.com> > Subject: Re: [PATCH v1 0/1] hw/misc/aspeed_sbc: Implement OTP memory and > controller > > Hello Kane, > > + Markus (for ebc29e1beab0 implementation) > > On 4/7/25 09:33, Kane Chen wrote: > > Hi Cédric/Philippe, > > > > OTP (One-Time Programmable) memory is a type of non-volatile memory in > > which each bit can be programmed only once. It is typically used to > > store critical and permanent information, such as the chip ID and > > secure boot keys. The structure and behavior of OTP memory are > > consistent across both the AST1030 and AST2600 platforms. > > > > As Philippe pointed out, this proposal models the OTP memory as a > > flash device and utilizes a block backend for persistent storage. In > > contrast, existing implementations such as NPCM7xxOTPState, > > BCM2835OTPState, and SiFiveUOTPState expose OTP memory via MMIO and > > always initialize it in a blank state. > > AFAIU, Aspeed SBC is also MMIO based or is there another device, an eeprom, > accessible through an external bus ? How is it implemented in HW ? > > > The goal of this design is to > > allow the guest system to boot with a pre-configured OTP memory state. > > Yes. This is a valid request. It's not the first time we've had this kind of > requests. > The initial content of EEPROM devices are an example and some machines, > like the rainier, have a lot. > > If the device can be defined on the command line, like would be an EEPROM > device attached to an I2C bus or a flash device attached to a SPI bus, we can > use a 'drive' property. Something like : > > qemu-system-arm -M ast2600-evb \ > -blockdev node-name=fmc0,driver=file,filename=/path/to/fmc0.img \ > -device mx66u51235f,bus=ssi.0,cs=0x0,drive=fmc0 \ > -blockdev node-name=fmc1,driver=file,filename=/path/to/fmc1.img \ > -device mx66u51235f,bus=ssi.0,cs=0x1,drive=fmc1 \ > -blockdev node-name=spi1,driver=file,filename=/path/to/spi1.img \ > -device mx66u51235f,cs=0x0,bus=ssi.1,drive=spi1 \ > ... > > However, the Aspeed SBC device is a platform device and it makes things more > complex : it can not be created on the command line, it is directly created by > the machine and the soc and passing device properties to specify a blockdev it > is not possible : > > qemu-system-arm -M ast2600-evb \ > -blockdev > node-name=otpmem,driver=file,filename=/path/to/otpmem.img \ > -device aspeed-sbc,drive=otpmem \ > ... > > > > To support this, the OTP memory is backed by a file, simulating > > persistent flash behavior. > > The idea is good but the implementation is problematic. > > +static BlockBackend *init_otpmem(int64_t size_bytes) > +{ > + Error *local_err = NULL; > + BlockDriverState *bs = NULL; > + BlockBackend *blk = NULL; > + bool image_created = false; > + QDict *options; > + uint32_t i, odd_def = 0xffffffff, even_def = 0, *def; > + > + if (!g_file_test(OTP_FILE_PATH, G_FILE_TEST_EXISTS)) { > + bdrv_img_create(OTP_FILE_PATH, "raw", NULL, NULL, > + NULL, size_bytes, 0, true, &local_err); > + if (local_err) { > + qemu_log_mask(LOG_GUEST_ERROR, > + "%s: Failed to create image %s: %s\n", > + __func__, OTP_FILE_PATH, > + error_get_pretty(local_err)); > + error_free(local_err); > + return NULL; > + } > + image_created = true; > + } > + > + blk = blk_new(qemu_get_aio_context(), > + BLK_PERM_CONSISTENT_READ | > BLK_PERM_WRITE, > + 0); > + if (!blk) { > + qemu_log_mask(LOG_GUEST_ERROR, > + "%s: Failed to create BlockBackend\n", > + __func__); > + return NULL; > + } > + > + options = qdict_new(); > + qdict_put_str(options, "driver", "raw"); > + bs = bdrv_open(OTP_FILE_PATH, NULL, options, BDRV_O_RDWR, > &local_err); > + if (local_err) { > + qemu_log_mask(LOG_GUEST_ERROR, > + "%s: Failed to create OTP memory, err = > %s\n", > + __func__, error_get_pretty(local_err)); > + blk_unref(blk); > + error_free(local_err); > + return NULL; > + } > + > + blk_insert_bs(blk, bs, &local_err); > + if (local_err) { > + qemu_log_mask(LOG_GUEST_ERROR, > + "%s: Failed to insert OTP memory to SBC, > err = %s\n", > + __func__, error_get_pretty(local_err)); > + bdrv_unref(bs); > + blk_unref(blk); > + error_free(local_err); > + return NULL; > + } > + bdrv_unref(bs); > ... > > IMO, this is low level block code that a device model shouldn't have to deal > with. A 'drive' should be used instead. Now, if the qemu-block maintainers are > OK with it, we need their approval. > > > > The OTP memory access flow is as follows: > > 1. The guest issues a read or write OTP command to the Secure Boot > > Controller (SBC) > > 2. The SBC triggers the corresponding operation in the OTP controller > > 3. The SBC returns the result to the guest > > > > Since the guest interacts with OTP memory exclusively through the SBC, > > the OTP logic is implemented within aspeed_sbc.c. > > > > If there are existing architectural guidelines or design patterns that > > should be followed for modeling OTP devices, I would greatly > > appreciate your feedback. I am happy to revise the implementation > > accordingly and submit updated patches for further review. > > Adding a 'drive' property to the aspeed-sbc model shouldn't change too much > the proposal and it will remove the init_otpmem() routine, which is > problematic. > > Then, we need to find a way to set the 'drive' property of the aspeed-sbc > model. > I suggest using the same method of the edk2 flash devices of the q35 machine. > See ebc29e1beab0. Setting a machine option would set the drive. Something > like : > > qemu-system-arm -M ast2600-evb,otpmem=otpmem-drive \ > -blockdev > node-name=otpmem,driver=file,filename=/path/to/otpmem.img \ > ... > > This machine option would only be defined for machine types needing it. > > Thanks, > > C. > > > > > > > Thanks for your comments and review. > > > > Best Regards, > > Kane > > > >> -----Original Message----- > >> From: Cédric Le Goater <c...@kaod.org> > >> Sent: Friday, April 4, 2025 9:54 PM > >> To: Philippe Mathieu-Daudé <phi...@linaro.org>; Kane Chen > >> <kane_c...@aspeedtech.com>; Peter Maydell <peter.mayd...@linaro.org>; > >> Steven Lee <steven_...@aspeedtech.com>; Troy Lee > <leet...@gmail.com>; > >> Jamin Lin <jamin_...@aspeedtech.com>; Andrew Jeffery > >> <and...@codeconstruct.com.au>; Joel Stanley <j...@jms.id.au>; open > >> list:ASPEED BMCs <qemu-...@nongnu.org>; open list:All patches CC here > >> <qemu-devel@nongnu.org>; qemu-block <qemu-bl...@nongnu.org> > >> Cc: Troy Lee <troy_...@aspeedtech.com> > >> Subject: Re: [PATCH v1 0/1] hw/misc/aspeed_sbc: Implement OTP memory > >> and controller > >> > >> On 4/4/25 15:00, Philippe Mathieu-Daudé wrote: > >>> +qemu-block@ > >>> > >>> On 4/4/25 14:06, Cédric Le Goater wrote: > >>>> Hello, > >>>> > >>>> On 4/2/25 11:14, Kane-Chen-AS wrote: > >>>>> This patch introduces part of the Secure Boot Controller device, > >>>>> which consists of several sub-components, including an OTP memory, > >>>>> OTP controller, cryptographic engine, and boot controller. > >>>>> > >>>>> In this version, the implementation includes the OTP memory and > >>>>> its controller. The OTP memory can be programmed from within the > >>>>> guest OS via a software utility. > >>>> > >>>> > >>>> What is the OTP memory ? An external flash device or built-in SRAM ? > >>>> If the latter, I suggest using an allocated buffer under the SBC > >>>> model and avoid the complexity of the BlockBackend implementation > >>>> and the definition of a drive on the command line for it. The > >>>> proposal is bypassing a lot of QEMU layers for this purpose. > >>> > >>> More of the former, a built-in eFuse behaving more like flash. So > >>> using block backend for the storage seems correct to me. > >> > >> How would you define the drive backend on the command line ? > >> > >>> However I don't think > >>> the implementation belongs to hw/misc/aspeed_sbc; ideally we'd have > >>> some abstract (or interface) implementation in hw/block/otp.c -- > >>> with methods such program_otp_data() --, completed by > hw/block/aspeed_otc.c. > >> > >> I was imagining more something like NPCM7xxOTPState or > >> BCM2835OTPState and not SiFiveUOTPState. > >> > >>> Current patch might be good enough to start with IMHO. > >> > >> Have you looked at the next patch and how the backend is handled ? > >> I will let the block people Ack this patch in that case. It's beyond my > >> skills. > >> > >> Thanks, > >> > >> C. > >> > >