1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
|
/*
* Intel(R) Matrix Storage Manager hardware and firmware support routines
*
* Copyright (C) 2008 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <asm/types.h>
#include <strings.h>
/* according to GUID format: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" */
#define GUID_STR_MAX 37
/* The IMSM Capability (IMSM AHCI and ISCU OROM/EFI variable) Version Table definition */
struct imsm_orom {
__u8 signature[4];
#define IMSM_OROM_SIGNATURE "$VER"
#define IMSM_NVME_OROM_COMPAT_SIGNATURE "$NVM"
#define IMSM_VMD_OROM_COMPAT_SIGNATURE "$VMD"
__u8 table_ver_major; /* Currently 2 (can change with future revs) */
__u8 table_ver_minor; /* Currently 2 (can change with future revs) */
__u16 major_ver; /* Example: 8 as in 8.6.0.1020 */
__u16 minor_ver; /* Example: 6 as in 8.6.0.1020 */
__u16 hotfix_ver; /* Example: 0 as in 8.6.0.1020 */
__u16 build; /* Example: 1020 as in 8.6.0.1020 */
__u8 len; /* number of bytes in this entire table */
__u8 checksum; /* checksum of all the bytes in this table */
__u16 rlc; /* RAID Level Capability */
/* we assume the cpu is x86 as the orom should not be found
* anywhere else
*/
#define IMSM_OROM_RLC_RAID0 (1 << 0)
#define IMSM_OROM_RLC_RAID1 (1 << 1)
#define IMSM_OROM_RLC_RAID10 (1 << 2)
#define IMSM_OROM_RLC_RAID1E (1 << 3)
#define IMSM_OROM_RLC_RAID5 (1 << 4)
#define IMSM_OROM_RLC_RAID_CNG (1 << 5)
__u16 sss; /* Strip Size Supported */
#define IMSM_OROM_SSS_2kB (1 << 0)
#define IMSM_OROM_SSS_4kB (1 << 1)
#define IMSM_OROM_SSS_8kB (1 << 2)
#define IMSM_OROM_SSS_16kB (1 << 3)
#define IMSM_OROM_SSS_32kB (1 << 4)
#define IMSM_OROM_SSS_64kB (1 << 5)
#define IMSM_OROM_SSS_128kB (1 << 6)
#define IMSM_OROM_SSS_256kB (1 << 7)
#define IMSM_OROM_SSS_512kB (1 << 8)
#define IMSM_OROM_SSS_1MB (1 << 9)
#define IMSM_OROM_SSS_2MB (1 << 10)
#define IMSM_OROM_SSS_4MB (1 << 11)
#define IMSM_OROM_SSS_8MB (1 << 12)
#define IMSM_OROM_SSS_16MB (1 << 13)
#define IMSM_OROM_SSS_32MB (1 << 14)
#define IMSM_OROM_SSS_64MB (1 << 15)
__u16 dpa; /* Disks Per Array supported */
#define IMSM_OROM_DISKS_PER_ARRAY 6
#define IMSM_OROM_DISKS_PER_ARRAY_NVME 12
__u16 tds; /* Total Disks Supported */
#define IMSM_OROM_TOTAL_DISKS 6
#define IMSM_OROM_TOTAL_DISKS_NVME 12
#define IMSM_OROM_TOTAL_DISKS_VMD 48
__u8 vpa; /* # Volumes Per Array supported */
#define IMSM_OROM_VOLUMES_PER_ARRAY 2
__u8 vphba; /* # Volumes Per Host Bus Adapter supported */
#define IMSM_OROM_VOLUMES_PER_HBA 4
#define IMSM_OROM_VOLUMES_PER_HBA_NVME 4
#define IMSM_OROM_VOLUMES_PER_HBA_VMD 24
/* Attributes supported. This should map to the
* attributes in the MPB. Also, lower 16 bits
* should match/duplicate RLC bits above.
*/
__u32 attr;
#define IMSM_OROM_ATTR_RAID0 IMSM_OROM_RLC_RAID0
#define IMSM_OROM_ATTR_RAID1 IMSM_OROM_RLC_RAID1
#define IMSM_OROM_ATTR_RAID10 IMSM_OROM_RLC_RAID10
#define IMSM_OROM_ATTR_RAID1E IMSM_OROM_RLC_RAID1E
#define IMSM_OROM_ATTR_RAID5 IMSM_OROM_RLC_RAID5
#define IMSM_OROM_ATTR_RAID_CNG IMSM_OROM_RLC_RAID_CNG
#define IMSM_OROM_ATTR_2TB_DISK (1 << 26)
#define IMSM_OROM_ATTR_2TB (1 << 29)
#define IMSM_OROM_ATTR_PM (1 << 30)
#define IMSM_OROM_ATTR_ChecksumVerify (1 << 31)
__u32 capabilities;
#define IMSM_OROM_CAPABILITIES_Ext_SATA (1 << 0)
#define IMSM_OROM_CAPABILITIES_TurboMemory (1 << 1)
#define IMSM_OROM_CAPABILITIES_HddPassword (1 << 2)
#define IMSM_OROM_CAPABILITIES_DiskCoercion (1 << 3)
__u32 driver_features;
#define IMSM_OROM_CAPABILITIES_HDDUnlock (1 << 0)
#define IMSM_OROM_CAPABILITIES_LEDLoc (1 << 1)
#define IMSM_OROM_CAPABILITIES_EnterpriseSystem (1 << 2)
#define IMSM_OROM_CAPABILITIES_Zpodd (1 << 3)
#define IMSM_OROM_CAPABILITIES_LargeDramCache (1 << 4)
#define IMSM_OROM_CAPABILITIES_Rohi (1 << 5)
#define IMSM_OROM_CAPABILITIES_ReadPatrol (1 << 6)
#define IMSM_OROM_CAPABILITIES_XorHw (1 << 7)
#define IMSM_OROM_CAPABILITIES_SKUMode ((1 << 8)|(1 << 9))
#define IMSM_OROM_CAPABILITIES_TPV (1 << 10)
} __attribute__((packed));
/* IMSM metadata requirements for each level */
struct imsm_level_ops {
int level;
bool (*is_level_supported)(const struct imsm_orom *);
bool (*is_raiddisks_count_supported)(const int);
char *name;
};
extern struct imsm_level_ops imsm_level_ops[];
static inline bool imsm_rlc_has_bit(const struct imsm_orom *orom, const unsigned short bit)
{
if (orom->rlc & bit)
return true;
return false;
}
/**
* imsm_orom_has_chunk - check if the orom supports the given chunk size
* @orom: orom pointer from find_imsm_orom
* @chunk: chunk size in kibibytes
*/
static inline int imsm_orom_has_chunk(const struct imsm_orom *orom, int chunk)
{
int fs = ffs(chunk);
if (!fs)
return 0;
fs--; /* bit num to bit index */
if (chunk & (chunk-1))
return 0; /* not a power of 2 */
return !!(orom->sss & (1 << (fs - 1)));
}
/**
* fls - find last (most-significant) bit set
* @x: the word to search
* The funciton is borrowed from Linux kernel code
* include/asm-generic/bitops/fls.h
*/
static inline int fls(int x)
{
int r = 32;
if (!x)
return 0;
if (!(x & 0xffff0000u)) {
x <<= 16;
r -= 16;
}
if (!(x & 0xff000000u)) {
x <<= 8;
r -= 8;
}
if (!(x & 0xf0000000u)) {
x <<= 4;
r -= 4;
}
if (!(x & 0xc0000000u)) {
x <<= 2;
r -= 2;
}
if (!(x & 0x80000000u)) {
r -= 1;
}
return r;
}
static inline int imsm_orom_is_enterprise(const struct imsm_orom *orom)
{
return !!(orom->driver_features & IMSM_OROM_CAPABILITIES_EnterpriseSystem);
}
static inline int imsm_orom_is_nvme(const struct imsm_orom *orom)
{
return memcmp(orom->signature, IMSM_NVME_OROM_COMPAT_SIGNATURE,
sizeof(orom->signature)) == 0;
}
static inline int imsm_orom_is_vmd_without_efi(const struct imsm_orom *orom)
{
return memcmp(orom->signature, IMSM_VMD_OROM_COMPAT_SIGNATURE,
sizeof(orom->signature)) == 0;
}
static inline int imsm_orom_has_tpv_support(const struct imsm_orom *orom)
{
return !!(orom->driver_features & IMSM_OROM_CAPABILITIES_TPV);
}
enum sys_dev_type {
SYS_DEV_UNKNOWN = 0,
SYS_DEV_SAS,
SYS_DEV_SATA,
SYS_DEV_NVME,
SYS_DEV_VMD,
SYS_DEV_SATA_VMD,
SYS_DEV_MAX
};
struct sys_dev {
enum sys_dev_type type;
char *path;
char *pci_id;
__u16 dev_id;
__u32 class;
struct sys_dev *next;
};
struct efi_guid {
__u8 b[16];
};
struct devid_list {
__u16 devid;
struct devid_list *next;
};
struct orom_entry {
struct imsm_orom orom;
struct devid_list *devid_list;
enum sys_dev_type type;
struct orom_entry *next;
};
extern struct orom_entry *orom_entries;
static inline char *guid_str(char *buf, struct efi_guid guid)
{
snprintf(buf, GUID_STR_MAX, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
guid.b[3], guid.b[2], guid.b[1], guid.b[0],
guid.b[5], guid.b[4], guid.b[7], guid.b[6],
guid.b[8], guid.b[9], guid.b[10], guid.b[11],
guid.b[12], guid.b[13], guid.b[14], guid.b[15]);
return buf;
}
char *get_nvme_multipath_dev_hw_path(const char *dev_path);
char *diskfd_to_devpath(int fd, int dev_level, char *buf);
int devpath_to_char(const char *dev_path, const char *entry, char *buf,
int len, int verbose);
__u16 devpath_to_vendor(const char *dev_path);
struct sys_dev *find_driver_devices(const char *bus, const char *driver);
struct sys_dev *find_intel_devices(void);
const struct imsm_orom *find_imsm_capability(struct sys_dev *hba);
const struct imsm_orom *find_imsm_orom(void);
int disk_attached_to_hba(int fd, const char *hba_path);
int devt_attached_to_hba(dev_t dev, const char *hba_path);
char *devt_to_devpath(dev_t dev, int dev_level, char *buf);
bool is_path_attached_to_hba(const char *disk_path, const char *hba_path);
const struct orom_entry *get_orom_entry_by_device_id(__u16 dev_id);
const struct imsm_orom *get_orom_by_device_id(__u16 device_id);
struct sys_dev *device_by_id(__u16 device_id);
struct sys_dev *device_by_id_and_path(__u16 device_id, const char *path);
int is_multipath_nvme(int disk_fd);
int imsm_is_nvme_namespace_supported(int disk_fd, int verbose);
char *vmd_domain_to_controller(struct sys_dev *hba, char *buf);
|