• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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