1508a0e8cSRob Johnston /* 2508a0e8cSRob Johnston * This file and its contents are supplied under the terms of the 3508a0e8cSRob Johnston * Common Development and Distribution License ("CDDL"), version 1.0. 4508a0e8cSRob Johnston * You may only use this file in accordance with the terms of version 5508a0e8cSRob Johnston * 1.0 of the CDDL. 6508a0e8cSRob Johnston * 7508a0e8cSRob Johnston * A full copy of the text of the CDDL should have accompanied this 8508a0e8cSRob Johnston * source. A copy of the CDDL is also available via the Internet at 9508a0e8cSRob Johnston * http://www.illumos.org/license/CDDL. 10508a0e8cSRob Johnston */ 11508a0e8cSRob Johnston 12508a0e8cSRob Johnston /* 13c9ad389fSJohn Levon * Copyright 2020 Joyent, Inc. 14*8d55b806SRobert Mustacchi * Copyright 2020 Oxide Computer Company 15508a0e8cSRob Johnston */ 16508a0e8cSRob Johnston 17508a0e8cSRob Johnston #ifndef _SYS_DDI_UFM_H 18508a0e8cSRob Johnston #define _SYS_DDI_UFM_H 19508a0e8cSRob Johnston 20508a0e8cSRob Johnston #ifdef __cplusplus 21508a0e8cSRob Johnston extern "C" { 22508a0e8cSRob Johnston #endif 23508a0e8cSRob Johnston 24508a0e8cSRob Johnston #ifdef _KERNEL 25508a0e8cSRob Johnston #include <sys/cred.h> 26508a0e8cSRob Johnston #include <sys/dditypes.h> 27508a0e8cSRob Johnston #include <sys/nvpair.h> 28508a0e8cSRob Johnston #include <sys/param.h> 29508a0e8cSRob Johnston #else 30508a0e8cSRob Johnston #include <sys/nvpair.h> 31508a0e8cSRob Johnston #include <sys/param.h> 32508a0e8cSRob Johnston #include <sys/types.h> 33508a0e8cSRob Johnston #endif /* _KERNEL */ 34508a0e8cSRob Johnston 35508a0e8cSRob Johnston #define DDI_UFM_DEV "/dev/ufm" 36508a0e8cSRob Johnston #define DDI_UFM_CURRENT_VERSION 1 37508a0e8cSRob Johnston #define DDI_UFM_VERSION_ONE 1 38508a0e8cSRob Johnston 39508a0e8cSRob Johnston #define UFM_IOC ('u' << 24) | ('f' << 16) | ('m' << 8) 40508a0e8cSRob Johnston #define UFM_IOC_GETCAPS (UFM_IOC | 1) 41508a0e8cSRob Johnston #define UFM_IOC_REPORTSZ (UFM_IOC | 2) 42508a0e8cSRob Johnston #define UFM_IOC_REPORT (UFM_IOC | 3) 43*8d55b806SRobert Mustacchi #define UFM_IOC_READIMG (UFM_IOC | 4) 44508a0e8cSRob Johnston #define UFM_IOC_MAX UFM_IOC_REPORT 45508a0e8cSRob Johnston 46508a0e8cSRob Johnston /* 47508a0e8cSRob Johnston * Bitfield enumerating the DDI UFM capabilities supported by this device 48508a0e8cSRob Johnston * instance. Currently there is only a single capability of being able to 49*8d55b806SRobert Mustacchi * report UFM information. When support for new capabilties are added to the 50*8d55b806SRobert Mustacchi * DDI UFM subsystem, it should be reflected in this enum and the implementation 51*8d55b806SRobert Mustacchi * of the UFM_IOC_GETCAPS should be extended appropriately. 52508a0e8cSRob Johnston */ 53508a0e8cSRob Johnston typedef enum { 54*8d55b806SRobert Mustacchi DDI_UFM_CAP_REPORT = 1 << 0, 55*8d55b806SRobert Mustacchi DDI_UFM_CAP_READIMG = 1 << 1 56508a0e8cSRob Johnston } ddi_ufm_cap_t; 57508a0e8cSRob Johnston 58508a0e8cSRob Johnston /* 59508a0e8cSRob Johnston * This struct defines the input/output data for the UFM_IOC_GETCAPS ioctl. 60508a0e8cSRob Johnston * Callers should specify the ufmg_version and ufmg_devpath fields. On success 61508a0e8cSRob Johnston * the ufmg_caps field will be filled in with a value indicating the supported 62508a0e8cSRob Johnston * UFM capabilities of the device specified in ufmg_devpath. 63508a0e8cSRob Johnston */ 64508a0e8cSRob Johnston typedef struct ufm_ioc_getcaps { 65508a0e8cSRob Johnston uint_t ufmg_version; /* DDI_UFM_VERSION */ 66508a0e8cSRob Johnston uint_t ufmg_caps; /* UFM Caps */ 67508a0e8cSRob Johnston char ufmg_devpath[MAXPATHLEN]; 68508a0e8cSRob Johnston } ufm_ioc_getcaps_t; 69508a0e8cSRob Johnston 70508a0e8cSRob Johnston /* 71508a0e8cSRob Johnston * This struct defines the input/output data for the UFM_IOC_REPORTSZ ioctl. 72508a0e8cSRob Johnston * Callers should specify the ufbz_version and ufbz_devpath fields. On success 73508a0e8cSRob Johnston * the ufmg_size field will be filled in with the amount of space (in bytes) 74508a0e8cSRob Johnston * required to hold the UFM data for this device instance. This should be used 75508a0e8cSRob Johnston * to allocate a sufficiently size buffer for the UFM_IOC_REPORT ioctl. 76508a0e8cSRob Johnston */ 77508a0e8cSRob Johnston typedef struct ufm_ioc_bufsz { 78508a0e8cSRob Johnston uint_t ufbz_version; /* DDI_UFM_VERSION */ 79508a0e8cSRob Johnston size_t ufbz_size; /* sz of buf to be returned by ioctl */ 80508a0e8cSRob Johnston char ufbz_devpath[MAXPATHLEN]; 81508a0e8cSRob Johnston } ufm_ioc_bufsz_t; 82508a0e8cSRob Johnston 83508a0e8cSRob Johnston #ifdef _KERNEL 84508a0e8cSRob Johnston typedef struct ufm_ioc_bufsz32 { 85508a0e8cSRob Johnston uint_t ufbz_version; 86508a0e8cSRob Johnston size32_t ufbz_size; 87508a0e8cSRob Johnston char ufbz_devpath[MAXPATHLEN]; 88508a0e8cSRob Johnston } ufm_ioc_bufsz32_t; 89508a0e8cSRob Johnston #endif /* _KERNEL */ 90508a0e8cSRob Johnston 91508a0e8cSRob Johnston /* 92508a0e8cSRob Johnston * This struct defines the input/output data for the UFM_IOC_REPORT ioctl. 93508a0e8cSRob Johnston * Callers should specify the ufmr_version, ufmr_bufsz and ufmr_devpath fields. 94508a0e8cSRob Johnston * On success, the ufmr_buf field will point to a packed nvlist containing the 95508a0e8cSRob Johnston * UFM data for the specified device instance. The value of ufmr_bufsz will be 96508a0e8cSRob Johnston * updated to reflect the actual size of data copied out. 97508a0e8cSRob Johnston */ 98508a0e8cSRob Johnston typedef struct ufm_ioc_report { 99508a0e8cSRob Johnston uint_t ufmr_version; /* DDI_UFM_VERSION */ 100508a0e8cSRob Johnston size_t ufmr_bufsz; /* size of caller-supplied buffer */ 101508a0e8cSRob Johnston caddr_t ufmr_buf; /* buf to hold packed output nvl */ 102508a0e8cSRob Johnston char ufmr_devpath[MAXPATHLEN]; 103508a0e8cSRob Johnston } ufm_ioc_report_t; 104508a0e8cSRob Johnston 105508a0e8cSRob Johnston #ifdef _KERNEL 106508a0e8cSRob Johnston typedef struct ufm_ioc_report32 { 107508a0e8cSRob Johnston uint_t ufmr_version; 108508a0e8cSRob Johnston size32_t ufmr_bufsz; 109508a0e8cSRob Johnston caddr32_t ufmr_buf; 110508a0e8cSRob Johnston char ufmr_devpath[MAXPATHLEN]; 111508a0e8cSRob Johnston } ufm_ioc_report32_t; 112508a0e8cSRob Johnston #endif /* _KERNEL */ 113508a0e8cSRob Johnston 114508a0e8cSRob Johnston /* 115*8d55b806SRobert Mustacchi * This struct defines the input/output data for the UFM_IOC_READ ioctl, which 116*8d55b806SRobert Mustacchi * reads the firmware image from a given slot. 117*8d55b806SRobert Mustacchi */ 118*8d55b806SRobert Mustacchi typedef struct ufm_ioc_readimg { 119*8d55b806SRobert Mustacchi uint_t ufri_version; 120*8d55b806SRobert Mustacchi uint_t ufri_imageno; 121*8d55b806SRobert Mustacchi uint_t ufri_slotno; 122*8d55b806SRobert Mustacchi uint64_t ufri_offset; 123*8d55b806SRobert Mustacchi uint64_t ufri_len; 124*8d55b806SRobert Mustacchi uint64_t ufri_nread; 125*8d55b806SRobert Mustacchi void *ufri_buf; 126*8d55b806SRobert Mustacchi char ufri_devpath[MAXPATHLEN]; 127*8d55b806SRobert Mustacchi } ufm_ioc_readimg_t; 128*8d55b806SRobert Mustacchi 129*8d55b806SRobert Mustacchi #ifdef _KERNEL 130*8d55b806SRobert Mustacchi #pragma pack(4) 131*8d55b806SRobert Mustacchi typedef struct ufm_ioc_readimg32 { 132*8d55b806SRobert Mustacchi uint_t ufri_version; 133*8d55b806SRobert Mustacchi uint_t ufri_imageno; 134*8d55b806SRobert Mustacchi uint_t ufri_slotno; 135*8d55b806SRobert Mustacchi uint64_t ufri_offset; 136*8d55b806SRobert Mustacchi uint64_t ufri_len; 137*8d55b806SRobert Mustacchi uint64_t ufri_nread; 138*8d55b806SRobert Mustacchi caddr32_t ufri_buf; 139*8d55b806SRobert Mustacchi char ufri_devpath[MAXPATHLEN]; 140*8d55b806SRobert Mustacchi } ufm_ioc_readimg32_t; 141*8d55b806SRobert Mustacchi #pragma pack() 142*8d55b806SRobert Mustacchi #endif /* _KERNEL */ 143*8d55b806SRobert Mustacchi 144*8d55b806SRobert Mustacchi /* 145508a0e8cSRob Johnston * The UFM_IOC_REPORT ioctl return UFM image and slot data in the form of a 146508a0e8cSRob Johnston * packed nvlist. The nvlist contains and array of nvlists (one-per-image). 147508a0e8cSRob Johnston * Each image nvlist contains will contain a string nvpair containing a 148508a0e8cSRob Johnston * description of the image and an optional nvlist nvpair containing 149508a0e8cSRob Johnston * miscellaneous image information. 150508a0e8cSRob Johnston */ 151508a0e8cSRob Johnston #define DDI_UFM_NV_IMAGES "ufm-images" 152508a0e8cSRob Johnston #define DDI_UFM_NV_IMAGE_DESC "ufm-image-description" 153508a0e8cSRob Johnston #define DDI_UFM_NV_IMAGE_MISC "ufm-image-misc" 154508a0e8cSRob Johnston 155508a0e8cSRob Johnston /* 156508a0e8cSRob Johnston * Each image nvlist also contains an array of nvlists representing the slots. 157508a0e8cSRob Johnston */ 158508a0e8cSRob Johnston #define DDI_UFM_NV_IMAGE_SLOTS "ufm-image-slots" 159508a0e8cSRob Johnston 160508a0e8cSRob Johnston /* 161*8d55b806SRobert Mustacchi * Each slot nvlist has the following: 162*8d55b806SRobert Mustacchi * 163*8d55b806SRobert Mustacchi * o A string nvpair describing the firmware image version 164*8d55b806SRobert Mustacchi * o A uint32 nvpair describing the slot attributes (see ddi_ufm_attr_t 165*8d55b806SRobert Mustacchi * below). 166*8d55b806SRobert Mustacchi * o An optional nvlist nvpar may be present containing additional 167508a0e8cSRob Johnston * miscellaneous slot data. 168*8d55b806SRobert Mustacchi * o An optional uint64 slot length that indicates the size of the image in 169*8d55b806SRobert Mustacchi * that slot. Note htis is the size of the image, not the size of the slot. 170508a0e8cSRob Johnston */ 171508a0e8cSRob Johnston #define DDI_UFM_NV_SLOT_VERSION "ufm-slot-version" 172*8d55b806SRobert Mustacchi #define DDI_UFM_NV_SLOT_IMGSIZE "ufm-slot-imgsize" 173508a0e8cSRob Johnston 174508a0e8cSRob Johnston typedef enum { 175508a0e8cSRob Johnston DDI_UFM_ATTR_READABLE = 1 << 0, 176508a0e8cSRob Johnston DDI_UFM_ATTR_WRITEABLE = 1 << 1, 177508a0e8cSRob Johnston DDI_UFM_ATTR_ACTIVE = 1 << 2, 178508a0e8cSRob Johnston DDI_UFM_ATTR_EMPTY = 1 << 3 179508a0e8cSRob Johnston } ddi_ufm_attr_t; 180508a0e8cSRob Johnston 181508a0e8cSRob Johnston #define DDI_UFM_ATTR_MAX DDI_UFM_ATTR_READABLE | \ 182508a0e8cSRob Johnston DDI_UFM_ATTR_WRITEABLE | \ 183508a0e8cSRob Johnston DDI_UFM_ATTR_ACTIVE | \ 184508a0e8cSRob Johnston DDI_UFM_ATTR_EMPTY 185508a0e8cSRob Johnston 186508a0e8cSRob Johnston #define DDI_UFM_NV_SLOT_ATTR "ufm-slot-attributes" 187508a0e8cSRob Johnston 188508a0e8cSRob Johnston #define DDI_UFM_NV_SLOT_MISC "ufm-slot-misc" 189508a0e8cSRob Johnston 190508a0e8cSRob Johnston #ifdef _KERNEL 191508a0e8cSRob Johnston /* opaque structures */ 192508a0e8cSRob Johnston typedef struct ddi_ufm_handle ddi_ufm_handle_t; 193508a0e8cSRob Johnston typedef struct ddi_ufm_image ddi_ufm_image_t; 194508a0e8cSRob Johnston typedef struct ddi_ufm_slot ddi_ufm_slot_t; 195508a0e8cSRob Johnston 196508a0e8cSRob Johnston /* 197508a0e8cSRob Johnston * DDI UFM Operations vector 198508a0e8cSRob Johnston */ 199508a0e8cSRob Johnston typedef struct ddi_ufm_ops { 200508a0e8cSRob Johnston int (*ddi_ufm_op_nimages)(ddi_ufm_handle_t *, void *, uint_t *); 201508a0e8cSRob Johnston int (*ddi_ufm_op_fill_image)(ddi_ufm_handle_t *, void *, uint_t, 202508a0e8cSRob Johnston ddi_ufm_image_t *); 203508a0e8cSRob Johnston int (*ddi_ufm_op_fill_slot)(ddi_ufm_handle_t *, void *, uint_t, uint_t, 204508a0e8cSRob Johnston ddi_ufm_slot_t *); 205508a0e8cSRob Johnston int (*ddi_ufm_op_getcaps)(ddi_ufm_handle_t *, void *, ddi_ufm_cap_t *); 206*8d55b806SRobert Mustacchi int (*ddi_ufm_op_readimg)(ddi_ufm_handle_t *, void *, uint_t, uint_t, 207*8d55b806SRobert Mustacchi uint64_t, uint64_t, void *, uint64_t *); 208508a0e8cSRob Johnston } ddi_ufm_ops_t; 209508a0e8cSRob Johnston 210508a0e8cSRob Johnston /* 211508a0e8cSRob Johnston * During a device driver's attach(9E) entry point, a device driver should 212508a0e8cSRob Johnston * register with the UFM subsystem by filling out a UFM operations vector 213508a0e8cSRob Johnston * (see above) and then calling ddi_ufm_init(9F). The driver may pass in a 214508a0e8cSRob Johnston * value, usually a pointer to its soft state pointer, which it will then 215508a0e8cSRob Johnston * receive when its subsequent entry points are called. 216508a0e8cSRob Johnston */ 217508a0e8cSRob Johnston int ddi_ufm_init(dev_info_t *, uint_t version, ddi_ufm_ops_t *, 218508a0e8cSRob Johnston ddi_ufm_handle_t **, void *); 219508a0e8cSRob Johnston 220508a0e8cSRob Johnston /* 221508a0e8cSRob Johnston * Device drivers should call ddi_ufm_update(9F) after driver initialization is 222508a0e8cSRob Johnston * complete and after calling ddi_ufm_init(9F), in order to indicate to the 223508a0e8cSRob Johnston * UFM subsystem that the driver is in a state where it is ready to receive 224508a0e8cSRob Johnston * calls to its UFM entry points. 225508a0e8cSRob Johnston * 226508a0e8cSRob Johnston * Additionally, whenever the driver detects a change in the state of a UFM, it 227508a0e8cSRob Johnston * should call ddi_ufm_update(9F). This will cause the UFM subsystem to 228508a0e8cSRob Johnston * invalidate any cached state regarding this driver's UFM(s) 229508a0e8cSRob Johnston */ 230508a0e8cSRob Johnston void ddi_ufm_update(ddi_ufm_handle_t *); 231508a0e8cSRob Johnston 232508a0e8cSRob Johnston /* 233508a0e8cSRob Johnston * A device driver should call ddi_ufm_fini(9F) during its detach(9E) entry 234508a0e8cSRob Johnston * point. Upon return, the driver is gaurunteed that no further DDI UFM entry 235508a0e8cSRob Johnston * points will be called and thus any related state can be safely torn down. 236508a0e8cSRob Johnston * 237508a0e8cSRob Johnston * After return, the UFM handle is no longer valid and should not be used in 238508a0e8cSRob Johnston * any future ddi_ufm_* calls. 239508a0e8cSRob Johnston */ 240508a0e8cSRob Johnston void ddi_ufm_fini(ddi_ufm_handle_t *); 241508a0e8cSRob Johnston 242508a0e8cSRob Johnston /* 243508a0e8cSRob Johnston * These interfaces should only be called within the context of a 244508a0e8cSRob Johnston * ddi_ufm_op_fill_image callback. 245508a0e8cSRob Johnston */ 246508a0e8cSRob Johnston void ddi_ufm_image_set_desc(ddi_ufm_image_t *, const char *); 247508a0e8cSRob Johnston void ddi_ufm_image_set_nslots(ddi_ufm_image_t *, uint_t); 248508a0e8cSRob Johnston void ddi_ufm_image_set_misc(ddi_ufm_image_t *, nvlist_t *); 249508a0e8cSRob Johnston 250508a0e8cSRob Johnston /* 251508a0e8cSRob Johnston * These interfaces should only be called within the context of a 252508a0e8cSRob Johnston * ddi_ufm_op_fill_slot callback. 253508a0e8cSRob Johnston */ 254508a0e8cSRob Johnston void ddi_ufm_slot_set_version(ddi_ufm_slot_t *, const char *); 255508a0e8cSRob Johnston void ddi_ufm_slot_set_attrs(ddi_ufm_slot_t *, ddi_ufm_attr_t); 256508a0e8cSRob Johnston void ddi_ufm_slot_set_misc(ddi_ufm_slot_t *, nvlist_t *); 257*8d55b806SRobert Mustacchi void ddi_ufm_slot_set_imgsize(ddi_ufm_slot_t *, uint64_t); 258508a0e8cSRob Johnston #endif /* _KERNEL */ 259508a0e8cSRob Johnston 260508a0e8cSRob Johnston #ifdef __cplusplus 261508a0e8cSRob Johnston } 262508a0e8cSRob Johnston #endif 263508a0e8cSRob Johnston 264508a0e8cSRob Johnston #endif /* _SYS_DDI_UFM_H */ 265