1 // SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1)
2 /* from src/prism2/download/prism2dl.c
3  *
4  * utility for downloading prism2 images moved into kernelspace
5  *
6  * Copyright (C) 1999 AbsoluteValue Systems, Inc.  All Rights Reserved.
7  * --------------------------------------------------------------------
8  *
9  * linux-wlan
10  *
11  * --------------------------------------------------------------------
12  *
13  * Inquiries regarding the linux-wlan Open Source project can be
14  * made directly to:
15  *
16  * AbsoluteValue Systems Inc.
17  * info@linux-wlan.com
18  * http://www.linux-wlan.com
19  *
20  * --------------------------------------------------------------------
21  *
22  * Portions of the development of this software were funded by
23  * Intersil Corporation as part of PRISM(R) chipset product development.
24  *
25  * --------------------------------------------------------------------
26  */
27 
28 /*================================================================*/
29 /* System Includes */
30 #include <linux/ihex.h>
31 #include <linux/slab.h>
32 
33 /*================================================================*/
34 /* Local Constants */
35 
36 #define PRISM2_USB_FWFILE	"prism2_ru.fw"
37 MODULE_FIRMWARE(PRISM2_USB_FWFILE);
38 
39 #define S3DATA_MAX		5000
40 #define S3PLUG_MAX		200
41 #define S3CRC_MAX		200
42 #define S3INFO_MAX		50
43 
44 #define S3ADDR_PLUG		(0xff000000UL)
45 #define S3ADDR_CRC		(0xff100000UL)
46 #define S3ADDR_INFO		(0xff200000UL)
47 #define S3ADDR_START		(0xff400000UL)
48 
49 #define CHUNKS_MAX		100
50 
51 #define WRITESIZE_MAX		4096
52 
53 /*================================================================*/
54 /* Local Types */
55 
56 struct s3datarec {
57 	u32 len;
58 	u32 addr;
59 	u8 checksum;
60 	u8 *data;
61 };
62 
63 struct s3plugrec {
64 	u32 itemcode;
65 	u32 addr;
66 	u32 len;
67 };
68 
69 struct s3crcrec {
70 	u32 addr;
71 	u32 len;
72 	unsigned int dowrite;
73 };
74 
75 struct s3inforec {
76 	u16 len;
77 	u16 type;
78 	union {
79 		struct hfa384x_compident version;
80 		struct hfa384x_caplevel compat;
81 		u16 buildseq;
82 		struct hfa384x_compident platform;
83 	} info;
84 };
85 
86 struct pda {
87 	u8 buf[HFA384x_PDA_LEN_MAX];
88 	struct hfa384x_pdrec *rec[HFA384x_PDA_RECS_MAX];
89 	unsigned int nrec;
90 };
91 
92 struct imgchunk {
93 	u32 addr;	/* start address */
94 	u32 len;	/* in bytes */
95 	u16 crc;	/* CRC value (if it falls at a chunk boundary) */
96 	u8 *data;
97 };
98 
99 /*================================================================*/
100 /* Local Static Definitions */
101 
102 /*----------------------------------------------------------------*/
103 /* s-record image processing */
104 
105 /* Data records */
106 static unsigned int ns3data;
107 static struct s3datarec *s3data;
108 
109 /* Plug records */
110 static unsigned int ns3plug;
111 static struct s3plugrec s3plug[S3PLUG_MAX];
112 
113 /* CRC records */
114 static unsigned int ns3crc;
115 static struct s3crcrec s3crc[S3CRC_MAX];
116 
117 /* Info records */
118 static unsigned int ns3info;
119 static struct s3inforec s3info[S3INFO_MAX];
120 
121 /* S7 record (there _better_ be only one) */
122 static u32 startaddr;
123 
124 /* Load image chunks */
125 static unsigned int nfchunks;
126 static struct imgchunk fchunk[CHUNKS_MAX];
127 
128 /* Note that for the following pdrec_t arrays, the len and code */
129 /*   fields are stored in HOST byte order. The mkpdrlist() function */
130 /*   does the conversion.  */
131 /*----------------------------------------------------------------*/
132 /* PDA, built from [card|newfile]+[addfile1+addfile2...] */
133 
134 static struct pda pda;
135 static struct hfa384x_compident nicid;
136 static struct hfa384x_caplevel rfid;
137 static struct hfa384x_caplevel macid;
138 static struct hfa384x_caplevel priid;
139 
140 /*================================================================*/
141 /* Local Function Declarations */
142 
143 static int prism2_fwapply(const struct ihex_binrec *rfptr,
144 			  struct wlandevice *wlandev);
145 
146 static int read_fwfile(const struct ihex_binrec *rfptr);
147 
148 static int mkimage(struct imgchunk *clist, unsigned int *ccnt);
149 
150 static int read_cardpda(struct pda *pda, struct wlandevice *wlandev);
151 
152 static int mkpdrlist(struct pda *pda);
153 
154 static int plugimage(struct imgchunk *fchunk, unsigned int nfchunks,
155 		     struct s3plugrec *s3plug, unsigned int ns3plug,
156 		     struct pda *pda);
157 
158 static int crcimage(struct imgchunk *fchunk, unsigned int nfchunks,
159 		    struct s3crcrec *s3crc, unsigned int ns3crc);
160 
161 static int writeimage(struct wlandevice *wlandev, struct imgchunk *fchunk,
162 		      unsigned int nfchunks);
163 
164 static void free_chunks(struct imgchunk *fchunk, unsigned int *nfchunks);
165 
166 static void free_srecs(void);
167 
168 static int validate_identity(void);
169 
170 /*================================================================*/
171 /* Function Definitions */
172 
173 /*----------------------------------------------------------------
174  * prism2_fwtry
175  *
176  * Try and get firmware into memory
177  *
178  * Arguments:
179  *	udev	usb device structure
180  *	wlandev wlan device structure
181  *
182  * Returns:
183  *	0	- success
184  *	~0	- failure
185  *----------------------------------------------------------------
186  */
prism2_fwtry(struct usb_device * udev,struct wlandevice * wlandev)187 static int prism2_fwtry(struct usb_device *udev, struct wlandevice *wlandev)
188 {
189 	const struct firmware *fw_entry = NULL;
190 
191 	netdev_info(wlandev->netdev, "prism2_usb: Checking for firmware %s\n",
192 		    PRISM2_USB_FWFILE);
193 	if (request_ihex_firmware(&fw_entry,
194 				  PRISM2_USB_FWFILE, &udev->dev) != 0) {
195 		netdev_info(wlandev->netdev,
196 			    "prism2_usb: Firmware not available, but not essential\n");
197 		netdev_info(wlandev->netdev,
198 			    "prism2_usb: can continue to use card anyway.\n");
199 		return 1;
200 	}
201 
202 	netdev_info(wlandev->netdev,
203 		    "prism2_usb: %s will be processed, size %zu\n",
204 		    PRISM2_USB_FWFILE, fw_entry->size);
205 	prism2_fwapply((const struct ihex_binrec *)fw_entry->data, wlandev);
206 
207 	release_firmware(fw_entry);
208 	return 0;
209 }
210 
211 /*----------------------------------------------------------------
212  * prism2_fwapply
213  *
214  * Apply the firmware loaded into memory
215  *
216  * Arguments:
217  *	rfptr	firmware image in kernel memory
218  *	wlandev device
219  *
220  * Returns:
221  *	0	- success
222  *	~0	- failure
223  *----------------------------------------------------------------
224  */
prism2_fwapply(const struct ihex_binrec * rfptr,struct wlandevice * wlandev)225 static int prism2_fwapply(const struct ihex_binrec *rfptr,
226 			  struct wlandevice *wlandev)
227 {
228 	signed int result = 0;
229 	struct p80211msg_dot11req_mibget getmsg;
230 	struct p80211itemd *item;
231 	u32 *data;
232 
233 	/* Initialize the data structures */
234 	ns3data = 0;
235 	s3data = kcalloc(S3DATA_MAX, sizeof(*s3data), GFP_KERNEL);
236 	if (!s3data) {
237 		result = -ENOMEM;
238 		goto out;
239 	}
240 
241 	ns3plug = 0;
242 	memset(s3plug, 0, sizeof(s3plug));
243 	ns3crc = 0;
244 	memset(s3crc, 0, sizeof(s3crc));
245 	ns3info = 0;
246 	memset(s3info, 0, sizeof(s3info));
247 	startaddr = 0;
248 
249 	nfchunks = 0;
250 	memset(fchunk, 0, sizeof(fchunk));
251 	memset(&nicid, 0, sizeof(nicid));
252 	memset(&rfid, 0, sizeof(rfid));
253 	memset(&macid, 0, sizeof(macid));
254 	memset(&priid, 0, sizeof(priid));
255 
256 	/* clear the pda and add an initial END record */
257 	memset(&pda, 0, sizeof(pda));
258 	pda.rec[0] = (struct hfa384x_pdrec *)pda.buf;
259 	pda.rec[0]->len = cpu_to_le16(2);	/* len in words */
260 	pda.rec[0]->code = cpu_to_le16(HFA384x_PDR_END_OF_PDA);
261 	pda.nrec = 1;
262 
263 	/*-----------------------------------------------------*/
264 	/* Put card into fwload state */
265 	prism2sta_ifstate(wlandev, P80211ENUM_ifstate_fwload);
266 
267 	/* Build the PDA we're going to use. */
268 	if (read_cardpda(&pda, wlandev)) {
269 		netdev_err(wlandev->netdev, "load_cardpda failed, exiting.\n");
270 		result = 1;
271 		goto out;
272 	}
273 
274 	/* read the card's PRI-SUP */
275 	memset(&getmsg, 0, sizeof(getmsg));
276 	getmsg.msgcode = DIDMSG_DOT11REQ_MIBGET;
277 	getmsg.msglen = sizeof(getmsg);
278 	strscpy(getmsg.devname, wlandev->name, sizeof(getmsg.devname));
279 
280 	getmsg.mibattribute.did = DIDMSG_DOT11REQ_MIBGET_MIBATTRIBUTE;
281 	getmsg.mibattribute.status = P80211ENUM_msgitem_status_data_ok;
282 	getmsg.resultcode.did = DIDMSG_DOT11REQ_MIBGET_RESULTCODE;
283 	getmsg.resultcode.status = P80211ENUM_msgitem_status_no_value;
284 
285 	item = (struct p80211itemd *)getmsg.mibattribute.data;
286 	item->did = DIDMIB_P2_NIC_PRISUPRANGE;
287 	item->status = P80211ENUM_msgitem_status_no_value;
288 
289 	data = (u32 *)item->data;
290 
291 	/* DIDmsg_dot11req_mibget */
292 	prism2mgmt_mibset_mibget(wlandev, &getmsg);
293 	if (getmsg.resultcode.data != P80211ENUM_resultcode_success)
294 		netdev_err(wlandev->netdev, "Couldn't fetch PRI-SUP info\n");
295 
296 	/* Already in host order */
297 	priid.role = *data++;
298 	priid.id = *data++;
299 	priid.variant = *data++;
300 	priid.bottom = *data++;
301 	priid.top = *data++;
302 
303 	/* Read the S3 file */
304 	result = read_fwfile(rfptr);
305 	if (result) {
306 		netdev_err(wlandev->netdev,
307 			   "Failed to read the data exiting.\n");
308 		goto out;
309 	}
310 
311 	result = validate_identity();
312 	if (result) {
313 		netdev_err(wlandev->netdev, "Incompatible firmware image.\n");
314 		goto out;
315 	}
316 
317 	if (startaddr == 0x00000000) {
318 		netdev_err(wlandev->netdev,
319 			   "Can't RAM download a Flash image!\n");
320 		result = 1;
321 		goto out;
322 	}
323 
324 	/* Make the image chunks */
325 	result = mkimage(fchunk, &nfchunks);
326 	if (result) {
327 		netdev_err(wlandev->netdev, "Failed to make image chunk.\n");
328 		goto free_chunks;
329 	}
330 
331 	/* Do any plugging */
332 	result = plugimage(fchunk, nfchunks, s3plug, ns3plug, &pda);
333 	if (result) {
334 		netdev_err(wlandev->netdev, "Failed to plug data.\n");
335 		goto free_chunks;
336 	}
337 
338 	/* Insert any CRCs */
339 	result = crcimage(fchunk, nfchunks, s3crc, ns3crc);
340 	if (result) {
341 		netdev_err(wlandev->netdev, "Failed to insert all CRCs\n");
342 		goto free_chunks;
343 	}
344 
345 	/* Write the image */
346 	result = writeimage(wlandev, fchunk, nfchunks);
347 	if (result) {
348 		netdev_err(wlandev->netdev, "Failed to ramwrite image data.\n");
349 		goto free_chunks;
350 	}
351 
352 	netdev_info(wlandev->netdev, "prism2_usb: firmware loading finished.\n");
353 
354 free_chunks:
355 	/* clear any allocated memory */
356 	free_chunks(fchunk, &nfchunks);
357 	free_srecs();
358 
359 out:
360 	return result;
361 }
362 
363 /*----------------------------------------------------------------
364  * crcimage
365  *
366  * Adds a CRC16 in the two bytes prior to each block identified by
367  * an S3 CRC record.  Currently, we don't actually do a CRC we just
368  * insert the value 0xC0DE in hfa384x order.
369  *
370  * Arguments:
371  *	fchunk		Array of image chunks
372  *	nfchunks	Number of image chunks
373  *	s3crc		Array of crc records
374  *	ns3crc		Number of crc records
375  *
376  * Returns:
377  *	0	success
378  *	~0	failure
379  *----------------------------------------------------------------
380  */
crcimage(struct imgchunk * fchunk,unsigned int nfchunks,struct s3crcrec * s3crc,unsigned int ns3crc)381 static int crcimage(struct imgchunk *fchunk, unsigned int nfchunks,
382 		    struct s3crcrec *s3crc, unsigned int ns3crc)
383 {
384 	int result = 0;
385 	int i;
386 	int c;
387 	u32 crcstart;
388 	u32 cstart = 0;
389 	u32 cend;
390 	u8 *dest;
391 	u32 chunkoff;
392 
393 	for (i = 0; i < ns3crc; i++) {
394 		if (!s3crc[i].dowrite)
395 			continue;
396 		crcstart = s3crc[i].addr;
397 		/* Find chunk */
398 		for (c = 0; c < nfchunks; c++) {
399 			cstart = fchunk[c].addr;
400 			cend = fchunk[c].addr + fchunk[c].len;
401 			/* the line below does an address & len match search */
402 			/* unfortunately, I've found that the len fields of */
403 			/* some crc records don't match with the length of */
404 			/* the actual data, so we're not checking right now */
405 			/* if (crcstart-2 >= cstart && crcend <= cend) break; */
406 
407 			/* note the -2 below, it's to make sure the chunk has */
408 			/* space for the CRC value */
409 			if (crcstart - 2 >= cstart && crcstart < cend)
410 				break;
411 		}
412 		if (c >= nfchunks) {
413 			pr_err("Failed to find chunk for crcrec[%d], addr=0x%06x len=%d , aborting crc.\n",
414 			       i, s3crc[i].addr, s3crc[i].len);
415 			return 1;
416 		}
417 
418 		/* Insert crc */
419 		pr_debug("Adding crc @ 0x%06x\n", s3crc[i].addr - 2);
420 		chunkoff = crcstart - cstart - 2;
421 		dest = fchunk[c].data + chunkoff;
422 		*dest = 0xde;
423 		*(dest + 1) = 0xc0;
424 	}
425 	return result;
426 }
427 
428 /*----------------------------------------------------------------
429  * free_chunks
430  *
431  * Clears the chunklist data structures in preparation for a new file.
432  *
433  * Arguments:
434  *	none
435  *
436  * Returns:
437  *	nothing
438  *----------------------------------------------------------------
439  */
free_chunks(struct imgchunk * fchunk,unsigned int * nfchunks)440 static void free_chunks(struct imgchunk *fchunk, unsigned int *nfchunks)
441 {
442 	int i;
443 
444 	for (i = 0; i < *nfchunks; i++)
445 		kfree(fchunk[i].data);
446 
447 	*nfchunks = 0;
448 	memset(fchunk, 0, sizeof(*fchunk));
449 }
450 
451 /*----------------------------------------------------------------
452  * free_srecs
453  *
454  * Clears the srec data structures in preparation for a new file.
455  *
456  * Arguments:
457  *	none
458  *
459  * Returns:
460  *	nothing
461  *----------------------------------------------------------------
462  */
free_srecs(void)463 static void free_srecs(void)
464 {
465 	ns3data = 0;
466 	kfree(s3data);
467 	ns3plug = 0;
468 	memset(s3plug, 0, sizeof(s3plug));
469 	ns3crc = 0;
470 	memset(s3crc, 0, sizeof(s3crc));
471 	ns3info = 0;
472 	memset(s3info, 0, sizeof(s3info));
473 	startaddr = 0;
474 }
475 
476 /*----------------------------------------------------------------
477  * mkimage
478  *
479  * Scans the currently loaded set of S records for data residing
480  * in contiguous memory regions.  Each contiguous region is then
481  * made into a 'chunk'.  This function assumes that we're building
482  * a new chunk list.  Assumes the s3data items are in sorted order.
483  *
484  * Arguments:	none
485  *
486  * Returns:
487  *	0	- success
488  *	~0	- failure (probably an errno)
489  *----------------------------------------------------------------
490  */
mkimage(struct imgchunk * clist,unsigned int * ccnt)491 static int mkimage(struct imgchunk *clist, unsigned int *ccnt)
492 {
493 	int result = 0;
494 	int i;
495 	int j;
496 	int currchunk = 0;
497 	u32 nextaddr = 0;
498 	u32 s3start;
499 	u32 s3end;
500 	u32 cstart = 0;
501 	u32 cend;
502 	u32 coffset;
503 
504 	/* There may already be data in the chunklist */
505 	*ccnt = 0;
506 
507 	/* Establish the location and size of each chunk */
508 	for (i = 0; i < ns3data; i++) {
509 		if (s3data[i].addr == nextaddr) {
510 			/* existing chunk, grow it */
511 			clist[currchunk].len += s3data[i].len;
512 			nextaddr += s3data[i].len;
513 		} else {
514 			/* New chunk */
515 			(*ccnt)++;
516 			currchunk = *ccnt - 1;
517 			clist[currchunk].addr = s3data[i].addr;
518 			clist[currchunk].len = s3data[i].len;
519 			nextaddr = s3data[i].addr + s3data[i].len;
520 			/* Expand the chunk if there is a CRC record at */
521 			/* their beginning bound */
522 			for (j = 0; j < ns3crc; j++) {
523 				if (s3crc[j].dowrite &&
524 				    s3crc[j].addr == clist[currchunk].addr) {
525 					clist[currchunk].addr -= 2;
526 					clist[currchunk].len += 2;
527 				}
528 			}
529 		}
530 	}
531 
532 	/* We're currently assuming there aren't any overlapping chunks */
533 	/*  if this proves false, we'll need to add code to coalesce. */
534 
535 	/* Allocate buffer space for chunks */
536 	for (i = 0; i < *ccnt; i++) {
537 		clist[i].data = kzalloc(clist[i].len, GFP_KERNEL);
538 		if (!clist[i].data)
539 			return 1;
540 
541 		pr_debug("chunk[%d]: addr=0x%06x len=%d\n",
542 			 i, clist[i].addr, clist[i].len);
543 	}
544 
545 	/* Copy srec data to chunks */
546 	for (i = 0; i < ns3data; i++) {
547 		s3start = s3data[i].addr;
548 		s3end = s3start + s3data[i].len - 1;
549 		for (j = 0; j < *ccnt; j++) {
550 			cstart = clist[j].addr;
551 			cend = cstart + clist[j].len - 1;
552 			if (s3start >= cstart && s3end <= cend)
553 				break;
554 		}
555 		if (((unsigned int)j) >= (*ccnt)) {
556 			pr_err("s3rec(a=0x%06x,l=%d), no chunk match, exiting.\n",
557 			       s3start, s3data[i].len);
558 			return 1;
559 		}
560 		coffset = s3start - cstart;
561 		memcpy(clist[j].data + coffset, s3data[i].data, s3data[i].len);
562 	}
563 
564 	return result;
565 }
566 
567 /*----------------------------------------------------------------
568  * mkpdrlist
569  *
570  * Reads a raw PDA and builds an array of pdrec_t structures.
571  *
572  * Arguments:
573  *	pda	buffer containing raw PDA bytes
574  *	pdrec	ptr to an array of pdrec_t's.  Will be filled on exit.
575  *	nrec	ptr to a variable that will contain the count of PDRs
576  *
577  * Returns:
578  *	0	- success
579  *	~0	- failure (probably an errno)
580  *----------------------------------------------------------------
581  */
mkpdrlist(struct pda * pda)582 static int mkpdrlist(struct pda *pda)
583 {
584 	__le16 *pda16 = (__le16 *)pda->buf;
585 	int curroff;		/* in 'words' */
586 
587 	pda->nrec = 0;
588 	curroff = 0;
589 	while (curroff < (HFA384x_PDA_LEN_MAX / 2 - 1) &&
590 	       le16_to_cpu(pda16[curroff + 1]) != HFA384x_PDR_END_OF_PDA) {
591 		pda->rec[pda->nrec] = (struct hfa384x_pdrec *)&pda16[curroff];
592 
593 		if (le16_to_cpu(pda->rec[pda->nrec]->code) ==
594 		    HFA384x_PDR_NICID) {
595 			memcpy(&nicid, &pda->rec[pda->nrec]->data.nicid,
596 			       sizeof(nicid));
597 			le16_to_cpus(&nicid.id);
598 			le16_to_cpus(&nicid.variant);
599 			le16_to_cpus(&nicid.major);
600 			le16_to_cpus(&nicid.minor);
601 		}
602 		if (le16_to_cpu(pda->rec[pda->nrec]->code) ==
603 		    HFA384x_PDR_MFISUPRANGE) {
604 			memcpy(&rfid, &pda->rec[pda->nrec]->data.mfisuprange,
605 			       sizeof(rfid));
606 			le16_to_cpus(&rfid.id);
607 			le16_to_cpus(&rfid.variant);
608 			le16_to_cpus(&rfid.bottom);
609 			le16_to_cpus(&rfid.top);
610 		}
611 		if (le16_to_cpu(pda->rec[pda->nrec]->code) ==
612 		    HFA384x_PDR_CFISUPRANGE) {
613 			memcpy(&macid, &pda->rec[pda->nrec]->data.cfisuprange,
614 			       sizeof(macid));
615 			le16_to_cpus(&macid.id);
616 			le16_to_cpus(&macid.variant);
617 			le16_to_cpus(&macid.bottom);
618 			le16_to_cpus(&macid.top);
619 		}
620 
621 		(pda->nrec)++;
622 		curroff += le16_to_cpu(pda16[curroff]) + 1;
623 	}
624 	if (curroff >= (HFA384x_PDA_LEN_MAX / 2 - 1)) {
625 		pr_err("no end record found or invalid lengths in PDR data, exiting. %x %d\n",
626 		       curroff, pda->nrec);
627 		return 1;
628 	}
629 	pda->rec[pda->nrec] = (struct hfa384x_pdrec *)&pda16[curroff];
630 	(pda->nrec)++;
631 	return 0;
632 }
633 
634 /*----------------------------------------------------------------
635  * plugimage
636  *
637  * Plugs the given image using the given plug records from the given
638  * PDA and filename.
639  *
640  * Arguments:
641  *	fchunk		Array of image chunks
642  *	nfchunks	Number of image chunks
643  *	s3plug		Array of plug records
644  *	ns3plug		Number of plug records
645  *	pda		Current pda data
646  *
647  * Returns:
648  *	0	success
649  *	~0	failure
650  *----------------------------------------------------------------
651  */
plugimage(struct imgchunk * fchunk,unsigned int nfchunks,struct s3plugrec * s3plug,unsigned int ns3plug,struct pda * pda)652 static int plugimage(struct imgchunk *fchunk, unsigned int nfchunks,
653 		     struct s3plugrec *s3plug, unsigned int ns3plug,
654 		     struct pda *pda)
655 {
656 	int result = 0;
657 	int i;			/* plug index */
658 	int j;			/* index of PDR or -1 if fname plug */
659 	int c;			/* chunk index */
660 	u32 pstart;
661 	u32 pend;
662 	u32 cstart = 0;
663 	u32 cend;
664 	u32 chunkoff;
665 	u8 *dest;
666 
667 	/* for each plug record */
668 	for (i = 0; i < ns3plug; i++) {
669 		pstart = s3plug[i].addr;
670 		pend = s3plug[i].addr + s3plug[i].len;
671 		j = -1;
672 		/* find the matching PDR (or filename) */
673 		if (s3plug[i].itemcode != 0xffffffffUL) { /* not filename */
674 			for (j = 0; j < pda->nrec; j++) {
675 				if (s3plug[i].itemcode ==
676 				    le16_to_cpu(pda->rec[j]->code))
677 					break;
678 			}
679 		}
680 		if (j >= pda->nrec && j != -1) { /*  if no matching PDR, fail */
681 			pr_warn("warning: Failed to find PDR for plugrec 0x%04x.\n",
682 				s3plug[i].itemcode);
683 			continue;	/* and move on to the next PDR */
684 
685 			/* MSM: They swear that unless it's the MAC address,
686 			 * the serial number, or the TX calibration records,
687 			 * then there's reasonable defaults in the f/w
688 			 * image.  Therefore, missing PDRs in the card
689 			 * should only be a warning, not fatal.
690 			 * TODO: add fatals for the PDRs mentioned above.
691 			 */
692 		}
693 
694 		/* Validate plug len against PDR len */
695 		if (j != -1 && s3plug[i].len < le16_to_cpu(pda->rec[j]->len)) {
696 			pr_err("error: Plug vs. PDR len mismatch for plugrec 0x%04x, abort plugging.\n",
697 			       s3plug[i].itemcode);
698 			result = 1;
699 			continue;
700 		}
701 
702 		/*
703 		 * Validate plug address against
704 		 * chunk data and identify chunk
705 		 */
706 		for (c = 0; c < nfchunks; c++) {
707 			cstart = fchunk[c].addr;
708 			cend = fchunk[c].addr + fchunk[c].len;
709 			if (pstart >= cstart && pend <= cend)
710 				break;
711 		}
712 		if (c >= nfchunks) {
713 			pr_err("error: Failed to find image chunk for plugrec 0x%04x.\n",
714 			       s3plug[i].itemcode);
715 			result = 1;
716 			continue;
717 		}
718 
719 		/* Plug data */
720 		chunkoff = pstart - cstart;
721 		dest = fchunk[c].data + chunkoff;
722 		pr_debug("Plugging item 0x%04x @ 0x%06x, len=%d, cnum=%d coff=0x%06x\n",
723 			 s3plug[i].itemcode, pstart, s3plug[i].len,
724 			 c, chunkoff);
725 
726 		if (j == -1) {	/* plug the filename */
727 			memset(dest, 0, s3plug[i].len);
728 			strncpy(dest, PRISM2_USB_FWFILE, s3plug[i].len - 1);
729 		} else {	/* plug a PDR */
730 			memcpy(dest, &pda->rec[j]->data, s3plug[i].len);
731 		}
732 	}
733 	return result;
734 }
735 
736 /*----------------------------------------------------------------
737  * read_cardpda
738  *
739  * Sends the command for the driver to read the pda from the card
740  * named in the device variable.  Upon success, the card pda is
741  * stored in the "cardpda" variables.  Note that the pda structure
742  * is considered 'well formed' after this function.  That means
743  * that the nrecs is valid, the rec array has been set up, and there's
744  * a valid PDAEND record in the raw PDA data.
745  *
746  * Arguments:
747  *	pda		pda structure
748  *	wlandev		device
749  *
750  * Returns:
751  *	0	- success
752  *	~0	- failure (probably an errno)
753  *----------------------------------------------------------------
754  */
read_cardpda(struct pda * pda,struct wlandevice * wlandev)755 static int read_cardpda(struct pda *pda, struct wlandevice *wlandev)
756 {
757 	int result = 0;
758 	struct p80211msg_p2req_readpda *msg;
759 
760 	msg = kzalloc(sizeof(*msg), GFP_KERNEL);
761 	if (!msg)
762 		return -ENOMEM;
763 
764 	/* set up the msg */
765 	msg->msgcode = DIDMSG_P2REQ_READPDA;
766 	msg->msglen = sizeof(msg);
767 	strscpy(msg->devname, wlandev->name, sizeof(msg->devname));
768 	msg->pda.did = DIDMSG_P2REQ_READPDA_PDA;
769 	msg->pda.len = HFA384x_PDA_LEN_MAX;
770 	msg->pda.status = P80211ENUM_msgitem_status_no_value;
771 	msg->resultcode.did = DIDMSG_P2REQ_READPDA_RESULTCODE;
772 	msg->resultcode.len = sizeof(u32);
773 	msg->resultcode.status = P80211ENUM_msgitem_status_no_value;
774 
775 	if (prism2mgmt_readpda(wlandev, msg) != 0) {
776 		/* prism2mgmt_readpda prints an errno if appropriate */
777 		result = -1;
778 	} else if (msg->resultcode.data == P80211ENUM_resultcode_success) {
779 		memcpy(pda->buf, msg->pda.data, HFA384x_PDA_LEN_MAX);
780 		result = mkpdrlist(pda);
781 	} else {
782 		/* resultcode must've been something other than success */
783 		result = -1;
784 	}
785 
786 	kfree(msg);
787 	return result;
788 }
789 
790 /*----------------------------------------------------------------
791  * read_fwfile
792  *
793  * Reads the given fw file which should have been compiled from an srec
794  * file. Each record in the fw file will either be a plain data record,
795  * a start address record, or other records used for plugging.
796  *
797  * Note that data records are expected to be sorted into
798  * ascending address order in the fw file.
799  *
800  * Note also that the start address record, originally an S7 record in
801  * the srec file, is expected in the fw file to be like a data record but
802  * with a certain address to make it identifiable.
803  *
804  * Here's the SREC format that the fw should have come from:
805  * S[37]nnaaaaaaaaddd...dddcc
806  *
807  *       nn - number of bytes starting with the address field
808  * aaaaaaaa - address in readable (or big endian) format
809  * dd....dd - 0-245 data bytes (two chars per byte)
810  *       cc - checksum
811  *
812  * The S7 record's (there should be only one) address value gets
813  * converted to an S3 record with address of 0xff400000, with the
814  * start address being stored as a 4 byte data word. That address is
815  * the start execution address used for RAM downloads.
816  *
817  * The S3 records have a collection of subformats indicated by the
818  * value of aaaaaaaa:
819  *   0xff000000 - Plug record, data field format:
820  *                xxxxxxxxaaaaaaaassssssss
821  *                x - PDR code number (little endian)
822  *                a - Address in load image to plug (little endian)
823  *                s - Length of plug data area (little endian)
824  *
825  *   0xff100000 - CRC16 generation record, data field format:
826  *                aaaaaaaassssssssbbbbbbbb
827  *                a - Start address for CRC calculation (little endian)
828  *                s - Length of data to  calculate over (little endian)
829  *                b - Boolean, true=write crc, false=don't write
830  *
831  *   0xff200000 - Info record, data field format:
832  *                ssssttttdd..dd
833  *                s - Size in words (little endian)
834  *                t - Info type (little endian), see #defines and
835  *                    struct s3inforec for details about types.
836  *                d - (s - 1) little endian words giving the contents of
837  *                    the given info type.
838  *
839  *   0xff400000 - Start address record, data field format:
840  *                aaaaaaaa
841  *                a - Address in load image to plug (little endian)
842  *
843  * Arguments:
844  *	record	firmware image (ihex record structure) in kernel memory
845  *
846  * Returns:
847  *	0	- success
848  *	~0	- failure (probably an errno)
849  *----------------------------------------------------------------
850  */
read_fwfile(const struct ihex_binrec * record)851 static int read_fwfile(const struct ihex_binrec *record)
852 {
853 	int		i;
854 	int		rcnt = 0;
855 	u16		*tmpinfo;
856 	u16		*ptr16;
857 	u32		*ptr32, len, addr;
858 
859 	pr_debug("Reading fw file ...\n");
860 
861 	while (record) {
862 		rcnt++;
863 
864 		len = be16_to_cpu(record->len);
865 		addr = be32_to_cpu(record->addr);
866 
867 		/* Point into data for different word lengths */
868 		ptr32 = (u32 *)record->data;
869 		ptr16 = (u16 *)record->data;
870 
871 		/* parse what was an S3 srec and put it in the right array */
872 		switch (addr) {
873 		case S3ADDR_START:
874 			startaddr = *ptr32;
875 			pr_debug("  S7 start addr, record=%d addr=0x%08x\n",
876 				 rcnt,
877 				 startaddr);
878 			break;
879 		case S3ADDR_PLUG:
880 			s3plug[ns3plug].itemcode = *ptr32;
881 			s3plug[ns3plug].addr = *(ptr32 + 1);
882 			s3plug[ns3plug].len = *(ptr32 + 2);
883 
884 			pr_debug("  S3 plugrec, record=%d itemcode=0x%08x addr=0x%08x len=%d\n",
885 				 rcnt,
886 				 s3plug[ns3plug].itemcode,
887 				 s3plug[ns3plug].addr,
888 				 s3plug[ns3plug].len);
889 
890 			ns3plug++;
891 			if (ns3plug == S3PLUG_MAX) {
892 				pr_err("S3 plugrec limit reached - aborting\n");
893 				return 1;
894 			}
895 			break;
896 		case S3ADDR_CRC:
897 			s3crc[ns3crc].addr = *ptr32;
898 			s3crc[ns3crc].len = *(ptr32 + 1);
899 			s3crc[ns3crc].dowrite = *(ptr32 + 2);
900 
901 			pr_debug("  S3 crcrec, record=%d addr=0x%08x len=%d write=0x%08x\n",
902 				 rcnt,
903 				 s3crc[ns3crc].addr,
904 				 s3crc[ns3crc].len,
905 				 s3crc[ns3crc].dowrite);
906 			ns3crc++;
907 			if (ns3crc == S3CRC_MAX) {
908 				pr_err("S3 crcrec limit reached - aborting\n");
909 				return 1;
910 			}
911 			break;
912 		case S3ADDR_INFO:
913 			s3info[ns3info].len = *ptr16;
914 			s3info[ns3info].type = *(ptr16 + 1);
915 
916 			pr_debug("  S3 inforec, record=%d len=0x%04x type=0x%04x\n",
917 				 rcnt,
918 				 s3info[ns3info].len,
919 				 s3info[ns3info].type);
920 			if (((s3info[ns3info].len - 1) * sizeof(u16)) >
921 			   sizeof(s3info[ns3info].info)) {
922 				pr_err("S3 inforec length too long - aborting\n");
923 				return 1;
924 			}
925 
926 			tmpinfo = (u16 *)&s3info[ns3info].info.version;
927 			pr_debug("            info=");
928 			for (i = 0; i < s3info[ns3info].len - 1; i++) {
929 				tmpinfo[i] = *(ptr16 + 2 + i);
930 				pr_debug("%04x ", tmpinfo[i]);
931 			}
932 			pr_debug("\n");
933 
934 			ns3info++;
935 			if (ns3info == S3INFO_MAX) {
936 				pr_err("S3 inforec limit reached - aborting\n");
937 				return 1;
938 			}
939 			break;
940 		default:	/* Data record */
941 			s3data[ns3data].addr = addr;
942 			s3data[ns3data].len = len;
943 			s3data[ns3data].data = (uint8_t *)record->data;
944 			ns3data++;
945 			if (ns3data == S3DATA_MAX) {
946 				pr_err("S3 datarec limit reached - aborting\n");
947 				return 1;
948 			}
949 			break;
950 		}
951 		record = ihex_next_binrec(record);
952 	}
953 	return 0;
954 }
955 
956 /*----------------------------------------------------------------
957  * writeimage
958  *
959  * Takes the chunks, builds p80211 messages and sends them down
960  * to the driver for writing to the card.
961  *
962  * Arguments:
963  *	wlandev		device
964  *	fchunk		Array of image chunks
965  *	nfchunks	Number of image chunks
966  *
967  * Returns:
968  *	0	success
969  *	~0	failure
970  *----------------------------------------------------------------
971  */
writeimage(struct wlandevice * wlandev,struct imgchunk * fchunk,unsigned int nfchunks)972 static int writeimage(struct wlandevice *wlandev, struct imgchunk *fchunk,
973 		      unsigned int nfchunks)
974 {
975 	int result = 0;
976 	struct p80211msg_p2req_ramdl_state *rstmsg;
977 	struct p80211msg_p2req_ramdl_write *rwrmsg;
978 	u32 resultcode;
979 	int i;
980 	int j;
981 	unsigned int nwrites;
982 	u32 curroff;
983 	u32 currlen;
984 	u32 currdaddr;
985 
986 	rstmsg = kzalloc(sizeof(*rstmsg), GFP_KERNEL);
987 	rwrmsg = kzalloc(sizeof(*rwrmsg), GFP_KERNEL);
988 	if (!rstmsg || !rwrmsg) {
989 		netdev_err(wlandev->netdev,
990 			   "%s: no memory for firmware download, aborting download\n",
991 			   __func__);
992 		result = -ENOMEM;
993 		goto free_result;
994 	}
995 
996 	/* Initialize the messages */
997 	strscpy(rstmsg->devname, wlandev->name, sizeof(rstmsg->devname));
998 	rstmsg->msgcode = DIDMSG_P2REQ_RAMDL_STATE;
999 	rstmsg->msglen = sizeof(*rstmsg);
1000 	rstmsg->enable.did = DIDMSG_P2REQ_RAMDL_STATE_ENABLE;
1001 	rstmsg->exeaddr.did = DIDMSG_P2REQ_RAMDL_STATE_EXEADDR;
1002 	rstmsg->resultcode.did = DIDMSG_P2REQ_RAMDL_STATE_RESULTCODE;
1003 	rstmsg->enable.status = P80211ENUM_msgitem_status_data_ok;
1004 	rstmsg->exeaddr.status = P80211ENUM_msgitem_status_data_ok;
1005 	rstmsg->resultcode.status = P80211ENUM_msgitem_status_no_value;
1006 	rstmsg->enable.len = sizeof(u32);
1007 	rstmsg->exeaddr.len = sizeof(u32);
1008 	rstmsg->resultcode.len = sizeof(u32);
1009 
1010 	strscpy(rwrmsg->devname, wlandev->name, sizeof(rwrmsg->devname));
1011 	rwrmsg->msgcode = DIDMSG_P2REQ_RAMDL_WRITE;
1012 	rwrmsg->msglen = sizeof(*rwrmsg);
1013 	rwrmsg->addr.did = DIDMSG_P2REQ_RAMDL_WRITE_ADDR;
1014 	rwrmsg->len.did = DIDMSG_P2REQ_RAMDL_WRITE_LEN;
1015 	rwrmsg->data.did = DIDMSG_P2REQ_RAMDL_WRITE_DATA;
1016 	rwrmsg->resultcode.did = DIDMSG_P2REQ_RAMDL_WRITE_RESULTCODE;
1017 	rwrmsg->addr.status = P80211ENUM_msgitem_status_data_ok;
1018 	rwrmsg->len.status = P80211ENUM_msgitem_status_data_ok;
1019 	rwrmsg->data.status = P80211ENUM_msgitem_status_data_ok;
1020 	rwrmsg->resultcode.status = P80211ENUM_msgitem_status_no_value;
1021 	rwrmsg->addr.len = sizeof(u32);
1022 	rwrmsg->len.len = sizeof(u32);
1023 	rwrmsg->data.len = WRITESIZE_MAX;
1024 	rwrmsg->resultcode.len = sizeof(u32);
1025 
1026 	/* Send xxx_state(enable) */
1027 	pr_debug("Sending dl_state(enable) message.\n");
1028 	rstmsg->enable.data = P80211ENUM_truth_true;
1029 	rstmsg->exeaddr.data = startaddr;
1030 
1031 	result = prism2mgmt_ramdl_state(wlandev, rstmsg);
1032 	if (result) {
1033 		netdev_err(wlandev->netdev,
1034 			   "%s state enable failed w/ result=%d, aborting download\n",
1035 			   __func__, result);
1036 		goto free_result;
1037 	}
1038 	resultcode = rstmsg->resultcode.data;
1039 	if (resultcode != P80211ENUM_resultcode_success) {
1040 		netdev_err(wlandev->netdev,
1041 			   "%s()->xxxdl_state msg indicates failure, w/ resultcode=%d, aborting download.\n",
1042 			   __func__, resultcode);
1043 		result = 1;
1044 		goto free_result;
1045 	}
1046 
1047 	/* Now, loop through the data chunks and send WRITESIZE_MAX data */
1048 	for (i = 0; i < nfchunks; i++) {
1049 		nwrites = fchunk[i].len / WRITESIZE_MAX;
1050 		nwrites += (fchunk[i].len % WRITESIZE_MAX) ? 1 : 0;
1051 		curroff = 0;
1052 		for (j = 0; j < nwrites; j++) {
1053 			/* TODO Move this to a separate function */
1054 			int lenleft = fchunk[i].len - (WRITESIZE_MAX * j);
1055 
1056 			if (fchunk[i].len > WRITESIZE_MAX)
1057 				currlen = WRITESIZE_MAX;
1058 			else
1059 				currlen = lenleft;
1060 			curroff = j * WRITESIZE_MAX;
1061 			currdaddr = fchunk[i].addr + curroff;
1062 			/* Setup the message */
1063 			rwrmsg->addr.data = currdaddr;
1064 			rwrmsg->len.data = currlen;
1065 			memcpy(rwrmsg->data.data,
1066 			       fchunk[i].data + curroff, currlen);
1067 
1068 			/* Send flashdl_write(pda) */
1069 			pr_debug
1070 			    ("Sending xxxdl_write message addr=%06x len=%d.\n",
1071 			     currdaddr, currlen);
1072 
1073 			result = prism2mgmt_ramdl_write(wlandev, rwrmsg);
1074 
1075 			/* Check the results */
1076 			if (result) {
1077 				netdev_err(wlandev->netdev,
1078 					   "%s chunk write failed w/ result=%d, aborting download\n",
1079 					   __func__, result);
1080 				goto free_result;
1081 			}
1082 			resultcode = rstmsg->resultcode.data;
1083 			if (resultcode != P80211ENUM_resultcode_success) {
1084 				pr_err("%s()->xxxdl_write msg indicates failure, w/ resultcode=%d, aborting download.\n",
1085 				       __func__, resultcode);
1086 				result = 1;
1087 				goto free_result;
1088 			}
1089 		}
1090 	}
1091 
1092 	/* Send xxx_state(disable) */
1093 	pr_debug("Sending dl_state(disable) message.\n");
1094 	rstmsg->enable.data = P80211ENUM_truth_false;
1095 	rstmsg->exeaddr.data = 0;
1096 
1097 	result = prism2mgmt_ramdl_state(wlandev, rstmsg);
1098 	if (result) {
1099 		netdev_err(wlandev->netdev,
1100 			   "%s state disable failed w/ result=%d, aborting download\n",
1101 			   __func__, result);
1102 		goto free_result;
1103 	}
1104 	resultcode = rstmsg->resultcode.data;
1105 	if (resultcode != P80211ENUM_resultcode_success) {
1106 		netdev_err(wlandev->netdev,
1107 			   "%s()->xxxdl_state msg indicates failure, w/ resultcode=%d, aborting download.\n",
1108 			   __func__, resultcode);
1109 		result = 1;
1110 		goto free_result;
1111 	}
1112 
1113 free_result:
1114 	kfree(rstmsg);
1115 	kfree(rwrmsg);
1116 	return result;
1117 }
1118 
validate_identity(void)1119 static int validate_identity(void)
1120 {
1121 	int i;
1122 	int result = 1;
1123 	int trump = 0;
1124 
1125 	pr_debug("NIC ID: %#x v%d.%d.%d\n",
1126 		 nicid.id, nicid.major, nicid.minor, nicid.variant);
1127 	pr_debug("MFI ID: %#x v%d %d->%d\n",
1128 		 rfid.id, rfid.variant, rfid.bottom, rfid.top);
1129 	pr_debug("CFI ID: %#x v%d %d->%d\n",
1130 		 macid.id, macid.variant, macid.bottom, macid.top);
1131 	pr_debug("PRI ID: %#x v%d %d->%d\n",
1132 		 priid.id, priid.variant, priid.bottom, priid.top);
1133 
1134 	for (i = 0; i < ns3info; i++) {
1135 		switch (s3info[i].type) {
1136 		case 1:
1137 			pr_debug("Version:  ID %#x %d.%d.%d\n",
1138 				 s3info[i].info.version.id,
1139 				 s3info[i].info.version.major,
1140 				 s3info[i].info.version.minor,
1141 				 s3info[i].info.version.variant);
1142 			break;
1143 		case 2:
1144 			pr_debug("Compat: Role %#x Id %#x v%d %d->%d\n",
1145 				 s3info[i].info.compat.role,
1146 				 s3info[i].info.compat.id,
1147 				 s3info[i].info.compat.variant,
1148 				 s3info[i].info.compat.bottom,
1149 				 s3info[i].info.compat.top);
1150 
1151 			/* MAC compat range */
1152 			if ((s3info[i].info.compat.role == 1) &&
1153 			    (s3info[i].info.compat.id == 2)) {
1154 				if (s3info[i].info.compat.variant !=
1155 				    macid.variant) {
1156 					result = 2;
1157 				}
1158 			}
1159 
1160 			/* PRI compat range */
1161 			if ((s3info[i].info.compat.role == 1) &&
1162 			    (s3info[i].info.compat.id == 3)) {
1163 				if ((s3info[i].info.compat.bottom >
1164 				     priid.top) ||
1165 				    (s3info[i].info.compat.top <
1166 				     priid.bottom)) {
1167 					result = 3;
1168 				}
1169 			}
1170 			/* SEC compat range */
1171 			if ((s3info[i].info.compat.role == 1) &&
1172 			    (s3info[i].info.compat.id == 4)) {
1173 				/* FIXME: isn't something missing here? */
1174 			}
1175 
1176 			break;
1177 		case 3:
1178 			pr_debug("Seq: %#x\n", s3info[i].info.buildseq);
1179 
1180 			break;
1181 		case 4:
1182 			pr_debug("Platform:  ID %#x %d.%d.%d\n",
1183 				 s3info[i].info.version.id,
1184 				 s3info[i].info.version.major,
1185 				 s3info[i].info.version.minor,
1186 				 s3info[i].info.version.variant);
1187 
1188 			if (nicid.id != s3info[i].info.version.id)
1189 				continue;
1190 			if (nicid.major != s3info[i].info.version.major)
1191 				continue;
1192 			if (nicid.minor != s3info[i].info.version.minor)
1193 				continue;
1194 			if ((nicid.variant != s3info[i].info.version.variant) &&
1195 			    (nicid.id != 0x8008))
1196 				continue;
1197 
1198 			trump = 1;
1199 			break;
1200 		case 0x8001:
1201 			pr_debug("name inforec len %d\n", s3info[i].len);
1202 
1203 			break;
1204 		default:
1205 			pr_debug("Unknown inforec type %d\n", s3info[i].type);
1206 		}
1207 	}
1208 	/* walk through */
1209 
1210 	if (trump && (result != 2))
1211 		result = 0;
1212 	return result;
1213 }
1214