]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
Use static allocation rather than scratch pointer in reed_solomon.
authorVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Tue, 24 Jan 2012 13:49:31 +0000 (14:49 +0100)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Tue, 24 Jan 2012 13:49:31 +0000 (14:49 +0100)
It decreases its size significantly and avoids a variable in .text.

* grub-core/lib/reed_solomon.c (scratch): Removed.
(chosenstat): New const or static array.
(sigma): Likewise.
(errpot): Likewise.
(errpos): Likewise.
(sy): Likewise.
(mstat): Likewise.
(errvals): Likewise.
(eqstat): Likewise.
(pol_evaluate): Replace x with log_x argument. All users updated.
(syndroms): Removed.
(gauss_solve): Use statically allocated arrays.
(rs_recover): Likewise.
Calculate syndroms directly.
(decode_block): Use statically allocated arrays.
(grub_reed_solomon_add_redundancy) [TEST]: Fix -DTEST compilation.
(main) [TEST]: Allow -DTEST -DSTANDALONE.

ChangeLog
grub-core/lib/reed_solomon.c

index d0c959ae35e096a90b020f9755c12232ceb0686d..eeacee49ec51771dc536942edbb81de6f9c582bf 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,26 @@
+2012-01-24  Vladimir Serbinenko  <phcoder@gmail.com>
+
+       Use static allocation rather than scratch pointer in reed_solomon.
+       It decreases its size significantly and avoids a variable in .text.
+
+       * grub-core/lib/reed_solomon.c (scratch): Removed.
+       (chosenstat): New const or static array.
+       (sigma): Likewise.
+       (errpot): Likewise.
+       (errpos): Likewise.
+       (sy): Likewise.
+       (mstat): Likewise.
+       (errvals): Likewise.
+       (eqstat): Likewise.
+       (pol_evaluate): Replace x with log_x argument. All users updated.
+       (syndroms): Removed.
+       (gauss_solve): Use statically allocated arrays.
+       (rs_recover): Likewise.
+       Calculate syndroms directly.
+       (decode_block): Use statically allocated arrays.
+       (grub_reed_solomon_add_redundancy) [TEST]: Fix -DTEST compilation.
+       (main) [TEST]: Allow -DTEST -DSTANDALONE.
+
 2012-01-24  Vladimir Serbinenko  <phcoder@gmail.com>
 
        Eliminate fixed limit on reed solomon decoder length.
index 0257342d0419463ef82e531c7c12ef52007e781b..704ebd3f2559a96ae81b7899779fd9e655acd20e 100644 (file)
@@ -41,6 +41,9 @@ typedef unsigned char grub_uint8_t;
 #endif
 #endif
 
+#define SECTOR_SIZE 512
+#define MAX_BLOCK_SIZE (200 * SECTOR_SIZE)
+
 #ifdef STANDALONE
 #ifdef TEST
 typedef unsigned int grub_size_t;
@@ -60,19 +63,29 @@ typedef grub_uint8_t gf_single_t;
 #if defined (STANDALONE) && !defined (TEST)
 static gf_single_t * const gf_powx __attribute__ ((section(".text"))) = (void *) 0x100000;
 static gf_single_t * const gf_powx_inv __attribute__ ((section(".text"))) = (void *) 0x100200;
-
-static char *scratch __attribute__ ((section(".text"))) = (void *) 0x100300;
+static int *const chosenstat __attribute__ ((section(".text"))) = (void *) 0x100300;
+static gf_single_t *const sigma __attribute__ ((section(".text"))) = (void *) 0x100700;
+static gf_single_t *const errpot __attribute__ ((section(".text"))) = (void *) 0x100800;
+static int *const errpos __attribute__ ((section(".text"))) = (void *) 0x100900;
+static gf_single_t *const sy __attribute__ ((section(".text"))) = (void *) 0x100d00;
+static gf_single_t *const mstat __attribute__ ((section(".text"))) = (void *) 0x100e00;
+static gf_single_t *const errvals __attribute__ ((section(".text"))) = (void *) 0x100f00;
+static gf_single_t *const eqstat __attribute__ ((section(".text"))) = (void *) 0x101000;
+/* Next available address: (void *) 0x112000.  */
 #else
