xref: /illumos-gate/usr/src/uts/common/sys/ddi_ufm.h (revision c9ad389f76487048d6fde034960b0f5edfb778d7)
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 2020 Joyent, Inc.
14  */
15 
16 #ifndef _SYS_DDI_UFM_H
17 #define	_SYS_DDI_UFM_H
18 
19 #ifdef __cplusplus
20 extern "C" {
21 #endif
22 
23 #ifdef _KERNEL
24 #include <sys/cred.h>
25 #include <sys/dditypes.h>
26 #include <sys/nvpair.h>
27 #include <sys/param.h>
28 #else
29 #include <sys/nvpair.h>
30 #include <sys/param.h>
31 #include <sys/types.h>
32 #endif /* _KERNEL */
33 
34 #define	DDI_UFM_DEV		"/dev/ufm"
35 #define	DDI_UFM_CURRENT_VERSION	1
36 #define	DDI_UFM_VERSION_ONE	1
37 
38 #define	UFM_IOC			('u' << 24) | ('f' << 16) | ('m' << 8)
39 #define	UFM_IOC_GETCAPS		(UFM_IOC | 1)
40 #define	UFM_IOC_REPORTSZ	(UFM_IOC | 2)
41 #define	UFM_IOC_REPORT		(UFM_IOC | 3)
42 #define	UFM_IOC_MAX		UFM_IOC_REPORT
43 
44 /*
45  * Bitfield enumerating the DDI UFM capabilities supported by this device
46  * instance.  Currently there is only a single capability of being able to
47  * report UFM information.  Future UFM versions may add additional capabilities
48  * such as the ability to obtain a raw dump the firmware image or ability to
49  * upgrade the firmware.  When support for new capabilties are added to the DDI
50  * UFM subsystem, it should be reflected in this enum and the implementation of
51  * the UFM_IOC_GETCAPS should be extended appropriately.
52  */
53 typedef enum {
54 	DDI_UFM_CAP_REPORT	= 1 << 0
55 } ddi_ufm_cap_t;
56 
57 /*
58  * This struct defines the input/output data for the UFM_IOC_GETCAPS ioctl.
59  * Callers should specify the ufmg_version and ufmg_devpath fields.  On success
60  * the ufmg_caps field will be filled in with a value indicating the supported
61  * UFM capabilities of the device specified in ufmg_devpath.
62  */
63 typedef struct ufm_ioc_getcaps {
64 	uint_t		ufmg_version;	/* DDI_UFM_VERSION */
65 	uint_t		ufmg_caps;	/* UFM Caps */
66 	char		ufmg_devpath[MAXPATHLEN];
67 } ufm_ioc_getcaps_t;
68 
69 /*
70  * This struct defines the input/output data for the UFM_IOC_REPORTSZ ioctl.
71  * Callers should specify the ufbz_version and ufbz_devpath fields.  On success
72  * the ufmg_size field will be filled in with the amount of space (in bytes)
73  * required to hold the UFM data for this device instance.  This should be used
74  * to allocate a sufficiently size buffer for the UFM_IOC_REPORT ioctl.
75  */
76 typedef struct ufm_ioc_bufsz {
77 	uint_t		ufbz_version;	/* DDI_UFM_VERSION */
78 	size_t		ufbz_size;	/* sz of buf to be returned by ioctl */
79 	char		ufbz_devpath[MAXPATHLEN];
80 } ufm_ioc_bufsz_t;
81 
82 #ifdef _KERNEL
83 typedef struct ufm_ioc_bufsz32 {
84 	uint_t		ufbz_version;
85 	size32_t	ufbz_size;
86 	char		ufbz_devpath[MAXPATHLEN];
87 } ufm_ioc_bufsz32_t;
88 #endif	/* _KERNEL */
89 
90 /*
91  * This struct defines the input/output data for the UFM_IOC_REPORT ioctl.
92  * Callers should specify the ufmr_version, ufmr_bufsz and ufmr_devpath fields.
93  * On success, the ufmr_buf field will point to a packed nvlist containing the
94  * UFM data for the specified device instance.  The value of ufmr_bufsz will be
95  * updated to reflect the actual size of data copied out.
96  */
97 typedef struct ufm_ioc_report {
98 	uint_t		ufmr_version;	/* DDI_UFM_VERSION */
99 	size_t		ufmr_bufsz;	/* size of caller-supplied buffer */
100 	caddr_t		ufmr_buf;	/* buf to hold packed output nvl */
101 	char		ufmr_devpath[MAXPATHLEN];
102 } ufm_ioc_report_t;
103 
104 #ifdef _KERNEL
105 typedef struct ufm_ioc_report32 {
106 	uint_t		ufmr_version;
107 	size32_t	ufmr_bufsz;
108 	caddr32_t	ufmr_buf;
109 	char		ufmr_devpath[MAXPATHLEN];
110 } ufm_ioc_report32_t;
111 #endif	/* _KERNEL */
112 
113 /*
114  * The UFM_IOC_REPORT ioctl return UFM image and slot data in the form of a
115  * packed nvlist.  The nvlist contains and array of nvlists (one-per-image).
116  * Each image nvlist contains will contain a string nvpair containing a
117  * description of the image and an optional nvlist nvpair containing
118  * miscellaneous image information.
119  */
120 #define	DDI_UFM_NV_IMAGES		"ufm-images"
121 #define	DDI_UFM_NV_IMAGE_DESC		"ufm-image-description"
122 #define	DDI_UFM_NV_IMAGE_MISC		"ufm-image-misc"
123 
124 /*
125  * Each image nvlist also contains an array of nvlists representing the slots.
126  */
127 #define	DDI_UFM_NV_IMAGE_SLOTS		"ufm-image-slots"
128 
129 /*
130  * Each slot nvlist as a string nvpair describing the firmware image version
131  * and an uint32 nvpair describing the slot attributes (see ddi_ufm_attr_t
132  * above).  An option nvlist nvpar may be present containing additional
133  * miscellaneous slot data.
134  */
135 #define	DDI_UFM_NV_SLOT_VERSION		"ufm-slot-version"
136 
137 typedef enum {
138 	DDI_UFM_ATTR_READABLE	= 1 << 0,
139 	DDI_UFM_ATTR_WRITEABLE	= 1 << 1,
140 	DDI_UFM_ATTR_ACTIVE	= 1 << 2,
141 	DDI_UFM_ATTR_EMPTY	= 1 << 3
142 } ddi_ufm_attr_t;
143 
144 #define	DDI_UFM_ATTR_MAX	DDI_UFM_ATTR_READABLE | \
145 				DDI_UFM_ATTR_WRITEABLE | \
146 				DDI_UFM_ATTR_ACTIVE | \
147 				DDI_UFM_ATTR_EMPTY
148 
149 #define	DDI_UFM_NV_SLOT_ATTR		"ufm-slot-attributes"
150 
151 #define	DDI_UFM_NV_SLOT_MISC		"ufm-slot-misc"
152 
153 #ifdef _KERNEL
154 /* opaque structures */
155 typedef struct ddi_ufm_handle ddi_ufm_handle_t;
156 typedef struct ddi_ufm_image ddi_ufm_image_t;
157 typedef struct ddi_ufm_slot ddi_ufm_slot_t;
158 
159 /*
160  * DDI UFM Operations vector
161  */
162 typedef struct ddi_ufm_ops {
163 	int (*ddi_ufm_op_nimages)(ddi_ufm_handle_t *, void *, uint_t *);
164 	int (*ddi_ufm_op_fill_image)(ddi_ufm_handle_t *, void *, uint_t,
165 	    ddi_ufm_image_t *);
166 	int (*ddi_ufm_op_fill_slot)(ddi_ufm_handle_t *, void *, uint_t, uint_t,
167 	    ddi_ufm_slot_t *);
168 	int (*ddi_ufm_op_getcaps)(ddi_ufm_handle_t *, void *, ddi_ufm_cap_t *);
169 } ddi_ufm_ops_t;
170 
171 /*
172  * During a device driver's attach(9E) entry point, a device driver should
173  * register with the UFM subsystem by filling out a UFM operations vector
174  * (see above) and then calling ddi_ufm_init(9F).  The driver may pass in a
175  * value, usually a pointer to its soft state pointer, which it will then
176  * receive when its subsequent entry points are called.
177  */
178 int ddi_ufm_init(dev_info_t *, uint_t version, ddi_ufm_ops_t *,
179     ddi_ufm_handle_t **, void *);
180 
181 /*
182  * Device drivers should call ddi_ufm_update(9F) after driver initialization is
183  * complete and after calling ddi_ufm_init(9F), in order to indicate to the
184  * UFM subsystem that the driver is in a state where it is ready to receive
185  * calls to its UFM entry points.
186  *
187  * Additionally, whenever the driver detects a change in the state of a UFM, it
188  * should call ddi_ufm_update(9F).  This will cause the UFM subsystem to
189  * invalidate any cached state regarding this driver's UFM(s)
190  */
191 void ddi_ufm_update(ddi_ufm_handle_t *);
192 
193 /*
194  * A device driver should call ddi_ufm_fini(9F) during its detach(9E) entry
195  * point.  Upon return, the driver is gaurunteed that no further DDI UFM entry
196  * points will be called and thus any related state can be safely torn down.
197  *
198  * After return, the UFM handle is no longer valid and should not be used in
199  * any future ddi_ufm_* calls.
200  */
201 void ddi_ufm_fini(ddi_ufm_handle_t *);
202 
203 /*
204  * These interfaces should only be called within the context of a
205  * ddi_ufm_op_fill_image callback.
206  */
207 void ddi_ufm_image_set_desc(ddi_ufm_image_t *, const char *);
208 void ddi_ufm_image_set_nslots(ddi_ufm_image_t *, uint_t);
209 void ddi_ufm_image_set_misc(ddi_ufm_image_t *, nvlist_t *);
210 
211 /*
212  * These interfaces should only be called within the context of a
213  * ddi_ufm_op_fill_slot callback.
214  */
215 void ddi_ufm_slot_set_version(ddi_ufm_slot_t *, const char *);
216 void ddi_ufm_slot_set_attrs(ddi_ufm_slot_t *, ddi_ufm_attr_t);
217 void ddi_ufm_slot_set_misc(ddi_ufm_slot_t *, nvlist_t *);
218 #endif /* _KERNEL */
219 
220 #ifdef __cplusplus
221 }
222 #endif
223 
224 #endif	/* _SYS_DDI_UFM_H */
225