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.
This commit is contained in:
parent
2e13ede59e
commit
bb26e4ff16
2 changed files with 87 additions and 173 deletions
23
ChangeLog
23
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>
|
2012-01-24 Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
|
||||||
Eliminate fixed limit on reed solomon decoder length.
|
Eliminate fixed limit on reed solomon decoder length.
|
||||||
|
|
|
@ -41,6 +41,9 @@ typedef unsigned char grub_uint8_t;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define SECTOR_SIZE 512
|
||||||
|
#define MAX_BLOCK_SIZE (200 * SECTOR_SIZE)
|
||||||
|
|
||||||
#ifdef STANDALONE
|
#ifdef STANDALONE
|
||||||
#ifdef TEST
|
#ifdef TEST
|
||||||
typedef unsigned int grub_size_t;
|
typedef unsigned int grub_size_t;
|
||||||
|
@ -60,19 +63,29 @@ typedef grub_uint8_t gf_single_t;
|
||||||
#if defined (STANDALONE) && !defined (TEST)
|
#if defined (STANDALONE) && !defined (TEST)
|
||||||
static gf_single_t * const gf_powx __attribute__ ((section(".text"))) = (void *) 0x100000;
|
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 gf_single_t * const gf_powx_inv __attribute__ ((section(".text"))) = (void *) 0x100200;
|
||||||
|
static int *const chosenstat __attribute__ ((section(".text"))) = (void *) 0x100300;
|
||||||
static char *scratch __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
|
#else
|
||||||
#if defined (STANDALONE)
|
|
||||||
static char *scratch;
|
|
||||||
#endif
|
|
||||||
static gf_single_t gf_powx[255 * 2];
|
static gf_single_t gf_powx[255 * 2];
|
||||||
static gf_single_t gf_powx_inv[256];
|
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
|
#endif
|
||||||
|
|
||||||
#define SECTOR_SIZE 512
|
|
||||||
#define MAX_BLOCK_SIZE (200 * SECTOR_SIZE)
|
|
||||||
|
|
||||||
static gf_single_t
|
static gf_single_t
|
||||||
gf_mul (gf_single_t a, gf_single_t b)
|
gf_mul (gf_single_t a, gf_single_t b)
|
||||||
{
|
{
|
||||||
|
@ -107,14 +120,11 @@ init_powx (void)
|
||||||
}
|
}
|
||||||
|
|
||||||
static gf_single_t
|
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;
|
int i;
|
||||||
gf_single_t s = 0;
|
gf_single_t s = 0;
|
||||||
int log_xn = 0, log_x;
|
int log_xn = 0;
|
||||||
if (x == 0)
|
|
||||||
return pol[0];
|
|
||||||
log_x = gf_powx_inv[x];
|
|
||||||
for (i = degree; i >= 0; i--)
|
for (i = degree; i >= 0; i--)
|
||||||
{
|
{
|
||||||
if (pol[i])
|
if (pol[i])
|
||||||
|
@ -164,26 +174,6 @@ rs_encode (gf_single_t *data, grub_size_t s, grub_size_t rs)
|
||||||
}
|
}
|
||||||
#endif
|
#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
|
static void
|
||||||
gauss_eliminate (gf_single_t *eq, int n, int m, int *chosen)
|
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
|
static void
|
||||||
gauss_solve (gf_single_t *eq, int n, int m, gf_single_t *sol)
|
gauss_solve (gf_single_t *eq, int n, int m, gf_single_t *sol)
|
||||||
{
|
{
|
||||||
int *chosen;
|
|
||||||
int i, j;
|
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++)
|
for (i = 0; i < n; i++)
|
||||||
chosen[i] = -1;
|
chosenstat[i] = -1;
|
||||||
for (i = 0; i < m; i++)
|
for (i = 0; i < m; i++)
|
||||||
sol[i] = 0;
|
sol[i] = 0;
|
||||||
gauss_eliminate (eq, n, m, chosen);
|
gauss_eliminate (eq, n, m, chosenstat);
|
||||||
for (i = n - 1; i >= 0; i--)
|
for (i = n - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
gf_single_t s = 0;
|
gf_single_t s = 0;
|
||||||
if (chosen[i] == -1)
|
if (chosenstat[i] == -1)
|
||||||
continue;
|
continue;
|
||||||
for (j = 0; j < m; j++)
|
for (j = 0; j < m; j++)
|
||||||
s ^= gf_mul (eq[i * (m + 1) + j], sol[j]);
|
s ^= gf_mul (eq[i * (m + 1) + j], sol[j]);
|
||||||
s ^= eq[i * (m + 1) + m];
|
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
|
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;
|
grub_size_t rs2 = rs / 2;
|
||||||
gf_single_t *sigma;
|
|
||||||
gf_single_t *errpot;
|
|
||||||
int *errpos;
|
|
||||||
gf_single_t *sy;
|
|
||||||
int errnum = 0;
|
int errnum = 0;
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
#ifndef STANDALONE
|
for (i = 0; i < (int) rs; i++)
|
||||||
sigma = xmalloc (rs2 * sizeof (gf_single_t));
|
sy[i] = pol_evaluate (mm, s + rs - 1, i);
|
||||||
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++)
|
for (i = 0; i < (int) rs; i++)
|
||||||
if (sy[i] != 0)
|
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. */
|
/* No error detected. */
|
||||||
if (i == (int) rs)
|
if (i == (int) rs)
|
||||||
{
|
return;
|
||||||
#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;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
{
|
||||||
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 (i = 0; i < (int) rs2; i++)
|
||||||
for (j = 0; j < (int) rs2 + 1; j++)
|
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++)
|
for (i = 0; i < (int) rs2; i++)
|
||||||
sigma[i] = 0;
|
sigma[i] = 0;
|
||||||
|
|
||||||
gauss_solve (eq, rs2, rs2, sigma);
|
gauss_solve (eqstat, rs2, rs2, sigma);
|
||||||
|
|
||||||
#ifndef STANDALONE
|
|
||||||
free (eq);
|
|
||||||
#else
|
|
||||||
scratch -= rs2 * (rs2 + 1) * sizeof (gf_single_t);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
for (i = 0; i < (int) (rs + s); i++)
|
||||||
gf_single_t xn = 1, yn = 1;
|
if (pol_evaluate (sigma, rs2 - 1, 255 - i) == gf_powx[i])
|
||||||
for (i = 0; i < (int) (rs + s); i++)
|
|
||||||
{
|
{
|
||||||
gf_single_t ev = (gf_mul (pol_evaluate (sigma, rs2 - 1, xn), xn) ^ 1);
|
errpot[errnum] = gf_powx[i];
|
||||||
if (ev == 0)
|
errpos[errnum++] = s + rs - i - 1;
|
||||||
{
|
|
||||||
errpot[errnum] = yn;
|
|
||||||
errpos[errnum++] = s + rs - i - 1;
|
|
||||||
}
|
|
||||||
yn = gf_mul (yn, 2);
|
|
||||||
xn = gf_mul (xn, GF_INVERT2);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
{
|
{
|
||||||
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++)
|
for (j = 0; j < errnum; j++)
|
||||||
eq[j] = 1;
|
eqstat[j] = 1;
|
||||||
eq[errnum] = sy[0];
|
eqstat[errnum] = sy[0];
|
||||||
for (i = 1; i < (int) rs; i++)
|
for (i = 1; i < (int) rs; i++)
|
||||||
{
|
{
|
||||||
for (j = 0; j < (int) errnum; j++)
|
for (j = 0; j < (int) errnum; j++)
|
||||||
eq[(errnum + 1) * i + j] = gf_mul (errpot[j],
|
eqstat[(errnum + 1) * i + j] = gf_mul (errpot[j],
|
||||||
eq[(errnum + 1) * (i - 1) + j]);
|
eqstat[(errnum + 1) * (i - 1)
|
||||||
eq[(errnum + 1) * i + errnum] = sy[i];
|
+ 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++)
|
for (i = 0; i < (int) errnum; i++)
|
||||||
m[errpos[i]] ^= errvals[i];
|
mm[errpos[i]] ^= errvals[i];
|
||||||
#ifndef STANDALONE
|
|
||||||
free (eq);
|
|
||||||
free (errvals);
|
|
||||||
#else
|
|
||||||
scratch -= rs * (errnum + 1) * sizeof (gf_single_t);
|
|
||||||
scratch -= errnum * sizeof (int);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
#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
|
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 ds = (s + SECTOR_SIZE - 1 - i) / SECTOR_SIZE;
|
||||||
grub_size_t rr = (rs + SECTOR_SIZE - 1 - i) / SECTOR_SIZE;
|
grub_size_t rr = (rs + SECTOR_SIZE - 1 - i) / SECTOR_SIZE;
|
||||||
gf_single_t *m;
|
|
||||||
|
|
||||||
/* Nothing to do. */
|
/* Nothing to do. */
|
||||||
if (!ds || !rr)
|
if (!ds || !rr)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
#ifndef STANDALONE
|
|
||||||
m = xmalloc (ds + rr);
|
|
||||||
#else
|
|
||||||
m = (gf_single_t *) scratch;
|
|
||||||
scratch += ds + rr;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (j = 0; j < (int) ds; j++)
|
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++)
|
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++)
|
for (j = 0; j < (int) ds; j++)
|
||||||
ptr[SECTOR_SIZE * j + i] = m[j];
|
ptr[SECTOR_SIZE * j + i] = mstat[j];
|
||||||
|
|
||||||
#ifndef STANDALONE
|
|
||||||
free (m);
|
|
||||||
#else
|
|
||||||
scratch -= ds + rr;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -490,7 +370,9 @@ grub_reed_solomon_add_redundancy (void *buffer, grub_size_t data_size,
|
||||||
rs -= crs;
|
rs -= crs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef TEST
|
||||||
assert (grub_memcmp (tmp, buffer, data_size) == 0);
|
assert (grub_memcmp (tmp, buffer, data_size) == 0);
|
||||||
|
#endif
|
||||||
free (tmp);
|
free (tmp);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -538,14 +420,11 @@ main (int argc, char **argv)
|
||||||
grub_memset (gf_powx, 0xee, sizeof (gf_powx));
|
grub_memset (gf_powx, 0xee, sizeof (gf_powx));
|
||||||
grub_memset (gf_powx_inv, 0xdd, sizeof (gf_powx_inv));
|
grub_memset (gf_powx_inv, 0xdd, sizeof (gf_powx_inv));
|
||||||
|
|
||||||
#ifdef STANDALONE
|
|
||||||
scratch = xmalloc (1048576);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef STANDALONE
|
#ifndef STANDALONE
|
||||||
init_powx ();
|
init_powx ();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef STANDALONE
|
||||||
in = fopen ("tst.bin", "rb");
|
in = fopen ("tst.bin", "rb");
|
||||||
if (!in)
|
if (!in)
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -562,6 +441,18 @@ main (int argc, char **argv)
|
||||||
out = fopen ("tst_rs.bin", "wb");
|
out = fopen ("tst_rs.bin", "wb");
|
||||||
fwrite (buf, 1, s + rs, out);
|
fwrite (buf, 1, s + rs, out);
|
||||||
fclose (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
|
#if 1
|
||||||
grub_memset (buf + 512 * 15, 0, 512);
|
grub_memset (buf + 512 * 15, 0, 512);
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue