Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1320309 > unrolled thread

[PATCH 0/8] mtd: spi-nor: locking fixes and updates

Started byBrian Norris <computersforpeace@gmail.com>
First post2016-01-28 07:00 +0100
Last post2016-01-28 15:50 +0100
Articles 14 — 2 participants

Back to article view | Back to linux.kernel


Contents

  [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

#1320309 — [PATCH 0/8] mtd: spi-nor: locking fixes and updates

FromBrian Norris <computersforpeace@gmail.com>
Date2016-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]


#1320311 — [PATCH 8/8] mtd: spi-nor: support lock/unlock for a few Winbond chips

FromBrian Norris <computersforpeace@gmail.com>
Date2016-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]


#1320312 — [PATCH 2/8] mtd: spi-nor: guard against underflows in stm_is_locked_sr

FromBrian Norris <computersforpeace@gmail.com>
Date2016-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]


#1320313 — [PATCH 4/8] mtd: spi-nor: disallow further writes to SR if WP# is low

FromBrian Norris <computersforpeace@gmail.com>
Date2016-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]


#1320740 — Re: [PATCH 4/8] mtd: spi-nor: disallow further writes to SR if WP# is low

FromEzequiel Garcia <ezequiel@vanguardiasur.com.ar>
Date2016-01-28 15:40 +0100
SubjectRe: [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]


#1320929 — Re: [PATCH 4/8] mtd: spi-nor: disallow further writes to SR if WP# is low

FromBrian Norris <computersforpeace@gmail.com>
Date2016-01-28 19:00 +0100
SubjectRe: [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]


#1320959 — Re: [PATCH 4/8] mtd: spi-nor: disallow further writes to SR if WP# is low

FromEzequiel Garcia <ezequiel@vanguardiasur.com.ar>
Date2016-01-28 20:30 +0100
SubjectRe: [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]


#1320989 — Re: [PATCH 4/8] mtd: spi-nor: disallow further writes to SR if WP# is low

FromBrian Norris <computersforpeace@gmail.com>
Date2016-01-28 20:50 +0100
SubjectRe: [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]


#1321751 — Re: [PATCH 4/8] mtd: spi-nor: disallow further writes to SR if WP# is low

FromEzequiel Garcia <ezequiel@vanguardiasur.com.ar>
Date2016-01-29 14:30 +0100
SubjectRe: [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]


#1322030 — Re: [PATCH 4/8] mtd: spi-nor: disallow further writes to SR if WP# is low

FromBrian Norris <computersforpeace@gmail.com>
Date2016-01-29 20:30 +0100
SubjectRe: [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]


#1320314 — [PATCH 5/8] mtd: spi-nor: use BIT() for flash_info flags

FromBrian Norris <computersforpeace@gmail.com>
Date2016-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]


#1320316 — [PATCH 6/8] mtd: spi-nor: add SPI_NOR_HAS_LOCK flag

FromBrian Norris <computersforpeace@gmail.com>
Date2016-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]


#1320317 — [PATCH 1/8] mtd: spi-nor: wait for SR_WIP to clear on initial unlock

FromBrian Norris <computersforpeace@gmail.com>
Date2016-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]


#1320747

FromEzequiel Garcia <ezequiel@vanguardiasur.com.ar>
Date2016-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