1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2025 Oxide Computer Company 14 */ 15 16 /* 17 * libi2c error manipulation and translation. 18 */ 19 20 #include <stdarg.h> 21 #include <stdio.h> 22 #include <string.h> 23 #include <upanic.h> 24 #include <sys/debug.h> 25 #include <sys/sysmacros.h> 26 27 #include "libi2c_impl.h" 28 29 static void 30 i2c_error_common(i2c_err_data_t *ep, i2c_err_t err, int32_t sys, 31 const char *fmt, va_list ap) 32 { 33 int ret; 34 35 ep->ie_err = err; 36 ep->ie_syserr = sys; 37 ep->ie_ctrl_err = I2C_CTRL_E_OK; 38 ret = vsnprintf(ep->ie_errmsg, sizeof (ep->ie_errmsg), fmt, ap); 39 if (ret >= sizeof (ep->ie_errmsg)) { 40 ep->ie_errlen = sizeof (ep->ie_errmsg) - 1; 41 } else if (ret <= 0) { 42 ep->ie_errlen = 0; 43 ep->ie_errmsg[0] = '\0'; 44 } else { 45 ep->ie_errlen = (size_t)ret; 46 } 47 } 48 49 bool 50 i2c_error(i2c_hdl_t *hdl, i2c_err_t err, int32_t sys, const char *fmt, ...) 51 { 52 va_list ap; 53 54 va_start(ap, fmt); 55 i2c_error_common(&hdl->ih_err, err, sys, fmt, ap); 56 va_end(ap); 57 58 return (false); 59 } 60 61 static bool 62 i2c_success_common(i2c_err_data_t *err) 63 { 64 err->ie_err = I2C_ERR_OK; 65 err->ie_syserr = 0; 66 err->ie_ctrl_err = I2C_CTRL_E_OK; 67 err->ie_errmsg[0] = '\0'; 68 err->ie_errlen = 0; 69 70 return (true); 71 } 72 73 bool 74 i2c_success(i2c_hdl_t *hdl) 75 { 76 return (i2c_success_common(&hdl->ih_err)); 77 } 78 79 i2c_err_t 80 i2c_err(i2c_hdl_t *hdl) 81 { 82 return (hdl->ih_err.ie_err); 83 } 84 85 i2c_ctrl_error_t 86 i2c_ctrl_err(i2c_hdl_t *hdl) 87 { 88 return (hdl->ih_err.ie_ctrl_err); 89 } 90 91 int32_t 92 i2c_syserr(i2c_hdl_t *hdl) 93 { 94 return (hdl->ih_err.ie_syserr); 95 } 96 97 const char * 98 i2c_errmsg(i2c_hdl_t *hdl) 99 { 100 return (hdl->ih_err.ie_errmsg); 101 } 102 103 const char * 104 i2c_errtostr(i2c_hdl_t *hdl, i2c_err_t err) 105 { 106 switch (err) { 107 case I2C_ERR_OK: 108 return ("I2C_ERR_OK"); 109 case I2C_ERR_CONTROLLER: 110 return ("I2C_ERR_CONTROLLER"); 111 case I2C_ERR_BAD_PTR: 112 return ("I2C_ERR_BAD_PTR"); 113 case I2C_ERR_NO_MEM: 114 return ("I2C_ERR_NO_MEM"); 115 case I2C_ERR_LIBDEVINFO: 116 return ("I2C_ERR_LIBDEVINFO"); 117 case I2C_ERR_BAD_DEVI: 118 return ("I2C_ERR_BAD_DEVI"); 119 case I2C_ERR_INTERNAL: 120 return ("I2C_ERR_INTERNAL"); 121 case I2C_ERR_PRIVS: 122 return ("I2C_ERR_PRIVS"); 123 case I2C_ERR_OPEN_DEV: 124 return ("I2C_ERR_OPEN_DEV"); 125 case I2C_ERR_BAD_CONTROLLER: 126 return ("I2C_ERR_BAD_CONTROLLER"); 127 case I2C_ERR_BAD_PORT: 128 return ("I2C_ERR_BAD_PORT"); 129 case I2C_ERR_BAD_DEVICE: 130 return ("I2C_ERR_BAD_DEVICE"); 131 case I2C_ERR_BAD_ADDR_TYPE: 132 return ("I2C_ERR_BAD_ADDR_TYPE"); 133 case I2C_ERR_BAD_ADDR: 134 return ("I2C_ERR_BAD_ADDR"); 135 case I2C_ERR_UNSUP_ADDR_TYPE: 136 return ("I2C_ERR_UNSUP_ADDR_TYPE"); 137 case I2C_ERR_ADDR_RSVD: 138 return ("I2C_ERR_ADDR_RSVD"); 139 case I2C_ERR_ADDR_IN_USE: 140 return ("I2C_ERR_ADDR_IN_USE"); 141 case I2C_ERR_ADDR_UNKNOWN: 142 return ("I2C_ERR_ADDR_UNKNOWN"); 143 case I2C_ERR_IO_READ_LEN_RANGE: 144 return ("I2C_ERR_IO_READ_LEN_RANGE"); 145 case I2C_ERR_IO_WRITE_LEN_RANGE: 146 return ("I2C_ERR_IO_WRITE_LEN_RANGE"); 147 case I2C_ERR_IO_REQ_MISSING_FIELDS: 148 return ("I2C_ERR_IO_REQ_MISSING_FIELDS"); 149 case I2C_ERR_IO_REQ_IO_INVALID: 150 return ("I2C_ERR_IO_REQ_IO_INVALID"); 151 case I2C_ERR_CANT_XLATE_IO_REQ: 152 return ("I2C_ERR_CANT_XLATE_IO_REQ"); 153 case I2C_ERR_SMBUS_OP_UNSUP: 154 return ("I2C_ERR_SMBUS_OP_UNSUP"); 155 case I2C_ERR_LOCK_WAIT_SIGNAL: 156 return ("I2C_ERR_LOCK_WAIT_SIGNAL"); 157 case I2C_ERR_LOCK_WOULD_BLOCK: 158 return ("I2C_ERR_LOCK_WOULD_BLOCK"); 159 case I2C_ERR_NO_KERN_MEM: 160 return ("I2C_ERR_NO_KERN_MEM"); 161 case I2C_ERR_BAD_DEV_NAME: 162 return ("I2C_ERR_BAD_DEV_NAME"); 163 case I2C_ERR_COMPAT_LEN_RANGE: 164 return ("I2C_ERR_COMPAT_LEN_RANGE"); 165 case I2C_ERR_ADD_DEV_REQ_MISSING_FIELDS: 166 return ("I2C_ERR_ADD_DEV_REQ_MISSING_FIELDS"); 167 case I2C_ERR_NEXUS: 168 return ("I2C_ERR_NEXUS"); 169 case I2C_ERR_OP_IN_PROGRESS: 170 return ("I2C_ERR_OP_IN_PROGRESS"); 171 case I2C_ERR_PROP_UNSUP: 172 return ("I2C_ERR_PROP_UNSUP"); 173 case I2C_ERR_BAD_PROP: 174 return ("I2C_ERR_BAD_PROP"); 175 case I2C_ERR_SET_PROP_UNSUP: 176 return ("I2C_ERR_SET_PROP_UNSUP"); 177 case I2C_ERR_PROP_READ_ONLY: 178 return ("I2C_ERR_PROP_READ_ONLY"); 179 case I2C_ERR_PROP_BUF_TOO_SMALL: 180 return ("I2C_ERR_PROP_BUF_TOO_SMALL"); 181 case I2C_ERR_PROP_BUF_TOO_BIG: 182 return ("I2C_ERR_PROP_BUF_TOO_BIG"); 183 case I2C_ERR_BAD_PROP_VAL: 184 return ("I2C_ERR_BAD_PROP_VAL"); 185 case I2C_ERR_NO_PROP_DEF_VAL: 186 return ("I2C_ERR_NO_PROP_DEF_VAL"); 187 case I2C_ERR_PROP_TYPE_MISMATCH: 188 return ("I2C_ERR_PROP_TYPE_MISMATCH"); 189 case I2C_ERR_BUF_TOO_SMALL: 190 return ("I2C_ERR_BUF_TOO_SMALL"); 191 default: 192 return ("unknown error"); 193 } 194 } 195 196 const char * 197 i2c_ctrl_errtostr(i2c_hdl_t *hdl, i2c_ctrl_error_t err) 198 { 199 switch (err) { 200 case I2C_CTRL_E_OK: 201 return ("I2C_CTRL_E_OK"); 202 case I2C_CTRL_E_INTERNAL: 203 return ("I2C_CTRL_E_INTERNAL"); 204 case I2C_CTRL_E_DRIVER: 205 return ("I2C_CTRL_E_DRIVER"); 206 case I2C_CTRL_E_UNSUP_CMD: 207 return ("I2C_CTRL_E_UNSUP_CMD"); 208 case I2C_CTRL_E_BUS_BUSY: 209 return ("I2C_CTRL_E_BUS_BUSY"); 210 case I2C_CTRL_E_ADDR_NACK: 211 return ("I2C_CTRL_E_ADDR_NACK"); 212 case I2C_CTRL_E_DATA_NACK: 213 return ("I2C_CTRL_E_DATA_NACK"); 214 case I2C_CTRL_E_NACK: 215 return ("I2C_CTRL_E_NACK"); 216 case I2C_CTRL_E_ARB_LOST: 217 return ("I2C_CTRL_E_ARB_LOST"); 218 case I2C_CTRL_E_BAD_ACK: 219 return ("I2C_CTRL_E_BAD_ACK"); 220 case I2C_CTRL_E_REQ_TO: 221 return ("I2C_CTRL_E_REQ_TO"); 222 case I2C_CTRL_E_BAD_SMBUS_RLEN: 223 return ("I2C_CTRL_E_BAD_SMBUS_RLEN"); 224 case I2C_CTRL_E_SMBUS_CLOCK_LOW: 225 return ("I2C_CTRL_E_SMBUS_CLOCK_LOW"); 226 default: 227 return ("unkonwn error"); 228 } 229 } 230 231 /* 232 * Most of our ioctls are designed to give us a semantic error. However, there 233 * are cases where we may fail outside of that. We opt to abort on a subset of 234 * these that represent gross library programmer error: mainly EBADF and EFAULT. 235 * Note, EFAULT generally covers the core ioctl structures and not any 236 * additional buffers that are passed in, therefore if this triggers then we 237 * have done something terribly wrong. 238 */ 239 bool 240 i2c_ioctl_syserror(i2c_hdl_t *hdl, int err, const char *desc) 241 { 242 switch (err) { 243 case EFAULT: 244 case EBADF: { 245 const char *base = "fatal libi2c internal programming error: " 246 "failed to issue ioctl"; 247 char msg[1024]; 248 int ret; 249 const char *up; 250 size_t ulen; 251 252 ret = snprintf(msg, sizeof (msg), "%s %s: %s (hdl %p)", 253 base, desc, strerror(err), hdl); 254 if (ret >= sizeof (msg)) { 255 ulen = sizeof (msg); 256 up = msg; 257 } else if (ret <= 0) { 258 up = base; 259 ulen = strlen(base) + 1; 260 } else { 261 ulen = (size_t)ret; 262 up = msg; 263 } 264 265 upanic(up, ulen); 266 } 267 case EPERM: 268 return (i2c_error(hdl, I2C_ERR_PRIVS, err, "failed to issue %s " 269 "ioctl due to missing privileges", desc)); 270 default: 271 return (i2c_error(hdl, I2C_ERR_INTERNAL, err, 272 "failed to issue %s ioctl due to unexpected system error: " 273 "%s", desc, strerrordesc_np(err))); 274 } 275 } 276 277 typedef struct { 278 i2c_errno_t kl_kern; 279 i2c_err_t kl_lib; 280 const char *kl_desc; 281 } i2c_ktolmap_t; 282 283 /* 284 * This facilitates mapping kernel errors to user library errors along with a 285 * short description. This is ordered based on the order of the kernel ioctls so 286 * we can more easily spot missing entries. The description is used to help 287 * users understand what happened. 288 */ 289 static const i2c_ktolmap_t i2c_ktolmap[] = { 290 /* 291 * We skip I2C_CORE_E_OK because it not reach here. We also handle the 292 * controller error, I2C_CORE_E_CONTROLLER, specifically so it is not 293 * translated here 294 */ 295 { I2C_CORE_E_BAD_ADDR_TYPE, I2C_ERR_BAD_ADDR_TYPE, "invalid I2C " 296 "address family type" }, 297 { I2C_CORE_E_BAD_ADDR, I2C_ERR_BAD_ADDR, "invalid I2C address" }, 298 { I2C_CORE_E_UNSUP_ADDR_TYPE, I2C_ERR_UNSUP_ADDR_TYPE, "address " 299 "family not supported by the controller" }, 300 { I2C_CORE_E_ADDR_RSVD, I2C_ERR_ADDR_RSVD, "I2C address is reserved" }, 301 { I2C_CORE_E_ADDR_IN_USE, I2C_ERR_ADDR_IN_USE, "I2C addrses is already " 302 "used" }, 303 { I2C_CORE_E_ADDR_REFCNT, I2C_ERR_INTERNAL, "address could not be " 304 "assigned due to kernel reference count exhaustion" }, 305 { I2C_CORE_E_UNKNOWN_ADDR, I2C_ERR_ADDR_UNKNOWN, "I2C address does not " 306 "map to a known device" }, 307 { I2C_CORE_E_CANT_XLATE_REQ, I2C_ERR_CANT_XLATE_IO_REQ, "I/O request " 308 "could not be translated to something the controller supports" }, 309 { I2C_CORE_E_NEED_READ_OR_WRITE, I2C_ERR_IO_REQ_IO_INVALID, "request " 310 "requires data to transmit or receive, but neither specified" }, 311 /* 312 * We have purposefully skipped I2C_CORE_E_BAD_I2C_REQ_FLAGS and 313 * I2C_CORE_E_BAD_SMBUS_REQ_FLAGS as these are not flags that users are 314 * able to set and therefore the only reason these should be wrong is if 315 * we screwed something up in the library. 316 */ 317 { I2C_CORE_E_BAD_I2C_REQ_READ_LEN, I2C_ERR_IO_READ_LEN_RANGE, "invalid " 318 "receive length" }, 319 { I2C_CORE_E_BAD_I2C_REQ_WRITE_LEN, I2C_ERR_IO_WRITE_LEN_RANGE, 320 "invalid transmit length" }, 321 { I2C_CORE_E_BAD_SMBUS_READ_LEN, I2C_ERR_IO_READ_LEN_RANGE, "invalid " 322 "receive length" }, 323 { I2C_CORE_E_BAD_SMBUS_WRITE_LEN, I2C_ERR_IO_WRITE_LEN_RANGE, 324 "invalid transmit length" }, 325 { I2C_CORE_E_UNSUP_SMBUS_OP, I2C_ERR_SMBUS_OP_UNSUP, "SMBus operation " 326 "unsupported by controller or system" }, 327 { I2C_CORE_E_LOCK_WOULD_BLOCK, I2C_ERR_LOCK_WOULD_BLOCK, "lock not " 328 "available and no blocking allowed" }, 329 { I2C_CORE_E_LOCK_WAIT_SIGNAL, I2C_ERR_LOCK_WAIT_SIGNAL, "signal " 330 "received while blocking" }, 331 /* 332 * We have purposefully skipped the nvlist device related errors, 333 * I2C_IOCTL_E_NVL_TOO_BIG, I2C_IOCTL_E_NVL_INVALID, 334 * I2C_IOCTL_E_NVL_KEY_MISSING, I2C_IOCTL_E_NVL_KEY_UNKNOWN, and 335 * I2C_IOCTL_E_NVL_KEY_BAD_TYPE. These are things that generally only 336 * the library can screw up. 337 */ 338 { I2C_IOCTL_E_BAD_USER_DATA, I2C_ERR_BAD_PTR, "the kernel detected an " 339 "invalid user buffer while trying to read/write the passed in " 340 "buffer" }, 341 { I2C_IOCTL_E_NO_KERN_MEM, I2C_ERR_NO_KERN_MEM, "the kerenl failed " 342 "to allocate memory for this operation" }, 343 { I2C_IOCTL_E_BAD_DEV_NAME, I2C_ERR_BAD_DEV_NAME, "invalid device " 344 "or compatible name" }, 345 { I2C_IOCTL_E_COMPAT_LEN_RANGE, I2C_ERR_COMPAT_LEN_RANGE, "invalid " 346 "compatible string length" }, 347 { I2C_IOCTL_E_NEXUS, I2C_ERR_NEXUS, "unexpected kernel nexus driver " 348 "error" }, 349 /* 350 * We have purposefully skipped I2C_IOCTL_E_NO_BUS_LOCK_NEXUS as there 351 * is no way to take an explicit lock in userland right now. 352 */ 353 { I2C_IOCTL_E_IN_PROGRESS, I2C_ERR_OP_IN_PROGRESS, "cannot perform " 354 "requested operation, handle already performing one" }, 355 /* 356 * All I2C_CLIENT class errors are skipped as they should not be 357 * returned to userland. 358 */ 359 { I2C_PROP_E_UNSUP, I2C_ERR_PROP_UNSUP, "property unsupported by " 360 "controller" }, 361 { I2C_PROP_E_UNKNOWN, I2C_ERR_BAD_PROP, "unknown property" }, 362 { I2C_PROP_E_READ_ONLY, I2C_ERR_PROP_READ_ONLY, "property is " 363 "read-only" }, 364 { I2C_PROP_E_SMALL_BUF, I2C_ERR_PROP_BUF_TOO_SMALL, "data buffer too " 365 "small for property" }, 366 { I2C_PROP_E_TOO_BIG_BUF, I2C_ERR_PROP_BUF_TOO_BIG, "data buffer too " 367 "big for property" }, 368 /* 369 * Indicates that the property value is invalid. 370 */ 371 { I2C_PROP_E_BAD_VAL, I2C_ERR_BAD_PROP, "invalid property value" }, 372 /* 373 * Indicates that the controller doesn't support setting properties. 374 */ 375 { I2C_PROP_E_SET_UNSUP, I2C_ERR_SET_PROP_UNSUP, "controller does not " 376 "support setting properties" }, 377 /* 378 * Currently all MUX class errors are skipped as they aren't really 379 * expected here. 380 */ 381 }; 382 383 bool 384 i2c_ioctl_error(i2c_hdl_t *hdl, const i2c_error_t *ioc, const char *desc) 385 { 386 int ret; 387 i2c_err_data_t *err = &hdl->ih_err; 388 VERIFY3U(ioc->i2c_error, !=, I2C_CORE_E_OK); 389 390 err->ie_syserr = 0; 391 392 if (ioc->i2c_error == I2C_CORE_E_CONTROLLER) { 393 const char *code = i2c_ctrl_errtostr(hdl, ioc->i2c_ctrl); 394 395 err->ie_err = I2C_ERR_CONTROLLER; 396 err->ie_ctrl_err = ioc->i2c_ctrl; 397 ret = snprintf(err->ie_errmsg, sizeof (err->ie_errmsg), 398 "failed to execute %s command: received controller " 399 "error %s (0x%x)", desc, code, ioc->i2c_ctrl); 400 } else { 401 const i2c_ktolmap_t *map = NULL; 402 for (size_t i = 0; i < ARRAY_SIZE(i2c_ktolmap); i++) { 403 if (i2c_ktolmap[i].kl_kern == ioc->i2c_error) { 404 map = &i2c_ktolmap[i]; 405 break; 406 } 407 } 408 409 if (map != NULL) { 410 err->ie_err = map->kl_lib; 411 ret = snprintf(err->ie_errmsg, sizeof (err->ie_errmsg), 412 "failed to execute %s command: %s", desc, 413 map->kl_desc); 414 } else { 415 err->ie_err = I2C_ERR_INTERNAL; 416 ret = snprintf(err->ie_errmsg, sizeof (err->ie_errmsg), 417 "failed to execute %s command: failed to map " 418 "kernel error 0x%x to a known cause", desc, 419 ioc->i2c_error); 420 } 421 } 422 423 if (ret >= sizeof (err->ie_errmsg)) { 424 err->ie_errlen = sizeof (err->ie_errlen) - 1; 425 } else if (ret <= 0) { 426 err->ie_errlen = 0; 427 err->ie_errmsg[0] = '\0'; 428 } else { 429 err->ie_errlen = (size_t)ret; 430 } 431 432 return (false); 433 } 434 435 bool 436 i2c_nvlist_error(i2c_hdl_t *hdl, int ret, const char *desc) 437 { 438 if (ret == 0) { 439 return (true); 440 } 441 442 if (ret == ENOMEM) { 443 return (i2c_error(hdl, I2C_ERR_NO_MEM, ret, "failed to " 444 "allocate memory to %s", desc)); 445 } 446 447 return (i2c_error(hdl, I2C_ERR_INTERNAL, ret, "unexpected internal " 448 "error while trying to %s", desc)); 449 } 450