2025-05-10 21:49:39 +08:00

264 lines
7.5 KiB
C

/*
* Copyright (C) 2023 Rockchip Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdbool.h>
#include "log.h"
#include "rktools.h"
#include "download.h"
#include "../mtdutils/mtdutils.h"
#define LOCAL_VERSION_PATH "/etc/version"
#define DOWNLOAD_VERSION_PATH "/tmp/version"
bool getVersionFromfile(const char * filepath, char *version, int maxLength)
{
if (version == NULL || filepath == NULL) {
LOGE("getLocalVersion is error, version == null.\n");
return false;
}
FILE *fp = fopen(filepath, "r");
if (fp == NULL) {
LOGE("open %s failed, error is %s.\n", filepath, strerror(errno));
return false;
}
char *line = NULL;
size_t len = 0;
size_t read;
while ((read = getline(&line, &len, fp)) != -1) {
if (read == 0 || line[0] == '#') {
continue;
}
char *pline = strstr(line, "RK_VERSION");
if (pline != NULL && (pline = strstr(pline, "=")) != NULL) {
pline++; //过滤掉等于号
//过滤掉空格
while (*pline == ' ') {
pline++;
}
int pline_len = strlen(pline) - 1;
int version_len = (pline_len > maxLength ? maxLength : pline_len);
memcpy(version, pline, version_len);
LOGI("version = %s.\n", version);
break;
}
}
free(line);
fclose(fp);
return true;
}
//下载服务器版本号文件
bool getRemoteVersion(char *url, char *version, int maxLength)
{
if (url == NULL) {
LOGE("getRemoteVersion url is null.\n");
return false;
}
if (download_file(url, DOWNLOAD_VERSION_PATH) == -1) {
LOGE("getRemoteVersion failed, url is %s.\n", url);
return false;
}
return getVersionFromfile(DOWNLOAD_VERSION_PATH, version, maxLength);
}
//获取本地版本号
bool getLocalVersion(char *version, int maxLength)
{
return getVersionFromfile(LOCAL_VERSION_PATH, version, maxLength);
}
//判断是MTD还是block 设备
bool isMtdDevice()
{
char param[2048];
int fd, ret;
char *s = NULL;
fd = open("/proc/cmdline", O_RDONLY);
ret = read(fd, (char*)param, 2048);
close(fd);
s = strstr(param, "storagemedia");
if (s == NULL) {
LOGI("no found storagemedia in cmdline, default is not MTD.\n");
return false;
} else {
s = strstr(s, "=");
if (s == NULL) {
LOGI("no found storagemedia in cmdline, default is not MTD.\n");
return false;
}
s++;
while (*s == ' ') {
s++;
}
if (strncmp(s, "mtd", 3) == 0 ) {
LOGI("Now is MTD.\n");
return true;
} else if (strncmp(s, "sd", 2) == 0) {
LOGI("Now is SD.\n");
if ( !access(MTD_PATH, F_OK) ) {
fd = open(MTD_PATH, O_RDONLY);
ret = read(fd, (char*)param, 2048);
close(fd);
s = strstr(param, "mtd");
if (s == NULL) {
LOGI("no found mtd.\n");
return false;
}
LOGI("Now is MTD.\n");
return true;
}
}
}
LOGI("Current device is not MTD\n");
return false;
}
/**
* 从cmdline 获取从哪里引导
* 返回值:
* 0: a分区
* 1: b分区
* -1: recovery 模式
*/
int getCurrentSlot()
{
char cmdline[CMDLINE_LENGTH];
int fd = open("/proc/cmdline", O_RDONLY);
if (read(fd, (char*)cmdline, CMDLINE_LENGTH) < 1) {
close(fd);
return -1;
}
close(fd);
char *slot = strstr(cmdline, "android_slotsufix");
if (slot == NULL) slot = strstr(cmdline, "androidboot.slot_suffix");
if (slot != NULL) {
slot = strstr(slot, "=");
if (slot != NULL && *(++slot) == '_') {
slot += 1;
LOGI("Current Mode is '%c' system.\n", (*slot == 'a') ? 'A' : 'B');
if ((*slot) == 'a') {
return 0;
} else if ((*slot) == 'b') {
return 1;
}
}
}
LOGI("Current Mode is recovery.\n");
return -1;
}
void getFlashPoint(char *path)
{
char *emmc_point = getenv(EMMC_POINT_NAME);
LOGI("test Current device is emmc : %s.\n", emmc_point);
if ( !access(emmc_point, F_OK) ) {
LOGI("Current device is emmc : %s.\n", emmc_point);
strcpy(path, emmc_point);
} else if (strncmp("emmc", getenv("storagemedia"), 4) == 0) {
LOGI("Current device is emmc : /dev/mmcblk0.\n");
strcpy(path, "/dev/mmcblk0");
} else {
LOGI("Current device is nand : %s.\n", NAND_DRIVER_DEV_LBA);
strcpy(path, NAND_DRIVER_DEV_LBA);
}
}
/*
* 获得flash 的大小,和块数
*/
int getFlashSize(char *path, long long* flash_size, long long* block_num)
{
LOGI("[%s:%d]\n", __func__, __LINE__);
off64_t total_size_64 = 0;
if (isMtdDevice()) {
size_t erase_size;
size_t total_size;
mtd_scan_partitions();
const MtdPartition *part = mtd_find_partition_by_name("rk-nand");
if ( part == NULL ) {
part = mtd_find_partition_by_name("spi-nand0");
}
if (part == NULL || mtd_partition_info(part, &total_size, &erase_size, NULL)) {
LOGE("Can't find rk-nand or spi-nand0\n");
return -1;
}
total_size = total_size - (erase_size * 4);
total_size_64 = total_size;
} else {
char flash_name[20];
getFlashPoint(flash_name);
int fd_dest = open(flash_name, O_RDWR | O_LARGEFILE);
if (fd_dest < 0) {
LOGE("Can't open %s\n", flash_name);
return -2;
}
if ((total_size_64 = lseek64(fd_dest, 0, SEEK_END)) == -1) {
LOGE("getFlashInfo lseek64 failed.\n");
close(fd_dest);
return -2;
}
lseek64(fd_dest, 0, SEEK_SET);
close(fd_dest);
}
if ( flash_size ) {
*flash_size = total_size_64 / 1024; //Kib
LOGI("[%s:%d] flash size [%lld] \n", __func__, __LINE__, *flash_size);
}
if ( block_num ) {
*block_num = (total_size_64 / 1024) * 2;
LOGI("[%s:%d] block num [%lld]\n", __func__, __LINE__, *block_num);
}
return 0;
}
int getFlashInfo (size_t *total_size, size_t *block_size, size_t *page_size)
{
if (isMtdDevice()) {
if (mtd_get_flash_info(total_size, block_size, page_size) != 0) {
LOGE("%s-%d: get mtd info error\n", __func__, __LINE__);
return -1;
}
return 0;
} else {
LOGI("[%s:%d]\n", __func__, __LINE__);
if (total_size) {
LOGE("%s-%d: get flash total size error. NOT support now.\n", __func__, __LINE__);
return -1;
}
if (block_size) *block_size = 512 * 1024;
if (page_size) *page_size = 2 * 1024;
return 0;
}
}