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