1 /*
2 * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
3 * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
4 *
5 * Inspired by libvolume_id by
6 * Kay Sievers <kay.sievers@vrfy.org>
7 *
8 * This file may be redistributed under the terms of the
9 * GNU Lesser General Public License.
10 */
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <unistd.h>
14 #include <string.h>
15 #include <stdint.h>
16
17 #include "superblocks.h"
18
19 struct nv_metadata {
20 uint8_t vendor[8];
21 uint32_t size;
22 uint32_t chksum;
23 uint16_t version;
24 } __attribute__((packed));
25
26 #define NVIDIA_SIGNATURE "NVIDIA "
27 #define NVIDIA_SUPERBLOCK_SIZE 120
28
29
30 static int nvraid_verify_checksum(blkid_probe pr, const struct nv_metadata *nv)
31 {
32 uint32_t csum = le32_to_cpu(nv->chksum);
33 for (size_t i = 0; i < le32_to_cpu(nv->size); i++)
34 csum += le32_to_cpu(((uint32_t *) nv)[i]);
35 return blkid_probe_verify_csum(pr, csum, le32_to_cpu(nv->chksum));
36 }
37
38 static int probe_nvraid(blkid_probe pr,
39 const struct blkid_idmag *mag __attribute__((__unused__)))
40 {
41 uint64_t off;
42 struct nv_metadata *nv;
43
44 if (pr->size < 0x10000)
45 return 1;
46 if (!S_ISREG(pr->mode) && !blkid_probe_is_wholedisk(pr))
47 return 1;
48
49 off = ((pr->size / 0x200) - 2) * 0x200;
50 nv = (struct nv_metadata *)
51 blkid_probe_get_buffer(pr,
52 off,
53 NVIDIA_SUPERBLOCK_SIZE);
54 if (!nv)
55 return errno ? -errno : 1;
56
57 if (memcmp(nv->vendor, NVIDIA_SIGNATURE, sizeof(NVIDIA_SIGNATURE)-1) != 0)
58 return 1;
59 if (le32_to_cpu(nv->size) * 4 != NVIDIA_SUPERBLOCK_SIZE)
60 return 1;
61 if (!nvraid_verify_checksum(pr, nv))
62 return 1;
63 if (blkid_probe_sprintf_version(pr, "%u", le16_to_cpu(nv->version)) != 0)
64 return 1;
65 if (blkid_probe_set_magic(pr, off, sizeof(nv->vendor),
66 (unsigned char *) nv->vendor))
67 return 1;
68 return 0;
69 }
70
71 const struct blkid_idinfo nvraid_idinfo = {
72 .name = "nvidia_raid_member",
73 .usage = BLKID_USAGE_RAID,
74 .probefunc = probe_nvraid,
75 .magics = BLKID_NONE_MAGIC
76 };
77
78