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