Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

imxrt-flash: support for calulating CRC32 of selected region #494

Merged
merged 2 commits into from
May 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
147 changes: 127 additions & 20 deletions storage/imxrt-flash/flashsrv.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@
#define IMXRT_FLASH_PRIO 3
#endif

#define CRC32_BUFSZ 256

/* clang-format off */
enum { flashsrv_memory_inactive = 0, flashsrv_memory_active = 0xff };
/* clang-format on */
Expand Down Expand Up @@ -78,7 +80,7 @@ typedef struct {
} flashsrv_memory_t;


struct {
static struct {
flashsrv_memory_t flash_memories[FLASH_MEMORIES_NO];
uint32_t flexspi_addresses[FLASH_MEMORIES_NO];
flashsrv_partitionOps_t ops;
Expand Down Expand Up @@ -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;
int res;

res = flashsrv_getFlashMemory(fID, &mem);
if (res < 0) {
return res;
}

/* caller should set crc32 to base */
tmp = *crc32;

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)
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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;

Expand All @@ -266,26 +317,44 @@ 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, base: %4x, id: %u, port: %u.",
idevctl->crc32.addr, idevctl->crc32.len, idevctl->crc32.base, 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);
crc32 = idevctl->crc32.base;
msg->o.err = flashsrv_calcCrc32(memory->fOid.id, idevctl->crc32.addr, idevctl->crc32.len, &crc32);
odevctl->crc32 = crc32;
break;

default:
Expand All @@ -300,6 +369,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;

Expand Down Expand Up @@ -336,14 +406,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;

Expand All @@ -360,26 +430,44 @@ 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, base: %4x, id: %u, port: %u.",
idevctl->crc32.addr, idevctl->crc32.len, idevctl->crc32.base, 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;
}

crc32 = idevctl->crc32.base;
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:
Expand Down Expand Up @@ -685,7 +773,7 @@ static int flashsrv_mountPart(flashsrv_partition_t *part)
part->pStatus = flashsrv_memory_active;
break;

/* Each meterfs partiton is handled by separete thread */
/* Each meterfs partition is handled by separate thread */
case ptable_meterfs:
res = flashsrv_initMeterfs(part);
if (res < 0) {
Expand Down Expand Up @@ -914,6 +1002,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;
Expand Down Expand Up @@ -977,6 +1083,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);
}
Expand Down
35 changes: 32 additions & 3 deletions storage/imxrt-flash/imxrt-flashsrv.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,39 @@
/* 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 */
gorbanchovie marked this conversation as resolved.
Show resolved Hide resolved
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 */
gorbanchovie marked this conversation as resolved.
Show resolved Hide resolved
uint32_t addr;
uint32_t len;
uint32_t base;
} crc32;
};
} __attribute__((packed)) flash_i_devctl_t;


Expand All @@ -42,7 +67,10 @@ typedef struct {


typedef struct {
flashsrv_properties_t properties;
union {
flashsrv_properties_t properties;
uint32_t crc32;
};
} __attribute__((packed)) flash_o_devctl_t;


Expand All @@ -60,6 +88,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;


Expand Down
Loading