1 /******************************************************************************
3 * Copyright (C) 2017-2018 Texas Instruments Incorporated - http://www.ti.com/
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
12 * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the
17 * Neither the name of Texas Instruments Incorporated nor the names of
18 * its contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 ******************************************************************************/
37 #include "flashloader.h"
40 /* Array holding erased state of the flash sectors. */
41 static bool g_is_erased[FLASH_MAX_SECTOR_COUNT];
43 extern uint8_t g_retain_buf[];
45 uint32_t flashloader_init(struct flash_params *params, uint8_t *buf1,
48 /* Initialize params buffers */
49 memset((void *)params, 0, 2 * sizeof(struct flash_params));
50 params[0].buf_addr = (uint32_t)buf1;
51 params[1].buf_addr = (uint32_t)buf2;
53 /* Mark all sectors at "not erased" */
54 memset(g_is_erased, false, sizeof(g_is_erased));
59 uint32_t flashloader_erase_and_program(uint8_t *src, uint32_t address,
62 if (byte_count > BUFFER_LEN)
63 return STATUS_FAILED_INVALID_ARGUMENTS;
65 /* Erase affected sectors */
66 uint32_t status = flashloader_erase_sectors(address, byte_count);
68 if (status != STATUS_OK)
72 status = flashloader_program(src, address, byte_count);
77 uint32_t flashloader_program_with_retain(uint8_t *src, uint32_t address,
80 #if (BUFFER_LEN > FLASH_ERASE_SIZE)
81 #error Buffer size cannot be larger than the flash sector size!
84 uint32_t first_sector_idx;
85 uint32_t last_sector_idx;
86 uint32_t status = STATUS_OK;
89 first_sector_idx = flashloader_address_to_sector(address);
90 last_sector_idx = flashloader_address_to_sector(address + byte_count - 1);
92 /* Mark all sectors as "not erased" before starting */
93 memset(g_is_erased, false, sizeof(g_is_erased));
95 uint32_t sec_offset = address % FLASH_ERASE_SIZE;
97 uint32_t src_offset = 0;
99 for (i = first_sector_idx; i <= last_sector_idx; i++) {
101 /* Chop off at sector boundary if data goes into the next sector. */
102 curr_count = byte_count;
103 if ((address + byte_count) > ((i+1) * FLASH_ERASE_SIZE))
104 curr_count -= (address + byte_count) % FLASH_ERASE_SIZE;
106 /* Copy flash sector to retain buffer */
107 memcpy(g_retain_buf, (void *)(i * FLASH_ERASE_SIZE), FLASH_ERASE_SIZE);
109 /* Copy data buffer to retain buffer */
110 memcpy(&g_retain_buf[sec_offset], &src[src_offset], curr_count);
112 /* Erase and program from retain buffer */
113 status = flashloader_erase_and_program(g_retain_buf,
114 (i * FLASH_ERASE_SIZE), FLASH_ERASE_SIZE);
115 if (status != STATUS_OK)
118 address += curr_count;
119 sec_offset = address % FLASH_ERASE_SIZE;
120 byte_count -= curr_count;
121 src_offset += curr_count;
127 uint32_t flashloader_erase_all(void)
129 if (flash_bank_erase(true) != FAPI_STATUS_SUCCESS)
130 return STATUS_FAILED_ERASE_ALL;
132 memset(g_is_erased, true, sizeof(g_is_erased));
137 uint32_t flashloader_erase_sectors(uint32_t address, uint32_t byte_count)
139 uint32_t first_sector_idx;
140 uint32_t last_sector_idx;
144 /* Floor address to the start of the sector and convert to sector number */
145 first_sector_idx = flashloader_address_to_sector(address);
146 last_sector_idx = flashloader_address_to_sector(address + byte_count - 1);
148 /* Erase given sector(s) */
149 for (idx = first_sector_idx; idx <= last_sector_idx; idx++) {
151 /* Only erase sectors that haven't already been erased */
152 if (g_is_erased[idx] == false) {
153 status = flash_sector_erase(idx * FLASH_ERASE_SIZE);
154 if (status != FAPI_STATUS_SUCCESS) {
155 status = (STATUS_FAILED_SECTOR_ERASE |
156 ((idx << STATUS_EXT_INFO_S) & STATUS_EXT_INFO_M) |
157 ((status << STATUS_ROM_CODE_S) & STATUS_ROM_CODE_M));
160 g_is_erased[idx] = true;
167 uint32_t flashloader_program(uint8_t *src, uint32_t address,
170 uint32_t status = flash_program(src, address, byte_count);
171 if (status != FAPI_STATUS_SUCCESS) {
172 status = (STATUS_FAILED_PROGRAM |
173 ((status << STATUS_ROM_CODE_S) & STATUS_ROM_CODE_M));