xref: /OK3568_Linux_fs/external/recovery/update_engine/update.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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