2 * Copyright (c) 2013 Broadcom Corporation
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 #include <linux/kernel.h>
18 #include <linux/slab.h>
19 #include <linux/device.h>
20 #include <linux/firmware.h>
21 #include <linux/module.h>
26 #define BRCMF_FW_MAX_NVRAM_SIZE 64000
27 #define BRCMF_FW_NVRAM_DEVPATH_LEN 19 /* devpath0=pcie/1/4/ */
28 #define BRCMF_FW_NVRAM_PCIEDEV_LEN 10 /* pcie/1/4/ + \0 */
30 char brcmf_firmware_path[BRCMF_FW_PATH_LEN];
31 module_param_string(firmware_path, brcmf_firmware_path,
32 BRCMF_FW_PATH_LEN, 0440);
34 enum nvram_parser_state {
43 * struct nvram_parser - internal info for parser.
45 * @state: current parser state.
46 * @data: input buffer being parsed.
47 * @nvram: output buffer with parse result.
48 * @nvram_len: lenght of parse result.
49 * @line: current line.
50 * @column: current column in line.
51 * @pos: byte offset in input buffer.
52 * @entry: start position of key,value entry.
53 * @multi_dev_v1: detect pcie multi device v1 (compressed).
54 * @multi_dev_v2: detect pcie multi device v2.
57 enum nvram_parser_state state;
70 * is_nvram_char() - check if char is a valid one for NVRAM entry
72 * It accepts all printable ASCII chars except for '#' which opens a comment.
73 * Please note that ' ' (space) while accepted is not a valid key name char.
75 static bool is_nvram_char(char c)
77 /* comment marker excluded */
81 /* key and value may have any other readable character */
82 return (c >= 0x20 && c < 0x7f);
85 static bool is_whitespace(char c)
87 return (c == ' ' || c == '\r' || c == '\n' || c == '\t');
90 static enum nvram_parser_state brcmf_nvram_handle_idle(struct nvram_parser *nvp)
94 c = nvp->data[nvp->pos];
101 if (is_nvram_char(c)) {
102 nvp->entry = nvp->pos;
105 brcmf_dbg(INFO, "warning: ln=%d:col=%d: ignoring invalid character\n",
106 nvp->line, nvp->column);
113 static enum nvram_parser_state brcmf_nvram_handle_key(struct nvram_parser *nvp)
115 enum nvram_parser_state st = nvp->state;
118 c = nvp->data[nvp->pos];
120 /* ignore RAW1 by treating as comment */
121 if (strncmp(&nvp->data[nvp->entry], "RAW1", 4) == 0)
125 if (strncmp(&nvp->data[nvp->entry], "devpath", 7) == 0)
126 nvp->multi_dev_v1 = true;
127 if (strncmp(&nvp->data[nvp->entry], "pcie/", 5) == 0)
128 nvp->multi_dev_v2 = true;
129 } else if (!is_nvram_char(c) || c == ' ') {
130 brcmf_dbg(INFO, "warning: ln=%d:col=%d: '=' expected, skip invalid key entry\n",
131 nvp->line, nvp->column);
140 static enum nvram_parser_state
141 brcmf_nvram_handle_value(struct nvram_parser *nvp)
148 c = nvp->data[nvp->pos];
149 if (!is_nvram_char(c)) {
150 /* key,value pair complete */
151 ekv = (u8 *)&nvp->data[nvp->pos];
152 skv = (u8 *)&nvp->data[nvp->entry];
154 if (nvp->nvram_len + cplen + 1 >= BRCMF_FW_MAX_NVRAM_SIZE)
156 /* copy to output buffer */
157 memcpy(&nvp->nvram[nvp->nvram_len], skv, cplen);
158 nvp->nvram_len += cplen;
159 nvp->nvram[nvp->nvram_len] = '\0';
168 static enum nvram_parser_state
169 brcmf_nvram_handle_comment(struct nvram_parser *nvp)
173 sol = (char *)&nvp->data[nvp->pos];
174 eoc = strchr(sol, '\n');
176 eoc = strchr(sol, '\0');
181 /* eat all moving to next line */
184 nvp->pos += (eoc - sol) + 1;
188 static enum nvram_parser_state brcmf_nvram_handle_end(struct nvram_parser *nvp)
194 static enum nvram_parser_state
195 (*nv_parser_states[])(struct nvram_parser *nvp) = {
196 brcmf_nvram_handle_idle,
197 brcmf_nvram_handle_key,
198 brcmf_nvram_handle_value,
199 brcmf_nvram_handle_comment,
200 brcmf_nvram_handle_end
203 static int brcmf_init_nvram_parser(struct nvram_parser *nvp,
204 const u8 *data, size_t data_len)
208 memset(nvp, 0, sizeof(*nvp));
210 /* Limit size to MAX_NVRAM_SIZE, some files contain lot of comment */
211 if (data_len > BRCMF_FW_MAX_NVRAM_SIZE)
212 size = BRCMF_FW_MAX_NVRAM_SIZE;
215 /* Alloc for extra 0 byte + roundup by 4 + length field */
216 size += 1 + 3 + sizeof(u32);
217 nvp->nvram = kzalloc(size, GFP_KERNEL);
226 /* brcmf_fw_strip_multi_v1 :Some nvram files contain settings for multiple
227 * devices. Strip it down for one device, use domain_nr/bus_nr to determine
228 * which data is to be returned. v1 is the version where nvram is stored
229 * compressed and "devpath" maps to index for valid entries.
231 static void brcmf_fw_strip_multi_v1(struct nvram_parser *nvp, u16 domain_nr,
234 /* Device path with a leading '=' key-value separator */
235 char pci_path[] = "=pci/?/?";
237 char pcie_path[] = "=pcie/?/?";
245 nvram = kzalloc(nvp->nvram_len + 1 + 3 + sizeof(u32), GFP_KERNEL);
249 /* min length: devpath0=pcie/1/4/ + 0:x=y */
250 if (nvp->nvram_len < BRCMF_FW_NVRAM_DEVPATH_LEN + 6)
253 /* First search for the devpathX and see if it is the configuration
254 * for domain_nr/bus_nr. Search complete nvp
256 snprintf(pci_path, sizeof(pci_path), "=pci/%d/%d", domain_nr,
258 pci_len = strlen(pci_path);
259 snprintf(pcie_path, sizeof(pcie_path), "=pcie/%d/%d", domain_nr,
261 pcie_len = strlen(pcie_path);
264 while (i < nvp->nvram_len - BRCMF_FW_NVRAM_DEVPATH_LEN) {
265 /* Format: devpathX=pcie/Y/Z/
266 * Y = domain_nr, Z = bus_nr, X = virtual ID
268 if (strncmp(&nvp->nvram[i], "devpath", 7) == 0 &&
269 (!strncmp(&nvp->nvram[i + 8], pci_path, pci_len) ||
270 !strncmp(&nvp->nvram[i + 8], pcie_path, pcie_len))) {
271 id = nvp->nvram[i + 7] - '0';
275 while (nvp->nvram[i] != 0)
282 /* Now copy all valid entries, release old nvram and assign new one */
285 while (i < nvp->nvram_len) {
286 if ((nvp->nvram[i] - '0' == id) && (nvp->nvram[i + 1] == ':')) {
288 while (nvp->nvram[i] != 0) {
289 nvram[j] = nvp->nvram[i];
296 while (nvp->nvram[i] != 0)
310 /* brcmf_fw_strip_multi_v2 :Some nvram files contain settings for multiple
311 * devices. Strip it down for one device, use domain_nr/bus_nr to determine
312 * which data is to be returned. v2 is the version where nvram is stored
313 * uncompressed, all relevant valid entries are identified by
314 * pcie/domain_nr/bus_nr:
316 static void brcmf_fw_strip_multi_v2(struct nvram_parser *nvp, u16 domain_nr,
319 char prefix[BRCMF_FW_NVRAM_PCIEDEV_LEN];
324 nvram = kzalloc(nvp->nvram_len + 1 + 3 + sizeof(u32), GFP_KERNEL);
328 /* Copy all valid entries, release old nvram and assign new one.
329 * Valid entries are of type pcie/X/Y/ where X = domain_nr and
332 snprintf(prefix, sizeof(prefix), "pcie/%d/%d/", domain_nr, bus_nr);
333 len = strlen(prefix);
336 while (i < nvp->nvram_len - len) {
337 if (strncmp(&nvp->nvram[i], prefix, len) == 0) {
339 while (nvp->nvram[i] != 0) {
340 nvram[j] = nvp->nvram[i];
347 while (nvp->nvram[i] != 0)
360 /* brcmf_nvram_strip :Takes a buffer of "<var>=<value>\n" lines read from a fil
361 * and ending in a NUL. Removes carriage returns, empty lines, comment lines,
362 * and converts newlines to NULs. Shortens buffer as needed and pads with NULs.
363 * End of buffer is completed with token identifying length of buffer.
365 static void *brcmf_fw_nvram_strip(const u8 *data, size_t data_len,
366 u32 *new_length, u16 domain_nr, u16 bus_nr)
368 struct nvram_parser nvp;
373 if (brcmf_init_nvram_parser(&nvp, data, data_len) < 0)
376 while (nvp.pos < data_len) {
377 nvp.state = nv_parser_states[nvp.state](&nvp);
378 if (nvp.state == END)
381 if (nvp.multi_dev_v1)
382 brcmf_fw_strip_multi_v1(&nvp, domain_nr, bus_nr);
383 else if (nvp.multi_dev_v2)
384 brcmf_fw_strip_multi_v2(&nvp, domain_nr, bus_nr);
386 if (nvp.nvram_len == 0) {
392 *new_length = roundup(nvp.nvram_len + 1, 4);
393 while (pad != *new_length) {
398 token = *new_length / 4;
399 token = (~token << 16) | (token & 0x0000FFFF);
400 token_le = cpu_to_le32(token);
402 memcpy(&nvp.nvram[*new_length], &token_le, sizeof(token_le));
403 *new_length += sizeof(token_le);
408 void brcmf_fw_nvram_free(void *nvram)
416 const struct firmware *code;
417 const char *nvram_name;
420 void (*done)(struct device *dev, const struct firmware *fw,
421 void *nvram_image, u32 nvram_len);
424 static void brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx)
426 struct brcmf_fw *fwctx = ctx;
427 u32 nvram_length = 0;
430 brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(fwctx->dev));
431 if (!fw && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL))
435 nvram = brcmf_fw_nvram_strip(fw->data, fw->size, &nvram_length,
436 fwctx->domain_nr, fwctx->bus_nr);
437 release_firmware(fw);
438 if (!nvram && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL))
442 fwctx->done(fwctx->dev, fwctx->code, nvram, nvram_length);
447 brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev));
448 release_firmware(fwctx->code);
449 device_release_driver(fwctx->dev);
453 static void brcmf_fw_request_code_done(const struct firmware *fw, void *ctx)
455 struct brcmf_fw *fwctx = ctx;
458 brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(fwctx->dev));
462 /* only requested code so done here */
463 if (!(fwctx->flags & BRCMF_FW_REQUEST_NVRAM)) {
464 fwctx->done(fwctx->dev, fw, NULL, 0);
469 ret = request_firmware_nowait(THIS_MODULE, true, fwctx->nvram_name,
470 fwctx->dev, GFP_KERNEL, fwctx,
471 brcmf_fw_request_nvram_done);
476 /* when nvram is optional call .done() callback here */
477 if (fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL) {
478 fwctx->done(fwctx->dev, fw, NULL, 0);
483 /* failed nvram request */
484 release_firmware(fw);
486 brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev));
487 device_release_driver(fwctx->dev);
491 int brcmf_fw_get_firmwares_pcie(struct device *dev, u16 flags,
492 const char *code, const char *nvram,
493 void (*fw_cb)(struct device *dev,
494 const struct firmware *fw,
495 void *nvram_image, u32 nvram_len),
496 u16 domain_nr, u16 bus_nr)
498 struct brcmf_fw *fwctx;
500 brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(dev));
504 if ((flags & BRCMF_FW_REQUEST_NVRAM) && !nvram)
507 fwctx = kzalloc(sizeof(*fwctx), GFP_KERNEL);
512 fwctx->flags = flags;
514 if (flags & BRCMF_FW_REQUEST_NVRAM)
515 fwctx->nvram_name = nvram;
516 fwctx->domain_nr = domain_nr;
517 fwctx->bus_nr = bus_nr;
519 return request_firmware_nowait(THIS_MODULE, true, code, dev,
521 brcmf_fw_request_code_done);
524 int brcmf_fw_get_firmwares(struct device *dev, u16 flags,
525 const char *code, const char *nvram,
526 void (*fw_cb)(struct device *dev,
527 const struct firmware *fw,
528 void *nvram_image, u32 nvram_len))
530 return brcmf_fw_get_firmwares_pcie(dev, flags, code, nvram, fw_cb, 0,