Skip to content

Commit 5902f00

Browse files
sylvioalvesfabiobaltieri
authored andcommitted
driver: flash: esp32: fix unaligned read
Fix flash read operation to account for all unaligned scenarios, i.e, address, buffer and length. This is needed when using flash APIs provided in ROM. This also removes the unaligned flash write call as it expects aligned values only. Signed-off-by: Sylvio Alves <sylvio.alves@espressif.com>
1 parent 904ec02 commit 5902f00

File tree

1 file changed

+59
-26
lines changed

1 file changed

+59
-26
lines changed

drivers/flash/flash_esp32.c

Lines changed: 59 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -76,26 +76,67 @@ static inline void flash_esp32_sem_give(const struct device *dev)
7676
#include <stdint.h>
7777
#include <string.h>
7878

79+
#ifdef CONFIG_MCUBOOT
80+
#define READ_BUFFER_SIZE 32
81+
static bool flash_esp32_is_aligned(off_t address, void *buffer, size_t length)
82+
{
83+
/* check if address, buffer pointer, and length are 4-byte aligned */
84+
return ((address & 3) == 0) && (((uintptr_t)buffer & 3) == 0) && ((length & 3) == 0);
85+
}
86+
#endif
87+
7988
static int flash_esp32_read(const struct device *dev, off_t address, void *buffer, size_t length)
8089
{
8190
int ret = 0;
8291

8392
#ifdef CONFIG_MCUBOOT
84-
/* ensure everything is 4-byte aligned */
85-
size_t aligned_length = ROUND_UP(length, 4);
86-
off_t aligned_address = ROUND_DOWN(address, 4);
87-
size_t address_offset = address - aligned_address;
88-
uint32_t temp_buf[aligned_length / 4];
89-
90-
if (!esp_flash_encryption_enabled()) {
91-
ret = esp_rom_flash_read(aligned_address, temp_buf, aligned_length, false);
92-
} else {
93-
ret = esp_rom_flash_read(aligned_address, temp_buf, aligned_length, true);
93+
uint8_t *dest_ptr = (uint8_t *)buffer;
94+
size_t remaining = length;
95+
size_t copy_size = 0;
96+
size_t aligned_size = 0;
97+
bool allow_decrypt = esp_flash_encryption_enabled();
98+
99+
if (flash_esp32_is_aligned(address, buffer, length)) {
100+
ret = esp_rom_flash_read(address, buffer, length, allow_decrypt);
101+
return (ret == ESP_OK) ? 0 : -EIO;
94102
}
95103

96-
memcpy((void *)buffer, ((uint8_t *)temp_buf) + address_offset, length);
97-
#else
104+
/* handle unaligned reading */
105+
uint8_t __aligned(4) temp_buf[READ_BUFFER_SIZE + 8];
106+
while (remaining > 0) {
107+
size_t addr_offset = address & 3;
108+
size_t buf_offset = (uintptr_t)dest_ptr & 3;
109+
110+
copy_size = (remaining > READ_BUFFER_SIZE) ? READ_BUFFER_SIZE : remaining;
111+
112+
if (addr_offset == 0 && buf_offset == 0 && copy_size >= 4) {
113+
aligned_size = copy_size & ~3;
114+
ret = esp_rom_flash_read(address, dest_ptr, aligned_size, allow_decrypt);
115+
if (ret != ESP_OK) {
116+
return -EIO;
117+
}
118+
119+
address += aligned_size;
120+
dest_ptr += aligned_size;
121+
remaining -= aligned_size;
122+
} else {
123+
size_t start_addr = address - addr_offset;
98124

125+
aligned_size = (copy_size + addr_offset + 3) & ~3;
126+
127+
ret = esp_rom_flash_read(start_addr, temp_buf, aligned_size, allow_decrypt);
128+
if (ret != ESP_OK) {
129+
return -EIO;
130+
}
131+
132+
memcpy(dest_ptr, temp_buf + addr_offset, copy_size);
133+
134+
address += copy_size;
135+
dest_ptr += copy_size;
136+
remaining -= copy_size;
137+
}
138+
}
139+
#else
99140
flash_esp32_sem_take(dev);
100141

101142
if (esp_flash_encryption_enabled()) {
@@ -105,7 +146,6 @@ static int flash_esp32_read(const struct device *dev, off_t address, void *buffe
105146
}
106147

107148
flash_esp32_sem_give(dev);
108-
109149
#endif
110150

111151
if (ret != 0) {
@@ -124,21 +164,15 @@ static int flash_esp32_write(const struct device *dev,
124164
int ret = 0;
125165

126166
#ifdef CONFIG_MCUBOOT
127-
/* ensure everything is 4-byte aligned */
128-
size_t aligned_length = ROUND_UP(length, 4);
129-
off_t aligned_address = ROUND_DOWN(address, 4);
130-
size_t address_offset = address - aligned_address;
131-
uint32_t temp_buf[aligned_length / 4];
132-
133-
if (!esp_flash_encryption_enabled()) {
134-
ret = esp_rom_flash_write(aligned_address, temp_buf, aligned_length, false);
135-
} else {
136-
ret = esp_rom_flash_write(aligned_address, temp_buf, aligned_length, true);
167+
if (!flash_esp32_is_aligned(address, (void *)buffer, length)) {
168+
LOG_ERR("Unaligned flash write is not supported");
169+
return -EINVAL;
137170
}
138171

139-
memcpy((void *)buffer, ((uint8_t *)temp_buf) + address_offset, length);
140-
#else
172+
bool encrypt = esp_flash_encryption_enabled();
141173

174+
ret = esp_rom_flash_write(address, (void *)buffer, length, encrypt);
175+
#else
142176
flash_esp32_sem_take(dev);
143177

144178
if (esp_flash_encryption_enabled()) {
@@ -148,7 +182,6 @@ static int flash_esp32_write(const struct device *dev,
148182
}
149183

150184
flash_esp32_sem_give(dev);
151-
152185
#endif
153186

154187
if (ret != 0) {

0 commit comments

Comments
 (0)