Skip to contentSkip to conversation

cmd_sf: Fix problem with "sf update" and unaligned length

PATCH New Stefan Roese 4 participants 13 messages Jan 9, 2015 – Apr 22, 2015

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 cmd_sf: Fix problem with "sf update" and unaligned length

On SoCFPGA, using "sf update" with an non-4byte aligned length leads to a hangup (and reboot via watchdog). This is because of the unaligned access in the cadence QSPI driver which is hard to prevent since the data is written into a 4-byte wide FIFO. This patch fixes this problem by changing the behavior of the last sector write (not sector aligned).

The new code is even simpler and copies the source data into the temp buffer and now uses the temp buffer to write the complete sector. So only one SPI sector write is used now instead of 2 in the old version.

Cc Gerlando Falauto <[email protected]>
Cc Valentin Longchamp <[email protected]>
Cc Holger Brunck <[email protected]>
Cc Jagannadha Sutradharudu Teki <[email protected]>
---
 common/cmd_sf.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)
common/cmd_sf.c +8 -8
index 5c788e9..dd82290 100644
@@ -163,6 +163,8 @@ static int do_spi_flash_probe(int argc, char * const argv[])
 static const char *spi_flash_update_block(struct spi_flash *flash, u32 offset,
 		size_t len, const char *buf, char *cmp_buf, size_t *skipped)
 {
+	char *ptr = (char *)buf;
+
 	debug("offset=%#x, sector_size=%#x, len=%#zx\n",
 	      offset, flash->sector_size, len);
 	/* Read the entire sector so to allow for rewriting */
@@ -178,16 +180,14 @@ static const char *spi_flash_update_block(struct spi_flash *flash, u32 offset,
 	/* Erase the entire sector */
 	if (spi_flash_erase(flash, offset, flash->sector_size))
 		return "erase";
-	/* Write the initial part of the block from the source */
-	if (spi_flash_write(flash, offset, len, buf))
-		return "write";
-	/* If it's a partial sector, rewrite the existing part */
+	/* If it's a partial sector, copy the data into the temp-buffer */
 	if (len != flash->sector_size) {
-		/* Rewrite the original data to the end of the sector */
-		if (spi_flash_write(flash, offset + len,
-				    flash->sector_size - len, &cmp_buf[len]))
-			return "write";
+		memcpy(cmp_buf, buf, len);
+		ptr = cmp_buf;
 	}
+	/* Write one complete sector */
+	if (spi_flash_write(flash, offset, flash->sector_size, ptr))
+		return "write";
 
 	return NULL;
 }
Signature · 1 line
2.2.1
#1 lore raw

PATCH 1/1 cmd_sf: Fix problem with "sf update" and unaligned length

Dear Stefan,

Quoted 4 lines · In message <[email protected]> you wrote:

The new code is even simpler and copies the source data into the temp buffer and now uses the temp buffer to write the complete sector. So only one SPI sector write is used now instead of 2 in the old version.

...

common/cmd_sf.c static const char *spi_flash_update_block(struct spi_flash *flash, u32 offset, · line 187

Quoted 8 lines
common/cmd_sf.c +2 -4
 	if (len != flash->sector_size) {
-		/* Rewrite the original data to the end of the sector */
-		if (spi_flash_write(flash, offset + len,
-				    flash->sector_size - len, &cmp_buf[len]))
-			return "write";
+		memcpy(cmp_buf, buf, len);
+		ptr = cmp_buf;
 	}

Should we add a memset(buf, 0, sizeof(buf)) before the memcpy() to prevent information from earlier activities to leak?

Best regards,

Wolfgang Denk

Signature · 4 lines
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
I read part of it all the way through.
#2 lore raw

PATCH 1/1 cmd_sf: Fix problem with "sf update" and unaligned length

Hi Wolfgang,

Quoted 5 lines · Wolfgang Denk
Quoted 3 lines

The new code is even simpler and copies the source data into the temp buffer and now uses the temp buffer to write the complete sector. So only one SPI sector write is used now instead of 2 in the old version.

...

Quoted 11 lines

common/cmd_sf.c static const char *spi_flash_update_block(struct spi_flash *flash, u32 offset, · line 187

Quoted 8 lines
  	if (len != flash->sector_size) {
common/cmd_sf.c +2 -4
-		/* Rewrite the original data to the end of the sector */
-		if (spi_flash_write(flash, offset + len,
-				    flash->sector_size - len, &cmp_buf[len]))
-			return "write";
+		memcpy(cmp_buf, buf, len);
+		ptr = cmp_buf;
  	}

Should we add a memset(buf, 0, sizeof(buf)) before the memcpy() to prevent information from earlier activities to leak?

"buf" points to the new data to be written into the flash. We're overwriting the first "len" bytes of "cmp_buf" with this data.

I don't see why we should erase anything there. Perhaps I'm missing something though.

Thanks,
Stefan

#3 lore raw

PATCH 1/1 cmd_sf: Fix problem with "sf update" and unaligned length

Hi Wolfgang,

Quoted 20 lines · Stefan Roese

Hi Wolfgang,

Quoted 5 lines · Wolfgang Denk
Quoted 3 lines

The new code is even simpler and copies the source data into the temp buffer and now uses the temp buffer to write the complete sector. So only one SPI sector write is used now instead of 2 in the old version.

...

Quoted 11 lines

common/cmd_sf.c static const char *spi_flash_update_block(struct spi_flash *flash, u32 offset, · line 187

Quoted 8 lines
   	if (len != flash->sector_size) {
common/cmd_sf.c +2 -4
-		/* Rewrite the original data to the end of the sector */
-		if (spi_flash_write(flash, offset + len,
-				    flash->sector_size - len, &cmp_buf[len]))
-			return "write";
+		memcpy(cmp_buf, buf, len);
+		ptr = cmp_buf;
   	}

Should we add a memset(buf, 0, sizeof(buf)) before the memcpy() to prevent information from earlier activities to leak?

Quoted 5 lines

"buf" points to the new data to be written into the flash. We're overwriting the first "len" bytes of "cmp_buf" with this data.

I don't see why we should erase anything there. Perhaps I'm missing something though.

That's right, and that's the whole point: cmp_buf points to the data read from the flash sector before erasing it, because that's what we want to keep (by re-writing it).
The first part, however, we overwrite with the new data (buf). So there's nothing to erase.

Thanks,
Gerlando

#4 lore raw

PATCH 1/1 cmd_sf: Fix problem with "sf update" and unaligned length

Dear Gerlando Falauto,

Quoted 6 lines · In message <[email protected]> you wrote:

That's right, and that's the whole point: cmp_buf points to the data read from the flash sector before erasing it, because that's what we want to keep (by re-writing it).
The first part, however, we overwrite with the new data (buf). So there's nothing to erase.

Well, if we have only a partially filled buffer, then there is some remainder which is left over from previous use. This should not make it to external storage. If you write any additional bytes, these should be known-to-be-harmless content, say all 0x00 or 0xFF bytes, but never any data that just happen to be there.

Best regards,

Wolfgang Denk

Signature · 5 lines
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
For every complex problem, there is a solution that is simple,  neat,
and wrong.                                           -- H. L. Mencken
#5 lore raw

PATCH 1/1 cmd_sf: Fix problem with "sf update" and unaligned length

In reply to Stefan Roese

Dear Stefan,

Quoted 6 lines · In message <[email protected]> you wrote:
Quoted 3 lines

Should we add a memset(buf, 0, sizeof(buf)) before the memcpy() to prevent information from earlier activities to leak?

"buf" points to the new data to be written into the flash. We're overwriting the first "len" bytes of "cmp_buf" with this data.

Oh, sorry for the mixup. Then cmp_buf should be cleared (or at elast the remaining, unused part).

Quoted 2 lines

I don't see why we should erase anything there. Perhaps I'm missing something though.

You are leaking data. This could contain "interesting" information; see the OpenSSL ?Heartbleed? vulnerability for a (nasty) example what information leakage can do.

Best regards,

Wolfgang Denk

Signature · 6 lines
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Very ugly or very beautiful women should be flattered on their
understanding, and mediocre ones on their beauty.
                                       -- Philip Earl of Chesterfield
#6 lore raw

PATCH 1/1 cmd_sf: Fix problem with "sf update" and unaligned length

Hi Wolfgang,

Quoted 8 lines · Wolfgang Denk
Quoted 5 lines
Quoted 2 lines

Should we add a memset(buf, 0, sizeof(buf)) before the memcpy() to prevent information from earlier activities to leak?

"buf" points to the new data to be written into the flash. We're overwriting the first "len" bytes of "cmp_buf" with this data.

Oh, sorry for the mixup. Then cmp_buf should be cleared (or at elast the remaining, unused part).

No. cmp_buf contains the original data from the flash. And only the beginning of this buffer is overwritten with the new data from "buf". So, the result of the memcpy() is that "cmp_buf" contains the data that should be written into the flash. Its a combination of the "original data" and the "new data".

Quoted 6 lines
Quoted 2 lines

I don't see why we should erase anything there. Perhaps I'm missing something though.

You are leaking data. This could contain "interesting" information; see the OpenSSL ?Heartbleed? vulnerability for a (nasty) example what information leakage can do.

There is nothing leaking here. When anything would be zeroed out, the resulting buffer would not be the one that should be used.

Viele Gr??e,
Stefan

--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-51 Fax: (+49)-8142-66989-80 Email: sr at denx.de

#7 lore raw

PATCH 1/1 cmd_sf: Fix problem with "sf update" and unaligned length

Quoted 26 lines · Stefan Roese

Hi Wolfgang,

Quoted 11 lines · Wolfgang Denk
Quoted 7 lines
Quoted 3 lines

Should we add a memset(buf, 0, sizeof(buf)) before the memcpy() to prevent information from earlier activities to leak?

"buf" points to the new data to be written into the flash. We're overwriting the first "len" bytes of "cmp_buf" with this data.

Oh, sorry for the mixup. Then cmp_buf should be cleared (or at elast the remaining, unused part).

No. cmp_buf contains the original data from the flash. And only the beginning of this buffer is overwritten with the new data from "buf". So, the result of the memcpy() is that "cmp_buf" contains the data that should be written into the flash. Its a combination of the "original data" and the "new data".

Quoted 4 lines
Quoted 2 lines

I don't see why we should erase anything there. Perhaps I'm missing something though.

Quoted 7 lines
Quoted 3 lines

You are leaking data. This could contain "interesting" information; see the OpenSSL ?Heartbleed? vulnerability for a (nasty) example what information leakage can do.

There is nothing leaking here. When anything would be zeroed out, the resulting buffer would not be the one that should be used.

I think this thread link got stopped any further update on this.

thanks!

Signature · 1 line
Jagan.
#8 lore raw

PATCH 1/1 cmd_sf: Fix problem with "sf update" and unaligned length

Quoted 29 lines · Jagan Teki
Quoted 29 lines · Wolfgang Denk
Quoted 11 lines
Quoted 7 lines
Quoted 3 lines

Should we add a memset(buf, 0, sizeof(buf)) before the memcpy() to prevent information from earlier activities to leak?

"buf" points to the new data to be written into the flash. We're overwriting the first "len" bytes of "cmp_buf" with this data.

Oh, sorry for the mixup. Then cmp_buf should be cleared (or at elast the remaining, unused part).

No. cmp_buf contains the original data from the flash. And only the beginning of this buffer is overwritten with the new data from "buf". So, the result of the memcpy() is that "cmp_buf" contains the data that should be written into the flash. Its a combination of the "original data" and the "new data".

Quoted 7 lines
Quoted 2 lines

I don't see why we should erase anything there. Perhaps I'm missing something though.

You are leaking data. This could contain "interesting" information; see the OpenSSL ?Heartbleed? vulnerability for a (nasty) example what information leakage can do.

Quoted 4 lines
Quoted 2 lines

There is nothing leaking here. When anything would be zeroed out, the resulting buffer would not be the one that should be used.

I think this thread link got stopped any further update on this.

I would have thought that this patch had been applied some time ago. If not, then please do.

Thanks,
Stefan

#9 lore raw

PATCH 1/1 cmd_sf: Fix problem with "sf update" and unaligned length

Quoted 43 lines · Stefan Roese
Quoted 42 lines · Jagan Teki
Quoted 40 lines · Wolfgang Denk
Quoted 7 lines
Quoted 7 lines
Quoted 4 lines

Should we add a memset(buf, 0, sizeof(buf)) before the memcpy() to prevent information from earlier activities to leak?

Quoted 7 lines
Quoted 2 lines

"buf" points to the new data to be written into the flash. We're overwriting the first "len" bytes of "cmp_buf" with this data.

Oh, sorry for the mixup. Then cmp_buf should be cleared (or at elast the remaining, unused part).

No. cmp_buf contains the original data from the flash. And only the beginning of this buffer is overwritten with the new data from "buf". So, the result of the memcpy() is that "cmp_buf" contains the data that should
be written into the flash. Its a combination of the "original data" and the
"new data".

Quoted 8 lines
Quoted 2 lines

I don't see why we should erase anything there. Perhaps I'm missing something though.

You are leaking data. This could contain "interesting" information; see the OpenSSL ?Heartbleed? vulnerability for a (nasty) example what information leakage can do.

There is nothing leaking here. When anything would be zeroed out, the resulting buffer would not be the one that should be used.

Quoted 5 lines
Quoted 1 line

I think this thread link got stopped any further update on this.

I would have thought that this patch had been applied some time ago. If not, then please do.

Applied to u-boot-spi/master

thanks!

Signature · 1 line
Jagan.
#10 lore raw

PATCH 1/1 cmd_sf: Fix problem with "sf update" and unaligned length

In reply to Stefan Roese

Hi Stefan,

thanks for the patch.
Please compare it with my v1 revision of the patch:
http://patchwork.ozlabs.org/patch/150468/
Back then, Simon suggested to use two separate SPI flash operations to avoid the memcpy() operation. I guess noone would have guessed about QSPI devices at the time.

Anyway, your patch looks even better than my v1 then, so:

Thank you,
Gerlando

Quoted 56 lines · Stefan Roese

On SoCFPGA, using "sf update" with an non-4byte aligned length leads to a hangup (and reboot via watchdog). This is because of the unaligned access in the cadence QSPI driver which is hard to prevent since the data is written into a 4-byte wide FIFO. This patch fixes this problem by changing the behavior of the last sector write (not sector aligned).

The new code is even simpler and copies the source data into the temp buffer and now uses the temp buffer to write the complete sector. So only one SPI sector write is used now instead of 2 in the old version.

Cc Gerlando Falauto <[email protected]>
Cc Valentin Longchamp <[email protected]>
Cc Holger Brunck <[email protected]>
Cc Jagannadha Sutradharudu Teki <[email protected]>
---
  common/cmd_sf.c | 16 ++++++++--------
  1 file changed, 8 insertions(+), 8 deletions(-)
common/cmd_sf.c +8 -8
index 5c788e9..dd82290 100644
@@ -163,6 +163,8 @@ static int do_spi_flash_probe(int argc, char * const argv[])
  static const char *spi_flash_update_block(struct spi_flash *flash, u32 offset,
  		size_t len, const char *buf, char *cmp_buf, size_t *skipped)
  {
+	char *ptr = (char *)buf;
+
  	debug("offset=%#x, sector_size=%#x, len=%#zx\n",
  	      offset, flash->sector_size, len);
  	/* Read the entire sector so to allow for rewriting */
@@ -178,16 +180,14 @@ static const char *spi_flash_update_block(struct spi_flash *flash, u32 offset,
  	/* Erase the entire sector */
  	if (spi_flash_erase(flash, offset, flash->sector_size))
  		return "erase";
-	/* Write the initial part of the block from the source */
-	if (spi_flash_write(flash, offset, len, buf))
-		return "write";
-	/* If it's a partial sector, rewrite the existing part */
+	/* If it's a partial sector, copy the data into the temp-buffer */
  	if (len != flash->sector_size) {
-		/* Rewrite the original data to the end of the sector */
-		if (spi_flash_write(flash, offset + len,
-				    flash->sector_size - len, &cmp_buf[len]))
-			return "write";
+		memcpy(cmp_buf, buf, len);
+		ptr = cmp_buf;
  	}
+	/* Write one complete sector */
+	if (spi_flash_write(flash, offset, flash->sector_size, ptr))
+		return "write";
 
  	return NULL;
  }
#11 lore raw

PATCH 1/1 cmd_sf: Fix problem with "sf update" and unaligned length

Hi Gerlando,

Quoted 5 lines · Gerlando Falauto

thanks for the patch.
Please compare it with my v1 revision of the patch:
http://patchwork.ozlabs.org/patch/150468/
Back then, Simon suggested to use two separate SPI flash operations to avoid the memcpy() operation.

This again could generate unaligned accesses which my patch version does not do.

Quoted 6 lines

I guess noone would have guessed about
QSPI devices at the time.

Anyway, your patch looks even better than my v1 then, so:

Thanks,
Stefan

#12 lore raw

PATCH 1/1 cmd_sf: Fix problem with "sf update" and unaligned length

Hi Stefan,

Quoted 11 lines · Stefan Roese

Hi Gerlando,

Quoted 5 lines · Gerlando Falauto

thanks for the patch.
Please compare it with my v1 revision of the patch:
http://patchwork.ozlabs.org/patch/150468/
Back then, Simon suggested to use two separate SPI flash operations to avoid the memcpy() operation.

This again could generate unaligned accesses which my patch version does not do.

That's right -- I was just trying to say that my v1 was actually doing the same thing as yours, and to explain why I changed it at a later point (which seemed legitimate back then). Since my new revision introduced unaligned accesses, we're now essentially reverting to the original one. That's all.

Thank you!
Gerlando

Quoted 11 lines
Quoted 7 lines

I guess noone would have guessed about
QSPI devices at the time.

Anyway, your patch looks even better than my v1 then, so:

Thanks,
Stefan