1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #ifndef	_FWFLASH_H
27 #define	_FWFLASH_H
28 
29 /*
30  * fwflash.h
31  */
32 
33 #ifdef __cplusplus
34 extern "C" {
35 #endif
36 
37 #include <sys/queue.h>
38 #include <libdevinfo.h>
39 
40 
41 #define	MSG_INFO	0
42 #define	MSG_WARN	1
43 #define	MSG_ERROR	2
44 
45 #define	FWFLASH_SUCCESS		0
46 #define	FWFLASH_FAILURE		1
47 
48 #define	FWFLASH_FLASH_IMAGES	2
49 
50 #define	FWPLUGINDIR		"/usr/lib/fwflash/identify"
51 #define	FWVERIFYPLUGINDIR	"/usr/lib/fwflash/verify"
52 
53 /*
54  * we search for a variable (fwplugin_version, type uint32_t)
55  * which should equal FWPLUGIN_VERSION_1
56  */
57 
58 #define	FWPLUGIN_VERSION_1	1
59 #define	FWPLUGIN_VERSION_2	2
60 
61 struct devicelist;
62 
63 struct fw_plugin {
64 	/*
65 	 * An opaque handle for dlopen()/dlclose() to use.
66 	 */
67 	void *handle;
68 
69 	/*
70 	 * fully-qualified filename in /usr/lib/fwflash/identify
71 	 * made up of [drivername].so
72 	 *
73 	 * eg  /usr/lib/fwflash/identify/ses.so
74 	 * is the identification plugin for devices attached to
75 	 * the host using the ses(4D) driver.
76 	 */
77 	char *filename;
78 
79 	/*
80 	 * The driver name that this plugin will search for in
81 	 * the device tree snapshot using di_drv_first_node(3DEVINFO)
82 	 * and di_drv_next_node(3DEVINFO).
83 	 */
84 	char *drvname; /* "ses" or "tavor" or .... */
85 
86 	/*
87 	 * Function entry point to support the command-line "-r"
88 	 * option - read image from device to persistent storage.
89 	 *
90 	 * Not all plugins and devices will support this operation.
91 	 */
92 	int (*fw_readfw)(struct devicelist *device, char *filename);
93 
94 	/*
95 	 * Function entry point to support the command-line "-f"
96 	 * option - writes from persistent storage to device
97 	 *
98 	 * All identification plugins must support this operation.
99 	 */
100 	int (*fw_writefw)(struct devicelist *device, char *filename);
101 
102 	/*
103 	 * Function entry point used to build the list of valid, flashable
104 	 * devices attached to the system using the loadable module drvname.
105 	 * (Not all devices attached using drvname will be valid for this
106 	 * plugin to report.
107 	 *
108 	 * start allows us to display flashable devices attached with
109 	 * different drivers and provide the user with a visual clue
110 	 * that these devices are different to others that are detected.
111 	 *
112 	 * All identification plugins must support this operation.
113 	 */
114 	int (*fw_identify)(int start);
115 
116 	/*
117 	 * Function entry point to support the command-line "-l"
118 	 * option - list/report flashable devices attached to the system.
119 	 *
120 	 * All identification plugins must support this operation.
121 	 */
122 	int (*fw_devinfo)(struct devicelist *thisdev);
123 
124 	/*
125 	 * Function entry point to allow the plugin to clean up its
126 	 * data structure use IF plugin_version == FWPLUGIN_VERSION_2.
127 	 *
128 	 * If this function is not defined in the plugin, that is not
129 	 * an error condition unless the plugin_version variable is
130 	 * defined.
131 	 */
132 	void (*fw_cleanup)(struct devicelist *thisdev);
133 };
134 
135 
136 struct pluginlist {
137 	/*
138 	 * fully qualified filename in /usr/lib/fwflash/identify
139 	 * made up of fwflash-[drivername].so
140 	 *
141 	 * eg  /usr/lib/fwflash/identify/ses.so
142 	 * is the identification plugin for devices attached to
143 	 * the host using the ses(4D) driver.
144 	 */
145 	char *filename;
146 
147 	/*
148 	 * The driver name that this plugin will search for in
149 	 * the device tree snapshot using di_drv_first_node(3DEVINFO)
150 	 * and di_drv_next_node(3DEVINFO).
151 	 */
152 	char *drvname;
153 
154 	/*
155 	 * pointer to the actual plugin, so we can access its
156 	 * function entry points
157 	 */
158 	struct fw_plugin *plugin;
159 
160 	/* pointer to the next element in the list */
161 	TAILQ_ENTRY(pluginlist) nextplugin;
162 };
163 
164 struct vpr {
165 	/* vendor ID, eg "HITACHI " */
166 	char *vid;
167 
168 	/* product ID, eg "DK32EJ36NSUN36G " */
169 	char *pid;
170 
171 	/* revision, eg "PQ08" */
172 	char *revid;
173 
174 	/*
175 	 * Additional, encapsulated identifying information.
176 	 * This pointer allows us to add details such as the
177 	 * IB hba sector size, which command set should be
178 	 * used or a part number.
179 	 */
180 	void *encap_ident;
181 };
182 
183 struct fwfile {
184 	/*
185 	 * The fully qualified filename. No default location for
186 	 * the firmware image file is mandated.
187 	 */
188 	char *filename;
189 
190 	/* Pointer to the identification plugin required */
191 	struct fw_plugin *plugin;
192 
193 	/* pointer to the identification summary structure */
194 	struct vpr *ident;
195 };
196 
197 struct devicelist {
198 	/*
199 	 * fully qualified pathname, with /devices/.... prefix
200 	 */
201 	char *access_devname;
202 
203 	/*
204 	 * Which drivername did we find this device attached with
205 	 * in our device tree walk? Eg, ses or tavor or sgen...
206 	 */
207 	char *drvname;
208 
209 	/*
210 	 * What class of device is this? For tavor-attached devices,
211 	 * we set this to "IB". For other devices, unless there is
212 	 * a common name to use, just make this the same as the
213 	 * drvname field.
214 	 */
215 	char *classname;
216 
217 	/* pointer to the VPR structure */
218 	struct vpr *ident;
219 
220 	/*
221 	 * In the original fwflash(8), it was possible to select a
222 	 * device for flashing by using an index number called a
223 	 * dev_num. We retain that concept for pluggable fwflash, with
224 	 * the following change - whenever our identification plugin has
225 	 * finished and found at least one acceptable device, we bump the
226 	 * index number by 100. This provides the user with another key
227 	 * to distinguish the desired device from a potentially very large
228 	 * list of similar-looking devices.
229 	 */
230 	unsigned int index;
231 
232 	/*
233 	 * Contains SAS or FC Port-WWNs, or IB GUIDS. Both SAS and FC only
234 	 * need one entry in this array since they really only have one
235 	 * address which we should track. IB devices can have 4 GUIDs
236 	 * (System Image, Node Image, Port 1 and Port 2).
237 	 */
238 	char *addresses[4];
239 
240 	/*
241 	 * Pointer to the plugin needed to flash this device, and
242 	 * to use for printing appropriate device-specific information
243 	 * as required by the "-l" option to fwflash(8).
244 	 */
245 	struct fw_plugin *plugin;
246 
247 	/* Next entry in the list */
248 	TAILQ_ENTRY(devicelist) nextdev;
249 };
250 
251 
252 /*
253  * this type of plugin is for the firmware image vendor-specific
254  * verification functions, which we load from FWVERIFYPLUGINDIR
255  */
256 
257 struct vrfyplugin {
258 	/*
259 	 * fully-qualified filename in /usr/lib/fwflash/verify,
260 	 * made up of [drivername]-[vendorname].so
261 	 *
262 	 * eg  /usr/lib/fwflash/verify/ses-SUN.so
263 	 * is the verification plugin for ses-attached devices which
264 	 * have a vendorname of "SUN".
265 	 */
266 	char *filename;
267 
268 	/*
269 	 * The vendor name, such as "SUN" or "MELLANOX"
270 	 */
271 	char *vendor;
272 
273 	/*
274 	 * An opaque handle for dlopen()/dlclose() to use.
275 	 */
276 	void *handle;
277 
278 	/*
279 	 * Firmware image size in bytes, as reported by
280 	 * stat().
281 	 */
282 	unsigned int imgsize;
283 
284 	/*
285 	 * Flashable devices frequently have different buffers
286 	 * to use for different image types. We track the buffer
287 	 * required for this particular image with this variable.
288 	 *
289 	 * Once the verifier has figured out what sort of image
290 	 * it's been passed, it will know what value to use for
291 	 * this variable.
292 	 */
293 	unsigned int flashbuf;
294 
295 	/*
296 	 * Points to the entire firmware image in memory.
297 	 * We do this so we can avoid multiple open()/close()
298 	 * operations, and to make it easier for checksum
299 	 * calculations.
300 	 */
301 	int *fwimage;
302 
303 	/*
304 	 * We also store the name of the firmware file that
305 	 * we point to with *fwimage. This is needed in cases
306 	 * where we need to key off the name of the file to
307 	 * determine whether a different buffer in the target
308 	 * device should be targeted.
309 	 *
310 	 * For example, our "standard" firmware image (file.fw)
311 	 * might require use of buffer id 0, but a boot image
312 	 * (boot.fw) might require use of buffer id 17. In each
313 	 * case, it is the verifier plugin that determines the
314 	 * specific bufferid that is needed by that firmware image.
315 	 */
316 	char *imgfile;
317 
318 	/*
319 	 * The verification function entry point. The code
320 	 * in fwflash.c calls this function to verify that
321 	 * the nominated firmware image file is valid for
322 	 * the selected devicenode.
323 	 *
324 	 * Note that if the verification fails, the image
325 	 * does _not_ get force-flashed to the device.
326 	 */
327 	int (*vendorvrfy)(struct devicelist *devicenode);
328 };
329 
330 /* Flags for argument parsing */
331 #define	FWFLASH_HELP_FLAG	0x01
332 #define	FWFLASH_VER_FLAG	0x02
333 #define	FWFLASH_YES_FLAG	0x04
334 #define	FWFLASH_LIST_FLAG	0x08
335 #define	FWFLASH_CLASS_FLAG	0x10
336 #define	FWFLASH_DEVICE_FLAG	0x20
337 #define	FWFLASH_FW_FLAG		0x40
338 #define	FWFLASH_READ_FLAG	0x80
339 
340 /* global variables for fwflash */
341 TAILQ_HEAD(PLUGINLIST, pluginlist);
342 TAILQ_HEAD(DEVICELIST, devicelist);
343 
344 /* exposed global args */
345 extern di_node_t rootnode;
346 extern struct PLUGINLIST *fw_pluginlist;
347 extern struct DEVICELIST *fw_devices;
348 extern struct vrfyplugin *verifier;
349 extern struct fw_plugin *self;
350 extern int fwflash_debug;
351 
352 /*
353  * utility defines and macros, since the firmware image we get
354  * from LSI is ARM-format and that means byte- and short-swapping
355  * on sparc
356  */
357 
358 #define	HIGHBITS16		0xff00
359 #define	HIGHBITS32		0xffff0000
360 #define	HIGHBITS64		0xffffffff00000000ULL
361 #define	LOWBITS16		0x00ff
362 #define	LOWBITS32		0x0000ffff
363 #define	LOWBITS64		0x00000000ffffffffULL
364 
365 #if defined(_LITTLE_ENDIAN)
366 #define	ARMSWAPBITS(bs)		(bs)
367 #define	MLXSWAPBITS16(bs)	ntohs(bs)
368 #define	MLXSWAPBITS32(bs)	ntohl(bs)
369 #define	MLXSWAPBITS64(bs)	\
370 	(BE_64(((bs) & LOWBITS64)) | BE_64(((bs) & HIGHBITS64)))
371 #else
372 #define	ARMSWAPBITS(bs)	(LE_32(((bs) & LOWBITS32)) | LE_32(((bs) & HIGHBITS32)))
373 #define	MLXSWAPBITS16(bs)	(bs)
374 #define	MLXSWAPBITS32(bs)	(bs)
375 #define	MLXSWAPBITS64(bs)	(bs)
376 #endif
377 
378 /* common functions for fwflash */
379 void logmsg(int severity, const char *msg, ...);
380 
381 #ifdef __cplusplus
382 }
383 #endif
384 
385 #endif /* _FWFLASH_H */
386