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