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 /*
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 int fwflash_debug;
45 
46 #define	FWFLASH_SUCCESS		0
47 #define	FWFLASH_FAILURE		1
48 
49 #define	FWFLASH_FLASH_IMAGES	2
50 
51 #define	FWPLUGINDIR		"/usr/lib/fwflash/identify"
52 #define	FWVERIFYPLUGINDIR	"/usr/lib/fwflash/verify"
53 
54 /*
55  * we search for a variable (fwplugin_version, type uint32_t)
56  * which should equal FWPLUGIN_VERSION_1
57  */
58 
59 #define	FWPLUGIN_VERSION_1	1
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(7D) 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 
126 struct pluginlist {
127 	/*
128 	 * fully qualified filename in /usr/lib/fwflash/identify
129 	 * made up of fwflash-[drivername].so
130 	 *
131 	 * eg  /usr/lib/fwflash/identify/ses.so
132 	 * is the identification plugin for devices attached to
133 	 * the host using the ses(7D) driver.
134 	 */
135 	char *filename;
136 
137 	/*
138 	 * The driver name that this plugin will search for in
139 	 * the device tree snapshot using di_drv_first_node(3DEVINFO)
140 	 * and di_drv_next_node(3DEVINFO).
141 	 */
142 	char *drvname;
143 
144 	/*
145 	 * pointer to the actual plugin, so we can access its
146 	 * function entry points
147 	 */
148 	struct fw_plugin *plugin;
149 
150 	/* pointer to the next element in the list */
151 	TAILQ_ENTRY(pluginlist) nextplugin;
152 };
153 
154 struct vpr {
155 	/* vendor ID, eg "HITACHI " */
156 	char *vid;
157 
158 	/* product ID, eg "DK32EJ36NSUN36G " */
159 	char *pid;
160 
161 	/* revision, eg "PQ08" */
162 	char *revid;
163 
164 	/*
165 	 * Additional, encapsulated identifying information.
166 	 * This pointer allows us to add details such as the
167 	 * IB hba sector size, which command set should be
168 	 * used or a part number.
169 	 */
170 	void *encap_ident;
171 };
172 
173 struct fwfile {
174 	/*
175 	 * The fully qualified filename. No default location for
176 	 * for the firmware image file is mandated.
177 	 */
178 	char *filename;
179 
180 	/* Pointer to the identification plugin required */
181 	struct fw_plugin *plugin;
182 
183 	/* pointer to the identification summary structure */
184 	struct vpr *ident;
185 };
186 
187 struct devicelist {
188 	/*
189 	 * fully qualified pathname, with /devices/.... prefix
190 	 */
191 	char *access_devname;
192 
193 	/*
194 	 * Which drivername did we find this device attached with
195 	 * in our device tree walk? Eg, ses or tavor or sgen...
196 	 */
197 	char *drvname;
198 
199 	/*
200 	 * What class of device is this? For tavor-attached devices,
201 	 * we set this to "IB". For other devices, unless there is
202 	 * a common name to use, just make this the same as the
203 	 * drvname field.
204 	 */
205 	char *classname;
206 
207 	/* pointer to the VPR structure */
208 	struct vpr *ident;
209 
210 	/*
211 	 * In the original fwflash(1M), it was possible to select a
212 	 * device for flashing by using an index number called a
213 	 * dev_num. We retain that concept for pluggable fwflash, with
214 	 * the following change - whenever our identification plugin has
215 	 * finished and found at least one acceptable device, we bump the
216 	 * index number by 100. This provides the user with another key
217 	 * to distinguish the desired device from a potentially very large
218 	 * list of similar-looking devices.
219 	 */
220 	unsigned int index;
221 
222 	/*
223 	 * Contains SAS or FC Port-WWNs, or IB GUIDS. Both SAS and FC only
224 	 * need one entry in this array since they really only have one
225 	 * address which we should track. IB devices can have 4 GUIDs
226 	 * (System Image, Node Image, Port 1 and Port 2).
227 	 */
228 	char *addresses[4];
229 
230 	/*
231 	 * Pointer to the plugin needed to flash this device, and
232 	 * to use for printing appropriate device-specific information
233 	 * as required by the "-l" option to fwflash(1M).
234 	 */
235 	struct fw_plugin *plugin;
236 
237 	/* Next entry in the list */
238 	TAILQ_ENTRY(devicelist) nextdev;
239 };
240 
241 
242 /*
243  * this type of plugin is for the firmware image vendor-specific
244  * verification functions, which we load from FWVERIFYPLUGINDIR
245  */
246 
247 struct vrfyplugin {
248 	/*
249 	 * fully-qualified filename in /usr/lib/fwflash/verify,
250 	 * made up of [drivername]-[vendorname].so
251 	 *
252 	 * eg  /usr/lib/fwflash/verify/ses-SUN.so
253 	 * is the verification plugin for ses-attached devices which
254 	 * have a vendorname of "SUN".
255 	 */
256 	char *filename;
257 
258 	/*
259 	 * The vendor name, such as "SUN" or "MELLANOX"
260 	 */
261 	char *vendor;
262 
263 	/*
264 	 * An opaque handle for dlopen()/dlclose() to use.
265 	 */
266 	void *handle;
267 
268 	/*
269 	 * Firmware image size in bytes, as reported by
270 	 * stat().
271 	 */
272 	unsigned int imgsize;
273 
274 	/*
275 	 * Flashable devices frequently have different buffers
276 	 * to use for different image types. We track the buffer
277 	 * required for this particular image with this variable.
278 	 *
279 	 * Once the verifier has figured out what sort of image
280 	 * it's been passed, it will know what value to use for
281 	 * this variable.
282 	 */
283 	unsigned int flashbuf;
284 
285 	/*
286 	 * Points to the entire firmware image in memory.
287 	 * We do this so we can avoid multiple open()/close()
288 	 * operations, and to make it easier for checksum
289 	 * calculations.
290 	 */
291 	int *fwimage;
292 
293 	/*
294 	 * We also store the name of the firmware file that
295 	 * we point to with *fwimage. This is needed in cases
296 	 * where we need to key off the name of the file to
297 	 * determine whether a different buffer in the target
298 	 * device should be targeted.
299 	 *
300 	 * For example, our "standard" firmware image (file.fw)
301 	 * might require use of buffer id 0, but a boot image
302 	 * (boot.fw) might require use of buffer id 17. In each
303 	 * case, it is the verifier plugin that determines the
304 	 * specific bufferid that is needed by that firmware image.
305 	 */
306 	char *imgfile;
307 
308 	/*
309 	 * The verification function entry point. The code
310 	 * in fwflash.c calls this function to verify that
311 	 * the nominated firmware image file is valid for
312 	 * the selected devicenode.
313 	 *
314 	 * Note that if the verification fails, the image
315 	 * does _not_ get force-flashed to the device.
316 	 */
317 	int (*vendorvrfy)(struct devicelist *devicenode);
318 };
319 
320 /* Flags for argument parsing */
321 #define	FWFLASH_HELP_FLAG	0x01
322 #define	FWFLASH_VER_FLAG	0x02
323 #define	FWFLASH_YES_FLAG	0x04
324 #define	FWFLASH_LIST_FLAG	0x08
325 #define	FWFLASH_CLASS_FLAG	0x10
326 #define	FWFLASH_DEVICE_FLAG	0x20
327 #define	FWFLASH_FW_FLAG		0x40
328 #define	FWFLASH_READ_FLAG	0x80
329 
330 /* global variables for fwflash */
331 TAILQ_HEAD(PLUGINLIST, pluginlist);
332 TAILQ_HEAD(DEVICELIST, devicelist);
333 struct PLUGINLIST *fw_pluginlist;
334 struct DEVICELIST *fw_devices;
335 
336 struct vrfyplugin *verifier;
337 di_node_t rootnode;
338 struct fw_plugin *self;
339 
340 int manufacturing_mode = 0;
341 
342 /*
343  * utility defines and macros, since the firmware image we get
344  * from LSI is ARM-format and that means byte- and short-swapping
345  * on sparc
346  */
347 
348 #define	HIGHBITS16		0xff00
349 #define	HIGHBITS32		0xffff0000
350 #define	HIGHBITS64		0xffffffff00000000ULL
351 #define	LOWBITS16		0x00ff
352 #define	LOWBITS32		0x0000ffff
353 #define	LOWBITS64		0x00000000ffffffffULL
354 
355 #if defined(_LITTLE_ENDIAN)
356 #define	ARMSWAPBITS(bs)		(bs)
357 #define	MLXSWAPBITS16(bs)	ntohs(bs)
358 #define	MLXSWAPBITS32(bs)	ntohl(bs)
359 #define	MLXSWAPBITS64(bs)	\
360 	(BE_64(((bs) & LOWBITS64)) | BE_64(((bs) & HIGHBITS64)))
361 #else
362 #define	ARMSWAPBITS(bs)	(LE_32(((bs) & LOWBITS32)) | LE_32(((bs) & HIGHBITS32)))
363 #define	MLXSWAPBITS16(bs)	(bs)
364 #define	MLXSWAPBITS32(bs)	(bs)
365 #define	MLXSWAPBITS64(bs)	(bs)
366 #endif
367 
368 /* common functions for fwflash */
369 void logmsg(int severity, const char *msg, ...);
370 
371 #ifdef __cplusplus
372 }
373 #endif
374 
375 #endif /* _FWFLASH_H */
376