aboutsummaryrefslogtreecommitdiffstats
path: root/roms/skiboot/libflash/test/test-mbox.c
diff options
context:
space:
mode:
Diffstat (limited to 'roms/skiboot/libflash/test/test-mbox.c')
-rw-r--r--roms/skiboot/libflash/test/test-mbox.c333
1 files changed, 333 insertions, 0 deletions
diff --git a/roms/skiboot/libflash/test/test-mbox.c b/roms/skiboot/libflash/test/test-mbox.c
new file mode 100644
index 000000000..260a3c7d4
--- /dev/null
+++ b/roms/skiboot/libflash/test/test-mbox.c
@@ -0,0 +1,333 @@
+// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+/* Copyright 2017-2018 IBM Corp. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include <libflash/libflash.h>
+#include <libflash/libflash-priv.h>
+
+#include "stubs.h"
+#include "mbox-server.h"
+
+#define zalloc(n) calloc(1, n)
+#define __unused __attribute__((unused))
+
+#undef pr_fmt
+
+void mbox_init(void)
+{
+}
+
+#include "../libflash.c"
+#include "../mbox-flash.c"
+#include "../ecc.c"
+#include "../blocklevel.c"
+
+#undef pr_fmt
+#define pr_fmt(fmt) "MBOX-PROXY: " fmt
+
+/* client interface */
+
+#include "../../include/lpc-mbox.h"
+
+#define ERR(...) FL_DBG(__VA_ARGS__)
+
+static int run_flash_test(struct blocklevel_device *bl)
+{
+ struct mbox_flash_data *mbox_flash;
+ char hello[] = "Hello World";
+ uint32_t erase_granule;
+ uint64_t total_size;
+ const char *name;
+ uint16_t *test;
+ char *tmp;
+ int i, rc;
+
+ mbox_flash = container_of(bl, struct mbox_flash_data, bl);
+
+ /*
+ * Do something first so that if it has been reset it does that
+ * before we check versions
+ */
+ rc = blocklevel_get_info(bl, &name, &total_size, &erase_granule);
+ if (rc) {
+ ERR("blocklevel_get_info() failed with err %d\n", rc);
+ return 1;
+ }
+ if (total_size != mbox_server_total_size()) {
+ ERR("Total flash size is incorrect: 0x%08lx vs 0x%08x\n",
+ total_size, mbox_server_total_size());
+ return 1;
+ }
+ if (erase_granule != mbox_server_erase_granule()) {
+ ERR("Erase granule is incorrect 0x%08x vs 0x%08x\n",
+ erase_granule, mbox_server_erase_granule());
+ return 1;
+ }
+
+
+ /* Sanity check that mbox_flash has inited correctly */
+ if (mbox_flash->version != mbox_server_version()) {
+ ERR("MBOX Flash didn't agree with the server version\n");
+ return 1;
+ }
+ if (mbox_flash->version == 1 && mbox_flash->shift != 12) {
+ ERR("MBOX Flash version 1 isn't using a 4K shift\n");
+ return 1;
+ }
+
+ mbox_server_memset(0xff);
+
+ test = calloc(erase_granule * 20, 1);
+
+ /* Make up a test pattern */
+ for (i = 0; i < erase_granule * 10; i++)
+ test[i] = i;
+
+ /* Write 64k of stuff at 0 and at 128k */
+ printf("Writing test patterns...\n");
+ rc = blocklevel_write(bl, 0, test, erase_granule * 10);
+ if (rc) {
+ ERR("blocklevel_write(0, erase_granule * 10) failed with err %d\n", rc);
+ return 1;
+ }
+ rc = blocklevel_write(bl, erase_granule * 20, test, erase_granule * 10);
+ if (rc) {
+ ERR("blocklevel_write(0x20000, 0x10000) failed with err %d\n", rc);
+ return 1;
+ }
+
+ if (mbox_server_memcmp(0, test, erase_granule * 10)) {
+ ERR("Test pattern mismatch !\n");
+ return 1;
+ }
+
+ /* Write "Hello world" straddling the 64k boundary */
+ printf("Writing test string...\n");
+ rc = blocklevel_write(bl, (erase_granule * 10) - 8, hello, sizeof(hello));
+ if (rc) {
+ ERR("blocklevel_write(0xfffc, %s, %lu) failed with err %d\n",
+ hello, sizeof(hello), rc);
+ return 1;
+ }
+
+ /* Check result */
+ if (mbox_server_memcmp((erase_granule * 10) - 8, hello, sizeof(hello))) {
+ ERR("Test string mismatch!\n");
+ return 1;
+ }
+
+ /* Erase granule is something but never 0x50, this shouldn't succeed */
+ rc = blocklevel_erase(bl, 0, 0x50);
+ if (!rc) {
+ ERR("blocklevel_erase(0, 0x50) didn't fail!\n");
+ return 1;
+ }
+
+ /* Check it didn't silently erase */
+ if (mbox_server_memcmp(0, test, (erase_granule * 10) - 8)) {
+ ERR("Test pattern mismatch !\n");
+ return 1;
+ }
+
+ /*
+ * For v1 protocol this should NOT call MARK_WRITE_ERASED!
+ * The server MARK_WRITE_ERASED will call exit(1) if it gets a
+ * MARK_WRITE_ERASED and version == 1
+ */
+ rc = blocklevel_erase(bl, 0, erase_granule);
+ if (rc) {
+ ERR("blocklevel_erase(0, erase_granule) failed with err %d\n", rc);
+ return 1;
+ }
+
+ /*
+ * Version 1 doesn't specify that the buffer actually becomes 0xff
+ * It is up to the daemon to do what it wants really - there are
+ * implementations that do nothing but writes to the same region
+ * work fine
+ */
+
+ /* This check is important for v2 */
+ /* Check stuff got erased */
+ tmp = malloc(erase_granule * 2);
+ if (!tmp) {
+ ERR("malloc failed\n");
+ return 1;
+ }
+ if (mbox_server_version() > 1) {
+ memset(tmp, 0xff, erase_granule);
+ if (mbox_server_memcmp(0, tmp, erase_granule)) {
+ ERR("Buffer not erased\n");
+ rc = 1;
+ goto out;
+ }
+ }
+
+ /* Read beyond the end of flash */
+ rc = blocklevel_read(bl, total_size, tmp, 0x1000);
+ if (!rc) {
+ ERR("blocklevel_read(total_size, 0x1000) (read beyond the end) succeeded\n");
+ goto out;
+ }
+
+ /* Test some simple write/read cases, avoid first page */
+ rc = blocklevel_write(bl, erase_granule * 2, test, erase_granule / 2);
+ if (rc) {
+ ERR("blocklevel_write(erase_granule, erase_granule / 2) failed with err %d\n", rc);
+ goto out;
+ }
+ rc = blocklevel_write(bl, erase_granule * 2 + erase_granule / 2, test, erase_granule / 2);
+ if (rc) {
+ ERR("blocklevel_write(erase_granule * 2 + erase_granule / 2, erase_granule) failed with err %d\n", rc);
+ goto out;
+ }
+
+ rc = mbox_server_memcmp(erase_granule * 2, test, erase_granule / 2);
+ if (rc) {
+ ERR("%s:%d mbox_server_memcmp miscompare\n", __FILE__, __LINE__);
+ goto out;
+ }
+ rc = mbox_server_memcmp(erase_granule * 2 + erase_granule / 2, test, erase_granule / 2);
+ if (rc) {
+ ERR("%s:%d mbox_server_memcmp miscompare\n", __FILE__, __LINE__);
+ goto out;
+ }
+
+ /* Great so the writes made it, can we read them back? Do it in
+ * four small reads */
+ for (i = 0; i < 4; i++) {
+ rc = blocklevel_read(bl, erase_granule * 2 + (i * erase_granule / 4), tmp + (i * erase_granule / 4), erase_granule / 4);
+ if (rc) {
+ ERR("blocklevel_read(0x%08x, erase_granule / 4) failed with err %d\n",
+ 2 * erase_granule + (i * erase_granule / 4), rc);
+ goto out;
+ }
+ }
+ rc = memcmp(test, tmp, erase_granule / 2);
+ if (rc) {
+ ERR("%s:%d read back miscompare\n", __FILE__, __LINE__);
+ goto out;
+ }
+ rc = memcmp(test, tmp + erase_granule / 2, erase_granule / 2);
+ if (rc) {
+ ERR("%s:%d read back miscompare\n", __FILE__, __LINE__);
+ goto out;
+ }
+
+ /*
+ * Make sure we didn't corrupt other stuff, also make sure one
+ * blocklevel call will understand how to read from two windows
+ */
+ for (i = 3; i < 9; i = i + 2) {
+ printf("i:%d erase: 0x%08x\n", i, erase_granule);
+ rc = blocklevel_read(bl, i * erase_granule, tmp, 2 * erase_granule);
+ if (rc) {
+ ERR("blocklevel_read(0x%08x, 2 * erase_granule) failed with err: %d\n", i * erase_granule, rc);
+ goto out;
+ }
+ rc = memcmp(((char *)test) + (i * erase_granule), tmp, 2 * erase_granule);
+ if (rc) {
+ ERR("%s:%d read back miscompare (pos: 0x%08x)\n", __FILE__, __LINE__, i * erase_granule);
+ goto out;
+ }
+ }
+
+ srand(1);
+ /*
+ * Try to jump around the place doing a tonne of small reads.
+ * Worth doing the same with writes TODO
+ */
+#ifdef __STRICT_TEST__
+#define TEST_LOOPS 1000
+#else
+#define TEST_LOOPS 100
+#endif
+ for (i = 0; i < TEST_LOOPS; i++) {
+ int r = rand();
+
+ printf("Loop %d of %d\n", i, TEST_LOOPS);
+ /* Avoid reading too far, just skip it */
+ if ((r % erase_granule * 10) + (r % erase_granule * 2) > erase_granule * 10)
+ continue;
+
+ rc = blocklevel_read(bl, erase_granule * 20 + (r % erase_granule * 10), tmp, r % erase_granule * 2);
+ if (rc) {
+ ERR("blocklevel_read(0x%08x, 0x%08x) failed with err %d\n", 0x20000 + (r % 0x100000), r % 0x2000, rc);
+ goto out;
+ }
+ rc = memcmp(((char *)test) + (r % erase_granule * 10), tmp, r % erase_granule * 2);
+ if (rc) {
+ ERR("%s:%d read back miscompare (pos: 0x%08x)\n", __FILE__, __LINE__, 0x20000 + (r % 0x10000));
+ goto out;
+ }
+ }
+out:
+ free(tmp);
+ return rc;
+}
+
+int main(void)
+{
+ struct blocklevel_device *bl;
+ int rc;
+
+ libflash_debug = true;
+
+ mbox_server_init();
+
+#ifdef __STRICT_TEST__
+ printf("Found __STRICT_TEST__, this may take time time.\n");
+#else
+ printf("__STRICT_TEST__ not found, use make strict-check for a more\n");
+ printf("thorough test, it will take significantly longer.\n");
+#endif
+
+ printf("Doing mbox-flash V1 tests\n");
+
+ /* run test */
+ mbox_flash_init(&bl);
+ rc = run_flash_test(bl);
+ if (rc)
+ goto out;
+ /*
+ * Trick mbox-flash into thinking there was a reboot so we can
+ * switch to v2
+ */
+
+ printf("Doing mbox-flash V2 tests\n");
+
+ mbox_server_reset(2, 12);
+
+ /* Do all the tests again */
+ rc = run_flash_test(bl);
+ if (rc)
+ goto out;
+
+ mbox_server_reset(2, 17);
+
+ /* Do all the tests again */
+ rc = run_flash_test(bl);
+ if (rc)
+ goto out;
+
+
+ printf("Doing mbox-flash V3 tests\n");
+
+ mbox_server_reset(3, 20);
+
+ /* Do all the tests again */
+ rc = run_flash_test(bl);
+
+
+out:
+ mbox_flash_exit(bl);
+
+ mbox_server_destroy();
+
+ return rc;
+}