Commit 7ac760c2 authored by Artem Bityutskiy's avatar Artem Bityutskiy

UBI: fix corrupted PEB detection for NOR flash

My new shiny code for corrupted PEB detection has NOR specific bug.
We tread PEB as corrupted and preserve it, if

1. EC header is OK.
2. VID header is corrupted.
3. data area is not "all 0xFFs"

In case of NOR we have 'nor_erase_prepare()' quirk, which invalidates
the headers before erasing the PEB. And we invalidate first the VID
header, and then the EC header. So if a power cut happens after we have
invalidated the VID header, but before we have invalidated the EC
header, we end up with a PEB which satisfies the above 3 conditions,
and the scanning code will treat it as corrupted, and will print
scary warnings, wrongly.

This patch fixes the issue by firt invalidating the EC header, then
invalidating the VID header. In case of power cut inbetween, we still
just lose the EC header, and UBI can deal with this situation gracefully.

Thanks to Anatolij Gustschin <agust@denx.de> for tracking this down.
Signed-off-by: default avatarArtem Bityutskiy <Artem.Bityutskiy@nokia.com>
Reported-by: default avatarAnatolij Gustschin <agust@denx.de>
Tested-by: default avatarAnatolij Gustschin <agust@denx.de>
parent e8a7e48b
...@@ -482,10 +482,17 @@ static int nor_erase_prepare(struct ubi_device *ubi, int pnum) ...@@ -482,10 +482,17 @@ static int nor_erase_prepare(struct ubi_device *ubi, int pnum)
uint32_t data = 0; uint32_t data = 0;
struct ubi_vid_hdr vid_hdr; struct ubi_vid_hdr vid_hdr;
addr = (loff_t)pnum * ubi->peb_size + ubi->vid_hdr_aloffset; /*
* It is important to first invalidate the EC header, and then the VID
* header. Otherwise a power cut may lead to valid EC header and
* invalid VID header, in which case UBI will treat this PEB as
* corrupted and will try to preserve it, and print scary warnings (see
* the header comment in scan.c for more information).
*/
addr = (loff_t)pnum * ubi->peb_size;
err = ubi->mtd->write(ubi->mtd, addr, 4, &written, (void *)&data); err = ubi->mtd->write(ubi->mtd, addr, 4, &written, (void *)&data);
if (!err) { if (!err) {
addr -= ubi->vid_hdr_aloffset; addr += ubi->vid_hdr_aloffset;
err = ubi->mtd->write(ubi->mtd, addr, 4, &written, err = ubi->mtd->write(ubi->mtd, addr, 4, &written,
(void *)&data); (void *)&data);
if (!err) if (!err)
...@@ -494,18 +501,24 @@ static int nor_erase_prepare(struct ubi_device *ubi, int pnum) ...@@ -494,18 +501,24 @@ static int nor_erase_prepare(struct ubi_device *ubi, int pnum)
/* /*
* We failed to write to the media. This was observed with Spansion * We failed to write to the media. This was observed with Spansion
* S29GL512N NOR flash. Most probably the eraseblock erasure was * S29GL512N NOR flash. Most probably the previously eraseblock erasure
* interrupted at a very inappropriate moment, so it became unwritable. * was interrupted at a very inappropriate moment, so it became
* In this case we probably anyway have garbage in this PEB. * unwritable. In this case we probably anyway have garbage in this
* PEB.
*/ */
err1 = ubi_io_read_vid_hdr(ubi, pnum, &vid_hdr, 0); err1 = ubi_io_read_vid_hdr(ubi, pnum, &vid_hdr, 0);
if (err1 == UBI_IO_BAD_HDR_EBADMSG || err1 == UBI_IO_BAD_HDR) {
struct ubi_ec_hdr ec_hdr;
err1 = ubi_io_read_ec_hdr(ubi, pnum, &ec_hdr, 0);
if (err1 == UBI_IO_BAD_HDR_EBADMSG || err1 == UBI_IO_BAD_HDR) if (err1 == UBI_IO_BAD_HDR_EBADMSG || err1 == UBI_IO_BAD_HDR)
/* /*
* The VID header is corrupted, so we can safely erase this * Both VID and EC headers are corrupted, so we can
* PEB and not afraid that it will be treated as a valid PEB in * safely erase this PEB and not afraid that it will be
* case of an unclean reboot. * treated as a valid PEB in case of an unclean reboot.
*/ */
return 0; return 0;
}
/* /*
* The PEB contains a valid VID header, but we cannot invalidate it. * The PEB contains a valid VID header, but we cannot invalidate it.
......
...@@ -953,6 +953,10 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, ...@@ -953,6 +953,10 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
* impossible to distinguish it from a PEB which just * impossible to distinguish it from a PEB which just
* contains garbage because of a power cut during erase * contains garbage because of a power cut during erase
* operation. So we just schedule this PEB for erasure. * operation. So we just schedule this PEB for erasure.
*
* Besides, in case of NOR flash, we deliberatly
* corrupt both headers because NOR flash erasure is
* slow and can start from the end.
*/ */
err = 0; err = 0;
else else
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment