WriteExecuteFirmware1.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. /*====================================================================*
  2. *
  3. * Copyright (c) 2013 Qualcomm Atheros, Inc.
  4. *
  5. * All rights reserved.
  6. *
  7. *====================================================================*/
  8. /*====================================================================*
  9. *
  10. * signed WriteExecuteFirmware1 (struct plc * plc, unsigned module, const struct lightning_nvm_header * nvm_header);
  11. *
  12. * plc.h
  13. *
  14. * write firmware image into SDRAM and start execution using the
  15. * VS_WRITE_AND_EXECUTE_APPLET message when the image is legacy
  16. * file format;
  17. *
  18. * the boot loader must be running for this to work since runtime
  19. * firmware ignores VS_WRITE_AND_EXECUTE_APPLET messages;
  20. *
  21. * Contributor(s):
  22. * Charles Maier <cmaier@qca.qualcomm.com>
  23. *
  24. *--------------------------------------------------------------------*/
  25. #ifndef WRITEEXECUTEFIRMWARE1_SOURCE
  26. #define WRITEEXECUTEFIRMWARE1_SOURCE
  27. #include "../tools/files.h"
  28. #include "../tools/error.h"
  29. #include "../plc/plc.h"
  30. signed WriteExecuteFirmware1 (struct plc * plc, unsigned module, const struct lightning_nvm_header * nvm_header)
  31. {
  32. struct channel * channel = (struct channel *) (plc->channel);
  33. struct message * message = (struct message *) (plc->message);
  34. #ifndef __GNUC__
  35. #pragma pack (push,1)
  36. #endif
  37. struct __packed vs_write_execute_request
  38. {
  39. struct ethernet_hdr ethernet;
  40. struct qualcomm_hdr qualcomm;
  41. uint32_t CLIENT_SESSION_ID;
  42. uint32_t SERVER_SESSION_ID;
  43. uint32_t FLAGS;
  44. uint8_t ALLOWED_MEM_TYPES [8];
  45. uint32_t TOTAL_LENGTH;
  46. uint32_t CURR_PART_LENGTH;
  47. uint32_t CURR_PART_OFFSET;
  48. uint32_t START_ADDR;
  49. uint32_t CHECKSUM;
  50. uint8_t RESERVED2 [8];
  51. uint8_t IMAGE [PLC_MODULE_SIZE];
  52. }
  53. * request = (struct vs_write_execute_request *) (message);
  54. struct __packed vs_write_execute_confirm
  55. {
  56. struct ethernet_hdr ethernet;
  57. struct qualcomm_hdr qualcomm;
  58. uint32_t MSTATUS;
  59. uint32_t CLIENT_SESSION_ID;
  60. uint32_t SERVER_SESSION_ID;
  61. uint32_t FLAGS;
  62. uint8_t ALLOWED_MEM_TYPES [8];
  63. uint32_t TOTAL_LENGTH;
  64. uint32_t CURR_PART_LENGTH;
  65. uint32_t CURR_PART_OFFSET;
  66. uint32_t START_ADDR;
  67. uint32_t CHECKSUM;
  68. uint8_t RESERVED2 [8];
  69. uint32_t CURR_PART_ABSOLUTE_ADDR;
  70. uint32_t ABSOLUTE_START_ADDR;
  71. }
  72. * confirm = (struct vs_write_execute_confirm *) (message);
  73. #ifndef __GNUC__
  74. #pragma pack (pop)
  75. #endif
  76. unsigned action = PLC_MODULE_ABSOLUTE;
  77. uint32_t length = PLC_MODULE_SIZE;
  78. uint32_t offset = LE32TOH (nvm_header->IMAGEADDRESS);
  79. uint32_t extent = LE32TOH (nvm_header->IMAGELENGTH);
  80. Request (plc, "Write %s (%d) (%08X:%d)", plc->NVM.name, module, offset, extent);
  81. while (extent)
  82. {
  83. memset (message, 0, sizeof (* message));
  84. EthernetHeader (& request->ethernet, channel->peer, channel->host, channel->type);
  85. QualcommHeader (& request->qualcomm, 0, (VS_WRITE_AND_EXECUTE_APPLET | MMTYPE_REQ));
  86. if (length > extent)
  87. {
  88. if (! (LE32TOH (nvm_header->ENTRYPOINT) % sizeof (nvm_header->ENTRYPOINT)))
  89. {
  90. Request (plc, "Start %s (%d) (%08X)", plc->NVM.name, module, LE32TOH (nvm_header->ENTRYPOINT));
  91. action |= PLC_MODULE_EXECUTE;
  92. }
  93. length = extent;
  94. }
  95. if (read (plc->NVM.file, request->IMAGE, length) != (signed) (length))
  96. {
  97. error (1, errno, FILE_CANTREAD, plc->NVM.name);
  98. }
  99. request->CLIENT_SESSION_ID = HTOLE32 (plc->cookie);
  100. request->SERVER_SESSION_ID = HTOLE32 (0);
  101. request->FLAGS = HTOLE32 (action);
  102. request->ALLOWED_MEM_TYPES [0] = 1;
  103. request->TOTAL_LENGTH = nvm_header->IMAGELENGTH;
  104. request->CURR_PART_LENGTH = HTOLE32 (length);
  105. request->CURR_PART_OFFSET = HTOLE32 (offset);
  106. request->START_ADDR = nvm_header->ENTRYPOINT;
  107. request->CHECKSUM = nvm_header->IMAGECHECKSUM;
  108. plc->packetsize = sizeof (* request);
  109. if (SendMME (plc) <= 0)
  110. {
  111. error (PLC_EXIT (plc), errno, CHANNEL_CANTSEND);
  112. return (-1);
  113. }
  114. if (ReadMME (plc, 0, (VS_WRITE_AND_EXECUTE_APPLET | MMTYPE_CNF)) <= 0)
  115. {
  116. error (PLC_EXIT (plc), errno, CHANNEL_CANTREAD);
  117. return (-1);
  118. }
  119. if (confirm->MSTATUS)
  120. {
  121. Failure (plc, PLC_WONTDOIT);
  122. return (-1);
  123. }
  124. if (LE32TOH (confirm->CURR_PART_LENGTH) != length)
  125. {
  126. error (PLC_EXIT (plc), 0, PLC_ERR_LENGTH);
  127. return (-1);
  128. }
  129. if (LE32TOH (confirm->CURR_PART_OFFSET) != offset)
  130. {
  131. error (PLC_EXIT (plc), 0, PLC_ERR_OFFSET);
  132. return (-1);
  133. }
  134. offset += length;
  135. extent -= length;
  136. }
  137. return (0);
  138. }
  139. #endif