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