Question

I'm trying to erase a NOR Flash memory with Linux MTD driver in C...

I'm confused about the return status from the ioctl(MEMUNLOCK) call which returns an error even if ioctl(MEMERASE) is successful after it.

The following code displays the warning message but works (i.e. the Flash block has been erased):

int erase_MTD_Pages(int fd, size_t size, off_t offset)
{
    mtd_info_t   mtd_info;
    erase_info_t ei;

    ioctl(fd, MEMGETINFO, &mtd_info);
    ei.length = mtd_info.erasesize;

    for(ei.start = offset; ei.start < (offset+size); ei.start += mtd_info.erasesize) {
        if(ioctl(fd, MEMUNLOCK, &ei) < 0)
        {
//          logPrintf(FAILURE, "[Flash] Can not unlock MTD (MEMUNLOCK, errno=%d)!\n", errno);
//          return RETURN_FILE_ERROR;
            logPrintf(WARNING, "[Flash] Can not unlock MTD (MEMUNLOCK, errno=%d)!\n", errno);

        }
        if(ioctl(fd, MEMERASE, &ei) < 0)
        {
            logPrintf(FAILURE, "[Flash] Can not erase MTD (MEMERASE, errno=%d)!\n", errno);
            return RETURN_FILE_ERROR;
        }
    }
    return RETURN_SUCCESS;
}

When I look some C codes on the net, the return status from MEMUNLOCK is not always checked (e.g. from mtc.c):

ioctl(fd, MEMUNLOCK, &mtdEraseInfo);
if(ioctl(fd, MEMERASE, &mtdEraseInfo)) {
    fprintf(stderr, "Could not erase MTD device: %s\n", mtd);
    close(fd);
    exit(1);
}

flash_unlock also returns an error:

root $ cat /proc/mtd
dev:    size   erasesize  name
mtd0: 00020000 00020000 "X-Loader-NOR"
mtd1: 000a0000 00020000 "U-Boot-NOR"
mtd2: 00040000 00020000 "Boot Env-NOR"
mtd3: 00400000 00020000 "Kernel-NOR"
mtd4: 03b00000 00020000 "File System-NOR"

root $ mtd_debug info /dev/mtd3
mtd.type = MTD_NORFLASH
mtd.flags = MTD_CAP_NORFLASH
mtd.size = 4194304 (4M)
mtd.erasesize = 131072 (128K)
mtd.writesize = 1
mtd.oobsize = 0
regions = 0

root $ flash_unlock /dev/mtd3
Could not unlock MTD device: /dev/mtd3

Am I missing something? Is it normal to get an error from MEMUNLOCK with some configurations?

Notes / Environment:

  • The read-only flag (MTD_WRITEABLE) in not set on the mtd3 partition (only on mtd0 and mtd1).
  • flash_lock also returns the same error.
  • TI AM3505 (ARM Cortex A8, OMAP34).
  • Linux 2.6.37.
  • Flash NOR Spansion S29GL512S12DHIV1.

Kernel log:

mtdoops: mtd device (mtddev=name/number) must be supplied
physmap platform flash device: 08000000 at 08000000
physmap-flash.0: Found 1 x16 devices at 0x0 in 16-bit bank. Manufacturer ID 0x000001 Chip ID 0x002301
Amd/Fujitsu Extended Query Table at 0x0040
  Amd/Fujitsu Extended Query version 1.5.
  Silicon revision: 14
  Address sensitive unlock: Required
  Erase Suspend: Read/write
  Block protection: 1 sectors per group
  Temporary block unprotect: Not supported
  Block protect/unprotect scheme: 8
  Number of simultaneous operations: 0
  Burst mode: Not supported
  Page mode: 12 word page
  Vpp Supply Minimum Program/Erase Voltage: 0.0 V
  Vpp Supply Maximum Program/Erase Voltage: 0.0 V
  Top/Bottom Boot Block: Uniform, Top WP
number of CFI chips: 1
RedBoot partition parsing not available
Using physmap partition information
Creating 5 MTD partitions on "physmap-flash.0":
0x000000000000-0x000000020000 : "X-Loader-NOR"
0x000000020000-0x0000000c0000 : "U-Boot-NOR"
0x0000000c0000-0x000000100000 : "Boot Env-NOR"
0x000000100000-0x000000500000 : "Kernel-NOR"
0x000000500000-0x000004000000 : "File System-NOR"
Was it helpful?

Solution

For a flash chip that I worked on (drivers/mtd/devices/m25p80.c), I found that UNLOCK was not implemented. The driver's ioctl(UNLOCK) returned -EOPNOTSUPP=95. And code inspection showed mtd_unlock return status being dropped on the floor, as you have found.

These imply assumptions in the m25p80 driver that flash will just never be locked, and in the mtd drivers that it's OK for the device driver to omit UNLOCK. On the board I worked on, flash was being locked by u-boot after every write, so erase and reprogram from linux didn't work at all. I looked at u-boot driver and device datasheet, got some code to implement m25p80_lock and m25p80_unlock, it was not too difficult after I knew what was up. I did not upstream it.

It does seem like a defect for chip drivers to not implement these.

By the way Mousstix, very nice job providing full information in this question.

OTHER TIPS

On newer Kernels (tested on 4.1.18) there is an device-tree option named "use-advanced-sector-protection;" When this is set, I was able to erase/write to protected flash-regions. It is also documented in the Kernel: Documentation/devicetree/bindings/mtd/mtd-physmap.txt

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top