devpath3.c revision 1.5 1 1.5 riastrad /* $NetBSD: devpath3.c,v 1.5 2025/03/02 00:23:59 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.5 riastrad __RCSID("$NetBSD: devpath3.c,v 1.5 2025/03/02 00:23:59 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.1 christos path->sz = easprintf(&path->cp, "VenMsg(%s,%s)", uuid_str, data_str);
582 1.1 christos }
583 1.1 christos else if (vt->fn == NULL) {
584 1.1 christos assert(vt->name != NULL);
585 1.1 christos path->sz = easprintf(&path->cp, "%s(%s)", vt->name, data_str);
586 1.1 christos }
587 1.1 christos else {
588 1.1 christos vt->fn(dp, path, dbg);
589 1.1 christos return;
590 1.1 christos }
591 1.1 christos if (dbg != NULL) {
592 1.1 christos dbg->sz = easprintf(&dbg->cp,
593 1.1 christos DEVPATH_FMT_HDR
594 1.1 christos DEVPATH_FMT(GUID: %s\n)
595 1.1 christos DEVPATH_FMT(Data: %s\n),
596 1.1 christos DEVPATH_DAT_HDR(dp),
597 1.1 christos uuid_str,
598 1.1 christos data_str);
599 1.1 christos }
600 1.1 christos free(data_str);
601 1.1 christos }
602 1.1 christos
603 1.1 christos static void
604 1.1 christos devpath_msg_mac(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
605 1.1 christos { /* See 10.3.4.10 */
606 1.1 christos struct { /* Sub-Type 11 */
607 1.1 christos devpath_t hdr; /* Length = 37 */
608 1.1 christos uint8_t mac_addr[32];
609 1.1 christos uint8_t IfType;
610 1.1 christos } __packed *p = (void *)dp;
611 1.1 christos __CTASSERT(sizeof(*p) == 37);
612 1.1 christos size_t addr_len;
613 1.1 christos char *mac_addr;
614 1.1 christos
615 1.1 christos switch (p->IfType) {
616 1.1 christos case 0:
617 1.1 christos case 1:
618 1.1 christos addr_len = 6;
619 1.1 christos break;
620 1.1 christos default:
621 1.1 christos addr_len = 32;
622 1.1 christos break;
623 1.1 christos }
624 1.1 christos #if 0
625 1.1 christos From: RFC3232 says everything is now online, found here:
626 1.1 christos https://www.iana.org/assignments/arp-parameters/arp-parameters.xhtml
627 1.1 christos
628 1.1 christos XXX: Should we make a table so we can show a name?
629 1.1 christos
630 1.1 christos 0 Reserved [RFC5494]
631 1.1 christos 1 Ethernet (10Mb) [Jon_Postel]
632 1.1 christos 2 Experimental Ethernet (3Mb) [Jon_Postel]
633 1.1 christos 3 Amateur Radio AX.25 [Philip_Koch]
634 1.1 christos 4 Proteon ProNET Token Ring [Avri_Doria]
635 1.1 christos 5 Chaos [Gill_Pratt]
636 1.1 christos 6 IEEE 802 Networks [Jon_Postel]
637 1.1 christos 7 ARCNET [RFC1201]
638 1.1 christos 8 Hyperchannel [Jon_Postel]
639 1.1 christos 9 Lanstar [Tom_Unger]
640 1.1 christos 10 Autonet Short Address [Mike_Burrows]
641 1.1 christos 11 LocalTalk [Joyce_K_Reynolds]
642 1.1 christos 12 LocalNet (IBM PCNet or SYTEK LocalNET) [Joseph Murdock]
643 1.1 christos 13 Ultra link [Rajiv_Dhingra]
644 1.1 christos 14 SMDS [George_Clapp]
645 1.1 christos 15 Frame Relay [Andy_Malis]
646 1.1 christos 16 Asynchronous Transmission Mode (ATM) [[JXB2]]
647 1.1 christos 17 HDLC [Jon_Postel]
648 1.1 christos 18 Fibre Channel [RFC4338]
649 1.1 christos 19 Asynchronous Transmission Mode (ATM) [RFC2225]
650 1.1 christos 20 Serial Line [Jon_Postel]
651 1.1 christos 21 Asynchronous Transmission Mode (ATM) [Mike_Burrows]
652 1.1 christos 22 MIL-STD-188-220 [Herb_Jensen]
653 1.1 christos 23 Metricom [Jonathan_Stone]
654 1.1 christos 24 IEEE 1394.1995 [Myron_Hattig]
655 1.1 christos 25 MAPOS [Mitsuru_Maruyama][RFC2176]
656 1.1 christos 26 Twinaxial [Marion_Pitts]
657 1.1 christos 27 EUI-64 [Kenji_Fujisawa]
658 1.1 christos 28 HIPARP [Jean_Michel_Pittet]
659 1.1 christos 29 IP and ARP over ISO 7816-3 [Scott_Guthery]
660 1.1 christos 30 ARPSec [Jerome_Etienne]
661 1.1 christos 31 IPsec tunnel [RFC3456]
662 1.1 christos 32 InfiniBand (TM) [RFC4391]
663 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]
664 1.1 christos 34 Wiegand Interface [Scott_Guthery_2]
665 1.1 christos 35 Pure IP [Inaky_Perez-Gonzalez]
666 1.1 christos 36 HW_EXP1 [RFC5494]
667 1.1 christos 37 HFI [Tseng-Hui_Lin]
668 1.1 christos 38 Unified Bus (UB) [Wei_Pan]
669 1.1 christos 39-255 Unassigned
670 1.1 christos 256 HW_EXP2 [RFC5494]
671 1.1 christos 257 AEthernet [Geoffroy_Gramaize]
672 1.1 christos 258-65534 Unassigned
673 1.1 christos 65535 Reserved [RFC5494]
674 1.1 christos #endif
675 1.1 christos
676 1.1 christos mac_addr = encode_data(p->mac_addr, addr_len);
677 1.1 christos path->sz = easprintf(&path->cp, "MAC(%s,%d)", mac_addr, p->IfType);
678 1.1 christos
679 1.1 christos if (dbg != NULL) {
680 1.1 christos dbg->sz = easprintf(&dbg->cp,
681 1.1 christos DEVPATH_FMT_HDR
682 1.1 christos DEVPATH_FMT(MAC_addr: %s\n)
683 1.1 christos DEVPATH_FMT(IfType: %x\n),
684 1.1 christos DEVPATH_DAT_HDR(dp),
685 1.1 christos mac_addr,
686 1.1 christos p->IfType);
687 1.1 christos }
688 1.1 christos free(mac_addr);
689 1.1 christos }
690 1.1 christos
691 1.1 christos static void
692 1.1 christos devpath_msg_ipv4(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
693 1.1 christos { /* See 10.3.4.11 */
694 1.1 christos struct { /* Sub-Type 12 */
695 1.1 christos devpath_t hdr; /* Length = 27 */
696 1.1 christos uint32_t LocalIPAddr;
697 1.1 christos uint32_t RemoteIPAddr;
698 1.1 christos uint16_t LocalPort;
699 1.1 christos uint16_t RemotePort;
700 1.1 christos uint16_t Protocol;
701 1.1 christos uint8_t StaticIPAddr;
702 1.1 christos uint32_t GatewayIPAddr;
703 1.1 christos uint32_t SubnetMask;
704 1.1 christos } __packed *p = (void *)dp;
705 1.1 christos __CTASSERT(sizeof(*p) == 27);
706 1.1 christos char *gaddr, *laddr, *raddr, *mask;
707 1.1 christos char *proto, *atype;
708 1.1 christos
709 1.1 christos laddr = ipv4_addr(p->LocalIPAddr);
710 1.1 christos gaddr = ipv4_addr(p->GatewayIPAddr);
711 1.1 christos raddr = ipv4_addr(p->RemoteIPAddr);
712 1.1 christos mask = ipv4_addr(p->SubnetMask);
713 1.1 christos proto = proto_name(p->Protocol);
714 1.1 christos atype = ipv4_type(p->StaticIPAddr);
715 1.1 christos
716 1.1 christos path->sz = easprintf(&path->cp, "IPv4(%s,%s,%s,%s,%s,%s)",
717 1.1 christos raddr, proto, atype, laddr, gaddr, mask);
718 1.1 christos
719 1.1 christos if (dbg != NULL) {
720 1.1 christos dbg->sz = easprintf(&dbg->cp,
721 1.1 christos DEVPATH_FMT_HDR
722 1.1 christos DEVPATH_FMT(LocalIPAddr: 0x%08x(%s)\n)
723 1.1 christos DEVPATH_FMT(RemoteIPAddr: 0x%08x(%s)\n)
724 1.1 christos DEVPATH_FMT(LocalPort: 0x%04x\n)
725 1.1 christos DEVPATH_FMT(RemotePort: 0x%04x\n)
726 1.1 christos DEVPATH_FMT(Protocol: 0x%04x(%s)\n)
727 1.1 christos DEVPATH_FMT(StaticIPAddr: 0x%02x(%s)\n)
728 1.1 christos DEVPATH_FMT(GatewayIPAddr: 0x%08x(%s)\n)
729 1.1 christos DEVPATH_FMT(SubnetMask: 0x%08x(%s)\n),
730 1.1 christos DEVPATH_DAT_HDR(dp),
731 1.1 christos p->LocalIPAddr, laddr,
732 1.1 christos p->RemoteIPAddr, raddr,
733 1.1 christos p->LocalPort,
734 1.1 christos p->RemotePort,
735 1.1 christos p->Protocol, proto,
736 1.1 christos p->StaticIPAddr, atype,
737 1.1 christos p->GatewayIPAddr, gaddr,
738 1.1 christos p->SubnetMask, mask);
739 1.1 christos }
740 1.1 christos free(atype);
741 1.1 christos free(proto);
742 1.1 christos free(mask);
743 1.1 christos free(raddr);
744 1.1 christos free(gaddr);
745 1.1 christos free(laddr);
746 1.1 christos }
747 1.1 christos
748 1.1 christos static void
749 1.1 christos devpath_msg_ipv6(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
750 1.1 christos { /* See 10.3.4.12 */
751 1.1 christos struct { /* Sub-Type 13 */
752 1.1 christos devpath_t hdr; /* Length = 60 */
753 1.1 christos struct in6_addr LocalIPAddr;
754 1.1 christos struct in6_addr RemoteIPAddr;
755 1.1 christos uint16_t LocalPort;
756 1.1 christos uint16_t RemotePort;
757 1.1 christos uint16_t Protocol;
758 1.1 christos uint8_t IPAddrOrigin;
759 1.1 christos uint8_t PrefixLength;
760 1.1 christos struct in6_addr GatewayIPAddr;
761 1.1 christos } __packed *p = (void *)dp;
762 1.1 christos __CTASSERT(sizeof(*p) == 60);
763 1.1 christos char *gaddr, *laddr, *raddr;
764 1.1 christos char *proto, *atype;
765 1.1 christos
766 1.1 christos laddr = ipv6_addr(&p->LocalIPAddr);
767 1.1 christos gaddr = ipv6_addr(&p->GatewayIPAddr);
768 1.1 christos raddr = ipv6_addr(&p->RemoteIPAddr);
769 1.1 christos proto = proto_name(p->Protocol);
770 1.1 christos atype = ipv6_type(p->IPAddrOrigin);
771 1.1 christos
772 1.1 christos path->sz = easprintf(&path->cp, "IPv6(%s,%s,%s,%s,%s)",
773 1.1 christos raddr, proto, atype, laddr, gaddr);
774 1.1 christos
775 1.1 christos if (dbg != NULL) {
776 1.1 christos dbg->sz = easprintf(&dbg->cp,
777 1.1 christos DEVPATH_FMT_HDR
778 1.1 christos DEVPATH_FMT(LocalIPAddr: %s\n)
779 1.1 christos DEVPATH_FMT(RemoteIPAddr: %s\n)
780 1.1 christos DEVPATH_FMT(LocalPort: 0x%04x\n)
781 1.1 christos DEVPATH_FMT(RemotePort: 0x%04x\n)
782 1.1 christos DEVPATH_FMT(Protocol: 0x%04x(%s)\n)
783 1.1 christos DEVPATH_FMT(IPAddrOrigin: 0x%02x(%s)\n)
784 1.1 christos DEVPATH_FMT(PrefixLength: 0x%02x\n)
785 1.1 christos DEVPATH_FMT(GatewayIPAddr: %s\n),
786 1.1 christos DEVPATH_DAT_HDR(dp),
787 1.1 christos laddr,
788 1.1 christos raddr,
789 1.1 christos p->LocalPort,
790 1.1 christos p->RemotePort,
791 1.1 christos p->Protocol, proto,
792 1.1 christos p->IPAddrOrigin, atype,
793 1.1 christos p->PrefixLength,
794 1.1 christos gaddr);
795 1.1 christos }
796 1.1 christos free(atype);
797 1.1 christos free(proto);
798 1.1 christos free(raddr);
799 1.1 christos free(gaddr);
800 1.1 christos free(laddr);
801 1.1 christos }
802 1.1 christos
803 1.1 christos static inline const char *
804 1.1 christos uart_parity(uint8_t n)
805 1.1 christos {
806 1.4 riastrad
807 1.1 christos switch (n) {
808 1.1 christos case 0: return "D";
809 1.1 christos case 1: return "N";
810 1.1 christos case 2: return "E";
811 1.1 christos case 3: return "O";
812 1.1 christos case 4: return "M";
813 1.1 christos case 5: return "S";
814 1.1 christos default: return "?";
815 1.1 christos }
816 1.1 christos }
817 1.1 christos
818 1.1 christos static inline const char *
819 1.1 christos uart_stopbits(uint8_t n)
820 1.1 christos {
821 1.1 christos
822 1.1 christos switch (n) {
823 1.1 christos case 0: return "D";
824 1.1 christos case 1: return "1";
825 1.1 christos case 2: return "1.5";
826 1.1 christos case 3: return "2";
827 1.1 christos default: return "?";
828 1.1 christos }
829 1.1 christos }
830 1.1 christos
831 1.1 christos static void
832 1.1 christos devpath_msg_uart(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
833 1.1 christos { /* See 10.3.4.15 */
834 1.1 christos struct { /* Sub-Type 14 */
835 1.1 christos devpath_t hdr; /* Length = 19 */
836 1.1 christos uint32_t Reserved;
837 1.1 christos uint64_t BaudRate;
838 1.1 christos uint8_t DataBits;
839 1.1 christos uint8_t Parity;
840 1.1 christos uint8_t StopBits;
841 1.1 christos } __packed *p = (void *)dp;
842 1.1 christos __CTASSERT(sizeof(*p) == 19);
843 1.1 christos const char *parity, *stopbits;
844 1.1 christos
845 1.1 christos parity = uart_parity(p->Parity);
846 1.1 christos stopbits = uart_stopbits(p->StopBits);
847 1.1 christos
848 1.2 martin path->sz = easprintf(&path->cp, "Uart(%" PRIx64 ",%u,%s,%s)",
849 1.2 martin p->BaudRate, p->DataBits, parity, stopbits);
850 1.1 christos
851 1.1 christos if (dbg != NULL) {
852 1.1 christos dbg->sz = easprintf(&dbg->cp,
853 1.1 christos DEVPATH_FMT_HDR
854 1.1 christos DEVPATH_FMT(Reserved: 0x%08x\n)
855 1.2 martin DEVPATH_FMT(BaudRate:) " 0x%016" PRIx64 "\n"
856 1.1 christos DEVPATH_FMT(DataBits: 0x%1x\n)
857 1.1 christos DEVPATH_FMT(Parity: 0x%1x(%s)\n)
858 1.1 christos DEVPATH_FMT(StopBits: 0x%1x(%s)\n),
859 1.1 christos DEVPATH_DAT_HDR(dp),
860 1.1 christos p->Reserved,
861 1.1 christos p->BaudRate,
862 1.1 christos p->DataBits,
863 1.1 christos p->Parity, parity,
864 1.1 christos p->StopBits, stopbits);
865 1.1 christos }
866 1.1 christos }
867 1.1 christos
868 1.1 christos static inline const char *
869 1.1 christos usbclass_name(uint8_t class, uint8_t subclass)
870 1.1 christos {
871 1.1 christos
872 1.1 christos switch (class) {
873 1.1 christos case 1: return "UsbAudio";
874 1.1 christos case 2: return "UsbCDCControl";
875 1.1 christos case 3: return "UsbHID";
876 1.1 christos case 6: return "UsbImage";
877 1.1 christos case 7: return "UsbPrintr";
878 1.1 christos case 8: return "UsbMassStorage";
879 1.1 christos case 9: return "UsbHub";
880 1.1 christos case 10: return "UsbCDCData";
881 1.1 christos case 11: return "UsbSmartCard";
882 1.1 christos case 14: return "UsbVideo";
883 1.1 christos case 220: return "UsbDiagnostic";
884 1.1 christos case 224: return "UsbWireless";
885 1.1 christos case 254:
886 1.1 christos switch (subclass) {
887 1.1 christos case 1: return "UsbDeviceFirmwareUpdate";
888 1.1 christos case 2: return "UsbIrdaBridge";
889 1.1 christos case 3: return "UsbTestAndMeasurement";
890 1.1 christos default: return NULL;
891 1.1 christos }
892 1.1 christos default: return NULL;
893 1.1 christos }
894 1.1 christos }
895 1.1 christos
896 1.1 christos static void
897 1.1 christos devpath_msg_usbclass(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
898 1.1 christos { /* See 10.3.4.8 */
899 1.1 christos struct { /* Sub-Type 15 */
900 1.1 christos devpath_t hdr; /* Length = 11 */
901 1.1 christos uint16_t VendorID;
902 1.1 christos uint16_t ProductID;
903 1.1 christos uint8_t DeviceClass;
904 1.1 christos uint8_t DeviceSubClass;
905 1.1 christos uint8_t DeviceProtocol;
906 1.1 christos } __packed *p = (void *)dp;
907 1.1 christos __CTASSERT(sizeof(*p) == 11);
908 1.1 christos const char *name;
909 1.1 christos
910 1.1 christos name = usbclass_name(p->DeviceClass, p->DeviceSubClass);
911 1.1 christos if (name == NULL) {
912 1.5 riastrad path->sz = easprintf(&path->cp,
913 1.5 riastrad "UsbClass(0x%04x,0x%04x,0x%02x,0x%02x,0x%02x,)",
914 1.1 christos p->VendorID, p->ProductID, p->DeviceClass,
915 1.1 christos p->DeviceSubClass, p->DeviceProtocol);
916 1.1 christos }
917 1.1 christos else if (p->DeviceClass != 254) {
918 1.5 riastrad path->sz = easprintf(&path->cp,
919 1.5 riastrad "%s(0x%04x,0x%04x,0x%02x,0x%02x,)",
920 1.5 riastrad name, p->VendorID, p->ProductID, p->DeviceSubClass,
921 1.5 riastrad p->DeviceProtocol);
922 1.1 christos }
923 1.1 christos else {
924 1.1 christos path->sz = easprintf(&path->cp, "%s(0x%04x,0x%04x,0x%02x,)",
925 1.1 christos name, p->VendorID, p->ProductID, p->DeviceProtocol);
926 1.1 christos }
927 1.1 christos
928 1.1 christos if (dbg != NULL) {
929 1.1 christos dbg->sz = easprintf(&dbg->cp,
930 1.1 christos DEVPATH_FMT_HDR
931 1.1 christos DEVPATH_FMT(VendorID: 0x%04x\n)
932 1.1 christos DEVPATH_FMT(ProductID: 0x%04x\n)
933 1.1 christos DEVPATH_FMT(DeviceClass: 0x%02x(%u)\n)
934 1.1 christos DEVPATH_FMT(DeviceSubClass: 0x%02x(%u)\n)
935 1.1 christos DEVPATH_FMT(DeviceProtocol: 0x%02x(%u)\n),
936 1.1 christos DEVPATH_DAT_HDR(dp),
937 1.1 christos p->VendorID,
938 1.1 christos p->ProductID,
939 1.1 christos p->DeviceClass, p->DeviceClass,
940 1.1 christos p->DeviceSubClass, p->DeviceSubClass,
941 1.1 christos p->DeviceProtocol, p->DeviceProtocol);
942 1.1 christos }
943 1.1 christos }
944 1.1 christos
945 1.1 christos static void
946 1.1 christos devpath_msg_usbwwid(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
947 1.1 christos { /* See 10.3.4.7 */
948 1.1 christos struct { /* Sub-Type 16 */
949 1.1 christos devpath_t hdr; /* Length = 10 + n */
950 1.1 christos uint16_t IFaceNum;
951 1.1 christos uint16_t VendorID;
952 1.1 christos uint16_t ProductID;
953 1.1 christos uint8_t SerialNum[];
954 1.1 christos } __packed *p = (void *)dp;
955 1.1 christos __CTASSERT(sizeof(*p) == 10);
956 1.1 christos char *serialnum;
957 1.1 christos size_t seriallen;
958 1.1 christos
959 1.1 christos seriallen = p->hdr.Length - offsetof(typeof(*p), SerialNum);
960 1.1 christos if (seriallen == 0) {
961 1.1 christos serialnum = __UNCONST("WWID"); /* XXX: This is an error! */
962 1.1 christos assert(0);
963 1.1 christos }
964 1.1 christos else {
965 1.1 christos size_t sz = p->hdr.Length - sizeof(*p);
966 1.1 christos serialnum = ucs2_to_utf8((uint16_t *)p->SerialNum, sz, NULL, NULL);
967 1.1 christos }
968 1.1 christos
969 1.1 christos path->sz = easprintf(&path->cp, "UsbWwid(0x%04x,0x%04x,0x%02x,%s)",
970 1.1 christos p->VendorID, p->ProductID, p->IFaceNum, serialnum);
971 1.1 christos
972 1.1 christos if (dbg != NULL) {
973 1.1 christos dbg->sz = easprintf(&dbg->cp,
974 1.1 christos DEVPATH_FMT_HDR
975 1.1 christos DEVPATH_FMT(IFaceNum: 0x%04x\n)
976 1.1 christos DEVPATH_FMT(VendorID: 0x%04x\n)
977 1.1 christos DEVPATH_FMT(ProductID: 0x%04x\n)
978 1.1 christos DEVPATH_FMT(SerialNum: %s\n),
979 1.1 christos DEVPATH_DAT_HDR(dp),
980 1.1 christos p->IFaceNum, p->VendorID, p->ProductID, serialnum);
981 1.1 christos }
982 1.1 christos
983 1.1 christos if (seriallen)
984 1.1 christos free(serialnum);
985 1.1 christos }
986 1.1 christos
987 1.1 christos static void
988 1.1 christos devpath_msg_unit(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
989 1.1 christos { /* See 10.3.4.8 */
990 1.1 christos struct { /* Sub-Type 17 */
991 1.1 christos devpath_t hdr; /* Length = 5 */
992 1.1 christos uint8_t LUN;
993 1.1 christos } __packed *p = (void *)dp;
994 1.1 christos __CTASSERT(sizeof(*p) == 5);
995 1.1 christos
996 1.1 christos path->sz = easprintf(&path->cp, "Unit(%u)", p->LUN);
997 1.1 christos
998 1.1 christos if (dbg != NULL) {
999 1.1 christos dbg->sz = easprintf(&dbg->cp,
1000 1.1 christos DEVPATH_FMT_HDR
1001 1.1 christos DEVPATH_FMT(LUN: %u\n),
1002 1.1 christos DEVPATH_DAT_HDR(dp),
1003 1.1 christos p->LUN);
1004 1.1 christos }
1005 1.1 christos }
1006 1.1 christos
1007 1.1 christos static void
1008 1.1 christos devpath_msg_sata(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
1009 1.1 christos { /* See 10.3.4.6 */
1010 1.1 christos struct { /* Sub-Type 18 */
1011 1.1 christos devpath_t hdr; /* Length = 10 */
1012 1.1 christos uint16_t SATAHBAPortNum;
1013 1.1 christos uint16_t SATAPortMultiplierPortNum;
1014 1.1 christos uint16_t SATALogicalUnitNum;
1015 1.1 christos } __packed *p = (void *)dp;
1016 1.1 christos __CTASSERT(sizeof(*p) == 10);
1017 1.1 christos
1018 1.1 christos path->sz = easprintf(&path->cp, "SATA(%u,%u,%u)", p->SATAHBAPortNum,
1019 1.1 christos p->SATAPortMultiplierPortNum, p->SATALogicalUnitNum);
1020 1.1 christos
1021 1.1 christos if (dbg != NULL) {
1022 1.1 christos dbg->sz = easprintf(&dbg->cp,
1023 1.1 christos DEVPATH_FMT_HDR
1024 1.1 christos DEVPATH_FMT(SATAHBAPortNum: %u\n)
1025 1.1 christos DEVPATH_FMT(SATAPortMultiplierPortNum: %u\n)
1026 1.1 christos DEVPATH_FMT(SATALogicalUnitNum: %u\n),
1027 1.1 christos DEVPATH_DAT_HDR(dp),
1028 1.1 christos p->SATAHBAPortNum,
1029 1.1 christos p->SATAPortMultiplierPortNum,
1030 1.1 christos p->SATALogicalUnitNum);
1031 1.1 christos }
1032 1.1 christos }
1033 1.1 christos
1034 1.1 christos static inline const char *
1035 1.1 christos hdrdgst_name(uint16_t LoginOptions)
1036 1.1 christos {
1037 1.1 christos
1038 1.1 christos switch (__SHIFTOUT(LoginOptions, __BITS(1,0))) {
1039 1.1 christos case 0: return "None";
1040 1.1 christos case 2: return "CRC32C";
1041 1.1 christos default: return "???";
1042 1.1 christos }
1043 1.1 christos }
1044 1.1 christos
1045 1.1 christos static inline const char *
1046 1.1 christos datdgst_name(uint16_t LoginOptions)
1047 1.1 christos {
1048 1.1 christos
1049 1.1 christos switch (__SHIFTOUT(LoginOptions, __BITS(3,2))) {
1050 1.1 christos case 0: return "None";
1051 1.1 christos case 2: return "CRC32C";
1052 1.1 christos default: return "???";
1053 1.1 christos }
1054 1.1 christos }
1055 1.1 christos
1056 1.1 christos static inline const char *
1057 1.1 christos auth_name(uint16_t LoginOptions)
1058 1.1 christos {
1059 1.1 christos
1060 1.1 christos switch (__SHIFTOUT(LoginOptions, __BITS(12,10))) {
1061 1.1 christos case 0: return "CHAP_BI";
1062 1.1 christos case 2: return "None";
1063 1.1 christos case 4: return "CHAP_UNI";
1064 1.1 christos default: return "???";
1065 1.1 christos }
1066 1.1 christos }
1067 1.1 christos
1068 1.1 christos static inline const char *
1069 1.1 christos protocol_name(uint16_t Protocol)
1070 1.1 christos {
1071 1.1 christos
1072 1.1 christos return Protocol == 0 ? "TCP" : "RSVD";
1073 1.1 christos }
1074 1.1 christos
1075 1.1 christos static void
1076 1.1 christos devpath_msg_iscsi(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
1077 1.1 christos { /* See 10.3.4.20 */
1078 1.1 christos #define LOGIN_OPTION_BITS \
1079 1.1 christos "\177\020" \
1080 1.1 christos "f\0\2""HdrDgst\0" \
1081 1.1 christos "=\x0""None\0" \
1082 1.1 christos "=\x2""CRC32C\0" \
1083 1.1 christos "f\x2\x2""DatDgst\0" \
1084 1.1 christos "=\x0""None\0" \
1085 1.1 christos "=\x2""CRC32C\0" \
1086 1.1 christos "f\xA\x3""Auth\0" \
1087 1.1 christos "=\x0""CHAP_BI\0" \
1088 1.1 christos "=\x2""None\0" \
1089 1.1 christos "=\x4""CHAP_UNI\0"
1090 1.1 christos struct { /* Sub-Type 19 */
1091 1.1 christos devpath_t hdr; /* Length = 18 + n */
1092 1.1 christos uint16_t Protocol;
1093 1.1 christos uint16_t LoginOptions;
1094 1.1 christos uint64_t LUN; /* display as big-endian */
1095 1.1 christos uint16_t TargetPortalGrp;
1096 1.1 christos char TargetName[];
1097 1.1 christos } __packed *p = (void *)dp;
1098 1.1 christos __CTASSERT(sizeof(*p) == 18);
1099 1.1 christos char *name;
1100 1.1 christos const char *auth, *datdgst, *hdrdgst, *proto;
1101 1.1 christos size_t len;
1102 1.1 christos
1103 1.1 christos /*
1104 1.1 christos * Make sure the TargetName is NUL terminated. The spec is
1105 1.1 christos * unclear on this, though their example is asciiz. I have
1106 1.1 christos * no real examples to test, so be safe.
1107 1.1 christos */
1108 1.1 christos len = p->hdr.Length - sizeof(*p);
1109 1.1 christos name = emalloc(len + 1);
1110 1.1 christos memcpy(name, p->TargetName, len);
1111 1.1 christos name[len] = '\0';
1112 1.1 christos
1113 1.1 christos auth = auth_name(p->LoginOptions);
1114 1.1 christos datdgst = datdgst_name(p->LoginOptions);
1115 1.1 christos hdrdgst = hdrdgst_name(p->LoginOptions);
1116 1.1 christos proto = protocol_name(p->Protocol);
1117 1.1 christos
1118 1.2 martin path->sz = easprintf(&path->cp, "iSCSI(%s,0x%04x,0x%064" PRIx64
1119 1.2 martin ",%s,%s,%s,%s)", p->TargetName, p->TargetPortalGrp,
1120 1.1 christos htobe64(p->LUN), hdrdgst, datdgst, auth, proto);
1121 1.1 christos
1122 1.1 christos if (dbg != NULL) {
1123 1.1 christos char liopt[256];
1124 1.1 christos
1125 1.1 christos snprintb(liopt, sizeof(liopt), LOGIN_OPTION_BITS, p->LoginOptions);
1126 1.1 christos dbg->sz = easprintf(&dbg->cp,
1127 1.1 christos DEVPATH_FMT_HDR
1128 1.1 christos DEVPATH_FMT(Protocol: 0x%04x(%s)\n)
1129 1.1 christos DEVPATH_FMT(LoginOptions: %s\n)
1130 1.2 martin DEVPATH_FMT(LUN:) " 0x%064" PRIx64 "\n"
1131 1.1 christos DEVPATH_FMT(TargetPortalGrp: 0x%04x\n)
1132 1.1 christos DEVPATH_FMT(TargetName: %s\n),
1133 1.1 christos DEVPATH_DAT_HDR(dp),
1134 1.1 christos p->Protocol, proto,
1135 1.1 christos liopt,
1136 1.1 christos htobe64(p->LUN),
1137 1.1 christos p->TargetPortalGrp,
1138 1.1 christos name);
1139 1.1 christos }
1140 1.1 christos
1141 1.1 christos free(name);
1142 1.1 christos }
1143 1.1 christos
1144 1.1 christos static void
1145 1.1 christos devpath_msg_vlan(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
1146 1.1 christos { /* See 10.3.4.13 */
1147 1.1 christos struct { /* Sub-Type 20 */
1148 1.1 christos devpath_t hdr; /* Length = 6 */
1149 1.1 christos uint16_t Vlanid;
1150 1.1 christos } __packed *p = (void *)dp;
1151 1.1 christos __CTASSERT(sizeof(*p) == 6);
1152 1.1 christos
1153 1.1 christos path->sz = easprintf(&path->cp, "Vlan(0x%04x)", p->Vlanid);
1154 1.1 christos
1155 1.1 christos if (dbg != NULL) {
1156 1.1 christos dbg->sz = easprintf(&dbg->cp,
1157 1.1 christos DEVPATH_FMT_HDR
1158 1.1 christos DEVPATH_FMT(Vlanid: 0x%04x\n),
1159 1.1 christos DEVPATH_DAT_HDR(dp),
1160 1.1 christos p->Vlanid);
1161 1.1 christos }
1162 1.1 christos }
1163 1.1 christos
1164 1.1 christos static void
1165 1.1 christos devpath_msg_fibreex(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
1166 1.1 christos { /* See 10.3.4.3 */
1167 1.1 christos struct { /* Sub-Type 21 */
1168 1.1 christos devpath_t hdr; /* Length = 24 */
1169 1.1 christos uint32_t Reserved;
1170 1.1 christos uint64_t WorldWideName; /* bit-endian */
1171 1.1 christos uint64_t LUN; /* bit-endian */
1172 1.1 christos } __packed *p = (void *)dp;
1173 1.1 christos __CTASSERT(sizeof(*p) == 24);
1174 1.1 christos
1175 1.2 martin path->sz = easprintf(&path->cp, "FibreEx(0x%064" PRIx64 ",0x%064"
1176 1.2 martin PRIx64 ")", htobe64(p->WorldWideName), htobe64(p->LUN));
1177 1.1 christos
1178 1.1 christos if (dbg != NULL) {
1179 1.1 christos dbg->sz = easprintf(&dbg->cp,
1180 1.1 christos DEVPATH_FMT_HDR
1181 1.2 martin DEVPATH_FMT(WorldWideName:) " 0x%064" PRIx64 "\n"
1182 1.2 martin DEVPATH_FMT(LUN:) " 0x%064" PRIx64 "\n",
1183 1.1 christos DEVPATH_DAT_HDR(dp),
1184 1.1 christos htobe64(p->WorldWideName),
1185 1.1 christos htobe64(p->LUN));
1186 1.1 christos }
1187 1.1 christos }
1188 1.1 christos
1189 1.1 christos static void
1190 1.1 christos devpath_msg_sasex(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
1191 1.1 christos { /* See 10.3.4.18 */
1192 1.1 christos struct { /* Sub-Type 22 */
1193 1.1 christos devpath_t hdr; /* Length = 24 XXX: 32 in text */
1194 1.1 christos uint64_t addr; /* display as big-endian */
1195 1.1 christos uint64_t LUN; /* display as big-endian */
1196 1.1 christos union {
1197 1.1 christos uint8_t b[2];
1198 1.1 christos uint16_t val;
1199 1.1 christos } __packed info; /* device/topology info */
1200 1.1 christos uint16_t RTP; /* Relative Target Port */
1201 1.1 christos } __packed *p = (void *)dp;
1202 1.1 christos __CTASSERT(sizeof(*p) == 24);
1203 1.1 christos
1204 1.1 christos /*
1205 1.1 christos * XXX: This should match what is in devpath_msg_sas().
1206 1.1 christos * Should we share code?
1207 1.1 christos */
1208 1.1 christos if (SASINFO_BYTES(p->info.b[0]) == 0) {
1209 1.2 martin path->sz = easprintf(&path->cp, "SasEx(0x%064" PRIx64
1210 1.2 martin ",0x%064" PRIx64 ")",
1211 1.1 christos htobe64(p->addr), htobe64(p->LUN));
1212 1.1 christos }
1213 1.1 christos else if (SASINFO_BYTES(p->info.b[0]) == 1) {
1214 1.1 christos if (SASINFO_IS_SATA(p->info.b[0])) {
1215 1.2 martin path->sz = easprintf(&path->cp, "SasEx(0x%064" PRIx64
1216 1.2 martin ",0x%064" PRIx64 ",SATA)",
1217 1.1 christos htobe64(p->addr), htobe64(p->LUN));
1218 1.1 christos }
1219 1.1 christos else {
1220 1.2 martin path->sz = easprintf(&path->cp, "SasEx(0x%064" PRIx64
1221 1.2 martin ",SAS)", htobe64(p->addr));
1222 1.1 christos }
1223 1.1 christos }
1224 1.1 christos else {
1225 1.1 christos assert(SASINFO_BYTES(p->info.b[0]) == 2);
1226 1.1 christos uint drivebay = p->info.b[1] + 1;
1227 1.2 martin path->sz = easprintf(&path->cp, "SasEx(0x%064" PRIx64
1228 1.2 martin ",0x%064" PRIx64 ",0x%04x,%s,%s,%s,%d)",
1229 1.1 christos htobe64(p->addr), htobe64(p->LUN), p->RTP,
1230 1.1 christos SASINFO_SASSATA(p->info.b[0]),
1231 1.1 christos SASINFO_EXTERNAL(p->info.b[0]),
1232 1.1 christos SASINFO_EXPANDER(p->info.b[0]),
1233 1.1 christos drivebay);
1234 1.1 christos }
1235 1.1 christos
1236 1.1 christos if (dbg != NULL) {
1237 1.1 christos dbg->sz = easprintf(&dbg->cp,
1238 1.1 christos DEVPATH_FMT_HDR
1239 1.2 martin DEVPATH_FMT(addr:) " 0x%064" PRIx64 "(0x%064" PRIx64 ")\n"
1240 1.2 martin DEVPATH_FMT(LUN:) " 0x%064" PRIx64 "(0x%064" PRIx64 ")\n"
1241 1.1 christos DEVPATH_FMT(info: 0x%02x 0x%02x\n)
1242 1.1 christos DEVPATH_FMT(RPT: 0x%04x\n),
1243 1.1 christos DEVPATH_DAT_HDR(dp),
1244 1.1 christos p->addr, htobe64(p->addr),
1245 1.1 christos p->LUN, htobe64(p->LUN),
1246 1.1 christos p->info.b[0], p->info.b[1],
1247 1.1 christos p->RTP);
1248 1.1 christos }
1249 1.1 christos }
1250 1.1 christos
1251 1.1 christos static void
1252 1.1 christos devpath_msg_nvme(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
1253 1.1 christos { /* See 10.3.4.21 */
1254 1.1 christos struct { /* Sub-Type 23 */
1255 1.1 christos devpath_t hdr; /* Length = 16 */
1256 1.1 christos uint32_t NSID; /* Name Space Identifier */
1257 1.1 christos union {
1258 1.1 christos uint8_t b[8];
1259 1.1 christos uint64_t val;
1260 1.1 christos } EUI; /* IEEE Extended Unique Identifier */
1261 1.1 christos } __packed *p = (void *)dp;
1262 1.1 christos __CTASSERT(sizeof(*p) == 16);
1263 1.1 christos
1264 1.1 christos path->sz = easprintf(&path->cp, "NVMe(0x%x,"
1265 1.1 christos "%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X)",
1266 1.1 christos p->NSID,
1267 1.1 christos p->EUI.b[0], p->EUI.b[1], p->EUI.b[2], p->EUI.b[3],
1268 1.1 christos p->EUI.b[4], p->EUI.b[5], p->EUI.b[6], p->EUI.b[7]);
1269 1.1 christos
1270 1.1 christos if (dbg != NULL) {
1271 1.1 christos dbg->sz = easprintf(&dbg->cp,
1272 1.1 christos DEVPATH_FMT_HDR
1273 1.1 christos DEVPATH_FMT(NSID: 0x%08x\n)
1274 1.2 martin DEVPATH_FMT(EUI:) " 0x%016" PRIx64 "\n",
1275 1.1 christos DEVPATH_DAT_HDR(dp),
1276 1.1 christos p->NSID, p->EUI.val);
1277 1.1 christos }
1278 1.1 christos }
1279 1.1 christos
1280 1.1 christos static void
1281 1.1 christos devpath_msg_uri(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
1282 1.1 christos { /* See 10.3.4.22 */
1283 1.1 christos struct { /* Sub-Type 24 */
1284 1.1 christos devpath_t hdr; /* Length = 4 + n */
1285 1.1 christos uint8_t data[];
1286 1.1 christos } __packed *p = (void *)dp;
1287 1.1 christos __CTASSERT(sizeof(*p) == 4);
1288 1.1 christos size_t len;
1289 1.1 christos char *buf;
1290 1.4 riastrad
1291 1.1 christos len = dp->Length - 4;
1292 1.1 christos
1293 1.1 christos buf = emalloc(len + 1);
1294 1.1 christos if (len > 0)
1295 1.1 christos memcpy(buf, p->data, len);
1296 1.1 christos buf[len] = '\0';
1297 1.1 christos
1298 1.1 christos path->sz = easprintf(&path->cp, "Uri(%s)", buf);
1299 1.1 christos
1300 1.1 christos if (dbg != NULL) {
1301 1.1 christos dbg->sz = easprintf(&dbg->cp,
1302 1.1 christos DEVPATH_FMT_HDR
1303 1.1 christos DEVPATH_FMT(Data: %s\n),
1304 1.1 christos DEVPATH_DAT_HDR(dp),
1305 1.1 christos buf);
1306 1.1 christos }
1307 1.1 christos free(buf);
1308 1.1 christos }
1309 1.1 christos
1310 1.1 christos static void
1311 1.1 christos devpath_msg_ufs(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
1312 1.1 christos { /* See 10.3.4.23 */
1313 1.1 christos struct { /* Sub-Type 25 */
1314 1.1 christos devpath_t hdr; /* Length = 6 */
1315 1.1 christos uint8_t PUN; /* Target ID */
1316 1.1 christos uint8_t LUN; /* Logical Unit Number */
1317 1.1 christos } __packed *p = (void *)dp;
1318 1.1 christos __CTASSERT(sizeof(*p) == 6);
1319 1.1 christos
1320 1.1 christos path->sz = easprintf(&path->cp, "UFS(%#x,0x%02x)", p->PUN, p->LUN);
1321 1.1 christos
1322 1.1 christos if (dbg != NULL) {
1323 1.1 christos dbg->sz = easprintf(&dbg->cp,
1324 1.1 christos DEVPATH_FMT_HDR
1325 1.1 christos DEVPATH_FMT(PUN: 0x%02x\n)
1326 1.1 christos DEVPATH_FMT(LUN: 0x%02x\n),
1327 1.1 christos DEVPATH_DAT_HDR(dp),
1328 1.1 christos p->PUN, p->LUN);
1329 1.1 christos }
1330 1.1 christos }
1331 1.1 christos
1332 1.1 christos static void
1333 1.1 christos devpath_msg_sd(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
1334 1.1 christos { /* See 10.3.4.24 */
1335 1.1 christos struct { /* Sub-Type 26 */
1336 1.1 christos devpath_t hdr; /* Length = 5 */
1337 1.1 christos uint8_t SlotNum;
1338 1.1 christos } __packed *p = (void *)dp;
1339 1.1 christos __CTASSERT(sizeof(*p) == 5);
1340 1.1 christos
1341 1.1 christos path->sz = easprintf(&path->cp, "SD(%d)", p->SlotNum);
1342 1.1 christos
1343 1.1 christos if (dbg != NULL) {
1344 1.1 christos dbg->sz = easprintf(&dbg->cp,
1345 1.1 christos DEVPATH_FMT_HDR
1346 1.1 christos DEVPATH_FMT(SlotNum: 0x%02x\n),
1347 1.1 christos DEVPATH_DAT_HDR(dp),
1348 1.1 christos p->SlotNum);
1349 1.1 christos }
1350 1.1 christos }
1351 1.1 christos
1352 1.1 christos static void
1353 1.1 christos devpath_msg_bluetooth(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
1354 1.1 christos { /* See 10.3.4.25 */
1355 1.1 christos struct { /* Sub-Type 27 */
1356 1.1 christos devpath_t hdr; /* Length = 10 */
1357 1.1 christos uint8_t bdaddr[6];
1358 1.1 christos } __packed *p = (void *)dp;
1359 1.1 christos __CTASSERT(sizeof(*p) == 10);
1360 1.1 christos
1361 1.1 christos path->sz = easprintf(&path->cp, "Bluetooth(%02x:%02x:%02x:%02x:%02x:%02x)",
1362 1.1 christos p->bdaddr[0], p->bdaddr[1], p->bdaddr[2],
1363 1.1 christos p->bdaddr[3], p->bdaddr[4], p->bdaddr[5]);
1364 1.1 christos
1365 1.1 christos if (dbg != NULL) {
1366 1.1 christos dbg->sz = easprintf(&dbg->cp,
1367 1.1 christos DEVPATH_FMT_HDR
1368 1.1 christos DEVPATH_FMT(bdaddr: 0x%02x%02x%02x%02x%02x%02x\n),
1369 1.1 christos DEVPATH_DAT_HDR(dp),
1370 1.1 christos p->bdaddr[0], p->bdaddr[1], p->bdaddr[2],
1371 1.1 christos p->bdaddr[3], p->bdaddr[4], p->bdaddr[5]);
1372 1.1 christos }
1373 1.1 christos }
1374 1.1 christos
1375 1.1 christos static void
1376 1.1 christos devpath_msg_wifi(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
1377 1.1 christos { /* See 10.3.4.26 */
1378 1.1 christos struct { /* Sub-Type 28 */
1379 1.1 christos devpath_t hdr; /* Length = 36 */
1380 1.1 christos char SSID[32];/* XXX: ascii? */
1381 1.1 christos } __packed *p = (void *)dp;
1382 1.1 christos __CTASSERT(sizeof(*p) == 36);
1383 1.1 christos
1384 1.1 christos path->sz = easprintf(&path->cp, "Wi-Fi(%s)", p->SSID);
1385 1.1 christos
1386 1.1 christos if (dbg != NULL) {
1387 1.1 christos char *ssid;
1388 1.1 christos
1389 1.1 christos ssid = encode_data((uint8_t *)p->SSID, sizeof(p->SSID));
1390 1.1 christos dbg->sz = easprintf(&dbg->cp,
1391 1.1 christos DEVPATH_FMT_HDR
1392 1.1 christos DEVPATH_FMT(SSID: %s\n),
1393 1.1 christos DEVPATH_DAT_HDR(dp),
1394 1.1 christos ssid);
1395 1.1 christos free(ssid);
1396 1.1 christos }
1397 1.1 christos }
1398 1.1 christos
1399 1.1 christos static void
1400 1.1 christos devpath_msg_emmc(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
1401 1.1 christos { /* See 10.3.4.27 */
1402 1.1 christos struct { /* Sub-Type 29 */
1403 1.1 christos devpath_t hdr; /* Length = 5 */
1404 1.1 christos uint8_t SlotNum;
1405 1.1 christos } __packed *p = (void *)dp;
1406 1.1 christos __CTASSERT(sizeof(*p) == 5);
1407 1.1 christos
1408 1.1 christos path->sz = easprintf(&path->cp, "eMMC(%d)", p->SlotNum);
1409 1.1 christos
1410 1.1 christos if (dbg != NULL) {
1411 1.1 christos dbg->sz = easprintf(&dbg->cp,
1412 1.1 christos DEVPATH_FMT_HDR
1413 1.1 christos DEVPATH_FMT(SlotNum: 0x%02x\n),
1414 1.1 christos DEVPATH_DAT_HDR(dp),
1415 1.1 christos p->SlotNum);
1416 1.1 christos }
1417 1.1 christos }
1418 1.1 christos
1419 1.1 christos static void
1420 1.1 christos devpath_msg_bluetoothle(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
1421 1.1 christos { /* See 10.3.4.28 */
1422 1.1 christos struct { /* Sub-Type 30 */
1423 1.1 christos devpath_t hdr; /* Length = 11 */
1424 1.1 christos uint8_t bdaddr[6];
1425 1.1 christos uint8_t addr_type;
1426 1.1 christos #define BDADDR_TYPE_PUBLIC 0
1427 1.1 christos #define BDADDR_TYPE_RANDOM 1
1428 1.1 christos } __packed *p = (void *)dp;
1429 1.1 christos __CTASSERT(sizeof(*p) == 11);
1430 1.1 christos
1431 1.5 riastrad path->sz = easprintf(&path->cp,
1432 1.5 riastrad "BluetoothLE(%02x:%02x:%02x:%02x:%02x:%02x,%d)",
1433 1.1 christos p->bdaddr[0], p->bdaddr[1], p->bdaddr[2],
1434 1.1 christos p->bdaddr[3], p->bdaddr[4], p->bdaddr[5],
1435 1.1 christos p->addr_type);
1436 1.1 christos
1437 1.1 christos if (dbg != NULL) {
1438 1.1 christos dbg->sz = easprintf(&dbg->cp,
1439 1.1 christos DEVPATH_FMT_HDR
1440 1.1 christos DEVPATH_FMT(bdaddr: 0x%02x%02x%02x%02x%02x%02x\n)
1441 1.1 christos DEVPATH_FMT(addr_type: 0x%02x\n),
1442 1.1 christos DEVPATH_DAT_HDR(dp),
1443 1.1 christos p->bdaddr[0], p->bdaddr[1], p->bdaddr[2],
1444 1.1 christos p->bdaddr[3], p->bdaddr[4], p->bdaddr[5],
1445 1.1 christos p->addr_type);
1446 1.1 christos }
1447 1.1 christos }
1448 1.1 christos
1449 1.1 christos static void
1450 1.1 christos devpath_msg_dns(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
1451 1.1 christos { /* See 10.3.4.29 */
1452 1.1 christos struct { /* Sub-Type 31 */
1453 1.1 christos devpath_t hdr; /* Length = 5 + n */
1454 1.1 christos uint8_t IsIPv6;
1455 1.1 christos uint8_t addr[];
1456 1.1 christos } __packed *p = (void *)dp;
1457 1.1 christos __CTASSERT(sizeof(*p) == 5);
1458 1.1 christos size_t cnt, n, sz;
1459 1.1 christos
1460 1.1 christos /* XXX: This is ugly at best */
1461 1.1 christos
1462 1.1 christos n = p->hdr.Length - sizeof(*p);
1463 1.1 christos sz = p->IsIPv6 ? sizeof(struct in6_addr) : sizeof(uint32_t);
1464 1.1 christos cnt = n / sz;
1465 1.1 christos assert(n == cnt * sz);
1466 1.1 christos assert(cnt > 0);
1467 1.1 christos
1468 1.1 christos if (cnt > 0) { /* XXX: should always be true */
1469 1.1 christos char *bp;
1470 1.1 christos
1471 1.1 christos #define DNS_PREFIX "Dns("
1472 1.1 christos if (p->IsIPv6) {
1473 1.1 christos struct in6_addr *ip6addr = (void *)p->addr;
1474 1.1 christos
1475 1.1 christos bp = path->cp = malloc(sizeof(DNS_PREFIX) +
1476 1.1 christos cnt * INET6_ADDRSTRLEN);
1477 1.1 christos bp = stpcpy(bp, DNS_PREFIX);
1478 1.1 christos bp = stpcpy(bp, ipv6_addr(&ip6addr[0]));
1479 1.1 christos for (size_t i = 1; i < cnt; i++) {
1480 1.1 christos *bp++ = ',';
1481 1.1 christos bp = stpcpy(bp, ipv6_addr(&ip6addr[i]));
1482 1.1 christos }
1483 1.1 christos *bp = ')';
1484 1.1 christos }
1485 1.1 christos else { /* IPv4 */
1486 1.1 christos uint32_t *ip4addr = (void *)p->addr;
1487 1.1 christos
1488 1.1 christos bp = path->cp = malloc(sizeof(DNS_PREFIX) +
1489 1.1 christos cnt * INET_ADDRSTRLEN);
1490 1.1 christos bp = stpcpy(bp, DNS_PREFIX);
1491 1.1 christos bp = stpcpy(bp, ipv4_addr(ip4addr[0]));
1492 1.1 christos for (size_t i = 1; i < cnt; i++) {
1493 1.1 christos *bp++ = ',';
1494 1.1 christos bp = stpcpy(bp, ipv4_addr(ip4addr[i]));
1495 1.1 christos }
1496 1.1 christos *bp = ')';
1497 1.1 christos }
1498 1.1 christos #undef DNS_PREFIX
1499 1.1 christos path->sz = strlen(bp);
1500 1.1 christos }
1501 1.1 christos
1502 1.1 christos if (dbg != NULL) {
1503 1.1 christos dbg->sz = easprintf(&dbg->cp,
1504 1.1 christos DEVPATH_FMT_HDR
1505 1.1 christos DEVPATH_FMT(IsIPv6: %d\n),
1506 1.1 christos DEVPATH_DAT_HDR(dp),
1507 1.1 christos p->IsIPv6);
1508 1.1 christos
1509 1.1 christos if (cnt > 0) { /* XXX: should always be true */
1510 1.1 christos char *bp, *tp;
1511 1.1 christos
1512 1.1 christos bp = dbg->cp;
1513 1.1 christos if (p->IsIPv6) {
1514 1.1 christos struct in6_addr *ip6addr = (void *)p->addr;
1515 1.1 christos
1516 1.1 christos for (size_t i = 0; i < cnt; i++) {
1517 1.1 christos uint8_t *cp;
1518 1.1 christos
1519 1.1 christos cp = ip6addr[i].__u6_addr.__u6_addr8;
1520 1.1 christos tp = bp;
1521 1.1 christos dbg->sz += easprintf(&bp,
1522 1.1 christos "%s"
1523 1.2 martin DEVPATH_FMT(addr[%zu]:)
1524 1.1 christos " %02x %02x %02x %02x"
1525 1.1 christos " %02x %02x %02x %02x"
1526 1.1 christos " %02x %02x %02x %02x"
1527 1.1 christos " %02x %02x %02x %02x\n",
1528 1.1 christos tp,
1529 1.1 christos i,
1530 1.1 christos cp[0], cp[1], cp[2], cp[3],
1531 1.1 christos cp[4], cp[5], cp[6], cp[7],
1532 1.1 christos cp[8], cp[9], cp[10], cp[11],
1533 1.1 christos cp[12], cp[13], cp[14], cp[15]);
1534 1.1 christos free(tp);
1535 1.1 christos }
1536 1.1 christos }
1537 1.1 christos else { /* IPv4 */
1538 1.1 christos uint32_t *ip4addr = (void *)p->addr;
1539 1.1 christos
1540 1.1 christos for (size_t i = 0; i < cnt; i++) {
1541 1.1 christos tp = bp;
1542 1.1 christos dbg->sz += easprintf(&bp,
1543 1.1 christos "%s"
1544 1.1 christos DEVPATH_FMT(addr[i]: 0x%08x\n),
1545 1.1 christos tp, ip4addr[i]);
1546 1.1 christos free(tp);
1547 1.1 christos }
1548 1.1 christos }
1549 1.1 christos }
1550 1.1 christos }
1551 1.1 christos }
1552 1.1 christos
1553 1.1 christos static void
1554 1.1 christos devpath_msg_nvdimm(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
1555 1.1 christos { /* See 10.3.4.30 */
1556 1.1 christos struct { /* Sub-Type 32 */
1557 1.1 christos devpath_t hdr; /* Length = 20 */
1558 1.1 christos uuid_t UUID;
1559 1.1 christos } __packed *p = (void *)dp;
1560 1.1 christos __CTASSERT(sizeof(*p) == 20);
1561 1.1 christos char uuid_str[UUID_STR_LEN];
1562 1.1 christos
1563 1.1 christos uuid_snprintf(uuid_str, sizeof(uuid_str), &p->UUID);
1564 1.1 christos path->sz = easprintf(&path->cp, "NVDIMM(%s)", uuid_str);
1565 1.1 christos
1566 1.1 christos if (dbg != NULL) {
1567 1.1 christos dbg->sz = easprintf(&dbg->cp,
1568 1.1 christos DEVPATH_FMT_HDR,
1569 1.1 christos DEVPATH_DAT_HDR(dp)
1570 1.1 christos );
1571 1.1 christos }
1572 1.1 christos }
1573 1.1 christos
1574 1.1 christos static void
1575 1.1 christos devpath_msg_restservice(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
1576 1.1 christos { /* See 10.3.4.31 */
1577 1.1 christos struct { /* Sub-Type 33 */
1578 1.1 christos devpath_t hdr; /* Length = 6 */
1579 1.1 christos uint8_t RestService;
1580 1.1 christos #define REST_SERVICE_REDFISH 0x01
1581 1.1 christos #define REST_SERVICE_ODATA 0x02
1582 1.1 christos uint8_t AccessMode;
1583 1.1 christos #define ACCESS_MODE_IN_BAND 0x01
1584 1.1 christos #define ACCESS_MODE_OUT_OF_BAND 0x02
1585 1.1 christos } __packed *p = (void *)dp;
1586 1.1 christos __CTASSERT(sizeof(*p) == 6);
1587 1.1 christos
1588 1.5 riastrad path->sz = easprintf(&path->cp, "RestService(%d,%d)",
1589 1.5 riastrad p->RestService, p->AccessMode);
1590 1.1 christos
1591 1.1 christos if (dbg != NULL) {
1592 1.1 christos dbg->sz = easprintf(&dbg->cp,
1593 1.1 christos DEVPATH_FMT_HDR
1594 1.1 christos DEVPATH_FMT(RestService: 0x%02x(%s)\n)
1595 1.1 christos DEVPATH_FMT(AccessMode: 0x%02x(%s)\n),
1596 1.1 christos DEVPATH_DAT_HDR(dp),
1597 1.1 christos p->RestService,
1598 1.1 christos p->RestService == REST_SERVICE_REDFISH ? "RedFish" :
1599 1.1 christos p->RestService == REST_SERVICE_ODATA ? "OData" : "???",
1600 1.1 christos p->AccessMode,
1601 1.1 christos p->AccessMode == ACCESS_MODE_IN_BAND ? "In-Band" :
1602 1.5 riastrad p->AccessMode == ACCESS_MODE_OUT_OF_BAND ? "Out-of-Band"
1603 1.5 riastrad : "???");
1604 1.1 christos }
1605 1.1 christos }
1606 1.1 christos
1607 1.1 christos static void
1608 1.1 christos devpath_msg_nvmeof(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
1609 1.1 christos { /* See 10.3.4.32 */
1610 1.1 christos struct { /* Sub-Type 34 */
1611 1.1 christos devpath_t hdr; /* Length = 21 XXX: 20 in text */
1612 1.1 christos uint8_t NIDT;
1613 1.1 christos union {
1614 1.1 christos uint64_t dw[2];
1615 1.1 christos uint8_t csi;
1616 1.1 christos uint64_t ieuid;
1617 1.1 christos uuid_t uuid;
1618 1.1 christos } NID; /* big-endian */
1619 1.1 christos uint8_t SubsystemNQN[]; /* UTF-8 null-terminated */
1620 1.1 christos } __packed *p = (void *)dp;
1621 1.1 christos __CTASSERT(sizeof(*p) == 21);
1622 1.1 christos char uuid_str[UUID_STR_LEN];
1623 1.1 christos
1624 1.1 christos /*
1625 1.1 christos * See 5.1.13.2.3 of NVM-Express Base Specification Rev 2.1,
1626 1.1 christos * in particular, Fig 315 on page 332.
1627 1.1 christos */
1628 1.1 christos switch (p->NIDT) {
1629 1.1 christos case 0:
1630 1.1 christos path->sz = easprintf(&path->cp, "NVMEoF(%s)", p->SubsystemNQN);
1631 1.1 christos break;
1632 1.1 christos case 1:
1633 1.2 martin path->sz = easprintf(&path->cp, "NVMEoF(%s,0x%016" PRIx64
1634 1.2 martin ")", p->SubsystemNQN, p->NID.ieuid);
1635 1.1 christos break;
1636 1.1 christos case 2:
1637 1.1 christos case 3:
1638 1.1 christos uuid_snprintf(uuid_str, sizeof(uuid_str), &p->NID.uuid);
1639 1.5 riastrad path->sz = easprintf(&path->cp, "NVMEoF(%s,%s)",
1640 1.5 riastrad p->SubsystemNQN, uuid_str);
1641 1.1 christos break;
1642 1.1 christos case 4:
1643 1.5 riastrad path->sz = easprintf(&path->cp, "NVMEoF(%s,0x%02x)",
1644 1.5 riastrad p->SubsystemNQN, p->NID.csi);
1645 1.1 christos break;
1646 1.1 christos default:
1647 1.5 riastrad path->sz = easprintf(&path->cp, "NVMEoF(%s,unknown)",
1648 1.5 riastrad p->SubsystemNQN);
1649 1.1 christos break;
1650 1.1 christos }
1651 1.1 christos
1652 1.1 christos if (dbg != NULL) {
1653 1.1 christos dbg->sz = easprintf(&dbg->cp,
1654 1.1 christos DEVPATH_FMT_HDR
1655 1.1 christos DEVPATH_FMT(NIDT: 0x%02x\n)
1656 1.2 martin DEVPATH_FMT(NID:) " 0x%016" PRIx64 "%016" PRIx64 "\n"
1657 1.1 christos DEVPATH_FMT(SubsystemNQN: '%s'\n),
1658 1.1 christos DEVPATH_DAT_HDR(dp),
1659 1.1 christos p->NIDT,
1660 1.1 christos p->NID.dw[0], p->NID.dw[1],
1661 1.1 christos p->SubsystemNQN);
1662 1.1 christos }
1663 1.1 christos }
1664 1.1 christos
1665 1.1 christos PUBLIC void
1666 1.1 christos devpath_msg(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
1667 1.1 christos {
1668 1.1 christos
1669 1.1 christos assert(dp->Type = 3);
1670 1.1 christos
1671 1.1 christos switch (dp->SubType) {
1672 1.1 christos case 1: devpath_msg_atapi(dp, path, dbg); return;
1673 1.1 christos case 2: devpath_msg_scsi(dp, path, dbg); return;
1674 1.1 christos case 3: devpath_msg_fibre(dp, path, dbg); return;
1675 1.1 christos case 4: devpath_msg_11394(dp, path, dbg); return;
1676 1.1 christos case 5: devpath_msg_usb(dp, path, dbg); return;
1677 1.1 christos case 6: devpath_msg_i2o(dp, path, dbg); return;
1678 1.1 christos case 9: devpath_msg_infiniband(dp, path, dbg); return;
1679 1.1 christos case 10: devpath_msg_vendor(dp, path, dbg); return;
1680 1.1 christos case 11: devpath_msg_mac(dp, path, dbg); return;
1681 1.1 christos case 12: devpath_msg_ipv4(dp, path, dbg); return;
1682 1.1 christos case 13: devpath_msg_ipv6(dp, path, dbg); return;
1683 1.1 christos case 14: devpath_msg_uart(dp, path, dbg); return;
1684 1.1 christos case 15: devpath_msg_usbclass(dp, path, dbg); return;
1685 1.1 christos case 16: devpath_msg_usbwwid(dp, path, dbg); return;
1686 1.1 christos case 17: devpath_msg_unit(dp, path, dbg); return;
1687 1.1 christos case 18: devpath_msg_sata(dp, path, dbg); return;
1688 1.1 christos case 19: devpath_msg_iscsi(dp, path, dbg); return;
1689 1.1 christos case 20: devpath_msg_vlan(dp, path, dbg); return;
1690 1.1 christos case 21: devpath_msg_fibreex(dp, path, dbg); return;
1691 1.1 christos case 22: devpath_msg_sasex(dp, path, dbg); return;
1692 1.1 christos case 23: devpath_msg_nvme(dp, path, dbg); return;
1693 1.1 christos case 24: devpath_msg_uri(dp, path, dbg); return;
1694 1.1 christos case 25: devpath_msg_ufs(dp, path, dbg); return;
1695 1.1 christos case 26: devpath_msg_sd(dp, path, dbg); return;
1696 1.1 christos case 27: devpath_msg_bluetooth(dp, path, dbg); return;
1697 1.1 christos case 28: devpath_msg_wifi(dp, path, dbg); return;
1698 1.1 christos case 29: devpath_msg_emmc(dp, path, dbg); return;
1699 1.1 christos case 30: devpath_msg_bluetoothle(dp, path, dbg); return;
1700 1.1 christos case 31: devpath_msg_dns(dp, path, dbg); return;
1701 1.1 christos case 32: devpath_msg_nvdimm(dp, path, dbg); return;
1702 1.1 christos case 33: devpath_msg_restservice(dp, path, dbg); return;
1703 1.1 christos case 34: devpath_msg_nvmeof(dp, path, dbg); return;
1704 1.1 christos default: devpath_unsupported(dp, path, dbg); return;
1705 1.1 christos }
1706 1.1 christos }
1707