diff --git a/storage/imxrt-flash/flashsrv.c b/storage/imxrt-flash/flashsrv.c index ef9a9ae5..8dc68a2a 100644 --- a/storage/imxrt-flash/flashsrv.c +++ b/storage/imxrt-flash/flashsrv.c @@ -47,6 +47,8 @@ #define IMXRT_FLASH_PRIO 3 #endif +#define CRC32_BUFSZ 1024 + /* clang-format off */ enum { flashsrv_memory_inactive = 0, flashsrv_memory_active = 0xff }; /* clang-format on */ @@ -166,6 +168,54 @@ static int flashsrv_chipErase(uint8_t fID) } +static uint32_t flashsrv_crc32Update(uint32_t crc32, const uint8_t *data, size_t len) +{ + unsigned int i; + + while (len--) { + crc32 ^= *data++; + for (i = 0; i < 8; i++) { + crc32 = (crc32 >> 1) ^ ((crc32 & 1) ? 0xedb88320 : 0); + } + } + + return crc32; +} + + +static int flashsrv_calcCrc32(uint8_t fID, size_t offset, size_t len, uint32_t *crc32) +{ + flashsrv_memory_t *mem; + uint8_t buf[CRC32_BUFSZ]; + uint32_t tmp; + unsigned int i; + int res; + + res = flashsrv_getFlashMemory(fID, &mem); + if (res < 0) { + return res; + } + + tmp = 0xffffffff; + + while (len > 0) { + res = flash_directRead(&mem->ctx, offset, buf, len < sizeof(buf) ? len : sizeof(buf)); + if (res < 0) { + return res; + } + + tmp = flashsrv_crc32Update(tmp, buf, res); + + offset += res; + len -= res; + } + + *crc32 = ~tmp; + + return EOK; +} + + /* Callbacks to meterfs - wrappers for basic flash functions */ static ssize_t flashsrv_fsWritef0(struct _meterfs_devCtx_t *devCtx, off_t offs, const void *buff, size_t bufflen) @@ -219,6 +269,7 @@ static int flashsrv_fsEraseSectorf1(struct _meterfs_devCtx_t *devCtx, off_t offs static void flashsrv_devCtl(flashsrv_memory_t *memory, msg_t *msg) { uint8_t fID; + uint32_t crc32; flash_i_devctl_t *idevctl = (flash_i_devctl_t *)msg->i.raw; flash_o_devctl_t *odevctl = (flash_o_devctl_t *)msg->o.raw; @@ -249,12 +300,12 @@ static void flashsrv_devCtl(flashsrv_memory_t *memory, msg_t *msg) break; case flashsrv_devctl_eraseSector: - TRACE("imxrt-flashsrv: flashsrv_devctl_eraseSector - addr: %u, id: %u, port: %u.", idevctl->addr, msg->oid.id, msg->oid.port); - if (idevctl->addr >= memory->ctx.properties.size) { + TRACE("imxrt-flashsrv: flashsrv_devctl_eraseSector - addr: %u, id: %u, port: %u.", idevctl->erase.addr, msg->oid.id, msg->oid.port); + if (idevctl->erase.addr >= memory->ctx.properties.size) { msg->o.err = -EINVAL; break; } - flashsrv_eraseSector(memory->fOid.id, idevctl->addr); + flashsrv_eraseSector(memory->fOid.id, idevctl->erase.addr); msg->o.err = EOK; break; @@ -266,26 +317,43 @@ static void flashsrv_devCtl(flashsrv_memory_t *memory, msg_t *msg) case flashsrv_devctl_directWrite: TRACE("imxrt-flashsrv: flashsrv_devctl_directWrite, addr: %u, size: %u, id: %u, port: %u.", - idevctl->addr, msg->i.size, msg->oid.id, msg->oid.port); + idevctl->write.addr, msg->i.size, msg->oid.id, msg->oid.port); - if (idevctl->addr >= memory->ctx.properties.size) { + if (idevctl->write.addr >= memory->ctx.properties.size) { msg->o.err = -EINVAL; break; } - msg->o.err = flashsrv_directWrite(memory->fOid.id, idevctl->addr, msg->i.data, msg->i.size); + msg->o.err = flashsrv_directWrite(memory->fOid.id, idevctl->write.addr, msg->i.data, msg->i.size); break; case flashsrv_devctl_directRead: TRACE("imxrt-flashsrv: flashsrv_devctl_directRead, addr: %u, size: %u, id: %u, port: %u.", - idevctl->addr, msg->o.size, msg->oid.id, msg->oid.port); + idevctl->read.addr, msg->o.size, msg->oid.id, msg->oid.port); + + if (idevctl->read.addr >= memory->ctx.properties.size) { + msg->o.err = -EINVAL; + break; + } + + msg->o.err = flashsrv_directRead(memory->fOid.id, idevctl->read.addr, msg->o.data, msg->o.size); + break; - if (idevctl->addr >= memory->ctx.properties.size) { + case flashsrv_devctl_calcCrc32: + TRACE("imxrt-flashsrv: flashsrv_devctl_calcCrc32, addr: %u, len: %u, id: %u, port: %u.", + idevctl->crc32.addr, idevctl->crc32.len, msg->oid.id, msg->oid.port); + + if (idevctl->crc32.addr == 0 && idevctl->crc32.len == 0) { + /* calculate CRC for whole flash */ + idevctl->crc32.len = memory->ctx.properties.size; + } + else if ((idevctl->crc32.addr + idevctl->crc32.len) > memory->ctx.properties.size) { msg->o.err = -EINVAL; break; } - msg->o.err = flashsrv_directRead(memory->fOid.id, idevctl->addr, msg->o.data, msg->o.size); + msg->o.err = flashsrv_calcCrc32(memory->fOid.id, idevctl->crc32.addr, idevctl->crc32.len, &crc32); + odevctl->crc32 = crc32; break; default: @@ -300,6 +368,7 @@ static void flashsrv_rawCtl(flashsrv_memory_t *memory, msg_t *msg) int i; uint32_t sNb; uint8_t partID; + uint32_t crc32; flash_i_devctl_t *idevctl = (flash_i_devctl_t *)msg->i.raw; flash_o_devctl_t *odevctl = (flash_o_devctl_t *)msg->o.raw; @@ -336,14 +405,14 @@ static void flashsrv_rawCtl(flashsrv_memory_t *memory, msg_t *msg) case flashsrv_devctl_eraseSector: TRACE("imxrt-flashsrv: flashsrv_devctl_eraseSector - addr: %u, id: %u, port: %u.", - idevctl->addr + memory->parts[partID].pHeader->offset, partID, msg->oid.port); + idevctl->erase.addr + memory->parts[partID].pHeader->offset, partID, msg->oid.port); - if (idevctl->addr >= memory->parts[msg->oid.id].pHeader->size) { + if (idevctl->erase.addr >= memory->parts[msg->oid.id].pHeader->size) { msg->o.err = -EINVAL; break; } - flashsrv_eraseSector(memory->fOid.id, memory->parts[partID].pHeader->offset + idevctl->addr); + flashsrv_eraseSector(memory->fOid.id, memory->parts[partID].pHeader->offset + idevctl->erase.addr); msg->o.err = EOK; break; @@ -360,26 +429,43 @@ static void flashsrv_rawCtl(flashsrv_memory_t *memory, msg_t *msg) case flashsrv_devctl_directWrite: TRACE("imxrt-flashsrv: flashsrv_devctl_directWrite, addr: %u, size: %u, id: %u, port: %u.", - idevctl->addr + memory->parts[partID].pHeader->offset, msg->i.size, msg->oid.id, msg->oid.port); + idevctl->write.addr + memory->parts[partID].pHeader->offset, msg->i.size, msg->oid.id, msg->oid.port); - if (idevctl->addr >= memory->parts[msg->oid.id].pHeader->size) { + if (idevctl->write.addr >= memory->parts[msg->oid.id].pHeader->size) { msg->o.err = -EINVAL; break; } - msg->o.err = flashsrv_directWrite(memory->fOid.id, memory->parts[partID].pHeader->offset + idevctl->addr, msg->i.data, msg->i.size); + msg->o.err = flashsrv_directWrite(memory->fOid.id, memory->parts[partID].pHeader->offset + idevctl->write.addr, msg->i.data, msg->i.size); break; case flashsrv_devctl_directRead: TRACE("imxrt-flashsrv: flashsrv_devctl_directRead, addr: %u, size: %u, id: %u, port: %u.", - idevctl->addr + memory->parts[partID].pHeader->offset, msg->o.size, msg->oid.id, msg->oid.port); + idevctl->read.addr + memory->parts[partID].pHeader->offset, msg->o.size, msg->oid.id, msg->oid.port); - if (idevctl->addr >= memory->parts[msg->oid.id].pHeader->size) { + if (idevctl->read.addr >= memory->parts[msg->oid.id].pHeader->size) { msg->o.err = -EINVAL; break; } - msg->o.err = flashsrv_directRead(memory->fOid.id, memory->parts[partID].pHeader->offset + idevctl->addr, msg->o.data, msg->o.size); + msg->o.err = flashsrv_directRead(memory->fOid.id, memory->parts[partID].pHeader->offset + idevctl->read.addr, msg->o.data, msg->o.size); + break; + + case flashsrv_devctl_calcCrc32: + TRACE("imxrt-flashsrv: flashsrv_devctl_calcCrc32, addr: %u, len: %u, id: %u, port: %u.", + idevctl->crc32.addr, idevctl->crc32.len, msg->oid.id, msg->oid.port); + + if (idevctl->crc32.addr == 0 && idevctl->crc32.len == 0) { + /* calculate CRC for whole partition */ + idevctl->crc32.len = memory->parts[partID].pHeader->size; + } + else if ((idevctl->crc32.addr + idevctl->crc32.len) > memory->parts[partID].pHeader->size) { + msg->o.err = -EINVAL; + break; + } + + msg->o.err = flashsrv_calcCrc32(memory->fOid.id, memory->parts[partID].pHeader->offset + idevctl->crc32.addr, idevctl->crc32.len, &crc32); + odevctl->crc32 = crc32; break; default: @@ -914,6 +1000,24 @@ static int flashsrv_getProperties(uint8_t fID, flashsrv_properties_t *p) } +static int flashsrv_safeCalcCrc32(uint8_t fID, size_t offset, size_t len, uint32_t *crc32) +{ + ssize_t ret; + flashsrv_memory_t *mem; + + ret = flashsrv_getFlashMemory(fID, &mem); + if (ret < 0) { + return ret; + } + + mutexLock(mem->lock); + ret = flashsrv_calcCrc32(fID, offset, len, crc32); + mutexUnlock(mem->lock); + + return ret; +} + + static ssize_t flashsrv_safeDirectWrite(uint8_t fID, size_t offset, const void *data, size_t size) { ssize_t ret; @@ -977,6 +1081,7 @@ static int flashsrv_customInit(void) flashsrv_common.ops.write = flashsrv_safeDirectWrite; flashsrv_common.ops.eraseSector = flashsrv_safeSectorErase; flashsrv_common.ops.getProperties = flashsrv_getProperties; + flashsrv_common.ops.calcCrc32 = flashsrv_safeCalcCrc32; return flashsrv_customIntInit(&flashsrv_common.ops); } diff --git a/storage/imxrt-flash/imxrt-flashsrv.h b/storage/imxrt-flash/imxrt-flashsrv.h index 6e378361..b1085c56 100644 --- a/storage/imxrt-flash/imxrt-flashsrv.h +++ b/storage/imxrt-flash/imxrt-flashsrv.h @@ -22,14 +22,38 @@ /* clang-format off */ enum { flashsrv_devctl_properties = 0, flashsrv_devctl_sync, flashsrv_devctl_eraseSector, - flashsrv_devctl_erasePartition, flashsrv_devctl_directWrite, flashsrv_devctl_directRead }; + flashsrv_devctl_erasePartition, flashsrv_devctl_directWrite, flashsrv_devctl_directRead, + flashsrv_devctl_calcCrc32 }; /* clang-format on */ typedef struct { int type; - uint32_t addr; + + union { + /* eraseSector */ + struct { + uint32_t addr; + } erase; + + /* directWrite */ + struct { + uint32_t addr; + } write; + + /* directRead */ + struct { + uint32_t addr; + } read; + + /* calcCrc32 */ + struct { + /* set addr & len to 0 for full range */ + uint32_t addr; + uint32_t len; + } crc32; + }; } __attribute__((packed)) flash_i_devctl_t; @@ -42,7 +66,10 @@ typedef struct { typedef struct { - flashsrv_properties_t properties; + union { + flashsrv_properties_t properties; + uint32_t crc32; + }; } __attribute__((packed)) flash_o_devctl_t; @@ -60,6 +87,7 @@ typedef struct { ssize_t (*write)(uint8_t fID, size_t offset, const void *data, size_t size); int (*eraseSector)(uint8_t fID, uint32_t offs); int (*getProperties)(uint8_t fID, flashsrv_properties_t *p); + int (*calcCrc32)(uint8_t fID, size_t offset, size_t len, uint32_t *crc32); } flashsrv_partitionOps_t;