-#if defined (STANDALONE)
-static char *scratch;
-#endif
+
 static gf_single_t gf_powx[255 * 2];
 static gf_single_t gf_powx_inv[256];
+static int chosenstat[256];
+static gf_single_t sigma[256];
+static gf_single_t errpot[256];
+static int errpos[256];
+static gf_single_t sy[256];
+static gf_single_t mstat[256];
+static gf_single_t errvals[256];
+static gf_single_t eqstat[65536 + 256];
 #endif
 
-#define SECTOR_SIZE 512
-#define MAX_BLOCK_SIZE (200 * SECTOR_SIZE)
-
 static gf_single_t
 gf_mul (gf_single_t a, gf_single_t b)
 {
@@ -107,14 +120,11 @@ init_powx (void)
 }
 
 static gf_single_t
-pol_evaluate (gf_single_t *pol, grub_size_t degree, gf_single_t x)
+pol_evaluate (gf_single_t *pol, grub_size_t degree, int log_x)
 {
   int i;
   gf_single_t s = 0;
-  int log_xn = 0, log_x;
-  if (x == 0)
-    return pol[0];
-  log_x = gf_powx_inv[x];
+  int log_xn = 0;
   for (i = degree; i >= 0; i--)
     {
       if (pol[i])
@@ -164,26 +174,6 @@ rs_encode (gf_single_t *data, grub_size_t s, grub_size_t rs)
 }
 #endif
 
-static void
-syndroms (gf_single_t *m, grub_size_t s, grub_size_t rs,
-         gf_single_t *sy)
-{
-  gf_single_t xn = 1;
-  unsigned i;
-  sy[0] = pol_evaluate (m, s + rs - 1, xn);
-  for (i = 1; i < rs; i++)
-    {
-      if (xn & (1 << (GF_SIZE - 1)))
-       {
-         xn <<= 1;
-         xn ^= GF_POLYNOMIAL;
-       }
-      else
-       xn <<= 1;
-      sy[i] = pol_evaluate (m, s + rs - 1, xn);
-    }
-}
-
 static void
 gauss_eliminate (gf_single_t *eq, int n, int m, int *chosen)
 {
@@ -214,65 +204,34 @@ gauss_eliminate (gf_single_t *eq, int n, int m, int *chosen)
 static void
 gauss_solve (gf_single_t *eq, int n, int m, gf_single_t *sol)
 {
-  int *chosen;
   int i, j;
 
-#ifndef STANDALONE
-  chosen = xmalloc (n * sizeof (int));
-#else
-  chosen = (void *) scratch;
-  scratch += n * sizeof (int);
-#endif
   for (i = 0; i < n; i++)
-    chosen[i] = -1;
+    chosenstat[i] = -1;
   for (i = 0; i < m; i++)
     sol[i] = 0;
-  gauss_eliminate (eq, n, m, chosen);
+  gauss_eliminate (eq, n, m, chosenstat);
   for (i = n - 1; i >= 0; i--)
     {
       gf_single_t s = 0;
-      if (chosen[i] == -1)
+      if (chosenstat[i] == -1)
        continue;
       for (j = 0; j < m; j++)
        s ^= gf_mul (eq[i * (m + 1) + j], sol[j]);
       s ^= eq[i * (m + 1) + m];
-      sol[chosen[i]] = s;
+      sol[chosenstat[i]] = s;
     }
-#ifndef STANDALONE
-  free (chosen);
-#else
-  scratch -= n * sizeof (int);
-#endif
 }
 
 static void
-rs_recover (gf_single_t *m, grub_size_t s, grub_size_t rs)
+rs_recover (gf_single_t *mm, grub_size_t s, grub_size_t rs)
 {
   grub_size_t rs2 = rs / 2;
-  gf_single_t *sigma;
-  gf_single_t *errpot;
-  int *errpos;
-  gf_single_t *sy;
   int errnum = 0;
   int i, j;
 
-#ifndef STANDALONE
-  sigma = xmalloc (rs2 * sizeof (gf_single_t));
-  errpot = xmalloc (rs2 * sizeof (gf_single_t));
-  errpos = xmalloc (rs2 * sizeof (int));
-  sy = xmalloc (rs * sizeof (gf_single_t));
-#else
-  sigma = (void *) scratch;
-  scratch += rs2 * sizeof (gf_single_t);
-  errpot = (void *) scratch;
-  scratch += rs2 * sizeof (gf_single_t);
-  errpos = (void *) scratch;
-  scratch += rs2 * sizeof (int);
-  sy = (void *) scratch;
-  scratch += rs * sizeof (gf_single_t);
-#endif
-
-  syndroms (m, s, rs, sy);
+  for (i = 0; i < (int) rs; i++)
+    sy[i] = pol_evaluate (mm, s + rs - 1, i);
 
   for (i = 0; i < (int) rs; i++)
     if (sy[i] != 0)
@@ -280,109 +239,44 @@ rs_recover (gf_single_t *m, grub_size_t s, grub_size_t rs)
 
   /* No error detected.  */
   if (i == (int) rs)
-    {
-#ifndef STANDALONE
-      free (sigma);
-      free (errpot);
-      free (errpos);
-      free (sy);
-#else
-      scratch -= rs2 * sizeof (gf_single_t);
-      scratch -= rs2 * sizeof (gf_single_t);
-      scratch -= rs2 * sizeof (int);
-      scratch -= rs * sizeof (gf_single_t);
-#endif
-      return;
-    }
+    return;
 
   {
-    gf_single_t *eq;
-
-#ifndef STANDALONE
-    eq = xmalloc (rs2 * (rs2 + 1) * sizeof (gf_single_t));
-#else
-    eq = (void *) scratch;
-    scratch += rs2 * (rs2 + 1) * sizeof (gf_single_t);
-#endif
 
     for (i = 0; i < (int) rs2; i++)
       for (j = 0; j < (int) rs2 + 1; j++)
-       eq[i * (rs2 + 1) + j] = sy[i+j];
+       eqstat[i * (rs2 + 1) + j] = sy[i+j];
 
     for (i = 0; i < (int) rs2; i++)
       sigma[i] = 0;
 
-    gauss_solve (eq, rs2, rs2, sigma);
-
-#ifndef STANDALONE
-    free (eq);
-#else
-    scratch -= rs2 * (rs2 + 1) * sizeof (gf_single_t);
-#endif
+    gauss_solve (eqstat, rs2, rs2, sigma);
   } 
 
-  {
-    gf_single_t xn = 1, yn = 1;
-    for (i = 0; i < (int) (rs + s); i++)
+  for (i = 0; i < (int) (rs + s); i++)
+    if (pol_evaluate (sigma, rs2 - 1, 255 - i) == gf_powx[i])
       {
-       gf_single_t ev = (gf_mul (pol_evaluate (sigma, rs2 - 1, xn), xn) ^ 1);
-       if (ev == 0)
-         {
-           errpot[errnum] = yn;
-           errpos[errnum++] = s + rs - i - 1;
-         }
-       yn = gf_mul (yn, 2);
-       xn = gf_mul (xn, GF_INVERT2);
+       errpot[errnum] = gf_powx[i];
+       errpos[errnum++] = s + rs - i - 1;
       }
-  }
   {
-    gf_single_t *errvals;
-    gf_single_t *eq;
-
-#ifndef STANDALONE
-    eq = xmalloc (rs * (errnum + 1) * sizeof (gf_single_t));
-    errvals = xmalloc (errnum * sizeof (int));
-#else
-    eq = (void *) scratch;
-    scratch += rs * (errnum + 1) * sizeof (gf_single_t);
-    errvals = (void *) scratch;
-    scratch += errnum * sizeof (int);
-#endif
-
     for (j = 0; j < errnum; j++)
-      eq[j] = 1;
-    eq[errnum] = sy[0];
+      eqstat[j] = 1;
+    eqstat[errnum] = sy[0];
     for (i = 1; i < (int) rs; i++)
       {
        for (j = 0; j < (int) errnum; j++)
-         eq[(errnum + 1) * i + j] = gf_mul (errpot[j],
-                                            eq[(errnum + 1) * (i - 1) + j]);
-       eq[(errnum + 1) * i + errnum] = sy[i];
+         eqstat[(errnum + 1) * i + j] = gf_mul (errpot[j],
+                                                eqstat[(errnum + 1) * (i - 1)
+                                                       + j]);
+       eqstat[(errnum + 1) * i + errnum] = sy[i];
       }
 
-    gauss_solve (eq, rs, errnum, errvals);
+    gauss_solve (eqstat, rs, errnum, errvals);
 
     for (i = 0; i < (int) errnum; i++)
-      m[errpos[i]] ^= errvals[i];
-#ifndef STANDALONE
-    free (eq);
-    free (errvals);
-#else
-    scratch -= rs * (errnum + 1) * sizeof (gf_single_t);
-    scratch -= errnum * sizeof (int);
-#endif
+      mm[errpos[i]] ^= errvals[i];
   }
-#ifndef STANDALONE
-  free (sigma);
-  free (errpot);
-  free (errpos);
-  free (sy);
-#else
-  scratch -= rs2 * sizeof (gf_single_t);
-  scratch -= rs2 * sizeof (gf_single_t);
-  scratch -= rs2 * sizeof (int);
-  scratch -= rs * sizeof (gf_single_t);
-#endif
 }
 
 static void
@@ -394,34 +288,20 @@ decode_block (gf_single_t *ptr, grub_size_t s,
     {
       grub_size_t ds = (s + SECTOR_SIZE - 1 - i) / SECTOR_SIZE;
       grub_size_t rr = (rs + SECTOR_SIZE - 1 - i) / SECTOR_SIZE;
-      gf_single_t *m;
 
       /* Nothing to do.  */
       if (!ds || !rr)
        continue;
 
-#ifndef STANDALONE
-      m = xmalloc (ds + rr);
-#else
-      m = (gf_single_t *) scratch;
-      scratch += ds + rr;
-#endif
-
       for (j = 0; j < (int) ds; j++)
-       m[j] = ptr[SECTOR_SIZE * j + i];
+       mstat[j] = ptr[SECTOR_SIZE * j + i];
       for (j = 0; j < (int) rr; j++)
-       m[j + ds] = rptr[SECTOR_SIZE * j + i];
+       mstat[j + ds] = rptr[SECTOR_SIZE * j + i];
 
-      rs_recover (m, ds, rr);
+      rs_recover (mstat, ds, rr);
 
       for (j = 0; j < (int) ds; j++)
-       ptr[SECTOR_SIZE * j + i] = m[j];
-
-#ifndef STANDALONE
-      free (m);
-#else
-      scratch -= ds + rr;
-#endif
+       ptr[SECTOR_SIZE * j + i] = mstat[j];
     }
 }
 
@@ -490,7 +370,9 @@ grub_reed_solomon_add_redundancy (void *buffer, grub_size_t data_size,
       rs -= crs;
     }
 
+#ifndef TEST
   assert (grub_memcmp (tmp, buffer, data_size) == 0);
+#endif
   free (tmp);
 }
 #endif
@@ -538,14 +420,11 @@ main (int argc, char **argv)
   grub_memset (gf_powx, 0xee, sizeof (gf_powx));
   grub_memset (gf_powx_inv, 0xdd, sizeof (gf_powx_inv));
 
-#ifdef STANDALONE
-  scratch = xmalloc (1048576);
-#endif
-
 #ifndef STANDALONE
   init_powx ();
 #endif
 
+#ifndef STANDALONE
   in = fopen ("tst.bin", "rb");
   if (!in)
     return 1;
@@ -562,6 +441,18 @@ main (int argc, char **argv)
   out = fopen ("tst_rs.bin", "wb");
   fwrite (buf, 1, s + rs, out);
   fclose (out);
+#else
+  out = fopen ("tst_rs.bin", "rb");
+  fseek (out, 0, SEEK_END);
+  s = ftell (out);
+  fseek (out, 0, SEEK_SET);
+  rs = 0x7007;
+  s -= rs;
+
+  buf = xmalloc (s + rs + SECTOR_SIZE);
+  fread (buf, 1, s + rs, out);
+  fclose (out);  
+#endif
 #if 1
   grub_memset (buf + 512 * 15, 0, 512);
 #endif