diff --git a/external/gard/gard.c b/external/gard/gard.c
index 4b26a3b8..fa505fd6 100644
--- a/external/gard/gard.c
+++ b/external/gard/gard.c
@@ -1,4 +1,4 @@
-/* Copyright 2013-2015 IBM Corp.
+/* Copyright 2013-2017 IBM Corp.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -35,7 +35,6 @@
 #include <libflash/libflash.h>
 #include <libflash/libffs.h>
 #include <libflash/file.h>
-#include <libflash/ecc.h>
 #include <libflash/blocklevel.h>
 #include <common/arch_flash.h>
 
@@ -51,7 +50,6 @@
 extern const char version[];
 
 struct gard_ctx {
-	bool ecc;
 	uint32_t f_size;
 	uint32_t f_pos;
 
@@ -63,15 +61,6 @@ struct gard_ctx {
 	struct ffs_handle *ffs;
 };
 
-/*
- * Return the size of a struct gard_ctx depending on if the buffer contains
- * ECC bits
- */
-static inline size_t sizeof_gard(struct gard_ctx *ctx)
-{
-	return ctx->ecc ? ecc_buffer_size(sizeof(struct gard_record)) : sizeof(struct gard_record);
-}
-
 static void show_flash_err(int rc)
 {
 	switch (rc) {
@@ -243,11 +232,11 @@ static int do_iterate(struct gard_ctx *ctx,
 	struct gard_record gard, null_gard;
 
 	memset(&null_gard, UINT_MAX, sizeof(gard));
-	for (i = 0; i * sizeof_gard(ctx) < ctx->gard_data_len && rc == 0; i++) {
+	for (i = 0; i * sizeof(gard) < ctx->gard_data_len && rc == 0; i++) {
 		memset(&gard, 0, sizeof(gard));
 
-		rc = blocklevel_read(ctx->bl, ctx->gard_data_pos +
-				(i * sizeof_gard(ctx)), &gard, sizeof(gard));
+		rc = blocklevel_read(ctx->bl, ctx->gard_data_pos + (i * sizeof(gard)),
+					&gard, sizeof(gard));
 		/* It isn't super clear what constitutes the end, this should do */
 		if (rc || memcmp(&gard, &null_gard, sizeof(gard)) == 0)
 			break;
@@ -403,7 +392,7 @@ static int do_clear_i(struct gard_ctx *ctx, int pos, struct gard_record *gard, v
 	if (pos < largest) {
 		/* We're not clearing the last record, shift all the records up */
 		int buf_len = ((largest - pos) * sizeof(struct gard_record));
-		int buf_pos = ctx->gard_data_pos + ((pos + 1) * sizeof_gard(ctx));
+		int buf_pos = ctx->gard_data_pos + ((pos + 1) * sizeof(struct gard_record));
 		buf = malloc(buf_len);
 		if (!buf)
 			return -ENOMEM;
@@ -415,17 +404,17 @@ static int do_clear_i(struct gard_ctx *ctx, int pos, struct gard_record *gard, v
 			return rc;
 		}
 
-		rc = blocklevel_smart_write(ctx->bl, buf_pos - sizeof_gard(ctx), buf, buf_len);
+		rc = blocklevel_smart_write(ctx->bl, buf_pos - sizeof(gard), buf, buf_len);
 		free(buf);
 		if (rc) {
 			fprintf(stderr, "Couldn't write to flash at 0x%08x for len 0x%08x\n",
-			        buf_pos - (int) sizeof_gard(ctx), buf_len);
+					buf_pos - (int) sizeof(struct gard_record), buf_len);
 			return rc;
 		}
 	}
 
 	/* Now wipe the last record */
-	rc = blocklevel_smart_write(ctx->bl, ctx->gard_data_pos + (largest * sizeof_gard(ctx)),
+	rc = blocklevel_smart_write(ctx->bl, ctx->gard_data_pos + (largest * sizeof(null_gard)),
 	                            &null_gard, sizeof(null_gard));
 	printf("done\n");
 
@@ -443,7 +432,7 @@ static int reset_partition(struct gard_ctx *ctx)
 		fprintf(stderr, "Couldn't erase the gard partition. Bailing out\n");
 		return rc;
 	}
-	for (i = 0; i + sizeof_gard(ctx) < ctx->gard_data_len; i += sizeof_gard(ctx)) {
+	for (i = 0; i + sizeof(gard) < ctx->gard_data_len; i += sizeof(gard)) {
 		rc = blocklevel_write(ctx->bl, ctx->gard_data_pos + i, &gard, sizeof(gard));
 		if (rc) {
 			fprintf(stderr, "Couldn't reset the entire gard partition. Bailing out\n");
@@ -667,7 +656,7 @@ int main(int argc, char **argv)
 			goto out;
 
 		rc = ffs_part_info(ctx->ffs, ctx->gard_part_idx, NULL, &(ctx->gard_data_pos),
-				&(ctx->gard_data_len), NULL, &(ctx->ecc));
+				&(ctx->gard_data_len), NULL, NULL);
 		if (rc)
 			goto out;
 	} else {
@@ -677,7 +666,6 @@ int main(int argc, char **argv)
 				goto out;
 		}
 
-		ctx->ecc = ecc;
 		ctx->gard_data_pos = 0;
 		ctx->gard_data_len = ctx->f_size;
 	}
diff --git a/libflash/blocklevel.c b/libflash/blocklevel.c
index bafeebc3..efb30261 100644
--- a/libflash/blocklevel.c
+++ b/libflash/blocklevel.c
@@ -68,6 +68,11 @@ static int ecc_protected(struct blocklevel_device *bl, uint64_t pos, uint64_t le
 	return 0;
 }
 
+static uint64_t with_ecc_pos(uint64_t ecc_start, uint64_t pos)
+{
+	return pos + ((pos - ecc_start) / (BYTES_PER_ECC));
+}
+
 static int reacquire(struct blocklevel_device *bl)
 {
 	if (!bl->keep_alive && bl->reacquire)
@@ -111,7 +116,7 @@ int blocklevel_read(struct blocklevel_device *bl, uint64_t pos, void *buf, uint6
 {
 	int rc, ecc_protection;
 	struct ecc64 *buffer;
-	uint64_t ecc_start, ecc_len = ecc_buffer_size(len);
+	uint64_t ecc_pos, ecc_start, ecc_diff, ecc_len;
 
 	if (!bl || !buf) {
 		errno = EINVAL;
@@ -136,6 +141,15 @@ int blocklevel_read(struct blocklevel_device *bl, uint64_t pos, void *buf, uint6
 		return FLASH_ERR_PARM_ERROR;
 	}
 
+	pos = with_ecc_pos(ecc_start, pos);
+
+	ecc_pos = ecc_buffer_align(ecc_start, pos);
+	ecc_diff = pos - ecc_pos;
+	ecc_len = ecc_buffer_size(len + ecc_diff);
+
+	FL_DBG("%s: adjusted_pos: 0x%" PRIx64 ", ecc_pos: 0x%" PRIx64
+			", ecc_diff: 0x%" PRIx64 ", ecc_len: 0x%" PRIx64 "\n",
+			__func__, pos, ecc_pos, ecc_diff, ecc_len);
 	buffer = malloc(ecc_len);
 	if (!buffer) {
 		errno = ENOMEM;
@@ -143,11 +157,15 @@ int blocklevel_read(struct blocklevel_device *bl, uint64_t pos, void *buf, uint6
 		goto out;
 	}
 
-	rc = blocklevel_raw_read(bl, pos, buffer, ecc_len);
+	rc = blocklevel_raw_read(bl, ecc_pos, buffer, ecc_len);
 	if (rc)
 		goto out;
 
-	if (memcpy_from_ecc(buf, buffer, len)) {
+	/*
+	 * Could optimise and simply call memcpy_from_ecc() if ecc_diff
+	 * == 0 but _unaligned checks and bascially does that for us
+	 */
+	if (memcpy_from_ecc_unaligned(buf, buffer, len, ecc_diff)) {
 		errno = EBADF;
 		rc = FLASH_ERR_ECC_INVALID;
 	}
@@ -184,7 +202,7 @@ int blocklevel_write(struct blocklevel_device *bl, uint64_t pos, const void *buf
 	int rc, ecc_protection;
 	struct ecc64 *buffer;
 	uint64_t ecc_len = ecc_buffer_size(len);
-	uint64_t ecc_start;
+	uint64_t ecc_start, ecc_pos, ecc_diff;
 
 	if (!bl || !buf) {
 		errno = EINVAL;
@@ -209,6 +227,16 @@ int blocklevel_write(struct blocklevel_device *bl, uint64_t pos, const void *buf
 		return FLASH_ERR_PARM_ERROR;
 	}
 
+	pos = with_ecc_pos(ecc_start, pos);
+
+	ecc_pos = ecc_buffer_align(ecc_start, pos);
+	ecc_diff = pos - ecc_pos;
+	ecc_len = ecc_buffer_size(len + ecc_diff);
+
+	FL_DBG("%s: adjusted_pos: 0x%" PRIx64 ", ecc_pos: 0x%" PRIx64
+			", ecc_diff: 0x%" PRIx64 ", ecc_len: 0x%" PRIx64 "\n",
+			__func__, pos, ecc_pos, ecc_diff, ecc_len);
+
 	buffer = malloc(ecc_len);
 	if (!buffer) {
 		errno = ENOMEM;
@@ -216,12 +244,44 @@ int blocklevel_write(struct blocklevel_device *bl, uint64_t pos, const void *buf
 		goto out;
 	}
 
-	if (memcpy_to_ecc(buffer, buf, len)) {
-		errno = EBADF;
-		rc = FLASH_ERR_ECC_INVALID;
-		goto out;
-	}
+	if (ecc_diff) {
+		uint64_t start_chunk = ecc_diff;
+		uint64_t end_chunk = BYTES_PER_ECC - ecc_diff;
+		uint64_t end_len = ecc_len - end_chunk;
+
+		/*
+		 * Read the start bytes that memcpy_to_ecc_unaligned() will need
+		 * to calculate the first ecc byte
+		 */
+		rc = blocklevel_raw_read(bl, ecc_pos, buffer, start_chunk);
+		if (rc) {
+			errno = EBADF;
+			rc = FLASH_ERR_ECC_INVALID;
+		}
+
+		/*
+		 * Read the end bytes that memcpy_to_ecc_unaligned() will need
+		 * to calculate the last ecc byte
+		 */
+		rc = blocklevel_raw_read(bl, ecc_pos + end_len, ((char *)buffer) + end_len,
+				end_chunk);
+		if (rc) {
+			errno = EBADF;
+			rc = FLASH_ERR_ECC_INVALID;
+		}
 
+		if (memcpy_to_ecc_unaligned(buffer, buf, len, ecc_diff)) {
+			errno = EBADF;
+			rc = FLASH_ERR_ECC_INVALID;
+			goto out;
+		}
+	} else {
+		if (memcpy_to_ecc(buffer, buf, len)) {
+			errno = EBADF;
+			rc = FLASH_ERR_ECC_INVALID;
+			goto out;
+		}
+	}
 	rc = blocklevel_raw_write(bl, pos, buffer, ecc_len);
 
 out:
diff --git a/libflash/test/test-blocklevel.c b/libflash/test/test-blocklevel.c
index d227f545..721efa13 100644
--- a/libflash/test/test-blocklevel.c
+++ b/libflash/test/test-blocklevel.c
@@ -30,11 +30,70 @@
 /* Setting this to true prints quite a lot of debug */
 bool libflash_debug = 0;
 
-int main(void)
+static int bl_test_read(struct blocklevel_device *bl, uint64_t pos, void *buf, uint64_t len)
+{
+	if (pos + len > 0x1000)
+		return FLASH_ERR_PARM_ERROR;
+
+	memcpy(buf, bl->priv + pos, len);
+
+	return 0;
+}
+
+static int bl_test_write(struct blocklevel_device *bl, uint64_t pos, const void *buf, uint64_t len)
+{
+	if (pos + len > 0x1000)
+		return FLASH_ERR_PARM_ERROR;
+
+	memcpy(bl->priv + pos, buf, len);
+
+	return 0;
+}
+
+static int bl_test_erase(struct blocklevel_device *bl, uint64_t pos, uint64_t len)
+{
+	if (pos + len > 0x1000)
+		return FLASH_ERR_PARM_ERROR;
+
+	memset(bl->priv + pos, 0xff, len);
+
+	return 0;
+}
+
+static void reset_buf(uint8_t *buf)
+{
+	int i;
+
+	for (i = 0; i < 0x1000; i++) {
+		/* This gives repeating a - z which will be nice to visualise */
+		buf[i] = (i % 26) + 'a';
+	}
+}
+
+static void print_ptr(void *ptr, int len)
 {
 	int i;
+	char *p = ptr;
+
+	printf("0x");
+	for (i = 0; i < len; i++) {
+		putchar(*p);
+		if (i && i % 8 == 0) {
+			putchar('\n');
+			if (len - i)
+				printf("0x");
+		}
+	}
+	putchar('\n');
+}
+
+int main(void)
+{
 	struct blocklevel_device bl_mem = { 0 };
 	struct blocklevel_device *bl = &bl_mem;
+	uint64_t with_ecc[10], without_ecc[10];
+	char *buf, *data;
+	int i, rc;
 
 	if (blocklevel_ecc_protect(bl, 0, 0x1000)) {
 		ERR("Failed to blocklevel_ecc_protect!\n");
@@ -211,6 +270,259 @@ int main(void)
 		}
 	}
 
+	/* Test ECC reading and writing being 100% transparent to the
+	 * caller */
+	buf = malloc(0x1000);
+	data = malloc(0x100);
+	if (!buf || !data) {
+		ERR("Malloc failed\n");
+		free(buf);
+		free(data);
+		rc = 1;
+		goto out;
+	}
+	memset(bl, 0, sizeof(*bl));
+	bl_mem.read = &bl_test_read;
+	bl_mem.write = &bl_test_write;
+	bl_mem.erase = &bl_test_erase;
+	bl_mem.priv = buf;
+	reset_buf(buf);
+
+	for (i = 0; i < 0x100; i++)
+		data[i] = i;
+
+	/* This really shouldn't fail */
+	rc = blocklevel_ecc_protect(bl, 0, 0x100);
+	if (rc) {
+		ERR("Couldn't blocklevel_ecc_protect(0, 0x100)\n");
+		goto out;
+	}
 
-	return 0;
+	rc = blocklevel_write(bl, 0, data, 0x100);
+	if (rc) {
+		ERR("Couldn't blocklevel_write(0, 0x100)\n");
+		goto out;
+	}
+
+	rc = blocklevel_write(bl, 0x200, data, 0x100);
+	if (rc) {
+		ERR("Couldn't blocklevel_write(0x200, 0x100)\n");
+		goto out;
+	}
+
+	/*
+	 * 0x50 once adjusted for the presence of ECC becomes 0x5a which
+	 * is ECC aligned.
+	 */
+	rc = blocklevel_read(bl, 0x50, with_ecc, 8);
+	if (rc) {
+		ERR("Couldn't blocklevel_read(0x50, 8) with ecc rc=%d\n", rc);
+		goto out;
+	}
+	rc = blocklevel_read(bl, 0x250, without_ecc, 8);
+	if (rc) {
+		ERR("Couldn't blocklevel_read(0x250, 8) without ecc rc=%d\n", rc);
+		goto out;
+	}
+	if (memcmp(with_ecc, without_ecc, 8) || memcmp(with_ecc, &data[0x50], 8)) {
+		ERR("ECC read and non-ECC read don't match or are wrong line: %d\n", __LINE__);
+		print_ptr(with_ecc, 8);
+		print_ptr(without_ecc, 8);
+		print_ptr(&data[50], 8);
+		rc = 1;
+		goto out;
+	}
+
+	/*
+	 * 0x50 once adjusted for the presence of ECC becomes 0x5a which
+	 * is ECC aligned.
+	 * So 0x4f won't be aligned!
+	 */
+	rc = blocklevel_read(bl, 0x4f, with_ecc, 8);
+	if (rc) {
+		ERR("Couldn't blocklevel_read(0x4f, 8) with ecc %d\n", rc);
+		goto out;
+	}
+	rc = blocklevel_read(bl, 0x24f, without_ecc, 8);
+	if (rc) {
+		ERR("Couldn't blocklevel_read(0x24f, 8) without ecc %d\n", rc);
+		goto out;
+	}
+	if (memcmp(with_ecc, without_ecc, 8) || memcmp(with_ecc, &data[0x4f], 8)) {
+		ERR("ECC read and non-ECC read don't match or are wrong line: %d\n", __LINE__);
+		print_ptr(with_ecc, 8);
+		print_ptr(without_ecc, 8);
+		print_ptr(&data[0x4f], 8);
+		rc = 1;
+		goto out;
+	}
+
+	/*
+	 * 0x50 once adjusted for the presence of ECC becomes 0x5a which
+	 * is ECC aligned.
+	 */
+	rc = blocklevel_read(bl, 0x50, with_ecc, 16);
+	if (rc) {
+		ERR("Couldn't blocklevel_read(0x50, 16) with ecc %d\n", rc);
+		goto out;
+	}
+	rc = blocklevel_read(bl, 0x250, without_ecc, 16);
+	if (rc) {
+		ERR("Couldn't blocklevel_read(0x250, 16) without ecc %d\n", rc);
+		goto out;
+	}
+	if (memcmp(with_ecc, without_ecc, 16)|| memcmp(with_ecc, &data[0x50], 16)) {
+		ERR("(long read )ECC read and non-ECC read don't match or are wrong line: %d\n", __LINE__);
+		print_ptr(with_ecc, 16);
+		print_ptr(without_ecc, 16);
+		print_ptr(&data[0x50], 16);
+		rc = 1;
+		goto out;
+	}
+
+	/*
+	 * 0x50 once adjusted for the presence of ECC becomes 0x5a which
+	 * is ECC aligned. So 4f won't be.
+	 */
+	rc = blocklevel_read(bl, 0x4f, with_ecc, 24);
+	if (rc) {
+		ERR("Couldn't blocklevel_read(0x4f, 24) with ecc %d\n", rc);
+		goto out;
+	}
+	rc = blocklevel_read(bl, 0x24f, without_ecc, 24);
+	if (rc) {
+		ERR("Couldn't blocklevel_read(0x24f, 24) without ecc %d\n", rc);
+		goto out;
+	}
+	if (memcmp(with_ecc, without_ecc, 24)|| memcmp(with_ecc, &data[0x4f], 24)) {
+		ERR("(long read )ECC read and non-ECC read don't match or are wrong: %d\n", __LINE__);
+		print_ptr(with_ecc, 24);
+		print_ptr(without_ecc, 24);
+		print_ptr(&data[0x4f], 24);
+		rc = 1;
+		goto out;
+	}
+
+	/*
+	 * Now lets try to write at non ECC aligned positions
+	 * Go easy first, 0x50 becomes 0x5a which is ECC byte aligned but
+	 * not aligned to the start of the partition
+	 */
+
+	rc = blocklevel_write(bl, 0x50, data, 0xb0);
+	if (rc) {
+		ERR("Couldn't blocklevel_write()\n");
+		goto out;
+	}
+	/* Read 8 bytes before to make sure we didn't ruin that */
+	rc = blocklevel_read(bl, 0x48, with_ecc, 24);
+	if (rc) {
+		ERR("Couldn't blocklevel_read() with ecc %d\n", rc);
+		goto out;
+	}
+	if (memcmp(with_ecc, data + 0x48, 8) || memcmp(with_ecc + 1, data, 16)) {
+		rc = 1;
+		ERR("Couldn't read back what we thought we wrote line: %d\n", __LINE__);
+		print_ptr(with_ecc, 24);
+		print_ptr(&data[0x48], 8);
+		print_ptr(data, 16);
+		goto out;
+	}
+
+	/* Ok lets get tricky */
+	rc = blocklevel_write(bl, 0x31, data, 0xcf);
+	if (rc) {
+		ERR("Couldn't blocklevel_write(0x31, 0xcf)\n");
+		goto out;
+	}
+	/* Read 8 bytes before to make sure we didn't ruin that */
+	rc = blocklevel_read(bl, 0x29, with_ecc, 24);
+	if (rc) {
+		ERR("Couldn't blocklevel_read(0x29, 24) with ecc rc=%d\n", rc);
+		goto out;
+	}
+	if (memcmp(with_ecc, &data[0x29], 8) || memcmp(with_ecc + 1, data, 16)) {
+		ERR("Couldn't read back what we thought we wrote line: %d\n", __LINE__);
+		print_ptr(with_ecc, 24);
+		print_ptr(&data[0x29], 8);
+		print_ptr(data, 16);
+		rc = 1;
+		goto out;
+	}
+
+	/*
+	 * Rewrite the pattern that we've messed up
+	 */
+	rc = blocklevel_write(bl, 0, data, 0x100);
+	if (rc) {
+		ERR("Couldn't blocklevel_write(0, 0x100) to reset\n");
+		goto out;
+	}
+
+	/* Be unalignmed as possible from now on, starting somewhat easy */
+	rc = blocklevel_read(bl, 0, with_ecc, 5);
+	if (rc) {
+		ERR("Couldn't blocklevel_write(0, 5)\n");
+		goto out;
+	}
+	if (memcmp(with_ecc, data, 5)) {
+		ERR("blocklevel_read 5, 0) didn't match line: %d\n", __LINE__);
+		print_ptr(with_ecc, 5);
+		print_ptr(data, 5);
+		rc = 1;
+		goto out;
+	}
+
+	/* 39 is neither divisible by 8 or by 9 */
+	rc = blocklevel_read(bl, 39, with_ecc, 5);
+	if (rc) {
+		ERR("Couldn't blocklevel_write(39, 5)\n");
+		goto out;
+	}
+	if (memcmp(with_ecc, &data[39], 5)) {
+		ERR("blocklevel_read(5, 39() didn't match line: %d\n", __LINE__);
+		print_ptr(with_ecc, 5);
+		print_ptr(&data[39], 5);
+		rc = 1;
+		goto out;
+	}
+
+	rc = blocklevel_read(bl, 0xb, &with_ecc, 39);
+	if (rc) {
+		ERR("Couldn't blocklevel_read(0xb, 39)\n");
+		goto out;
+	}
+	if (memcmp(with_ecc, &data[0xb], 39)) {
+		ERR("Strange sized and positioned read failed, blocklevel_read(0xb, 39) line: %d\n", __LINE__);
+		print_ptr(with_ecc, 39);
+		print_ptr(&data[0xb], 39);
+		rc = 1;
+		goto out;
+	}
+
+	rc = blocklevel_write(bl, 39, data, 50);
+	if (rc) {
+		ERR("Couldn't blocklevel_write(39, 50)\n");
+		goto out;
+	}
+
+	rc = blocklevel_read(bl, 32, with_ecc, 39);
+	if (rc) {
+		ERR("Couldn't blocklevel_read(32, 39)\n");
+		goto out;
+	}
+
+	if (memcmp(with_ecc, &data[32], 7) || memcmp(((char *)with_ecc) + 7, data, 32)) {
+		ERR("Read back of odd placed/odd sized write failed, blocklevel_read(32, 39) line: %d\n", __LINE__);
+		print_ptr(with_ecc, 39);
+		print_ptr(&data[32], 7);
+		print_ptr(data, 32);
+		rc = 1;
+		goto out;
+	}
+
+out:
+	free(buf);
+	free(data);
+return rc;
 }
