2026-04-02 16:00:27 +02:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
2026-04-02 16:25:49 +02:00
|
|
|
// Copyright (C) 2013 Andrea Mazzoleni
|
2013-09-07 19:43:33 +02:00
|
|
|
|
|
|
|
|
#include <stdio.h>
|
2013-12-27 13:56:56 +01:00
|
|
|
#include <stdint.h>
|
2013-09-07 19:43:33 +02:00
|
|
|
|
2026-07-29 12:47:13 +02:00
|
|
|
/*
|
|
|
|
|
* Galois field reduction polynomials.
|
|
|
|
|
*
|
|
|
|
|
* RAID_POLY_RAID - Standard RAID polynomial 0x1d (x^8 + x^4 + x^3 + x^2 + 1).
|
2026-08-23 20:26:14 +02:00
|
|
|
* RAID_POLY_AES - AES polynomial 0x1b (x^8 + x^4 + x^3 + x + 1), using generator g=3.
|
2026-07-29 12:47:13 +02:00
|
|
|
*/
|
|
|
|
|
#define RAID_POLY_RAID 0x1d
|
|
|
|
|
#define RAID_POLY_AES 0x1b
|
|
|
|
|
|
2013-10-25 18:03:05 +02:00
|
|
|
/**
|
2014-02-10 20:38:31 +01:00
|
|
|
* Multiplication a*b in GF(2^8).
|
2013-10-25 18:03:05 +02:00
|
|
|
*/
|
2026-07-29 12:47:13 +02:00
|
|
|
static uint8_t raid_gfmul(uint8_t poly, uint8_t a, uint8_t b)
|
2013-09-07 19:43:33 +02:00
|
|
|
{
|
2013-12-27 13:56:56 +01:00
|
|
|
uint8_t v;
|
2013-09-07 19:43:33 +02:00
|
|
|
|
|
|
|
|
v = 0;
|
2014-11-12 20:41:00 +01:00
|
|
|
while (b) {
|
2013-09-07 19:43:33 +02:00
|
|
|
if ((b & 1) != 0)
|
|
|
|
|
v ^= a;
|
|
|
|
|
|
|
|
|
|
if ((a & 0x80) != 0) {
|
|
|
|
|
a <<= 1;
|
2026-05-17 23:35:29 +02:00
|
|
|
a ^= poly;
|
2013-09-07 19:43:33 +02:00
|
|
|
} else {
|
|
|
|
|
a <<= 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
b >>= 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return v;
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-19 17:59:02 +02:00
|
|
|
/**
|
|
|
|
|
* Setup the GFNI affine matrix for multiplication by a constant.
|
|
|
|
|
*
|
|
|
|
|
* VGF2P8MULB is fixed to the AES polynomial 0x11b, while RAID parity is
|
|
|
|
|
* defined over GF(2^8) modulo 0x11d. VGF2P8AFFINEQB can implement the
|
|
|
|
|
* multiplication because multiplication by a constant is GF(2)-linear.
|
|
|
|
|
*
|
|
|
|
|
* VGF2P8AFFINEQB stores the row producing output bit j in byte 7-j.
|
|
|
|
|
* Within each row, bit k selects input bit k.
|
|
|
|
|
*/
|
|
|
|
|
static void set_affine(uint8_t poly, uint8_t c, uint8_t *matrix)
|
|
|
|
|
{
|
|
|
|
|
int j, k;
|
|
|
|
|
|
|
|
|
|
for (j = 0; j < 8; ++j) {
|
|
|
|
|
uint8_t row = 0;
|
|
|
|
|
|
|
|
|
|
for (k = 0; k < 8; ++k) {
|
|
|
|
|
uint8_t v = raid_gfmul(poly, c, (uint8_t)(1U << k));
|
|
|
|
|
|
|
|
|
|
if ((v & (1U << j)) != 0)
|
|
|
|
|
row |= (uint8_t)(1U << k);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
matrix[7 - j] = row;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-25 18:03:05 +02:00
|
|
|
/**
|
2014-02-10 20:38:31 +01:00
|
|
|
* Inversion (1/a) in GF(2^8).
|
2013-10-25 18:03:05 +02:00
|
|
|
*/
|
2026-07-29 12:47:13 +02:00
|
|
|
uint8_t raid_gfinv[256];
|
2013-10-22 23:40:05 +02:00
|
|
|
|
|
|
|
|
/**
|
2014-02-10 20:38:31 +01:00
|
|
|
* Number of parities.
|
|
|
|
|
* This is the number of rows of the generator matrix.
|
2013-10-22 23:40:05 +02:00
|
|
|
*/
|
2013-10-25 18:03:05 +02:00
|
|
|
#define PARITY 6
|
2013-10-22 23:40:05 +02:00
|
|
|
|
2013-10-25 18:03:05 +02:00
|
|
|
/**
|
|
|
|
|
* Number of disks.
|
2014-02-10 20:38:31 +01:00
|
|
|
* This is the number of columns of the generator matrix.
|
2013-10-25 18:03:05 +02:00
|
|
|
*/
|
2014-11-12 20:41:00 +01:00
|
|
|
#define DISK (257 - PARITY)
|
2013-10-22 23:40:05 +02:00
|
|
|
|
|
|
|
|
/**
|
2013-11-02 15:55:57 +01:00
|
|
|
* Setup the Cauchy matrix used to generate the parity.
|
2013-10-22 23:40:05 +02:00
|
|
|
*/
|
2026-08-19 01:36:18 +02:00
|
|
|
static void set_cauchy(uint8_t poly, uint8_t generator, uint8_t *matrix)
|
2013-10-22 23:40:05 +02:00
|
|
|
{
|
|
|
|
|
int i, j;
|
2013-12-27 13:56:56 +01:00
|
|
|
uint8_t inv_x, y;
|
2013-10-25 18:03:05 +02:00
|
|
|
|
|
|
|
|
/*
|
2026-04-15 10:47:29 +02:00
|
|
|
* The first row of the generator matrix is formed by all 1s.
|
2013-10-25 18:03:05 +02:00
|
|
|
*
|
2014-02-10 20:38:31 +01:00
|
|
|
* The generator matrix is an Extended Cauchy matrix built from
|
2026-04-15 10:47:29 +02:00
|
|
|
* a Cauchy matrix by adding a row at the top of all 1s.
|
2014-02-10 20:38:31 +01:00
|
|
|
*
|
|
|
|
|
* Extending a Cauchy matrix in this way maintains the MDS property
|
|
|
|
|
* of the matrix.
|
|
|
|
|
*
|
|
|
|
|
* For example, considering a generator matrix of 4x6 we have now:
|
|
|
|
|
*
|
|
|
|
|
* 1 1 1 1 1 1
|
|
|
|
|
* - - - - - -
|
|
|
|
|
* - - - - - -
|
|
|
|
|
* - - - - - -
|
2013-10-25 18:03:05 +02:00
|
|
|
*/
|
2013-12-28 12:04:16 +01:00
|
|
|
for (i = 0; i < DISK; ++i)
|
2014-11-12 20:41:00 +01:00
|
|
|
matrix[0 * DISK + i] = 1;
|
2013-10-22 23:40:05 +02:00
|
|
|
|
2013-10-25 18:03:05 +02:00
|
|
|
/*
|
2026-08-19 01:36:18 +02:00
|
|
|
* The second row is formed with powers g^i, and it's the first
|
2014-02-10 20:38:31 +01:00
|
|
|
* row of the Cauchy matrix.
|
2013-10-25 18:03:05 +02:00
|
|
|
*
|
2014-02-10 20:38:31 +01:00
|
|
|
* Each element of the Cauchy matrix is in the form 1/(x_i + y_j)
|
|
|
|
|
* where all x_i and y_j must be different for any i and j.
|
2013-10-25 18:03:05 +02:00
|
|
|
*
|
2026-08-19 01:36:18 +02:00
|
|
|
* For the first row with j=0, we choose x_i = g^-i and y_0 = 0
|
2014-02-10 20:38:31 +01:00
|
|
|
* and we obtain a first row formed as:
|
2013-10-25 18:03:05 +02:00
|
|
|
*
|
2026-08-19 01:36:18 +02:00
|
|
|
* 1/(x_i + y_0) = 1/(g^-i + 0) = g^i
|
2013-10-25 18:03:05 +02:00
|
|
|
*
|
2026-08-19 01:36:18 +02:00
|
|
|
* with g^-i != 0 for any i
|
|
|
|
|
*
|
|
|
|
|
* The numerical examples below use RAID_MODE_CAUCHY_RAID,
|
|
|
|
|
* with polynomial 0x11d and generator g=2.
|
2014-02-10 20:38:31 +01:00
|
|
|
*
|
|
|
|
|
* In the example we get:
|
|
|
|
|
*
|
|
|
|
|
* x_0 = 1
|
|
|
|
|
* x_1 = 142
|
|
|
|
|
* x_2 = 71
|
|
|
|
|
* x_3 = 173
|
|
|
|
|
* x_4 = 216
|
|
|
|
|
* x_5 = 108
|
|
|
|
|
* y_0 = 0
|
|
|
|
|
*
|
|
|
|
|
* with the matrix:
|
|
|
|
|
*
|
|
|
|
|
* 1 1 1 1 1 1
|
|
|
|
|
* 1 2 4 8 16 32
|
|
|
|
|
* - - - - - -
|
|
|
|
|
* - - - - - -
|
2013-10-25 18:03:05 +02:00
|
|
|
*/
|
|
|
|
|
inv_x = 1;
|
2013-12-28 12:04:16 +01:00
|
|
|
for (i = 0; i < DISK; ++i) {
|
2014-11-12 20:41:00 +01:00
|
|
|
matrix[1 * DISK + i] = inv_x;
|
2026-08-19 01:36:18 +02:00
|
|
|
inv_x = raid_gfmul(poly, generator, inv_x);
|
2013-10-22 23:40:05 +02:00
|
|
|
}
|
|
|
|
|
|
2013-10-25 18:03:05 +02:00
|
|
|
/*
|
2026-04-15 10:47:29 +02:00
|
|
|
* The rest of the Cauchy matrix is formed by choosing for each row j
|
2026-08-19 01:36:18 +02:00
|
|
|
* a new y_j = g^j and reusing the x_i already assigned in the first
|
2014-02-10 20:38:31 +01:00
|
|
|
* row obtaining :
|
|
|
|
|
*
|
2026-08-19 01:36:18 +02:00
|
|
|
* 1/(x_i + y_j) = 1/(g^-i + g^j)
|
2014-02-10 20:38:31 +01:00
|
|
|
*
|
2026-08-19 01:36:18 +02:00
|
|
|
* with g^-i + g^j != 0, because g is primitive and has
|
|
|
|
|
* multiplicative order 255, with i + j < 255 for all supported entries.
|
2013-10-25 18:03:05 +02:00
|
|
|
*
|
2014-02-10 20:38:31 +01:00
|
|
|
* In the example we get:
|
2013-10-25 18:03:05 +02:00
|
|
|
*
|
2014-02-10 20:38:31 +01:00
|
|
|
* y_1 = 2
|
|
|
|
|
* y_2 = 4
|
2013-10-25 18:03:05 +02:00
|
|
|
*
|
2014-02-10 20:38:31 +01:00
|
|
|
* with the matrix:
|
|
|
|
|
*
|
|
|
|
|
* 1 1 1 1 1 1
|
|
|
|
|
* 1 2 4 8 16 32
|
|
|
|
|
* 244 83 78 183 118 47
|
|
|
|
|
* 167 39 213 59 153 82
|
2013-10-25 18:03:05 +02:00
|
|
|
*/
|
2026-08-19 01:36:18 +02:00
|
|
|
y = generator;
|
2014-11-12 20:41:00 +01:00
|
|
|
for (j = 0; j < PARITY - 2; ++j) {
|
2013-10-25 18:03:05 +02:00
|
|
|
inv_x = 1;
|
2013-12-28 12:04:16 +01:00
|
|
|
for (i = 0; i < DISK; ++i) {
|
2026-07-29 12:47:13 +02:00
|
|
|
uint8_t x = raid_gfinv[inv_x];
|
2015-03-12 18:53:36 +01:00
|
|
|
|
2026-07-29 12:47:13 +02:00
|
|
|
matrix[(j + 2) * DISK + i] = raid_gfinv[y ^ x];
|
2026-08-19 01:36:18 +02:00
|
|
|
inv_x = raid_gfmul(poly, generator, inv_x);
|
2013-10-22 23:40:05 +02:00
|
|
|
}
|
|
|
|
|
|
2026-08-19 01:36:18 +02:00
|
|
|
y = raid_gfmul(poly, generator, y);
|
2013-10-25 18:03:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
2026-04-15 10:47:29 +02:00
|
|
|
* Finally we adjust the matrix multiplying each row by
|
2013-10-25 18:03:05 +02:00
|
|
|
* the inverse of the first element in the row.
|
|
|
|
|
*
|
2014-02-10 20:38:31 +01:00
|
|
|
* Also this operation maintains the MDS property of the matrix.
|
|
|
|
|
*
|
|
|
|
|
* Resulting in:
|
|
|
|
|
*
|
|
|
|
|
* 1 1 1 1 1 1
|
|
|
|
|
* 1 2 4 8 16 32
|
|
|
|
|
* 1 245 210 196 154 113
|
2026-08-19 01:36:18 +02:00
|
|
|
* 1 187 166 215 199 7
|
2013-10-25 18:03:05 +02:00
|
|
|
*/
|
2014-11-12 20:41:00 +01:00
|
|
|
for (j = 0; j < PARITY - 2; ++j) {
|
2026-07-29 12:47:13 +02:00
|
|
|
uint8_t f = raid_gfinv[matrix[(j + 2) * DISK]];
|
2013-10-25 18:03:05 +02:00
|
|
|
|
2013-12-28 12:04:16 +01:00
|
|
|
for (i = 0; i < DISK; ++i)
|
2026-07-29 12:47:13 +02:00
|
|
|
matrix[(j + 2) * DISK + i] = raid_gfmul(poly, matrix[(j + 2) * DISK + i], f);
|
2013-10-22 23:40:05 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-11-04 23:47:49 +01:00
|
|
|
/**
|
|
|
|
|
* Setup the Power matrix used to generate the parity.
|
|
|
|
|
*/
|
2026-05-17 23:35:29 +02:00
|
|
|
static void set_power(uint8_t poly, uint8_t *matrix)
|
2013-11-04 23:47:49 +01:00
|
|
|
{
|
|
|
|
|
unsigned i;
|
2013-12-27 13:56:56 +01:00
|
|
|
uint8_t v;
|
2026-05-17 23:35:29 +02:00
|
|
|
uint8_t div_by_2 = (((poly) >> 1) | 0x80);
|
2013-11-04 23:47:49 +01:00
|
|
|
|
|
|
|
|
v = 1;
|
2013-12-28 12:04:16 +01:00
|
|
|
for (i = 0; i < DISK; ++i)
|
2014-11-12 20:41:00 +01:00
|
|
|
matrix[0 * DISK + i] = v;
|
2013-11-04 23:47:49 +01:00
|
|
|
|
|
|
|
|
v = 1;
|
2013-12-28 12:04:16 +01:00
|
|
|
for (i = 0; i < DISK; ++i) {
|
2014-11-12 20:41:00 +01:00
|
|
|
matrix[1 * DISK + i] = v;
|
2026-07-29 12:47:13 +02:00
|
|
|
v = raid_gfmul(poly, 2, v);
|
2013-11-04 23:47:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
v = 1;
|
2013-12-28 12:04:16 +01:00
|
|
|
for (i = 0; i < DISK; ++i) {
|
2014-11-12 20:41:00 +01:00
|
|
|
matrix[2 * DISK + i] = v;
|
2026-07-29 12:47:13 +02:00
|
|
|
v = raid_gfmul(poly, div_by_2, v);
|
2013-11-04 23:47:49 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-19 01:36:18 +02:00
|
|
|
void tables(uint8_t poly, uint8_t generator, const char *tag)
|
2013-09-07 19:43:33 +02:00
|
|
|
{
|
2013-12-27 13:56:56 +01:00
|
|
|
uint8_t v;
|
2013-10-22 23:40:05 +02:00
|
|
|
int i, j, k, p;
|
2013-12-27 13:56:56 +01:00
|
|
|
uint8_t matrix[PARITY * 256];
|
2013-10-22 23:40:05 +02:00
|
|
|
|
2013-09-07 19:43:33 +02:00
|
|
|
/* a*b */
|
2026-07-29 12:47:13 +02:00
|
|
|
printf("const uint8_t __aligned(256) raid_gfmul_%s[256][256] =\n", tag);
|
2013-09-07 19:43:33 +02:00
|
|
|
printf("{\n");
|
2013-12-28 12:04:16 +01:00
|
|
|
for (i = 0; i < 256; ++i) {
|
2013-09-07 19:43:33 +02:00
|
|
|
printf("\t{\n");
|
2013-12-28 12:04:16 +01:00
|
|
|
for (j = 0; j < 256; ++j) {
|
2013-09-07 19:43:33 +02:00
|
|
|
if (j % 8 == 0)
|
|
|
|
|
printf("\t\t");
|
2026-07-29 12:47:13 +02:00
|
|
|
v = raid_gfmul(poly, i, j);
|
2013-09-09 19:12:33 +02:00
|
|
|
if (v == 1)
|
2026-07-29 12:47:13 +02:00
|
|
|
raid_gfinv[i] = j;
|
2013-09-09 19:12:33 +02:00
|
|
|
printf("0x%02x,", (unsigned)v);
|
2013-09-07 19:43:33 +02:00
|
|
|
if (j % 8 == 7)
|
|
|
|
|
printf("\n");
|
|
|
|
|
else
|
|
|
|
|
printf(" ");
|
|
|
|
|
}
|
|
|
|
|
printf("\t},\n");
|
|
|
|
|
}
|
|
|
|
|
printf("};\n\n");
|
|
|
|
|
|
2026-08-19 17:59:02 +02:00
|
|
|
if (poly == RAID_POLY_RAID) {
|
|
|
|
|
uint8_t affine[8];
|
|
|
|
|
|
|
|
|
|
printf("/**\n");
|
|
|
|
|
printf(" * GFNI affine matrices for multiplication in GF(2^8)/0x11d.\n");
|
|
|
|
|
printf(" *\n");
|
|
|
|
|
printf(" * VGF2P8AFFINEQB consumes one 8x8 matrix per 64-bit lane.\n");
|
|
|
|
|
printf(" * Byte 7-j contains the row producing output bit j, and bit k\n");
|
|
|
|
|
printf(" * of that byte selects input bit k. The instruction uses imm8=0.\n");
|
|
|
|
|
printf(" */\n");
|
|
|
|
|
printf("const uint8_t __aligned(256) raid_gfaffine_raid[256][8] =\n");
|
|
|
|
|
printf("{\n");
|
|
|
|
|
for (i = 0; i < 256; ++i) {
|
|
|
|
|
set_affine(poly, (uint8_t)i, affine);
|
|
|
|
|
printf("\t{ ");
|
|
|
|
|
for (j = 0; j < 8; ++j) {
|
|
|
|
|
printf("0x%02x", (unsigned)affine[j]);
|
|
|
|
|
if (j != 7)
|
|
|
|
|
printf(", ");
|
|
|
|
|
}
|
|
|
|
|
printf(" },\n");
|
|
|
|
|
}
|
|
|
|
|
printf("};\n\n");
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-19 01:36:18 +02:00
|
|
|
/* generator^a */
|
2026-07-29 12:47:13 +02:00
|
|
|
printf("const uint8_t __aligned(256) raid_gfexp_%s[256] =\n", tag);
|
2013-09-07 19:43:33 +02:00
|
|
|
printf("{\n");
|
|
|
|
|
v = 1;
|
2013-12-28 12:04:16 +01:00
|
|
|
for (i = 0; i < 256; ++i) {
|
2013-09-07 19:43:33 +02:00
|
|
|
if (i % 8 == 0)
|
|
|
|
|
printf("\t");
|
|
|
|
|
printf("0x%02x,", v);
|
2026-08-19 01:36:18 +02:00
|
|
|
v = raid_gfmul(poly, v, generator);
|
2013-09-07 19:43:33 +02:00
|
|
|
if (i % 8 == 7)
|
|
|
|
|
printf("\n");
|
|
|
|
|
else
|
|
|
|
|
printf(" ");
|
|
|
|
|
}
|
|
|
|
|
printf("};\n\n");
|
|
|
|
|
|
|
|
|
|
/* 1/a */
|
2026-07-29 12:47:13 +02:00
|
|
|
printf("const uint8_t __aligned(256) raid_gfinv_%s[256] =\n", tag);
|
2013-09-07 19:43:33 +02:00
|
|
|
printf("{\n");
|
2026-04-15 10:47:29 +02:00
|
|
|
printf("\t/* note that the first element is not significant */\n");
|
2013-12-28 12:04:16 +01:00
|
|
|
for (i = 0; i < 256; ++i) {
|
2013-09-07 19:43:33 +02:00
|
|
|
if (i % 8 == 0)
|
|
|
|
|
printf("\t");
|
|
|
|
|
if (i == 0)
|
|
|
|
|
v = 0;
|
|
|
|
|
else
|
2026-07-29 12:47:13 +02:00
|
|
|
v = raid_gfinv[i];
|
2013-09-07 19:43:33 +02:00
|
|
|
printf("0x%02x,", v);
|
|
|
|
|
if (i % 8 == 7)
|
|
|
|
|
printf("\n");
|
|
|
|
|
else
|
|
|
|
|
printf(" ");
|
|
|
|
|
}
|
|
|
|
|
printf("};\n\n");
|
|
|
|
|
|
2013-10-25 18:03:05 +02:00
|
|
|
/* cauchy matrix */
|
2026-08-19 01:36:18 +02:00
|
|
|
set_cauchy(poly, generator, matrix);
|
2013-10-22 23:40:05 +02:00
|
|
|
|
|
|
|
|
printf("/**\n");
|
2013-11-03 10:41:52 +01:00
|
|
|
printf(" * Cauchy matrix used to generate parity.\n");
|
2013-10-25 18:03:05 +02:00
|
|
|
printf(" * This matrix is valid for up to %u parity with %u data disks.\n", PARITY, DISK);
|
2013-10-22 23:40:05 +02:00
|
|
|
printf(" *\n");
|
2013-12-28 12:04:16 +01:00
|
|
|
for (p = 0; p < PARITY; ++p) {
|
2015-03-10 19:05:54 +01:00
|
|
|
printf(" *");
|
2013-12-28 12:04:16 +01:00
|
|
|
for (i = 0; i < DISK; ++i)
|
2015-03-10 19:05:54 +01:00
|
|
|
printf(" %02x", matrix[p * DISK + i]);
|
2013-10-22 23:40:05 +02:00
|
|
|
printf("\n");
|
|
|
|
|
}
|
|
|
|
|
printf(" */\n");
|
2026-07-29 12:47:13 +02:00
|
|
|
printf("const uint8_t __aligned(256) raid_gfcauchy_%s[%u][256] =\n", tag, PARITY);
|
2013-10-22 23:40:05 +02:00
|
|
|
printf("{\n");
|
2013-12-28 12:04:16 +01:00
|
|
|
for (p = 0; p < PARITY; ++p) {
|
2013-10-22 23:40:05 +02:00
|
|
|
printf("\t{\n");
|
2013-12-28 12:04:16 +01:00
|
|
|
for (i = 0; i < DISK; ++i) {
|
2013-10-22 23:40:05 +02:00
|
|
|
if (i % 8 == 0)
|
|
|
|
|
printf("\t\t");
|
2014-11-12 20:41:00 +01:00
|
|
|
printf("0x%02x,", matrix[p * DISK + i]);
|
2015-03-10 19:05:54 +01:00
|
|
|
if (i != DISK - 1) {
|
|
|
|
|
if (i % 8 == 7)
|
|
|
|
|
printf("\n");
|
|
|
|
|
else
|
|
|
|
|
printf(" ");
|
|
|
|
|
}
|
2013-10-22 23:40:05 +02:00
|
|
|
}
|
|
|
|
|
printf("\n\t},\n");
|
|
|
|
|
}
|
|
|
|
|
printf("};\n\n");
|
|
|
|
|
|
2026-08-23 21:55:26 +02:00
|
|
|
if (poly == RAID_POLY_RAID) {
|
|
|
|
|
uint8_t affine[8];
|
|
|
|
|
|
|
|
|
|
printf("#ifdef CONFIG_X86_64\n");
|
|
|
|
|
printf("/**\n");
|
|
|
|
|
printf(" * GFNI affine matrices for the RAID Cauchy coefficients.\n");
|
|
|
|
|
printf(" *\n");
|
|
|
|
|
printf(" * Indexes are [DISK][PARITY - 1][8].\n");
|
|
|
|
|
printf(" * Where DISK is from 0 to %u and PARITY is from 2 to %u.\n", DISK - 1, PARITY);
|
|
|
|
|
printf(" * The last index contains the 8 bytes of the affine matrix.\n");
|
|
|
|
|
printf(" */\n");
|
|
|
|
|
printf("const uint8_t __aligned(256) raid_gfcauchyaffine_raid[%u][%u][8] =\n",
|
|
|
|
|
DISK, PARITY - 1);
|
|
|
|
|
printf("{\n");
|
|
|
|
|
for (i = 0; i < DISK; ++i) {
|
|
|
|
|
printf("\t{\n");
|
|
|
|
|
for (p = 1; p < PARITY; ++p) {
|
|
|
|
|
set_affine(poly, matrix[p * DISK + i], affine);
|
|
|
|
|
|
|
|
|
|
printf("\t\t{ ");
|
|
|
|
|
for (j = 0; j < 8; ++j) {
|
|
|
|
|
printf("0x%02x", (unsigned)affine[j]);
|
|
|
|
|
if (j != 7)
|
|
|
|
|
printf(", ");
|
|
|
|
|
}
|
|
|
|
|
printf(" },\n");
|
|
|
|
|
}
|
|
|
|
|
printf("\t},\n");
|
|
|
|
|
}
|
|
|
|
|
printf("};\n");
|
|
|
|
|
printf("#endif\n\n");
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-20 21:47:31 +02:00
|
|
|
printf("#if defined(CONFIG_X86) || defined(CONFIG_NEON) || defined(CONFIG_NEON32)\n");
|
2013-10-22 23:40:05 +02:00
|
|
|
printf("/**\n");
|
2013-11-03 10:41:52 +01:00
|
|
|
printf(" * PSHUFB tables for the Cauchy matrix.\n");
|
2013-10-22 23:40:05 +02:00
|
|
|
printf(" *\n");
|
2013-10-25 18:03:05 +02:00
|
|
|
printf(" * Indexes are [DISK][PARITY - 2][LH].\n");
|
2026-05-28 23:46:32 +02:00
|
|
|
printf(" * Where DISK is from 0 to %u, PARITY from 1 to %u, LH from 0 to 1.\n", DISK - 1, PARITY);
|
2013-10-22 23:40:05 +02:00
|
|
|
printf(" */\n");
|
2026-07-29 12:47:13 +02:00
|
|
|
printf("const uint8_t __aligned(256) raid_gfcauchypshufb_%s[%u][%u][2][16] =\n", tag, DISK, PARITY - 1);
|
2013-10-22 23:40:05 +02:00
|
|
|
printf("{\n");
|
2013-12-28 12:04:16 +01:00
|
|
|
for (i = 0; i < DISK; ++i) {
|
2013-10-22 23:40:05 +02:00
|
|
|
printf("\t{\n");
|
2026-05-28 23:46:32 +02:00
|
|
|
for (p = 1; p < PARITY; ++p) {
|
2013-10-22 23:40:05 +02:00
|
|
|
printf("\t\t{\n");
|
2013-12-28 12:04:16 +01:00
|
|
|
for (j = 0; j < 2; ++j) {
|
2013-10-22 23:40:05 +02:00
|
|
|
printf("\t\t\t{ ");
|
2013-12-28 12:04:16 +01:00
|
|
|
for (k = 0; k < 16; ++k) {
|
2026-07-29 12:47:13 +02:00
|
|
|
v = raid_gfmul(poly, matrix[p * DISK + i], k);
|
2013-10-22 23:40:05 +02:00
|
|
|
if (j == 1)
|
2026-07-29 12:47:13 +02:00
|
|
|
v = raid_gfmul(poly, v, 16);
|
2013-10-22 23:40:05 +02:00
|
|
|
printf("0x%02x", (unsigned)v);
|
|
|
|
|
if (k != 15)
|
|
|
|
|
printf(", ");
|
|
|
|
|
}
|
|
|
|
|
printf(" },\n");
|
|
|
|
|
}
|
|
|
|
|
printf("\t\t},\n");
|
|
|
|
|
}
|
|
|
|
|
printf("\t},\n");
|
|
|
|
|
}
|
|
|
|
|
printf("};\n");
|
|
|
|
|
printf("#endif\n\n");
|
|
|
|
|
|
2026-08-20 21:47:31 +02:00
|
|
|
printf("#if defined(CONFIG_X86) || defined(CONFIG_NEON) || defined(CONFIG_NEON32)\n");
|
2013-11-03 17:50:09 +01:00
|
|
|
printf("/**\n");
|
|
|
|
|
printf(" * PSHUFB tables for generic multiplication.\n");
|
|
|
|
|
printf(" *\n");
|
2020-05-02 14:21:40 +02:00
|
|
|
printf(" * Indexes are [MULTIPLIER][LH].\n");
|
|
|
|
|
printf(" * Where MULTIPLIER is from 0 to 255, LH from 0 to 1.\n");
|
2013-11-03 17:50:09 +01:00
|
|
|
printf(" */\n");
|
2026-07-29 12:47:13 +02:00
|
|
|
printf("const uint8_t __aligned(256) raid_gfmulpshufb_%s[256][2][16] =\n", tag);
|
2013-11-03 17:50:09 +01:00
|
|
|
printf("{\n");
|
2013-12-28 12:04:16 +01:00
|
|
|
for (i = 0; i < 256; ++i) {
|
2013-11-03 17:50:09 +01:00
|
|
|
printf("\t{\n");
|
2013-12-28 12:04:16 +01:00
|
|
|
for (j = 0; j < 2; ++j) {
|
2013-11-03 17:50:09 +01:00
|
|
|
printf("\t\t{ ");
|
2013-12-28 12:04:16 +01:00
|
|
|
for (k = 0; k < 16; ++k) {
|
2026-07-29 12:47:13 +02:00
|
|
|
v = raid_gfmul(poly, i, k);
|
2013-11-03 17:50:09 +01:00
|
|
|
if (j == 1)
|
2026-07-29 12:47:13 +02:00
|
|
|
v = raid_gfmul(poly, v, 16);
|
2013-11-03 17:50:09 +01:00
|
|
|
printf("0x%02x", (unsigned)v);
|
|
|
|
|
if (k != 15)
|
|
|
|
|
printf(", ");
|
|
|
|
|
}
|
|
|
|
|
printf(" },\n");
|
|
|
|
|
}
|
|
|
|
|
printf("\t},\n");
|
|
|
|
|
}
|
|
|
|
|
printf("};\n");
|
|
|
|
|
printf("#endif\n\n");
|
2026-07-29 12:47:13 +02:00
|
|
|
|
|
|
|
|
if (poly == RAID_POLY_AES)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
/* power matrix */
|
|
|
|
|
set_power(poly, matrix);
|
|
|
|
|
|
|
|
|
|
printf("/**\n");
|
|
|
|
|
printf(" * Power matrix used to generate parity.\n");
|
|
|
|
|
printf(" * This matrix is valid for up to %u parities with %u data disks.\n", 3, DISK);
|
|
|
|
|
printf(" *\n");
|
|
|
|
|
for (p = 0; p < 3; ++p) {
|
|
|
|
|
printf(" *");
|
|
|
|
|
for (i = 0; i < DISK; ++i)
|
|
|
|
|
printf(" %02x", matrix[p * DISK + i]);
|
|
|
|
|
printf("\n");
|
|
|
|
|
}
|
|
|
|
|
printf(" */\n");
|
|
|
|
|
printf("const uint8_t __aligned(256) raid_gfvandermonde_%s[%u][256] =\n", tag, 3);
|
|
|
|
|
printf("{\n");
|
|
|
|
|
for (p = 0; p < 3; ++p) {
|
|
|
|
|
printf("\t{\n");
|
|
|
|
|
for (i = 0; i < DISK; ++i) {
|
|
|
|
|
if (i % 8 == 0)
|
|
|
|
|
printf("\t\t");
|
|
|
|
|
printf("0x%02x,", matrix[p * DISK + i]);
|
|
|
|
|
if (i != DISK - 1) {
|
|
|
|
|
if (i % 8 == 7)
|
|
|
|
|
printf("\n");
|
|
|
|
|
else
|
|
|
|
|
printf(" ");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
printf("\n\t},\n");
|
|
|
|
|
}
|
|
|
|
|
printf("};\n\n");
|
2026-05-17 23:35:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int main(void)
|
|
|
|
|
{
|
|
|
|
|
printf("// SPDX-License-Identifier: GPL-2.0-or-later\n");
|
|
|
|
|
printf("// Copyright (C) 2013 Andrea Mazzoleni\n");
|
|
|
|
|
printf("\n");
|
|
|
|
|
|
|
|
|
|
printf("#include \"internal.h\"\n");
|
2026-07-29 12:47:13 +02:00
|
|
|
printf("#include \"gf.h\"\n");
|
2026-05-17 23:35:29 +02:00
|
|
|
printf("\n");
|
|
|
|
|
|
|
|
|
|
printf("/* Tables with the RAID Polynomial 0x1d */\n");
|
2026-08-19 01:36:18 +02:00
|
|
|
tables(RAID_POLY_RAID, 2, "raid");
|
2026-07-29 12:47:13 +02:00
|
|
|
|
|
|
|
|
printf("/* Tables with the AES Polynomial 0x1b */\n");
|
2026-08-19 01:36:18 +02:00
|
|
|
tables(RAID_POLY_AES, 3, "aes");
|
2013-11-03 17:50:09 +01:00
|
|
|
|
2013-09-07 19:43:33 +02:00
|
|
|
return 0;
|
|
|
|
|
}
|