1 /* dmraid_nvidia.c - module to handle Nvidia fakeraid. */
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2006,2007,2008 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/raid.h>
27 #define NV_SIGNATURES 4
30 #define NV_SCDB_INIT_RAID 2
31 #define NV_SCDB_REBUILD_RAID 3
32 #define NV_SCDB_UPGRADE_RAID 4
33 #define NV_SCDB_SYNC_RAID 5
35 #define NV_LEVEL_UNKNOWN 0x00
36 #define NV_LEVEL_JBOD 0xFF
37 #define NV_LEVEL_0 0x80
38 #define NV_LEVEL_1 0x81
39 #define NV_LEVEL_3 0x83
40 #define NV_LEVEL_5 0x85
41 #define NV_LEVEL_10 0x8a
42 #define NV_LEVEL_1_0 0x8180
44 #define NV_ARRAY_FLAG_BOOT 1 /* BIOS use only. */
45 #define NV_ARRAY_FLAG_ERROR 2 /* Degraded or offling. */
46 #define NV_ARRAY_FLAG_PARITY_VALID 4 /* RAID-3/5 parity valid. */
50 grub_uint32_t version
;
51 grub_uint32_t signature
[NV_SIGNATURES
];
52 grub_uint8_t raid_job_code
;
53 grub_uint8_t stripe_width
;
54 grub_uint8_t total_volumes
;
55 grub_uint8_t original_width
;
56 grub_uint32_t raid_level
;
57 grub_uint32_t stripe_block_size
;
58 grub_uint32_t stripe_block_size_bytes
;
59 grub_uint32_t stripe_block_size_log2
;
60 grub_uint32_t stripe_mask
;
61 grub_uint32_t stripe_size
;
62 grub_uint32_t stripe_size_bytes
;
63 grub_uint32_t raid_job_mask
;
64 grub_uint32_t original_capacity
;
69 #define NV_ID_STRING "NVIDIA"
70 #define NV_VERSION 100
72 #define NV_PRODID_LEN 16
73 #define NV_PRODREV_LEN 4
77 char vendor
[NV_ID_LEN
]; /* 0x00 - 0x07 ID string. */
78 grub_uint32_t size
; /* 0x08 - 0x0B Size of metadata in dwords. */
79 grub_uint32_t chksum
; /* 0x0C - 0x0F Checksum of this struct. */
80 grub_uint16_t version
; /* 0x10 - 0x11 NV version. */
81 grub_uint8_t unit_number
; /* 0x12 Disk index in array. */
82 grub_uint8_t reserved
; /* 0x13. */
83 grub_uint32_t capacity
; /* 0x14 - 0x17 Array capacity in sectors. */
84 grub_uint32_t sector_size
; /* 0x18 - 0x1B Sector size. */
85 char prodid
[NV_PRODID_LEN
]; /* 0x1C - 0x2B Array product ID. */
86 char prodrev
[NV_PRODREV_LEN
]; /* 0x2C - 0x2F Array product revision */
87 grub_uint32_t unit_flags
; /* 0x30 - 0x33 Flags for this disk */
88 struct grub_nv_array array
; /* Array information */
89 } __attribute__ ((packed
));
92 grub_dmraid_nv_detect (grub_disk_t disk
, struct grub_raid_array
*array
)
94 grub_disk_addr_t sector
;
95 struct grub_nv_super sb
;
98 return grub_error (GRUB_ERR_OUT_OF_RANGE
, "skip partition");
100 sector
= grub_disk_get_size (disk
) - 2;
102 if (grub_disk_read (disk
, sector
, 0, sizeof (sb
), (char *) &sb
))
105 if (grub_memcmp (sb
.vendor
, NV_ID_STRING
, 6))
106 return grub_error (GRUB_ERR_OUT_OF_RANGE
, "not raid");
108 if (sb
.version
!= NV_VERSION
)
109 return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET
,
110 "Unknown version: %d.%d", sb
.version
);
112 switch (sb
.array
.raid_level
)
116 array
->disk_size
= sb
.capacity
/ sb
.array
.total_volumes
;
121 array
->disk_size
= sb
.capacity
;
126 array
->layout
= GRUB_RAID_LAYOUT_LEFT_ASYMMETRIC
;
127 array
->disk_size
= sb
.capacity
/ (sb
.array
.total_volumes
- 1);
131 return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET
,
132 "Unsupported RAID level: %d", sb
.array
.raid_level
);
136 array
->total_devs
= sb
.array
.total_volumes
;
137 array
->chunk_size
= sb
.array
.stripe_block_size
;
138 array
->index
= sb
.unit_number
;
139 array
->uuid_len
= sizeof (sb
.array
.signature
);
140 array
->uuid
= grub_malloc (sizeof (sb
.array
.signature
));
144 grub_memcpy (array
->uuid
, (char *) &sb
.array
.signature
,
145 sizeof (sb
.array
.signature
));
150 static struct grub_raid grub_dmraid_nv_dev
=
153 .detect
= grub_dmraid_nv_detect
,
159 grub_raid_register (&grub_dmraid_nv_dev
);
164 grub_raid_register (&grub_dmraid_nv_dev
);