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
34extern "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
61struct devicelist;
62
63struct 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	 * 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
136struct 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(7D) 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
164struct 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
183struct 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
197struct 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(1M), 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(1M).
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
257struct 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 */
341TAILQ_HEAD(PLUGINLIST, pluginlist);
342TAILQ_HEAD(DEVICELIST, devicelist);
343
344/* exposed global args */
345extern di_node_t rootnode;
346extern struct PLUGINLIST *fw_pluginlist;
347extern struct DEVICELIST *fw_devices;
348extern struct vrfyplugin *verifier;
349extern struct fw_plugin *self;
350extern 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 */
379void logmsg(int severity, const char *msg, ...);
380
381#ifdef __cplusplus
382}
383#endif
384
385#endif /* _FWFLASH_H */
386