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. uint32_t encryption_size = encryption ? sizeof(uint32_t) : 0;
  52. flash_begin_command_t flash_begin_cmd = {
  53. .common = {
  54. .direction = WRITE_DIRECTION,
  55. .command = FLASH_BEGIN,
  56. .size = CMD_SIZE(flash_begin_cmd) - encryption_size,
  57. .checksum = 0
  58. },
  59. .erase_size = erase_size,
  60. .packet_count = blocks_to_write,
  61. .packet_size = block_size,
  62. .offset = offset,
  63. .encrypted = 0
  64. };
  65. s_sequence_number = 0;
  66. return send_cmd(&flash_begin_cmd, sizeof(flash_begin_cmd) - encryption_size, NULL);
  67. }
  68. esp_loader_error_t loader_flash_data_cmd(const uint8_t *data, uint32_t size)
  69. {
  70. data_command_t data_cmd = {
  71. .common = {
  72. .direction = WRITE_DIRECTION,
  73. .command = FLASH_DATA,
  74. .size = CMD_SIZE(data_cmd) + size,
  75. .checksum = compute_checksum(data, size)
  76. },
  77. .data_size = size,
  78. .sequence_number = s_sequence_number++,
  79. };
  80. return send_cmd_with_data(&data_cmd, sizeof(data_cmd), data, size);
  81. }
  82. esp_loader_error_t loader_flash_end_cmd(bool stay_in_loader)
  83. {
  84. flash_end_command_t end_cmd = {
  85. .common = {
  86. .direction = WRITE_DIRECTION,
  87. .command = FLASH_END,
  88. .size = CMD_SIZE(end_cmd),
  89. .checksum = 0
  90. },
  91. .stay_in_loader = stay_in_loader
  92. };
  93. return send_cmd(&end_cmd, sizeof(end_cmd), NULL);
  94. }
  95. esp_loader_error_t loader_mem_begin_cmd(uint32_t offset, uint32_t size, uint32_t blocks_to_write, uint32_t block_size)
  96. {
  97. mem_begin_command_t mem_begin_cmd = {
  98. .common = {
  99. .direction = WRITE_DIRECTION,
  100. .command = MEM_BEGIN,
  101. .size = CMD_SIZE(mem_begin_cmd),
  102. .checksum = 0
  103. },
  104. .total_size = size,
  105. .blocks = blocks_to_write,
  106. .block_size = block_size,
  107. .offset = offset
  108. };
  109. s_sequence_number = 0;
  110. return send_cmd(&mem_begin_cmd, sizeof(mem_begin_cmd), NULL);
  111. }
  112. esp_loader_error_t loader_mem_data_cmd(const uint8_t *data, uint32_t size)
  113. {
  114. data_command_t data_cmd = {
  115. .common = {
  116. .direction = WRITE_DIRECTION,
  117. .command = MEM_DATA,
  118. .size = CMD_SIZE(data_cmd) + size,
  119. .checksum = compute_checksum(data, size)
  120. },
  121. .data_size = size,
  122. .sequence_number = s_sequence_number++,
  123. };
  124. return send_cmd_with_data(&data_cmd, sizeof(data_cmd), data, size);
  125. }
  126. esp_loader_error_t loader_mem_end_cmd(uint32_t entrypoint)
  127. {
  128. mem_end_command_t end_cmd = {
  129. .common = {
  130. .direction = WRITE_DIRECTION,
  131. .command = MEM_END,
  132. .size = CMD_SIZE(end_cmd),
  133. },
  134. .stay_in_loader = (entrypoint == 0),
  135. .entry_point_address = entrypoint
  136. };
  137. return send_cmd(&end_cmd, sizeof(end_cmd), NULL);
  138. }
  139. esp_loader_error_t loader_sync_cmd(void)
  140. {
  141. sync_command_t sync_cmd = {
  142. .common = {
  143. .direction = WRITE_DIRECTION,
  144. .command = SYNC,
  145. .size = CMD_SIZE(sync_cmd),
  146. .checksum = 0
  147. },
  148. .sync_sequence = {
  149. 0x07, 0x07, 0x12, 0x20,
  150. 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
  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. }
  155. };
  156. return send_cmd(&sync_cmd, sizeof(sync_cmd), NULL);
  157. }
  158. esp_loader_error_t loader_write_reg_cmd(uint32_t address, uint32_t value,
  159. uint32_t mask, uint32_t delay_us)
  160. {
  161. write_reg_command_t write_cmd = {
  162. .common = {
  163. .direction = WRITE_DIRECTION,
  164. .command = WRITE_REG,
  165. .size = CMD_SIZE(write_cmd),
  166. .checksum = 0
  167. },
  168. .address = address,
  169. .value = value,
  170. .mask = mask,
  171. .delay_us = delay_us
  172. };
  173. return send_cmd(&write_cmd, sizeof(write_cmd), NULL);
  174. }
  175. esp_loader_error_t loader_read_reg_cmd(uint32_t address, uint32_t *reg)
  176. {
  177. read_reg_command_t read_cmd = {
  178. .common = {
  179. .direction = WRITE_DIRECTION,
  180. .command = READ_REG,
  181. .size = CMD_SIZE(read_cmd),
  182. .checksum = 0
  183. },
  184. .address = address,
  185. };
  186. return send_cmd(&read_cmd, sizeof(read_cmd), reg);
  187. }
  188. esp_loader_error_t loader_spi_attach_cmd(uint32_t config)
  189. {
  190. spi_attach_command_t attach_cmd = {
  191. .common = {
  192. .direction = WRITE_DIRECTION,
  193. .command = SPI_ATTACH,
  194. .size = CMD_SIZE(attach_cmd),
  195. .checksum = 0
  196. },
  197. .configuration = config,
  198. .zero = 0
  199. };
  200. return send_cmd(&attach_cmd, sizeof(attach_cmd), NULL);
  201. }
  202. esp_loader_error_t loader_change_baudrate_cmd(uint32_t baudrate)
  203. {
  204. change_baudrate_command_t baudrate_cmd = {
  205. .common = {
  206. .direction = WRITE_DIRECTION,
  207. .command = CHANGE_BAUDRATE,
  208. .size = CMD_SIZE(baudrate_cmd),
  209. .checksum = 0
  210. },
  211. .new_baudrate = baudrate,
  212. .old_baudrate = 0 // ESP32 ROM only
  213. };
  214. return send_cmd(&baudrate_cmd, sizeof(baudrate_cmd), NULL);
  215. }
  216. esp_loader_error_t loader_md5_cmd(uint32_t address, uint32_t size, uint8_t *md5_out)
  217. {
  218. spi_flash_md5_command_t md5_cmd = {
  219. .common = {
  220. .direction = WRITE_DIRECTION,
  221. .command = SPI_FLASH_MD5,
  222. .size = CMD_SIZE(md5_cmd),
  223. .checksum = 0
  224. },
  225. .address = address,
  226. .size = size,
  227. .reserved_0 = 0,
  228. .reserved_1 = 0
  229. };
  230. return send_cmd_md5(&md5_cmd, sizeof(md5_cmd), md5_out);
  231. }
  232. esp_loader_error_t loader_spi_parameters(uint32_t total_size)
  233. {
  234. write_spi_command_t spi_cmd = {
  235. .common = {
  236. .direction = WRITE_DIRECTION,
  237. .command = SPI_SET_PARAMS,
  238. .size = 24,
  239. .checksum = 0
  240. },
  241. .id = 0,
  242. .total_size = total_size,
  243. .block_size = 64 * 1024,
  244. .sector_size = 4 * 1024,
  245. .page_size = 0x100,
  246. .status_mask = 0xFFFF,
  247. };
  248. return send_cmd(&spi_cmd, sizeof(spi_cmd), NULL);
  249. }
  250. __attribute__ ((weak)) void loader_port_debug_print(const char *str)
  251. {
  252. (void)(str);
  253. }