diff --git a/ChangeLog b/ChangeLog index d0c959ae3..eeacee49e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,26 @@ +2012-01-24 Vladimir Serbinenko + + 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 Eliminate fixed limit on reed solomon decoder length. diff --git a/grub-core/lib/reed_solomon.c b/grub-core/lib/reed_solomon.c index 0257342d0..704ebd3f2 100644 --- a/grub-core/lib/reed_solomon.c +++ b/grub-core/lib/reed_solomon.c @@ -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