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