ReadFlashParameters.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. /*====================================================================*
  2. *
  3. * Copyright (c) 2013 Qualcomm Atheros, Inc.
  4. *
  5. * All rights reserved.
  6. *
  7. *====================================================================*/
  8. /*====================================================================*
  9. *
  10. * signed ReadFlashParameters (struct plc *plc);
  11. *
  12. * nda.h
  13. *
  14. * Read PIB Image from flash memory using as many VS_RD_BLK_NVM
  15. * messages as needed; Write image blocks to file as they are
  16. * read;
  17. *
  18. * the objective here is to read the PIB module in 1024 byte blocks
  19. * until the module offset equals or exceeds the PIB length; we do
  20. * not know the PIB length until we have read the header contained
  21. * in the first block read from OFFSET 0;
  22. *
  23. * MOFFSET and MLENGTH fields occupy different offsets in REQ and CNF
  24. * messages; we exploit that by initializing them using CNF message
  25. * offsets then copying values into REQ message offsets before each
  26. * read; this works because confirmation messages always return all
  27. * the data we request or nothing at all;
  28. *
  29. * See the Atheros HomePlug AV Firmware Technical Reference Manual
  30. * for more information;
  31. *
  32. * Contributor(s):
  33. * Charles Maier <cmaier@qca.qualcomm.com>
  34. *
  35. *--------------------------------------------------------------------*/
  36. #ifndef READFLASHPARAMETERS_SOURCE
  37. #define READFLASHPARAMETERS_SOURCE
  38. #include <stdint.h>
  39. #include <unistd.h>
  40. #include <memory.h>
  41. #include "../tools/error.h"
  42. #include "../tools/files.h"
  43. #include "../pib/pib.h"
  44. #include "../plc/plc.h"
  45. #include "../nda/nda.h"
  46. signed ReadFlashParameters (struct plc * plc)
  47. {
  48. struct channel * channel = (struct channel *) (plc->channel);
  49. struct message * message = (struct message *) (plc->message);
  50. #ifndef __GNUC__
  51. #pragma pack (push,1)
  52. #endif
  53. struct __packed vs_rd_mod_request
  54. {
  55. struct ethernet_hdr ethernet;
  56. struct qualcomm_hdr qualcomm;
  57. uint16_t MODULEID;
  58. uint32_t MOFFSET;
  59. uint32_t MLENGTH;
  60. }
  61. * request = (struct vs_rd_mod_request *) (message);
  62. struct __packed vs_rd_mod_confirm
  63. {
  64. struct ethernet_hdr ethernet;
  65. struct qualcomm_hdr qualcomm;
  66. uint8_t MSTATUS;
  67. uint16_t MODULEID;
  68. uint32_t MOFFSET;
  69. uint32_t MLENGTH;
  70. uint8_t BUFFER [PLC_RECORD_SIZE];
  71. }
  72. * confirm = (struct vs_rd_mod_confirm *) (message);
  73. #ifndef __GNUC__
  74. #pragma pack (pop)
  75. #endif
  76. uint32_t extent = 0;
  77. uint32_t offset = 0;
  78. uint32_t length = PLC_RECORD_SIZE;
  79. Request (plc, "Read Parameters from Flash");
  80. if (lseek (plc->pib.file, 0, SEEK_SET))
  81. {
  82. error (PLC_EXIT (plc), errno, FILE_CANTHOME, plc->pib.name);
  83. return (1);
  84. }
  85. do
  86. {
  87. memset (message, 0, sizeof (* message));
  88. EthernetHeader (& request->ethernet, channel->peer, channel->host, channel->type);
  89. QualcommHeader (& request->qualcomm, 0, (VS_RD_BLK_NVM | MMTYPE_REQ));
  90. plc->packetsize = (ETHER_MIN_LEN - ETHER_CRC_LEN);
  91. request->MODULEID = HTOLE16 (MID_USERPIB);
  92. request->MLENGTH = HTOLE32 (length);
  93. request->MOFFSET = HTOLE32 (offset);
  94. if (SendMME (plc) <= 0)
  95. {
  96. error (PLC_EXIT (plc), ECANCELED, CHANNEL_CANTSEND);
  97. return (-1);
  98. }
  99. if (ReadMME (plc, 0, (VS_RD_BLK_NVM | MMTYPE_CNF)) <= 0)
  100. {
  101. error (PLC_EXIT (plc), ECANCELED, CHANNEL_CANTREAD);
  102. return (-1);
  103. }
  104. if (confirm->MSTATUS)
  105. {
  106. Failure (plc, PLC_WONTDOIT);
  107. return (-1);
  108. }
  109. #if 1
  110. if (LE32TOH (confirm->MOFFSET) != offset)
  111. {
  112. Failure (plc, PLC_ERR_OFFSET);
  113. return (-1);
  114. }
  115. if (LE32TOH (confirm->MLENGTH) != length)
  116. {
  117. Failure (plc, PLC_ERR_LENGTH);
  118. return (-1);
  119. }
  120. #else
  121. if (LE32TOH (confirm->MOFFSET) != offset)
  122. {
  123. error (PLC_EXIT (plc), 0, PLC_ERR_OFFSET);
  124. length = PLC_RECORD_SIZE;
  125. offset = 0;
  126. continue;
  127. }
  128. if (LE32TOH (confirm->MLENGTH) != length)
  129. {
  130. error (PLC_EXIT (plc), 0, PLC_ERR_LENGTH);
  131. length = PLC_RECORD_SIZE;
  132. offset = 0;
  133. continue;
  134. }
  135. #endif
  136. offset = LE32TOH (confirm->MOFFSET);
  137. length = LE32TOH (confirm->MLENGTH);
  138. if (offset == extent)
  139. {
  140. struct pib_header * pib_header = (struct pib_header *) (confirm->BUFFER);
  141. extent = LE16TOH (pib_header->PIBLENGTH);
  142. }
  143. if ((offset + length) > extent)
  144. {
  145. length = extent - offset;
  146. }
  147. if (lseek (plc->pib.file, offset, SEEK_SET) != (signed) (offset))
  148. {
  149. error (PLC_EXIT (plc), errno, "can't seek %s", plc->pib.name);
  150. return (-1);
  151. }
  152. if (write (plc->pib.file, confirm->BUFFER, length) < (signed) (length))
  153. {
  154. error (PLC_EXIT (plc), errno, "can't save %s", plc->pib.name);
  155. return (-1);
  156. }
  157. offset += length;
  158. }
  159. while (offset < extent);
  160. return (0);
  161. }
  162. #endif