2 * SPDX-FileCopyrightText: 2016 Cesanta Software Limited
4 * SPDX-License-Identifier: GPL-2.0-or-later
6 * SPDX-FileContributor: 2016-2022 Espressif Systems (Shanghai) CO LTD
9 #if defined(PLATFORM_ESP32) && defined(TARGET_RX)
11 #include "stub_write_flash.h"
12 #include "rom/miniz.h"
14 #include "soc_support.h"
15 #include "stub_flasher.h"
20 /* local flashing state
22 This is wrapped in a structure because gcc 4.8
23 generates significantly more code for ESP32
24 if they are static variables (literal pool, I think!)
28 /* set by flash_begin, cleared by flash_end */
30 /* number of output bytes remaining to write */
32 /* last error generated by a data packet */
33 esp_command_error last_error
;
40 /* inflator state for deflate write */
41 tinfl_decompressor inflator
;
42 /* number of compressed bytes remaining to read */
43 uint32_t remaining_compressed
;
46 bool is_in_flash_mode(void)
48 return fs
.in_flash_mode
;
51 esp_command_error
get_flash_error(void)
56 esp_command_error
handle_flash_get_md5sum(uint32_t addr
, uint32_t len
)
58 /* ESP32 ROM sends as hex, but stub just send raw bytes - esptool.py can handle either. */
59 fs
.md5
.add(fs
.last_buf
, len
- fs
.last_end
);
63 SLIP_send_frame_data_buf(md5
, sizeof(md5
));
67 esp_command_error
handle_flash_begin(uint32_t total_size
, uint32_t offset
)
69 fs
.in_flash_mode
= true;
70 fs
.remaining
= total_size
;
73 Update
.begin(total_size
);
74 fs
.last_buf
= static_cast<uint8_t *>(malloc(32768));
82 esp_command_error
handle_flash_deflated_begin(uint32_t uncompressed_size
, uint32_t compressed_size
, uint32_t offset
)
84 esp_command_error err
= handle_flash_begin(uncompressed_size
, offset
);
85 tinfl_init(&fs
.inflator
);
86 fs
.remaining_compressed
= compressed_size
;
90 void handle_flash_data(uint8_t *data_buf
, uint32_t length
)
94 fs
.md5
.add(fs
.last_buf
, fs
.last_length
);
95 fs
.last_end
+= fs
.last_length
;
97 if (length
> fs
.remaining
)
99 /* Trim the final block, as it may have padding beyond
100 the length we are writing */
101 length
= fs
.remaining
;
103 memcpy(fs
.last_buf
, data_buf
, length
);
104 fs
.last_length
= length
;
105 fs
.remaining
-= length
;
106 Update
.write(data_buf
, length
);
108 fs
.last_error
= ESP_UPDATE_OK
;
111 void handle_flash_deflated_data(uint8_t *data_buf
, uint32_t length
)
113 static uint8_t *out_buf
= nullptr;
114 static uint8_t *next_out
= nullptr;
115 int status
= TINFL_STATUS_NEEDS_MORE_INPUT
;
117 const size_t out_size
= 32768;
118 if (out_buf
== nullptr)
120 out_buf
= static_cast<uint8_t *>(malloc(out_size
));
123 while (length
> 0 && fs
.remaining
> 0 && status
> TINFL_STATUS_DONE
)
125 size_t in_bytes
= length
; /* input remaining */
126 size_t out_bytes
= out_buf
+ out_size
- next_out
; /* output space remaining */
127 int flags
= TINFL_FLAG_PARSE_ZLIB_HEADER
;
128 if (fs
.remaining_compressed
> length
)
130 flags
|= TINFL_FLAG_HAS_MORE_INPUT
;
133 status
= tinfl_decompress(&fs
.inflator
, data_buf
, &in_bytes
, out_buf
, next_out
, &out_bytes
, flags
);
135 fs
.remaining_compressed
-= in_bytes
;
137 data_buf
+= in_bytes
;
139 next_out
+= out_bytes
;
140 size_t bytes_in_out_buf
= next_out
- out_buf
;
141 if (status
== TINFL_STATUS_DONE
|| bytes_in_out_buf
== out_size
)
143 // Output buffer full, or done
144 handle_flash_data(out_buf
, bytes_in_out_buf
);
149 if (status
< TINFL_STATUS_DONE
)
151 /* error won't get sent back to esptool.py until next block is sent */
152 fs
.last_error
= ESP_INFLATE_ERROR
;
155 if (status
== TINFL_STATUS_DONE
&& fs
.remaining
> 0)
157 fs
.last_error
= ESP_NOT_ENOUGH_DATA
;
159 if (status
!= TINFL_STATUS_DONE
&& fs
.remaining
== 0)
161 fs
.last_error
= ESP_TOO_MUCH_DATA
;
165 esp_command_error
handle_flash_end(void)
167 if (!fs
.in_flash_mode
)
169 return ESP_NOT_IN_FLASH_MODE
;
172 if (fs
.remaining
> 0)
174 return ESP_NOT_ENOUGH_DATA
;
177 fs
.in_flash_mode
= false;
179 if (!Update
.end(true))
181 switch (Update
.getError())
183 case UPDATE_ERROR_SPACE
:
184 return ESP_TOO_MUCH_DATA
;
185 case UPDATE_ERROR_SIZE
:
186 return ESP_NOT_ENOUGH_DATA
;
187 case UPDATE_ERROR_MD5
:
188 return ESP_BAD_DATA_CHECKSUM
;
190 return ESP_INVALID_COMMAND
;
193 return fs
.last_error
;