xref: /OK3568_Linux_fs/external/recovery/update_engine/rktools.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 <stdio.h>
18*4882a593Smuzhiyun #include <unistd.h>
19*4882a593Smuzhiyun #include <string.h>
20*4882a593Smuzhiyun #include <errno.h>
21*4882a593Smuzhiyun #include <stdlib.h>
22*4882a593Smuzhiyun #include <sys/types.h>
23*4882a593Smuzhiyun #include <sys/stat.h>
24*4882a593Smuzhiyun #include <fcntl.h>
25*4882a593Smuzhiyun #include <stdbool.h>
26*4882a593Smuzhiyun #include "log.h"
27*4882a593Smuzhiyun #include "rktools.h"
28*4882a593Smuzhiyun #include "download.h"
29*4882a593Smuzhiyun #include "../mtdutils/mtdutils.h"
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun 
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun #define LOCAL_VERSION_PATH "/etc/version"
34*4882a593Smuzhiyun #define DOWNLOAD_VERSION_PATH "/tmp/version"
35*4882a593Smuzhiyun 
getVersionFromfile(const char * filepath,char * version,int maxLength)36*4882a593Smuzhiyun bool getVersionFromfile(const char * filepath, char *version, int maxLength)
37*4882a593Smuzhiyun {
38*4882a593Smuzhiyun     if (version == NULL || filepath == NULL) {
39*4882a593Smuzhiyun         LOGE("getLocalVersion is error, version == null.\n");
40*4882a593Smuzhiyun         return false;
41*4882a593Smuzhiyun     }
42*4882a593Smuzhiyun     FILE *fp = fopen(filepath, "r");
43*4882a593Smuzhiyun     if (fp == NULL) {
44*4882a593Smuzhiyun         LOGE("open %s failed, error is %s.\n", filepath, strerror(errno));
45*4882a593Smuzhiyun         return false;
46*4882a593Smuzhiyun     }
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun     char *line = NULL;
49*4882a593Smuzhiyun     size_t len = 0;
50*4882a593Smuzhiyun     size_t read;
51*4882a593Smuzhiyun     while ((read = getline(&line, &len, fp)) != -1) {
52*4882a593Smuzhiyun         if (read == 0 || line[0] == '#') {
53*4882a593Smuzhiyun             continue;
54*4882a593Smuzhiyun         }
55*4882a593Smuzhiyun         char *pline = strstr(line, "RK_VERSION");
56*4882a593Smuzhiyun         if (pline != NULL && (pline = strstr(pline, "=")) != NULL) {
57*4882a593Smuzhiyun             pline++; //过滤掉等于号
58*4882a593Smuzhiyun             //过滤掉空格
59*4882a593Smuzhiyun             while (*pline == ' ') {
60*4882a593Smuzhiyun                 pline++;
61*4882a593Smuzhiyun             }
62*4882a593Smuzhiyun             int pline_len = strlen(pline) - 1;
63*4882a593Smuzhiyun             int version_len = (pline_len > maxLength ? maxLength : pline_len);
64*4882a593Smuzhiyun             memcpy(version, pline, version_len);
65*4882a593Smuzhiyun             LOGI("version = %s.\n", version);
66*4882a593Smuzhiyun             break;
67*4882a593Smuzhiyun         }
68*4882a593Smuzhiyun     }
69*4882a593Smuzhiyun     free(line);
70*4882a593Smuzhiyun     fclose(fp);
71*4882a593Smuzhiyun     return true;
72*4882a593Smuzhiyun }
73*4882a593Smuzhiyun 
74*4882a593Smuzhiyun //下载服务器版本号文件
getRemoteVersion(char * url,char * version,int maxLength)75*4882a593Smuzhiyun bool getRemoteVersion(char *url, char *version, int maxLength)
76*4882a593Smuzhiyun {
77*4882a593Smuzhiyun     if (url == NULL) {
78*4882a593Smuzhiyun         LOGE("getRemoteVersion url is null.\n");
79*4882a593Smuzhiyun         return false;
80*4882a593Smuzhiyun     }
81*4882a593Smuzhiyun 
82*4882a593Smuzhiyun     if (download_file(url, DOWNLOAD_VERSION_PATH) == -1) {
83*4882a593Smuzhiyun         LOGE("getRemoteVersion failed, url is %s.\n", url);
84*4882a593Smuzhiyun         return false;
85*4882a593Smuzhiyun     }
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun     return getVersionFromfile(DOWNLOAD_VERSION_PATH, version, maxLength);
88*4882a593Smuzhiyun }
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun //获取本地版本号
getLocalVersion(char * version,int maxLength)91*4882a593Smuzhiyun bool getLocalVersion(char *version, int maxLength)
92*4882a593Smuzhiyun {
93*4882a593Smuzhiyun     return getVersionFromfile(LOCAL_VERSION_PATH, version, maxLength);
94*4882a593Smuzhiyun }
95*4882a593Smuzhiyun 
96*4882a593Smuzhiyun //判断是MTD还是block 设备
isMtdDevice()97*4882a593Smuzhiyun bool isMtdDevice()
98*4882a593Smuzhiyun {
99*4882a593Smuzhiyun     char param[2048];
100*4882a593Smuzhiyun     int fd, ret;
101*4882a593Smuzhiyun     char *s = NULL;
102*4882a593Smuzhiyun     fd = open("/proc/cmdline", O_RDONLY);
103*4882a593Smuzhiyun     ret = read(fd, (char*)param, 2048);
104*4882a593Smuzhiyun     close(fd);
105*4882a593Smuzhiyun     s = strstr(param, "storagemedia");
106*4882a593Smuzhiyun     if (s == NULL) {
107*4882a593Smuzhiyun         LOGI("no found storagemedia in cmdline, default is not MTD.\n");
108*4882a593Smuzhiyun         return false;
109*4882a593Smuzhiyun     } else {
110*4882a593Smuzhiyun         s = strstr(s, "=");
111*4882a593Smuzhiyun         if (s == NULL) {
112*4882a593Smuzhiyun             LOGI("no found storagemedia in cmdline, default is not MTD.\n");
113*4882a593Smuzhiyun             return false;
114*4882a593Smuzhiyun         }
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun         s++;
117*4882a593Smuzhiyun         while (*s == ' ') {
118*4882a593Smuzhiyun             s++;
119*4882a593Smuzhiyun         }
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun         if (strncmp(s, "mtd", 3) == 0 ) {
122*4882a593Smuzhiyun             LOGI("Now is MTD.\n");
123*4882a593Smuzhiyun             return true;
124*4882a593Smuzhiyun         } else if (strncmp(s, "sd", 2) == 0) {
125*4882a593Smuzhiyun             LOGI("Now is SD.\n");
126*4882a593Smuzhiyun             if ( !access(MTD_PATH, F_OK) ) {
127*4882a593Smuzhiyun                 fd = open(MTD_PATH, O_RDONLY);
128*4882a593Smuzhiyun                 ret = read(fd, (char*)param, 2048);
129*4882a593Smuzhiyun                 close(fd);
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun                 s = strstr(param, "mtd");
132*4882a593Smuzhiyun                 if (s == NULL) {
133*4882a593Smuzhiyun                     LOGI("no found mtd.\n");
134*4882a593Smuzhiyun                     return false;
135*4882a593Smuzhiyun                 }
136*4882a593Smuzhiyun                 LOGI("Now is MTD.\n");
137*4882a593Smuzhiyun                 return true;
138*4882a593Smuzhiyun             }
139*4882a593Smuzhiyun         }
140*4882a593Smuzhiyun     }
141*4882a593Smuzhiyun     LOGI("Current device is not MTD\n");
142*4882a593Smuzhiyun     return false;
143*4882a593Smuzhiyun }
144*4882a593Smuzhiyun 
145*4882a593Smuzhiyun /**
146*4882a593Smuzhiyun  * 从cmdline 获取从哪里引导
147*4882a593Smuzhiyun  * 返回值:
148*4882a593Smuzhiyun  *     0: a分区
149*4882a593Smuzhiyun  *     1: b分区
150*4882a593Smuzhiyun  *    -1: recovery 模式
151*4882a593Smuzhiyun  */
getCurrentSlot()152*4882a593Smuzhiyun int getCurrentSlot()
153*4882a593Smuzhiyun {
154*4882a593Smuzhiyun     char cmdline[CMDLINE_LENGTH];
155*4882a593Smuzhiyun     int fd = open("/proc/cmdline", O_RDONLY);
156*4882a593Smuzhiyun     if (read(fd, (char*)cmdline, CMDLINE_LENGTH) < 1) {
157*4882a593Smuzhiyun         close(fd);
158*4882a593Smuzhiyun         return -1;
159*4882a593Smuzhiyun     }
160*4882a593Smuzhiyun     close(fd);
161*4882a593Smuzhiyun     char *slot = strstr(cmdline, "android_slotsufix");
162*4882a593Smuzhiyun     if (slot == NULL) slot = strstr(cmdline, "androidboot.slot_suffix");
163*4882a593Smuzhiyun     if (slot != NULL) {
164*4882a593Smuzhiyun         slot = strstr(slot, "=");
165*4882a593Smuzhiyun         if (slot != NULL && *(++slot) == '_') {
166*4882a593Smuzhiyun             slot += 1;
167*4882a593Smuzhiyun             LOGI("Current Mode is '%c' system.\n", (*slot == 'a') ? 'A' : 'B');
168*4882a593Smuzhiyun             if ((*slot) == 'a') {
169*4882a593Smuzhiyun                 return 0;
170*4882a593Smuzhiyun             } else if ((*slot) == 'b') {
171*4882a593Smuzhiyun                 return 1;
172*4882a593Smuzhiyun             }
173*4882a593Smuzhiyun         }
174*4882a593Smuzhiyun     }
175*4882a593Smuzhiyun     LOGI("Current Mode is recovery.\n");
176*4882a593Smuzhiyun     return -1;
177*4882a593Smuzhiyun }
178*4882a593Smuzhiyun 
getFlashPoint(char * path)179*4882a593Smuzhiyun void getFlashPoint(char *path)
180*4882a593Smuzhiyun {
181*4882a593Smuzhiyun     char *emmc_point = getenv(EMMC_POINT_NAME);
182*4882a593Smuzhiyun     LOGI("test Current device is emmc : %s.\n", emmc_point);
183*4882a593Smuzhiyun     if ( !access(emmc_point, F_OK) ) {
184*4882a593Smuzhiyun         LOGI("Current device is emmc : %s.\n", emmc_point);
185*4882a593Smuzhiyun         strcpy(path, emmc_point);
186*4882a593Smuzhiyun     } else if (strncmp("emmc", getenv("storagemedia"), 4) == 0) {
187*4882a593Smuzhiyun         LOGI("Current device is emmc : /dev/mmcblk0.\n");
188*4882a593Smuzhiyun         strcpy(path, "/dev/mmcblk0");
189*4882a593Smuzhiyun     } else {
190*4882a593Smuzhiyun         LOGI("Current device is nand : %s.\n", NAND_DRIVER_DEV_LBA);
191*4882a593Smuzhiyun         strcpy(path, NAND_DRIVER_DEV_LBA);
192*4882a593Smuzhiyun     }
193*4882a593Smuzhiyun }
194*4882a593Smuzhiyun /*
195*4882a593Smuzhiyun  * 获得flash 的大小,和块数
196*4882a593Smuzhiyun  */
getFlashSize(char * path,long long * flash_size,long long * block_num)197*4882a593Smuzhiyun int getFlashSize(char *path, long long* flash_size, long long* block_num)
198*4882a593Smuzhiyun {
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun     LOGI("[%s:%d]\n", __func__, __LINE__);
201*4882a593Smuzhiyun 
202*4882a593Smuzhiyun     off64_t total_size_64 = 0;
203*4882a593Smuzhiyun     if (isMtdDevice()) {
204*4882a593Smuzhiyun         size_t erase_size;
205*4882a593Smuzhiyun         size_t total_size;
206*4882a593Smuzhiyun         mtd_scan_partitions();
207*4882a593Smuzhiyun         const MtdPartition *part = mtd_find_partition_by_name("rk-nand");
208*4882a593Smuzhiyun         if ( part == NULL ) {
209*4882a593Smuzhiyun             part = mtd_find_partition_by_name("spi-nand0");
210*4882a593Smuzhiyun         }
211*4882a593Smuzhiyun         if (part == NULL || mtd_partition_info(part, &total_size, &erase_size, NULL)) {
212*4882a593Smuzhiyun             LOGE("Can't find rk-nand or spi-nand0\n");
213*4882a593Smuzhiyun             return -1;
214*4882a593Smuzhiyun         }
215*4882a593Smuzhiyun         total_size = total_size - (erase_size * 4);
216*4882a593Smuzhiyun         total_size_64 = total_size;
217*4882a593Smuzhiyun     } else {
218*4882a593Smuzhiyun         char flash_name[20];
219*4882a593Smuzhiyun         getFlashPoint(flash_name);
220*4882a593Smuzhiyun         int fd_dest = open(flash_name, O_RDWR | O_LARGEFILE);
221*4882a593Smuzhiyun         if (fd_dest < 0) {
222*4882a593Smuzhiyun             LOGE("Can't open %s\n", flash_name);
223*4882a593Smuzhiyun             return -2;
224*4882a593Smuzhiyun         }
225*4882a593Smuzhiyun         if ((total_size_64 = lseek64(fd_dest, 0, SEEK_END)) == -1) {
226*4882a593Smuzhiyun             LOGE("getFlashInfo lseek64 failed.\n");
227*4882a593Smuzhiyun             close(fd_dest);
228*4882a593Smuzhiyun             return -2;
229*4882a593Smuzhiyun         }
230*4882a593Smuzhiyun         lseek64(fd_dest, 0, SEEK_SET);
231*4882a593Smuzhiyun         close(fd_dest);
232*4882a593Smuzhiyun     }
233*4882a593Smuzhiyun     if ( flash_size ) {
234*4882a593Smuzhiyun         *flash_size = total_size_64 / 1024; //Kib
235*4882a593Smuzhiyun         LOGI("[%s:%d] flash size [%lld] \n", __func__, __LINE__, *flash_size);
236*4882a593Smuzhiyun     }
237*4882a593Smuzhiyun     if ( block_num ) {
238*4882a593Smuzhiyun         *block_num = (total_size_64 / 1024) * 2;
239*4882a593Smuzhiyun         LOGI("[%s:%d]  block num [%lld]\n", __func__, __LINE__, *block_num);
240*4882a593Smuzhiyun     }
241*4882a593Smuzhiyun 
242*4882a593Smuzhiyun     return 0;
243*4882a593Smuzhiyun }
244*4882a593Smuzhiyun 
getFlashInfo(size_t * total_size,size_t * block_size,size_t * page_size)245*4882a593Smuzhiyun int getFlashInfo (size_t *total_size, size_t *block_size, size_t *page_size)
246*4882a593Smuzhiyun {
247*4882a593Smuzhiyun     if (isMtdDevice()) {
248*4882a593Smuzhiyun         if (mtd_get_flash_info(total_size, block_size, page_size) != 0) {
249*4882a593Smuzhiyun             LOGE("%s-%d: get mtd info error\n", __func__, __LINE__);
250*4882a593Smuzhiyun             return -1;
251*4882a593Smuzhiyun         }
252*4882a593Smuzhiyun         return 0;
253*4882a593Smuzhiyun     } else {
254*4882a593Smuzhiyun         LOGI("[%s:%d]\n", __func__, __LINE__);
255*4882a593Smuzhiyun         if (total_size) {
256*4882a593Smuzhiyun             LOGE("%s-%d: get flash total size error. NOT support now.\n", __func__, __LINE__);
257*4882a593Smuzhiyun             return -1;
258*4882a593Smuzhiyun         }
259*4882a593Smuzhiyun         if (block_size) *block_size = 512 * 1024;
260*4882a593Smuzhiyun         if (page_size) *page_size = 2 * 1024;
261*4882a593Smuzhiyun         return 0;
262*4882a593Smuzhiyun     }
263*4882a593Smuzhiyun }
264