]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
Use a power of generator representation of GF(256) multiplication group
authorVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Fri, 4 Nov 2011 12:27:50 +0000 (13:27 +0100)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Fri, 4 Nov 2011 12:27:50 +0000 (13:27 +0100)
to save space time and complexity.

* grub-core/disk/raid6_recover.c (raid6_table1): Removed.
(raid6_table2): Likewise.
(powx): New array.
(powx_inv): Likewise.
(poly): New const.
(grub_raid_block_mul): Replace with ...
(grub_raid_block_mulx): ...this.
(grub_raid6_init_table): Rewritten.
(grub_raid6_recover): Use power of generator representation.

ChangeLog
grub-core/disk/raid6_recover.c

index f8813f259c8687bc8940b31bca31c60c54da3fc8..b9e32f0e02a7c418b8f1fc6906898fab64a0070a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2011-11-04  Vladimir Serbinenko  <phcoder@gmail.com>
+
+       Use a power of generator representation of GF(256) multiplication group
+       to save space time and complexity.
+
+       * grub-core/disk/raid6_recover.c (raid6_table1): Removed.
+       (raid6_table2): Likewise.
+       (powx): New array.
+       (powx_inv): Likewise.
+       (poly): New const.
+       (grub_raid_block_mul): Replace with ...
+       (grub_raid_block_mulx): ...this.
+       (grub_raid6_init_table): Rewritten.
+       (grub_raid6_recover): Use power of generator representation.
+
 2011-11-04  Vladimir Serbinenko  <phcoder@gmail.com>
 
        * grub-core/disk/raid6_recover.c (grub_raid6_recover): Get start_sector
index 54dc612ee20ca6fea444c057de2074f2db3b1c56..e91992547fbd468791996450a5e3325dda1d7145 100644 (file)
 
 GRUB_MOD_LICENSE ("GPLv3+");
 
-static grub_uint8_t raid6_table1[256][256];
-static grub_uint8_t raid6_table2[256][256];
+/* x**y.  */
+static grub_uint8_t powx[255 * 2];
+/* Such an s that x**s = y */
+static int powx_inv[256];
+static const grub_uint8_t poly = 0x1d;
 
 static void
-grub_raid_block_mul (grub_uint8_t mul, char *buf, int size)
+grub_raid_block_mulx (int mul, char *buf, int size)
 {
   int i;
   grub_uint8_t *p;
 
   p = (grub_uint8_t *) buf;
   for (i = 0; i < size; i++, p++)
-    *p = raid6_table1[mul][*p];
+    if (*p)
+      *p = powx[mul + powx_inv[*p]];
 }
 
 static void
 grub_raid6_init_table (void)
 {
-  int i, j;
-
-  for (i = 0; i < 256; i++)
-    raid6_table1[i][1] = raid6_table1[1][i] = i;
-
-  for (i = 2; i < 256; i++)
-    for (j = i; j < 256; j++)
-      {
-        int n;
-        grub_uint8_t c;
-
-        n = i >> 1;
-
-        c = raid6_table1[n][j];
-        c = (c << 1) ^ ((c & 0x80) ? 0x1d : 0);
-        if (i & 1)
-          c ^= j;
-
-        raid6_table1[j][i] = raid6_table1[i][j] = c;
-      }
-
-  raid6_table2[0][0] = 1;
-  for (i = 1; i < 256; i++)
-    raid6_table2[i][i] = raid6_table1[raid6_table2[i - 1][i - 1]][2];
-
-  for (i = 0; i < 254; i++)
-    for (j = 0; j < 254; j++)
-      {
-        grub_uint8_t c, n;
-        int k;
-
-        if (i == j)
-          continue;
-
-        k = i - j;
-        if (k < 0)
-          k += 255;
-
-        c = n = raid6_table2[k][k] ^ 1;
-        for (k = 0; k < 253; k++)
-          c = raid6_table1[c][n];
+  int i;
 
-        raid6_table2[i][j] = raid6_table1[raid6_table2[255 - j][255 - j]][c];
-      }
+  grub_uint8_t cur = 1;
+  for (i = 0; i < 255; i++)
+    {
+      powx[i] = cur;
+      powx[i + 255] = cur;
+      powx_inv[cur] = i;
+      if (cur & 0x80)
+       cur = (cur << 1) ^ poly;
+      else
+       cur <<= 1;
+    }
 }
 
 static grub_err_t
@@ -126,7 +99,7 @@ grub_raid6_recover (struct grub_raid_array *array, int disknr, int p,
                                 0, size, buf)))
             {
               grub_raid_block_xor (pbuf, buf, size);
-              grub_raid_block_mul (raid6_table2[i][i], buf, size);
+              grub_raid_block_mulx (i, buf, size);
               grub_raid_block_xor (qbuf, buf, size);
             }
           else
@@ -173,13 +146,13 @@ grub_raid6_recover (struct grub_raid_array *array, int disknr, int p,
         goto quit;
 
       grub_raid_block_xor (buf, qbuf, size);
-      grub_raid_block_mul (raid6_table2[255 - bad1][255 - bad1], buf,
+      grub_raid_block_mulx (255 - bad1, buf,
                            size);
     }
   else
     {
       /* Two bad devices */
-      grub_uint8_t c;
+      int c;
 
       if ((! array->members[p].device) || (! array->members[q].device))
         {
@@ -201,11 +174,11 @@ grub_raid6_recover (struct grub_raid_array *array, int disknr, int p,
 
       grub_raid_block_xor (qbuf, buf, size);
 
-      c = raid6_table2[bad2][bad1];
-      grub_raid_block_mul (c, qbuf, size);
+      c = (255 - bad1 + (255 - powx_inv[(powx[bad2 - bad1 + 255] ^ 1)])) % 255;
+      grub_raid_block_mulx (c, qbuf, size);
 
-      c = raid6_table1[raid6_table2[bad2][bad2]][c];
-      grub_raid_block_mul (c, pbuf, size);
+      c = (bad2 + c) % 255;
+      grub_raid_block_mulx (c, pbuf, size);
 
       grub_raid_block_xor (pbuf, qbuf, size);
       grub_memcpy (buf, pbuf, size);