1*bbf21555SRichard Lowe.\" 2*bbf21555SRichard Lowe.\" This file and its contents are supplied under the terms of the 3*bbf21555SRichard Lowe.\" Common Development and Distribution License ("CDDL"), version 1.0. 4*bbf21555SRichard Lowe.\" You may only use this file in accordance with the terms of version 5*bbf21555SRichard Lowe.\" 1.0 of the CDDL. 6*bbf21555SRichard Lowe.\" 7*bbf21555SRichard Lowe.\" A full copy of the text of the CDDL should have accompanied this 8*bbf21555SRichard Lowe.\" source. A copy of the CDDL is also available via the Internet at 9*bbf21555SRichard Lowe.\" http://www.illumos.org/license/CDDL. 10*bbf21555SRichard Lowe.\" 11*bbf21555SRichard Lowe.\" 12*bbf21555SRichard Lowe.\" Copyright 2019 Joyent, Inc. 13*bbf21555SRichard Lowe.\" Copyright 2020 Oxide Computer Company 14*bbf21555SRichard Lowe.\" 15*bbf21555SRichard Lowe.Dd May 23, 2021 16*bbf21555SRichard Lowe.Dt UFM 4D 17*bbf21555SRichard Lowe.Os 18*bbf21555SRichard Lowe.Sh NAME 19*bbf21555SRichard Lowe.Nm ufm 20*bbf21555SRichard Lowe.Nd Upgradeable Firmware Module driver 21*bbf21555SRichard Lowe.Sh SYNOPSIS 22*bbf21555SRichard Lowe.Pa /dev/ufm 23*bbf21555SRichard Lowe.Lp 24*bbf21555SRichard Lowe.In sys/ddi_ufm.h 25*bbf21555SRichard Lowe.Sh DESCRIPTION 26*bbf21555SRichard LoweThe 27*bbf21555SRichard Lowe.Nm 28*bbf21555SRichard Lowedevice is a character special file that provides access to 29*bbf21555SRichard LoweUpgradeable Firmware Image information, as described in 30*bbf21555SRichard Lowe.Xr ddi_ufm 9E 31*bbf21555SRichard Lowevia a private ioctl interface. 32*bbf21555SRichard Lowe.Pp 33*bbf21555SRichard LoweThe UFM interfaces described below are used in the implementation of the 34*bbf21555SRichard Lowesystem through tools such as 35*bbf21555SRichard Lowe.Xr fwflash 8 36*bbf21555SRichard Loweor as part of the fault management architecture. 37*bbf21555SRichard Lowe.Sh FILES 38*bbf21555SRichard Lowe.Bl -tag -width Pa 39*bbf21555SRichard Lowe.It Pa /kernel/drv/amd64/ufm 40*bbf21555SRichard Lowe64-bit AMD64 ELF kernel driver 41*bbf21555SRichard Lowe.It Pa /kernel/drv/sparcv9/ufm 42*bbf21555SRichard Lowe64-bit SPARC ELF kernel driver 43*bbf21555SRichard Lowe.El 44*bbf21555SRichard Lowe.Sh IOCTLS 45*bbf21555SRichard LoweThe 46*bbf21555SRichard Lowe.Nm 47*bbf21555SRichard Lowedriver implements a versioned ioctl interface for accessing UFM facilities. 48*bbf21555SRichard LoweThe ioctl interfaces are defined in sys/ddi_ufm.h. 49*bbf21555SRichard LoweThe following ioctl cmds are supported by DDI_UFM_VERSION_ONE: 50*bbf21555SRichard Lowe.Bl -tag -width Dv 51*bbf21555SRichard Lowe.It Dv UFM_IOC_GETCAPS 52*bbf21555SRichard LoweThe 53*bbf21555SRichard Lowe.Dv UFM_IOC_GETCAPS 54*bbf21555SRichard Loweioctl is used to retrieve the set of DDI UFM capabilities supported by this 55*bbf21555SRichard Lowedevice instance. 56*bbf21555SRichard Lowe.Pp 57*bbf21555SRichard LoweThe ddi_ufm_cap_t type defines a bitfield enumerating the full set of DDI UFM 58*bbf21555SRichard Lowecapabilities. 59*bbf21555SRichard Lowe.Bd -literal 60*bbf21555SRichard Lowetypedef enum { 61*bbf21555SRichard Lowe DDI_UFM_CAP_REPORT = 1 << 0, 62*bbf21555SRichard Lowe DDI_UFM_CAP_READIMG = 1 << 1 63*bbf21555SRichard Lowe} ddi_ufm_cap_t; 64*bbf21555SRichard Lowe.Ed 65*bbf21555SRichard Lowe.Pp 66*bbf21555SRichard LoweThe capabilities mean: 67*bbf21555SRichard Lowe.Bl -tag -width Dv 68*bbf21555SRichard Lowe.It Dv DDI_UFM_CAP_REPORT 69*bbf21555SRichard LoweIndicates that the device is capable of reporting UFM information and 70*bbf21555SRichard Lowesupports the 71*bbf21555SRichard Lowe.Dv UFM_IOC_REPORT 72*bbf21555SRichard Loweand 73*bbf21555SRichard Lowe.Dv UFM_IOC_REPORTSZ 74*bbf21555SRichard Loweioctls. 75*bbf21555SRichard Lowe.It Dv DDI_UFM_CAP_READIMG 76*bbf21555SRichard LoweIndicates that the device is capable of retrieving a firmware image from 77*bbf21555SRichard Lowea slot and transferring it back to the caller. 78*bbf21555SRichard LoweThe 79*bbf21555SRichard Lowe.Dv UFM_IOC_READIMG 80*bbf21555SRichard Loweioctl is supported. 81*bbf21555SRichard Lowe.El 82*bbf21555SRichard Lowe.Pp 83*bbf21555SRichard LoweThe 84*bbf21555SRichard Lowe.Vt ufm_ioc_getcaps_t 85*bbf21555SRichard Lowestructure defines the input/output data for the 86*bbf21555SRichard Lowe.Dv UFM_IOC_GETCAPS 87*bbf21555SRichard Loweioctl. 88*bbf21555SRichard LoweCallers should specify the 89*bbf21555SRichard Lowe.Fa ufmg_version 90*bbf21555SRichard Loweand 91*bbf21555SRichard Lowe.Fa ufmg_devpath 92*bbf21555SRichard Lowefields. 93*bbf21555SRichard LoweOn success the 94*bbf21555SRichard Lowe.Fa ufmg_caps 95*bbf21555SRichard Lowefield will be filled in with a value indicating the 96*bbf21555SRichard Lowesupported UFM capabilities of the device specified in 97*bbf21555SRichard Lowe.Fa ufmg_devpath . 98*bbf21555SRichard Lowe.Bd -literal 99*bbf21555SRichard Lowetypedef struct ufm_ioc_getcaps { 100*bbf21555SRichard Lowe uint_t ufmg_version; /* DDI_UFM_VERSION_ONE */ 101*bbf21555SRichard Lowe uint_t ufmg_caps; /* UFM Caps */ 102*bbf21555SRichard Lowe char ufmg_devpath[MAXPATHLEN]; 103*bbf21555SRichard Lowe} ufm_ioc_getcaps_t; 104*bbf21555SRichard Lowe.Ed 105*bbf21555SRichard Lowe.It Dv UFM_IOC_REPORTSZ 106*bbf21555SRichard LoweThe 107*bbf21555SRichard Lowe.Dv UFM_IOC_REPORTSZ 108*bbf21555SRichard Loweioctl is used to retrieve the amount of space 109*bbf21555SRichard Lowe(in bytes) required to hold the UFM data for this device instance. 110*bbf21555SRichard LoweThis should be used to allocate a sufficiently sized buffer for the 111*bbf21555SRichard Lowe.Dv UFM_IOC_REPORT 112*bbf21555SRichard Loweioctl. 113*bbf21555SRichard Lowe.Pp 114*bbf21555SRichard LoweThe 115*bbf21555SRichard Lowe.Vt ufm_ioc_bufsz_t 116*bbf21555SRichard Lowestructure defines the input/output data for the 117*bbf21555SRichard Lowe.Dv UFM_IOC_REPORTSZ 118*bbf21555SRichard Loweioctl. 119*bbf21555SRichard LoweCallers should specify the 120*bbf21555SRichard Lowe.Fa ufbz_version 121*bbf21555SRichard Loweand 122*bbf21555SRichard Lowe.Fa ufbz_devpath 123*bbf21555SRichard Lowefields. 124*bbf21555SRichard LoweOn success the 125*bbf21555SRichard Lowe.Fa ufbz_size 126*bbf21555SRichard Lowefield will be filled in with the required buffer size. 127*bbf21555SRichard Lowe.Bd -literal 128*bbf21555SRichard Lowetypedef struct ufm_ioc_bufsz { 129*bbf21555SRichard Lowe uint_t ufbz_version; /* DDI_UFM_VERSION_ONE */ 130*bbf21555SRichard Lowe size_t ufbz_size; /* sz of buf to be returned by ioctl */ 131*bbf21555SRichard Lowe char ufbz_devpath[MAXPATHLEN]; 132*bbf21555SRichard Lowe} ufm_ioc_bufsz_t; 133*bbf21555SRichard Lowe.Ed 134*bbf21555SRichard Lowe.It Dv UFM_IOC_REPORT 135*bbf21555SRichard LoweThe 136*bbf21555SRichard Lowe.Dv UFM_IOC_REPORT 137*bbf21555SRichard Loweioctl returns UFM image and slot data in the form of a packed nvlist. 138*bbf21555SRichard LoweThe 139*bbf21555SRichard Lowe.Vt ufm_ioc_report_t 140*bbf21555SRichard Lowestructure defines the input/output data for the 141*bbf21555SRichard Lowe.Dv UFM_IOC_REPORT 142*bbf21555SRichard Loweioctl. 143*bbf21555SRichard LoweCallers should specify the ufmr_version, ufmr_bufsz and ufmr_devpath fields. 144*bbf21555SRichard LoweOn success, the ufmr_buf field will point to a packed nvlist containing the UFM 145*bbf21555SRichard Lowedata for the specified device instance. 146*bbf21555SRichard LoweThis data can be unpacked and decoded into an nvlist using 147*bbf21555SRichard Lowe.Xr nvlist_unpack 3NVPAIR . 148*bbf21555SRichard Lowe.Bd -literal 149*bbf21555SRichard Lowetypedef struct ufm_ioc_report { 150*bbf21555SRichard Lowe uint_t ufmr_version; /* DDI_UFM_VERSIONONE */ 151*bbf21555SRichard Lowe size_t ufmr_bufsz; /* size of caller-supplied buffer */ 152*bbf21555SRichard Lowe caddr_t ufmr_buf; /* buf to hold packed output nvl */ 153*bbf21555SRichard Lowe char ufmr_devpath[MAXPATHLEN]; 154*bbf21555SRichard Lowe} ufm_ioc_report_t; 155*bbf21555SRichard Lowe.Ed 156*bbf21555SRichard Lowe.Pp 157*bbf21555SRichard LoweDue to the asynchronous nature of the system, it's possible for a device to 158*bbf21555SRichard Loweundergo a configuration change in between a 159*bbf21555SRichard Lowe.Dv UFM_IOC_REPORTSZ 160*bbf21555SRichard Loweioctl and a subsequent 161*bbf21555SRichard Lowe.Dv UFM_IOC_REPORT 162*bbf21555SRichard Loweioctl that would alter the size of the buffer 163*bbf21555SRichard Lowerequired to hold the UFM data. 164*bbf21555SRichard Lowe.Pp 165*bbf21555SRichard LoweIf the size of buffer supplied in the 166*bbf21555SRichard Lowe.Dv UFM_IOC_REPORT 167*bbf21555SRichard Loweioctl is greater than is required to hold the UFM data, then 168*bbf21555SRichard Lowethe ioctl will succeed and the ufmr_bufsz field will be updated to reflect the 169*bbf21555SRichard Loweactual size of the returned UFM data. 170*bbf21555SRichard LoweIf the size of buffer supplied in the 171*bbf21555SRichard Lowe.Dv UFM_IOC_REPORT 172*bbf21555SRichard Loweioctl is less than what is required to hold the UFM data, 173*bbf21555SRichard Lowethe ioctl will fail with errno set to 174*bbf21555SRichard Lowe.Er EOVERFLOW . 175*bbf21555SRichard Lowe.It Dv UFM_IOC_READIMG 176*bbf21555SRichard LoweThe 177*bbf21555SRichard Lowe.Dv UFM_IOC_READIMG 178*bbf21555SRichard Loweioctl retrieves a firmware image and slot from a device. 179*bbf21555SRichard LoweThe 180*bbf21555SRichard Lowe.Vt ufm_ioc_readimg_t 181*bbf21555SRichard Lowestructure defines the input and output data for the ioctl. 182*bbf21555SRichard LoweDevices may have their own alignment and size constraints which may be 183*bbf21555SRichard Loweenforced upon issuing this ioctl. 184*bbf21555SRichard LoweThe structure has the following form: 185*bbf21555SRichard Lowe.Bd -literal 186*bbf21555SRichard Lowetypedef struct ufm_ioc_readimg { 187*bbf21555SRichard Lowe uint_t ufri_version; 188*bbf21555SRichard Lowe uint_t ufri_imageno; 189*bbf21555SRichard Lowe uint_t ufri_slotno; 190*bbf21555SRichard Lowe uint64_t ufri_offset; 191*bbf21555SRichard Lowe uint64_t ufri_len; 192*bbf21555SRichard Lowe uint64_t ufri_nread; 193*bbf21555SRichard Lowe void *ufri_buf; 194*bbf21555SRichard Lowe char ufri_devpath[MAXPATHLEN]; 195*bbf21555SRichard Lowe} ufm_ioc_readimg_t; 196*bbf21555SRichard Lowe.Ed 197*bbf21555SRichard Lowe.Pp 198*bbf21555SRichard LoweThe 199*bbf21555SRichard Lowe.Ft ufri_imageno 200*bbf21555SRichard Loweand 201*bbf21555SRichard Lowe.Ft ufri_slotno 202*bbf21555SRichard Lowevalues are used to indicate the image and slot to read. 203*bbf21555SRichard LoweThese indexes correspond to the same indices that are returned in the 204*bbf21555SRichard Lowenvlist from the 205*bbf21555SRichard Lowe.Dv UFM_IOC_REPORT 206*bbf21555SRichard Loweioctl. 207*bbf21555SRichard LoweThe 208*bbf21555SRichard Lowe.Ft ufri_offset 209*bbf21555SRichard Loweand 210*bbf21555SRichard Lowe.Ft ufri_len 211*bbf21555SRichard Lowemembers are used to indicate how many bytes to read from the image and 212*bbf21555SRichard Lowewhere in the image to begin. 213*bbf21555SRichard LoweThe 214*bbf21555SRichard Lowe.Fa ufri_buf 215*bbf21555SRichard Lowemember must be set to a valid pointer. 216*bbf21555SRichard LoweData read from the device will be placed in that pointer. 217*bbf21555SRichard LoweThe pointer must be at least 218*bbf21555SRichard Lowe.Fa ufri_len 219*bbf21555SRichard Lowebytes long. 220*bbf21555SRichard LoweUpon successful completion, the 221*bbf21555SRichard Lowe.Fa ufri_nread 222*bbf21555SRichard Lowemember will be filled in with the number of bytes that have been placed 223*bbf21555SRichard Lowein 224*bbf21555SRichard Lowe.Fa ufri_buf . 225*bbf21555SRichard LoweFinally, the 226*bbf21555SRichard Lowe.Fa ufri_version 227*bbf21555SRichard Loweand 228*bbf21555SRichard Lowe.Fa ufri_devpath 229*bbf21555SRichard Lowefields must be filled in with the version number, 230*bbf21555SRichard Lowe.Dv DDI_UFM_VERSION_ONE , 231*bbf21555SRichard Loweand the corresponding /devices path. 232*bbf21555SRichard Lowe.El 233*bbf21555SRichard Lowe.Sh EXAMPLES 234*bbf21555SRichard LoweThis example demonstrates how to use the 235*bbf21555SRichard Lowe.Dv UFM_IOC_GETCAPS 236*bbf21555SRichard Loweioctl to determine the UFM capabilities of a given device instance. 237*bbf21555SRichard Lowe.Bd -literal 238*bbf21555SRichard Lowe#include <stdio.h> 239*bbf21555SRichard Lowe#include <stdlib.h> 240*bbf21555SRichard Lowe#include <errno.h> 241*bbf21555SRichard Lowe#include <fcntl.h> 242*bbf21555SRichard Lowe#include <string.h> 243*bbf21555SRichard Lowe#include <unistd.h> 244*bbf21555SRichard Lowe#include <sys/ddi_ufm.h> 245*bbf21555SRichard Lowe#include <sys/types.h> 246*bbf21555SRichard Lowe 247*bbf21555SRichard Lowestatic const char devname[] = "/pci@ce,0/pci8086,2030@0/pci15d9,808@0"; 248*bbf21555SRichard Lowe 249*bbf21555SRichard Loweint 250*bbf21555SRichard Lowemain(int argc, char **argv) 251*bbf21555SRichard Lowe{ 252*bbf21555SRichard Lowe int fd; 253*bbf21555SRichard Lowe ufm_ioc_getcaps_t ioc = { 0 }; 254*bbf21555SRichard Lowe 255*bbf21555SRichard Lowe if ((fd = open(DDI_UFM_DEV, O_RDWR)) < 0) { 256*bbf21555SRichard Lowe (void) fprintf(stderr, "failed to open %s (%s)\n", DDI_UFM_DEV, 257*bbf21555SRichard Lowe strerror(errno)); 258*bbf21555SRichard Lowe return (1); 259*bbf21555SRichard Lowe } 260*bbf21555SRichard Lowe 261*bbf21555SRichard Lowe ioc.ufmg_version = DDI_UFM_CURRENT_VERSION; 262*bbf21555SRichard Lowe (void) strcpy(ioc.ufmg_devpath, devname); 263*bbf21555SRichard Lowe 264*bbf21555SRichard Lowe if (ioctl(fd, UFM_IOC_GETCAPS, &ioc) < 0) { 265*bbf21555SRichard Lowe (void) fprintf(stderr, "getcaps ioctl failed (%s)\n", 266*bbf21555SRichard Lowe strerror(errno)); 267*bbf21555SRichard Lowe (void) close(fd); 268*bbf21555SRichard Lowe return (1); 269*bbf21555SRichard Lowe } 270*bbf21555SRichard Lowe if ((ioc.ufmg_caps & DDI_UFM_CAP_REPORT) == 0) { 271*bbf21555SRichard Lowe (void) printf("Driver does not support DDI_UFM_CAP_REPORT\n"); 272*bbf21555SRichard Lowe } else { 273*bbf21555SRichard Lowe (void) printf("Driver supports DDI_UFM_CAP_REPORT\n"); 274*bbf21555SRichard Lowe } 275*bbf21555SRichard Lowe (void) close(fd); 276*bbf21555SRichard Lowe return (0); 277*bbf21555SRichard Lowe} 278*bbf21555SRichard Lowe.Ed 279*bbf21555SRichard Lowe.Sh ERRORS 280*bbf21555SRichard LoweOn failure to open or perform ioctls to the 281*bbf21555SRichard Lowe.Nm 282*bbf21555SRichard Lowedriver, 283*bbf21555SRichard Lowe.Va errno 284*bbf21555SRichard Lowewill be set to indicate the type of error. 285*bbf21555SRichard LoweA subset of the more common errors are detailed below. 286*bbf21555SRichard LoweFor a full list of error numbers, see 287*bbf21555SRichard Lowe.Xr Intro 2 288*bbf21555SRichard Lowe.Bl -tag -width Er 289*bbf21555SRichard Lowe.It Er EAGAIN 290*bbf21555SRichard LoweThe device driver is not currently ready to accept calls to it's DDI UFM entry 291*bbf21555SRichard Lowepoints. 292*bbf21555SRichard LoweThis may be because the driver is not fully initialized or because the driver 293*bbf21555SRichard Loweis in the process of detaching. 294*bbf21555SRichard Lowe.It Er EFAULT 295*bbf21555SRichard LoweThe ufm driver encountered a failure while copying data either from or to the 296*bbf21555SRichard Loweaddress space of the calling process. 297*bbf21555SRichard Lowe.It Er EINVAL 298*bbf21555SRichard LoweThe offset or length of an image would have resulted in a read outside 299*bbf21555SRichard Loweof the image's valid range or with improper alignment. 300*bbf21555SRichard Lowe.It Er EIO 301*bbf21555SRichard LoweA failure occurred while executing a DDI UFM entry point. 302*bbf21555SRichard Lowe.It Er ENOTSUP 303*bbf21555SRichard LoweEither the requested ioctl is not supported by the target device, the device 304*bbf21555SRichard Lowedoes not exist or the device does not support the UFM interfaces. 305*bbf21555SRichard Lowe.El 306*bbf21555SRichard Lowe.Sh INTERFACE STABILITY 307*bbf21555SRichard Lowe.Sy Evolving 308*bbf21555SRichard Lowe.Sh SEE ALSO 309*bbf21555SRichard Lowe.Xr ddi_ufm 9E , 310*bbf21555SRichard Lowe.Xr ddi_ufm 9F , 311*bbf21555SRichard Lowe.Xr ddi_ufm_image 9F , 312*bbf21555SRichard Lowe.Xr ddi_ufm_slot 9F 313