1 /* dmraid_nvidia.c - module to handle Nvidia fakeraid. */
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/>.
21 #include <grub/disk.h>
24 #include <grub/misc.h>
25 #include <grub/diskfilter.h>
27 GRUB_MOD_LICENSE ("GPLv3+");
29 #define NV_SIGNATURES 4
32 #define NV_SCDB_INIT_RAID 2
33 #define NV_SCDB_REBUILD_RAID 3
34 #define NV_SCDB_UPGRADE_RAID 4
35 #define NV_SCDB_SYNC_RAID 5
37 #define NV_LEVEL_UNKNOWN 0x00
38 #define NV_LEVEL_JBOD 0xFF
39 #define NV_LEVEL_0 0x80
40 #define NV_LEVEL_1 0x81
41 #define NV_LEVEL_3 0x83
42 #define NV_LEVEL_5 0x85
43 #define NV_LEVEL_10 0x8a
44 #define NV_LEVEL_1_0 0x8180
46 #define NV_ARRAY_FLAG_BOOT 1 /* BIOS use only. */
47 #define NV_ARRAY_FLAG_ERROR 2 /* Degraded or offline. */
48 #define NV_ARRAY_FLAG_PARITY_VALID 4 /* RAID-3/5 parity valid. */
52 grub_uint32_t version
;
53 grub_uint32_t signature
[NV_SIGNATURES
];
54 grub_uint8_t raid_job_code
;
55 grub_uint8_t stripe_width
;
56 grub_uint8_t total_volumes
;
57 grub_uint8_t original_width
;
58 grub_uint32_t raid_level
;
59 grub_uint32_t stripe_block_size
;
60 grub_uint32_t stripe_block_size_bytes
;
61 grub_uint32_t stripe_block_size_log2
;
62 grub_uint32_t stripe_mask
;
63 grub_uint32_t stripe_size
;
64 grub_uint32_t stripe_size_bytes
;
65 grub_uint32_t raid_job_mask
;
66 grub_uint32_t original_capacity
;
71 #define NV_ID_STRING "NVIDIA"
72 #define NV_VERSION 100
74 #define NV_PRODID_LEN 16
75 #define NV_PRODREV_LEN 4
79 char vendor
[NV_ID_LEN
]; /* 0x00 - 0x07 ID string. */
80 grub_uint32_t size
; /* 0x08 - 0x0B Size of metadata in dwords. */
81 grub_uint32_t chksum
; /* 0x0C - 0x0F Checksum of this struct. */
82 grub_uint16_t version
; /* 0x10 - 0x11 NV version. */
83 grub_uint8_t unit_number
; /* 0x12 Disk index in array. */
84 grub_uint8_t reserved
; /* 0x13. */
85 grub_uint32_t capacity
; /* 0x14 - 0x17 Array capacity in sectors. */
86 grub_uint32_t sector_size
; /* 0x18 - 0x1B Sector size. */
87 char prodid
[NV_PRODID_LEN
]; /* 0x1C - 0x2B Array product ID. */
88 char prodrev
[NV_PRODREV_LEN
]; /* 0x2C - 0x2F Array product revision */
89 grub_uint32_t unit_flags
; /* 0x30 - 0x33 Flags for this disk */
90 struct grub_nv_array array
; /* Array information */
93 static struct grub_diskfilter_vg
*
94 grub_dmraid_nv_detect (grub_disk_t disk
,
95 struct grub_diskfilter_pv_id
*id
,
96 grub_disk_addr_t
*start_sector
)
98 grub_disk_addr_t sector
;
99 struct grub_nv_super sb
;
101 grub_uint64_t disk_size
;
105 /* Skip partition. */
108 sector
= grub_disk_get_size (disk
);
109 if (sector
== GRUB_DISK_SIZE_UNKNOWN
)
113 if (grub_disk_read (disk
, sector
, 0, sizeof (sb
), &sb
))
116 if (grub_memcmp (sb
.vendor
, NV_ID_STRING
, 6))
120 if (sb
.version
!= NV_VERSION
)
122 grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET
,
123 "unknown version: %d.%d", sb
.version
);
127 switch (sb
.array
.raid_level
)
131 disk_size
= sb
.capacity
/ sb
.array
.total_volumes
;
132 if (sb
.array
.total_volumes
== 0)
139 disk_size
= sb
.capacity
;
144 disk_size
= sb
.capacity
/ (sb
.array
.total_volumes
- 1);
145 if (sb
.array
.total_volumes
== 0 || sb
.array
.total_volumes
== 1)
151 grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET
,
152 "unsupported RAID level: %d", sb
.array
.raid_level
);
156 uuid
= grub_malloc (sizeof (sb
.array
.signature
));
160 grub_memcpy (uuid
, (char *) &sb
.array
.signature
,
161 sizeof (sb
.array
.signature
));
164 id
->id
= sb
.unit_number
;
168 return grub_diskfilter_make_raid (sizeof (sb
.array
.signature
),
169 uuid
, sb
.array
.total_volumes
,
171 sb
.array
.stripe_block_size
,
172 GRUB_RAID_LAYOUT_LEFT_ASYMMETRIC
,
176 static struct grub_diskfilter grub_dmraid_nv_dev
=
179 .detect
= grub_dmraid_nv_detect
,
185 grub_diskfilter_register_front (&grub_dmraid_nv_dev
);
190 grub_diskfilter_unregister (&grub_dmraid_nv_dev
);