Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1320309 > unrolled thread
| Started by | Brian Norris <computersforpeace@gmail.com> |
|---|---|
| First post | 2016-01-28 07:00 +0100 |
| Last post | 2016-01-28 15:50 +0100 |
| Articles | 14 — 2 participants |
Back to article view | Back to linux.kernel
[PATCH 0/8] mtd: spi-nor: locking fixes and updates Brian Norris <computersforpeace@gmail.com> - 2016-01-28 07:00 +0100
[PATCH 8/8] mtd: spi-nor: support lock/unlock for a few Winbond chips Brian Norris <computersforpeace@gmail.com> - 2016-01-28 07:00 +0100
[PATCH 2/8] mtd: spi-nor: guard against underflows in stm_is_locked_sr Brian Norris <computersforpeace@gmail.com> - 2016-01-28 07:00 +0100
[PATCH 4/8] mtd: spi-nor: disallow further writes to SR if WP# is low Brian Norris <computersforpeace@gmail.com> - 2016-01-28 07:00 +0100
Re: [PATCH 4/8] mtd: spi-nor: disallow further writes to SR if WP# is low Ezequiel Garcia <ezequiel@vanguardiasur.com.ar> - 2016-01-28 15:40 +0100
Re: [PATCH 4/8] mtd: spi-nor: disallow further writes to SR if WP# is low Brian Norris <computersforpeace@gmail.com> - 2016-01-28 19:00 +0100
Re: [PATCH 4/8] mtd: spi-nor: disallow further writes to SR if WP# is low Ezequiel Garcia <ezequiel@vanguardiasur.com.ar> - 2016-01-28 20:30 +0100
Re: [PATCH 4/8] mtd: spi-nor: disallow further writes to SR if WP# is low Brian Norris <computersforpeace@gmail.com> - 2016-01-28 20:50 +0100
Re: [PATCH 4/8] mtd: spi-nor: disallow further writes to SR if WP# is low Ezequiel Garcia <ezequiel@vanguardiasur.com.ar> - 2016-01-29 14:30 +0100
Re: [PATCH 4/8] mtd: spi-nor: disallow further writes to SR if WP# is low Brian Norris <computersforpeace@gmail.com> - 2016-01-29 20:30 +0100
[PATCH 5/8] mtd: spi-nor: use BIT() for flash_info flags Brian Norris <computersforpeace@gmail.com> - 2016-01-28 07:00 +0100
[PATCH 6/8] mtd: spi-nor: add SPI_NOR_HAS_LOCK flag Brian Norris <computersforpeace@gmail.com> - 2016-01-28 07:00 +0100
[PATCH 1/8] mtd: spi-nor: wait for SR_WIP to clear on initial unlock Brian Norris <computersforpeace@gmail.com> - 2016-01-28 07:00 +0100
Re: [PATCH 0/8] mtd: spi-nor: locking fixes and updates Ezequiel Garcia <ezequiel@vanguardiasur.com.ar> - 2016-01-28 15:50 +0100
| From | Brian Norris <computersforpeace@gmail.com> |
|---|---|
| Date | 2016-01-28 07:00 +0100 |
| Subject | [PATCH 0/8] mtd: spi-nor: locking fixes and updates |
| Message-ID | <qVNMB-7dr-5@gated-at.bofh.it> |
Hi,
These are an assortment of fixes and updates to the SPI NOR lock/unlock
feature. The biggest new features are:
(a) Status Register protection; I don't see why this shouldn't be enabled by
default. See patch 4's description.
(b) Bottom-block protection support (via TB status bit)
(c) Lock/unlock support for a few Winbond flash
Patch 7 (Top/Bottom protection support) is still an RFC, as I think it deserves
a bit more work. But I'm just getting it out there, as it's been sitting on my
plate for a while.
Regards,
Brian
Brian Norris (8):
mtd: spi-nor: wait for SR_WIP to clear on initial unlock
mtd: spi-nor: guard against underflows in stm_is_locked_sr
mtd: spi-nor: silently drop lock/unlock for already locked/unlocked
region
mtd: spi-nor: disallow further writes to SR if WP# is low
mtd: spi-nor: use BIT() for flash_info flags
mtd: spi-nor: add SPI_NOR_HAS_LOCK flag
mtd: spi-nor: add TB (Top/Bottom) protect support
mtd: spi-nor: support lock/unlock for a few Winbond chips
drivers/mtd/spi-nor/spi-nor.c | 153 +++++++++++++++++++++++++++++++++--------
include/linux/mtd/spi-nor.h | 2 +
2 files changed, 128 insertions(+), 27 deletions(-)
--
1.7.9.5
[toc] | [next] | [standalone]
| From | Brian Norris <computersforpeace@gmail.com> |
|---|---|
| Date | 2016-01-28 07:00 +0100 |
| Subject | [PATCH 8/8] mtd: spi-nor: support lock/unlock for a few Winbond chips |
| Message-ID | <qVNMD-7dr-11@gated-at.bofh.it> |
| In reply to | #1320309 |
These are recent Winbond models that are known to have lock/unlock
support via writing the Status Register, and that also support the TB
(Top/Bottom) protection bit.
Tested on w25q32dw.
[Note on style: these entries are getting pretty long lines, so I picked
a style that seems reasonable for splitting up the flags separate from
the other mostly-similar fields.]
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
---
drivers/mtd/spi-nor/spi-nor.c | 18 +++++++++++++++---
1 file changed, 15 insertions(+), 3 deletions(-)
diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index 5e84e3c543aa..cd3908e26712 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -942,11 +942,23 @@ static const struct flash_info spi_nor_ids[] = {
{ "w25x16", INFO(0xef3015, 0, 64 * 1024, 32, SECT_4K) },
{ "w25x32", INFO(0xef3016, 0, 64 * 1024, 64, SECT_4K) },
{ "w25q32", INFO(0xef4016, 0, 64 * 1024, 64, SECT_4K) },
- { "w25q32dw", INFO(0xef6016, 0, 64 * 1024, 64, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+ {
+ "w25q32dw", INFO(0xef6016, 0, 64 * 1024, 64,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+ SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
+ },
{ "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) },
{ "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) },
- { "w25q64dw", INFO(0xef6017, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
- { "w25q128fw", INFO(0xef6018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+ {
+ "w25q64dw", INFO(0xef6017, 0, 64 * 1024, 128,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+ SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
+ },
+ {
+ "w25q128fw", INFO(0xef6018, 0, 64 * 1024, 256,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+ SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
+ },
{ "w25q80", INFO(0xef5014, 0, 64 * 1024, 16, SECT_4K) },
{ "w25q80bl", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K) },
{ "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K) },
--
1.7.9.5
[toc] | [prev] | [next] | [standalone]
| From | Brian Norris <computersforpeace@gmail.com> |
|---|---|
| Date | 2016-01-28 07:00 +0100 |
| Subject | [PATCH 2/8] mtd: spi-nor: guard against underflows in stm_is_locked_sr |
| Message-ID | <qVNMD-7dr-17@gated-at.bofh.it> |
| In reply to | #1320309 |
Users of stm_is_locked_sr() might do arithmetic that could result in a negative offset. For example, when stm_unlock() tries to check the status of the eraseblock below the range, it doesn't check for: ofs - mtd->erasesize < 0 Instead of forcing callers to be extra careful, let's just make stm_is_locked_sr() do the right thing and report errors for invalid ranges. Also, fixup the calculations in stm_unlock(), so we: (a) can handle non-eraseblock-aligned offsets and (b) don't look for a negative offset when checking the first block Signed-off-by: Brian Norris <computersforpeace@gmail.com> --- drivers/mtd/spi-nor/spi-nor.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index ef89bed1e5ea..c19674573eec 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -447,6 +447,9 @@ static int stm_is_locked_sr(struct spi_nor *nor, loff_t ofs, uint64_t len, loff_t lock_offs; uint64_t lock_len; + if (ofs < 0 || ofs + len > nor->mtd.size) + return -EINVAL; + stm_get_locked_range(nor, sr, &lock_offs, &lock_len); return (ofs + len <= lock_offs + lock_len) && (ofs >= lock_offs); @@ -543,9 +546,13 @@ static int stm_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len) if (status_old < 0) return status_old; - /* Cannot unlock; would unlock larger region than requested */ - if (stm_is_locked_sr(nor, ofs - mtd->erasesize, mtd->erasesize, - status_old)) + /* + * Check the eraseblock next to us; if locked, then this would unlock + * larger region than requested + */ + if (ofs > 0 && stm_is_locked_sr(nor, ALIGN(ofs - mtd->erasesize, + mtd->erasesize), mtd->erasesize, + status_old)) return -EINVAL; /* -- 1.7.9.5
[toc] | [prev] | [next] | [standalone]
| From | Brian Norris <computersforpeace@gmail.com> |
|---|---|
| Date | 2016-01-28 07:00 +0100 |
| Subject | [PATCH 4/8] mtd: spi-nor: disallow further writes to SR if WP# is low |
| Message-ID | <qVNMD-7dr-15@gated-at.bofh.it> |
| In reply to | #1320309 |
Locking the flash is most useful if it provides real hardware security.
Otherwise, it's little more than a software permission bit.
A reasonable use case that provides real HW security might be like
follows:
(1) hardware WP# is deasserted
(2) program flash
(3) flash range is protected via status register
(4) hardware WP# is asserted
(5) flash protection range can no longer be changed, until WP# is
deasserted
In this way, flash protection is co-owned by hardware and software.
Now, one would expect to be able to perform step (3) with
ioctl(MEMLOCK), except that the spi-nor driver does not set the Status
Register Protect bit (a.k.a. Status Register Write Disable (SRWD)), so
even though the range is now locked, it does not satisfy step (5) -- it
can still be changed by a call to ioctl(MEMUNLOCK).
So, let's enable status register protection after the first lock
command.
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
---
drivers/mtd/spi-nor/spi-nor.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index 3a08aa53c171..46da6bb706fa 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -518,6 +518,9 @@ static int stm_lock(struct spi_nor *nor, loff_t ofs, uint64_t len)
status_new = (status_old & ~mask) | val;
+ /* Disallow further writes if WP pin is asserted */
+ status_new |= SR_SRWD;
+
/* Don't bother if they're the same */
if (status_new == status_old)
return 0;
--
1.7.9.5
[toc] | [prev] | [next] | [standalone]
| From | Ezequiel Garcia <ezequiel@vanguardiasur.com.ar> |
|---|---|
| Date | 2016-01-28 15:40 +0100 |
| Subject | Re: [PATCH 4/8] mtd: spi-nor: disallow further writes to SR if WP# is low |
| Message-ID | <qVVTR-4Lm-41@gated-at.bofh.it> |
| In reply to | #1320313 |
On 28 January 2016 at 02:51, Brian Norris <computersforpeace@gmail.com> wrote: > Locking the flash is most useful if it provides real hardware security. > Otherwise, it's little more than a software permission bit. > > A reasonable use case that provides real HW security might be like > follows: > > (1) hardware WP# is deasserted > (2) program flash > (3) flash range is protected via status register > (4) hardware WP# is asserted > (5) flash protection range can no longer be changed, until WP# is > deasserted > > In this way, flash protection is co-owned by hardware and software. > > Now, one would expect to be able to perform step (3) with > ioctl(MEMLOCK), except that the spi-nor driver does not set the Status > Register Protect bit (a.k.a. Status Register Write Disable (SRWD)), so > even though the range is now locked, it does not satisfy step (5) -- it > can still be changed by a call to ioctl(MEMUNLOCK). > > So, let's enable status register protection after the first lock > command. > > Signed-off-by: Brian Norris <computersforpeace@gmail.com> > --- > drivers/mtd/spi-nor/spi-nor.c | 3 +++ > 1 file changed, 3 insertions(+) > > diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c > index 3a08aa53c171..46da6bb706fa 100644 > --- a/drivers/mtd/spi-nor/spi-nor.c > +++ b/drivers/mtd/spi-nor/spi-nor.c > @@ -518,6 +518,9 @@ static int stm_lock(struct spi_nor *nor, loff_t ofs, uint64_t len) > > status_new = (status_old & ~mask) | val; > > + /* Disallow further writes if WP pin is asserted */ > + status_new |= SR_SRWD; > + No need to clear SR_SRWD in stm_unlock? -- Ezequiel García, VanguardiaSur www.vanguardiasur.com.ar
[toc] | [prev] | [next] | [standalone]
| From | Brian Norris <computersforpeace@gmail.com> |
|---|---|
| Date | 2016-01-28 19:00 +0100 |
| Subject | Re: [PATCH 4/8] mtd: spi-nor: disallow further writes to SR if WP# is low |
| Message-ID | <qVZ1p-6V6-27@gated-at.bofh.it> |
| In reply to | #1320740 |
Hi Ezequiel, Thanks for the review. On Thu, Jan 28, 2016 at 11:36:13AM -0300, Ezequiel Garcia wrote: > On 28 January 2016 at 02:51, Brian Norris <computersforpeace@gmail.com> wrote: > > Locking the flash is most useful if it provides real hardware security. > > Otherwise, it's little more than a software permission bit. > > > > A reasonable use case that provides real HW security might be like > > follows: > > > > (1) hardware WP# is deasserted > > (2) program flash > > (3) flash range is protected via status register > > (4) hardware WP# is asserted > > (5) flash protection range can no longer be changed, until WP# is > > deasserted > > > > In this way, flash protection is co-owned by hardware and software. > > > > Now, one would expect to be able to perform step (3) with > > ioctl(MEMLOCK), except that the spi-nor driver does not set the Status > > Register Protect bit (a.k.a. Status Register Write Disable (SRWD)), so > > even though the range is now locked, it does not satisfy step (5) -- it > > can still be changed by a call to ioctl(MEMUNLOCK). > > > > So, let's enable status register protection after the first lock > > command. > > > > Signed-off-by: Brian Norris <computersforpeace@gmail.com> > > --- > > drivers/mtd/spi-nor/spi-nor.c | 3 +++ > > 1 file changed, 3 insertions(+) > > > > diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c > > index 3a08aa53c171..46da6bb706fa 100644 > > --- a/drivers/mtd/spi-nor/spi-nor.c > > +++ b/drivers/mtd/spi-nor/spi-nor.c > > @@ -518,6 +518,9 @@ static int stm_lock(struct spi_nor *nor, loff_t ofs, uint64_t len) > > > > status_new = (status_old & ~mask) | val; > > > > + /* Disallow further writes if WP pin is asserted */ > > + status_new |= SR_SRWD; > > + > > No need to clear SR_SRWD in stm_unlock? Good point. I actually had thought about that earlier, but I didn't come up with a great plan, and then I forgot about it when I was preparing this RFC. I don't think we want *all* "unlock" operations to unprotect the status register. What if we had the whole flash locked, and we're just calling unlock on the top half, with the intention of leaving the bottom half protected still? So, maybe we want to clear SR_SRWD only when we unlock the *entire* flash? What do you think? Brian
[toc] | [prev] | [next] | [standalone]
| From | Ezequiel Garcia <ezequiel@vanguardiasur.com.ar> |
|---|---|
| Date | 2016-01-28 20:30 +0100 |
| Subject | Re: [PATCH 4/8] mtd: spi-nor: disallow further writes to SR if WP# is low |
| Message-ID | <qW0qu-841-7@gated-at.bofh.it> |
| In reply to | #1320929 |
On 28 January 2016 at 14:59, Brian Norris <computersforpeace@gmail.com> wrote: > Hi Ezequiel, > > Thanks for the review. > > On Thu, Jan 28, 2016 at 11:36:13AM -0300, Ezequiel Garcia wrote: >> On 28 January 2016 at 02:51, Brian Norris <computersforpeace@gmail.com> wrote: >> > Locking the flash is most useful if it provides real hardware security. >> > Otherwise, it's little more than a software permission bit. >> > >> > A reasonable use case that provides real HW security might be like >> > follows: >> > >> > (1) hardware WP# is deasserted >> > (2) program flash >> > (3) flash range is protected via status register >> > (4) hardware WP# is asserted >> > (5) flash protection range can no longer be changed, until WP# is >> > deasserted >> > >> > In this way, flash protection is co-owned by hardware and software. >> > >> > Now, one would expect to be able to perform step (3) with >> > ioctl(MEMLOCK), except that the spi-nor driver does not set the Status >> > Register Protect bit (a.k.a. Status Register Write Disable (SRWD)), so >> > even though the range is now locked, it does not satisfy step (5) -- it >> > can still be changed by a call to ioctl(MEMUNLOCK). >> > >> > So, let's enable status register protection after the first lock >> > command. >> > >> > Signed-off-by: Brian Norris <computersforpeace@gmail.com> >> > --- >> > drivers/mtd/spi-nor/spi-nor.c | 3 +++ >> > 1 file changed, 3 insertions(+) >> > >> > diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c >> > index 3a08aa53c171..46da6bb706fa 100644 >> > --- a/drivers/mtd/spi-nor/spi-nor.c >> > +++ b/drivers/mtd/spi-nor/spi-nor.c >> > @@ -518,6 +518,9 @@ static int stm_lock(struct spi_nor *nor, loff_t ofs, uint64_t len) >> > >> > status_new = (status_old & ~mask) | val; >> > >> > + /* Disallow further writes if WP pin is asserted */ >> > + status_new |= SR_SRWD; >> > + >> >> No need to clear SR_SRWD in stm_unlock? > > Good point. > > I actually had thought about that earlier, but I didn't come up with a > great plan, and then I forgot about it when I was preparing this RFC. I > don't think we want *all* "unlock" operations to unprotect the status > register. What if we had the whole flash locked, and we're just calling > unlock on the top half, with the intention of leaving the bottom half > protected still? > Right. > So, maybe we want to clear SR_SRWD only when we unlock the *entire* > flash? What do you think? > How about this: 1) ioctl(MEMLOCK) the entire flash (SR_SRWD is set) 2) ioctl(MEMUNLOCK) partially (SW_SRWD keeps set) 3) ioctl(MEMLOCK) the entire flash again Not sure this use case make sense, but would (3) be allowed given SW_SRWD is set? -- Ezequiel García, VanguardiaSur www.vanguardiasur.com.ar
[toc] | [prev] | [next] | [standalone]
| From | Brian Norris <computersforpeace@gmail.com> |
|---|---|
| Date | 2016-01-28 20:50 +0100 |
| Subject | Re: [PATCH 4/8] mtd: spi-nor: disallow further writes to SR if WP# is low |
| Message-ID | <qW0JR-8ef-47@gated-at.bofh.it> |
| In reply to | #1320959 |
On Thu, Jan 28, 2016 at 04:24:50PM -0300, Ezequiel Garcia wrote:
> On 28 January 2016 at 14:59, Brian Norris <computersforpeace@gmail.com> wrote:
> > So, maybe we want to clear SR_SRWD only when we unlock the *entire*
> > flash? What do you think?
I'll paste in the relevant datasheet details from w25q32fw, to make sure
we're on the same page here, noting that 'SRP0' is our 'SR_SRWD', and
we're not touching SRP1 (i.e., SRP1=0):
"SRP1=0, SRP0=0, /WP=X: Software Protection
/WP pin has no control. The Status register can be written to after
a Write Enable instruction, WEL=1. [Factory Default]
SRP1=0, SRP0=1, /WP=0: Hardware Protected
When /WP pin is low the Status Register locked [sic] and cannot be
written to.
SRP1=0, SRP0=1, /WP=1: Hardware Unprotected
When /WP pin is high the Status register is unlocked and can be
written to after a Write Enable instruction, WEL=1."
> How about this:
>
> 1) ioctl(MEMLOCK) the entire flash (SR_SRWD is set)
> 2) ioctl(MEMUNLOCK) partially (SW_SRWD keeps set)
> 3) ioctl(MEMLOCK) the entire flash again
I might be confused; are you making a suggestion of a new behavior, or
are you just trying to clarify my proposal? Because this sounds like it
matches my proposal.
> Not sure this use case make sense,
I suppose it could make sense, if you (e.g.) have some intermediate
steps toward determining the locked regions during factory programming.
Maybe a process would start by doing #1 and #2, then decide
conditionally whether to do #3. And only after the whole process is done
does something assert /WP=0 (in my case, a factory process would tie /WP
low).
> but would (3) be allowed given
> SW_SRWD is set?
Yes, if /WP=1 (high).
Brian
[toc] | [prev] | [next] | [standalone]
| From | Ezequiel Garcia <ezequiel@vanguardiasur.com.ar> |
|---|---|
| Date | 2016-01-29 14:30 +0100 |
| Subject | Re: [PATCH 4/8] mtd: spi-nor: disallow further writes to SR if WP# is low |
| Message-ID | <qWhhE-3Fy-13@gated-at.bofh.it> |
| In reply to | #1320989 |
On 28 January 2016 at 16:48, Brian Norris <computersforpeace@gmail.com> wrote: > On Thu, Jan 28, 2016 at 04:24:50PM -0300, Ezequiel Garcia wrote: >> On 28 January 2016 at 14:59, Brian Norris <computersforpeace@gmail.com> wrote: >> > So, maybe we want to clear SR_SRWD only when we unlock the *entire* >> > flash? What do you think? > > I'll paste in the relevant datasheet details from w25q32fw, to make sure > we're on the same page here, noting that 'SRP0' is our 'SR_SRWD', and > we're not touching SRP1 (i.e., SRP1=0): > > "SRP1=0, SRP0=0, /WP=X: Software Protection > /WP pin has no control. The Status register can be written to after > a Write Enable instruction, WEL=1. [Factory Default] > SRP1=0, SRP0=1, /WP=0: Hardware Protected > When /WP pin is low the Status Register locked [sic] and cannot be > written to. > SRP1=0, SRP0=1, /WP=1: Hardware Unprotected > When /WP pin is high the Status register is unlocked and can be > written to after a Write Enable instruction, WEL=1." > Yes, we are on the same page. >> How about this: >> >> 1) ioctl(MEMLOCK) the entire flash (SR_SRWD is set) >> 2) ioctl(MEMUNLOCK) partially (SW_SRWD keeps set) >> 3) ioctl(MEMLOCK) the entire flash again > > I might be confused; are you making a suggestion of a new behavior, or > are you just trying to clarify my proposal? Because this sounds like it > matches my proposal. > I was trying to clarify how the SRWD would work in that case, but I forgot about /WP when I asked that! >> Not sure this use case make sense, > > I suppose it could make sense, if you (e.g.) have some intermediate > steps toward determining the locked regions during factory programming. > Maybe a process would start by doing #1 and #2, then decide > conditionally whether to do #3. And only after the whole process is done > does something assert /WP=0 (in my case, a factory process would tie /WP > low). > >> but would (3) be allowed given >> SW_SRWD is set? > > Yes, if /WP=1 (high). > Right. So, after giving some more thought do this, I'd say it might make sense to clear SRWD only when unlocking the entire flash. If anything else, it would allow a path to disable hardware protection on the lock range? -- Ezequiel García, VanguardiaSur www.vanguardiasur.com.ar
[toc] | [prev] | [next] | [standalone]
| From | Brian Norris <computersforpeace@gmail.com> |
|---|---|
| Date | 2016-01-29 20:30 +0100 |
| Subject | Re: [PATCH 4/8] mtd: spi-nor: disallow further writes to SR if WP# is low |
| Message-ID | <qWmU4-7SX-63@gated-at.bofh.it> |
| In reply to | #1321751 |
On Fri, Jan 29, 2016 at 10:22:34AM -0300, Ezequiel Garcia wrote: > On 28 January 2016 at 16:48, Brian Norris <computersforpeace@gmail.com> wrote: > > On Thu, Jan 28, 2016 at 04:24:50PM -0300, Ezequiel Garcia wrote: > >> How about this: > >> > >> 1) ioctl(MEMLOCK) the entire flash (SR_SRWD is set) > >> 2) ioctl(MEMUNLOCK) partially (SW_SRWD keeps set) > >> 3) ioctl(MEMLOCK) the entire flash again ... > >> but would (3) be allowed given > >> SW_SRWD is set? > > > > Yes, if /WP=1 (high). > > > > Right. So, after giving some more thought do this, I'd say it might > make sense to clear SRWD only when unlocking the entire flash. If > anything else, it would allow a path to disable hardware protection on > the lock range? Yes, that sounds fine to me, as it does allow removal of the HW protection. So one could, for example, do: 0. bring /WP=1 (high) 1. unlock the whole flash 2. bring /WP=0 (low) -- flash is still unlocked 3. allow a one-time relocking of the flash via MEMLOCK 4. no more locking changes I'll send out v2. Brian
[toc] | [prev] | [next] | [standalone]
| From | Brian Norris <computersforpeace@gmail.com> |
|---|---|
| Date | 2016-01-28 07:00 +0100 |
| Subject | [PATCH 5/8] mtd: spi-nor: use BIT() for flash_info flags |
| Message-ID | <qVNMD-7dr-19@gated-at.bofh.it> |
| In reply to | #1320309 |
It's a little easier to read and make sure there are no collisions
(IMO).
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
---
drivers/mtd/spi-nor/spi-nor.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index 46da6bb706fa..ac930e902ee3 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -61,14 +61,14 @@ struct flash_info {
u16 addr_width;
u16 flags;
-#define SECT_4K 0x01 /* SPINOR_OP_BE_4K works uniformly */
-#define SPI_NOR_NO_ERASE 0x02 /* No erase command needed */
-#define SST_WRITE 0x04 /* use SST byte programming */
-#define SPI_NOR_NO_FR 0x08 /* Can't do fastread */
-#define SECT_4K_PMC 0x10 /* SPINOR_OP_BE_4K_PMC works uniformly */
-#define SPI_NOR_DUAL_READ 0x20 /* Flash supports Dual Read */
-#define SPI_NOR_QUAD_READ 0x40 /* Flash supports Quad Read */
-#define USE_FSR 0x80 /* use flag status register */
+#define SECT_4K BIT(0) /* SPINOR_OP_BE_4K works uniformly */
+#define SPI_NOR_NO_ERASE BIT(1) /* No erase command needed */
+#define SST_WRITE BIT(2) /* use SST byte programming */
+#define SPI_NOR_NO_FR BIT(3) /* Can't do fastread */
+#define SECT_4K_PMC BIT(4) /* SPINOR_OP_BE_4K_PMC works uniformly */
+#define SPI_NOR_DUAL_READ BIT(5) /* Flash supports Dual Read */
+#define SPI_NOR_QUAD_READ BIT(6) /* Flash supports Quad Read */
+#define USE_FSR BIT(7) /* use flag status register */
};
#define JEDEC_MFR(info) ((info)->id[0])
--
1.7.9.5
[toc] | [prev] | [next] | [standalone]
| From | Brian Norris <computersforpeace@gmail.com> |
|---|---|
| Date | 2016-01-28 07:00 +0100 |
| Subject | [PATCH 6/8] mtd: spi-nor: add SPI_NOR_HAS_LOCK flag |
| Message-ID | <qVNMD-7dr-25@gated-at.bofh.it> |
| In reply to | #1320309 |
We can't determine this purely by manufacturer type (see commit
67b9bcd36906 ("mtd: spi-nor: fix Spansion regressions (aliased with
Winbond)")), and it's not autodetectable by anything like SFDP. So make
a new flag for it.
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
---
drivers/mtd/spi-nor/spi-nor.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index ac930e902ee3..8846b575b526 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -69,6 +69,7 @@ struct flash_info {
#define SPI_NOR_DUAL_READ BIT(5) /* Flash supports Dual Read */
#define SPI_NOR_QUAD_READ BIT(6) /* Flash supports Quad Read */
#define USE_FSR BIT(7) /* use flag status register */
+#define SPI_NOR_HAS_LOCK BIT(8) /* Flash supports lock/unlock via SR */
};
#define JEDEC_MFR(info) ((info)->id[0])
@@ -1251,7 +1252,8 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode)
if (JEDEC_MFR(info) == SNOR_MFR_ATMEL ||
JEDEC_MFR(info) == SNOR_MFR_INTEL ||
- JEDEC_MFR(info) == SNOR_MFR_SST) {
+ JEDEC_MFR(info) == SNOR_MFR_SST ||
+ info->flags & SPI_NOR_HAS_LOCK) {
write_enable(nor);
write_sr(nor, 0);
spi_nor_wait_till_ready(nor);
@@ -1268,7 +1270,8 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode)
mtd->_read = spi_nor_read;
/* NOR protection support for STmicro/Micron chips and similar */
- if (JEDEC_MFR(info) == SNOR_MFR_MICRON) {
+ if (JEDEC_MFR(info) == SNOR_MFR_MICRON ||
+ info->flags & SPI_NOR_HAS_LOCK) {
nor->flash_lock = stm_lock;
nor->flash_unlock = stm_unlock;
nor->flash_is_locked = stm_is_locked;
--
1.7.9.5
[toc] | [prev] | [next] | [standalone]
| From | Brian Norris <computersforpeace@gmail.com> |
|---|---|
| Date | 2016-01-28 07:00 +0100 |
| Subject | [PATCH 1/8] mtd: spi-nor: wait for SR_WIP to clear on initial unlock |
| Message-ID | <qVNMD-7dr-23@gated-at.bofh.it> |
| In reply to | #1320309 |
Fixup a piece leftover by commit 32321e950d8a ("mtd: spi-nor: wait until
lock/unlock operations are ready"). That commit made us wait for the WIP
bit to settle after lock/unlock operations, but it missed the open-coded
"unlock" that happens at probe() time.
We should probably have this code utilize the unlock() routines in the
future, to avoid duplication, but unfortunately, flash which need to be
unlocked don't all have a proper ->flash_unlock() callback.
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
Cc: Stas Sergeev <stsp@users.sourceforge.net>
Cc: Ezequiel Garcia <ezequiel@vanguardiasur.com.ar>
---
drivers/mtd/spi-nor/spi-nor.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index ed0c19c558b5..ef89bed1e5ea 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -1236,6 +1236,7 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode)
JEDEC_MFR(info) == SNOR_MFR_SST) {
write_enable(nor);
write_sr(nor, 0);
+ spi_nor_wait_till_ready(nor);
}
if (!mtd->name)
--
1.7.9.5
[toc] | [prev] | [next] | [standalone]
| From | Ezequiel Garcia <ezequiel@vanguardiasur.com.ar> |
|---|---|
| Date | 2016-01-28 15:50 +0100 |
| Message-ID | <qVW3w-4OQ-27@gated-at.bofh.it> |
| In reply to | #1320309 |
On 28 January 2016 at 02:51, Brian Norris <computersforpeace@gmail.com> wrote: > Hi, > > These are an assortment of fixes and updates to the SPI NOR lock/unlock > feature. The biggest new features are: > (a) Status Register protection; I don't see why this shouldn't be enabled by > default. See patch 4's description. > (b) Bottom-block protection support (via TB status bit) > (c) Lock/unlock support for a few Winbond flash > > Patch 7 (Top/Bottom protection support) is still an RFC, as I think it deserves > a bit more work. But I'm just getting it out there, as it's been sitting on my > plate for a while. > > Regards, > Brian > > Brian Norris (8): > mtd: spi-nor: wait for SR_WIP to clear on initial unlock > mtd: spi-nor: guard against underflows in stm_is_locked_sr > mtd: spi-nor: silently drop lock/unlock for already locked/unlocked > region > mtd: spi-nor: disallow further writes to SR if WP# is low > mtd: spi-nor: use BIT() for flash_info flags > mtd: spi-nor: add SPI_NOR_HAS_LOCK flag > mtd: spi-nor: add TB (Top/Bottom) protect support > mtd: spi-nor: support lock/unlock for a few Winbond chips > For all patches, except RFC 7/8: Reviewed-by: Ezequiel Garcia <ezequiel@vanguardiasur.com.ar> -- Ezequiel García, VanguardiaSur www.vanguardiasur.com.ar
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web