plchost.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582
  1. /*====================================================================*
  2. *
  3. * Copyright (c) 2013 Qualcomm Atheros, Inc.
  4. *
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or
  8. * without modification, are permitted (subject to the limitations
  9. * in the disclaimer below) provided that the following conditions
  10. * are met:
  11. *
  12. * * Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. *
  15. * * Redistributions in binary form must reproduce the above
  16. * copyright notice, this list of conditions and the following
  17. * disclaimer in the documentation and/or other materials
  18. * provided with the distribution.
  19. *
  20. * * Neither the name of Qualcomm Atheros nor the names of
  21. * its contributors may be used to endorse or promote products
  22. * derived from this software without specific prior written
  23. * permission.
  24. *
  25. * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
  26. * GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE
  27. * COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
  28. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  29. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  30. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
  31. * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  32. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  33. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  34. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  35. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  36. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
  37. * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  38. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  39. *
  40. *--------------------------------------------------------------------*/
  41. /*====================================================================*"
  42. *
  43. * plchost.c -
  44. *
  45. *
  46. * Contributor(s):
  47. * Charles Maier
  48. *
  49. *--------------------------------------------------------------------*/
  50. /*====================================================================*"
  51. * system header files;
  52. *--------------------------------------------------------------------*/
  53. #include <unistd.h>
  54. #include <stdlib.h>
  55. #include <limits.h>
  56. #include <string.h>
  57. #include <ctype.h>
  58. #include <memory.h>
  59. #include <signal.h>
  60. #include <errno.h>
  61. #include <sys/socket.h>
  62. /*====================================================================*
  63. * custom header files;
  64. *--------------------------------------------------------------------*/
  65. #include "../ether/channel.h"
  66. #include "../tools/getoptv.h"
  67. #include "../tools/putoptv.h"
  68. #include "../tools/memory.h"
  69. #include "../tools/number.h"
  70. #include "../tools/types.h"
  71. #include "../tools/flags.h"
  72. #include "../tools/files.h"
  73. #include "../tools/error.h"
  74. #include "../ram/nvram.h"
  75. #include "../ram/sdram.h"
  76. #include "../nvm/nvm.h"
  77. #include "../pib/pib.h"
  78. #include "../plc/plc.h"
  79. /*====================================================================*
  80. * custom source files;
  81. *--------------------------------------------------------------------*/
  82. #ifndef MAKEFILE
  83. #include "../plc/BootDevice2.c"
  84. #include "../plc/BootFirmware2.c"
  85. #include "../plc/BootParameters2.c"
  86. #include "../plc/chipset.c"
  87. #include "../plc/Confirm.c"
  88. #include "../plc/Devices.c"
  89. #include "../plc/Failure.c"
  90. #include "../plc/FlashDevice2.c"
  91. #include "../plc/FlashSoftloader.c"
  92. #include "../plc/FlashFirmware.c"
  93. #include "../plc/FlashParameters.c"
  94. #include "../plc/FlashNVM.c"
  95. #include "../plc/HostActionResponse.c"
  96. #include "../plc/InitDevice2.c"
  97. #include "../plc/ModuleRead.c"
  98. #include "../plc/ModuleSpec.c"
  99. #include "../plc/ModuleSession.c"
  100. #include "../plc/ModuleWrite.c"
  101. #include "../plc/ModuleCommit.c"
  102. #include "../plc/LocalDevices.c"
  103. #include "../plc/NVMSelect.c"
  104. #include "../plc/ReadFirmware2.c"
  105. #include "../plc/ReadParameters2.c"
  106. #include "../plc/Request.c"
  107. #include "../plc/ResetDevice.c"
  108. #include "../plc/ReadMME.c"
  109. #include "../plc/SendMME.c"
  110. #include "../plc/WaitForReset.c"
  111. #include "../plc/WaitForStart.c"
  112. #include "../plc/WriteMEM.c"
  113. #include "../plc/WriteNVM.c"
  114. #include "../plc/WritePIB.c"
  115. #include "../plc/WriteExecuteFirmware2.c"
  116. #include "../plc/WriteExecuteParameters2.c"
  117. #include "../plc/WriteExecuteApplet2.c"
  118. #include "../plc/WriteFirmware2.c"
  119. #include "../plc/PLCSelect.c"
  120. #endif
  121. #ifndef MAKEFILE
  122. #include "../tools/getoptv.c"
  123. #include "../tools/putoptv.c"
  124. #include "../tools/version.c"
  125. #include "../tools/uintspec.c"
  126. #include "../tools/checkfilename.c"
  127. #include "../tools/hexdecode.c"
  128. #include "../tools/hexstring.c"
  129. #include "../tools/todigit.c"
  130. #include "../tools/hexdump.c"
  131. #include "../tools/checksum32.c"
  132. #include "../tools/fdchecksum32.c"
  133. #include "../tools/error.c"
  134. #include "../tools/strfbits.c"
  135. #include "../tools/typename.c"
  136. #endif
  137. #ifndef MAKEFILE
  138. #include "../ether/openchannel.c"
  139. #include "../ether/closechannel.c"
  140. #include "../ether/readpacket.c"
  141. #include "../ether/sendpacket.c"
  142. #include "../ether/channel.c"
  143. #endif
  144. #ifndef MAKEFILE
  145. #include "../mme/EthernetHeader.c"
  146. #include "../mme/QualcommHeader.c"
  147. #include "../mme/UnwantedMessage.c"
  148. #include "../mme/MMECode.c"
  149. #ifdef AR7x00
  150. #include "../mme/QualcommHeader1.c"
  151. #endif
  152. #endif
  153. #ifndef MAKEFILE
  154. #include "../key/keys.c"
  155. #endif
  156. #ifndef MAKEFILE
  157. #include "../nvm/nvmfile2.c"
  158. #endif
  159. #ifndef MAKEFILE
  160. #include "../pib/pibfile2.c"
  161. #include "../pib/pibpeek2.c"
  162. #endif
  163. /*====================================================================*
  164. * program constants;
  165. *--------------------------------------------------------------------*/
  166. #define NEWPIB "user.pib"
  167. #define NEWNVM "user.nvm"
  168. /*====================================================================*
  169. *
  170. * signed function (struct plc * plc);
  171. *
  172. * wait indefinitely for VS_HOST_ACTION messages; service the device
  173. * only; it will stop dead - like a bug! - on error;
  174. *
  175. *
  176. * Contributor(s):
  177. * Charles Maier
  178. *
  179. *--------------------------------------------------------------------*/
  180. signed function (struct plc * plc)
  181. {
  182. struct channel * channel = (struct channel *)(plc->channel);
  183. struct message * message = (struct message *)(plc->message);
  184. #ifndef __GNUC__
  185. #pragma pack (push,1)
  186. #endif
  187. struct __packed vs_host_action_ind
  188. {
  189. struct ethernet_hdr ethernet;
  190. struct qualcomm_hdr qualcomm;
  191. uint8_t MACTION;
  192. uint8_t MAJOR_VERSION;
  193. uint8_t MINOR_VERSION;
  194. }
  195. * indicate = (struct vs_host_action_ind *) (message);
  196. #ifndef __GNUC__
  197. #pragma pack (pop)
  198. #endif
  199. char firmware [PLC_VERSION_STRING];
  200. char const * FactoryNVM = plc->NVM.name;
  201. char const * FactoryPIB = plc->PIB.name;
  202. signed status;
  203. while (true)
  204. {
  205. status = ReadMME (plc, 0, (VS_HOST_ACTION | MMTYPE_IND));
  206. if (status < 0)
  207. {
  208. break;
  209. }
  210. if (status > 0)
  211. {
  212. signed action = indicate->MACTION;
  213. memcpy (channel->peer, indicate->ethernet.OSA, sizeof (channel->peer));
  214. if (HostActionResponse (plc))
  215. {
  216. return (-1);
  217. }
  218. if (action == 0x00)
  219. {
  220. if (BootDevice2 (plc))
  221. {
  222. return (-1);
  223. }
  224. if (WaitForStart (plc, firmware, sizeof (firmware)))
  225. {
  226. return (-1);
  227. }
  228. if (_anyset (plc->flags, PLC_FLASH_DEVICE))
  229. {
  230. FlashDevice2 (plc, (PLC_COMMIT_FORCE | PLC_COMMIT_NORESET | PLC_COMMIT_FACTPIB));
  231. }
  232. continue;
  233. }
  234. if (action == 0x01)
  235. {
  236. close (plc->NVM.file);
  237. if (ReadFirmware2 (plc))
  238. {
  239. return (-1);
  240. }
  241. if ((plc->NVM.file = open (plc->NVM.name = plc->nvm.name, O_BINARY|O_RDONLY)) == -1)
  242. {
  243. error (1, errno, "%s", plc->NVM.name);
  244. }
  245. continue;
  246. }
  247. if (action == 0x02)
  248. {
  249. close (plc->PIB.file);
  250. if (ReadParameters2 (plc))
  251. {
  252. return (-1);
  253. }
  254. if ((plc->PIB.file = open (plc->PIB.name = plc->pib.name, O_BINARY|O_RDONLY)) == -1)
  255. {
  256. error (1, errno, "%s", plc->PIB.name);
  257. }
  258. if (ResetDevice (plc))
  259. {
  260. return (-1);
  261. }
  262. continue;
  263. }
  264. if (action == 0x03)
  265. {
  266. close (plc->PIB.file);
  267. if (ReadParameters2 (plc))
  268. {
  269. return (-1);
  270. }
  271. if ((plc->PIB.file = open (plc->PIB.name = plc->pib.name, O_BINARY|O_RDONLY)) == -1)
  272. {
  273. error (1, errno, "%s", plc->PIB.name);
  274. }
  275. close (plc->NVM.file);
  276. if (ReadFirmware2 (plc))
  277. {
  278. return (-1);
  279. }
  280. if ((plc->NVM.file = open (plc->NVM.name = plc->nvm.name, O_BINARY|O_RDONLY)) == -1)
  281. {
  282. error (1, errno, "%s", plc->NVM.name);
  283. }
  284. if (ResetDevice (plc))
  285. {
  286. return (-1);
  287. }
  288. continue;
  289. }
  290. if (action == 0x04)
  291. {
  292. if (InitDevice2 (plc))
  293. {
  294. return (-1);
  295. }
  296. continue;
  297. }
  298. if (action == 0x05)
  299. {
  300. close (plc->NVM.file);
  301. if ((plc->NVM.file = open (plc->NVM.name = FactoryNVM, O_BINARY|O_RDONLY)) == -1)
  302. {
  303. error (1, errno, "%s", plc->NVM.name);
  304. }
  305. close (plc->PIB.file);
  306. if ((plc->PIB.file = open (plc->PIB.name = FactoryPIB, O_BINARY|O_RDONLY)) == -1)
  307. {
  308. error (1, errno, "%s", plc->PIB.name);
  309. }
  310. if (ResetDevice (plc))
  311. {
  312. return (-1);
  313. }
  314. continue;
  315. }
  316. if (action == 0x06)
  317. {
  318. close (plc->PIB.file);
  319. if (ReadParameters2 (plc))
  320. {
  321. return (-1);
  322. }
  323. if ((plc->PIB.file = open (plc->PIB.name = plc->pib.name, O_BINARY|O_RDONLY)) == -1)
  324. {
  325. error (1, errno, "%s", plc->PIB.name);
  326. }
  327. continue;
  328. }
  329. error (0, ENOSYS, "Host Action 0x%02X", action);
  330. }
  331. }
  332. return (0);
  333. }
  334. /*====================================================================*
  335. *
  336. * int main (int argc, char const * argv[]);
  337. *
  338. * parse command line, populate plc structure and perform selected
  339. * operations; show help summary when asked; see getoptv and putoptv
  340. * to understand command line parsing and help summary display; see
  341. * plc.h for the definition of struct plc;
  342. *
  343. *
  344. *--------------------------------------------------------------------*/
  345. int main (int argc, char const * argv [])
  346. {
  347. extern struct channel channel;
  348. extern void terminate (signo_t);
  349. static char const * optv [] =
  350. {
  351. "Fi:n:N:p:P:qS:t:vw:x",
  352. "-N file -P file [-S file]",
  353. "Qualcomm Atheros PLC Host Daemon",
  354. "F [F]\tflash [force] non-volatile memory",
  355. #if defined (WINPCAP) || defined (LIBPCAP)
  356. "i n\thost interface is (n) [" LITERAL (CHANNEL_ETHNUMBER) "]",
  357. #else
  358. "i s\thost interface is (s) [" LITERAL (CHANNEL_ETHDEVICE) "]",
  359. #endif
  360. "n f\tuser firmware file is (f)",
  361. "N f\tfirmware file is (f)",
  362. "p f\tuser parameter file is (f)",
  363. "P f\tparameter file is (f)",
  364. "q\tquiet mode",
  365. "S f\tsoftloader file is (f)",
  366. "t n\tread timeout is (n) milliseconds [" LITERAL (CHANNEL_TIMEOUT) "]",
  367. "v\tverbose mode",
  368. "w n\twakeup every (n) seconds [" LITERAL (PLC_LONGTIME) "]",
  369. "x\texit on error",
  370. (char const *) (0)
  371. };
  372. #include "../plc/plc.c"
  373. signed c;
  374. if (getenv (PLCDEVICE))
  375. {
  376. #if defined (WINPCAP) || defined (LIBPCAP)
  377. channel.ifindex = atoi (getenv (PLCDEVICE));
  378. #else
  379. channel.ifname = strdup (getenv (PLCDEVICE));
  380. #endif
  381. }
  382. optind = 1;
  383. plc.timer = PLC_LONGTIME;
  384. while ((c = getoptv (argc, argv, optv)) != -1)
  385. {
  386. switch (c)
  387. {
  388. case 'd':
  389. _setbits (plc.flags, PLC_DAEMON);
  390. break;
  391. case 'F':
  392. _setbits (plc.module, (VS_MODULE_MAC | VS_MODULE_PIB));
  393. if (_anyset (plc.flags, PLC_FLASH_DEVICE))
  394. {
  395. _setbits (plc.module, VS_MODULE_FORCE);
  396. }
  397. _setbits (plc.flags, PLC_FLASH_DEVICE);
  398. break;
  399. case 'i':
  400. #if defined (WINPCAP) || defined (LIBPCAP)
  401. channel.ifindex = atoi (optarg);
  402. #else
  403. channel.ifname = optarg;
  404. #endif
  405. break;
  406. case 'N':
  407. if (!checkfilename (optarg))
  408. {
  409. error (1, EINVAL, "%s", optarg);
  410. }
  411. if ((plc.NVM.file = open (plc.NVM.name = optarg, O_BINARY|O_RDONLY)) == -1)
  412. {
  413. error (1, errno, "%s", plc.NVM.name);
  414. }
  415. if (nvmfile2 (&plc.NVM))
  416. {
  417. error (1, errno, "Bad firmware file: %s", plc.NVM.name);
  418. }
  419. _setbits (plc.flags, PLC_WRITE_MAC);
  420. break;
  421. case 'n':
  422. if (!checkfilename (optarg))
  423. {
  424. error (1, EINVAL, "%s", optarg);
  425. }
  426. if ((plc.nvm.file = open (plc.nvm.name = optarg, O_BINARY|O_CREAT|O_RDWR|O_TRUNC, FILE_FILEMODE)) == -1)
  427. {
  428. error (1, errno, "%s", plc.nvm.name);
  429. }
  430. break;
  431. case 'P':
  432. if (!checkfilename (optarg))
  433. {
  434. error (1, EINVAL, "%s", optarg);
  435. }
  436. if ((plc.PIB.file = open (plc.PIB.name = optarg, O_BINARY|O_RDONLY)) == -1)
  437. {
  438. error (1, errno, "%s", plc.PIB.name);
  439. }
  440. if (pibfile2 (&plc.PIB))
  441. {
  442. error (1, errno, "Bad parameter file: %s", plc.PIB.name);
  443. }
  444. _setbits (plc.flags, PLC_WRITE_PIB);
  445. break;
  446. case 'p':
  447. if (!checkfilename (optarg))
  448. {
  449. error (1, EINVAL, "%s", optarg);
  450. }
  451. if ((plc.pib.file = open (plc.pib.name = optarg, O_BINARY|O_CREAT|O_RDWR|O_TRUNC, FILE_FILEMODE)) == -1)
  452. {
  453. error (1, errno, "%s", plc.pib.name);
  454. }
  455. break;
  456. case 'q':
  457. _setbits (channel.flags, CHANNEL_SILENCE);
  458. _setbits (plc.flags, PLC_SILENCE);
  459. break;
  460. case 'S':
  461. if (!checkfilename (optarg))
  462. {
  463. error (1, EINVAL, "%s", optarg);
  464. }
  465. if ((plc.SFT.file = open (plc.SFT.name = optarg, O_BINARY|O_RDONLY)) == -1)
  466. {
  467. error (1, errno, "%s", plc.SFT.name);
  468. }
  469. if (nvmfile2 (&plc.SFT))
  470. {
  471. error (1, errno, "Bad firmware file: %s", plc.SFT.name);
  472. }
  473. break;
  474. case 't':
  475. channel.timeout = (signed)(uintspec (optarg, 0, UINT_MAX));
  476. break;
  477. case 'v':
  478. _setbits (channel.flags, CHANNEL_VERBOSE);
  479. _setbits (plc.flags, PLC_VERBOSE);
  480. break;
  481. case 'w':
  482. plc.timer = (unsigned)(uintspec (optarg, 1, 3600));
  483. break;
  484. case 'x':
  485. _setbits (plc.flags, PLC_BAILOUT);
  486. break;
  487. default:
  488. break;
  489. }
  490. }
  491. argc -= optind;
  492. argv += optind;
  493. if (argc)
  494. {
  495. error (1, ENOTSUP, ERROR_TOOMANY);
  496. }
  497. if (plc.NVM.file == -1)
  498. {
  499. error (1, ECANCELED, "No host NVM file named");
  500. }
  501. if (plc.PIB.file == -1)
  502. {
  503. error (1, ECANCELED, "No host PIB file named");
  504. }
  505. if (plc.SFT.file == -1)
  506. {
  507. if (_anyset (plc.flags, PLC_FLASH_DEVICE))
  508. {
  509. error (1, ECANCELED, "No Softloader file named");
  510. }
  511. }
  512. if (plc.nvm.file == -1)
  513. {
  514. if ((plc.nvm.file = open (plc.nvm.name = NEWNVM, O_BINARY|O_CREAT|O_RDWR|O_TRUNC, FILE_FILEMODE)) == -1)
  515. {
  516. error (1, errno, "%s", plc.nvm.name);
  517. }
  518. }
  519. if (plc.pib.file == -1)
  520. {
  521. if ((plc.pib.file = open (plc.pib.name = NEWPIB, O_BINARY|O_CREAT|O_RDWR|O_TRUNC, FILE_FILEMODE)) == -1)
  522. {
  523. error (1, errno, "%s", plc.pib.name);
  524. }
  525. }
  526. openchannel (&channel);
  527. if (!(plc.message = malloc (sizeof (* plc.message))))
  528. {
  529. error (1, errno, PLC_NOMEMORY);
  530. }
  531. function (&plc);
  532. free (plc.message);
  533. closechannel (&channel);
  534. exit (0);
  535. }