LCOV - code coverage report
Current view: top level - libflash/test - test-blocklevel.c (source / functions) Hit Total Coverage
Test: skiboot.info Lines: 160 392 40.8 %
Date: 2024-01-02 21:04:04 Functions: 6 10 60.0 %
Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
       2                 :            : /* Copyright 2013-2018 IBM Corp. */
       3                 :            : 
       4                 :            : #include <stdio.h>
       5                 :            : #include <stdlib.h>
       6                 :            : #include <stdint.h>
       7                 :            : #include <string.h>
       8                 :            : 
       9                 :            : #include <libflash/blocklevel.h>
      10                 :            : 
      11                 :            : #include "../ecc.c"
      12                 :            : #include "../blocklevel.c"
      13                 :            : 
      14                 :            : #define __unused                __attribute__((unused))
      15                 :            : 
      16                 :            : #define ERR(fmt...) fprintf(stderr, fmt)
      17                 :            : 
      18                 :            : bool libflash_debug;
      19                 :            : 
      20                 :          0 : static int bl_test_bad_read(struct blocklevel_device *bl __unused, uint64_t pos __unused,
      21                 :            :                 void *buf __unused, uint64_t len __unused)
      22                 :            : {
      23                 :          0 :         return FLASH_ERR_PARM_ERROR;
      24                 :            : }
      25                 :            : 
      26                 :         25 : static int bl_test_read(struct blocklevel_device *bl, uint64_t pos, void *buf, uint64_t len)
      27                 :            : {
      28                 :         25 :         if (pos + len > 0x1000)
      29                 :          0 :                 return FLASH_ERR_PARM_ERROR;
      30                 :            : 
      31                 :         25 :         memcpy(buf, bl->priv + pos, len);
      32                 :            : 
      33                 :         25 :         return 0;
      34                 :            : }
      35                 :            : 
      36                 :          0 : static int bl_test_bad_write(struct blocklevel_device *bl __unused, uint64_t pos __unused,
      37                 :            :                 const void *buf __unused, uint64_t len __unused)
      38                 :            : {
      39                 :          0 :         return FLASH_ERR_PARM_ERROR;
      40                 :            : }
      41                 :            : 
      42                 :         14 : static int bl_test_write(struct blocklevel_device *bl, uint64_t pos, const void *buf, uint64_t len)
      43                 :            : {
      44                 :         14 :         if (pos + len > 0x1000)
      45                 :          0 :                 return FLASH_ERR_PARM_ERROR;
      46                 :            : 
      47                 :         14 :         memcpy(bl->priv + pos, buf, len);
      48                 :            : 
      49                 :         14 :         return 0;
      50                 :            : }
      51                 :            : 
      52                 :         12 : static int bl_test_erase(struct blocklevel_device *bl, uint64_t pos, uint64_t len)
      53                 :            : {
      54                 :         12 :         if (pos + len > 0x1000)
      55                 :          0 :                 return FLASH_ERR_PARM_ERROR;
      56                 :            : 
      57                 :         12 :         memset(bl->priv + pos, 0xff, len);
      58                 :            : 
      59                 :         12 :         return 0;
      60                 :            : }
      61                 :            : 
      62                 :          0 : static void dump_buf(uint8_t *buf, int start, int end, int miss)
      63                 :            : {
      64                 :            :         int i;
      65                 :            : 
      66                 :          0 :         printf("pos: value\n");
      67                 :          0 :         for (i = start; i < end; i++)
      68                 :          0 :                 printf("%04x: %c%s\n", i, buf[i] == 0xff ? '-' : buf[i], i == miss ? " <- First missmatch" : "");
      69                 :          0 : }
      70                 :            : 
      71                 :            : /*
      72                 :            :  * Returns zero if the buffer is ok. Otherwise returns the position of
      73                 :            :  * the mismatch. If the mismatch is at zero -1 is returned
      74                 :            :  */
      75                 :          8 : static int check_buf(uint8_t *buf, int zero_start, int zero_end)
      76                 :            : {
      77                 :            :         int i;
      78                 :            : 
      79                 :      32776 :         for (i = 0; i < 0x1000; i++) {
      80                 :      32768 :                 if (i >= zero_start && i < zero_end && buf[i] != 0xff)
      81                 :          0 :                         return i == 0 ? -1 : i;
      82                 :      32768 :                 if ((i < zero_start || i >= zero_end) && buf[i] != (i % 26) + 'a')
      83                 :          0 :                         return i == 0 ? -1 : i;
      84                 :            :         }
      85                 :            : 
      86                 :          8 :         return 0;
      87                 :            : }
      88                 :            : 
      89                 :          9 : static void reset_buf(uint8_t *buf)
      90                 :            : {
      91                 :            :         int i;
      92                 :            : 
      93                 :      36873 :         for (i = 0; i < 0x1000; i++) {
      94                 :            :                 /* This gives repeating a - z which will be nice to visualise */
      95                 :      36864 :                 buf[i] = (i % 26) + 'a';
      96                 :            :         }
      97                 :          9 : }
      98                 :            : 
      99                 :          0 : static void print_ptr(void *ptr, int len)
     100                 :            : {
     101                 :            :         int i;
     102                 :          0 :         char *p = ptr;
     103                 :            : 
     104                 :          0 :         printf("0x");
     105                 :          0 :         for (i = 0; i < len; i++) {
     106                 :          0 :                 putchar(*p);
     107                 :          0 :                 if (i && i % 8 == 0) {
     108                 :          0 :                         putchar('\n');
     109                 :          0 :                         if (len - i)
     110                 :          0 :                                 printf("0x");
     111                 :            :                 }
     112                 :            :         }
     113                 :          0 :         putchar('\n');
     114                 :          0 : }
     115                 :            : 
     116                 :          1 : int main(void)
     117                 :            : {
     118                 :          1 :         struct blocklevel_device bl_mem = { 0 };
     119                 :          1 :         struct blocklevel_device *bl = &bl_mem;
     120                 :            :         uint64_t with_ecc[10], without_ecc[10];
     121                 :          1 :         char *buf = NULL, *data = NULL;
     122                 :            :         int i, rc, miss;
     123                 :            : 
     124                 :          1 :         if (blocklevel_ecc_protect(bl, 0, 0x1000)) {
     125                 :          0 :                 ERR("Failed to blocklevel_ecc_protect!\n");
     126                 :          0 :                 return 1;
     127                 :            :         }
     128                 :            : 
     129                 :            :         /* 0x1000 -> 0x3000 should remain unprotected */
     130                 :            : 
     131                 :          1 :         if (blocklevel_ecc_protect(bl, 0x3000, 0x1000)) {
     132                 :          0 :                 ERR("Failed to blocklevel_ecc_protect(0x3000, 0x1000)\n");
     133                 :          0 :                 return 1;
     134                 :            :         }
     135                 :          1 :         if (blocklevel_ecc_protect(bl, 0x2f00, 0x1100)) {
     136                 :          0 :                 ERR("Failed to blocklevel_ecc_protect(0x2f00, 0x1100)\n");
     137                 :          0 :                 return 1;
     138                 :            :         }
     139                 :            : 
     140                 :            :         /* Zero length protection */
     141                 :          1 :         if (!blocklevel_ecc_protect(bl, 0x4000, 0)) {
     142                 :          0 :                 ERR("Shouldn't have succeeded blocklevel_ecc_protect(0x4000, 0)\n");
     143                 :          0 :                 return 1;
     144                 :            :         }
     145                 :            : 
     146                 :            :         /* Minimum creatable size */
     147                 :          1 :         if (blocklevel_ecc_protect(bl, 0x4000, BYTES_PER_ECC)) {
     148                 :          0 :                 ERR("Failed to blocklevel_ecc_protect(0x4000, BYTES_PER_ECC)\n");
     149                 :          0 :                 return 1;
     150                 :            :         }
     151                 :            : 
     152                 :            :         /* Deal with overlapping protections */
     153                 :          1 :         if (blocklevel_ecc_protect(bl, 0x100, 0x1000)) {
     154                 :          0 :                 ERR("Failed to protect overlaping region blocklevel_ecc_protect(0x100, 0x1000)\n");
     155                 :          0 :                 return 1;
     156                 :            :         }
     157                 :            : 
     158                 :            :         /* Deal with overflow */
     159                 :          1 :         if (!blocklevel_ecc_protect(bl, 1, 0xFFFFFFFF)) {
     160                 :          0 :                 ERR("Added an 'overflow' protection blocklevel_ecc_protect(1, 0xFFFFFFFF)\n");
     161                 :          0 :                 return 1;
     162                 :            :         }
     163                 :            : 
     164                 :            :         /* Protect everything */
     165                 :          1 :         if (blocklevel_ecc_protect(bl, 0, 0xFFFFFFFF)) {
     166                 :          0 :                 ERR("Couldn't protect everything blocklevel_ecc_protect(0, 0xFFFFFFFF)\n");
     167                 :          0 :                 return 1;
     168                 :            :         }
     169                 :            : 
     170                 :          1 :         if (ecc_protected(bl, 0, 1, NULL) != 1) {
     171                 :          0 :                 ERR("Invaid result for ecc_protected(0, 1)\n");
     172                 :          0 :                 return 1;
     173                 :            :         }
     174                 :            : 
     175                 :          1 :         if (ecc_protected(bl, 0, 0x1000, NULL) != 1) {
     176                 :          0 :                 ERR("Invalid result for ecc_protected(0, 0x1000)\n");
     177                 :          0 :                 return 1;
     178                 :            :         }
     179                 :            : 
     180                 :          1 :         if (ecc_protected(bl, 0x100, 0x100, NULL) != 1) {
     181                 :          0 :                 ERR("Invalid result for ecc_protected(0x0100, 0x100)\n");
     182                 :          0 :                 return 1;
     183                 :            :         }
     184                 :            : 
     185                 :            :         /* Clear the protections */
     186                 :          1 :         bl->ecc_prot.n_prot = 0;
     187                 :            :         /* Reprotect */
     188                 :          1 :         if (blocklevel_ecc_protect(bl, 0x3000, 0x1000)) {
     189                 :          0 :                 ERR("Failed to blocklevel_ecc_protect(0x3000, 0x1000)\n");
     190                 :          0 :                 return 1;
     191                 :            :         }
     192                 :            :         /* Deal with overlapping protections */
     193                 :          1 :         if (blocklevel_ecc_protect(bl, 0x100, 0x1000)) {
     194                 :          0 :                 ERR("Failed to protect overlaping region blocklevel_ecc_protect(0x100, 0x1000)\n");
     195                 :          0 :                 return 1;
     196                 :            :         }
     197                 :            : 
     198                 :          1 :         if (ecc_protected(bl, 0x1000, 0, NULL) != 1) {
     199                 :          0 :                 ERR("Invalid result for ecc_protected(0x1000, 0)\n");
     200                 :          0 :                 return 1;
     201                 :            :         }
     202                 :            : 
     203                 :          1 :         if (ecc_protected(bl, 0x1000, 0x1000, NULL) != -1) {
     204                 :          0 :                 ERR("Invalid result for ecc_protected(0x1000, 0x1000)\n");
     205                 :          0 :                 return 1;
     206                 :            :         }
     207                 :            : 
     208                 :          1 :         if (ecc_protected(bl, 0x1000, 0x100, NULL) != 1) {
     209                 :          0 :                 ERR("Invalid result for ecc_protected(0x1000, 0x100)\n");
     210                 :          0 :                 return 1;
     211                 :            :         }
     212                 :            : 
     213                 :          1 :         if (ecc_protected(bl, 0x2000, 0, NULL) != 0) {
     214                 :          0 :                 ERR("Invalid result for ecc_protected(0x2000, 0)\n");
     215                 :          0 :                 return 1;
     216                 :            :         }
     217                 :            : 
     218                 :          1 :         if (ecc_protected(bl, 0x4000, 1, NULL) != 0) {
     219                 :          0 :                 ERR("Invalid result for ecc_protected(0x4000, 1)\n");
     220                 :          0 :                 return 1;
     221                 :            :         }
     222                 :            : 
     223                 :            :         /* Check for asking for a region with mixed protection */
     224                 :          1 :         if (ecc_protected(bl, 0x100, 0x2000, NULL) != -1) {
     225                 :          0 :                 ERR("Invalid result for ecc_protected(0x100, 0x2000)\n");
     226                 :          0 :                 return 1;
     227                 :            :         }
     228                 :            : 
     229                 :            :         /* Test the auto extending of regions */
     230                 :          1 :         if (blocklevel_ecc_protect(bl, 0x5000, 0x100)) {
     231                 :          0 :                 ERR("Failed to blocklevel_ecc_protect(0x5000, 0x100)\n");
     232                 :          0 :                 return 1;
     233                 :            :         }
     234                 :            : 
     235                 :          1 :         if (blocklevel_ecc_protect(bl, 0x5100, 0x100)) {
     236                 :          0 :                 ERR("Failed to blocklevel_ecc_protect(0x5100, 0x100)\n");
     237                 :          0 :                 return 1;
     238                 :            :         }
     239                 :            : 
     240                 :          1 :         if (blocklevel_ecc_protect(bl, 0x5200, 0x100)) {
     241                 :          0 :                 ERR("Failed to blocklevel_ecc_protect(0x5200, 0x100)\n");
     242                 :          0 :                 return 1;
     243                 :            :         }
     244                 :            : 
     245                 :          1 :         if (ecc_protected(bl, 0x5120, 0x10, NULL) != 1) {
     246                 :          0 :                 ERR("Invalid result for ecc_protected(0x5120, 0x10)\n");
     247                 :          0 :                 return 1;
     248                 :            :         }
     249                 :            : 
     250                 :          1 :         if (blocklevel_ecc_protect(bl, 0x4f00, 0x100)) {
     251                 :          0 :                 ERR("Failed to blocklevel_ecc_protected(0x4900, 0x100)\n");
     252                 :          0 :                 return 1;
     253                 :            :         }
     254                 :            : 
     255                 :          1 :         if (blocklevel_ecc_protect(bl, 0x4900, 0x100)) {
     256                 :          0 :                 ERR("Failed to blocklevel_ecc_protected(0x4900, 0x100)\n");
     257                 :          0 :                 return 1;
     258                 :            :         }
     259                 :            : 
     260                 :          1 :         if (ecc_protected(bl, 0x4920, 0x10, NULL) != 1) {
     261                 :          0 :                 ERR("Invalid result for ecc_protected(0x4920, 0x10)\n");
     262                 :          0 :                 return 1;
     263                 :            :         }
     264                 :            : 
     265                 :          1 :         if (blocklevel_ecc_protect(bl, 0x5290, 0x10)) {
     266                 :          0 :                 ERR("Failed to blocklevel_ecc_protect(0x5290, 0x10)\n");
     267                 :          0 :                 return 1;
     268                 :            :         }
     269                 :            : 
     270                 :            :         /* Test the auto extending of regions */
     271                 :          1 :         if (blocklevel_ecc_protect(bl, 0x6000, 0x100)) {
     272                 :          0 :                 ERR("Failed to blocklevel_ecc_protect(0x6000, 0x100)\n");
     273                 :          0 :                 return 1;
     274                 :            :         }
     275                 :            : 
     276                 :          1 :         if (blocklevel_ecc_protect(bl, 0x6200, 0x100)) {
     277                 :          0 :                 ERR("Failed to blocklevel_ecc_protect(0x6200, 0x100)\n");
     278                 :          0 :                 return 1;
     279                 :            :         }
     280                 :            : 
     281                 :            :         /* Test ECC reading and writing being 100% transparent to the
     282                 :            :          * caller */
     283                 :          1 :         buf = malloc(0x1000);
     284                 :          1 :         data = malloc(0x100);
     285                 :          1 :         if (!buf || !data) {
     286                 :          0 :                 ERR("Malloc failed\n");
     287                 :          0 :                 rc = 1;
     288                 :          0 :                 goto out;
     289                 :            :         }
     290                 :          1 :         memset(bl, 0, sizeof(*bl));
     291                 :          1 :         bl_mem.read = &bl_test_read;
     292                 :          1 :         bl_mem.write = &bl_test_write;
     293                 :          1 :         bl_mem.erase = &bl_test_erase;
     294                 :          1 :         bl_mem.erase_mask = 0xff;
     295                 :          1 :         bl_mem.priv = buf;
     296                 :          1 :         reset_buf(buf);
     297                 :            : 
     298                 :            : 
     299                 :            :         /*
     300                 :            :          * Test 1: One full and exact erase block, this shouldn't call
     301                 :            :          * read or write, ensure this fails if it does.
     302                 :            :          */
     303                 :          1 :         bl_mem.write = &bl_test_bad_write;
     304                 :          1 :         bl_mem.read = &bl_test_bad_read;
     305                 :          1 :         if (blocklevel_smart_erase(bl, 0x100, 0x100)) {
     306                 :          0 :                 ERR("Failed to blocklevel_smart_erase(0x100, 0x100)\n");
     307                 :          0 :                 goto out;
     308                 :            :         }
     309                 :          1 :         miss = check_buf(buf, 0x100, 0x200);
     310                 :          1 :         if (miss) {
     311                 :          0 :                 ERR("Buffer mismatch after blocklevel_smart_erase(0x100, 0x100) at 0x%0x\n",
     312                 :            :                                 miss == -1 ? 0 : miss);
     313                 :          0 :                 dump_buf(buf, 0xfc, 0x105, miss == -1 ? 0 : miss);
     314                 :          0 :                 dump_buf(buf, 0x1fc, 0x205, miss == -1 ? 0 : miss);
     315                 :          0 :                 goto out;
     316                 :            :         }
     317                 :          1 :         bl_mem.read = &bl_test_read;
     318                 :          1 :         bl_mem.write = &bl_test_write;
     319                 :            : 
     320                 :          1 :         reset_buf(buf);
     321                 :            :         /* Test 2: Only touch one erase block */
     322                 :          1 :         if (blocklevel_smart_erase(bl, 0x20, 0x40)) {
     323                 :          0 :                 ERR("Failed to blocklevel_smart_erase(0x20, 0x40)\n");
     324                 :          0 :                 goto out;
     325                 :            :         }
     326                 :          1 :         miss = check_buf(buf, 0x20, 0x60);
     327                 :          1 :         if (miss) {
     328                 :          0 :                 ERR("Buffer mismatch after blocklevel_smart_erase(0x20, 0x40) at 0x%x\n",
     329                 :            :                                 miss == -1 ? 0 : miss);
     330                 :          0 :                 dump_buf(buf, 0x1c, 0x65, miss == -1 ? 0 : miss);
     331                 :          0 :                 goto out;
     332                 :            :         }
     333                 :            : 
     334                 :          1 :         reset_buf(buf);
     335                 :            :         /* Test 3: Start aligned but finish somewhere in it */
     336                 :          1 :         if (blocklevel_smart_erase(bl, 0x100, 0x50)) {
     337                 :          0 :                 ERR("Failed to blocklevel_smart_erase(0x100, 0x50)\n");
     338                 :          0 :                 goto out;
     339                 :            :         }
     340                 :          1 :         miss = check_buf(buf, 0x100, 0x150);
     341                 :          1 :         if (miss) {
     342                 :          0 :                 ERR("Buffer mismatch after blocklevel_smart_erase(0x100, 0x50) at 0x%0x\n",
     343                 :            :                                 miss == -1 ? 0 : miss);
     344                 :          0 :                 dump_buf(buf, 0xfc, 0x105, miss == -1 ? 0 : miss);
     345                 :          0 :                 dump_buf(buf, 0x14c, 0x155, miss == -1 ? 0 : miss);
     346                 :          0 :                 goto out;
     347                 :            :         }
     348                 :            : 
     349                 :          1 :         reset_buf(buf);
     350                 :            :         /* Test 4: Start somewhere in it, finish aligned */
     351                 :          1 :         if (blocklevel_smart_erase(bl, 0x50, 0xb0)) {
     352                 :          0 :                 ERR("Failed to blocklevel_smart_erase(0x50, 0xb0)\n");
     353                 :          0 :                 goto out;
     354                 :            :         }
     355                 :          1 :         miss = check_buf(buf, 0x50, 0x100);
     356                 :          1 :         if (miss) {
     357                 :          0 :                 ERR("Buffer mismatch after blocklevel_smart_erase(0x50, 0xb0) at 0x%x\n",
     358                 :            :                                 miss == -1 ? 0 : miss);
     359                 :          0 :                 dump_buf(buf, 0x4c, 0x55, miss == -1 ? 0 : miss);
     360                 :          0 :                 dump_buf(buf, 0x100, 0x105, miss == -1 ? 0 : miss);
     361                 :          0 :                 goto out;
     362                 :            :         }
     363                 :            : 
     364                 :          1 :         reset_buf(buf);
     365                 :            :         /* Test 5: Cover two erase blocks exactly */
     366                 :          1 :         if (blocklevel_smart_erase(bl, 0x100, 0x200)) {
     367                 :          0 :                 ERR("Failed to blocklevel_smart_erase(0x100, 0x200)\n");
     368                 :          0 :                 goto out;
     369                 :            :         }
     370                 :          1 :         miss = check_buf(buf, 0x100, 0x300);
     371                 :          1 :         if (miss) {
     372                 :          0 :                 ERR("Buffer mismatch after blocklevel_smart_erase(0x100, 0x200) at 0x%x\n",
     373                 :            :                                 miss == -1 ? 0 : miss);
     374                 :          0 :                 dump_buf(buf, 0xfc, 0x105, miss == -1 ? 0 : miss);
     375                 :          0 :                 dump_buf(buf, 0x2fc, 0x305, miss == -1 ? 0 : miss);
     376                 :          0 :                 goto out;
     377                 :            :         }
     378                 :            : 
     379                 :          1 :         reset_buf(buf);
     380                 :            :         /* Test 6: Erase 1.5 blocks (start aligned) */
     381                 :          1 :         if (blocklevel_smart_erase(bl, 0x100, 0x180)) {
     382                 :          0 :                 ERR("Failed to blocklevel_smart_erase(0x100, 0x180)\n");
     383                 :          0 :                 goto out;
     384                 :            :         }
     385                 :          1 :         miss = check_buf(buf, 0x100, 0x280);
     386                 :          1 :         if (miss) {
     387                 :          0 :                 ERR("Buffer mismatch after blocklevel_smart_erase(0x100, 0x180) at 0x%x\n",
     388                 :            :                                 miss == -1 ? 0 : miss);
     389                 :          0 :                 dump_buf(buf, 0xfc, 0x105, miss == -1 ? 0 : miss);
     390                 :          0 :                 dump_buf(buf, 0x27c, 0x285, miss == -1 ? 0 : miss);
     391                 :          0 :                 goto out;
     392                 :            :         }
     393                 :            : 
     394                 :          1 :         reset_buf(buf);
     395                 :            :         /* Test 7: Erase 1.5 blocks (end aligned) */
     396                 :          1 :         if (blocklevel_smart_erase(bl, 0x80, 0x180)) {
     397                 :          0 :                 ERR("Failed to blocklevel_smart_erase(0x80, 0x180)\n");
     398                 :          0 :                 goto out;
     399                 :            :         }
     400                 :          1 :         miss = check_buf(buf, 0x80, 0x200);
     401                 :          1 :         if (miss) {
     402                 :          0 :                 ERR("Buffer mismatch after blocklevel_smart_erase(0x80, 0x180) at 0x%x\n",
     403                 :            :                                 miss == -1 ? 0 : miss);
     404                 :          0 :                 dump_buf(buf, 0x7c, 0x85, miss == -1 ? 0 : miss);
     405                 :          0 :                 dump_buf(buf, 0x1fc, 0x205, miss == -1 ? 0 : miss);
     406                 :          0 :                 goto out;
     407                 :            :         }
     408                 :            : 
     409                 :          1 :         reset_buf(buf);
     410                 :            :         /* Test 8: Erase a big section, not aligned */
     411                 :          1 :         if (blocklevel_smart_erase(bl, 0x120, 0x544)) {
     412                 :          0 :                 ERR("Failed to blocklevel_smart_erase(0x120, 0x544)\n");
     413                 :          0 :                 goto out;
     414                 :            :         }
     415                 :          1 :         miss = check_buf(buf, 0x120, 0x664);
     416                 :          1 :         if (miss) {
     417                 :          0 :                 ERR("Buffer mismatch after blocklevel_smart_erase(0x120, 0x544) at 0x%x\n",
     418                 :            :                                 miss == -1 ? 0 : miss);
     419                 :          0 :                 dump_buf(buf, 0x11c, 0x125, miss == -1 ? 0 : miss);
     420                 :          0 :                 dump_buf(buf, 0x65f, 0x669, miss == -1 ? 0 : miss);
     421                 :          0 :                 goto out;
     422                 :            :         }
     423                 :            : 
     424                 :          1 :         bl_mem.priv = buf;
     425                 :          1 :         reset_buf(buf);
     426                 :            : 
     427                 :        257 :         for (i = 0; i < 0x100; i++)
     428                 :        256 :                 data[i] = i;
     429                 :            : 
     430                 :            :         /* This really shouldn't fail */
     431                 :          1 :         rc = blocklevel_ecc_protect(bl, 0, 0x100);
     432                 :          1 :         if (rc) {
     433                 :          0 :                 ERR("Couldn't blocklevel_ecc_protect(0, 0x100)\n");
     434                 :          0 :                 goto out;
     435                 :            :         }
     436                 :            : 
     437                 :          1 :         rc = blocklevel_write(bl, 0, data, 0x100);
     438                 :          1 :         if (rc) {
     439                 :          0 :                 ERR("Couldn't blocklevel_write(0, 0x100)\n");
     440                 :          0 :                 goto out;
     441                 :            :         }
     442                 :            : 
     443                 :          1 :         rc = blocklevel_write(bl, 0x200, data, 0x100);
     444                 :          1 :         if (rc) {
     445                 :          0 :                 ERR("Couldn't blocklevel_write(0x200, 0x100)\n");
     446                 :          0 :                 goto out;
     447                 :            :         }
     448                 :            : 
     449                 :            :         /*
     450                 :            :          * 0x50 once adjusted for the presence of ECC becomes 0x5a which
     451                 :            :          * is ECC aligned.
     452                 :            :          */
     453                 :          1 :         rc = blocklevel_read(bl, 0x50, with_ecc, 8);
     454                 :          1 :         if (rc) {
     455                 :          0 :                 ERR("Couldn't blocklevel_read(0x50, 8) with ecc rc=%d\n", rc);
     456                 :          0 :                 goto out;
     457                 :            :         }
     458                 :          1 :         rc = blocklevel_read(bl, 0x250, without_ecc, 8);
     459                 :          1 :         if (rc) {
     460                 :          0 :                 ERR("Couldn't blocklevel_read(0x250, 8) without ecc rc=%d\n", rc);
     461                 :          0 :                 goto out;
     462                 :            :         }
     463                 :          1 :         if (memcmp(with_ecc, without_ecc, 8) || memcmp(with_ecc, &data[0x50], 8)) {
     464                 :          0 :                 ERR("ECC read and non-ECC read don't match or are wrong line: %d\n", __LINE__);
     465                 :          0 :                 print_ptr(with_ecc, 8);
     466                 :          0 :                 print_ptr(without_ecc, 8);
     467                 :          0 :                 print_ptr(&data[50], 8);
     468                 :          0 :                 rc = 1;
     469                 :          0 :                 goto out;
     470                 :            :         }
     471                 :            : 
     472                 :            :         /*
     473                 :            :          * 0x50 once adjusted for the presence of ECC becomes 0x5a which
     474                 :            :          * is ECC aligned.
     475                 :            :          * So 0x4f won't be aligned!
     476                 :            :          */
     477                 :          1 :         rc = blocklevel_read(bl, 0x4f, with_ecc, 8);
     478                 :          1 :         if (rc) {
     479                 :          0 :                 ERR("Couldn't blocklevel_read(0x4f, 8) with ecc %d\n", rc);
     480                 :          0 :                 goto out;
     481                 :            :         }
     482                 :          1 :         rc = blocklevel_read(bl, 0x24f, without_ecc, 8);
     483                 :          1 :         if (rc) {
     484                 :          0 :                 ERR("Couldn't blocklevel_read(0x24f, 8) without ecc %d\n", rc);
     485                 :          0 :                 goto out;
     486                 :            :         }
     487                 :          1 :         if (memcmp(with_ecc, without_ecc, 8) || memcmp(with_ecc, &data[0x4f], 8)) {
     488                 :          0 :                 ERR("ECC read and non-ECC read don't match or are wrong line: %d\n", __LINE__);
     489                 :          0 :                 print_ptr(with_ecc, 8);
     490                 :          0 :                 print_ptr(without_ecc, 8);
     491                 :          0 :                 print_ptr(&data[0x4f], 8);
     492                 :          0 :                 rc = 1;
     493                 :          0 :                 goto out;
     494                 :            :         }
     495                 :            : 
     496                 :            :         /*
     497                 :            :          * 0x50 once adjusted for the presence of ECC becomes 0x5a which
     498                 :            :          * is ECC aligned.
     499                 :            :          */
     500                 :          1 :         rc = blocklevel_read(bl, 0x50, with_ecc, 16);
     501                 :          1 :         if (rc) {
     502                 :          0 :                 ERR("Couldn't blocklevel_read(0x50, 16) with ecc %d\n", rc);
     503                 :          0 :                 goto out;
     504                 :            :         }
     505                 :          1 :         rc = blocklevel_read(bl, 0x250, without_ecc, 16);
     506                 :          1 :         if (rc) {
     507                 :          0 :                 ERR("Couldn't blocklevel_read(0x250, 16) without ecc %d\n", rc);
     508                 :          0 :                 goto out;
     509                 :            :         }
     510                 :          1 :         if (memcmp(with_ecc, without_ecc, 16)|| memcmp(with_ecc, &data[0x50], 16)) {
     511                 :          0 :                 ERR("(long read )ECC read and non-ECC read don't match or are wrong line: %d\n", __LINE__);
     512                 :          0 :                 print_ptr(with_ecc, 16);
     513                 :          0 :                 print_ptr(without_ecc, 16);
     514                 :          0 :                 print_ptr(&data[0x50], 16);
     515                 :          0 :                 rc = 1;
     516                 :          0 :                 goto out;
     517                 :            :         }
     518                 :            : 
     519                 :            :         /*
     520                 :            :          * 0x50 once adjusted for the presence of ECC becomes 0x5a which
     521                 :            :          * is ECC aligned. So 4f won't be.
     522                 :            :          */
     523                 :          1 :         rc = blocklevel_read(bl, 0x4f, with_ecc, 24);
     524                 :          1 :         if (rc) {
     525                 :          0 :                 ERR("Couldn't blocklevel_read(0x4f, 24) with ecc %d\n", rc);
     526                 :          0 :                 goto out;
     527                 :            :         }
     528                 :          1 :         rc = blocklevel_read(bl, 0x24f, without_ecc, 24);
     529                 :          1 :         if (rc) {
     530                 :          0 :                 ERR("Couldn't blocklevel_read(0x24f, 24) without ecc %d\n", rc);
     531                 :          0 :                 goto out;
     532                 :            :         }
     533                 :          1 :         if (memcmp(with_ecc, without_ecc, 24)|| memcmp(with_ecc, &data[0x4f], 24)) {
     534                 :          0 :                 ERR("(long read )ECC read and non-ECC read don't match or are wrong: %d\n", __LINE__);
     535                 :          0 :                 print_ptr(with_ecc, 24);
     536                 :          0 :                 print_ptr(without_ecc, 24);
     537                 :          0 :                 print_ptr(&data[0x4f], 24);
     538                 :          0 :                 rc = 1;
     539                 :          0 :                 goto out;
     540                 :            :         }
     541                 :            : 
     542                 :            :         /*
     543                 :            :          * Now lets try to write at non ECC aligned positions
     544                 :            :          * Go easy first, 0x50 becomes 0x5a which is ECC byte aligned but
     545                 :            :          * not aligned to the start of the partition
     546                 :            :          */
     547                 :            : 
     548                 :          1 :         rc = blocklevel_write(bl, 0x50, data, 0xb0);
     549                 :          1 :         if (rc) {
     550                 :          0 :                 ERR("Couldn't blocklevel_write()\n");
     551                 :          0 :                 goto out;
     552                 :            :         }
     553                 :            :         /* Read 8 bytes before to make sure we didn't ruin that */
     554                 :          1 :         rc = blocklevel_read(bl, 0x48, with_ecc, 24);
     555                 :          1 :         if (rc) {
     556                 :          0 :                 ERR("Couldn't blocklevel_read() with ecc %d\n", rc);
     557                 :          0 :                 goto out;
     558                 :            :         }
     559                 :          1 :         if (memcmp(with_ecc, data + 0x48, 8) || memcmp(with_ecc + 1, data, 16)) {
     560                 :          0 :                 rc = 1;
     561                 :          0 :                 ERR("Couldn't read back what we thought we wrote line: %d\n", __LINE__);
     562                 :          0 :                 print_ptr(with_ecc, 24);
     563                 :          0 :                 print_ptr(&data[0x48], 8);
     564                 :          0 :                 print_ptr(data, 16);
     565                 :          0 :                 goto out;
     566                 :            :         }
     567                 :            : 
     568                 :            :         /* Ok lets get tricky */
     569                 :          1 :         rc = blocklevel_write(bl, 0x31, data, 0xcf);
     570                 :          1 :         if (rc) {
     571                 :          0 :                 ERR("Couldn't blocklevel_write(0x31, 0xcf)\n");
     572                 :          0 :                 goto out;
     573                 :            :         }
     574                 :            :         /* Read 8 bytes before to make sure we didn't ruin that */
     575                 :          1 :         rc = blocklevel_read(bl, 0x29, with_ecc, 24);
     576                 :          1 :         if (rc) {
     577                 :          0 :                 ERR("Couldn't blocklevel_read(0x29, 24) with ecc rc=%d\n", rc);
     578                 :          0 :                 goto out;
     579                 :            :         }
     580                 :          1 :         if (memcmp(with_ecc, &data[0x29], 8) || memcmp(with_ecc + 1, data, 16)) {
     581                 :          0 :                 ERR("Couldn't read back what we thought we wrote line: %d\n", __LINE__);
     582                 :          0 :                 print_ptr(with_ecc, 24);
     583                 :          0 :                 print_ptr(&data[0x29], 8);
     584                 :          0 :                 print_ptr(data, 16);
     585                 :          0 :                 rc = 1;
     586                 :          0 :                 goto out;
     587                 :            :         }
     588                 :            : 
     589                 :            :         /*
     590                 :            :          * Rewrite the pattern that we've messed up
     591                 :            :          */
     592                 :          1 :         rc = blocklevel_write(bl, 0, data, 0x100);
     593                 :          1 :         if (rc) {
     594                 :          0 :                 ERR("Couldn't blocklevel_write(0, 0x100) to reset\n");
     595                 :          0 :                 goto out;
     596                 :            :         }
     597                 :            : 
     598                 :            :         /* Be unalignmed as possible from now on, starting somewhat easy */
     599                 :          1 :         rc = blocklevel_read(bl, 0, with_ecc, 5);
     600                 :          1 :         if (rc) {
     601                 :          0 :                 ERR("Couldn't blocklevel_write(0, 5)\n");
     602                 :          0 :                 goto out;
     603                 :            :         }
     604                 :          1 :         if (memcmp(with_ecc, data, 5)) {
     605                 :          0 :                 ERR("blocklevel_read 5, 0) didn't match line: %d\n", __LINE__);
     606                 :          0 :                 print_ptr(with_ecc, 5);
     607                 :          0 :                 print_ptr(data, 5);
     608                 :          0 :                 rc = 1;
     609                 :          0 :                 goto out;
     610                 :            :         }
     611                 :            : 
     612                 :            :         /* 39 is neither divisible by 8 or by 9 */
     613                 :          1 :         rc = blocklevel_read(bl, 39, with_ecc, 5);
     614                 :          1 :         if (rc) {
     615                 :          0 :                 ERR("Couldn't blocklevel_write(39, 5)\n");
     616                 :          0 :                 goto out;
     617                 :            :         }
     618                 :          1 :         if (memcmp(with_ecc, &data[39], 5)) {
     619                 :          0 :                 ERR("blocklevel_read(5, 39() didn't match line: %d\n", __LINE__);
     620                 :          0 :                 print_ptr(with_ecc, 5);
     621                 :          0 :                 print_ptr(&data[39], 5);
     622                 :          0 :                 rc = 1;
     623                 :          0 :                 goto out;
     624                 :            :         }
     625                 :            : 
     626                 :          1 :         rc = blocklevel_read(bl, 0xb, &with_ecc, 39);
     627                 :          1 :         if (rc) {
     628                 :          0 :                 ERR("Couldn't blocklevel_read(0xb, 39)\n");
     629                 :          0 :                 goto out;
     630                 :            :         }
     631                 :          1 :         if (memcmp(with_ecc, &data[0xb], 39)) {
     632                 :          0 :                 ERR("Strange sized and positioned read failed, blocklevel_read(0xb, 39) line: %d\n", __LINE__);
     633                 :          0 :                 print_ptr(with_ecc, 39);
     634                 :          0 :                 print_ptr(&data[0xb], 39);
     635                 :          0 :                 rc = 1;
     636                 :          0 :                 goto out;
     637                 :            :         }
     638                 :            : 
     639                 :          1 :         rc = blocklevel_write(bl, 39, data, 50);
     640                 :          1 :         if (rc) {
     641                 :          0 :                 ERR("Couldn't blocklevel_write(39, 50)\n");
     642                 :          0 :                 goto out;
     643                 :            :         }
     644                 :            : 
     645                 :          1 :         rc = blocklevel_read(bl, 32, with_ecc, 39);
     646                 :          1 :         if (rc) {
     647                 :          0 :                 ERR("Couldn't blocklevel_read(32, 39)\n");
     648                 :          0 :                 goto out;
     649                 :            :         }
     650                 :            : 
     651                 :          1 :         if (memcmp(with_ecc, &data[32], 7) || memcmp(((char *)with_ecc) + 7, data, 32)) {
     652                 :          0 :                 ERR("Read back of odd placed/odd sized write failed, blocklevel_read(32, 39) line: %d\n", __LINE__);
     653                 :          0 :                 print_ptr(with_ecc, 39);
     654                 :          0 :                 print_ptr(&data[32], 7);
     655                 :          0 :                 print_ptr(data, 32);
     656                 :          0 :                 rc = 1;
     657                 :          0 :                 goto out;
     658                 :            :         }
     659                 :            : 
     660                 :          1 : out:
     661                 :          1 :         free(buf);
     662                 :          1 :         free(data);
     663                 :          1 : return rc;
     664                 :            : }

Generated by: LCOV version 1.14