1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright (C) 2023 Rockchip Electronics Co., Ltd.
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Licensed under the Apache License, Version 2.0 (the "License");
5*4882a593Smuzhiyun * you may not use this file except in compliance with the License.
6*4882a593Smuzhiyun * You may obtain a copy of the License at
7*4882a593Smuzhiyun *
8*4882a593Smuzhiyun * http://www.apache.org/licenses/LICENSE-2.0
9*4882a593Smuzhiyun *
10*4882a593Smuzhiyun * Unless required by applicable law or agreed to in writing, software
11*4882a593Smuzhiyun * distributed under the License is distributed on an "AS IS" BASIS,
12*4882a593Smuzhiyun * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*4882a593Smuzhiyun * See the License for the specific language governing permissions and
14*4882a593Smuzhiyun * limitations under the License.
15*4882a593Smuzhiyun */
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun #include <stdlib.h>
18*4882a593Smuzhiyun #include <stdio.h>
19*4882a593Smuzhiyun #include <string.h>
20*4882a593Smuzhiyun #include <unistd.h>
21*4882a593Smuzhiyun #include <sys/stat.h>
22*4882a593Smuzhiyun #include <fcntl.h>
23*4882a593Smuzhiyun #include <errno.h>
24*4882a593Smuzhiyun #include <libgen.h>
25*4882a593Smuzhiyun #include <stdbool.h>
26*4882a593Smuzhiyun #include "update.h"
27*4882a593Smuzhiyun #include "log.h"
28*4882a593Smuzhiyun #include "download.h"
29*4882a593Smuzhiyun #include "rkimage.h"
30*4882a593Smuzhiyun #include "flash_image.h"
31*4882a593Smuzhiyun #include "rktools.h"
32*4882a593Smuzhiyun #include "md5sum.h"
33*4882a593Smuzhiyun #include "defineHeader.h"
34*4882a593Smuzhiyun #include "../mtdutils/mtdutils.h"
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun #define CMD4RECOVERY_FILENAME "/mnt/sdcard/cmd4recovery"
38*4882a593Smuzhiyun #define CMD4RECOVERY_UDISK_FILENAME "/mnt/usb_storage/cmd4recovery"
39*4882a593Smuzhiyun static char * _url = NULL;
40*4882a593Smuzhiyun static char const * _save_path = NULL;
41*4882a593Smuzhiyun static char _url_dir[128];
42*4882a593Smuzhiyun double processvalue = 0;
43*4882a593Smuzhiyun
RK_ota_set_url(char * url,char * savepath)44*4882a593Smuzhiyun void RK_ota_set_url(char *url, char *savepath)
45*4882a593Smuzhiyun {
46*4882a593Smuzhiyun LOGI("start RK_ota_url url [%s] save path [%s].\n", url, savepath);
47*4882a593Smuzhiyun if ( url == NULL ) {
48*4882a593Smuzhiyun LOGE("RK_ota_set_url : url is NULL.\n");
49*4882a593Smuzhiyun return ;
50*4882a593Smuzhiyun }
51*4882a593Smuzhiyun if (savepath == NULL) {
52*4882a593Smuzhiyun _save_path = DEFAULT_DOWNLOAD_PATH;
53*4882a593Smuzhiyun } else {
54*4882a593Smuzhiyun _save_path = savepath;
55*4882a593Smuzhiyun }
56*4882a593Smuzhiyun LOGI("save image to %s.\n", _save_path);
57*4882a593Smuzhiyun _url = url;
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun sprintf(_url_dir, "%s", _url);
60*4882a593Smuzhiyun dirname(_url_dir);
61*4882a593Smuzhiyun }
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun bool is_sdboot = false;
64*4882a593Smuzhiyun bool is_usbboot = false;
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun UPDATE_CMD update_cmd[] = {
67*4882a593Smuzhiyun {"bootloader", false, false, 0, 0, 0, "", false, flash_bootloader},
68*4882a593Smuzhiyun {"parameter", false, false, 0, 0, 0, "", false, flash_parameter},
69*4882a593Smuzhiyun {"uboot", false, false, 0, 0, 0, "", false, flash_normal},
70*4882a593Smuzhiyun {"trust", false, false, 0, 0, 0, "", false, flash_normal},
71*4882a593Smuzhiyun {"boot", false, true, 0, 0, 0, "", false, flash_normal},
72*4882a593Smuzhiyun {"recovery", false, false, 0, 0, 0, "", false, flash_normal},
73*4882a593Smuzhiyun {"rootfs", false, true, 0, 0, 0, "", false, flash_normal},
74*4882a593Smuzhiyun {"oem", false, false, 0, 0, 0, "", false, flash_normal},
75*4882a593Smuzhiyun {"uboot_a", false, false, 0, 0, 0, "", false, flash_normal},
76*4882a593Smuzhiyun {"uboot_b", false, false, 0, 0, 0, "", false, flash_normal},
77*4882a593Smuzhiyun {"boot_a", false, false, 0, 0, 0, "", false, flash_normal},
78*4882a593Smuzhiyun {"boot_b", false, false, 0, 0, 0, "", false, flash_normal},
79*4882a593Smuzhiyun {"system_a", false, false, 0, 0, 0, "", false, flash_normal},
80*4882a593Smuzhiyun {"system_b", false, false, 0, 0, 0, "", false, flash_normal},
81*4882a593Smuzhiyun {"misc", false, false, 0, 0, 0, "", false, flash_normal},
82*4882a593Smuzhiyun {"userdata", false, false, 0, 0, 0, "", false, flash_normal},
83*4882a593Smuzhiyun };
84*4882a593Smuzhiyun
RK_ota_set_partition(int partition)85*4882a593Smuzhiyun bool RK_ota_set_partition(int partition)
86*4882a593Smuzhiyun {
87*4882a593Smuzhiyun //000000000000000000000000: 没有升级分区
88*4882a593Smuzhiyun //100000000000000000000000: 升级loader分区
89*4882a593Smuzhiyun //010000000000000000000000: 升级parameter分区
90*4882a593Smuzhiyun //001000000000000000000000: 升级uboot分区
91*4882a593Smuzhiyun //000100000000000000000000: 升级trust分区
92*4882a593Smuzhiyun //000010000000000000000000: 升级boot分区
93*4882a593Smuzhiyun //000001000000000000000000: 升级recovery分区
94*4882a593Smuzhiyun //000000100000000000000000: 升级rootfs分区
95*4882a593Smuzhiyun //000000010000000000000000: 升级oem分区
96*4882a593Smuzhiyun //000000001000000000000000: 升级uboot_a分区
97*4882a593Smuzhiyun //000000000100000000000000: 升级uboot_b分区
98*4882a593Smuzhiyun //000000000010000000000000: 升级boot_a分区
99*4882a593Smuzhiyun //000000000001000000000000: 升级boot_b分区
100*4882a593Smuzhiyun //000000000000100000000000: 升级system_a分区
101*4882a593Smuzhiyun //000000000000010000000000: 升级system_b分区
102*4882a593Smuzhiyun //000000000000001000000000: 升级misc分区,sdboot使用
103*4882a593Smuzhiyun //000000000000000100000000: 升级userdata分区
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun int num = sizeof(update_cmd) / sizeof(UPDATE_CMD);
106*4882a593Smuzhiyun LOGI("[%s:%d] num [%d]\n", __func__, __LINE__, num);
107*4882a593Smuzhiyun
108*4882a593Smuzhiyun if (partition == -1) {
109*4882a593Smuzhiyun //设置目标分区大小
110*4882a593Smuzhiyun RKIMAGE_HDR rkimage_hdr;
111*4882a593Smuzhiyun if ( analyticImage(_url, &rkimage_hdr) != 0) {
112*4882a593Smuzhiyun LOGE("analyticImage error.\n");
113*4882a593Smuzhiyun return false;
114*4882a593Smuzhiyun }
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun for (int i = 0; i < num; i++) {
117*4882a593Smuzhiyun if ( update_cmd[i].need_update || is_sdboot || is_usbboot) {
118*4882a593Smuzhiyun update_cmd[i].need_update = false;
119*4882a593Smuzhiyun for (int j = 0; j < rkimage_hdr.item_count; j++) {
120*4882a593Smuzhiyun if (strcmp(rkimage_hdr.item[j].name, update_cmd[i].name) == 0) {
121*4882a593Smuzhiyun LOGI("found rkimage_hdr.item[%d].name = %s.\n", j, update_cmd[i].name);
122*4882a593Smuzhiyun if (rkimage_hdr.item[j].file[50] == 'H') {
123*4882a593Smuzhiyun update_cmd[i].offset = *((DWORD *)(&rkimage_hdr.item[j].file[51]));
124*4882a593Smuzhiyun update_cmd[i].offset <<= 32;
125*4882a593Smuzhiyun update_cmd[i].offset += rkimage_hdr.item[j].offset;
126*4882a593Smuzhiyun LOGI("offset more than 4G, after adjusting is %lld.\n", update_cmd[i].offset);
127*4882a593Smuzhiyun } else {
128*4882a593Smuzhiyun update_cmd[i].offset = rkimage_hdr.item[j].offset;
129*4882a593Smuzhiyun }
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun if (rkimage_hdr.item[j].file[55] == 'H') {
132*4882a593Smuzhiyun update_cmd[i].size = *((DWORD *)(&rkimage_hdr.item[j].file[56]));
133*4882a593Smuzhiyun update_cmd[i].size <<= 32;
134*4882a593Smuzhiyun update_cmd[i].size += rkimage_hdr.item[j].size;
135*4882a593Smuzhiyun LOGI("size more than 4G, after adjusting is %lld.\n", update_cmd[i].size);
136*4882a593Smuzhiyun } else {
137*4882a593Smuzhiyun update_cmd[i].size = rkimage_hdr.item[j].size;
138*4882a593Smuzhiyun }
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun if (is_sdboot || is_usbboot) {
141*4882a593Smuzhiyun update_cmd[i].flash_offset = (long long)rkimage_hdr.item[j].flash_offset * SECTOR_SIZE;
142*4882a593Smuzhiyun }
143*4882a593Smuzhiyun update_cmd[i].need_update = true;
144*4882a593Smuzhiyun continue ;
145*4882a593Smuzhiyun }
146*4882a593Smuzhiyun }
147*4882a593Smuzhiyun }
148*4882a593Smuzhiyun }
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun if (!is_sdboot && !is_usbboot) {
151*4882a593Smuzhiyun for ( int i = 0; i < num; i++ ) {
152*4882a593Smuzhiyun if (*update_cmd[i].dest_path && (update_cmd[i].need_update == false)) {
153*4882a593Smuzhiyun
154*4882a593Smuzhiyun unsigned char len = strlen(update_cmd[i].name);
155*4882a593Smuzhiyun if (update_cmd[i].name[len - 2] == '_' && (update_cmd[i].name[len - 1] == 'a' || update_cmd[i].name[len - 1] == 'b')) {
156*4882a593Smuzhiyun
157*4882a593Smuzhiyun char slot_find = (update_cmd[i].name[len - 1] == 'a') ? 'b' : 'a';
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun update_cmd[i].name[len - 1] = slot_find;
160*4882a593Smuzhiyun for (int j = 0; j < rkimage_hdr.item_count; j++) {
161*4882a593Smuzhiyun if (strcmp(rkimage_hdr.item[j].name, update_cmd[i].name) == 0) {
162*4882a593Smuzhiyun LOGI("again found rkimage_hdr.item[%d].name = %s.\n", j, update_cmd[i].name);
163*4882a593Smuzhiyun if (rkimage_hdr.item[j].file[50] == 'H') {
164*4882a593Smuzhiyun update_cmd[i].offset = *((DWORD *)(&rkimage_hdr.item[j].file[51]));
165*4882a593Smuzhiyun update_cmd[i].offset <<= 32;
166*4882a593Smuzhiyun update_cmd[i].offset += rkimage_hdr.item[j].offset;
167*4882a593Smuzhiyun LOGI("offset more than 4G, after adjusting is %lld.\n", update_cmd[i].offset);
168*4882a593Smuzhiyun } else {
169*4882a593Smuzhiyun update_cmd[i].offset = rkimage_hdr.item[j].offset;
170*4882a593Smuzhiyun }
171*4882a593Smuzhiyun
172*4882a593Smuzhiyun if (rkimage_hdr.item[j].file[55] == 'H') {
173*4882a593Smuzhiyun update_cmd[i].size = *((DWORD *)(&rkimage_hdr.item[j].file[56]));
174*4882a593Smuzhiyun update_cmd[i].size <<= 32;
175*4882a593Smuzhiyun update_cmd[i].size += rkimage_hdr.item[j].size;
176*4882a593Smuzhiyun LOGI("size more than 4G, after adjusting is %lld.\n", update_cmd[i].size);
177*4882a593Smuzhiyun } else {
178*4882a593Smuzhiyun update_cmd[i].size = rkimage_hdr.item[j].size;
179*4882a593Smuzhiyun }
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun update_cmd[i].need_update = true;
182*4882a593Smuzhiyun continue ;
183*4882a593Smuzhiyun }
184*4882a593Smuzhiyun }
185*4882a593Smuzhiyun }
186*4882a593Smuzhiyun }
187*4882a593Smuzhiyun }
188*4882a593Smuzhiyun }
189*4882a593Smuzhiyun // for ( int i=0; i<num; i++ ) {
190*4882a593Smuzhiyun // printf ( "[%s:%d] update_cmd[%d].name [%s] dest path [%s] flash offset [%#llx] offset [%#llx] size [%#llx] \n",
191*4882a593Smuzhiyun // __func__, __LINE__, i, update_cmd[i].name, update_cmd[i].dest_path, update_cmd[i].flash_offset, update_cmd[i].offset, update_cmd[i].size);
192*4882a593Smuzhiyun // }
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun return true;
195*4882a593Smuzhiyun }
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun for (int i = 0; i < num; i++) {
198*4882a593Smuzhiyun // For OTA and SD update MUST read gpt from update***.img
199*4882a593Smuzhiyun if ( (partition & 0x800000 || is_sdboot || is_usbboot || (strcmp(update_cmd[i].name, "parameter") == 0) ) ) {
200*4882a593Smuzhiyun LOGI("need update %s.\n", update_cmd[i].name);
201*4882a593Smuzhiyun update_cmd[i].need_update = true;
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun if (is_sdboot || is_usbboot) {
204*4882a593Smuzhiyun memset(update_cmd[i].dest_path, 0, sizeof(update_cmd[i].dest_path) / sizeof(update_cmd[i].dest_path[0]));
205*4882a593Smuzhiyun if (strcmp(update_cmd[i].name, "parameter") == 0) {
206*4882a593Smuzhiyun sprintf(update_cmd[i].dest_path, "%s/gpt", _url_dir);
207*4882a593Smuzhiyun } else {
208*4882a593Smuzhiyun sprintf(update_cmd[i].dest_path, "%s/%s", _url_dir, update_cmd[i].name);
209*4882a593Smuzhiyun }
210*4882a593Smuzhiyun } else {
211*4882a593Smuzhiyun if (strcmp(update_cmd[i].name, "parameter") == 0) {
212*4882a593Smuzhiyun sprintf(update_cmd[i].dest_path, "/dev/block/by-name/gpt");
213*4882a593Smuzhiyun } else {
214*4882a593Smuzhiyun if (!isMtdDevice()) {
215*4882a593Smuzhiyun sprintf(update_cmd[i].dest_path, "/dev/block/by-name/%s", update_cmd[i].name);
216*4882a593Smuzhiyun } else {
217*4882a593Smuzhiyun if ( update_cmd[i].need_update && (mtd_scan_partitions() > 0) ) {
218*4882a593Smuzhiyun const MtdPartition *mtdp = mtd_find_partition_by_name(update_cmd[i].name);
219*4882a593Smuzhiyun if (mtdp) {
220*4882a593Smuzhiyun sprintf(update_cmd[i].dest_path, "/dev/mtd%d", mtdp->device_index);
221*4882a593Smuzhiyun LOGI("need update %s ,.dest_path: %s.\n", update_cmd[i].name, update_cmd[i].dest_path);
222*4882a593Smuzhiyun }
223*4882a593Smuzhiyun } else {
224*4882a593Smuzhiyun sprintf(update_cmd[i].dest_path, "/dev/block/by-name/%s", update_cmd[i].name);
225*4882a593Smuzhiyun }
226*4882a593Smuzhiyun }
227*4882a593Smuzhiyun }
228*4882a593Smuzhiyun }
229*4882a593Smuzhiyun }
230*4882a593Smuzhiyun partition = (partition << 1);
231*4882a593Smuzhiyun }
232*4882a593Smuzhiyun
233*4882a593Smuzhiyun return true;
234*4882a593Smuzhiyun
235*4882a593Smuzhiyun }
236*4882a593Smuzhiyun
ota_recovery_cmds(long long flash_offset,const char * dest_path)237*4882a593Smuzhiyun static int ota_recovery_cmds (long long flash_offset, const char *dest_path)
238*4882a593Smuzhiyun {
239*4882a593Smuzhiyun char data_buf[256];
240*4882a593Smuzhiyun unsigned int write_count = 0;
241*4882a593Smuzhiyun int fd = -1;
242*4882a593Smuzhiyun if (dest_path == NULL) {
243*4882a593Smuzhiyun LOGE("[%s-%d] error dest path is NULL.\n", __func__, __LINE__);
244*4882a593Smuzhiyun return -1;
245*4882a593Smuzhiyun }
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun LOGI("[%s:%d] parameter flash offset %#llx dest path %s\n", __func__, __LINE__, flash_offset, dest_path);
248*4882a593Smuzhiyun memset(data_buf, 0, sizeof(data_buf) / sizeof(data_buf[0]));
249*4882a593Smuzhiyun
250*4882a593Smuzhiyun if (is_sdboot) {
251*4882a593Smuzhiyun fd = open(CMD4RECOVERY_FILENAME, O_CREAT | O_RDWR | O_SYNC | O_APPEND, 0644);
252*4882a593Smuzhiyun if (fd < 0) {
253*4882a593Smuzhiyun LOGE("[%s-%d] error opening %s.\n", __func__, __LINE__, CMD4RECOVERY_FILENAME);
254*4882a593Smuzhiyun return -1;
255*4882a593Smuzhiyun }
256*4882a593Smuzhiyun } else if (is_usbboot) {
257*4882a593Smuzhiyun fd = open(CMD4RECOVERY_UDISK_FILENAME, O_CREAT | O_RDWR | O_SYNC | O_APPEND, 0644);
258*4882a593Smuzhiyun if (fd < 0) {
259*4882a593Smuzhiyun LOGE("[%s-%d] error opening %s.\n", __func__, __LINE__, CMD4RECOVERY_UDISK_FILENAME);
260*4882a593Smuzhiyun return -1;
261*4882a593Smuzhiyun }
262*4882a593Smuzhiyun }
263*4882a593Smuzhiyun
264*4882a593Smuzhiyun if (isMtdDevice()) {
265*4882a593Smuzhiyun sprintf(data_buf, "nandwrite -p /dev/mtd0 -s %#llx %s; \n", flash_offset, dest_path);
266*4882a593Smuzhiyun } else {
267*4882a593Smuzhiyun char flash_name[20];
268*4882a593Smuzhiyun getFlashPoint(flash_name);
269*4882a593Smuzhiyun
270*4882a593Smuzhiyun #define DD_MALLOC_MAX_SIZE (0x100000*10) /* 10MB */
271*4882a593Smuzhiyun
272*4882a593Smuzhiyun unsigned int dd_bs = 0;
273*4882a593Smuzhiyun long long dd_seek = 1;
274*4882a593Smuzhiyun
275*4882a593Smuzhiyun for ( int j = DD_MALLOC_MAX_SIZE / SECTOR_SIZE; j > 0 ; j-- ) {
276*4882a593Smuzhiyun dd_bs = j * SECTOR_SIZE;
277*4882a593Smuzhiyun if ( !(flash_offset % dd_bs) ) {
278*4882a593Smuzhiyun dd_seek = flash_offset / dd_bs;
279*4882a593Smuzhiyun LOGI( "flash offset = [%#llx] j=%d bs=%#x seek = %#llx result = [%s]\n",
280*4882a593Smuzhiyun flash_offset, j, dd_bs, dd_seek, (dd_bs * dd_seek == flash_offset) ? "YES" : "NO" );
281*4882a593Smuzhiyun break;
282*4882a593Smuzhiyun } else {
283*4882a593Smuzhiyun dd_bs = 1;
284*4882a593Smuzhiyun dd_seek = flash_offset;
285*4882a593Smuzhiyun }
286*4882a593Smuzhiyun }
287*4882a593Smuzhiyun sprintf(data_buf, "dd of=%s if=%s bs=%d seek=%lld; \t###flash offset [%#10llx] \n", flash_name, dest_path, dd_bs, dd_seek, flash_offset);
288*4882a593Smuzhiyun }
289*4882a593Smuzhiyun
290*4882a593Smuzhiyun write_count = strlen(data_buf);
291*4882a593Smuzhiyun
292*4882a593Smuzhiyun if (write(fd, data_buf, write_count) != write_count) {
293*4882a593Smuzhiyun close(fd);
294*4882a593Smuzhiyun LOGE("[%s:%d] Write failed(%s)\n", __func__, __LINE__, strerror(errno));
295*4882a593Smuzhiyun return -2;
296*4882a593Smuzhiyun }
297*4882a593Smuzhiyun
298*4882a593Smuzhiyun close(fd);
299*4882a593Smuzhiyun return 0;
300*4882a593Smuzhiyun }
301*4882a593Smuzhiyun
RK_ota_start(RK_upgrade_callback cb,RK_print_callback print_cb)302*4882a593Smuzhiyun void RK_ota_start(RK_upgrade_callback cb, RK_print_callback print_cb)
303*4882a593Smuzhiyun {
304*4882a593Smuzhiyun LOGI("start RK_ota_start.\n");
305*4882a593Smuzhiyun processvalue = 95;
306*4882a593Smuzhiyun cb(NULL, RK_UPGRADE_START);
307*4882a593Smuzhiyun
308*4882a593Smuzhiyun //确认升级路径
309*4882a593Smuzhiyun if (_url == NULL) {
310*4882a593Smuzhiyun LOGE("url is NULL\n");
311*4882a593Smuzhiyun cb(NULL, RK_UPGRADE_ERR);
312*4882a593Smuzhiyun return ;
313*4882a593Smuzhiyun }
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun // 1. 获取文件
316*4882a593Smuzhiyun int res = download_file(_url, _save_path);
317*4882a593Smuzhiyun if (res == 0) {
318*4882a593Smuzhiyun _url = (char *)_save_path;
319*4882a593Smuzhiyun } else if (res == -1) {
320*4882a593Smuzhiyun LOGE("download_file error.\n");
321*4882a593Smuzhiyun cb(NULL, RK_UPGRADE_ERR);
322*4882a593Smuzhiyun return ;
323*4882a593Smuzhiyun }
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun // 2. 获取文件信息
326*4882a593Smuzhiyun if (!RK_ota_set_partition(-1)) {
327*4882a593Smuzhiyun LOGE("RK_ota_set_partition failed.\n");
328*4882a593Smuzhiyun cb(NULL, RK_UPGRADE_ERR);
329*4882a593Smuzhiyun return ;
330*4882a593Smuzhiyun }
331*4882a593Smuzhiyun
332*4882a593Smuzhiyun STRUCT_PARAM_ITEM param_item[20] = {0};
333*4882a593Smuzhiyun long long gpt_backup_offset = -1;
334*4882a593Smuzhiyun memset(param_item, 0, sizeof(param_item));
335*4882a593Smuzhiyun flash_register_partition_data(param_item, &gpt_backup_offset);
336*4882a593Smuzhiyun
337*4882a593Smuzhiyun int is_mtd_flag = isMtdDevice();
338*4882a593Smuzhiyun
339*4882a593Smuzhiyun // 3. 下载文件到分区并校验
340*4882a593Smuzhiyun int num = sizeof(update_cmd) / sizeof(UPDATE_CMD);
341*4882a593Smuzhiyun char prompt[128] = {0};
342*4882a593Smuzhiyun for (int i = 0; i < num; i++ ) {
343*4882a593Smuzhiyun if (update_cmd[i].need_update) {
344*4882a593Smuzhiyun if (update_cmd[i].cmd != NULL) {
345*4882a593Smuzhiyun LOGI("now write %s to %s.\n", update_cmd[i].name, update_cmd[i].dest_path);
346*4882a593Smuzhiyun sprintf(prompt, "[%s] upgrade start...\n", update_cmd[i].name);
347*4882a593Smuzhiyun print_cb(prompt);
348*4882a593Smuzhiyun if (!is_sdboot && !is_usbboot &&
349*4882a593Smuzhiyun ( (strcmp(update_cmd[i].name, "misc") == 0) ||
350*4882a593Smuzhiyun (strcmp(update_cmd[i].name, "parameter") == 0) )) {
351*4882a593Smuzhiyun LOGI("ingore misc.\n");
352*4882a593Smuzhiyun continue;
353*4882a593Smuzhiyun }
354*4882a593Smuzhiyun // 下载固件到分区
355*4882a593Smuzhiyun LOGI("update_cmd.flash_offset = %lld.\n", update_cmd[i].flash_offset);
356*4882a593Smuzhiyun if (update_cmd[i].cmd(_url, (void*)(&update_cmd[i])) != 0) {
357*4882a593Smuzhiyun LOGE("update %s error.\n", update_cmd[i].dest_path);
358*4882a593Smuzhiyun sprintf(prompt, "[%s] upgrade fail\n", update_cmd[i].name);
359*4882a593Smuzhiyun print_cb(prompt);
360*4882a593Smuzhiyun cb(NULL, RK_UPGRADE_ERR);
361*4882a593Smuzhiyun return ;
362*4882a593Smuzhiyun } else {
363*4882a593Smuzhiyun sprintf(prompt, "[%s] upgraede success!\n", update_cmd[i].name);
364*4882a593Smuzhiyun print_cb(prompt);
365*4882a593Smuzhiyun }
366*4882a593Smuzhiyun if (is_sdboot) {
367*4882a593Smuzhiyun if (ota_recovery_cmds(update_cmd[i].flash_offset, update_cmd[i].dest_path)) {
368*4882a593Smuzhiyun LOGE("write recovery cmds to %s failed.\n", CMD4RECOVERY_FILENAME);
369*4882a593Smuzhiyun cb(NULL, RK_UPGRADE_ERR);
370*4882a593Smuzhiyun return ;
371*4882a593Smuzhiyun }
372*4882a593Smuzhiyun LOGI("not check in sdboot (sdcard).\n");
373*4882a593Smuzhiyun continue;
374*4882a593Smuzhiyun } else if (is_usbboot) {
375*4882a593Smuzhiyun if (ota_recovery_cmds(update_cmd[i].flash_offset, update_cmd[i].dest_path)) {
376*4882a593Smuzhiyun LOGE("write recovery cmds to %s failed.\n", CMD4RECOVERY_UDISK_FILENAME);
377*4882a593Smuzhiyun cb(NULL, RK_UPGRADE_ERR);
378*4882a593Smuzhiyun return ;
379*4882a593Smuzhiyun }
380*4882a593Smuzhiyun LOGI("not check in usb storage (udisk).\n");
381*4882a593Smuzhiyun continue;
382*4882a593Smuzhiyun }
383*4882a593Smuzhiyun // parameter 和loader 先不校验
384*4882a593Smuzhiyun if (strcmp(update_cmd[i].name, "parameter") == 0 || strcmp(update_cmd[i].name, "bootloader") == 0) {
385*4882a593Smuzhiyun LOGI("not check parameter and loader.\n");
386*4882a593Smuzhiyun continue;
387*4882a593Smuzhiyun }
388*4882a593Smuzhiyun // 校验分区
389*4882a593Smuzhiyun if (!update_cmd[i].skip_verify &&
390*4882a593Smuzhiyun comparefile(update_cmd[i].dest_path, _url,
391*4882a593Smuzhiyun update_cmd[i].flash_offset,
392*4882a593Smuzhiyun update_cmd[i].offset, update_cmd[i].size)) {
393*4882a593Smuzhiyun LOGI("check %s ok.\n", update_cmd[i].dest_path);
394*4882a593Smuzhiyun } else if (!update_cmd[i].skip_verify) {
395*4882a593Smuzhiyun LOGE("check %s failed.\n", update_cmd[i].dest_path);
396*4882a593Smuzhiyun cb(NULL, RK_UPGRADE_ERR);
397*4882a593Smuzhiyun return ;
398*4882a593Smuzhiyun }
399*4882a593Smuzhiyun }
400*4882a593Smuzhiyun }
401*4882a593Smuzhiyun }
402*4882a593Smuzhiyun
403*4882a593Smuzhiyun /*
404*4882a593Smuzhiyun * Fix if update_xxx.img not found some A/B partition image.
405*4882a593Smuzhiyun */
406*4882a593Smuzhiyun if (is_sdboot || is_usbboot) {
407*4882a593Smuzhiyun for (int i = 0; i < num; i++) {
408*4882a593Smuzhiyun if ( (!update_cmd[i].need_update) || (update_cmd[i].cmd == NULL)) {
409*4882a593Smuzhiyun continue;
410*4882a593Smuzhiyun }
411*4882a593Smuzhiyun unsigned char len = strlen(update_cmd[i].name);
412*4882a593Smuzhiyun if (update_cmd[i].name[len - 2] == '_' && (update_cmd[i].name[len - 1] == 'a' || update_cmd[i].name[len - 1] == 'b') ) {
413*4882a593Smuzhiyun char slot_find = (update_cmd[i].name[len - 1] == 'a') ? 'b' : 'a';
414*4882a593Smuzhiyun int part_need_fix = 1;
415*4882a593Smuzhiyun char part_name[32];
416*4882a593Smuzhiyun memset(part_name, 0, sizeof(part_name) / sizeof(part_name[0]));
417*4882a593Smuzhiyun memcpy(part_name, update_cmd[i].name, len);
418*4882a593Smuzhiyun part_name[len - 1] = slot_find;
419*4882a593Smuzhiyun
420*4882a593Smuzhiyun for (int k = 0; k < num; k++) {
421*4882a593Smuzhiyun if ( (!update_cmd[k].need_update) || (update_cmd[k].cmd == NULL)) {
422*4882a593Smuzhiyun continue;
423*4882a593Smuzhiyun }
424*4882a593Smuzhiyun if ( (strcmp(update_cmd[k].name, part_name) == 0) ) {
425*4882a593Smuzhiyun part_need_fix = 0;
426*4882a593Smuzhiyun }
427*4882a593Smuzhiyun }
428*4882a593Smuzhiyun
429*4882a593Smuzhiyun if (part_need_fix) {
430*4882a593Smuzhiyun for (int j = 0; j < sizeof(param_item) / sizeof(param_item[0]); j++) {
431*4882a593Smuzhiyun if (strcmp(param_item[j].name, part_name) == 0) {
432*4882a593Smuzhiyun if (ota_recovery_cmds(param_item[j].offset * SECTOR_SIZE, update_cmd[i].dest_path)) {
433*4882a593Smuzhiyun LOGE("sdboot fix write recovery cmds to %s failed.\n", CMD4RECOVERY_FILENAME);
434*4882a593Smuzhiyun cb(NULL, RK_UPGRADE_ERR);
435*4882a593Smuzhiyun return ;
436*4882a593Smuzhiyun }
437*4882a593Smuzhiyun }
438*4882a593Smuzhiyun }
439*4882a593Smuzhiyun }
440*4882a593Smuzhiyun }
441*4882a593Smuzhiyun }
442*4882a593Smuzhiyun
443*4882a593Smuzhiyun // write gpt backup
444*4882a593Smuzhiyun /*
445*4882a593Smuzhiyun * char gpt_backup_img_path[100] = {0};
446*4882a593Smuzhiyun * sprintf(gpt_backup_img_path, "%s/%s", _url_dir, GPT_BACKUP_FILE_NAME);
447*4882a593Smuzhiyun * if (ota_recovery_cmds(gpt_backup_offset, gpt_backup_img_path)) {
448*4882a593Smuzhiyun * LOGE("write gpt backup to recovery cmds failed (%s).\n", gpt_backup_img_path);
449*4882a593Smuzhiyun * cb(NULL, RK_UPGRADE_ERR);
450*4882a593Smuzhiyun * return ;
451*4882a593Smuzhiyun * }
452*4882a593Smuzhiyun */
453*4882a593Smuzhiyun
454*4882a593Smuzhiyun }
455*4882a593Smuzhiyun
456*4882a593Smuzhiyun // 4. 是否设置misc
457*4882a593Smuzhiyun
458*4882a593Smuzhiyun LOGI("RK_ota_start is ok!");
459*4882a593Smuzhiyun processvalue = 100;
460*4882a593Smuzhiyun cb(NULL, RK_UPGRADE_FINISHED);
461*4882a593Smuzhiyun print_cb((char *)"updateEngine upgrade OK!\n");
462*4882a593Smuzhiyun
463*4882a593Smuzhiyun /* We're successful upgraded, Remove the done_file(see flash_image.cpp) if exist. */
464*4882a593Smuzhiyun {
465*4882a593Smuzhiyun char done_file[256];
466*4882a593Smuzhiyun snprintf(done_file, 256, "%s.done", _url);
467*4882a593Smuzhiyun unlink(done_file);
468*4882a593Smuzhiyun }
469*4882a593Smuzhiyun }
470*4882a593Smuzhiyun
RK_ota_get_progress()471*4882a593Smuzhiyun int RK_ota_get_progress()
472*4882a593Smuzhiyun {
473*4882a593Smuzhiyun return processvalue;
474*4882a593Smuzhiyun }
475*4882a593Smuzhiyun
RK_ota_get_sw_version(char * buffer,int maxLength)476*4882a593Smuzhiyun void RK_ota_get_sw_version(char *buffer, int maxLength)
477*4882a593Smuzhiyun {
478*4882a593Smuzhiyun getLocalVersion(buffer, maxLength);
479*4882a593Smuzhiyun }
480*4882a593Smuzhiyun
RK_ota_check_version(char * url)481*4882a593Smuzhiyun bool RK_ota_check_version(char *url)
482*4882a593Smuzhiyun {
483*4882a593Smuzhiyun char source_version[20] = {0};
484*4882a593Smuzhiyun char target_version[20] = {0};
485*4882a593Smuzhiyun if (!getLocalVersion(source_version, sizeof(source_version))) {
486*4882a593Smuzhiyun return false;
487*4882a593Smuzhiyun }
488*4882a593Smuzhiyun
489*4882a593Smuzhiyun if (strncmp(url, "http", 4) == 0) {
490*4882a593Smuzhiyun //如果是远程文件,从远程获取版本号
491*4882a593Smuzhiyun if (!getRemoteVersion(url, target_version, sizeof(target_version))) {
492*4882a593Smuzhiyun return false;
493*4882a593Smuzhiyun }
494*4882a593Smuzhiyun } else {
495*4882a593Smuzhiyun //如果是本地文件,从固件获取版本号
496*4882a593Smuzhiyun if (!getImageVersion(url, target_version, sizeof(target_version))) {
497*4882a593Smuzhiyun return false;
498*4882a593Smuzhiyun }
499*4882a593Smuzhiyun }
500*4882a593Smuzhiyun
501*4882a593Smuzhiyun LOGI("check version new:%s old:%s", target_version, source_version);
502*4882a593Smuzhiyun if (strcmp(target_version, source_version) > 0) {
503*4882a593Smuzhiyun return true;
504*4882a593Smuzhiyun }
505*4882a593Smuzhiyun return false;
506*4882a593Smuzhiyun }
507