|
30 | 30 |
|
31 | 31 | #ifndef EMULATOR |
32 | 32 |
|
| 33 | +bool do_memory_ranges_overlap(size_t range1Start, size_t range1End, size_t range2Start, size_t range2End) { |
| 34 | + if (range1Start <= range2Start) { |
| 35 | + return range2Start < range1End; |
| 36 | + } else { |
| 37 | + return range1Start < range2End; |
| 38 | + } |
| 39 | +} |
| 40 | + |
| 41 | +bool allow_svhandler_flash_sector(const FlashSector* sector) { |
| 42 | + return sector->use == FLASH_STORAGE1 || |
| 43 | + sector->use == FLASH_STORAGE2 || |
| 44 | + sector->use == FLASH_STORAGE3 || |
| 45 | + sector->use == FLASH_UNUSED0 || |
| 46 | + sector->use == FLASH_APP; |
| 47 | +} |
| 48 | + |
| 49 | +bool allow_svhandler_flash_sector_num(int sector) { |
| 50 | + for (const FlashSector *s = flash_sector_map; s->use != FLASH_INVALID; s++) { |
| 51 | + if (s->sector == sector) return allow_svhandler_flash_sector(s); |
| 52 | + } |
| 53 | + return false; |
| 54 | +} |
| 55 | + |
| 56 | +bool allow_svhandler_flash_range(size_t start, size_t end) { |
| 57 | + // Protect from overflow. |
| 58 | + if (start > end) return false; |
| 59 | + |
| 60 | + // Disallow non-flash writes. |
| 61 | + if (start < FLASH_ORIGIN || end > FLASH_END) return false; |
| 62 | + |
| 63 | + // Disallow writes to any sectors which aren't allowed. |
| 64 | + bool startAllowed = false; |
| 65 | + bool endAllowed = false; |
| 66 | + for (const FlashSector* s = flash_sector_map; s->use != FLASH_INVALID; s++) { |
| 67 | + if (allow_svhandler_flash_sector(s)) { |
| 68 | + if (!startAllowed && |
| 69 | + start + 1 > start && |
| 70 | + do_memory_ranges_overlap(start, start + 1, s->start, s->start + s->len)) { |
| 71 | + startAllowed = true; |
| 72 | + } |
| 73 | + if (!endAllowed && |
| 74 | + end - 1 < end && |
| 75 | + do_memory_ranges_overlap(end - 1, end, s->start, s->start + s->len)) { |
| 76 | + endAllowed = true; |
| 77 | + } |
| 78 | + } else { |
| 79 | + if (do_memory_ranges_overlap(start, end, s->start, s->start + s->len)) return false; |
| 80 | + } |
| 81 | + } |
| 82 | + |
| 83 | + // Ensure writes start and end in allowed sectors. As long as flash_sector_map consists of |
| 84 | + // contiguous sectors, this will ensure no writes can target flash outside the map. |
| 85 | + if (!startAllowed || !endAllowed) return false; |
| 86 | + |
| 87 | + return true; |
| 88 | +} |
| 89 | + |
33 | 90 | /// Return context from user isr processing |
34 | 91 | void svc_busr_return(void) { |
35 | 92 | __asm__ __volatile__("svc %0" ::"i"(SVC_BUSR_RET) : "memory"); |
@@ -76,13 +133,10 @@ bool svc_flash_pgm_word(uint32_t beginAddr, uint32_t data) { |
76 | 133 | } |
77 | 134 |
|
78 | 135 | void svhandler_flash_erase_sector(void) { |
79 | | - uint32_t sector = _param_1; |
| 136 | + uint8_t sector = _param_1; |
80 | 137 |
|
81 | | - // Do not allow firmware to erase bootstrap or bootloader sectors. |
82 | | - if ((sector == FLASH_BOOTSTRAP_SECTOR) || |
83 | | - (sector >= FLASH_BOOT_SECTOR_FIRST && sector <= FLASH_BOOT_SECTOR_LAST)) { |
84 | | - return; |
85 | | - } |
| 138 | + // Verify requested sector is allowed. |
| 139 | + if (!allow_svhandler_flash_sector_num(sector)) return; |
86 | 140 |
|
87 | 141 | // Unlock flash. |
88 | 142 | flash_clear_status_flags(); |
@@ -111,25 +165,8 @@ void svhandler_flash_pgm_blk(void) { |
111 | 165 | uint32_t data = _param_2; |
112 | 166 | uint32_t length = _param_3; |
113 | 167 |
|
114 | | - // Protect from overflow. |
115 | | - if (beginAddr + length < beginAddr) return; |
116 | | - |
117 | | - // Do not allow firmware to erase bootstrap or bootloader sectors. |
118 | | - if (((beginAddr >= BSTRP_FLASH_SECT_START) && |
119 | | - (beginAddr <= (BSTRP_FLASH_SECT_START + BSTRP_FLASH_SECT_LEN - 1))) || |
120 | | - (((beginAddr + length) >= BSTRP_FLASH_SECT_START) && |
121 | | - ((beginAddr + length) <= |
122 | | - (BSTRP_FLASH_SECT_START + BSTRP_FLASH_SECT_LEN - 1)))) { |
123 | | - return; |
124 | | - } |
125 | | - |
126 | | - if (((beginAddr >= BLDR_FLASH_SECT_START) && |
127 | | - (beginAddr <= (BLDR_FLASH_SECT_START + 2 * BLDR_FLASH_SECT_LEN - 1))) || |
128 | | - (((beginAddr + length) >= BLDR_FLASH_SECT_START) && |
129 | | - ((beginAddr + length) <= |
130 | | - (BLDR_FLASH_SECT_START + 2 * BLDR_FLASH_SECT_LEN - 1)))) { |
131 | | - return; |
132 | | - } |
| 168 | + // Verify requested address range is allowed. |
| 169 | + if (!allow_svhandler_flash_range(beginAddr, beginAddr + length)) return; |
133 | 170 |
|
134 | 171 | // Unlock flash. |
135 | 172 | flash_clear_status_flags(); |
@@ -157,16 +194,8 @@ void svhandler_flash_pgm_word(void) { |
157 | 194 | uint32_t dst = _param_1; |
158 | 195 | uint32_t src = _param_2; |
159 | 196 |
|
160 | | - // Do not allow firmware to erase bootstrap or bootloader sectors. |
161 | | - if ((dst >= BSTRP_FLASH_SECT_START) && |
162 | | - (dst <= (BSTRP_FLASH_SECT_START + BSTRP_FLASH_SECT_LEN))) { |
163 | | - return; |
164 | | - } |
165 | | - |
166 | | - if ((dst >= BLDR_FLASH_SECT_START) && |
167 | | - (dst <= (BLDR_FLASH_SECT_START + 2 * BLDR_FLASH_SECT_LEN))) { |
168 | | - return; |
169 | | - } |
| 197 | + // Verify requested address range is allowed. |
| 198 | + if (!allow_svhandler_flash_range(dst, dst + sizeof(uint32_t))) return; |
170 | 199 |
|
171 | 200 | // Unlock flash. |
172 | 201 | flash_clear_status_flags(); |
|
0 commit comments