devpath3.c revision 1.3 1 1.3 christos /* $NetBSD: devpath3.c,v 1.3 2025/02/25 22:11:36 christos Exp $ */
2 1.1 christos
3 1.1 christos /*
4 1.1 christos * Redistribution and use in source and binary forms, with or without
5 1.1 christos * modification, are permitted provided that the following conditions
6 1.1 christos * are met:
7 1.1 christos * 1. Redistributions of source code must retain the above copyright
8 1.1 christos * notice, this list of conditions and the following disclaimer.
9 1.1 christos * 2. Redistributions in binary form must reproduce the above copyright
10 1.1 christos * notice, this list of conditions and the following disclaimer in the
11 1.1 christos * documentation and/or other materials provided with the distribution.
12 1.1 christos *
13 1.1 christos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
14 1.1 christos * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15 1.1 christos * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16 1.1 christos * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 1.1 christos * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 1.1 christos * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19 1.1 christos * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 1.1 christos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 1.1 christos * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 1.1 christos * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 1.1 christos * SUCH DAMAGE.
24 1.1 christos */
25 1.1 christos
26 1.1 christos #include <sys/cdefs.h>
27 1.1 christos #ifndef lint
28 1.3 christos __RCSID("$NetBSD: devpath3.c,v 1.3 2025/02/25 22:11:36 christos Exp $");
29 1.1 christos #endif /* not lint */
30 1.1 christos
31 1.1 christos #include <arpa/inet.h>
32 1.1 christos #include <sys/uuid.h>
33 1.1 christos
34 1.1 christos #include <assert.h>
35 1.1 christos #include <ctype.h>
36 1.1 christos #include <err.h>
37 1.1 christos #include <netdb.h>
38 1.1 christos #include <stddef.h>
39 1.1 christos #include <stdio.h>
40 1.1 christos #include <stdlib.h>
41 1.1 christos #include <string.h>
42 1.1 christos #include <util.h>
43 1.1 christos
44 1.1 christos #include "defs.h"
45 1.1 christos #include "devpath.h"
46 1.1 christos #include "devpath3.h"
47 1.1 christos #include "utils.h"
48 1.1 christos
49 1.1 christos #define easprintf (size_t)easprintf
50 1.1 christos
51 1.1 christos #if 0
52 1.1 christos GUID= EFI_PC_ANSI_GUID
53 1.1 christos GUID= EFI_VT_100_GIUD
54 1.1 christos GUID= EFI_VT_100_PLUS_GUID
55 1.1 christos GUID= EFI_VT_UTF8_GUID
56 1.1 christos GUID= DEVICE_PATH_MESSAGING_UART_FLOW_CONTROL
57 1.1 christos GUID= EFI_DEBUGPORT_PROTOCOL_GUID
58 1.1 christos GUID= d487ddb4-008b-11d9-afdc-001083ffca4d
59 1.1 christos #endif
60 1.1 christos
61 1.1 christos /* Used in sub-type 10 */
62 1.1 christos #define EFI_PC_ANSI_GUID\
63 1.3 christos {0xe0c14753,0xf9be,0x11d2,0x9a,0x0c,{0x00,0x90,0x27,0x3f,0xc1,0x4d}}
64 1.1 christos
65 1.1 christos #define EFI_VT_100_GUID\
66 1.3 christos {0xdfa66065,0xb419,0x11d3,0x9a,0x2d,{0x00,0x90,0x27,0x3f,0xc1,0x4d}}
67 1.1 christos
68 1.1 christos #define EFI_VT_100_PLUS_GUID\
69 1.3 christos {0x7baec70b,0x57e0,0x4c76,0x8e,0x87,{0x2f,0x9e,0x28,0x08,0x83,0x43}}
70 1.1 christos
71 1.1 christos #define EFI_VT_UTF8_GUID\
72 1.3 christos {0xad15a0d6,0x8bec,0x4acf,0xa0,0x73,{0xd0,0x1d,0xe7,0x7e,0x2d,0x88}}
73 1.1 christos
74 1.1 christos #define EFI_DEBUGPORT_PROTOCOL_GUID \
75 1.3 christos {0xeba4e8d2,0x3858,0x41ec,0xa2,0x81,{0x26,0x47,0xba,0x96,0x60,0xd0}}
76 1.1 christos
77 1.1 christos #define DEVICE_PATH_MESSAGING_UART_FLOW_CONTROL \
78 1.3 christos {0x37499a9d,0x542f,0x4c89,0xa0,0x26,{0x35,0xda,0x14,0x20,0x94,0xe4}}
79 1.1 christos
80 1.1 christos #define EFI_VENDOR_SAS\
81 1.3 christos {0xd487ddb4,0x008b,0x11d9,0xaf,0xdc,{0x00,0x10,0x83,0xff,0xca,0x4d}}
82 1.1 christos
83 1.1 christos /************************************************************************/
84 1.1 christos
85 1.1 christos static inline char *
86 1.1 christos upcase(char *str)
87 1.1 christos {
88 1.1 christos
89 1.1 christos for (char *p = str; *p != '\0'; p++)
90 1.1 christos *p = (char)toupper((int)(unsigned char)*p);
91 1.1 christos return str;
92 1.1 christos }
93 1.1 christos
94 1.1 christos static inline char *
95 1.1 christos proto_name(uint16_t proto) /* See RFC3233/RFC1700 */
96 1.1 christos {
97 1.1 christos struct protoent *ent;
98 1.1 christos char *name;
99 1.1 christos char *bp;
100 1.1 christos
101 1.1 christos ent = getprotobynumber(proto);
102 1.1 christos if (ent == NULL) {
103 1.1 christos easprintf(&bp, "0x%04x", proto);
104 1.1 christos return bp;
105 1.1 christos }
106 1.1 christos name = estrdup(ent->p_name);
107 1.1 christos return upcase(name);
108 1.1 christos }
109 1.1 christos
110 1.1 christos static inline char *
111 1.1 christos ipv4_addr(uint32_t addr)
112 1.1 christos {
113 1.1 christos char *bp;
114 1.1 christos
115 1.1 christos bp = ecalloc(1, INET_ADDRSTRLEN);
116 1.1 christos if (inet_ntop(AF_INET, &addr, bp, INET_ADDRSTRLEN) == NULL)
117 1.1 christos err(EXIT_FAILURE, "%s: inet_ntop(AF_INET)", __func__);
118 1.1 christos return bp;
119 1.1 christos }
120 1.1 christos
121 1.1 christos static inline char *
122 1.1 christos ipv4_type(uint8_t type)
123 1.1 christos {
124 1.1 christos
125 1.1 christos switch (type) {
126 1.1 christos case 0: return estrdup("DHCP");
127 1.1 christos case 1: return estrdup("Static");
128 1.1 christos default: return estrdup("Unknown");
129 1.1 christos }
130 1.1 christos }
131 1.1 christos
132 1.1 christos static inline char *
133 1.1 christos ipv6_addr(struct in6_addr *addr)
134 1.1 christos {
135 1.1 christos char *bp;
136 1.1 christos
137 1.1 christos bp = ecalloc(1, INET6_ADDRSTRLEN);
138 1.1 christos if (inet_ntop(AF_INET6, addr, bp, INET6_ADDRSTRLEN) == NULL)
139 1.1 christos err(EXIT_FAILURE, "%s: inet_ntop(AF_INET6)", __func__);
140 1.1 christos return bp;
141 1.1 christos }
142 1.1 christos
143 1.1 christos static inline char *
144 1.1 christos ipv6_type(uint8_t type)
145 1.1 christos {
146 1.1 christos
147 1.1 christos switch (type) {
148 1.1 christos case 0: return estrdup("Static");
149 1.1 christos case 1: return estrdup("StatelessAutoConfigure");
150 1.1 christos case 2: return estrdup("StatefulAutoConfigure");
151 1.1 christos default: return estrdup("Unknown");
152 1.1 christos }
153 1.1 christos }
154 1.1 christos
155 1.1 christos /************************************************************************
156 1.1 christos * Type 3 - Messaging Device Path
157 1.1 christos ************************************************************************/
158 1.1 christos static void
159 1.1 christos devpath_msg_atapi(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
160 1.1 christos { /* See 10.3.4.1 */
161 1.1 christos struct { /* Sub-Type 1 */
162 1.1 christos devpath_t hdr; /* Length = 8 */
163 1.1 christos uint8_t IsSecondary;
164 1.1 christos uint8_t IsSlave;
165 1.1 christos uint16_t LUN;
166 1.1 christos } __packed *p = (void *)dp;
167 1.1 christos __CTASSERT(sizeof(*p) == 8);
168 1.1 christos
169 1.1 christos path->sz = easprintf(&path->cp, "ATAPI(%u,%u,%u)", p->IsSecondary, p->IsSlave, p->LUN);
170 1.1 christos
171 1.1 christos if (dbg != NULL) {
172 1.1 christos dbg->sz = easprintf(&dbg->cp,
173 1.1 christos DEVPATH_FMT_HDR
174 1.1 christos DEVPATH_FMT(IsSecondary: %u\n)
175 1.1 christos DEVPATH_FMT(IsPrimary: %u\n)
176 1.1 christos DEVPATH_FMT(LUN: %u\n),
177 1.1 christos DEVPATH_DAT_HDR(dp),
178 1.1 christos p->IsSecondary,
179 1.1 christos p->IsSlave,
180 1.1 christos p->LUN);
181 1.1 christos }
182 1.1 christos }
183 1.1 christos
184 1.1 christos static void
185 1.1 christos devpath_msg_scsi(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
186 1.1 christos { /* See 10.3.4.2 */
187 1.1 christos struct { /* Sub-Type 2 */
188 1.1 christos devpath_t hdr; /* Length = 8 */
189 1.1 christos uint16_t SCSITargetID; /* PUN */
190 1.1 christos uint16_t SCSILogicalUnitNum; /* LUN */
191 1.1 christos } __packed *p = (void *)dp;
192 1.1 christos __CTASSERT(sizeof(*p) == 8);
193 1.1 christos
194 1.1 christos path->sz = easprintf(&path->cp, "SCSI(%u,%u)", p->SCSITargetID, p->SCSILogicalUnitNum);
195 1.1 christos
196 1.1 christos if (dbg != NULL) {
197 1.1 christos dbg->sz = easprintf(&dbg->cp,
198 1.1 christos DEVPATH_FMT_HDR
199 1.1 christos DEVPATH_FMT(SCSITargetID: %u\n)
200 1.1 christos DEVPATH_FMT(SCSILogicalUnitNum: %u\n),
201 1.1 christos DEVPATH_DAT_HDR(dp),
202 1.1 christos p->SCSITargetID,
203 1.1 christos p->SCSILogicalUnitNum);
204 1.1 christos }
205 1.1 christos }
206 1.1 christos
207 1.1 christos static void
208 1.1 christos devpath_msg_fibre(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
209 1.1 christos { /* See 10.3.4.3 */
210 1.1 christos struct { /* Sub-Type 3 */
211 1.1 christos devpath_t hdr; /* Length = 24 */
212 1.1 christos uint32_t Reserved;
213 1.1 christos uint64_t WWName;
214 1.1 christos uint64_t LUN;
215 1.1 christos } __packed *p = (void *)dp;
216 1.1 christos __CTASSERT(sizeof(*p) == 24);
217 1.1 christos
218 1.2 martin path->sz = easprintf(&path->cp, "Fibre(0x%016" PRIx64 ",0x%016"
219 1.2 martin PRIx64 ")", p->WWName, p->LUN);
220 1.1 christos
221 1.1 christos if (dbg != NULL) {
222 1.1 christos dbg->sz = easprintf(&dbg->cp,
223 1.1 christos DEVPATH_FMT_HDR
224 1.1 christos DEVPATH_FMT(Reserved: 0x%08x\n)
225 1.2 martin DEVPATH_FMT(WWName:) " 0x%016" PRIx64 "\n"
226 1.2 martin DEVPATH_FMT(LUN:) " 0x%016" PRIx64 "\n",
227 1.1 christos DEVPATH_DAT_HDR(dp),
228 1.1 christos p->Reserved,
229 1.1 christos p->WWName,
230 1.1 christos p->LUN);
231 1.1 christos }
232 1.1 christos }
233 1.1 christos
234 1.1 christos static void
235 1.1 christos devpath_msg_11394(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
236 1.1 christos { /* See 10.3.4.4 */
237 1.1 christos struct { /* Sub-Type 4 */
238 1.1 christos devpath_t hdr; /* Length = 16 */
239 1.1 christos uint32_t Reserved;
240 1.1 christos uint64_t GUID; /* XXX: not an EFI_GUID */
241 1.1 christos } __packed *p = (void *)dp;
242 1.1 christos __CTASSERT(sizeof(*p) == 16);
243 1.1 christos
244 1.2 martin path->sz = easprintf(&path->cp, "11394(0x%016" PRIx64 ")", p->GUID);
245 1.1 christos
246 1.1 christos if (dbg != NULL) {
247 1.1 christos dbg->sz = easprintf(&dbg->cp,
248 1.1 christos DEVPATH_FMT_HDR
249 1.1 christos DEVPATH_FMT(Reserved: 0x%08x\n)
250 1.2 martin DEVPATH_FMT(GUID:) " 0x%016" PRIx64 "\n",
251 1.1 christos DEVPATH_DAT_HDR(dp),
252 1.1 christos p->Reserved,
253 1.1 christos p->GUID);
254 1.1 christos }
255 1.1 christos }
256 1.1 christos
257 1.1 christos static void
258 1.1 christos devpath_msg_usb(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
259 1.1 christos { /* See 10.3.4.5 */
260 1.1 christos struct { /* Sub-Type 5 */
261 1.1 christos devpath_t hdr; /* Length = 6 */
262 1.1 christos uint8_t USBParentPortNum;
263 1.1 christos uint8_t USBInterfaceNum;
264 1.1 christos } __packed *p = (void *)dp;
265 1.1 christos __CTASSERT(sizeof(*p) == 6);
266 1.1 christos
267 1.1 christos path->sz = easprintf(&path->cp, "USB(%u,%u)", p->USBParentPortNum, p->USBInterfaceNum);
268 1.1 christos
269 1.1 christos if (dbg != NULL) {
270 1.1 christos dbg->sz = easprintf(&dbg->cp,
271 1.1 christos DEVPATH_FMT_HDR
272 1.1 christos DEVPATH_FMT(USBParentPortNum: %u\n)
273 1.1 christos DEVPATH_FMT(USBInterfaceNum: %u\n),
274 1.1 christos DEVPATH_DAT_HDR(dp),
275 1.1 christos p->USBParentPortNum,
276 1.1 christos p->USBInterfaceNum);
277 1.1 christos }
278 1.1 christos }
279 1.1 christos
280 1.1 christos static void
281 1.1 christos devpath_msg_i2o(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
282 1.1 christos { /* See 10.3.4.9 */
283 1.1 christos struct { /* Sub-Type 6 */
284 1.1 christos devpath_t hdr; /* Length = 8 */
285 1.1 christos uint32_t TID;
286 1.1 christos } __packed *p = (void *)dp;
287 1.1 christos __CTASSERT(sizeof(*p) == 8);
288 1.1 christos
289 1.1 christos path->sz = easprintf(&path->cp, "I2O(0x%08x)", p->TID);
290 1.1 christos
291 1.1 christos if (dbg != NULL) {
292 1.1 christos dbg->sz = easprintf(&dbg->cp,
293 1.1 christos DEVPATH_FMT_HDR
294 1.1 christos DEVPATH_FMT(TID: 0x%08x\n),
295 1.1 christos DEVPATH_DAT_HDR(dp),
296 1.1 christos p->TID);
297 1.1 christos }
298 1.1 christos }
299 1.1 christos
300 1.1 christos #define INFINIBAND_FLAG_BITS \
301 1.1 christos "\177\020" \
302 1.1 christos "b\x0""Service\0" \
303 1.1 christos "b\x1""BootEnv\0" \
304 1.1 christos "b\x2""ConProto\0" \
305 1.1 christos "b\x3""Storage\0" \
306 1.1 christos "b\x4""NetWork\0" \
307 1.1 christos "f\x5\11""Resvd\0"
308 1.1 christos
309 1.1 christos static void
310 1.1 christos devpath_msg_infiniband(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
311 1.1 christos { /* See 10.3.4.14 */
312 1.1 christos struct { /* Sub-Type 9 */
313 1.1 christos devpath_t hdr; /* Length = 48 */
314 1.1 christos uint32_t Flags;
315 1.1 christos uuid_t GUID;
316 1.1 christos uint64_t ServiceID;
317 1.1 christos uint64_t PortID;
318 1.1 christos uint64_t DeviceID;
319 1.1 christos } __packed *p = (void *)dp;
320 1.1 christos __CTASSERT(sizeof(*p) == 48);
321 1.1 christos char uuid_str[UUID_STR_LEN];
322 1.1 christos
323 1.1 christos uuid_snprintf(uuid_str, sizeof(uuid_str), &p->GUID);
324 1.1 christos
325 1.2 martin path->sz = easprintf(&path->cp, "Infiniband(%#x,%s,0x%016" PRIx64
326 1.2 martin ",0x%016" PRIx64 ",0x%016" PRIx64 ")",
327 1.1 christos p->Flags, uuid_str, p->ServiceID, p->PortID, p->DeviceID);
328 1.1 christos
329 1.1 christos if (dbg != NULL) {
330 1.1 christos char flags_str[128];
331 1.1 christos
332 1.1 christos snprintb(flags_str, sizeof(flags_str), INFINIBAND_FLAG_BITS,
333 1.1 christos p->Flags);
334 1.1 christos
335 1.1 christos dbg->sz = easprintf(&dbg->cp,
336 1.1 christos DEVPATH_FMT_HDR
337 1.1 christos DEVPATH_FMT(Flags: %s\n)
338 1.1 christos DEVPATH_FMT(GUID: %s\n)
339 1.2 martin DEVPATH_FMT(ServiceID:) " 0x%016" PRIx64 "\n"
340 1.2 martin DEVPATH_FMT(PortID:) " 0x%016" PRIx64 "\n"
341 1.2 martin DEVPATH_FMT(DeviceID:) " 0x%016" PRIx64 "\n",
342 1.1 christos DEVPATH_DAT_HDR(dp),
343 1.1 christos flags_str, uuid_str,
344 1.1 christos p->ServiceID, p->PortID, p->DeviceID);
345 1.1 christos }
346 1.1 christos }
347 1.1 christos
348 1.1 christos /****************************************
349 1.1 christos * Sub-Type 10 variants
350 1.1 christos */
351 1.1 christos static void
352 1.1 christos devpath_msg_debugport(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
353 1.1 christos { /* See 18.3.7 */
354 1.1 christos struct { /* Sub-Type 10 */
355 1.1 christos devpath_t hdr; /* Length = 20 */
356 1.1 christos uuid_t GUID;
357 1.1 christos } __packed *p = (void *)dp;
358 1.1 christos __CTASSERT(sizeof(*p) == 20);
359 1.1 christos
360 1.1 christos path->sz = easprintf(&path->cp, "DebugPort()");
361 1.1 christos
362 1.1 christos if (dbg != NULL) {
363 1.1 christos char uuid_str[UUID_STR_LEN];
364 1.1 christos
365 1.1 christos uuid_snprintf(uuid_str, sizeof(uuid_str), &p->GUID);
366 1.1 christos
367 1.1 christos dbg->sz = easprintf(&dbg->cp,
368 1.1 christos DEVPATH_FMT_HDR
369 1.1 christos DEVPATH_FMT(GUID: %s\n),
370 1.1 christos DEVPATH_DAT_HDR(dp),
371 1.1 christos uuid_str);
372 1.1 christos }
373 1.1 christos }
374 1.1 christos
375 1.1 christos static void
376 1.1 christos devpath_msg_uartflowctl(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
377 1.1 christos { /* See 10.3.4.17 */
378 1.1 christos struct { /* Sub-Type 10 */
379 1.1 christos devpath_t hdr; /* Length = 24 */
380 1.1 christos uuid_t GUID;
381 1.1 christos uint32_t FlowCtl;
382 1.1 christos } __packed *p = (void *)dp;
383 1.1 christos __CTASSERT(sizeof(*p) == 24);
384 1.1 christos const char *fc_str;
385 1.1 christos
386 1.1 christos switch (p->FlowCtl) {
387 1.1 christos case 0: fc_str = "None"; break;
388 1.1 christos case 1: fc_str = "Hardware"; break;
389 1.1 christos case 2: fc_str = "XonXoff"; break;
390 1.1 christos default: fc_str = "????"; break;
391 1.1 christos }
392 1.1 christos
393 1.1 christos path->sz = easprintf(&path->cp, "UartFlowCtrl(%s)", fc_str);
394 1.1 christos
395 1.1 christos if (dbg != NULL) {
396 1.1 christos char uuid_str[UUID_STR_LEN];
397 1.1 christos
398 1.1 christos uuid_snprintf(uuid_str, sizeof(uuid_str), &p->GUID);
399 1.1 christos
400 1.1 christos dbg->sz = easprintf(&dbg->cp,
401 1.1 christos DEVPATH_FMT_HDR
402 1.1 christos DEVPATH_FMT(GUID: %s\n)
403 1.1 christos DEVPATH_FMT(FlowCtl: 0x%04x(%s)\n),
404 1.1 christos DEVPATH_DAT_HDR(dp),
405 1.1 christos uuid_str,
406 1.1 christos p->FlowCtl, fc_str);
407 1.1 christos }
408 1.1 christos }
409 1.1 christos
410 1.1 christos /****************************************
411 1.1 christos * Macros for dealing with SAS/SATA device and topology info field.
412 1.1 christos */
413 1.1 christos
414 1.1 christos #define SASINFO_BYTES_MASK __BITS(3,0)
415 1.1 christos #define SASINFO_SATA_BIT __BIT(4)
416 1.1 christos #define SASINFO_EXTERNAL_BIT __BIT(5)
417 1.1 christos #define SASINFO_EXPANDER_BIT __BIT(6)
418 1.1 christos
419 1.1 christos #define SASINFO_BYTES(b) __SHIFTOUT((b), SASINFO_BYTES_MASK)
420 1.1 christos #define SASINFO_IS_SATA(b) ((b) % SASINFO_SATA_BIT)
421 1.1 christos #define SASINFO_IS_EXTERNAL(b) ((b) % SASINFO_EXTERNAL_BIT)
422 1.1 christos #define SASINFO_IS_EXPANDER(b) ((b) % SASINFO_EXPANDER_BIT)
423 1.1 christos
424 1.1 christos #define SASINFO_SASSATA(b) (SASINFO_IS_SATA(b) ? "SATA" : "SAS")
425 1.1 christos #define SASINFO_EXTERNAL(b) (SASINFO_IS_EXTERNAL(b) ? "External" : "Internal")
426 1.1 christos #define SASINFO_EXPANDER(b) (SASINFO_IS_EXPANDER(b) ? "Expander" : "direct")
427 1.1 christos
428 1.1 christos /****************************************/
429 1.1 christos
430 1.1 christos static void
431 1.1 christos devpath_msg_sas(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
432 1.1 christos { /* See 10.3.4.18 */
433 1.1 christos struct { /* Sub-Type 10 */
434 1.1 christos devpath_t hdr; /* Length = 44 */
435 1.1 christos uuid_t GUID;
436 1.1 christos uint32_t resv;
437 1.1 christos uint64_t addr; /* display as big-endian */
438 1.1 christos uint64_t LUN; /* display as big-endian */
439 1.1 christos union {
440 1.1 christos uint8_t b[2];
441 1.1 christos uint16_t val;
442 1.1 christos } __packed info; /* device/topology info */
443 1.1 christos uint16_t RTP; /* Relative Target Port */
444 1.1 christos } __packed *p = (void *)dp;
445 1.1 christos __CTASSERT(sizeof(*p) == 44);
446 1.1 christos
447 1.1 christos /*
448 1.1 christos * There seems to be a discrepency between the display
449 1.1 christos * examples in 10.3.4.18, 10.3.4.18.4, and Table 10.67. The
450 1.1 christos * first example in 10.3.4.18 also refers to a third number
451 1.1 christos * (RTP) which isn't present. I also find the info in Table
452 1.1 christos * 10.67 a bit unclear.
453 1.1 christos */
454 1.1 christos if (SASINFO_BYTES(p->info.b[0]) == 0) {
455 1.2 martin path->sz = easprintf(&path->cp, "SAS(0x%064" PRIx64
456 1.2 martin ",0x%064" PRIx64 ")",
457 1.1 christos htobe64(p->addr), htobe64(p->LUN));
458 1.1 christos }
459 1.1 christos else if (SASINFO_BYTES(p->info.b[0]) == 1) {
460 1.1 christos if (SASINFO_IS_SATA(p->info.b[0])) {
461 1.2 martin path->sz = easprintf(&path->cp, "SAS(0x%064" PRIx64
462 1.2 martin ",0x%064" PRIx64 ",SATA)",
463 1.1 christos htobe64(p->addr), htobe64(p->LUN));
464 1.1 christos }
465 1.1 christos else {
466 1.2 martin path->sz = easprintf(&path->cp, "SAS(0x%064" PRIx64
467 1.2 martin ",SAS)", htobe64(p->addr));
468 1.1 christos }
469 1.1 christos }
470 1.1 christos else {
471 1.1 christos assert(SASINFO_BYTES(p->info.b[0]) == 2);
472 1.1 christos uint drivebay = p->info.b[1] + 1;
473 1.2 martin path->sz = easprintf(&path->cp, "SAS(0x%064" PRIx64
474 1.2 martin ",0x%064" PRIx64 ",0x%04x,%s,%s,%s,%d,0x%04x)",
475 1.1 christos htobe64(p->addr), htobe64(p->LUN), p->RTP,
476 1.1 christos SASINFO_SASSATA(p->info.b[0]),
477 1.1 christos SASINFO_EXTERNAL(p->info.b[0]),
478 1.1 christos SASINFO_EXPANDER(p->info.b[0]),
479 1.1 christos drivebay,
480 1.1 christos p->resv);
481 1.1 christos }
482 1.1 christos
483 1.1 christos if (dbg != NULL) {
484 1.1 christos char uuid_str[UUID_STR_LEN];
485 1.1 christos
486 1.1 christos uuid_snprintf(uuid_str, sizeof(uuid_str), &p->GUID);
487 1.1 christos
488 1.1 christos dbg->sz = easprintf(&dbg->cp,
489 1.1 christos DEVPATH_FMT_HDR
490 1.1 christos DEVPATH_FMT(GUID: %s\n)
491 1.1 christos DEVPATH_FMT(resv: 0x%08x\n)
492 1.2 martin DEVPATH_FMT(addr:) " 0x%064" PRIx64 "(0x%064" PRIx64 ")\n"
493 1.2 martin DEVPATH_FMT(LUN:) " 0x%064" PRIx64 "(0x%064" PRIx64 ")\n"
494 1.1 christos DEVPATH_FMT(info: 0x%02x 0x%02x\n)
495 1.1 christos DEVPATH_FMT(RPT: 0x%04x\n),
496 1.1 christos DEVPATH_DAT_HDR(dp),
497 1.1 christos uuid_str,
498 1.1 christos p->resv,
499 1.1 christos p->addr, htobe64(p->addr),
500 1.1 christos p->LUN, htobe64(p->LUN),
501 1.1 christos p->info.b[0], p->info.b[1],
502 1.1 christos p->RTP);
503 1.1 christos }
504 1.1 christos }
505 1.1 christos
506 1.1 christos static struct vendor_type {
507 1.1 christos uuid_t GUID;
508 1.1 christos void(*fn)(devpath_t *, devpath_elm_t *, devpath_elm_t *);
509 1.1 christos const char *name;
510 1.1 christos } *
511 1.1 christos devpath_msg_vendor_type(uuid_t *uuid)
512 1.1 christos {
513 1.1 christos static struct vendor_type tbl[] = {
514 1.1 christos { .GUID = EFI_PC_ANSI_GUID,
515 1.1 christos .fn = NULL,
516 1.1 christos .name = "VenPcAnsi",
517 1.1 christos },
518 1.1 christos { .GUID = EFI_VT_100_GUID,
519 1.1 christos .fn = NULL,
520 1.1 christos .name = "VenVt100",
521 1.1 christos },
522 1.1 christos { .GUID = EFI_VT_100_PLUS_GUID,
523 1.1 christos .fn = NULL,
524 1.1 christos .name = "VenVt100Plus",
525 1.1 christos },
526 1.1 christos { .GUID = EFI_VT_UTF8_GUID,
527 1.1 christos .fn = NULL,
528 1.1 christos .name = "VenUtf8",
529 1.1 christos },
530 1.1 christos /********/
531 1.1 christos /* See 18.3.7 */
532 1.1 christos { .GUID = EFI_DEBUGPORT_PROTOCOL_GUID,
533 1.1 christos .fn = devpath_msg_debugport,
534 1.1 christos .name = "DebugPort",
535 1.1 christos },
536 1.1 christos /********/
537 1.1 christos /* See 10.3.4.17 */
538 1.1 christos { .GUID = DEVICE_PATH_MESSAGING_UART_FLOW_CONTROL,
539 1.1 christos .fn = devpath_msg_uartflowctl,
540 1.1 christos .name = "UartFlowCtrl",
541 1.1 christos },
542 1.1 christos /* See 10.3.4.18 */
543 1.1 christos { .GUID = EFI_VENDOR_SAS,
544 1.1 christos .fn = devpath_msg_sas,
545 1.1 christos .name = "SAS",
546 1.1 christos },
547 1.1 christos };
548 1.1 christos
549 1.1 christos for (size_t i = 0; i < __arraycount(tbl); i++) {
550 1.1 christos if (memcmp(uuid, &tbl[i].GUID, sizeof(*uuid)) == 0) {
551 1.1 christos return &tbl[i];
552 1.1 christos }
553 1.1 christos }
554 1.1 christos return NULL;
555 1.1 christos }
556 1.1 christos
557 1.1 christos static void
558 1.1 christos devpath_msg_vendor(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
559 1.1 christos { /* See 10.3.4.16 */
560 1.1 christos struct { /* Sub-Type 10 */
561 1.1 christos devpath_t hdr; /* Length = 20 + n */
562 1.1 christos uuid_t GUID;
563 1.1 christos uint8_t data[];
564 1.1 christos } __packed *p = (void *)dp;
565 1.1 christos __CTASSERT(sizeof(*p) == 20);
566 1.1 christos char uuid_str[UUID_STR_LEN];
567 1.1 christos size_t len;
568 1.1 christos struct vendor_type *vt;
569 1.1 christos char *data_str;
570 1.1 christos
571 1.1 christos uuid_snprintf(uuid_str, sizeof(uuid_str), &p->GUID);
572 1.1 christos
573 1.1 christos len = dp->Length - sizeof(*p);
574 1.1 christos data_str = encode_data(p->data, len);
575 1.1 christos
576 1.1 christos vt = devpath_msg_vendor_type(&p->GUID);
577 1.1 christos if (vt == NULL) {
578 1.1 christos path->sz = easprintf(&path->cp, "VenMsg(%s,%s)", uuid_str, data_str);
579 1.1 christos }
580 1.1 christos else if (vt->fn == NULL) {
581 1.1 christos assert(vt->name != NULL);
582 1.1 christos path->sz = easprintf(&path->cp, "%s(%s)", vt->name, data_str);
583 1.1 christos }
584 1.1 christos else {
585 1.1 christos vt->fn(dp, path, dbg);
586 1.1 christos return;
587 1.1 christos }
588 1.1 christos if (dbg != NULL) {
589 1.1 christos dbg->sz = easprintf(&dbg->cp,
590 1.1 christos DEVPATH_FMT_HDR
591 1.1 christos DEVPATH_FMT(GUID: %s\n)
592 1.1 christos DEVPATH_FMT(Data: %s\n),
593 1.1 christos DEVPATH_DAT_HDR(dp),
594 1.1 christos uuid_str,
595 1.1 christos data_str);
596 1.1 christos }
597 1.1 christos free(data_str);
598 1.1 christos }
599 1.1 christos
600 1.1 christos static void
601 1.1 christos devpath_msg_mac(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
602 1.1 christos { /* See 10.3.4.10 */
603 1.1 christos struct { /* Sub-Type 11 */
604 1.1 christos devpath_t hdr; /* Length = 37 */
605 1.1 christos uint8_t mac_addr[32];
606 1.1 christos uint8_t IfType;
607 1.1 christos } __packed *p = (void *)dp;
608 1.1 christos __CTASSERT(sizeof(*p) == 37);
609 1.1 christos size_t addr_len;
610 1.1 christos char *mac_addr;
611 1.1 christos
612 1.1 christos switch (p->IfType) {
613 1.1 christos case 0:
614 1.1 christos case 1:
615 1.1 christos addr_len = 6;
616 1.1 christos break;
617 1.1 christos default:
618 1.1 christos addr_len = 32;
619 1.1 christos break;
620 1.1 christos }
621 1.1 christos #if 0
622 1.1 christos From: RFC3232 says everything is now online, found here:
623 1.1 christos https://www.iana.org/assignments/arp-parameters/arp-parameters.xhtml
624 1.1 christos
625 1.1 christos XXX: Should we make a table so we can show a name?
626 1.1 christos
627 1.1 christos 0 Reserved [RFC5494]
628 1.1 christos 1 Ethernet (10Mb) [Jon_Postel]
629 1.1 christos 2 Experimental Ethernet (3Mb) [Jon_Postel]
630 1.1 christos 3 Amateur Radio AX.25 [Philip_Koch]
631 1.1 christos 4 Proteon ProNET Token Ring [Avri_Doria]
632 1.1 christos 5 Chaos [Gill_Pratt]
633 1.1 christos 6 IEEE 802 Networks [Jon_Postel]
634 1.1 christos 7 ARCNET [RFC1201]
635 1.1 christos 8 Hyperchannel [Jon_Postel]
636 1.1 christos 9 Lanstar [Tom_Unger]
637 1.1 christos 10 Autonet Short Address [Mike_Burrows]
638 1.1 christos 11 LocalTalk [Joyce_K_Reynolds]
639 1.1 christos 12 LocalNet (IBM PCNet or SYTEK LocalNET) [Joseph Murdock]
640 1.1 christos 13 Ultra link [Rajiv_Dhingra]
641 1.1 christos 14 SMDS [George_Clapp]
642 1.1 christos 15 Frame Relay [Andy_Malis]
643 1.1 christos 16 Asynchronous Transmission Mode (ATM) [[JXB2]]
644 1.1 christos 17 HDLC [Jon_Postel]
645 1.1 christos 18 Fibre Channel [RFC4338]
646 1.1 christos 19 Asynchronous Transmission Mode (ATM) [RFC2225]
647 1.1 christos 20 Serial Line [Jon_Postel]
648 1.1 christos 21 Asynchronous Transmission Mode (ATM) [Mike_Burrows]
649 1.1 christos 22 MIL-STD-188-220 [Herb_Jensen]
650 1.1 christos 23 Metricom [Jonathan_Stone]
651 1.1 christos 24 IEEE 1394.1995 [Myron_Hattig]
652 1.1 christos 25 MAPOS [Mitsuru_Maruyama][RFC2176]
653 1.1 christos 26 Twinaxial [Marion_Pitts]
654 1.1 christos 27 EUI-64 [Kenji_Fujisawa]
655 1.1 christos 28 HIPARP [Jean_Michel_Pittet]
656 1.1 christos 29 IP and ARP over ISO 7816-3 [Scott_Guthery]
657 1.1 christos 30 ARPSec [Jerome_Etienne]
658 1.1 christos 31 IPsec tunnel [RFC3456]
659 1.1 christos 32 InfiniBand (TM) [RFC4391]
660 1.1 christos 33 TIA-102 Project 25 Common Air Interface (CAI) [Jeff Anderson, Telecommunications Industry of America (TIA) TR-8.5 Formulating Group, <cja015&motorola.com>, June 2004]
661 1.1 christos 34 Wiegand Interface [Scott_Guthery_2]
662 1.1 christos 35 Pure IP [Inaky_Perez-Gonzalez]
663 1.1 christos 36 HW_EXP1 [RFC5494]
664 1.1 christos 37 HFI [Tseng-Hui_Lin]
665 1.1 christos 38 Unified Bus (UB) [Wei_Pan]
666 1.1 christos 39-255 Unassigned
667 1.1 christos 256 HW_EXP2 [RFC5494]
668 1.1 christos 257 AEthernet [Geoffroy_Gramaize]
669 1.1 christos 258-65534 Unassigned
670 1.1 christos 65535 Reserved [RFC5494]
671 1.1 christos #endif
672 1.1 christos
673 1.1 christos mac_addr = encode_data(p->mac_addr, addr_len);
674 1.1 christos path->sz = easprintf(&path->cp, "MAC(%s,%d)", mac_addr, p->IfType);
675 1.1 christos
676 1.1 christos if (dbg != NULL) {
677 1.1 christos dbg->sz = easprintf(&dbg->cp,
678 1.1 christos DEVPATH_FMT_HDR
679 1.1 christos DEVPATH_FMT(MAC_addr: %s\n)
680 1.1 christos DEVPATH_FMT(IfType: %x\n),
681 1.1 christos DEVPATH_DAT_HDR(dp),
682 1.1 christos mac_addr,
683 1.1 christos p->IfType);
684 1.1 christos }
685 1.1 christos free(mac_addr);
686 1.1 christos }
687 1.1 christos
688 1.1 christos static void
689 1.1 christos devpath_msg_ipv4(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
690 1.1 christos { /* See 10.3.4.11 */
691 1.1 christos struct { /* Sub-Type 12 */
692 1.1 christos devpath_t hdr; /* Length = 27 */
693 1.1 christos uint32_t LocalIPAddr;
694 1.1 christos uint32_t RemoteIPAddr;
695 1.1 christos uint16_t LocalPort;
696 1.1 christos uint16_t RemotePort;
697 1.1 christos uint16_t Protocol;
698 1.1 christos uint8_t StaticIPAddr;
699 1.1 christos uint32_t GatewayIPAddr;
700 1.1 christos uint32_t SubnetMask;
701 1.1 christos } __packed *p = (void *)dp;
702 1.1 christos __CTASSERT(sizeof(*p) == 27);
703 1.1 christos char *gaddr, *laddr, *raddr, *mask;
704 1.1 christos char *proto, *atype;
705 1.1 christos
706 1.1 christos laddr = ipv4_addr(p->LocalIPAddr);
707 1.1 christos gaddr = ipv4_addr(p->GatewayIPAddr);
708 1.1 christos raddr = ipv4_addr(p->RemoteIPAddr);
709 1.1 christos mask = ipv4_addr(p->SubnetMask);
710 1.1 christos proto = proto_name(p->Protocol);
711 1.1 christos atype = ipv4_type(p->StaticIPAddr);
712 1.1 christos
713 1.1 christos path->sz = easprintf(&path->cp, "IPv4(%s,%s,%s,%s,%s,%s)",
714 1.1 christos raddr, proto, atype, laddr, gaddr, mask);
715 1.1 christos
716 1.1 christos if (dbg != NULL) {
717 1.1 christos dbg->sz = easprintf(&dbg->cp,
718 1.1 christos DEVPATH_FMT_HDR
719 1.1 christos DEVPATH_FMT(LocalIPAddr: 0x%08x(%s)\n)
720 1.1 christos DEVPATH_FMT(RemoteIPAddr: 0x%08x(%s)\n)
721 1.1 christos DEVPATH_FMT(LocalPort: 0x%04x\n)
722 1.1 christos DEVPATH_FMT(RemotePort: 0x%04x\n)
723 1.1 christos DEVPATH_FMT(Protocol: 0x%04x(%s)\n)
724 1.1 christos DEVPATH_FMT(StaticIPAddr: 0x%02x(%s)\n)
725 1.1 christos DEVPATH_FMT(GatewayIPAddr: 0x%08x(%s)\n)
726 1.1 christos DEVPATH_FMT(SubnetMask: 0x%08x(%s)\n),
727 1.1 christos DEVPATH_DAT_HDR(dp),
728 1.1 christos p->LocalIPAddr, laddr,
729 1.1 christos p->RemoteIPAddr, raddr,
730 1.1 christos p->LocalPort,
731 1.1 christos p->RemotePort,
732 1.1 christos p->Protocol, proto,
733 1.1 christos p->StaticIPAddr, atype,
734 1.1 christos p->GatewayIPAddr, gaddr,
735 1.1 christos p->SubnetMask, mask);
736 1.1 christos }
737 1.1 christos free(atype);
738 1.1 christos free(proto);
739 1.1 christos free(mask);
740 1.1 christos free(raddr);
741 1.1 christos free(gaddr);
742 1.1 christos free(laddr);
743 1.1 christos }
744 1.1 christos
745 1.1 christos static void
746 1.1 christos devpath_msg_ipv6(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
747 1.1 christos { /* See 10.3.4.12 */
748 1.1 christos struct { /* Sub-Type 13 */
749 1.1 christos devpath_t hdr; /* Length = 60 */
750 1.1 christos struct in6_addr LocalIPAddr;
751 1.1 christos struct in6_addr RemoteIPAddr;
752 1.1 christos uint16_t LocalPort;
753 1.1 christos uint16_t RemotePort;
754 1.1 christos uint16_t Protocol;
755 1.1 christos uint8_t IPAddrOrigin;
756 1.1 christos uint8_t PrefixLength;
757 1.1 christos struct in6_addr GatewayIPAddr;
758 1.1 christos } __packed *p = (void *)dp;
759 1.1 christos __CTASSERT(sizeof(*p) == 60);
760 1.1 christos char *gaddr, *laddr, *raddr;
761 1.1 christos char *proto, *atype;
762 1.1 christos
763 1.1 christos laddr = ipv6_addr(&p->LocalIPAddr);
764 1.1 christos gaddr = ipv6_addr(&p->GatewayIPAddr);
765 1.1 christos raddr = ipv6_addr(&p->RemoteIPAddr);
766 1.1 christos proto = proto_name(p->Protocol);
767 1.1 christos atype = ipv6_type(p->IPAddrOrigin);
768 1.1 christos
769 1.1 christos path->sz = easprintf(&path->cp, "IPv6(%s,%s,%s,%s,%s)",
770 1.1 christos raddr, proto, atype, laddr, gaddr);
771 1.1 christos
772 1.1 christos if (dbg != NULL) {
773 1.1 christos dbg->sz = easprintf(&dbg->cp,
774 1.1 christos DEVPATH_FMT_HDR
775 1.1 christos DEVPATH_FMT(LocalIPAddr: %s\n)
776 1.1 christos DEVPATH_FMT(RemoteIPAddr: %s\n)
777 1.1 christos DEVPATH_FMT(LocalPort: 0x%04x\n)
778 1.1 christos DEVPATH_FMT(RemotePort: 0x%04x\n)
779 1.1 christos DEVPATH_FMT(Protocol: 0x%04x(%s)\n)
780 1.1 christos DEVPATH_FMT(IPAddrOrigin: 0x%02x(%s)\n)
781 1.1 christos DEVPATH_FMT(PrefixLength: 0x%02x\n)
782 1.1 christos DEVPATH_FMT(GatewayIPAddr: %s\n),
783 1.1 christos DEVPATH_DAT_HDR(dp),
784 1.1 christos laddr,
785 1.1 christos raddr,
786 1.1 christos p->LocalPort,
787 1.1 christos p->RemotePort,
788 1.1 christos p->Protocol, proto,
789 1.1 christos p->IPAddrOrigin, atype,
790 1.1 christos p->PrefixLength,
791 1.1 christos gaddr);
792 1.1 christos }
793 1.1 christos free(atype);
794 1.1 christos free(proto);
795 1.1 christos free(raddr);
796 1.1 christos free(gaddr);
797 1.1 christos free(laddr);
798 1.1 christos }
799 1.1 christos
800 1.1 christos static inline const char *
801 1.1 christos uart_parity(uint8_t n)
802 1.1 christos {
803 1.1 christos
804 1.1 christos switch (n) {
805 1.1 christos case 0: return "D";
806 1.1 christos case 1: return "N";
807 1.1 christos case 2: return "E";
808 1.1 christos case 3: return "O";
809 1.1 christos case 4: return "M";
810 1.1 christos case 5: return "S";
811 1.1 christos default: return "?";
812 1.1 christos }
813 1.1 christos }
814 1.1 christos
815 1.1 christos static inline const char *
816 1.1 christos uart_stopbits(uint8_t n)
817 1.1 christos {
818 1.1 christos
819 1.1 christos switch (n) {
820 1.1 christos case 0: return "D";
821 1.1 christos case 1: return "1";
822 1.1 christos case 2: return "1.5";
823 1.1 christos case 3: return "2";
824 1.1 christos default: return "?";
825 1.1 christos }
826 1.1 christos }
827 1.1 christos
828 1.1 christos static void
829 1.1 christos devpath_msg_uart(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
830 1.1 christos { /* See 10.3.4.15 */
831 1.1 christos struct { /* Sub-Type 14 */
832 1.1 christos devpath_t hdr; /* Length = 19 */
833 1.1 christos uint32_t Reserved;
834 1.1 christos uint64_t BaudRate;
835 1.1 christos uint8_t DataBits;
836 1.1 christos uint8_t Parity;
837 1.1 christos uint8_t StopBits;
838 1.1 christos } __packed *p = (void *)dp;
839 1.1 christos __CTASSERT(sizeof(*p) == 19);
840 1.1 christos const char *parity, *stopbits;
841 1.1 christos
842 1.1 christos parity = uart_parity(p->Parity);
843 1.1 christos stopbits = uart_stopbits(p->StopBits);
844 1.1 christos
845 1.2 martin path->sz = easprintf(&path->cp, "Uart(%" PRIx64 ",%u,%s,%s)",
846 1.2 martin p->BaudRate, p->DataBits, parity, stopbits);
847 1.1 christos
848 1.1 christos if (dbg != NULL) {
849 1.1 christos dbg->sz = easprintf(&dbg->cp,
850 1.1 christos DEVPATH_FMT_HDR
851 1.1 christos DEVPATH_FMT(Reserved: 0x%08x\n)
852 1.2 martin DEVPATH_FMT(BaudRate:) " 0x%016" PRIx64 "\n"
853 1.1 christos DEVPATH_FMT(DataBits: 0x%1x\n)
854 1.1 christos DEVPATH_FMT(Parity: 0x%1x(%s)\n)
855 1.1 christos DEVPATH_FMT(StopBits: 0x%1x(%s)\n),
856 1.1 christos DEVPATH_DAT_HDR(dp),
857 1.1 christos p->Reserved,
858 1.1 christos p->BaudRate,
859 1.1 christos p->DataBits,
860 1.1 christos p->Parity, parity,
861 1.1 christos p->StopBits, stopbits);
862 1.1 christos }
863 1.1 christos }
864 1.1 christos
865 1.1 christos static inline const char *
866 1.1 christos usbclass_name(uint8_t class, uint8_t subclass)
867 1.1 christos {
868 1.1 christos
869 1.1 christos switch (class) {
870 1.1 christos case 1: return "UsbAudio";
871 1.1 christos case 2: return "UsbCDCControl";
872 1.1 christos case 3: return "UsbHID";
873 1.1 christos case 6: return "UsbImage";
874 1.1 christos case 7: return "UsbPrintr";
875 1.1 christos case 8: return "UsbMassStorage";
876 1.1 christos case 9: return "UsbHub";
877 1.1 christos case 10: return "UsbCDCData";
878 1.1 christos case 11: return "UsbSmartCard";
879 1.1 christos case 14: return "UsbVideo";
880 1.1 christos case 220: return "UsbDiagnostic";
881 1.1 christos case 224: return "UsbWireless";
882 1.1 christos case 254:
883 1.1 christos switch (subclass) {
884 1.1 christos case 1: return "UsbDeviceFirmwareUpdate";
885 1.1 christos case 2: return "UsbIrdaBridge";
886 1.1 christos case 3: return "UsbTestAndMeasurement";
887 1.1 christos default: return NULL;
888 1.1 christos }
889 1.1 christos default: return NULL;
890 1.1 christos }
891 1.1 christos }
892 1.1 christos
893 1.1 christos static void
894 1.1 christos devpath_msg_usbclass(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
895 1.1 christos { /* See 10.3.4.8 */
896 1.1 christos struct { /* Sub-Type 15 */
897 1.1 christos devpath_t hdr; /* Length = 11 */
898 1.1 christos uint16_t VendorID;
899 1.1 christos uint16_t ProductID;
900 1.1 christos uint8_t DeviceClass;
901 1.1 christos uint8_t DeviceSubClass;
902 1.1 christos uint8_t DeviceProtocol;
903 1.1 christos } __packed *p = (void *)dp;
904 1.1 christos __CTASSERT(sizeof(*p) == 11);
905 1.1 christos const char *name;
906 1.1 christos
907 1.1 christos name = usbclass_name(p->DeviceClass, p->DeviceSubClass);
908 1.1 christos if (name == NULL) {
909 1.1 christos path->sz = easprintf(&path->cp, "UsbClass(0x%04x,0x%04x,0x%02x,0x%02x,0x%02x,)",
910 1.1 christos p->VendorID, p->ProductID, p->DeviceClass,
911 1.1 christos p->DeviceSubClass, p->DeviceProtocol);
912 1.1 christos }
913 1.1 christos else if (p->DeviceClass != 254) {
914 1.1 christos path->sz = easprintf(&path->cp, "%s(0x%04x,0x%04x,0x%02x,0x%02x,)",
915 1.1 christos name, p->VendorID, p->ProductID, p->DeviceSubClass, p->DeviceProtocol);
916 1.1 christos }
917 1.1 christos else {
918 1.1 christos path->sz = easprintf(&path->cp, "%s(0x%04x,0x%04x,0x%02x,)",
919 1.1 christos name, p->VendorID, p->ProductID, p->DeviceProtocol);
920 1.1 christos }
921 1.1 christos
922 1.1 christos if (dbg != NULL) {
923 1.1 christos dbg->sz = easprintf(&dbg->cp,
924 1.1 christos DEVPATH_FMT_HDR
925 1.1 christos DEVPATH_FMT(VendorID: 0x%04x\n)
926 1.1 christos DEVPATH_FMT(ProductID: 0x%04x\n)
927 1.1 christos DEVPATH_FMT(DeviceClass: 0x%02x(%u)\n)
928 1.1 christos DEVPATH_FMT(DeviceSubClass: 0x%02x(%u)\n)
929 1.1 christos DEVPATH_FMT(DeviceProtocol: 0x%02x(%u)\n),
930 1.1 christos DEVPATH_DAT_HDR(dp),
931 1.1 christos p->VendorID,
932 1.1 christos p->ProductID,
933 1.1 christos p->DeviceClass, p->DeviceClass,
934 1.1 christos p->DeviceSubClass, p->DeviceSubClass,
935 1.1 christos p->DeviceProtocol, p->DeviceProtocol);
936 1.1 christos }
937 1.1 christos }
938 1.1 christos
939 1.1 christos static void
940 1.1 christos devpath_msg_usbwwid(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
941 1.1 christos { /* See 10.3.4.7 */
942 1.1 christos struct { /* Sub-Type 16 */
943 1.1 christos devpath_t hdr; /* Length = 10 + n */
944 1.1 christos uint16_t IFaceNum;
945 1.1 christos uint16_t VendorID;
946 1.1 christos uint16_t ProductID;
947 1.1 christos uint8_t SerialNum[];
948 1.1 christos } __packed *p = (void *)dp;
949 1.1 christos __CTASSERT(sizeof(*p) == 10);
950 1.1 christos char *serialnum;
951 1.1 christos size_t seriallen;
952 1.1 christos
953 1.1 christos seriallen = p->hdr.Length - offsetof(typeof(*p), SerialNum);
954 1.1 christos if (seriallen == 0) {
955 1.1 christos serialnum = __UNCONST("WWID"); /* XXX: This is an error! */
956 1.1 christos assert(0);
957 1.1 christos }
958 1.1 christos else {
959 1.1 christos size_t sz = p->hdr.Length - sizeof(*p);
960 1.1 christos serialnum = ucs2_to_utf8((uint16_t *)p->SerialNum, sz, NULL, NULL);
961 1.1 christos }
962 1.1 christos
963 1.1 christos path->sz = easprintf(&path->cp, "UsbWwid(0x%04x,0x%04x,0x%02x,%s)",
964 1.1 christos p->VendorID, p->ProductID, p->IFaceNum, serialnum);
965 1.1 christos
966 1.1 christos if (dbg != NULL) {
967 1.1 christos dbg->sz = easprintf(&dbg->cp,
968 1.1 christos DEVPATH_FMT_HDR
969 1.1 christos DEVPATH_FMT(IFaceNum: 0x%04x\n)
970 1.1 christos DEVPATH_FMT(VendorID: 0x%04x\n)
971 1.1 christos DEVPATH_FMT(ProductID: 0x%04x\n)
972 1.1 christos DEVPATH_FMT(SerialNum: %s\n),
973 1.1 christos DEVPATH_DAT_HDR(dp),
974 1.1 christos p->IFaceNum, p->VendorID, p->ProductID, serialnum);
975 1.1 christos }
976 1.1 christos
977 1.1 christos if (seriallen)
978 1.1 christos free(serialnum);
979 1.1 christos }
980 1.1 christos
981 1.1 christos static void
982 1.1 christos devpath_msg_unit(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
983 1.1 christos { /* See 10.3.4.8 */
984 1.1 christos struct { /* Sub-Type 17 */
985 1.1 christos devpath_t hdr; /* Length = 5 */
986 1.1 christos uint8_t LUN;
987 1.1 christos } __packed *p = (void *)dp;
988 1.1 christos __CTASSERT(sizeof(*p) == 5);
989 1.1 christos
990 1.1 christos path->sz = easprintf(&path->cp, "Unit(%u)", p->LUN);
991 1.1 christos
992 1.1 christos if (dbg != NULL) {
993 1.1 christos dbg->sz = easprintf(&dbg->cp,
994 1.1 christos DEVPATH_FMT_HDR
995 1.1 christos DEVPATH_FMT(LUN: %u\n),
996 1.1 christos DEVPATH_DAT_HDR(dp),
997 1.1 christos p->LUN);
998 1.1 christos }
999 1.1 christos }
1000 1.1 christos
1001 1.1 christos static void
1002 1.1 christos devpath_msg_sata(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
1003 1.1 christos { /* See 10.3.4.6 */
1004 1.1 christos struct { /* Sub-Type 18 */
1005 1.1 christos devpath_t hdr; /* Length = 10 */
1006 1.1 christos uint16_t SATAHBAPortNum;
1007 1.1 christos uint16_t SATAPortMultiplierPortNum;
1008 1.1 christos uint16_t SATALogicalUnitNum;
1009 1.1 christos } __packed *p = (void *)dp;
1010 1.1 christos __CTASSERT(sizeof(*p) == 10);
1011 1.1 christos
1012 1.1 christos path->sz = easprintf(&path->cp, "SATA(%u,%u,%u)", p->SATAHBAPortNum,
1013 1.1 christos p->SATAPortMultiplierPortNum, p->SATALogicalUnitNum);
1014 1.1 christos
1015 1.1 christos if (dbg != NULL) {
1016 1.1 christos dbg->sz = easprintf(&dbg->cp,
1017 1.1 christos DEVPATH_FMT_HDR
1018 1.1 christos DEVPATH_FMT(SATAHBAPortNum: %u\n)
1019 1.1 christos DEVPATH_FMT(SATAPortMultiplierPortNum: %u\n)
1020 1.1 christos DEVPATH_FMT(SATALogicalUnitNum: %u\n),
1021 1.1 christos DEVPATH_DAT_HDR(dp),
1022 1.1 christos p->SATAHBAPortNum,
1023 1.1 christos p->SATAPortMultiplierPortNum,
1024 1.1 christos p->SATALogicalUnitNum);
1025 1.1 christos }
1026 1.1 christos }
1027 1.1 christos
1028 1.1 christos static inline const char *
1029 1.1 christos hdrdgst_name(uint16_t LoginOptions)
1030 1.1 christos {
1031 1.1 christos
1032 1.1 christos switch (__SHIFTOUT(LoginOptions, __BITS(1,0))) {
1033 1.1 christos case 0: return "None";
1034 1.1 christos case 2: return "CRC32C";
1035 1.1 christos default: return "???";
1036 1.1 christos }
1037 1.1 christos }
1038 1.1 christos
1039 1.1 christos static inline const char *
1040 1.1 christos datdgst_name(uint16_t LoginOptions)
1041 1.1 christos {
1042 1.1 christos
1043 1.1 christos switch (__SHIFTOUT(LoginOptions, __BITS(3,2))) {
1044 1.1 christos case 0: return "None";
1045 1.1 christos case 2: return "CRC32C";
1046 1.1 christos default: return "???";
1047 1.1 christos }
1048 1.1 christos }
1049 1.1 christos
1050 1.1 christos
1051 1.1 christos static inline const char *
1052 1.1 christos auth_name(uint16_t LoginOptions)
1053 1.1 christos {
1054 1.1 christos
1055 1.1 christos switch (__SHIFTOUT(LoginOptions, __BITS(12,10))) {
1056 1.1 christos case 0: return "CHAP_BI";
1057 1.1 christos case 2: return "None";
1058 1.1 christos case 4: return "CHAP_UNI";
1059 1.1 christos default: return "???";
1060 1.1 christos }
1061 1.1 christos }
1062 1.1 christos
1063 1.1 christos static inline const char *
1064 1.1 christos protocol_name(uint16_t Protocol)
1065 1.1 christos {
1066 1.1 christos
1067 1.1 christos return Protocol == 0 ? "TCP" : "RSVD";
1068 1.1 christos }
1069 1.1 christos
1070 1.1 christos static void
1071 1.1 christos devpath_msg_iscsi(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
1072 1.1 christos { /* See 10.3.4.20 */
1073 1.1 christos #define LOGIN_OPTION_BITS \
1074 1.1 christos "\177\020" \
1075 1.1 christos "f\0\2""HdrDgst\0" \
1076 1.1 christos "=\x0""None\0" \
1077 1.1 christos "=\x2""CRC32C\0" \
1078 1.1 christos "f\x2\x2""DatDgst\0" \
1079 1.1 christos "=\x0""None\0" \
1080 1.1 christos "=\x2""CRC32C\0" \
1081 1.1 christos "f\xA\x3""Auth\0" \
1082 1.1 christos "=\x0""CHAP_BI\0" \
1083 1.1 christos "=\x2""None\0" \
1084 1.1 christos "=\x4""CHAP_UNI\0"
1085 1.1 christos struct { /* Sub-Type 19 */
1086 1.1 christos devpath_t hdr; /* Length = 18 + n */
1087 1.1 christos uint16_t Protocol;
1088 1.1 christos uint16_t LoginOptions;
1089 1.1 christos uint64_t LUN; /* display as big-endian */
1090 1.1 christos uint16_t TargetPortalGrp;
1091 1.1 christos char TargetName[];
1092 1.1 christos } __packed *p = (void *)dp;
1093 1.1 christos __CTASSERT(sizeof(*p) == 18);
1094 1.1 christos char *name;
1095 1.1 christos const char *auth, *datdgst, *hdrdgst, *proto;
1096 1.1 christos size_t len;
1097 1.1 christos
1098 1.1 christos /*
1099 1.1 christos * Make sure the TargetName is NUL terminated. The spec is
1100 1.1 christos * unclear on this, though their example is asciiz. I have
1101 1.1 christos * no real examples to test, so be safe.
1102 1.1 christos */
1103 1.1 christos len = p->hdr.Length - sizeof(*p);
1104 1.1 christos name = emalloc(len + 1);
1105 1.1 christos memcpy(name, p->TargetName, len);
1106 1.1 christos name[len] = '\0';
1107 1.1 christos
1108 1.1 christos auth = auth_name(p->LoginOptions);
1109 1.1 christos datdgst = datdgst_name(p->LoginOptions);
1110 1.1 christos hdrdgst = hdrdgst_name(p->LoginOptions);
1111 1.1 christos proto = protocol_name(p->Protocol);
1112 1.1 christos
1113 1.2 martin path->sz = easprintf(&path->cp, "iSCSI(%s,0x%04x,0x%064" PRIx64
1114 1.2 martin ",%s,%s,%s,%s)", p->TargetName, p->TargetPortalGrp,
1115 1.1 christos htobe64(p->LUN), hdrdgst, datdgst, auth, proto);
1116 1.1 christos
1117 1.1 christos if (dbg != NULL) {
1118 1.1 christos char liopt[256];
1119 1.1 christos
1120 1.1 christos snprintb(liopt, sizeof(liopt), LOGIN_OPTION_BITS, p->LoginOptions);
1121 1.1 christos dbg->sz = easprintf(&dbg->cp,
1122 1.1 christos DEVPATH_FMT_HDR
1123 1.1 christos DEVPATH_FMT(Protocol: 0x%04x(%s)\n)
1124 1.1 christos DEVPATH_FMT(LoginOptions: %s\n)
1125 1.2 martin DEVPATH_FMT(LUN:) " 0x%064" PRIx64 "\n"
1126 1.1 christos DEVPATH_FMT(TargetPortalGrp: 0x%04x\n)
1127 1.1 christos DEVPATH_FMT(TargetName: %s\n),
1128 1.1 christos DEVPATH_DAT_HDR(dp),
1129 1.1 christos p->Protocol, proto,
1130 1.1 christos liopt,
1131 1.1 christos htobe64(p->LUN),
1132 1.1 christos p->TargetPortalGrp,
1133 1.1 christos name);
1134 1.1 christos }
1135 1.1 christos
1136 1.1 christos free(name);
1137 1.1 christos }
1138 1.1 christos
1139 1.1 christos static void
1140 1.1 christos devpath_msg_vlan(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
1141 1.1 christos { /* See 10.3.4.13 */
1142 1.1 christos struct { /* Sub-Type 20 */
1143 1.1 christos devpath_t hdr; /* Length = 6 */
1144 1.1 christos uint16_t Vlanid;
1145 1.1 christos } __packed *p = (void *)dp;
1146 1.1 christos __CTASSERT(sizeof(*p) == 6);
1147 1.1 christos
1148 1.1 christos path->sz = easprintf(&path->cp, "Vlan(0x%04x)", p->Vlanid);
1149 1.1 christos
1150 1.1 christos if (dbg != NULL) {
1151 1.1 christos dbg->sz = easprintf(&dbg->cp,
1152 1.1 christos DEVPATH_FMT_HDR
1153 1.1 christos DEVPATH_FMT(Vlanid: 0x%04x\n),
1154 1.1 christos DEVPATH_DAT_HDR(dp),
1155 1.1 christos p->Vlanid);
1156 1.1 christos }
1157 1.1 christos }
1158 1.1 christos
1159 1.1 christos static void
1160 1.1 christos devpath_msg_fibreex(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
1161 1.1 christos { /* See 10.3.4.3 */
1162 1.1 christos struct { /* Sub-Type 21 */
1163 1.1 christos devpath_t hdr; /* Length = 24 */
1164 1.1 christos uint32_t Reserved;
1165 1.1 christos uint64_t WorldWideName; /* bit-endian */
1166 1.1 christos uint64_t LUN; /* bit-endian */
1167 1.1 christos } __packed *p = (void *)dp;
1168 1.1 christos __CTASSERT(sizeof(*p) == 24);
1169 1.1 christos
1170 1.2 martin path->sz = easprintf(&path->cp, "FibreEx(0x%064" PRIx64 ",0x%064"
1171 1.2 martin PRIx64 ")", htobe64(p->WorldWideName), htobe64(p->LUN));
1172 1.1 christos
1173 1.1 christos if (dbg != NULL) {
1174 1.1 christos dbg->sz = easprintf(&dbg->cp,
1175 1.1 christos DEVPATH_FMT_HDR
1176 1.2 martin DEVPATH_FMT(WorldWideName:) " 0x%064" PRIx64 "\n"
1177 1.2 martin DEVPATH_FMT(LUN:) " 0x%064" PRIx64 "\n",
1178 1.1 christos DEVPATH_DAT_HDR(dp),
1179 1.1 christos htobe64(p->WorldWideName),
1180 1.1 christos htobe64(p->LUN));
1181 1.1 christos }
1182 1.1 christos }
1183 1.1 christos
1184 1.1 christos static void
1185 1.1 christos devpath_msg_sasex(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
1186 1.1 christos { /* See 10.3.4.18 */
1187 1.1 christos struct { /* Sub-Type 22 */
1188 1.1 christos devpath_t hdr; /* Length = 24 XXX: 32 in text */
1189 1.1 christos uint64_t addr; /* display as big-endian */
1190 1.1 christos uint64_t LUN; /* display as big-endian */
1191 1.1 christos union {
1192 1.1 christos uint8_t b[2];
1193 1.1 christos uint16_t val;
1194 1.1 christos } __packed info; /* device/topology info */
1195 1.1 christos uint16_t RTP; /* Relative Target Port */
1196 1.1 christos } __packed *p = (void *)dp;
1197 1.1 christos __CTASSERT(sizeof(*p) == 24);
1198 1.1 christos
1199 1.1 christos /*
1200 1.1 christos * XXX: This should match what is in devpath_msg_sas().
1201 1.1 christos * Should we share code?
1202 1.1 christos */
1203 1.1 christos if (SASINFO_BYTES(p->info.b[0]) == 0) {
1204 1.2 martin path->sz = easprintf(&path->cp, "SasEx(0x%064" PRIx64
1205 1.2 martin ",0x%064" PRIx64 ")",
1206 1.1 christos htobe64(p->addr), htobe64(p->LUN));
1207 1.1 christos }
1208 1.1 christos else if (SASINFO_BYTES(p->info.b[0]) == 1) {
1209 1.1 christos if (SASINFO_IS_SATA(p->info.b[0])) {
1210 1.2 martin path->sz = easprintf(&path->cp, "SasEx(0x%064" PRIx64
1211 1.2 martin ",0x%064" PRIx64 ",SATA)",
1212 1.1 christos htobe64(p->addr), htobe64(p->LUN));
1213 1.1 christos }
1214 1.1 christos else {
1215 1.2 martin path->sz = easprintf(&path->cp, "SasEx(0x%064" PRIx64
1216 1.2 martin ",SAS)", htobe64(p->addr));
1217 1.1 christos }
1218 1.1 christos }
1219 1.1 christos else {
1220 1.1 christos assert(SASINFO_BYTES(p->info.b[0]) == 2);
1221 1.1 christos uint drivebay = p->info.b[1] + 1;
1222 1.2 martin path->sz = easprintf(&path->cp, "SasEx(0x%064" PRIx64
1223 1.2 martin ",0x%064" PRIx64 ",0x%04x,%s,%s,%s,%d)",
1224 1.1 christos htobe64(p->addr), htobe64(p->LUN), p->RTP,
1225 1.1 christos SASINFO_SASSATA(p->info.b[0]),
1226 1.1 christos SASINFO_EXTERNAL(p->info.b[0]),
1227 1.1 christos SASINFO_EXPANDER(p->info.b[0]),
1228 1.1 christos drivebay);
1229 1.1 christos }
1230 1.1 christos
1231 1.1 christos if (dbg != NULL) {
1232 1.1 christos dbg->sz = easprintf(&dbg->cp,
1233 1.1 christos DEVPATH_FMT_HDR
1234 1.2 martin DEVPATH_FMT(addr:) " 0x%064" PRIx64 "(0x%064" PRIx64 ")\n"
1235 1.2 martin DEVPATH_FMT(LUN:) " 0x%064" PRIx64 "(0x%064" PRIx64 ")\n"
1236 1.1 christos DEVPATH_FMT(info: 0x%02x 0x%02x\n)
1237 1.1 christos DEVPATH_FMT(RPT: 0x%04x\n),
1238 1.1 christos DEVPATH_DAT_HDR(dp),
1239 1.1 christos p->addr, htobe64(p->addr),
1240 1.1 christos p->LUN, htobe64(p->LUN),
1241 1.1 christos p->info.b[0], p->info.b[1],
1242 1.1 christos p->RTP);
1243 1.1 christos }
1244 1.1 christos }
1245 1.1 christos
1246 1.1 christos static void
1247 1.1 christos devpath_msg_nvme(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
1248 1.1 christos { /* See 10.3.4.21 */
1249 1.1 christos struct { /* Sub-Type 23 */
1250 1.1 christos devpath_t hdr; /* Length = 16 */
1251 1.1 christos uint32_t NSID; /* Name Space Identifier */
1252 1.1 christos union {
1253 1.1 christos uint8_t b[8];
1254 1.1 christos uint64_t val;
1255 1.1 christos } EUI; /* IEEE Extended Unique Identifier */
1256 1.1 christos } __packed *p = (void *)dp;
1257 1.1 christos __CTASSERT(sizeof(*p) == 16);
1258 1.1 christos
1259 1.1 christos path->sz = easprintf(&path->cp, "NVMe(0x%x,"
1260 1.1 christos "%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X)",
1261 1.1 christos p->NSID,
1262 1.1 christos p->EUI.b[0], p->EUI.b[1], p->EUI.b[2], p->EUI.b[3],
1263 1.1 christos p->EUI.b[4], p->EUI.b[5], p->EUI.b[6], p->EUI.b[7]);
1264 1.1 christos
1265 1.1 christos if (dbg != NULL) {
1266 1.1 christos dbg->sz = easprintf(&dbg->cp,
1267 1.1 christos DEVPATH_FMT_HDR
1268 1.1 christos DEVPATH_FMT(NSID: 0x%08x\n)
1269 1.2 martin DEVPATH_FMT(EUI:) " 0x%016" PRIx64 "\n",
1270 1.1 christos DEVPATH_DAT_HDR(dp),
1271 1.1 christos p->NSID, p->EUI.val);
1272 1.1 christos }
1273 1.1 christos }
1274 1.1 christos
1275 1.1 christos
1276 1.1 christos static void
1277 1.1 christos devpath_msg_uri(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
1278 1.1 christos { /* See 10.3.4.22 */
1279 1.1 christos struct { /* Sub-Type 24 */
1280 1.1 christos devpath_t hdr; /* Length = 4 + n */
1281 1.1 christos uint8_t data[];
1282 1.1 christos } __packed *p = (void *)dp;
1283 1.1 christos __CTASSERT(sizeof(*p) == 4);
1284 1.1 christos size_t len;
1285 1.1 christos char *buf;
1286 1.1 christos
1287 1.1 christos len = dp->Length - 4;
1288 1.1 christos
1289 1.1 christos buf = emalloc(len + 1);
1290 1.1 christos if (len > 0)
1291 1.1 christos memcpy(buf, p->data, len);
1292 1.1 christos buf[len] = '\0';
1293 1.1 christos
1294 1.1 christos path->sz = easprintf(&path->cp, "Uri(%s)", buf);
1295 1.1 christos
1296 1.1 christos if (dbg != NULL) {
1297 1.1 christos dbg->sz = easprintf(&dbg->cp,
1298 1.1 christos DEVPATH_FMT_HDR
1299 1.1 christos DEVPATH_FMT(Data: %s\n),
1300 1.1 christos DEVPATH_DAT_HDR(dp),
1301 1.1 christos buf);
1302 1.1 christos }
1303 1.1 christos free(buf);
1304 1.1 christos }
1305 1.1 christos
1306 1.1 christos static void
1307 1.1 christos devpath_msg_ufs(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
1308 1.1 christos { /* See 10.3.4.23 */
1309 1.1 christos struct { /* Sub-Type 25 */
1310 1.1 christos devpath_t hdr; /* Length = 6 */
1311 1.1 christos uint8_t PUN; /* Target ID */
1312 1.1 christos uint8_t LUN; /* Logical Unit Number */
1313 1.1 christos } __packed *p = (void *)dp;
1314 1.1 christos __CTASSERT(sizeof(*p) == 6);
1315 1.1 christos
1316 1.1 christos path->sz = easprintf(&path->cp, "UFS(%#x,0x%02x)", p->PUN, p->LUN);
1317 1.1 christos
1318 1.1 christos if (dbg != NULL) {
1319 1.1 christos dbg->sz = easprintf(&dbg->cp,
1320 1.1 christos DEVPATH_FMT_HDR
1321 1.1 christos DEVPATH_FMT(PUN: 0x%02x\n)
1322 1.1 christos DEVPATH_FMT(LUN: 0x%02x\n),
1323 1.1 christos DEVPATH_DAT_HDR(dp),
1324 1.1 christos p->PUN, p->LUN);
1325 1.1 christos }
1326 1.1 christos }
1327 1.1 christos
1328 1.1 christos static void
1329 1.1 christos devpath_msg_sd(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
1330 1.1 christos { /* See 10.3.4.24 */
1331 1.1 christos struct { /* Sub-Type 26 */
1332 1.1 christos devpath_t hdr; /* Length = 5 */
1333 1.1 christos uint8_t SlotNum;
1334 1.1 christos } __packed *p = (void *)dp;
1335 1.1 christos __CTASSERT(sizeof(*p) == 5);
1336 1.1 christos
1337 1.1 christos path->sz = easprintf(&path->cp, "SD(%d)", p->SlotNum);
1338 1.1 christos
1339 1.1 christos if (dbg != NULL) {
1340 1.1 christos dbg->sz = easprintf(&dbg->cp,
1341 1.1 christos DEVPATH_FMT_HDR
1342 1.1 christos DEVPATH_FMT(SlotNum: 0x%02x\n),
1343 1.1 christos DEVPATH_DAT_HDR(dp),
1344 1.1 christos p->SlotNum);
1345 1.1 christos }
1346 1.1 christos }
1347 1.1 christos
1348 1.1 christos static void
1349 1.1 christos devpath_msg_bluetooth(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
1350 1.1 christos { /* See 10.3.4.25 */
1351 1.1 christos struct { /* Sub-Type 27 */
1352 1.1 christos devpath_t hdr; /* Length = 10 */
1353 1.1 christos uint8_t bdaddr[6];
1354 1.1 christos } __packed *p = (void *)dp;
1355 1.1 christos __CTASSERT(sizeof(*p) == 10);
1356 1.1 christos
1357 1.1 christos path->sz = easprintf(&path->cp, "Bluetooth(%02x:%02x:%02x:%02x:%02x:%02x)",
1358 1.1 christos p->bdaddr[0], p->bdaddr[1], p->bdaddr[2],
1359 1.1 christos p->bdaddr[3], p->bdaddr[4], p->bdaddr[5]);
1360 1.1 christos
1361 1.1 christos if (dbg != NULL) {
1362 1.1 christos dbg->sz = easprintf(&dbg->cp,
1363 1.1 christos DEVPATH_FMT_HDR
1364 1.1 christos DEVPATH_FMT(bdaddr: 0x%02x%02x%02x%02x%02x%02x\n),
1365 1.1 christos DEVPATH_DAT_HDR(dp),
1366 1.1 christos p->bdaddr[0], p->bdaddr[1], p->bdaddr[2],
1367 1.1 christos p->bdaddr[3], p->bdaddr[4], p->bdaddr[5]);
1368 1.1 christos }
1369 1.1 christos }
1370 1.1 christos
1371 1.1 christos static void
1372 1.1 christos devpath_msg_wifi(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
1373 1.1 christos { /* See 10.3.4.26 */
1374 1.1 christos struct { /* Sub-Type 28 */
1375 1.1 christos devpath_t hdr; /* Length = 36 */
1376 1.1 christos char SSID[32];/* XXX: ascii? */
1377 1.1 christos } __packed *p = (void *)dp;
1378 1.1 christos __CTASSERT(sizeof(*p) == 36);
1379 1.1 christos
1380 1.1 christos path->sz = easprintf(&path->cp, "Wi-Fi(%s)", p->SSID);
1381 1.1 christos
1382 1.1 christos if (dbg != NULL) {
1383 1.1 christos char *ssid;
1384 1.1 christos
1385 1.1 christos ssid = encode_data((uint8_t *)p->SSID, sizeof(p->SSID));
1386 1.1 christos dbg->sz = easprintf(&dbg->cp,
1387 1.1 christos DEVPATH_FMT_HDR
1388 1.1 christos DEVPATH_FMT(SSID: %s\n),
1389 1.1 christos DEVPATH_DAT_HDR(dp),
1390 1.1 christos ssid);
1391 1.1 christos free(ssid);
1392 1.1 christos }
1393 1.1 christos }
1394 1.1 christos
1395 1.1 christos static void
1396 1.1 christos devpath_msg_emmc(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
1397 1.1 christos { /* See 10.3.4.27 */
1398 1.1 christos struct { /* Sub-Type 29 */
1399 1.1 christos devpath_t hdr; /* Length = 5 */
1400 1.1 christos uint8_t SlotNum;
1401 1.1 christos } __packed *p = (void *)dp;
1402 1.1 christos __CTASSERT(sizeof(*p) == 5);
1403 1.1 christos
1404 1.1 christos path->sz = easprintf(&path->cp, "eMMC(%d)", p->SlotNum);
1405 1.1 christos
1406 1.1 christos if (dbg != NULL) {
1407 1.1 christos dbg->sz = easprintf(&dbg->cp,
1408 1.1 christos DEVPATH_FMT_HDR
1409 1.1 christos DEVPATH_FMT(SlotNum: 0x%02x\n),
1410 1.1 christos DEVPATH_DAT_HDR(dp),
1411 1.1 christos p->SlotNum);
1412 1.1 christos }
1413 1.1 christos }
1414 1.1 christos
1415 1.1 christos static void
1416 1.1 christos devpath_msg_bluetoothle(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
1417 1.1 christos { /* See 10.3.4.28 */
1418 1.1 christos struct { /* Sub-Type 30 */
1419 1.1 christos devpath_t hdr; /* Length = 11 */
1420 1.1 christos uint8_t bdaddr[6];
1421 1.1 christos uint8_t addr_type;
1422 1.1 christos #define BDADDR_TYPE_PUBLIC 0
1423 1.1 christos #define BDADDR_TYPE_RANDOM 1
1424 1.1 christos } __packed *p = (void *)dp;
1425 1.1 christos __CTASSERT(sizeof(*p) == 11);
1426 1.1 christos
1427 1.1 christos path->sz = easprintf(&path->cp, "BluetoothLE(%02x:%02x:%02x:%02x:%02x:%02x,%d)",
1428 1.1 christos p->bdaddr[0], p->bdaddr[1], p->bdaddr[2],
1429 1.1 christos p->bdaddr[3], p->bdaddr[4], p->bdaddr[5],
1430 1.1 christos p->addr_type);
1431 1.1 christos
1432 1.1 christos if (dbg != NULL) {
1433 1.1 christos dbg->sz = easprintf(&dbg->cp,
1434 1.1 christos DEVPATH_FMT_HDR
1435 1.1 christos DEVPATH_FMT(bdaddr: 0x%02x%02x%02x%02x%02x%02x\n)
1436 1.1 christos DEVPATH_FMT(addr_type: 0x%02x\n),
1437 1.1 christos DEVPATH_DAT_HDR(dp),
1438 1.1 christos p->bdaddr[0], p->bdaddr[1], p->bdaddr[2],
1439 1.1 christos p->bdaddr[3], p->bdaddr[4], p->bdaddr[5],
1440 1.1 christos p->addr_type);
1441 1.1 christos }
1442 1.1 christos }
1443 1.1 christos
1444 1.1 christos static void
1445 1.1 christos devpath_msg_dns(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
1446 1.1 christos { /* See 10.3.4.29 */
1447 1.1 christos struct { /* Sub-Type 31 */
1448 1.1 christos devpath_t hdr; /* Length = 5 + n */
1449 1.1 christos uint8_t IsIPv6;
1450 1.1 christos uint8_t addr[];
1451 1.1 christos } __packed *p = (void *)dp;
1452 1.1 christos __CTASSERT(sizeof(*p) == 5);
1453 1.1 christos size_t cnt, n, sz;
1454 1.1 christos
1455 1.1 christos /* XXX: This is ugly at best */
1456 1.1 christos
1457 1.1 christos n = p->hdr.Length - sizeof(*p);
1458 1.1 christos sz = p->IsIPv6 ? sizeof(struct in6_addr) : sizeof(uint32_t);
1459 1.1 christos cnt = n / sz;
1460 1.1 christos assert(n == cnt * sz);
1461 1.1 christos assert(cnt > 0);
1462 1.1 christos
1463 1.1 christos if (cnt > 0) { /* XXX: should always be true */
1464 1.1 christos char *bp;
1465 1.1 christos
1466 1.1 christos #define DNS_PREFIX "Dns("
1467 1.1 christos if (p->IsIPv6) {
1468 1.1 christos struct in6_addr *ip6addr = (void *)p->addr;
1469 1.1 christos
1470 1.1 christos bp = path->cp = malloc(sizeof(DNS_PREFIX) +
1471 1.1 christos cnt * INET6_ADDRSTRLEN);
1472 1.1 christos bp = stpcpy(bp, DNS_PREFIX);
1473 1.1 christos bp = stpcpy(bp, ipv6_addr(&ip6addr[0]));
1474 1.1 christos for (size_t i = 1; i < cnt; i++) {
1475 1.1 christos *bp++ = ',';
1476 1.1 christos bp = stpcpy(bp, ipv6_addr(&ip6addr[i]));
1477 1.1 christos }
1478 1.1 christos *bp = ')';
1479 1.1 christos }
1480 1.1 christos else { /* IPv4 */
1481 1.1 christos uint32_t *ip4addr = (void *)p->addr;
1482 1.1 christos
1483 1.1 christos bp = path->cp = malloc(sizeof(DNS_PREFIX) +
1484 1.1 christos cnt * INET_ADDRSTRLEN);
1485 1.1 christos bp = stpcpy(bp, DNS_PREFIX);
1486 1.1 christos bp = stpcpy(bp, ipv4_addr(ip4addr[0]));
1487 1.1 christos for (size_t i = 1; i < cnt; i++) {
1488 1.1 christos *bp++ = ',';
1489 1.1 christos bp = stpcpy(bp, ipv4_addr(ip4addr[i]));
1490 1.1 christos }
1491 1.1 christos *bp = ')';
1492 1.1 christos }
1493 1.1 christos #undef DNS_PREFIX
1494 1.1 christos path->sz = strlen(bp);
1495 1.1 christos }
1496 1.1 christos
1497 1.1 christos if (dbg != NULL) {
1498 1.1 christos dbg->sz = easprintf(&dbg->cp,
1499 1.1 christos DEVPATH_FMT_HDR
1500 1.1 christos DEVPATH_FMT(IsIPv6: %d\n),
1501 1.1 christos DEVPATH_DAT_HDR(dp),
1502 1.1 christos p->IsIPv6);
1503 1.1 christos
1504 1.1 christos if (cnt > 0) { /* XXX: should always be true */
1505 1.1 christos char *bp, *tp;
1506 1.1 christos
1507 1.1 christos bp = dbg->cp;
1508 1.1 christos if (p->IsIPv6) {
1509 1.1 christos struct in6_addr *ip6addr = (void *)p->addr;
1510 1.1 christos
1511 1.1 christos for (size_t i = 0; i < cnt; i++) {
1512 1.1 christos uint8_t *cp;
1513 1.1 christos
1514 1.1 christos cp = ip6addr[i].__u6_addr.__u6_addr8;
1515 1.1 christos tp = bp;
1516 1.1 christos dbg->sz += easprintf(&bp,
1517 1.1 christos "%s"
1518 1.2 martin DEVPATH_FMT(addr[%zu]:)
1519 1.1 christos " %02x %02x %02x %02x"
1520 1.1 christos " %02x %02x %02x %02x"
1521 1.1 christos " %02x %02x %02x %02x"
1522 1.1 christos " %02x %02x %02x %02x\n",
1523 1.1 christos tp,
1524 1.1 christos i,
1525 1.1 christos cp[0], cp[1], cp[2], cp[3],
1526 1.1 christos cp[4], cp[5], cp[6], cp[7],
1527 1.1 christos cp[8], cp[9], cp[10], cp[11],
1528 1.1 christos cp[12], cp[13], cp[14], cp[15]);
1529 1.1 christos free(tp);
1530 1.1 christos }
1531 1.1 christos }
1532 1.1 christos else { /* IPv4 */
1533 1.1 christos uint32_t *ip4addr = (void *)p->addr;
1534 1.1 christos
1535 1.1 christos for (size_t i = 0; i < cnt; i++) {
1536 1.1 christos tp = bp;
1537 1.1 christos dbg->sz += easprintf(&bp,
1538 1.1 christos "%s"
1539 1.1 christos DEVPATH_FMT(addr[i]: 0x%08x\n),
1540 1.1 christos tp, ip4addr[i]);
1541 1.1 christos free(tp);
1542 1.1 christos }
1543 1.1 christos }
1544 1.1 christos }
1545 1.1 christos
1546 1.1 christos
1547 1.1 christos }
1548 1.1 christos }
1549 1.1 christos
1550 1.1 christos static void
1551 1.1 christos devpath_msg_nvdimm(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
1552 1.1 christos { /* See 10.3.4.30 */
1553 1.1 christos struct { /* Sub-Type 32 */
1554 1.1 christos devpath_t hdr; /* Length = 20 */
1555 1.1 christos uuid_t UUID;
1556 1.1 christos } __packed *p = (void *)dp;
1557 1.1 christos __CTASSERT(sizeof(*p) == 20);
1558 1.1 christos char uuid_str[UUID_STR_LEN];
1559 1.1 christos
1560 1.1 christos uuid_snprintf(uuid_str, sizeof(uuid_str), &p->UUID);
1561 1.1 christos path->sz = easprintf(&path->cp, "NVDIMM(%s)", uuid_str);
1562 1.1 christos
1563 1.1 christos if (dbg != NULL) {
1564 1.1 christos dbg->sz = easprintf(&dbg->cp,
1565 1.1 christos DEVPATH_FMT_HDR,
1566 1.1 christos DEVPATH_DAT_HDR(dp)
1567 1.1 christos );
1568 1.1 christos }
1569 1.1 christos }
1570 1.1 christos
1571 1.1 christos static void
1572 1.1 christos devpath_msg_restservice(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
1573 1.1 christos { /* See 10.3.4.31 */
1574 1.1 christos struct { /* Sub-Type 33 */
1575 1.1 christos devpath_t hdr; /* Length = 6 */
1576 1.1 christos uint8_t RestService;
1577 1.1 christos #define REST_SERVICE_REDFISH 0x01
1578 1.1 christos #define REST_SERVICE_ODATA 0x02
1579 1.1 christos uint8_t AccessMode;
1580 1.1 christos #define ACCESS_MODE_IN_BAND 0x01
1581 1.1 christos #define ACCESS_MODE_OUT_OF_BAND 0x02
1582 1.1 christos } __packed *p = (void *)dp;
1583 1.1 christos __CTASSERT(sizeof(*p) == 6);
1584 1.1 christos
1585 1.1 christos path->sz = easprintf(&path->cp, "RestService(%d,%d)", p->RestService, p->AccessMode);
1586 1.1 christos
1587 1.1 christos if (dbg != NULL) {
1588 1.1 christos dbg->sz = easprintf(&dbg->cp,
1589 1.1 christos DEVPATH_FMT_HDR
1590 1.1 christos DEVPATH_FMT(RestService: 0x%02x(%s)\n)
1591 1.1 christos DEVPATH_FMT(AccessMode: 0x%02x(%s)\n),
1592 1.1 christos DEVPATH_DAT_HDR(dp),
1593 1.1 christos p->RestService,
1594 1.1 christos p->RestService == REST_SERVICE_REDFISH ? "RedFish" :
1595 1.1 christos p->RestService == REST_SERVICE_ODATA ? "OData" : "???",
1596 1.1 christos p->AccessMode,
1597 1.1 christos p->AccessMode == ACCESS_MODE_IN_BAND ? "In-Band" :
1598 1.1 christos p->AccessMode == ACCESS_MODE_OUT_OF_BAND ? "Out-of-Band" : "???");
1599 1.1 christos }
1600 1.1 christos }
1601 1.1 christos
1602 1.1 christos static void
1603 1.1 christos devpath_msg_nvmeof(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
1604 1.1 christos { /* See 10.3.4.32 */
1605 1.1 christos struct { /* Sub-Type 34 */
1606 1.1 christos devpath_t hdr; /* Length = 21 XXX: 20 in text */
1607 1.1 christos uint8_t NIDT;
1608 1.1 christos union {
1609 1.1 christos uint64_t dw[2];
1610 1.1 christos uint8_t csi;
1611 1.1 christos uint64_t ieuid;
1612 1.1 christos uuid_t uuid;
1613 1.1 christos } NID; /* big-endian */
1614 1.1 christos uint8_t SubsystemNQN[]; /* UTF-8 null-terminated */
1615 1.1 christos } __packed *p = (void *)dp;
1616 1.1 christos __CTASSERT(sizeof(*p) == 21);
1617 1.1 christos char uuid_str[UUID_STR_LEN];
1618 1.1 christos
1619 1.1 christos /*
1620 1.1 christos * See 5.1.13.2.3 of NVM-Express Base Specification Rev 2.1,
1621 1.1 christos * in particular, Fig 315 on page 332.
1622 1.1 christos */
1623 1.1 christos switch (p->NIDT) {
1624 1.1 christos case 0:
1625 1.1 christos path->sz = easprintf(&path->cp, "NVMEoF(%s)", p->SubsystemNQN);
1626 1.1 christos break;
1627 1.1 christos case 1:
1628 1.2 martin path->sz = easprintf(&path->cp, "NVMEoF(%s,0x%016" PRIx64
1629 1.2 martin ")", p->SubsystemNQN, p->NID.ieuid);
1630 1.1 christos break;
1631 1.1 christos case 2:
1632 1.1 christos case 3:
1633 1.1 christos uuid_snprintf(uuid_str, sizeof(uuid_str), &p->NID.uuid);
1634 1.1 christos path->sz = easprintf(&path->cp, "NVMEoF(%s,%s)", p->SubsystemNQN, uuid_str);
1635 1.1 christos break;
1636 1.1 christos case 4:
1637 1.1 christos path->sz = easprintf(&path->cp, "NVMEoF(%s,0x%02x)", p->SubsystemNQN, p->NID.csi);
1638 1.1 christos break;
1639 1.1 christos default:
1640 1.1 christos path->sz = easprintf(&path->cp, "NVMEoF(%s,unknown)", p->SubsystemNQN);
1641 1.1 christos break;
1642 1.1 christos }
1643 1.1 christos
1644 1.1 christos if (dbg != NULL) {
1645 1.1 christos dbg->sz = easprintf(&dbg->cp,
1646 1.1 christos DEVPATH_FMT_HDR
1647 1.1 christos DEVPATH_FMT(NIDT: 0x%02x\n)
1648 1.2 martin DEVPATH_FMT(NID:) " 0x%016" PRIx64 "%016" PRIx64 "\n"
1649 1.1 christos DEVPATH_FMT(SubsystemNQN: '%s'\n),
1650 1.1 christos DEVPATH_DAT_HDR(dp),
1651 1.1 christos p->NIDT,
1652 1.1 christos p->NID.dw[0], p->NID.dw[1],
1653 1.1 christos p->SubsystemNQN);
1654 1.1 christos }
1655 1.1 christos }
1656 1.1 christos
1657 1.1 christos PUBLIC void
1658 1.1 christos devpath_msg(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
1659 1.1 christos {
1660 1.1 christos
1661 1.1 christos assert(dp->Type = 3);
1662 1.1 christos
1663 1.1 christos switch (dp->SubType) {
1664 1.1 christos case 1: devpath_msg_atapi(dp, path, dbg); return;
1665 1.1 christos case 2: devpath_msg_scsi(dp, path, dbg); return;
1666 1.1 christos case 3: devpath_msg_fibre(dp, path, dbg); return;
1667 1.1 christos case 4: devpath_msg_11394(dp, path, dbg); return;
1668 1.1 christos case 5: devpath_msg_usb(dp, path, dbg); return;
1669 1.1 christos case 6: devpath_msg_i2o(dp, path, dbg); return;
1670 1.1 christos case 9: devpath_msg_infiniband(dp, path, dbg); return;
1671 1.1 christos case 10: devpath_msg_vendor(dp, path, dbg); return;
1672 1.1 christos case 11: devpath_msg_mac(dp, path, dbg); return;
1673 1.1 christos case 12: devpath_msg_ipv4(dp, path, dbg); return;
1674 1.1 christos case 13: devpath_msg_ipv6(dp, path, dbg); return;
1675 1.1 christos case 14: devpath_msg_uart(dp, path, dbg); return;
1676 1.1 christos case 15: devpath_msg_usbclass(dp, path, dbg); return;
1677 1.1 christos case 16: devpath_msg_usbwwid(dp, path, dbg); return;
1678 1.1 christos case 17: devpath_msg_unit(dp, path, dbg); return;
1679 1.1 christos case 18: devpath_msg_sata(dp, path, dbg); return;
1680 1.1 christos case 19: devpath_msg_iscsi(dp, path, dbg); return;
1681 1.1 christos case 20: devpath_msg_vlan(dp, path, dbg); return;
1682 1.1 christos case 21: devpath_msg_fibreex(dp, path, dbg); return;
1683 1.1 christos case 22: devpath_msg_sasex(dp, path, dbg); return;
1684 1.1 christos case 23: devpath_msg_nvme(dp, path, dbg); return;
1685 1.1 christos case 24: devpath_msg_uri(dp, path, dbg); return;
1686 1.1 christos case 25: devpath_msg_ufs(dp, path, dbg); return;
1687 1.1 christos case 26: devpath_msg_sd(dp, path, dbg); return;
1688 1.1 christos case 27: devpath_msg_bluetooth(dp, path, dbg); return;
1689 1.1 christos case 28: devpath_msg_wifi(dp, path, dbg); return;
1690 1.1 christos case 29: devpath_msg_emmc(dp, path, dbg); return;
1691 1.1 christos case 30: devpath_msg_bluetoothle(dp, path, dbg); return;
1692 1.1 christos case 31: devpath_msg_dns(dp, path, dbg); return;
1693 1.1 christos case 32: devpath_msg_nvdimm(dp, path, dbg); return;
1694 1.1 christos case 33: devpath_msg_restservice(dp, path, dbg); return;
1695 1.1 christos case 34: devpath_msg_nvmeof(dp, path, dbg); return;
1696 1.1 christos default: devpath_unsupported(dp, path, dbg); return;
1697 1.1 christos }
1698 1.1 christos }
1699