From mboxrd@z Thu Jan 1 00:00:00 1970 From: Patrice CHOTARD Date: Wed, 18 Mar 2020 10:07:06 +0000 Subject: [PATCH 04/10] arm: stm32mp: bsec: add permanent lock support in bsec driver In-Reply-To: <20200212183744.5309-5-patrick.delaunay@st.com> References: <20200212183744.5309-1-patrick.delaunay@st.com> <20200212183744.5309-5-patrick.delaunay@st.com> Message-ID: List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de On 2/12/20 7:37 PM, Patrick Delaunay wrote: > Add BSEC lock access (read / write) at 0xC0000000 offset of misc driver. > The write access only available for Trusted boot mode, based on new > SMC STM32_SMC_WRLOCK_OTP. > > With the fuse command, the permanent lock status is accessed with > 0x10000000 offset (0xC0000000 - 0x8000000 for OTP sense/program > divided by u32 size), for example: > > Read lock status of fuse 57 (0x39) > > STM32MP> fuse sense 0 0x10000039 1 > > Sensing bank 0: > > Word 0x10000039: 00000000 > > Set permanent lock of fuse 57 (0x39) > > STM32MP> fuse prog 0 0x10000039 1 > > Sensing bank 0: > > Word 0x10000039: 00000000 > > WARNING: the OTP lock is updated only after reboot > > WARING: Programming lock or fuses is an irreversible operation! > This may brick your system. > > Signed-off-by: Patrick Delaunay > --- > > arch/arm/mach-stm32mp/bsec.c | 88 +++++++++++++------ > arch/arm/mach-stm32mp/cpu.c | 6 -- > arch/arm/mach-stm32mp/include/mach/stm32.h | 9 +- > .../mach-stm32mp/include/mach/stm32mp1_smc.h | 1 + > doc/board/st/stm32mp1.rst | 34 ++++--- > 5 files changed, 95 insertions(+), 43 deletions(-) > > diff --git a/arch/arm/mach-stm32mp/bsec.c b/arch/arm/mach-stm32mp/bsec.c > index 1d904caae1..3b923f088e 100644 > --- a/arch/arm/mach-stm32mp/bsec.c > +++ b/arch/arm/mach-stm32mp/bsec.c > @@ -12,8 +12,6 @@ > #include > > #define BSEC_OTP_MAX_VALUE 95 > - > -#ifndef CONFIG_STM32MP1_TRUSTED > #define BSEC_TIMEOUT_US 10000 > > /* BSEC REGISTER OFFSET (base relative) */ > @@ -24,9 +22,10 @@ > #define BSEC_OTP_LOCK_OFF 0x010 > #define BSEC_DISTURBED_OFF 0x01C > #define BSEC_ERROR_OFF 0x034 > -#define BSEC_SPLOCK_OFF 0x064 /* Program safmem sticky lock */ > -#define BSEC_SWLOCK_OFF 0x07C /* write in OTP sticky lock */ > -#define BSEC_SRLOCK_OFF 0x094 /* shadowing sticky lock */ > +#define BSEC_WRLOCK_OFF 0x04C /* OTP write permananet lock */ > +#define BSEC_SPLOCK_OFF 0x064 /* OTP write sticky lock */ > +#define BSEC_SWLOCK_OFF 0x07C /* shadow write sticky lock */ > +#define BSEC_SRLOCK_OFF 0x094 /* shadow read sticky lock */ > #define BSEC_OTP_DATA_OFF 0x200 > > /* BSEC_CONFIGURATION Register MASK */ > @@ -53,12 +52,12 @@ > #define BSEC_LOCK_PROGRAM 0x04 > > /** > - * bsec_check_error() - Check status of one otp > - * @base: base address of bsec IP > + * bsec_lock() - manage lock for each type SR/SP/SW > + * @address: address of bsec IP register > * @otp: otp number (0 - BSEC_OTP_MAX_VALUE) > - * Return: 0 if no error, -EAGAIN or -ENOTSUPP > + * Return: true if locked else false > */ > -static u32 bsec_check_error(u32 base, u32 otp) > +static bool bsec_read_lock(u32 address, u32 otp) > { > u32 bit; > u32 bank; > @@ -66,21 +65,17 @@ static u32 bsec_check_error(u32 base, u32 otp) > bit = 1 << (otp & OTP_LOCK_MASK); > bank = ((otp >> OTP_LOCK_BANK_SHIFT) & OTP_LOCK_MASK) * sizeof(u32); > > - if (readl(base + BSEC_DISTURBED_OFF + bank) & bit) > - return -EAGAIN; > - else if (readl(base + BSEC_ERROR_OFF + bank) & bit) > - return -ENOTSUPP; > - > - return 0; > + return !!(readl(address + bank) & bit); > } > > +#ifndef CONFIG_STM32MP1_TRUSTED > /** > - * bsec_lock() - manage lock for each type SR/SP/SW > - * @address: address of bsec IP register > + * bsec_check_error() - Check status of one otp > + * @base: base address of bsec IP > * @otp: otp number (0 - BSEC_OTP_MAX_VALUE) > - * Return: true if locked else false > + * Return: 0 if no error, -EAGAIN or -ENOTSUPP > */ > -static bool bsec_read_lock(u32 address, u32 otp) > +static u32 bsec_check_error(u32 base, u32 otp) > { > u32 bit; > u32 bank; > @@ -88,7 +83,12 @@ static bool bsec_read_lock(u32 address, u32 otp) > bit = 1 << (otp & OTP_LOCK_MASK); > bank = ((otp >> OTP_LOCK_BANK_SHIFT) & OTP_LOCK_MASK) * sizeof(u32); > > - return !!(readl(address + bank) & bit); > + if (readl(base + BSEC_DISTURBED_OFF + bank) & bit) > + return -EAGAIN; > + else if (readl(base + BSEC_ERROR_OFF + bank) & bit) > + return -ENOTSUPP; > + > + return 0; > } > > /** > @@ -324,6 +324,16 @@ static int stm32mp_bsec_read_shadow(struct udevice *dev, u32 *val, u32 otp) > #endif > } > > +static int stm32mp_bsec_read_lock(struct udevice *dev, u32 *val, u32 otp) > +{ > + struct stm32mp_bsec_platdata *plat = dev_get_platdata(dev); > + > + /* return OTP permanent write lock status */ > + *val = bsec_read_lock(plat->base + BSEC_WRLOCK_OFF, otp); > + > + return 0; > +} > + > static int stm32mp_bsec_write_otp(struct udevice *dev, u32 val, u32 otp) > { > #ifdef CONFIG_STM32MP1_TRUSTED > @@ -350,17 +360,36 @@ static int stm32mp_bsec_write_shadow(struct udevice *dev, u32 val, u32 otp) > #endif > } > > +static int stm32mp_bsec_write_lock(struct udevice *dev, u32 val, u32 otp) > +{ > +#ifdef CONFIG_STM32MP1_TRUSTED > + if (val == 1) > + return stm32_smc_exec(STM32_SMC_BSEC, > + STM32_SMC_WRLOCK_OTP, > + otp, 0); > + if (val == 0) > + return 0; /* nothing to do */ > + > + return -EINVAL; > +#else > + return -ENOTSUPP; > +#endif > +} > + > static int stm32mp_bsec_read(struct udevice *dev, int offset, > void *buf, int size) > { > int ret; > int i; > - bool shadow = true; > + bool shadow = true, lock = false; > int nb_otp = size / sizeof(u32); > int otp; > unsigned int offs = offset; > > - if (offs >= STM32_BSEC_OTP_OFFSET) { > + if (offs >= STM32_BSEC_LOCK_OFFSET) { > + offs -= STM32_BSEC_LOCK_OFFSET; > + lock = true; > + } else if (offs >= STM32_BSEC_OTP_OFFSET) { > offs -= STM32_BSEC_OTP_OFFSET; > shadow = false; > } > @@ -373,7 +402,9 @@ static int stm32mp_bsec_read(struct udevice *dev, int offset, > for (i = otp; i < (otp + nb_otp) && i <= BSEC_OTP_MAX_VALUE; i++) { > u32 *addr = &((u32 *)buf)[i - otp]; > > - if (shadow) > + if (lock) > + ret = stm32mp_bsec_read_lock(dev, addr, i); > + else if (shadow) > ret = stm32mp_bsec_read_shadow(dev, addr, i); > else > ret = stm32mp_bsec_read_otp(dev, addr, i); > @@ -392,12 +423,15 @@ static int stm32mp_bsec_write(struct udevice *dev, int offset, > { > int ret = 0; > int i; > - bool shadow = true; > + bool shadow = true, lock = false; > int nb_otp = size / sizeof(u32); > int otp; > unsigned int offs = offset; > > - if (offs >= STM32_BSEC_OTP_OFFSET) { > + if (offs >= STM32_BSEC_LOCK_OFFSET) { > + offs -= STM32_BSEC_LOCK_OFFSET; > + lock = true; > + } else if (offs >= STM32_BSEC_OTP_OFFSET) { > offs -= STM32_BSEC_OTP_OFFSET; > shadow = false; > } > @@ -410,7 +444,9 @@ static int stm32mp_bsec_write(struct udevice *dev, int offset, > for (i = otp; i < otp + nb_otp && i <= BSEC_OTP_MAX_VALUE; i++) { > u32 *val = &((u32 *)buf)[i - otp]; > > - if (shadow) > + if (lock) > + ret = stm32mp_bsec_write_lock(dev, *val, i); > + else if (shadow) > ret = stm32mp_bsec_write_shadow(dev, *val, i); > else > ret = stm32mp_bsec_write_otp(dev, *val, i); > diff --git a/arch/arm/mach-stm32mp/cpu.c b/arch/arm/mach-stm32mp/cpu.c > index ea0bd94605..5febed735c 100644 > --- a/arch/arm/mach-stm32mp/cpu.c > +++ b/arch/arm/mach-stm32mp/cpu.c > @@ -61,12 +61,6 @@ > #define BOOTROM_INSTANCE_MASK GENMASK(31, 16) > #define BOOTROM_INSTANCE_SHIFT 16 > > -/* BSEC OTP index */ > -#define BSEC_OTP_RPN 1 > -#define BSEC_OTP_SERIAL 13 > -#define BSEC_OTP_PKG 16 > -#define BSEC_OTP_MAC 57 > - > /* Device Part Number (RPN) = OTP_DATA1 lower 8 bits */ > #define RPN_SHIFT 0 > #define RPN_MASK GENMASK(7, 0) > diff --git a/arch/arm/mach-stm32mp/include/mach/stm32.h b/arch/arm/mach-stm32mp/include/mach/stm32.h > index f0636005e5..6daf9f7121 100644 > --- a/arch/arm/mach-stm32mp/include/mach/stm32.h > +++ b/arch/arm/mach-stm32mp/include/mach/stm32.h > @@ -119,7 +119,14 @@ enum forced_boot_mode { > #define STM32_BSEC_SHADOW(id) (STM32_BSEC_SHADOW_OFFSET + (id) * 4) > #define STM32_BSEC_OTP_OFFSET 0x80000000 > #define STM32_BSEC_OTP(id) (STM32_BSEC_OTP_OFFSET + (id) * 4) > - > +#define STM32_BSEC_LOCK_OFFSET 0xC0000000 > +#define STM32_BSEC_LOCK(id) (STM32_BSEC_LOCK_OFFSET + (id) * 4) > + > +/* BSEC OTP index */ > +#define BSEC_OTP_RPN 1 > +#define BSEC_OTP_SERIAL 13 > +#define BSEC_OTP_PKG 16 > +#define BSEC_OTP_MAC 57 > #define BSEC_OTP_BOARD 59 > > #endif /* __ASSEMBLY__*/ > diff --git a/arch/arm/mach-stm32mp/include/mach/stm32mp1_smc.h b/arch/arm/mach-stm32mp/include/mach/stm32mp1_smc.h > index 8130546b27..7b9167c356 100644 > --- a/arch/arm/mach-stm32mp/include/mach/stm32mp1_smc.h > +++ b/arch/arm/mach-stm32mp/include/mach/stm32mp1_smc.h > @@ -27,6 +27,7 @@ > #define STM32_SMC_READ_OTP 0x04 > #define STM32_SMC_READ_ALL 0x05 > #define STM32_SMC_WRITE_ALL 0x06 > +#define STM32_SMC_WRLOCK_OTP 0x07 > > /* SMC error codes */ > #define STM32_SMC_OK 0x0 > diff --git a/doc/board/st/stm32mp1.rst b/doc/board/st/stm32mp1.rst > index 131f4902a3..274f8d9710 100644 > --- a/doc/board/st/stm32mp1.rst > +++ b/doc/board/st/stm32mp1.rst > @@ -402,20 +402,26 @@ For STMicroelectonics board, it is retrieved in STM32MP15x OTP : > - OTP_58[15:0] = MAC_ADDR[47:32] > > To program a MAC address on virgin OTP words above, you can use the fuse command > -on bank 0 to access to internal OTP: > +on bank 0 to access to internal OTP and lock them: > > Prerequisite: check if a MAC address isn't yet programmed in OTP > > -1) check OTP: their value must be equal to 0 > +1) check OTP: their value must be equal to 0:: > > - STM32MP> fuse sense 0 57 2 > - Sensing bank 0: > - Word 0x00000039: 00000000 00000000 > + STM32MP> fuse sense 0 57 2 > + Sensing bank 0: > + Word 0x00000039: 00000000 00000000 > + > +2) check environment variable:: > + > + STM32MP> env print ethaddr > + ## Error: "ethaddr" not defined > > -2) check environment variable > +3) check lock status of fuse 57 & 58 (at 0x39, 0=unlocked, 1=locked):: > > - STM32MP> env print ethaddr > - ## Error: "ethaddr" not defined > + STM32MP> fuse sense 0 0x10000039 2 > + Sensing bank 0: > + Word 0x10000039: 00000000 00000000 > > Example to set mac address "12:34:56:78:9a:bc" > > @@ -429,11 +435,19 @@ Example to set mac address "12:34:56:78:9a:bc" > Sensing bank 0: > Word 0x00000039: 78563412 0000bc9a > > -3) next REBOOT, in the trace:: > +3) Lock OTP:: > + > + STM32MP> fuse prog 0 0x10000039 1 1 > + > + STM32MP> fuse sense 0 0x10000039 2 > + Sensing bank 0: > + Word 0x10000039: 00000001 00000001 > + > +4) next REBOOT, in the trace:: > > Acked-by: Patrice Chotard > > Thanks > > Patrice > > > ### Setting environment from OTP MAC address = "12:34:56:78:9a:bc" > > -4) check env update:: > +5) check env update:: > > STM32MP> env print ethaddr > ethaddr=12:34:56:78:9a:bc Acked-by: Patrice Chotard Thanks Patrice