0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 {
0013 struct rs_codec *rs = rsc->codec;
0014 int deg_lambda, el, deg_omega;
0015 int i, j, r, k, pad;
0016 int nn = rs->nn;
0017 int nroots = rs->nroots;
0018 int fcr = rs->fcr;
0019 int prim = rs->prim;
0020 int iprim = rs->iprim;
0021 uint16_t *alpha_to = rs->alpha_to;
0022 uint16_t *index_of = rs->index_of;
0023 uint16_t u, q, tmp, num1, num2, den, discr_r, syn_error;
0024 int count = 0;
0025 int num_corrected;
0026 uint16_t msk = (uint16_t) rs->nn;
0027
0028
0029
0030
0031
0032 uint16_t *lambda = rsc->buffers + RS_DECODE_LAMBDA * (nroots + 1);
0033 uint16_t *syn = rsc->buffers + RS_DECODE_SYN * (nroots + 1);
0034 uint16_t *b = rsc->buffers + RS_DECODE_B * (nroots + 1);
0035 uint16_t *t = rsc->buffers + RS_DECODE_T * (nroots + 1);
0036 uint16_t *omega = rsc->buffers + RS_DECODE_OMEGA * (nroots + 1);
0037 uint16_t *root = rsc->buffers + RS_DECODE_ROOT * (nroots + 1);
0038 uint16_t *reg = rsc->buffers + RS_DECODE_REG * (nroots + 1);
0039 uint16_t *loc = rsc->buffers + RS_DECODE_LOC * (nroots + 1);
0040
0041
0042 pad = nn - nroots - len;
0043 BUG_ON(pad < 0 || pad >= nn - nroots);
0044
0045
0046 if (s != NULL) {
0047 for (i = 0; i < nroots; i++) {
0048
0049
0050
0051 if (s[i] != nn)
0052 goto decode;
0053 }
0054
0055
0056 return 0;
0057 }
0058
0059
0060
0061 for (i = 0; i < nroots; i++)
0062 syn[i] = (((uint16_t) data[0]) ^ invmsk) & msk;
0063
0064 for (j = 1; j < len; j++) {
0065 for (i = 0; i < nroots; i++) {
0066 if (syn[i] == 0) {
0067 syn[i] = (((uint16_t) data[j]) ^
0068 invmsk) & msk;
0069 } else {
0070 syn[i] = ((((uint16_t) data[j]) ^
0071 invmsk) & msk) ^
0072 alpha_to[rs_modnn(rs, index_of[syn[i]] +
0073 (fcr + i) * prim)];
0074 }
0075 }
0076 }
0077
0078 for (j = 0; j < nroots; j++) {
0079 for (i = 0; i < nroots; i++) {
0080 if (syn[i] == 0) {
0081 syn[i] = ((uint16_t) par[j]) & msk;
0082 } else {
0083 syn[i] = (((uint16_t) par[j]) & msk) ^
0084 alpha_to[rs_modnn(rs, index_of[syn[i]] +
0085 (fcr+i)*prim)];
0086 }
0087 }
0088 }
0089 s = syn;
0090
0091
0092 syn_error = 0;
0093 for (i = 0; i < nroots; i++) {
0094 syn_error |= s[i];
0095 s[i] = index_of[s[i]];
0096 }
0097
0098 if (!syn_error) {
0099
0100
0101
0102 return 0;
0103 }
0104
0105 decode:
0106 memset(&lambda[1], 0, nroots * sizeof(lambda[0]));
0107 lambda[0] = 1;
0108
0109 if (no_eras > 0) {
0110
0111 lambda[1] = alpha_to[rs_modnn(rs,
0112 prim * (nn - 1 - (eras_pos[0] + pad)))];
0113 for (i = 1; i < no_eras; i++) {
0114 u = rs_modnn(rs, prim * (nn - 1 - (eras_pos[i] + pad)));
0115 for (j = i + 1; j > 0; j--) {
0116 tmp = index_of[lambda[j - 1]];
0117 if (tmp != nn) {
0118 lambda[j] ^=
0119 alpha_to[rs_modnn(rs, u + tmp)];
0120 }
0121 }
0122 }
0123 }
0124
0125 for (i = 0; i < nroots + 1; i++)
0126 b[i] = index_of[lambda[i]];
0127
0128
0129
0130
0131
0132 r = no_eras;
0133 el = no_eras;
0134 while (++r <= nroots) {
0135
0136 discr_r = 0;
0137 for (i = 0; i < r; i++) {
0138 if ((lambda[i] != 0) && (s[r - i - 1] != nn)) {
0139 discr_r ^=
0140 alpha_to[rs_modnn(rs,
0141 index_of[lambda[i]] +
0142 s[r - i - 1])];
0143 }
0144 }
0145 discr_r = index_of[discr_r];
0146 if (discr_r == nn) {
0147
0148 memmove (&b[1], b, nroots * sizeof (b[0]));
0149 b[0] = nn;
0150 } else {
0151
0152 t[0] = lambda[0];
0153 for (i = 0; i < nroots; i++) {
0154 if (b[i] != nn) {
0155 t[i + 1] = lambda[i + 1] ^
0156 alpha_to[rs_modnn(rs, discr_r +
0157 b[i])];
0158 } else
0159 t[i + 1] = lambda[i + 1];
0160 }
0161 if (2 * el <= r + no_eras - 1) {
0162 el = r + no_eras - el;
0163
0164
0165
0166
0167 for (i = 0; i <= nroots; i++) {
0168 b[i] = (lambda[i] == 0) ? nn :
0169 rs_modnn(rs, index_of[lambda[i]]
0170 - discr_r + nn);
0171 }
0172 } else {
0173
0174 memmove(&b[1], b, nroots * sizeof(b[0]));
0175 b[0] = nn;
0176 }
0177 memcpy(lambda, t, (nroots + 1) * sizeof(t[0]));
0178 }
0179 }
0180
0181
0182 deg_lambda = 0;
0183 for (i = 0; i < nroots + 1; i++) {
0184 lambda[i] = index_of[lambda[i]];
0185 if (lambda[i] != nn)
0186 deg_lambda = i;
0187 }
0188
0189 if (deg_lambda == 0) {
0190
0191
0192
0193
0194 return -EBADMSG;
0195 }
0196
0197
0198 memcpy(®[1], &lambda[1], nroots * sizeof(reg[0]));
0199 count = 0;
0200 for (i = 1, k = iprim - 1; i <= nn; i++, k = rs_modnn(rs, k + iprim)) {
0201 q = 1;
0202 for (j = deg_lambda; j > 0; j--) {
0203 if (reg[j] != nn) {
0204 reg[j] = rs_modnn(rs, reg[j] + j);
0205 q ^= alpha_to[reg[j]];
0206 }
0207 }
0208 if (q != 0)
0209 continue;
0210
0211 if (k < pad) {
0212
0213 return -EBADMSG;
0214 }
0215
0216
0217 root[count] = i;
0218 loc[count] = k;
0219
0220
0221
0222 if (++count == deg_lambda)
0223 break;
0224 }
0225 if (deg_lambda != count) {
0226
0227
0228
0229
0230 return -EBADMSG;
0231 }
0232
0233
0234
0235
0236 deg_omega = deg_lambda - 1;
0237 for (i = 0; i <= deg_omega; i++) {
0238 tmp = 0;
0239 for (j = i; j >= 0; j--) {
0240 if ((s[i - j] != nn) && (lambda[j] != nn))
0241 tmp ^=
0242 alpha_to[rs_modnn(rs, s[i - j] + lambda[j])];
0243 }
0244 omega[i] = index_of[tmp];
0245 }
0246
0247
0248
0249
0250
0251
0252 num_corrected = 0;
0253 for (j = count - 1; j >= 0; j--) {
0254 num1 = 0;
0255 for (i = deg_omega; i >= 0; i--) {
0256 if (omega[i] != nn)
0257 num1 ^= alpha_to[rs_modnn(rs, omega[i] +
0258 i * root[j])];
0259 }
0260
0261 if (num1 == 0) {
0262
0263 b[j] = 0;
0264 continue;
0265 }
0266
0267 num2 = alpha_to[rs_modnn(rs, root[j] * (fcr - 1) + nn)];
0268 den = 0;
0269
0270
0271
0272 for (i = min(deg_lambda, nroots - 1) & ~1; i >= 0; i -= 2) {
0273 if (lambda[i + 1] != nn) {
0274 den ^= alpha_to[rs_modnn(rs, lambda[i + 1] +
0275 i * root[j])];
0276 }
0277 }
0278
0279 b[j] = alpha_to[rs_modnn(rs, index_of[num1] +
0280 index_of[num2] +
0281 nn - index_of[den])];
0282 num_corrected++;
0283 }
0284
0285
0286
0287
0288
0289 for (i = 0; i < nroots; i++) {
0290 tmp = 0;
0291 for (j = 0; j < count; j++) {
0292 if (b[j] == 0)
0293 continue;
0294
0295 k = (fcr + i) * prim * (nn-loc[j]-1);
0296 tmp ^= alpha_to[rs_modnn(rs, index_of[b[j]] + k)];
0297 }
0298
0299 if (tmp != alpha_to[s[i]])
0300 return -EBADMSG;
0301 }
0302
0303
0304
0305
0306
0307 if (corr && eras_pos) {
0308 j = 0;
0309 for (i = 0; i < count; i++) {
0310 if (b[i]) {
0311 corr[j] = b[i];
0312 eras_pos[j++] = loc[i] - pad;
0313 }
0314 }
0315 } else if (data && par) {
0316
0317 for (i = 0; i < count; i++) {
0318 if (loc[i] < (nn - nroots))
0319 data[loc[i] - pad] ^= b[i];
0320 else
0321 par[loc[i] - pad - len] ^= b[i];
0322 }
0323 }
0324
0325 return num_corrected;
0326 }