Hi,
As discussed over IRC, please apply this patch over the latest stable branch of flashrom from https://github.com/flashrom/flashrom. This is a "hacked" solution and is certainly not merge-worthy in its current state.
Patch description - When prettyprinting status register byte 1 of N25Q128 chip, also print least two significant bits of lock register for each 64 kB sector.
Thanks, Hatim
Signed-off-by: Hatim Kanchwala hatim@hatimak.me --- spi25_statusreg.c | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-)
diff --git a/spi25_statusreg.c b/spi25_statusreg.c index 266e7a9..b050ae1 100644 --- a/spi25_statusreg.c +++ b/spi25_statusreg.c @@ -454,58 +454,65 @@ static void spi_prettyprint_status_register_atmel_at25_swp(uint8_t status) }
int spi_prettyprint_status_register_at25df(struct flashctx *flash) { uint8_t status = spi_read_status_register(flash); spi_prettyprint_status_register_hex(status);
spi_prettyprint_status_register_atmel_at25_srpl(status); spi_prettyprint_status_register_bit(status, 6); spi_prettyprint_status_register_atmel_at25_epewpp(status); spi_prettyprint_status_register_atmel_at25_swp(status); spi_prettyprint_status_register_welwip(status);
- if (flash->chip->model_id == ATMEL_AT25DF161) + if (flash->chip->model_id == ST_N25Q128__3E) { int address, i, count, result; - unsigned char read_result, lockdown_status_sector[32], cmd[5]; - cmd[0] = (unsigned char)0x35; - cmd[4] = (unsigned char)0x00; + uint8_t read_result, lockdown_status_sector[flash->chip->total_size / 64], cmd[4]; + cmd[0] = (uint8_t)0xE8;
- for (address = 0x000000, i = 0, count = 0; address < 0x200000; address += 0x010000, i++) + msg_cdbg("Additional information regarding block locks for %s\n", flash->chip->name); + for (address = 0x000000, i = 0, count = 0; + address < flash->chip->total_size * 1024; + address += 0x010000, i++) { cmd[1] = (unsigned char)(address >> 16) & 0xff; cmd[2] = (unsigned char)(address >> 8) & 0xff; cmd[3] = (unsigned char)address & 0xff; - result = spi_send_command(flash, sizeof(cmd), sizeof(unsigned char), cmd, &read_result); + result = spi_send_command(flash, sizeof(cmd), sizeof(uint8_t), cmd, &read_result); if (result) { - msg_cerr("%s failed during command execution (ATMEL_AT25DF161)\n", __func__); + msg_cerr("%s failed during command execution (ST_N25Q128__3E)\n", __func__); return result; } if (i % 8 == 0) msg_cdbg("0x%02x:", i); - msg_cdbg(" %02x%s", read_result, (i + 1) % 8 == 0 ? "\n": ""); - lockdown_status_sector[address / 0x010000] = read_result; - if (read_result) + msg_cdbg(" [%s,%s]%s", + (read_result & 0x02) ? "1" : "0", + (read_result & 0x01) ? "1" : "0", + (i + 1) % 8 == 0 ? "\n": ""); + lockdown_status_sector[address / 0x010000] = read_result & 0x03; + if (read_result & 0x01) count++; }
- msg_cdbg("%d sector%s locked down permanently%s", count, (count == 1) ? "" : "s", (count == 0) ? "." : " :"); + msg_cdbg("%d sector%s locked down%s", count, (count == 1) ? "" : "s", + (count == 0) ? "." : " :"); if (count) - for (i = 0; i < 32; i++) + for (i = 0; i < ARRAY_SIZE(lockdown_status_sector); i++) if (lockdown_status_sector[i]) msg_cdbg(" %2d", i); msg_cdbg("\n"); + msg_cdbg("You _may_ be able to unlock the sector%s\n", (count == 1) ? "" : "s"); }
return 0; }
int spi_prettyprint_status_register_at25df_sec(struct flashctx *flash) { /* FIXME: We should check the security lockdown. */ msg_cdbg("Ignoring security lockdown (if present)\n"); msg_cdbg("Ignoring status register byte 2\n"); return spi_prettyprint_status_register_at25df(flash); }
Hi,
Apologies for the previous patch, it wouldn't have worked. In haste, I had based it off an older patch I had written for AT25DF161 (a similar case). I am quite positive the following patch is correct :)
Thanks :) Hatim
Signed-off-by: Hatim Kanchwala hatim@hatimak.me --- spi25_statusreg.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+)
diff --git a/spi25_statusreg.c b/spi25_statusreg.c index 01a6862..49c7b2e 100644 --- a/spi25_statusreg.c +++ b/spi25_statusreg.c @@ -10,34 +10,35 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
#include "flash.h" #include "chipdrivers.h" #include "spi.h" +#include "flashchips.h"
/* === Generic functions === */ int spi_write_status_enable(struct flashctx *flash) { static const unsigned char cmd[JEDEC_EWSR_OUTSIZE] = { JEDEC_EWSR }; int result;
/* Send EWSR (Enable Write Status Register). */ result = spi_send_command(flash, sizeof(cmd), JEDEC_EWSR_INSIZE, cmd, NULL);
if (result) msg_cerr("%s failed\n", __func__);
return result; }
static int spi_write_status_register_flag(struct flashctx *flash, int status, const unsigned char enable_opcode) @@ -645,34 +646,76 @@ int spi_disable_blockprotect_n25q(struct flashctx *flash) return spi_disable_blockprotect_generic(flash, 0x5C, 1 << 7, 0, 0xFF); }
int spi_prettyprint_status_register_n25q(struct flashctx *flash) { uint8_t status = spi_read_status_register(flash); spi_prettyprint_status_register_hex(status);
spi_prettyprint_status_register_srwd(status); if (flash->chip->total_size <= 32 / 8 * 1024) /* N25Q16 and N25Q32: reserved */ spi_prettyprint_status_register_bit(status, 6); else msg_cdbg("Chip status register: Block Protect 3 (BP3) is %sset\n", (status & (1 << 6)) ? "" : "not "); msg_cdbg("Chip status register: Top/Bottom (TB) is %s\n", (status & (1 << 5)) ? "bottom" : "top"); spi_prettyprint_status_register_bp(status, 2); spi_prettyprint_status_register_welwip(status); + + if (flash->chip->model_id == ST_N25Q128__3E) + { + int address, i, count, result; + uint8_t read_result, lockdown_status_sector[flash->chip->total_size / 64], cmd[4]; + cmd[0] = (uint8_t)0xE8; + + msg_cdbg("Additional information regarding block locks for %s\n", flash->chip->name); + for (address = 0x000000, i = 0, count = 0; + address < flash->chip->total_size * 1024; + address += 0x010000, i++) + { + cmd[1] = (unsigned char)(address >> 16) & 0xff; + cmd[2] = (unsigned char)(address >> 8) & 0xff; + cmd[3] = (unsigned char)address & 0xff; + result = spi_send_command(flash, sizeof(cmd), sizeof(uint8_t), cmd, &read_result); + if (result) + { + msg_cerr("%s failed during command execution (ST_N25Q128__3E)\n", __func__); + return result; + } + if (i % 8 == 0) + msg_cdbg("0x%02x:", i); + msg_cdbg(" [%s,%s]%s", + (read_result & 0x02) ? "1" : "0", + (read_result & 0x01) ? "1" : "0", + (i + 1) % 8 == 0 ? "\n": ""); + lockdown_status_sector[address / 0x010000] = read_result & 0x03; + if (read_result & 0x01) + count++; + } + + msg_cdbg("%d sector%s locked down%s", count, (count == 1) ? "" : "s", + (count == 0) ? "." : " :"); + if (count) + for (i = 0; i < ARRAY_SIZE(lockdown_status_sector); i++) + if (lockdown_status_sector[i]) + msg_cdbg(" %2d", i); + msg_cdbg("\n"); + msg_cdbg("You _may_ be able to unlock the sector%s\n", (count == 1) ? "" : "s"); + } + return 0; }
/* Used by Intel/Numonyx S33 and Spansion S25FL-S chips */ /* TODO: Clear P_FAIL and E_FAIL with Clear SR Fail Flags Command (30h) here? */ int spi_disable_blockprotect_bp2_ep_srwd(struct flashctx *flash) { return spi_disable_blockprotect_bp2_srwd(flash); }
/* Used by Intel/Numonyx S33 and Spansion S25FL-S chips */ int spi_prettyprint_status_register_bp2_ep_srwd(struct flashctx *flash) { uint8_t status = spi_read_status_register(flash); spi_prettyprint_status_register_hex(status);
spi_prettyprint_status_register_srwd(status);
Hi Hatim
I tried it yesterday applying the patch but couldn't succeed. Then I gave it to one of our low level embedded developer but same result. Then we decided to apply it directly into the source code since it is just one time try. I will try today your new patch and let you know about the result.
Thank you very much for your time, Regards,
Aykut
-----Original Message----- From: Hatim Kanchwala [mailto:hatim@hatimak.me] Sent: donderdag 14 juli 2016 17:42 To: Avci, Aykut Cc: flashrom@flashrom.org Subject: Re: [PATCH] Print lock register configuration for N25Q128
Hi,
Apologies for the previous patch, it wouldn't have worked. In haste, I had based it off an older patch I had written for AT25DF161 (a similar case). I am quite positive the following patch is correct :)
Thanks :) Hatim
Signed-off-by: Hatim Kanchwala hatim@hatimak.me
spi25_statusreg.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+)
diff --git a/spi25_statusreg.c b/spi25_statusreg.c index 01a6862..49c7b2e 100644 --- a/spi25_statusreg.c +++ b/spi25_statusreg.c @@ -10,34 +10,35 @@
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; version 2 of the License.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "flash.h" #include "chipdrivers.h" #include "spi.h" +#include "flashchips.h"
/* === Generic functions === */ int spi_write_status_enable(struct flashctx *flash) { static const unsigned char cmd[JEDEC_EWSR_OUTSIZE] = { JEDEC_EWSR }; int result;
/* Send EWSR (Enable Write Status Register). */ result = spi_send_command(flash, sizeof(cmd), JEDEC_EWSR_INSIZE,
cmd, NULL);
if (result) msg_cerr("%s failed\n", __func__); return result;
}
static int spi_write_status_register_flag(struct flashctx *flash, int status, const unsigned char enable_opcode) @@ -645,34 +646,76 @@ int spi_disable_blockprotect_n25q(struct flashctx *flash) return spi_disable_blockprotect_generic(flash, 0x5C, 1 << 7, 0, 0xFF); }
int spi_prettyprint_status_register_n25q(struct flashctx *flash) { uint8_t status = spi_read_status_register(flash); spi_prettyprint_status_register_hex(status);
spi_prettyprint_status_register_srwd(status); if (flash->chip->total_size <= 32 / 8 * 1024) /* N25Q16 and N25Q32:
reserved */ spi_prettyprint_status_register_bit(status, 6); else msg_cdbg("Chip status register: Block Protect 3 (BP3) is %sset\n", (status & (1 << 6)) ? "" : "not "); msg_cdbg("Chip status register: Top/Bottom (TB) is %s\n", (status & (1 << 5)) ? "bottom" : "top"); spi_prettyprint_status_register_bp(status, 2); spi_prettyprint_status_register_welwip(status);
if (flash->chip->model_id == ST_N25Q128__3E)
{
int address, i, count, result;
uint8_t read_result, lockdown_status_sector[flash->chip-
total_size / 64], cmd[4];
cmd[0] = (uint8_t)0xE8;
msg_cdbg("Additional information regarding block locks for
%s\n", flash->chip->name);
for (address = 0x000000, i = 0, count = 0;
address < flash->chip->total_size * 1024;
address += 0x010000, i++)
{
cmd[1] = (unsigned char)(address >> 16) & 0xff;
cmd[2] = (unsigned char)(address >> 8) & 0xff;
cmd[3] = (unsigned char)address & 0xff;
result = spi_send_command(flash, sizeof(cmd),
sizeof(uint8_t), cmd, &read_result);
if (result)
{
msg_cerr("%s failed during command
execution (ST_N25Q128__3E)\n", __func__);
return result;
}
if (i % 8 == 0)
msg_cdbg("0x%02x:", i);
msg_cdbg(" [%s,%s]%s",
(read_result & 0x02) ? "1" : "0",
(read_result & 0x01) ? "1" : "0",
(i + 1) % 8 == 0 ? "\n": "");
lockdown_status_sector[address / 0x010000] =
read_result & 0x03;
if (read_result & 0x01)
count++;
}
msg_cdbg("%d sector%s locked down%s", count, (count ==
- ? "" : "s",
(count == 0) ? "." : " :");
if (count)
for (i = 0; i < ARRAY_SIZE(lockdown_status_sector);
i++)
if (lockdown_status_sector[i])
msg_cdbg(" %2d", i);
msg_cdbg("\n");
msg_cdbg("You _may_ be able to unlock the sector%s\n",
(count == 1) ? "" : "s");
}
return 0;
}
/* Used by Intel/Numonyx S33 and Spansion S25FL-S chips */ /* TODO: Clear P_FAIL and E_FAIL with Clear SR Fail Flags Command (30h) here? */ int spi_disable_blockprotect_bp2_ep_srwd(struct flashctx *flash) { return spi_disable_blockprotect_bp2_srwd(flash); }
/* Used by Intel/Numonyx S33 and Spansion S25FL-S chips */ int spi_prettyprint_status_register_bp2_ep_srwd(struct flashctx *flash) { uint8_t status = spi_read_status_register(flash); spi_prettyprint_status_register_hex(status);
spi_prettyprint_status_register_srwd(status);
-- 2.7.4
This message is subject to the following terms and conditions: MAIL DISCLAIMERhttp://www.barco.com/en/maildisclaimer