protocol_common.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. /* Copyright 2020-2023 Espressif Systems (Shanghai) CO LTD
  2. *
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. #include "protocol.h"
  16. #include "protocol_prv.h"
  17. #include "esp_loader_io.h"
  18. #include <stddef.h>
  19. #include <string.h>
  20. #define CMD_SIZE(cmd) ( sizeof(cmd) - sizeof(command_common_t) )
  21. static uint32_t s_sequence_number = 0;
  22. static uint8_t compute_checksum(const uint8_t *data, uint32_t size)
  23. {
  24. uint8_t checksum = 0xEF;
  25. while (size--) {
  26. checksum ^= *data++;
  27. }
  28. return checksum;
  29. }
  30. void log_loader_internal_error(error_code_t error)
  31. {
  32. loader_port_debug_print("Error: ");
  33. switch (error) {
  34. case INVALID_CRC: loader_port_debug_print("INVALID_CRC"); break;
  35. case INVALID_COMMAND: loader_port_debug_print("INVALID_COMMAND"); break;
  36. case COMMAND_FAILED: loader_port_debug_print("COMMAND_FAILED"); break;
  37. case FLASH_WRITE_ERR: loader_port_debug_print("FLASH_WRITE_ERR"); break;
  38. case FLASH_READ_ERR: loader_port_debug_print("FLASH_READ_ERR"); break;
  39. case READ_LENGTH_ERR: loader_port_debug_print("READ_LENGTH_ERR"); break;
  40. case DEFLATE_ERROR: loader_port_debug_print("DEFLATE_ERROR"); break;
  41. default: loader_port_debug_print("UNKNOWN ERROR"); break;
  42. }
  43. loader_port_debug_print("\n");
  44. }
  45. esp_loader_error_t loader_flash_begin_cmd(uint32_t offset,
  46. uint32_t erase_size,
  47. uint32_t block_size,
  48. uint32_t blocks_to_write,
  49. bool encryption)
  50. {
  51. flash_begin_command_t flash_begin_cmd = {
  52. .common = {
  53. .direction = WRITE_DIRECTION,
  54. .command = FLASH_BEGIN,
  55. .size = CMD_SIZE(flash_begin_cmd) - (encryption ? 0 : sizeof(uint32_t)),
  56. .checksum = 0
  57. },
  58. .erase_size = erase_size,
  59. .packet_count = blocks_to_write,
  60. .packet_size = block_size,
  61. .offset = offset,
  62. .encrypted = 0
  63. };
  64. s_sequence_number = 0;
  65. return send_cmd(&flash_begin_cmd,
  66. sizeof(flash_begin_cmd) - (encryption ? 0 : sizeof(uint32_t)),
  67. NULL);
  68. }
  69. esp_loader_error_t loader_flash_data_cmd(const uint8_t *data, uint32_t size)
  70. {
  71. data_command_t data_cmd = {
  72. .common = {
  73. .direction = WRITE_DIRECTION,
  74. .command = FLASH_DATA,
  75. .size = CMD_SIZE(data_cmd) + size,
  76. .checksum = compute_checksum(data, size)
  77. },
  78. .data_size = size,
  79. .sequence_number = s_sequence_number++,
  80. };
  81. return send_cmd_with_data(&data_cmd, sizeof(data_cmd), data, size);
  82. }
  83. esp_loader_error_t loader_flash_end_cmd(bool stay_in_loader)
  84. {
  85. flash_end_command_t end_cmd = {
  86. .common = {
  87. .direction = WRITE_DIRECTION,
  88. .command = FLASH_END,
  89. .size = CMD_SIZE(end_cmd),
  90. .checksum = 0
  91. },
  92. .stay_in_loader = stay_in_loader
  93. };
  94. return send_cmd(&end_cmd, sizeof(end_cmd), NULL);
  95. }
  96. esp_loader_error_t loader_mem_begin_cmd(uint32_t offset, uint32_t size, uint32_t blocks_to_write, uint32_t block_size)
  97. {
  98. mem_begin_command_t mem_begin_cmd = {
  99. .common = {
  100. .direction = WRITE_DIRECTION,
  101. .command = MEM_BEGIN,
  102. .size = CMD_SIZE(mem_begin_cmd),
  103. .checksum = 0
  104. },
  105. .total_size = size,
  106. .blocks = blocks_to_write,
  107. .block_size = block_size,
  108. .offset = offset
  109. };
  110. s_sequence_number = 0;
  111. return send_cmd(&mem_begin_cmd, sizeof(mem_begin_cmd), NULL);
  112. }
  113. esp_loader_error_t loader_mem_data_cmd(const uint8_t *data, uint32_t size)
  114. {
  115. data_command_t data_cmd = {
  116. .common = {
  117. .direction = WRITE_DIRECTION,
  118. .command = MEM_DATA,
  119. .size = CMD_SIZE(data_cmd) + size,
  120. .checksum = compute_checksum(data, size)
  121. },
  122. .data_size = size,
  123. .sequence_number = s_sequence_number++,
  124. };
  125. return send_cmd_with_data(&data_cmd, sizeof(data_cmd), data, size);
  126. }
  127. esp_loader_error_t loader_mem_end_cmd(uint32_t entrypoint)
  128. {
  129. mem_end_command_t end_cmd = {
  130. .common = {
  131. .direction = WRITE_DIRECTION,
  132. .command = MEM_END,
  133. .size = CMD_SIZE(end_cmd),
  134. },
  135. .stay_in_loader = (entrypoint == 0),
  136. .entry_point_address = entrypoint
  137. };
  138. return send_cmd(&end_cmd, sizeof(end_cmd), NULL);
  139. }
  140. esp_loader_error_t loader_sync_cmd(void)
  141. {
  142. sync_command_t sync_cmd = {
  143. .common = {
  144. .direction = WRITE_DIRECTION,
  145. .command = SYNC,
  146. .size = CMD_SIZE(sync_cmd),
  147. .checksum = 0
  148. },
  149. .sync_sequence = {
  150. 0x07, 0x07, 0x12, 0x20,
  151. 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
  152. 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
  153. 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
  154. 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
  155. }
  156. };
  157. return send_cmd(&sync_cmd, sizeof(sync_cmd), NULL);
  158. }
  159. esp_loader_error_t loader_write_reg_cmd(uint32_t address, uint32_t value,
  160. uint32_t mask, uint32_t delay_us)
  161. {
  162. write_reg_command_t write_cmd = {
  163. .common = {
  164. .direction = WRITE_DIRECTION,
  165. .command = WRITE_REG,
  166. .size = CMD_SIZE(write_cmd),
  167. .checksum = 0
  168. },
  169. .address = address,
  170. .value = value,
  171. .mask = mask,
  172. .delay_us = delay_us
  173. };
  174. return send_cmd(&write_cmd, sizeof(write_cmd), NULL);
  175. }
  176. esp_loader_error_t loader_read_reg_cmd(uint32_t address, uint32_t *reg)
  177. {
  178. read_reg_command_t read_cmd = {
  179. .common = {
  180. .direction = WRITE_DIRECTION,
  181. .command = READ_REG,
  182. .size = CMD_SIZE(read_cmd),
  183. .checksum = 0
  184. },
  185. .address = address,
  186. };
  187. return send_cmd(&read_cmd, sizeof(read_cmd), reg);
  188. }
  189. esp_loader_error_t loader_spi_attach_cmd(uint32_t config)
  190. {
  191. spi_attach_command_t attach_cmd = {
  192. .common = {
  193. .direction = WRITE_DIRECTION,
  194. .command = SPI_ATTACH,
  195. .size = CMD_SIZE(attach_cmd),
  196. .checksum = 0
  197. },
  198. .configuration = config,
  199. .zero = 0
  200. };
  201. return send_cmd(&attach_cmd, sizeof(attach_cmd), NULL);
  202. }
  203. esp_loader_error_t loader_change_baudrate_cmd(uint32_t baudrate)
  204. {
  205. change_baudrate_command_t baudrate_cmd = {
  206. .common = {
  207. .direction = WRITE_DIRECTION,
  208. .command = CHANGE_BAUDRATE,
  209. .size = CMD_SIZE(baudrate_cmd),
  210. .checksum = 0
  211. },
  212. .new_baudrate = baudrate,
  213. .old_baudrate = 0 // ESP32 ROM only
  214. };
  215. return send_cmd(&baudrate_cmd, sizeof(baudrate_cmd), NULL);
  216. }
  217. esp_loader_error_t loader_md5_cmd(uint32_t address, uint32_t size, uint8_t *md5_out)
  218. {
  219. spi_flash_md5_command_t md5_cmd = {
  220. .common = {
  221. .direction = WRITE_DIRECTION,
  222. .command = SPI_FLASH_MD5,
  223. .size = CMD_SIZE(md5_cmd),
  224. .checksum = 0
  225. },
  226. .address = address,
  227. .size = size,
  228. .reserved_0 = 0,
  229. .reserved_1 = 0
  230. };
  231. return send_cmd_md5(&md5_cmd, sizeof(md5_cmd), md5_out);
  232. }
  233. esp_loader_error_t loader_spi_parameters(uint32_t total_size)
  234. {
  235. write_spi_command_t spi_cmd = {
  236. .common = {
  237. .direction = WRITE_DIRECTION,
  238. .command = SPI_SET_PARAMS,
  239. .size = 24,
  240. .checksum = 0
  241. },
  242. .id = 0,
  243. .total_size = total_size,
  244. .block_size = 64 * 1024,
  245. .sector_size = 4 * 1024,
  246. .page_size = 0x100,
  247. .status_mask = 0xFFFF,
  248. };
  249. return send_cmd(&spi_cmd, sizeof(spi_cmd), NULL);
  250. }
  251. __attribute__ ((weak)) void loader_port_debug_print(const char *str)
  252. {
  253. (void) str;
  254. }