Hi,
I have little problem And I would like to ask for help if is possible.
I need flash 2 types of eeprom, and I bought cheap Ch341A programmer as I
see that he "supports" EON 25F16 and EON 25F80 but I have Issue I try with
windows and with flashrom but I canno't get detection of ic's. I check
Connection of every pin between eeprom flash and ch341A and it is GOOD. in
windows I use software that I get with it but only that I get working is
detection of ch341a nothing more. Always i get eepron not found or
manufactures id FF or memory id FF hope you get point.
So I read in datasheet that eon ic's have protection blocks for write read
like 512 bit sometnig. Is it there any way to shoot that command for
enabling write read or is it programmer(CH341A) Fault .
Thanks,
H
Hello Timothy and David,
I have attached a patch that adds support for W25Q128BV and W25Q128FV chips (I noticed Timothy needed these chips;) so I added only these for now). This patch should be applied on top of all my most recent patches. Instead of downloading and locally applying all those patches and then applying the attached one, I recommend you clone my fork of flashrom (dev branch) from GitHub (https://github.com/hatimak/flashrom/tree/dev). I have already pushed the attached patch there ;)
Now, on how to use it. Once you compile and install it, have a look at the man page and the --help output. If you run --wp-list, you can see the access protection table. For you particular case you will need --wp-set-range start=0xfff000,len=4. This will lock the top 4kB of either or W25Q128BV or W25Q128FV. The man page will explain how you can set status register write protection if you need that. If it happens that you need OTP support for these chips, that is available as well :)
The CLI is arguably not the best, but this is a more general solution than what you sent. I hope this is sufficient and helps you out. Feel free to reach out for any comments/feedback/help over mail or IRC (hatim on #flashrom).
Thanks,
Hatim
On Wednesday 24 August 2016 05:42 AM, David Hendricks wrote:
> Hi Timothy,
> Check out Hatim's GSOC work for manipulating status register and write protect bits:
> https://patchwork.coreboot.org/patch/4471/
> https://patchwork.coreboot.org/patch/4472/
> https://patchwork.coreboot.org/patch/4469/
> https://patchwork.coreboot.org/patch/4467/
> https://patchwork.coreboot.org/patch/4468/
> https://patchwork.coreboot.org/patch/4470/
>
> There's also similar work done in Chromium.org fork of flashrom which might do what you need (--wp-enable command): https://chromium.googlesource.com/chromiumos/third_party/flashrom/
>
Thanks David for your reply :) Seeing my work being used and recommended feels extraordinarily happy ;)
>
> On Tue, Aug 23, 2016 at 2:32 PM, Timothy Pearson <tpearson(a)raptorengineering.com <mailto:tpearson@raptorengineering.com>> wrote:
>
> RFC PATCH
>
> TPM-enabled systems require an immutable (or at least very difficult to modify) CRTM, which can be provided via a locked bootblock sector.
>
> Add initial support for locking the upper 4K sector on Winbond Flash ROMs. Unlocking the sector after it has been locked requires hardware access to the write protect pin, satisfying the above requirements for many use cases.
>
> To use, pass the --lock flag to Flashrom. This flag can be used in isolation, or as part of a normal read / write / verify cycle.
>
Timothy, thanks for your patch :) Hope what I explained above is helpful to you. And I would gently point out that you forgot the "Signed-off-by" tag in your patch :)
> Index: spi25_statusreg.c
> ===================================================================
> --- spi25_statusreg.c (revision 1955)
> +++ spi25_statusreg.c (working copy)
> @@ -123,6 +123,78 @@
> return readarr[0];
> }
>
> +static uint8_t spi_read_status_register_2(struct flashctx *flash)
> +{
> + static const unsigned char cmd[JEDEC_RDSR_OUTSIZE] = { JEDEC_RDSR2 };
> + /* FIXME: No workarounds for driver/hardware bugs in generic code. */
> + unsigned char readarr[2]; /* JEDEC_RDSR2_INSIZE=1 but wbsio needs 2 */
> + int ret;
> +
> + /* Read Status Register */
> + ret = spi_send_command(flash, sizeof(cmd), sizeof(readarr), cmd, readarr);
> + if (ret)
> + msg_cerr("RDSR2 failed!\n");
> +
> + return readarr[0];
> +}
> +
> +/* Winbond sector protection enable that tries to set the status register bits given. */
> +int spi_enable_sectorprotect_winbond(struct flashctx *flash, const uint8_t status_flags)
> +{
> + uint8_t status, status2;
> + int result;
> + uint8_t lock_mask = 0x80;
> + uint8_t lock2_mask = 0x1;
> +
> + status = spi_read_status_register(flash);
> + status2 = spi_read_status_register_2(flash);
> + if ((status & lock_mask) != 0) {
> + msg_cdbg("\n\tNeed to disable the register lock first... ");
> + if ((status2 & lock2_mask) != 0) {
> + msg_cerr("Hardware protection is active, enabling write protection is impossible.\n");
> + return 1;
> + }
> + /* All bits except the register lock bit (often called SPRL, SRWD, WPEN) are readonly. */
> + result = spi_write_status_register(flash, status & ~lock_mask);
> + if (result) {
> + msg_cerr("spi_write_status_register failed.\n");
> + return result;
> + }
> + status = spi_read_status_register(flash);
> + if ((status & lock_mask) != 0) {
> + msg_cerr("Unsetting lock bit(s) failed.\n");
> + return 1;
> + }
> + msg_cdbg("done.\n");
> + }
> +
> + /* Set requested protect bits */
> + result = spi_write_status_register(flash, status | (status_flags << 2) );
> + if (result) {
> + msg_cerr("spi_write_status_register failed.\n");
> + return result;
> + }
> + status = spi_read_status_register(flash);
> + if ((status & (status_flags << 2)) != (status_flags << 2)) {
> + msg_cerr("Setting lock bit(s) failed.\n");
> + return 1;
> + }
> +
> + /* Set lock bit */
> + result = spi_write_status_register(flash, status | lock_mask);
> + if (result) {
> + msg_cerr("spi_write_status_register failed.\n");
> + return result;
> + }
> + status = spi_read_status_register(flash);
> + if ((status & lock_mask) == 0) {
> + msg_cerr("Setting lock bit(s) failed.\n");
> + return 1;
> + }
> +
> + return 0;
> +}
> +
> /* A generic block protection disable.
> * Tests if a protection is enabled with the block protection mask (bp_mask) and returns success otherwise.
> * Tests if the register bits are locked with the lock_mask (lock_mask).
> Index: flashrom.c
> ===================================================================
> --- flashrom.c (revision 1955)
> +++ flashrom.c (working copy)
> @@ -1977,7 +1977,7 @@
> * Besides that, the function itself is a textbook example of abysmal code flow.
> */
> int doit(struct flashctx *flash, int force, const char *filename, int read_it,
> - int write_it, int erase_it, int verify_it)
> + int write_it, int erase_it, int verify_it, int lock_it)
> {
> uint8_t *oldcontents;
> uint8_t *newcontents;
> @@ -2129,6 +2129,13 @@
> msg_cinfo("VERIFIED.\n");
> }
>
> + if (lock_it && flash->chip->lock) {
> + msg_cinfo("Locking upper 4K (bootblock)... ");
> + ret = flash->chip->lock(flash, 0x11);
> + if (!ret)
> + msg_cinfo("LOCKED.\n");
> + }
> +
> out:
> free(oldcontents);
> free(newcontents);
> Index: cli_classic.c
> ===================================================================
> --- cli_classic.c (revision 1955)
> +++ cli_classic.c (working copy)
> @@ -49,6 +49,7 @@
> " -r | --read <file> read flash and save to <file>\n"
> " -w | --write <file> write <file> to flash\n"
> " -v | --verify <file> verify flash against <file>\n"
> + " -u | --lock lock upper Flash region (typically the 4K bootblock)\n"
> " -E | --erase erase flash memory\n"
> " -V | --verbose more verbose output\n"
> " -c | --chip <chipname> probe only for specified flash chip\n"
> @@ -101,18 +102,19 @@
> #if CONFIG_PRINT_WIKI == 1
> int list_supported_wiki = 0;
> #endif
> - int read_it = 0, write_it = 0, erase_it = 0, verify_it = 0;
> + int read_it = 0, write_it = 0, erase_it = 0, verify_it = 0, lock_it = 0;
> int dont_verify_it = 0, list_supported = 0, operation_specified = 0;
> enum programmer prog = PROGRAMMER_INVALID;
> int ret = 0;
>
> - static const char optstring[] = "r:Rw:v:nVEfc:l:i:p:Lzho:";
> + static const char optstring[] = "r:Rw:v:nuVEfc:l:i:p:Lzho:";
> static const struct option long_options[] = {
> {"read", 1, NULL, 'r'},
> {"write", 1, NULL, 'w'},
> {"erase", 0, NULL, 'E'},
> {"verify", 1, NULL, 'v'},
> {"noverify", 0, NULL, 'n'},
> + {"lock", 0, NULL, 'u'},
> {"chip", 1, NULL, 'c'},
> {"verbose", 0, NULL, 'V'},
> {"force", 0, NULL, 'f'},
> @@ -187,6 +189,9 @@
> }
> dont_verify_it = 1;
> break;
> + case 'u':
> + lock_it = 1;
> + break;
> case 'c':
> chip_to_probe = strdup(optarg);
> break;
> @@ -522,7 +527,7 @@
> goto out_shutdown;
> }
>
> - if (!(read_it | write_it | verify_it | erase_it)) {
> + if (!(read_it | write_it | verify_it | erase_it | lock_it)) {
> msg_ginfo("No operations were specified.\n");
> goto out_shutdown;
> }
> @@ -542,7 +547,7 @@
> * Give the chip time to settle.
> */
> programmer_delay(100000);
> - ret |= doit(fill_flash, force, filename, read_it, write_it, erase_it, verify_it);
> + ret |= doit(fill_flash, force, filename, read_it, write_it, erase_it, verify_it, lock_it);
>
> unmap_flash(fill_flash);
> out_shutdown:
> Index: flashchips.c
> ===================================================================
> --- flashchips.c (revision 1955)
> +++ flashchips.c (working copy)
> @@ -14581,6 +14581,7 @@
> },
> .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */
> .unlock = spi_disable_blockprotect,
> + .lock = spi_enable_sectorprotect_winbond,
> .write = spi_chip_write_256,
> .read = spi_chip_read,
> .voltage = {2700, 3600},
> Index: chipdrivers.h
> ===================================================================
> --- chipdrivers.h (revision 1955)
> +++ chipdrivers.h (working copy)
> @@ -73,6 +73,7 @@
> int spi_prettyprint_status_register_bp4_srwd(struct flashctx *flash);
> int spi_prettyprint_status_register_bp2_bpl(struct flashctx *flash);
> int spi_prettyprint_status_register_bp2_tb_bpl(struct flashctx *flash);
> +int spi_enable_sectorprotect_winbond(struct flashctx *flash, const uint8_t status_flags);
> int spi_disable_blockprotect(struct flashctx *flash);
> int spi_disable_blockprotect_bp1_srwd(struct flashctx *flash);
> int spi_disable_blockprotect_bp2_srwd(struct flashctx *flash);
> Index: flash.h
> ===================================================================
> --- flash.h (revision 1955)
> +++ flash.h (working copy)
> @@ -200,6 +200,7 @@
> } block_erasers[NUM_ERASEFUNCTIONS];
>
> int (*printlock) (struct flashctx *flash);
> + int (*lock) (struct flashctx *flash, const uint8_t status_flags);
> int (*unlock) (struct flashctx *flash);
> int (*write) (struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len);
> int (*read) (struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len);
> @@ -281,7 +282,7 @@
> void print_banner(void);
> void list_programmers_linebreak(int startcol, int cols, int paren);
> int selfcheck(void);
> -int doit(struct flashctx *flash, int force, const char *filename, int read_it, int write_it, int erase_it, int verify_it);
> +int doit(struct flashctx *flash, int force, const char *filename, int read_it, int write_it, int erase_it, int verify_it, int lock_it);
> int read_buf_from_file(unsigned char *buf, unsigned long size, const char *filename);
> int write_buf_to_file(const unsigned char *buf, unsigned long size, const char *filename);
>
> Index: spi.h
> ===================================================================
> --- spi.h (revision 1955)
> +++ spi.h (working copy)
> @@ -121,6 +121,11 @@
> #define JEDEC_RDSR_OUTSIZE 0x01
> #define JEDEC_RDSR_INSIZE 0x01
>
> +/* Read Status Register 2 */
> +#define JEDEC_RDSR2 0x35
> +#define JEDEC_RDSR2_OUTSIZE 0x01
> +#define JEDEC_RDSR2_INSIZE 0x01
> +
> /* Status Register Bits */
> #define SPI_SR_WIP (0x01 << 0)
> #define SPI_SR_WEL (0x01 << 1)
>
> _______________________________________________
> flashrom mailing list
> flashrom(a)flashrom.org <mailto:flashrom@flashrom.org>
> https://www.flashrom.org/mailman/listinfo/flashrom <https://www.flashrom.org/mailman/listinfo/flashrom>
>
>
>
>
> --
> David Hendricks (dhendrix)
> Systems Software Engineer, Google Inc.
On Thu, 25 Aug 2016 19:41:33 +0200
Rudolf Dovičín <rudolf.dovicin(a)gmail.com> wrote:
> Hello flashers. :-)
>
> I try rewrite BIOS on ThinkPad X200 by instructions on:
> https://Libreboot.org/docs/install/x200_external.html
>
> I use OrangePi PC instead of BeagleBone Black.
>
> When I try to read from chip with command:
> flashrom -p linux_spi:dev=/dev/spidev0.0,spispeed=512 -r factory_1.rom
> I get reply with "Multiple flash chip definitions match the detected chip...".
>
> When I try to add any of detected chips to command line parameter, e. g.
> flashrom -p linux_spi:dev=/dev/spidev0.0,spispeed=512 -r factory_1.rom
> -c "MX25L6405"
> I get error "No EEPROM/flash device found."
>
> Please, where can be the problem?
Hi Rudolf,
what you are seeing is just an artifact of the bad connection between
the programmer and the chip/board. If you look at the verbose log
output you will see that the RDID replies will vary (although they
should always be the same).
Flashing the X200 is annoying. With some hacks you might improve the
result though. One example for another programmer can be found here:
https://patchwork.coreboot.org/patch/4322/
--
Kind regards/Mit freundlichen Grüßen, Stefan Tauner
Hello flashers. :-)
I try rewrite BIOS on ThinkPad X200 by instructions on:
https://Libreboot.org/docs/install/x200_external.html
I use OrangePi PC instead of BeagleBone Black.
When I try to read from chip with command:
flashrom -p linux_spi:dev=/dev/spidev0.0,spispeed=512 -r factory_1.rom
I get reply with "Multiple flash chip definitions match the detected chip...".
When I try to add any of detected chips to command line parameter, e. g.
flashrom -p linux_spi:dev=/dev/spidev0.0,spispeed=512 -r factory_1.rom
-c "MX25L6405"
I get error "No EEPROM/flash device found."
Please, where can be the problem?
--
Rudolf Dovičín
Partizánska 1506/92-34
957 01 Bánovce nad Bebravou 1
SLOVENSKO
mailto:Rudolf.Dovicin@Gmail.com
xmpp:ruwolf@jabbim.sk
(cellular: +421 940 872 846, short messages only)
flashrom v0.9.8-r1888 on Linux 4.4.6-gentoo (x86_64)
flashrom is free software, get the source code at http://www.flashrom.org
flashrom was built with libpci 3.4.1, GCC 4.9.3, little endian
Command line (3 args): flashrom -V -p internal
Calibrating delay loop... OS timer resolution is 1 usecs, 1715M loops per
second, 10 myus = 10 us, 100 myus = 111 us, 1000 myus = 1016 us, 10000 myus
= 9999 us, 4 myus = 4 us, OK.
Initializing internal programmer
No coreboot table found.
Using Internal DMI decoder.
DMI chassis-type is not specific enough.
DMI string system-manufacturer: "Dell Inc."
DMI string system-product-name: "OptiPlex 980 "
DMI string system-version: "Not Specified"
DMI string baseboard-manufacturer: "Dell Inc."
DMI string baseboard-product-name: "0C522T"
DMI string baseboard-version: "A00"
========================================================================
WARNING! You may be running flashrom on an unsupported laptop. We could
not detect this for sure because your vendor has not setup the SMBIOS
tables correctly. You can enforce execution by adding
'-p internal:laptop=this_is_not_a_laptop' to the command line, but
please read the following warning if you are not sure.
Laptops, notebooks and netbooks are difficult to support and we
recommend to use the vendor flashing utility. The embedded controller
(EC) in these machines often interacts badly with flashing.
See the manpage and http://www.flashrom.org/Laptops for details.
If flash is shared with the EC, erase is guaranteed to brick your laptop
and write may brick your laptop.
Read and probe may irritate your EC and cause fan failure, backlight
failure and sudden poweroff.
You have been warned.
========================================================================
Aborting.
Error: Programmer initialization failed.
--
upen,
emerge -uD life (Upgrade Life with dependencies)
Hi all,
I have a T420 with Macronix MX25L6406E flash. flashrom's first erase algorithm fails, the second succeeds, which is obviously not fatal, but means an unimportant (internal flasher), annoying (raspi) to painful (arduino) delay. Would be awesome if the second erase algorithm could be default for this chip!
best regards,
Arian
bad quality pictures:
https://semioptimal.net/t420_flash_side.jpghttps://semioptimal.net/t420_onlyflash.jpg
relevant flashrom output:
Found Macronix flash chip "MX25L6405" (8192 kB, SPI) mapped at physical address 0x00000000ff800000.
Reading old flash chip contents... done.
Erasing and writing flash chip... FAILED at 0x00001000! Expected=0xff, Found=0x00, failed byte count from 0x00000000-0x0000ffff: 0x1653
ERASE FAILED!
Reading current flash chip contents... done. Looking for another erase function.
Erase/write done.
Verifying flash... VERIFIED.