xref: /illumos-gate/usr/src/uts/common/sys/ddi_ufm.h (revision 8d55b806)
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