1 /*
2 * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 * Description: OTA适配实现 (此文件为DEMO,需集成方适配修改)
15 */
16 #include "hilink_open_ota_adapter.h"
17 #include "securec.h"
18 #include "sfc.h"
19 #include "partition.h"
20 #include "upg_porting.h"
21 #include "upg_common_porting.h"
22 #include "partition_resource_id.h"
23 #include "hilink_sal_defines.h"
24 #include "watchdog.h"
25
26 typedef struct {
27 /* 升级的偏移 */
28 unsigned int write_offset;
29 /* 可升级区域的总大小 */
30 unsigned int max_size;
31 } upg_param;
32
33 /* 记录升级相关的信息,比如开始地址,擦写块信息,可升级的最大区域 */
34 static upg_param g_upgrade;
35
36 const sfc_flash_config_t sfc_cfg = {
37 .read_type = FAST_READ_QUAD_OUTPUT,
38 .write_type = PAGE_PROGRAM,
39 .mapping_addr = 0x200000,
40 .mapping_size = 0x800000,
41 };
42
upg_get_upgrade_part_start_addr(uint32_t * start_address)43 static errcode_t upg_get_upgrade_part_start_addr(uint32_t *start_address)
44 {
45 errcode_t ret_val;
46 partition_information_t info;
47 ret_val = uapi_partition_get_info(PARTITION_FOTA_DATA, &info);
48 if (ret_val != ERRCODE_SUCC) {
49 return ret_val;
50 }
51 *start_address = info.part_info.addr_info.addr;
52 return ERRCODE_SUCC;
53 }
54
upg_get_upgrade_part_size(uint32_t * size)55 static errcode_t upg_get_upgrade_part_size(uint32_t *size)
56 {
57 errcode_t ret_val;
58 partition_information_t info;
59 ret_val = uapi_partition_get_info(PARTITION_FOTA_DATA, &info);
60 if (ret_val != ERRCODE_SUCC) {
61 return ret_val;
62 }
63 *size = info.part_info.addr_info.size - UPG_UPGRADE_FLAG_LENGTH;
64 return ERRCODE_SUCC;
65 }
66
67 /*
68 * Flash初始化
69 * 返回值是true时,表示初始化正常
70 * 返回值是false时,表示初始化异常
71 */
HILINK_OtaAdapterFlashInit(void)72 bool HILINK_OtaAdapterFlashInit(void)
73 {
74 uint32_t ret = uapi_sfc_init((sfc_flash_config_t *)&sfc_cfg);
75 if (ret != ERRCODE_SUCC) {
76 return false;
77 }
78 if (memset_s(&g_upgrade, sizeof(upg_param), 0, sizeof(upg_param)) != EOK) {
79 return false;
80 }
81 uint32_t size = 0;
82 if (upg_get_upgrade_part_size(&size) != 0) {
83 HILINK_SAL_WARN("get upgrade max file len fail.\r\n");
84 return false;
85 }
86 g_upgrade.max_size = size;
87 return true;
88 }
89
90 /*
91 * 判断需要升级的分区
92 * 返回值是UPGRADE_FW_BIN1时,表示升级固件到分区1
93 * 返回值是UPGRADE_FW_BIN2时,表示升级固件到分区2
94 */
HILINK_OtaAdapterGetUpdateIndex(void)95 unsigned int HILINK_OtaAdapterGetUpdateIndex(void)
96 {
97 return UPGRADE_FW_BIN1;
98 }
99
100 /*
101 * 擦除需要升级的分区
102 * size表示需要擦除的分区大小
103 * 返回值是RETURN_OK时,表示擦除成功
104 * 返回值是RETURN_ERROR时,表示擦除失败
105 */
HILINK_OtaAdapterFlashErase(unsigned int size)106 int HILINK_OtaAdapterFlashErase(unsigned int size)
107 {
108 errcode_t ret_val;
109 if (size > g_upgrade.max_size) {
110 return RETURN_ERROR;
111 }
112 upg_prepare_info_t prepare_info;
113
114 prepare_info.package_len = size;
115 ret_val = uapi_upg_prepare(&prepare_info);
116 if (ret_val != ERRCODE_SUCC) {
117 return RETURN_ERROR;
118 }
119 return RETURN_OK;
120 }
121
122 /*
123 * 升级数据写入升级的分区
124 * buf表示待写入数据
125 * bufLen表示待写入数据的长度
126 * 返回值是RETURN_OK时,表示写入成功
127 * 返回值是RETURN_ERROR时,表示写入失败
128 */
129
130 /* 需要记录写入后的offset */
HILINK_OtaAdapterFlashWrite(const unsigned char * buf,unsigned int bufLen)131 int HILINK_OtaAdapterFlashWrite(const unsigned char *buf, unsigned int bufLen)
132 {
133 (void)uapi_watchdog_kick();
134
135 errcode_t ret_val;
136 uint32_t start_addr;
137 if ((buf == NULL) || (bufLen == 0) || ((g_upgrade.write_offset + bufLen) > g_upgrade.max_size)) {
138 return RETURN_ERROR;
139 }
140 ret_val = upg_get_upgrade_part_start_addr(&start_addr);
141 if (ret_val != ERRCODE_SUCC) {
142 return RETURN_ERROR;
143 }
144 // 写入
145 ret_val = upg_flash_write(start_addr + g_upgrade.write_offset, bufLen, buf, false);
146 if (ret_val != ERRCODE_SUCC) {
147 return RETURN_ERROR;
148 }
149 g_upgrade.write_offset += bufLen;
150 return RETURN_OK;
151 }
152
153 /*
154 * 读取升级分区数据
155 * offset表示读写偏移
156 * buf表示输出数据的内存地址
157 * bufLen表示输出数据的内存长度
158 * 返回值是RETURN_OK时,表示读取成功
159 * 返回值是RETURN_ERROR时,表示读取失败
160 */
HILINK_OtaAdapterFlashRead(unsigned int offset,unsigned char * buf,unsigned int bufLen)161 int HILINK_OtaAdapterFlashRead(unsigned int offset, unsigned char *buf, unsigned int bufLen)
162 {
163 errcode_t ret_val;
164 uint32_t start_addr;
165 if ((buf == NULL) || (bufLen == 0) || ((offset + bufLen) > g_upgrade.max_size)) {
166 return RETURN_ERROR;
167 }
168 ret_val = upg_get_upgrade_part_start_addr(&start_addr);
169 if (ret_val != ERRCODE_SUCC) {
170 return RETURN_ERROR;
171 }
172 // 读取
173 ret_val = upg_flash_read(start_addr + offset, bufLen, buf);
174 if (ret_val != ERRCODE_SUCC) {
175 return RETURN_ERROR;
176 }
177 return RETURN_OK;
178 }
179
180 /*
181 * 分区升级结束
182 * 返回值是true时,表示结束正常
183 * 返回值是false时,表示结束异常
184 */
185
186 /* 下载镜像结束,需要调起本地升级的接口 */
HILINK_OtaAdapterFlashFinish(void)187 bool HILINK_OtaAdapterFlashFinish(void)
188 {
189 errcode_t ret;
190 ret = uapi_upg_request_upgrade(false);
191 if (ret != ERRCODE_SUCC) {
192 return false;
193 }
194
195 return true;
196 }
197
198 /* 获取升级区间最大长度 */
HILINK_OtaAdapterFlashMaxSize(void)199 unsigned int HILINK_OtaAdapterFlashMaxSize(void)
200 {
201 errcode_t ret_val;
202 uint32_t size;
203 ret_val = upg_get_upgrade_part_size(&size);
204 if (ret_val != ERRCODE_SUCC) {
205 return 0;
206 }
207 return size;
208 }
209
210 /*
211 * 根据标志重启模组
212 * flag表示重启标志
213 * 当flag是RESTART_FLAG_NOW时,表示只有MCU升级时立即重启
214 * 当flag是RESTART_FLAG_LATER时,表示有模组时切换分区后再重启
215 */
HILINK_OtaAdapterRestart(int flag)216 void HILINK_OtaAdapterRestart(int flag)
217 {
218 upg_reboot();
219 return;
220 }
221
222 /*
223 * 开始模组升级
224 * type表示升级类型
225 * 当type是UPDATE_TYPE_MANUAL时,表示本次升级流程是由用户主动发起的手动升级
226 * 当type是UPDATE_TYPE_AUTO时,表示本次升级流程是经过用户同意的自动升级
227 * 返回值是RETURN_OK时,表示处理成功,HiLink SDK将开始启动升级流程
228 * 返回值是RETURN_ERROR时,表示处理不成功,HiLink SDK将终止本次升级流程
229 * 注意:在手动场景场景下,HiLink SDK在接收到用户发出的升级指令后,将直接调用此接口;
230 * 在自动升级场景下,当HiLink SDK在调用HilinkGetRebootFlag接口返回值是MODULE_CAN_REBOOT时,HiLink SDK将调用此接口。
231 * 厂商可在此接口中完成和升级流程相关的处理。
232 * 开机后10分钟到1小时内随机时间检测一次是否有新版本,之后以当前时间为起点,23小时加1小时内随机值周期性检测新版本。
233 * 如果用户打开了自动升级开关,检测到有新版本并且是可以重启的情况下,就进行新版本的下载,下载完成后自动重启。
234 * 自动升级流程可能在凌晨进行,因此厂商在实现升级流程相关功能时,确保在升级的下载安装固件和重启设备时避免对用户产生
235 * 影响,比如发出声音,光亮等。
236 */
HILINK_OtaStartProcess(int type)237 int HILINK_OtaStartProcess(int type)
238 {
239 return RETURN_OK;
240 }
241
242 /*
243 * 模组升级结束
244 * status表示升级结果
245 * 当status是100时,表示升级成功
246 * 当status不是100时,表示升级失败
247 * 返回值是RETURN_OK时,表示处理成功,HiLink SDK将置升级标志或切换运行区标志
248 * 返回值不是RETURN_OK时,表示处理不成功,HiLink SDK将终止本次升级流程
249 * 注意:HiLink SDK在将固件写入到OTA升级区后,且完整性校验通过后,将调用厂商适配的此接口;
250 * 厂商可在此接口中完成和升级流程相关的处理。
251 * 开机后10分钟到1小时内随机时间检测一次是否有新版本,之后以当前时间为起点,23小时加1小时内随机值周期性检测新版本。
252 * 如果用户打开了自动升级开关,检测到有新版本并且是可以重启的情况下,就进行新版本的下载,下载完成后自动重启。
253 * 自动升级流程可能在凌晨进行,因此厂商在实现升级流程相关功能时,确保在升级的下载安装固件和重启设备时避免对用户产生
254 * 影响,比如发出声音,光亮等;升级类型是否为自动升级可参考接口HilinkOtaStartProcess的参数type的描述。
255 */
HILINK_OtaEndProcess(int status)256 int HILINK_OtaEndProcess(int status)
257 {
258 return RETURN_OK;
259 }
260
261 /*
262 * 判断模组是否能立即升级并重启
263 * 返回值是MODULE_CAN_REBOOT时,表示模组可以立即升级并重启,HiLink SDK将开始自动升级流程。
264 * 返回值是MODULE_CANNOT_REBOOT时,表示模组不能立即升级并重启,HiLink SDK将不进行本次自动升级流程。
265 * 注意:在用户同意设备可以自动升级的情况下,HiLink SDK调用此接口获取设备当前业务状态下,模组是否可以立即升级并重启的标志。
266 * 只有当设备处于业务空闲状态时,接口才可以返回MODULE_CAN_REBOOT。
267 * 当设备处于业务非空闲状态时,接口返回MODULE_CANNOT_REBOOT。
268 */
HILINK_GetRebootFlag(void)269 int HILINK_GetRebootFlag(void)
270 {
271 return MODULE_CAN_REBOOT;
272 }
273