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