firmware.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542
  1. /*
  2. * Copyright (c) 2013 Broadcom Corporation
  3. *
  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.
  7. *
  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.
  15. */
  16. #include <linux/kernel.h>
  17. #include <linux/slab.h>
  18. #include <linux/device.h>
  19. #include <linux/firmware.h>
  20. #include <linux/module.h>
  21. #include <linux/bcm47xx_nvram.h>
  22. #include "debug.h"
  23. #include "firmware.h"
  24. #define BRCMF_FW_MAX_NVRAM_SIZE 64000
  25. #define BRCMF_FW_NVRAM_DEVPATH_LEN 19 /* devpath0=pcie/1/4/ */
  26. #define BRCMF_FW_NVRAM_PCIEDEV_LEN 10 /* pcie/1/4/ + \0 */
  27. char brcmf_firmware_path[BRCMF_FW_PATH_LEN];
  28. module_param_string(firmware_path, brcmf_firmware_path,
  29. BRCMF_FW_PATH_LEN, 0440);
  30. enum nvram_parser_state {
  31. IDLE,
  32. KEY,
  33. VALUE,
  34. COMMENT,
  35. END
  36. };
  37. /**
  38. * struct nvram_parser - internal info for parser.
  39. *
  40. * @state: current parser state.
  41. * @data: input buffer being parsed.
  42. * @nvram: output buffer with parse result.
  43. * @nvram_len: lenght of parse result.
  44. * @line: current line.
  45. * @column: current column in line.
  46. * @pos: byte offset in input buffer.
  47. * @entry: start position of key,value entry.
  48. * @multi_dev_v1: detect pcie multi device v1 (compressed).
  49. * @multi_dev_v2: detect pcie multi device v2.
  50. */
  51. struct nvram_parser {
  52. enum nvram_parser_state state;
  53. const u8 *data;
  54. u8 *nvram;
  55. u32 nvram_len;
  56. u32 line;
  57. u32 column;
  58. u32 pos;
  59. u32 entry;
  60. bool multi_dev_v1;
  61. bool multi_dev_v2;
  62. };
  63. /**
  64. * is_nvram_char() - check if char is a valid one for NVRAM entry
  65. *
  66. * It accepts all printable ASCII chars except for '#' which opens a comment.
  67. * Please note that ' ' (space) while accepted is not a valid key name char.
  68. */
  69. static bool is_nvram_char(char c)
  70. {
  71. /* comment marker excluded */
  72. if (c == '#')
  73. return false;
  74. /* key and value may have any other readable character */
  75. return (c >= 0x20 && c < 0x7f);
  76. }
  77. static bool is_whitespace(char c)
  78. {
  79. return (c == ' ' || c == '\r' || c == '\n' || c == '\t');
  80. }
  81. static enum nvram_parser_state brcmf_nvram_handle_idle(struct nvram_parser *nvp)
  82. {
  83. char c;
  84. c = nvp->data[nvp->pos];
  85. if (c == '\n')
  86. return COMMENT;
  87. if (is_whitespace(c))
  88. goto proceed;
  89. if (c == '#')
  90. return COMMENT;
  91. if (is_nvram_char(c)) {
  92. nvp->entry = nvp->pos;
  93. return KEY;
  94. }
  95. brcmf_dbg(INFO, "warning: ln=%d:col=%d: ignoring invalid character\n",
  96. nvp->line, nvp->column);
  97. proceed:
  98. nvp->column++;
  99. nvp->pos++;
  100. return IDLE;
  101. }
  102. static enum nvram_parser_state brcmf_nvram_handle_key(struct nvram_parser *nvp)
  103. {
  104. enum nvram_parser_state st = nvp->state;
  105. char c;
  106. c = nvp->data[nvp->pos];
  107. if (c == '=') {
  108. /* ignore RAW1 by treating as comment */
  109. if (strncmp(&nvp->data[nvp->entry], "RAW1", 4) == 0)
  110. st = COMMENT;
  111. else
  112. st = VALUE;
  113. if (strncmp(&nvp->data[nvp->entry], "devpath", 7) == 0)
  114. nvp->multi_dev_v1 = true;
  115. if (strncmp(&nvp->data[nvp->entry], "pcie/", 5) == 0)
  116. nvp->multi_dev_v2 = true;
  117. } else if (!is_nvram_char(c) || c == ' ') {
  118. brcmf_dbg(INFO, "warning: ln=%d:col=%d: '=' expected, skip invalid key entry\n",
  119. nvp->line, nvp->column);
  120. return COMMENT;
  121. }
  122. nvp->column++;
  123. nvp->pos++;
  124. return st;
  125. }
  126. static enum nvram_parser_state
  127. brcmf_nvram_handle_value(struct nvram_parser *nvp)
  128. {
  129. char c;
  130. char *skv;
  131. char *ekv;
  132. u32 cplen;
  133. c = nvp->data[nvp->pos];
  134. if (!is_nvram_char(c)) {
  135. /* key,value pair complete */
  136. ekv = (u8 *)&nvp->data[nvp->pos];
  137. skv = (u8 *)&nvp->data[nvp->entry];
  138. cplen = ekv - skv;
  139. if (nvp->nvram_len + cplen + 1 >= BRCMF_FW_MAX_NVRAM_SIZE)
  140. return END;
  141. /* copy to output buffer */
  142. memcpy(&nvp->nvram[nvp->nvram_len], skv, cplen);
  143. nvp->nvram_len += cplen;
  144. nvp->nvram[nvp->nvram_len] = '\0';
  145. nvp->nvram_len++;
  146. return IDLE;
  147. }
  148. nvp->pos++;
  149. nvp->column++;
  150. return VALUE;
  151. }
  152. static enum nvram_parser_state
  153. brcmf_nvram_handle_comment(struct nvram_parser *nvp)
  154. {
  155. char *eoc, *sol;
  156. sol = (char *)&nvp->data[nvp->pos];
  157. eoc = strchr(sol, '\n');
  158. if (!eoc) {
  159. eoc = strchr(sol, '\0');
  160. if (!eoc)
  161. return END;
  162. }
  163. /* eat all moving to next line */
  164. nvp->line++;
  165. nvp->column = 1;
  166. nvp->pos += (eoc - sol) + 1;
  167. return IDLE;
  168. }
  169. static enum nvram_parser_state brcmf_nvram_handle_end(struct nvram_parser *nvp)
  170. {
  171. /* final state */
  172. return END;
  173. }
  174. static enum nvram_parser_state
  175. (*nv_parser_states[])(struct nvram_parser *nvp) = {
  176. brcmf_nvram_handle_idle,
  177. brcmf_nvram_handle_key,
  178. brcmf_nvram_handle_value,
  179. brcmf_nvram_handle_comment,
  180. brcmf_nvram_handle_end
  181. };
  182. static int brcmf_init_nvram_parser(struct nvram_parser *nvp,
  183. const u8 *data, size_t data_len)
  184. {
  185. size_t size;
  186. memset(nvp, 0, sizeof(*nvp));
  187. nvp->data = data;
  188. /* Limit size to MAX_NVRAM_SIZE, some files contain lot of comment */
  189. if (data_len > BRCMF_FW_MAX_NVRAM_SIZE)
  190. size = BRCMF_FW_MAX_NVRAM_SIZE;
  191. else
  192. size = data_len;
  193. /* Alloc for extra 0 byte + roundup by 4 + length field */
  194. size += 1 + 3 + sizeof(u32);
  195. nvp->nvram = kzalloc(size, GFP_KERNEL);
  196. if (!nvp->nvram)
  197. return -ENOMEM;
  198. nvp->line = 1;
  199. nvp->column = 1;
  200. return 0;
  201. }
  202. /* brcmf_fw_strip_multi_v1 :Some nvram files contain settings for multiple
  203. * devices. Strip it down for one device, use domain_nr/bus_nr to determine
  204. * which data is to be returned. v1 is the version where nvram is stored
  205. * compressed and "devpath" maps to index for valid entries.
  206. */
  207. static void brcmf_fw_strip_multi_v1(struct nvram_parser *nvp, u16 domain_nr,
  208. u16 bus_nr)
  209. {
  210. /* Device path with a leading '=' key-value separator */
  211. char pci_path[] = "=pci/?/?";
  212. size_t pci_len;
  213. char pcie_path[] = "=pcie/?/?";
  214. size_t pcie_len;
  215. u32 i, j;
  216. bool found;
  217. u8 *nvram;
  218. u8 id;
  219. nvram = kzalloc(nvp->nvram_len + 1 + 3 + sizeof(u32), GFP_KERNEL);
  220. if (!nvram)
  221. goto fail;
  222. /* min length: devpath0=pcie/1/4/ + 0:x=y */
  223. if (nvp->nvram_len < BRCMF_FW_NVRAM_DEVPATH_LEN + 6)
  224. goto fail;
  225. /* First search for the devpathX and see if it is the configuration
  226. * for domain_nr/bus_nr. Search complete nvp
  227. */
  228. snprintf(pci_path, sizeof(pci_path), "=pci/%d/%d", domain_nr,
  229. bus_nr);
  230. pci_len = strlen(pci_path);
  231. snprintf(pcie_path, sizeof(pcie_path), "=pcie/%d/%d", domain_nr,
  232. bus_nr);
  233. pcie_len = strlen(pcie_path);
  234. found = false;
  235. i = 0;
  236. while (i < nvp->nvram_len - BRCMF_FW_NVRAM_DEVPATH_LEN) {
  237. /* Format: devpathX=pcie/Y/Z/
  238. * Y = domain_nr, Z = bus_nr, X = virtual ID
  239. */
  240. if (strncmp(&nvp->nvram[i], "devpath", 7) == 0 &&
  241. (!strncmp(&nvp->nvram[i + 8], pci_path, pci_len) ||
  242. !strncmp(&nvp->nvram[i + 8], pcie_path, pcie_len))) {
  243. id = nvp->nvram[i + 7] - '0';
  244. found = true;
  245. break;
  246. }
  247. while (nvp->nvram[i] != 0)
  248. i++;
  249. i++;
  250. }
  251. if (!found)
  252. goto fail;
  253. /* Now copy all valid entries, release old nvram and assign new one */
  254. i = 0;
  255. j = 0;
  256. while (i < nvp->nvram_len) {
  257. if ((nvp->nvram[i] - '0' == id) && (nvp->nvram[i + 1] == ':')) {
  258. i += 2;
  259. while (nvp->nvram[i] != 0) {
  260. nvram[j] = nvp->nvram[i];
  261. i++;
  262. j++;
  263. }
  264. nvram[j] = 0;
  265. j++;
  266. }
  267. while (nvp->nvram[i] != 0)
  268. i++;
  269. i++;
  270. }
  271. kfree(nvp->nvram);
  272. nvp->nvram = nvram;
  273. nvp->nvram_len = j;
  274. return;
  275. fail:
  276. kfree(nvram);
  277. nvp->nvram_len = 0;
  278. }
  279. /* brcmf_fw_strip_multi_v2 :Some nvram files contain settings for multiple
  280. * devices. Strip it down for one device, use domain_nr/bus_nr to determine
  281. * which data is to be returned. v2 is the version where nvram is stored
  282. * uncompressed, all relevant valid entries are identified by
  283. * pcie/domain_nr/bus_nr:
  284. */
  285. static void brcmf_fw_strip_multi_v2(struct nvram_parser *nvp, u16 domain_nr,
  286. u16 bus_nr)
  287. {
  288. char prefix[BRCMF_FW_NVRAM_PCIEDEV_LEN];
  289. size_t len;
  290. u32 i, j;
  291. u8 *nvram;
  292. nvram = kzalloc(nvp->nvram_len + 1 + 3 + sizeof(u32), GFP_KERNEL);
  293. if (!nvram)
  294. goto fail;
  295. /* Copy all valid entries, release old nvram and assign new one.
  296. * Valid entries are of type pcie/X/Y/ where X = domain_nr and
  297. * Y = bus_nr.
  298. */
  299. snprintf(prefix, sizeof(prefix), "pcie/%d/%d/", domain_nr, bus_nr);
  300. len = strlen(prefix);
  301. i = 0;
  302. j = 0;
  303. while (i < nvp->nvram_len - len) {
  304. if (strncmp(&nvp->nvram[i], prefix, len) == 0) {
  305. i += len;
  306. while (nvp->nvram[i] != 0) {
  307. nvram[j] = nvp->nvram[i];
  308. i++;
  309. j++;
  310. }
  311. nvram[j] = 0;
  312. j++;
  313. }
  314. while (nvp->nvram[i] != 0)
  315. i++;
  316. i++;
  317. }
  318. kfree(nvp->nvram);
  319. nvp->nvram = nvram;
  320. nvp->nvram_len = j;
  321. return;
  322. fail:
  323. kfree(nvram);
  324. nvp->nvram_len = 0;
  325. }
  326. /* brcmf_nvram_strip :Takes a buffer of "<var>=<value>\n" lines read from a fil
  327. * and ending in a NUL. Removes carriage returns, empty lines, comment lines,
  328. * and converts newlines to NULs. Shortens buffer as needed and pads with NULs.
  329. * End of buffer is completed with token identifying length of buffer.
  330. */
  331. static void *brcmf_fw_nvram_strip(const u8 *data, size_t data_len,
  332. u32 *new_length, u16 domain_nr, u16 bus_nr)
  333. {
  334. struct nvram_parser nvp;
  335. u32 pad;
  336. u32 token;
  337. __le32 token_le;
  338. if (brcmf_init_nvram_parser(&nvp, data, data_len) < 0)
  339. return NULL;
  340. while (nvp.pos < data_len) {
  341. nvp.state = nv_parser_states[nvp.state](&nvp);
  342. if (nvp.state == END)
  343. break;
  344. }
  345. if (nvp.multi_dev_v1)
  346. brcmf_fw_strip_multi_v1(&nvp, domain_nr, bus_nr);
  347. else if (nvp.multi_dev_v2)
  348. brcmf_fw_strip_multi_v2(&nvp, domain_nr, bus_nr);
  349. if (nvp.nvram_len == 0) {
  350. kfree(nvp.nvram);
  351. return NULL;
  352. }
  353. pad = nvp.nvram_len;
  354. *new_length = roundup(nvp.nvram_len + 1, 4);
  355. while (pad != *new_length) {
  356. nvp.nvram[pad] = 0;
  357. pad++;
  358. }
  359. token = *new_length / 4;
  360. token = (~token << 16) | (token & 0x0000FFFF);
  361. token_le = cpu_to_le32(token);
  362. memcpy(&nvp.nvram[*new_length], &token_le, sizeof(token_le));
  363. *new_length += sizeof(token_le);
  364. return nvp.nvram;
  365. }
  366. void brcmf_fw_nvram_free(void *nvram)
  367. {
  368. kfree(nvram);
  369. }
  370. struct brcmf_fw {
  371. struct device *dev;
  372. u16 flags;
  373. const struct firmware *code;
  374. const char *nvram_name;
  375. u16 domain_nr;
  376. u16 bus_nr;
  377. void (*done)(struct device *dev, const struct firmware *fw,
  378. void *nvram_image, u32 nvram_len);
  379. };
  380. static void brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx)
  381. {
  382. struct brcmf_fw *fwctx = ctx;
  383. u32 nvram_length = 0;
  384. void *nvram = NULL;
  385. u8 *data = NULL;
  386. size_t data_len;
  387. bool raw_nvram;
  388. brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(fwctx->dev));
  389. if (fw && fw->data) {
  390. data = (u8 *)fw->data;
  391. data_len = fw->size;
  392. raw_nvram = false;
  393. } else {
  394. data = bcm47xx_nvram_get_contents(&data_len);
  395. if (!data && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL))
  396. goto fail;
  397. raw_nvram = true;
  398. }
  399. if (data)
  400. nvram = brcmf_fw_nvram_strip(data, data_len, &nvram_length,
  401. fwctx->domain_nr, fwctx->bus_nr);
  402. if (raw_nvram)
  403. bcm47xx_nvram_release_contents(data);
  404. if (fw)
  405. release_firmware(fw);
  406. if (!nvram && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL))
  407. goto fail;
  408. fwctx->done(fwctx->dev, fwctx->code, nvram, nvram_length);
  409. kfree(fwctx);
  410. return;
  411. fail:
  412. brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev));
  413. release_firmware(fwctx->code);
  414. device_release_driver(fwctx->dev);
  415. kfree(fwctx);
  416. }
  417. static void brcmf_fw_request_code_done(const struct firmware *fw, void *ctx)
  418. {
  419. struct brcmf_fw *fwctx = ctx;
  420. int ret;
  421. brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(fwctx->dev));
  422. if (!fw)
  423. goto fail;
  424. /* only requested code so done here */
  425. if (!(fwctx->flags & BRCMF_FW_REQUEST_NVRAM)) {
  426. fwctx->done(fwctx->dev, fw, NULL, 0);
  427. kfree(fwctx);
  428. return;
  429. }
  430. fwctx->code = fw;
  431. ret = request_firmware_nowait(THIS_MODULE, true, fwctx->nvram_name,
  432. fwctx->dev, GFP_KERNEL, fwctx,
  433. brcmf_fw_request_nvram_done);
  434. if (!ret)
  435. return;
  436. brcmf_fw_request_nvram_done(NULL, fwctx);
  437. return;
  438. fail:
  439. brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev));
  440. device_release_driver(fwctx->dev);
  441. kfree(fwctx);
  442. }
  443. int brcmf_fw_get_firmwares_pcie(struct device *dev, u16 flags,
  444. const char *code, const char *nvram,
  445. void (*fw_cb)(struct device *dev,
  446. const struct firmware *fw,
  447. void *nvram_image, u32 nvram_len),
  448. u16 domain_nr, u16 bus_nr)
  449. {
  450. struct brcmf_fw *fwctx;
  451. brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(dev));
  452. if (!fw_cb || !code)
  453. return -EINVAL;
  454. if ((flags & BRCMF_FW_REQUEST_NVRAM) && !nvram)
  455. return -EINVAL;
  456. fwctx = kzalloc(sizeof(*fwctx), GFP_KERNEL);
  457. if (!fwctx)
  458. return -ENOMEM;
  459. fwctx->dev = dev;
  460. fwctx->flags = flags;
  461. fwctx->done = fw_cb;
  462. if (flags & BRCMF_FW_REQUEST_NVRAM)
  463. fwctx->nvram_name = nvram;
  464. fwctx->domain_nr = domain_nr;
  465. fwctx->bus_nr = bus_nr;
  466. return request_firmware_nowait(THIS_MODULE, true, code, dev,
  467. GFP_KERNEL, fwctx,
  468. brcmf_fw_request_code_done);
  469. }
  470. int brcmf_fw_get_firmwares(struct device *dev, u16 flags,
  471. const char *code, const char *nvram,
  472. void (*fw_cb)(struct device *dev,
  473. const struct firmware *fw,
  474. void *nvram_image, u32 nvram_len))
  475. {
  476. return brcmf_fw_get_firmwares_pcie(dev, flags, code, nvram, fw_cb, 0,
  477. 0);
  478. }