1 /******************************************************************************
2 * Copyright (c) 2020 Huawei Device Co., Ltd.
3 * All rights reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 * Copyright (c) 2022 Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
17 *
18 *****************************************************************************/
19
20 #include <stdbool.h>
21 #include <stdio.h>
22
23 #include <securec.h>
24
25 #include <los_compiler.h>
26
27 #include "hal_hota_board.h"
28
29 #include <B91/flash.h>
30
31 #define CONFIG_USE_BOOTLOADER 1
32
33 #define PAGE_MASK (~(unsigned int)(PAGE_SIZE - 1))
34 #define BOOT_MARK_OFFSET 0x20
35
36 #define OTA_PARTITION_SIZE (1024 * 64 * 8)
37 #define OTA_PARTITONS_START OTA_PARTITION_SIZE
38
39 #define RUNNING_PARTITION_ADDR 0
40
41 #define B_IN_KB 1024
42 #define BLOCK_64K (64 * B_IN_KB)
43 #define BOOT_MARK_SIZE 4
44 #define BOOTLOADER_STEP (B_IN_KB * 128)
45
46 #define RDID_CAPACITY_ID 2
47
48
49 static struct {
50 size_t flash_size;
51 size_t first_invalid_byte;
52 int n_partition_started;
53 size_t partition0_addr;
54 size_t cur_partition_addr;
55 UpdateMetaData metaData;
56 } g_ota_state;
57
58 static const char mypublic_pem[] = "-----BEGIN PUBLIC KEY-----\n"
59 "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAL4tQSooTP+Bn2LDxnBzUehsoYERgsus\n"
60 "mthynMi1HPEzzQJX3lsaFmGgMQMeUiMkfs8+e6YF4iKhNkpvf09WIWECAwEAAQ==\n"
61 "-----END PUBLIC KEY-----";
62
HotaHalInit(void)63 int HotaHalInit(void)
64 {
65 g_ota_state.n_partition_started = -1;
66
67 g_ota_state.cur_partition_addr = BOOTLOADER_STEP * (reg_mspi_set_l & 0x07);
68
69 if (g_ota_state.cur_partition_addr) {
70 g_ota_state.partition0_addr = 0;
71 } else {
72 g_ota_state.partition0_addr = OTA_PARTITONS_START;
73 }
74
75 UINT8 buf[4];
76 flash_read_mid(buf);
77 g_ota_state.flash_size = 1 << buf[RDID_CAPACITY_ID];
78 g_ota_state.first_invalid_byte =
79 ((g_ota_state.flash_size - OTA_PARTITONS_START) / OTA_PARTITION_SIZE) * OTA_PARTITION_SIZE +
80 OTA_PARTITONS_START;
81 printf("flash_size: %uk first_invalid_byte: %u\r\n", g_ota_state.flash_size / B_IN_KB,
82 g_ota_state.first_invalid_byte);
83
84 return OHOS_SUCCESS;
85 }
86
HotaHalGetUpdateIndex(unsigned int * index)87 int HotaHalGetUpdateIndex(unsigned int *index)
88 {
89 printf(" === %s:%d\r\n", __func__, __LINE__);
90 return OHOS_SUCCESS;
91 }
92
HotaHalDeInit(void)93 int HotaHalDeInit(void)
94 {
95 if (g_ota_state.n_partition_started >= 0) {
96 size_t addr = OTA_PARTITONS_START + OTA_PARTITION_SIZE * g_ota_state.n_partition_started;
97 size_t next_part = addr + OTA_PARTITION_SIZE;
98 while (addr < next_part) {
99 flash_erase_64kblock(addr);
100 addr += BLOCK_64K;
101 }
102 g_ota_state.n_partition_started = -1;
103 printf(" === %s:%d\r\n", __func__, __LINE__);
104 } else {
105 printf(" === %s:%d\r\n", __func__, __LINE__);
106 return OHOS_FAILURE;
107 }
108
109 return OHOS_SUCCESS;
110 }
111
HotaHalRead(int partition,unsigned int offset,unsigned int bufLen,unsigned char * buffer)112 int HotaHalRead(int partition, unsigned int offset, unsigned int bufLen, unsigned char *buffer)
113 {
114 if ((buffer == NULL) || (bufLen == 0)) {
115 return OHOS_FAILURE;
116 }
117
118 unsigned int start =
119 ((0 == partition) ? g_ota_state.partition0_addr : OTA_PARTITONS_START + OTA_PARTITION_SIZE * partition) +
120 offset;
121 unsigned int end = start + bufLen;
122 if ((start > g_ota_state.first_invalid_byte) || (end > g_ota_state.first_invalid_byte)) {
123 printf("ERROR: Exceed flash size start: %u end: %u\r\n", start, end);
124 return OHOS_FAILURE;
125 }
126
127 memset(buffer, 0, bufLen);
128 flash_read_page(start, bufLen, buffer);
129 printf(" === %s:%d\r\n", __func__, __LINE__);
130
131 return OHOS_SUCCESS;
132 }
133
OtaPartitionClear(unsigned int addr)134 _attribute_ram_code_sec_ void OtaPartitionClear(unsigned int addr)
135 {
136 for (unsigned int current = addr, end = addr + OTA_PARTITION_SIZE; current < end; current += BLOCK_64K) {
137 flash_erase_64kblock_ram(current);
138 }
139 }
140
HotaHalWrite(int partition,unsigned char * buffer,unsigned int offset,unsigned int bufLen)141 int HotaHalWrite(int partition, unsigned char *buffer, unsigned int offset, unsigned int bufLen)
142 {
143 if (partition == PARTITION_INFO_COMP) {
144 printf("partition == PARTITION_INFO_COMP, skip it.");
145 return OHOS_SUCCESS;
146 }
147
148 unsigned int start =
149 ((0 == partition) ? g_ota_state.partition0_addr : OTA_PARTITONS_START + OTA_PARTITION_SIZE * partition) +
150 offset;
151
152 if (-1 == g_ota_state.n_partition_started) {
153 g_ota_state.n_partition_started = partition;
154 OtaPartitionClear(start & (~(OTA_PARTITION_SIZE - 1)));
155 }
156
157 unsigned int end = start + bufLen;
158 if ((start > g_ota_state.first_invalid_byte) || (end > g_ota_state.first_invalid_byte)) {
159 printf("ERROR: Exceed flash size start: %u end: %u\r\n", start, end);
160 return OHOS_FAILURE;
161 }
162
163 flash_write_page(start, bufLen, buffer);
164
165 return OHOS_SUCCESS;
166 }
FlashCheckPageIsFree(unsigned int addr,UINT8 * workbuf)167 _attribute_ram_code_sec_ bool FlashCheckPageIsFree(unsigned int addr, UINT8 *workbuf)
168 {
169 addr &= PAGE_MASK;
170 flash_read_page_ram(addr, PAGE_SIZE, workbuf);
171
172 for (const UINT32 *p = workbuf, *page_end = p + (PAGE_SIZE / sizeof(*p)); p < page_end; ++p) {
173 if (*p != 0xFFFFFFFFu) {
174 return false;
175 }
176 }
177
178 return true;
179 }
180
FlashCopyPage(unsigned int dst,unsigned int src,UINT8 * workbuf)181 _attribute_ram_code_sec_ STATIC void FlashCopyPage(unsigned int dst, unsigned int src, UINT8 *workbuf)
182 {
183 if (false == FlashCheckPageIsFree(dst, workbuf)) {
184 flash_erase_page_ram(dst);
185 }
186
187 flash_read_page_ram(src, PAGE_SIZE, workbuf);
188 flash_write_page_ram(dst, PAGE_SIZE, workbuf);
189 }
190
OtaPartitionCopy(unsigned int dst,unsigned int src,UINT8 * workbuf)191 _attribute_ram_code_sec_ STATIC void OtaPartitionCopy(unsigned int dst, unsigned int src, UINT8 *workbuf)
192 {
193 for (unsigned int addr = 0; addr < OTA_PARTITION_SIZE; addr += PAGE_SIZE) {
194 FlashCopyPage(dst + addr, src + addr, workbuf);
195 }
196 }
197
flash_write_data(unsigned long addr,unsigned long len,const UINT8 * data,UINT8 * buf)198 _attribute_ram_code_sec_ STATIC void flash_write_data(unsigned long addr, unsigned long len, const UINT8 *data,
199 UINT8 *buf)
200 {
201 unsigned int page_addr = addr & PAGE_MASK;
202 flash_read_page_ram(page_addr, PAGE_SIZE, buf);
203 memcpy(&buf[(addr % PAGE_SIZE)], data, len);
204 flash_erase_page_ram(page_addr);
205 flash_write_page_ram(page_addr, PAGE_SIZE, buf);
206 }
207
HotaBootNewImpl(void)208 _attribute_ram_code_sec_ STATIC int HotaBootNewImpl(void)
209 {
210 void *buf = malloc(PAGE_SIZE);
211
212 if (buf == NULL) {
213 return OHOS_FAILURE;
214 }
215
216 core_interrupt_disable();
217
218 __asm__ volatile("csrci mmisc_ctl, 8"); // disable BTB
219
220 unsigned int new_partition_addr =
221 ((g_ota_state.n_partition_started == 0)
222 ? g_ota_state.partition0_addr
223 : OTA_PARTITONS_START + OTA_PARTITION_SIZE * g_ota_state.n_partition_started);
224
225 flash_write_data(new_partition_addr + BOOT_MARK_OFFSET, BOOT_MARK_SIZE, "KNLT", buf);
226 flash_write_data(g_ota_state.cur_partition_addr + BOOT_MARK_OFFSET, BOOT_MARK_SIZE, "\0\0\0\0", buf);
227
228 sys_reboot();
229
230 while (1) {
231 _ASM_NOP_;
232 }
233
234 __builtin_unreachable();
235 }
236
HotaHalRestart(void)237 int HotaHalRestart(void)
238 {
239 if (-1 == g_ota_state.n_partition_started) {
240 return OHOS_FAILURE;
241 }
242
243 printf(" === %s:%d\r\n", __func__, __LINE__);
244
245 return HotaBootNewImpl();
246 }
247
HotaHalSetBootSettings(void)248 int HotaHalSetBootSettings(void)
249 {
250 printf(" === %s:%d\r\n", __func__, __LINE__);
251
252 return OHOS_SUCCESS;
253 }
254
HotaBootRoollbackImpl(void)255 _attribute_ram_code_sec_ int HotaBootRoollbackImpl(void)
256 {
257 if (-1 != g_ota_state.n_partition_started) {
258 return OHOS_FAILURE;
259 }
260
261 void *buf = malloc(PAGE_SIZE);
262
263 if (buf == NULL) {
264 return OHOS_FAILURE;
265 }
266
267 unsigned int r = core_interrupt_disable();
268
269 __asm__ volatile("csrci mmisc_ctl, 8"); // disable BTB
270
271 unsigned int rollback_partition_addr = g_ota_state.partition0_addr;
272
273 if (true == FlashCheckPageIsFree(rollback_partition_addr, buf)) {
274 __asm__ volatile("csrsi mmisc_ctl, 8"); // enable BTB
275 core_restore_interrupt(r);
276 free(buf);
277 return OHOS_FAILURE;
278 }
279
280 flash_write_data(rollback_partition_addr + BOOT_MARK_OFFSET, BOOT_MARK_SIZE, "KNLT", buf);
281 flash_write_data(g_ota_state.cur_partition_addr + BOOT_MARK_OFFSET, BOOT_MARK_SIZE, "\0\0\0\0", buf);
282
283 sys_reboot();
284
285 while (1) {
286 _ASM_NOP_;
287 }
288
289 __builtin_unreachable();
290 }
291
HotaHalRollback(void)292 int HotaHalRollback(void)
293 {
294 printf(" === %s:%d\r\n", __func__, __LINE__);
295 return HotaBootRoollbackImpl();
296 }
297
HotaHalGetPartitionInfo()298 const ComponentTableInfo *HotaHalGetPartitionInfo()
299 {
300 printf(" === %s:%d\r\n", __func__, __LINE__);
301 return NULL;
302 }
303
HotaHalGetPubKey(unsigned int * length)304 unsigned char *HotaHalGetPubKey(unsigned int *length)
305 {
306 if (length == NULL) {
307 printf("OTA pub key is NULL.\r\n");
308 return NULL;
309 }
310
311 printf(" === %s:%d\r\n", __func__, __LINE__);
312
313 *length = sizeof(mypublic_pem);
314 return mypublic_pem;
315 }
316
HotaHalGetUpdateAbility(void)317 int HotaHalGetUpdateAbility(void)
318 {
319 printf(" === %s:%d\r\n", __func__, __LINE__);
320 return 0;
321 }
322
HotaHalGetOtaPkgPath(char * path,int len)323 int HotaHalGetOtaPkgPath(char *path, int len)
324 {
325 printf(" === %s:%d\r\n", __func__, __LINE__);
326 return OHOS_FAILURE;
327 }
328
HotaHalIsDeviceCanReboot(void)329 int HotaHalIsDeviceCanReboot(void)
330 {
331 return 1;
332 }
333
HotaHalGetMetaData(UpdateMetaData * metaData)334 int HotaHalGetMetaData(UpdateMetaData *metaData)
335 {
336 *metaData = g_ota_state.metaData;
337 return OHOS_SUCCESS;
338 }
339
HotaHalSetMetaData(UpdateMetaData * metaData)340 int HotaHalSetMetaData(UpdateMetaData *metaData)
341 {
342 g_ota_state.metaData = *metaData;
343 return OHOS_SUCCESS;
344 }
345
HotaHalRebootAndCleanUserData(void)346 int HotaHalRebootAndCleanUserData(void)
347 {
348 return OHOS_SUCCESS;
349 }
350
HotaHalRebootAndCleanCache(void)351 int HotaHalRebootAndCleanCache(void)
352 {
353 return OHOS_SUCCESS;
354 }
355
HotaHalCheckVersionValid(const char * currentVersion,const char * pkgVersion,unsigned int pkgVersionLength)356 int HotaHalCheckVersionValid(const char *currentVersion, const char *pkgVersion, unsigned int pkgVersionLength)
357 {
358 return (strncmp(currentVersion, pkgVersion, pkgVersionLength) == 0) ? 1 : 0;
359 }
360