Add following files to svn:ingore:
[grub2/phcoder/solaris.git] / disk / dmraid_nvidia.c
blob84dfad8c4e2fa076704850f8f5bb2cb10c2cae50
1 /* dmraid_nvidia.c - module to handle Nvidia fakeraid. */
2 /*
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/>.
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/raid.h>
27 #define NV_SIGNATURES 4
29 #define NV_IDLE 0
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 offline. */
46 #define NV_ARRAY_FLAG_PARITY_VALID 4 /* RAID-3/5 parity valid. */
48 struct grub_nv_array
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;
65 grub_uint32_t flags;
68 #define NV_ID_LEN 8
69 #define NV_ID_STRING "NVIDIA"
70 #define NV_VERSION 100
72 #define NV_PRODID_LEN 16
73 #define NV_PRODREV_LEN 4
75 struct grub_nv_super
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));
91 static grub_err_t
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;
97 if (disk->partition)
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), &sb))
103 return grub_errno;
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)
114 case NV_LEVEL_0:
115 array->level = 0;
116 array->disk_size = sb.capacity / sb.array.total_volumes;
117 break;
119 case NV_LEVEL_1:
120 array->level = 1;
121 array->disk_size = sb.capacity;
122 break;
124 case NV_LEVEL_5:
125 array->level = 5;
126 array->layout = GRUB_RAID_LAYOUT_LEFT_ASYMMETRIC;
127 array->disk_size = sb.capacity / (sb.array.total_volumes - 1);
128 break;
130 default:
131 return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
132 "Unsupported RAID level: %d", sb.array.raid_level);
135 array->number = 0;
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));
141 if (! array->uuid)
142 return grub_errno;
144 grub_memcpy (array->uuid, (char *) &sb.array.signature,
145 sizeof (sb.array.signature));
147 return 0;
150 static struct grub_raid grub_dmraid_nv_dev =
152 .name = "dmraid_nv",
153 .detect = grub_dmraid_nv_detect,
154 .next = 0
157 GRUB_MOD_INIT(dm_nv)
159 grub_raid_register (&grub_dmraid_nv_dev);
162 GRUB_MOD_FINI(dm_nv)
164 grub_raid_unregister (&grub_dmraid_nv_dev);