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