blob: eae2627d00edbed66e6eefce21c91a2aba0ec83c [file] [log] [blame]
// SPDX-License-Identifier: Apache-2.0
// Copyright (C) 2018 IBM Corp.
#include <assert.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <linux/types.h>
#include "mbox.h"
#include "flash.h"
#include "test/tmpf.h"
static struct tmpf mtd;
void cleanup_mtd(void)
{
tmpf_destroy(&mtd);
}
char *get_dev_mtd(void)
{
int rc;
rc = tmpf_init(&mtd, "flash-store.XXXXXX");
if (rc < 0)
return NULL;
return strdup(mtd.path);
}
struct erase_info_user *recorded;
int n_ioctls;
#define MEM_SIZE 3
#define ERASE_SIZE 1
int ioctl(int fd, unsigned long request, ...)
{
va_list ap;
struct erase_info_user *provided, *alloced;
if (!(request == MEMERASE || request == MEMGETINFO)) {
printf("Uh-oh: ioctl() called with request 0x%08lx\n", request);
return -1;
}
switch (request) {
case MEMGETINFO:
{
struct mtd_info_user *info;
va_start(ap, request);
info = va_arg(ap, struct mtd_info_user *);
info->size = MEM_SIZE;
info->erasesize = ERASE_SIZE;
va_end(ap);
break;
}
case MEMERASE:
va_start(ap, request);
provided = va_arg(ap, struct erase_info_user *);
n_ioctls++;
alloced = realloc(recorded, n_ioctls * sizeof(*recorded));
if (!alloced)
return -1;
recorded = alloced;
memcpy(&recorded[n_ioctls - 1], provided, sizeof(*provided));
va_end(ap);
break;
default:
break;
}
return 0;
}
void dump_ioctls(void)
{
int i;
printf("n_ioctls: %d\n", n_ioctls);
for (i = 0; i < n_ioctls; i++)
printf("%d: start: %d, length %d\n",
i, recorded[i].start, recorded[i].length);
}
int main(void)
{
struct mbox_context context;
char data[MEM_SIZE];
int rc;
rc = atexit(cleanup_mtd);
if (rc)
return rc;
mbox_vlog = &mbox_log_console;
n_ioctls = 0;
recorded = NULL;
flash_dev_init(&context);
/* Erase from an unknown state */
rc = erase_flash(&context, 0, sizeof(data));
assert(rc == 0);
assert(n_ioctls == 1);
assert(recorded[0].start == 0);
assert(recorded[0].length == sizeof(data));
free(recorded);
recorded = NULL;
n_ioctls = 0;
/* Erase an erased flash */
rc = erase_flash(&context, 0, sizeof(data));
assert(rc == 0);
assert(n_ioctls == 0);
memset(data, 0xaa, sizeof(data));
/* Erase written flash */
rc = write_flash(&context, 0, data, sizeof(data));
assert(rc == 0);
rc = erase_flash(&context, 0, sizeof(data));
assert(rc == 0);
assert(n_ioctls == 1);
assert(recorded[0].start == 0);
assert(recorded[0].length == sizeof(data));
free(recorded);
recorded = NULL;
n_ioctls = 0;
/* Erase the start of flash */
rc = write_flash(&context, 0, data, sizeof(data) - 1);
assert(rc == 0);
rc = erase_flash(&context, 0, sizeof(data));
assert(rc == 0);
assert(n_ioctls == 1);
assert(recorded[0].start == 0);
assert(recorded[0].length == sizeof(data) - 1);
free(recorded);
recorded = NULL;
n_ioctls = 0;
/* Erase the end of flash */
rc = write_flash(&context, 1, data, sizeof(data) - 1);
assert(rc == 0);
rc = erase_flash(&context, 0, sizeof(data));
assert(rc == 0);
assert(n_ioctls == 1);
assert(recorded[0].start == 1);
assert(recorded[0].length == sizeof(data) - 1);
free(recorded);
recorded = NULL;
n_ioctls = 0;
/* Erase each end of flash */
rc = write_flash(&context, 0, data, 1);
rc = write_flash(&context, 2, data, 1);
assert(rc == 0);
rc = erase_flash(&context, 0, sizeof(data));
assert(rc == 0);
assert(n_ioctls == 2);
assert(recorded[0].start == 0);
assert(recorded[0].length == 1);
assert(recorded[1].start == 2);
assert(recorded[1].length == 1);
free(recorded);
recorded = NULL;
n_ioctls = 0;
/* Erase the middle of flash */
rc = write_flash(&context, 1, data, 1);
assert(rc == 0);
rc = erase_flash(&context, 0, sizeof(data));
assert(rc == 0);
assert(n_ioctls == 1);
assert(recorded[0].start == 1);
assert(recorded[0].length == 1);
free(recorded);
recorded = NULL;
n_ioctls = 0;
flash_dev_free(&context);
return rc;
}