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 2019 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 */