Indentation fix, cleanup.
[AROS.git] / arch / all-pc / boot / grub2-aros / grub-core / disk / raid6_recover.c
blobf9ec632fb23de952c972577465868febfda8a67a
1 /* raid6_recover.c - module to recover from faulty RAID6 arrays. */
2 /*
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2006,2007,2008,2009 Free Software Foundation, Inc.
6 * GRUB is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * GRUB is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
20 #include <grub/dl.h>
21 #include <grub/disk.h>
22 #include <grub/mm.h>
23 #include <grub/err.h>
24 #include <grub/misc.h>
25 #include <grub/diskfilter.h>
26 #include <grub/crypto.h>
28 GRUB_MOD_LICENSE ("GPLv3+");
30 /* x**y. */
31 static grub_uint8_t powx[255 * 2];
32 /* Such an s that x**s = y */
33 static unsigned powx_inv[256];
34 static const grub_uint8_t poly = 0x1d;
36 static void
37 grub_raid_block_mulx (unsigned mul, char *buf, grub_size_t size)
39 grub_size_t i;
40 grub_uint8_t *p;
42 p = (grub_uint8_t *) buf;
43 for (i = 0; i < size; i++, p++)
44 if (*p)
45 *p = powx[mul + powx_inv[*p]];
48 static void
49 grub_raid6_init_table (void)
51 unsigned i;
53 grub_uint8_t cur = 1;
54 for (i = 0; i < 255; i++)
56 powx[i] = cur;
57 powx[i + 255] = cur;
58 powx_inv[cur] = i;
59 if (cur & 0x80)
60 cur = (cur << 1) ^ poly;
61 else
62 cur <<= 1;
66 static grub_err_t
67 grub_raid6_recover (struct grub_diskfilter_segment *array, int disknr, int p,
68 char *buf, grub_disk_addr_t sector, grub_size_t size)
70 int i, q, pos;
71 int bad1 = -1, bad2 = -1;
72 char *pbuf = 0, *qbuf = 0;
74 size <<= GRUB_DISK_SECTOR_BITS;
75 pbuf = grub_zalloc (size);
76 if (!pbuf)
77 goto quit;
79 qbuf = grub_zalloc (size);
80 if (!qbuf)
81 goto quit;
83 q = p + 1;
84 if (q == (int) array->node_count)
85 q = 0;
87 pos = q + 1;
88 if (pos == (int) array->node_count)
89 pos = 0;
91 for (i = 0; i < (int) array->node_count - 2; i++)
93 int c;
94 if (array->layout & GRUB_RAID_LAYOUT_MUL_FROM_POS)
95 c = pos;
96 else
97 c = i;
98 if (pos == disknr)
99 bad1 = c;
100 else
102 if (! grub_diskfilter_read_node (&array->nodes[pos], sector,
103 size >> GRUB_DISK_SECTOR_BITS, buf))
105 grub_crypto_xor (pbuf, pbuf, buf, size);
106 grub_raid_block_mulx (c, buf, size);
107 grub_crypto_xor (qbuf, qbuf, buf, size);
109 else
111 /* Too many bad devices */
112 if (bad2 >= 0)
113 goto quit;
115 bad2 = c;
116 grub_errno = GRUB_ERR_NONE;
120 pos++;
121 if (pos == (int) array->node_count)
122 pos = 0;
125 /* Invalid disknr or p */
126 if (bad1 < 0)
127 goto quit;
129 if (bad2 < 0)
131 /* One bad device */
132 if ((! grub_diskfilter_read_node (&array->nodes[p], sector,
133 size >> GRUB_DISK_SECTOR_BITS, buf)))
135 grub_crypto_xor (buf, buf, pbuf, size);
136 goto quit;
139 grub_errno = GRUB_ERR_NONE;
140 if (grub_diskfilter_read_node (&array->nodes[q], sector,
141 size >> GRUB_DISK_SECTOR_BITS, buf))
142 goto quit;
144 grub_crypto_xor (buf, buf, qbuf, size);
145 grub_raid_block_mulx (255 - bad1, buf,
146 size);
148 else
150 /* Two bad devices */
151 unsigned c;
153 if (grub_diskfilter_read_node (&array->nodes[p], sector,
154 size >> GRUB_DISK_SECTOR_BITS, buf))
155 goto quit;
157 grub_crypto_xor (pbuf, pbuf, buf, size);
159 if (grub_diskfilter_read_node (&array->nodes[q], sector,
160 size >> GRUB_DISK_SECTOR_BITS, buf))
161 goto quit;
163 grub_crypto_xor (qbuf, qbuf, buf, size);
165 c = ((255 ^ bad1)
166 + (255 ^ powx_inv[(powx[bad2 + (bad1 ^ 255)] ^ 1)])) % 255;
167 grub_raid_block_mulx (c, qbuf, size);
169 c = ((unsigned) bad2 + c) % 255;
170 grub_raid_block_mulx (c, pbuf, size);
172 grub_crypto_xor (pbuf, pbuf, qbuf, size);
173 grub_memcpy (buf, pbuf, size);
176 quit:
177 grub_free (pbuf);
178 grub_free (qbuf);
180 return grub_errno;
183 GRUB_MOD_INIT(raid6rec)
185 grub_raid6_init_table ();
186 grub_raid6_recover_func = grub_raid6_recover;
189 GRUB_MOD_FINI(raid6rec)
191 grub_raid6_recover_func = 0;