328 lines
12 KiB
C
Raw Normal View History

2025-05-10 21:49:39 +08:00
/*
* 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 <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>
#include <sys/reboot.h>
#include "log.h"
#include "update.h"
#include "../bootloader.h"
#include "../recovery_version.h"
#include "defineHeader.h"
#include "rktools.h"
extern bool is_sdboot;
extern bool is_usbboot;
static bool rkdebug = false;
static char *ui_rotation = NULL;
static const char *update_engine_version = RECOVERY_VERSION_STRING;
RK_Upgrade_Status_t m_status = RK_UPGRADE_ERR;
FILE* cmd_pipe = NULL;
void handle_upgrade_callback(void *user_data, RK_Upgrade_Status_t status)
{
if (status == RK_UPGRADE_FINISHED) {
LOGI("rk ota success.\n");
setSlotActivity();
}
m_status = status;
LOGI("rk m_status = %d.\n", m_status);
}
void handle_print_callback(char *szPrompt)
{
if (cmd_pipe != NULL) {
fprintf(cmd_pipe, "ui_print %s\n", szPrompt);
}
}
static int MiscUpdate(char *url, char *update_partition, char *save_path)
{
int partition;
char *savepath = NULL;
int slot = -1;
if (url == NULL) {
//如果没有传入URL则可以去查找是否有存在
LOGE("MiscUpdate URL must be set.\n");
return -1;
}
slot = getCurrentSlot();
if (update_partition == NULL) {
//没有传入要升级的分区,默认升级
if (slot == -1) {
// recovery mdoe
// u-boot/trust/boot/recovery/boot/rootfs/oem
partition = 0X3F0000;
} else {
// A/B mdoe
// uboot_a/uboot_b/boot_a/boot_b/system_a/system_b
partition = 0XFC00;
}
} else {
partition = strtol(update_partition + 2, NULL, 16);
}
if (save_path == NULL) {
savepath = url;
} else {
savepath = save_path;
}
RK_ota_set_url(url, savepath);
LOGI("url = %s.\n", url);
LOGI("[%s:%d] save path: %s\n", __func__, __LINE__, savepath);
// If it's recovery mode, upgrade recovery in normal system.
if (slot == -1 && !is_sdboot && !is_usbboot) {
if (partition & 0x040000) {
LOGI("update recovery in normal system.\n");
partition = partition & 0xFBFFFF;
// upgrade recoery in normal system
if (!RK_ota_set_partition(0x040000)) {
LOGE("ota file is error.\n");
return -1;
}
RK_ota_start(handle_upgrade_callback, handle_print_callback);
if (m_status != RK_UPGRADE_FINISHED) {
return -1;
}
//写MISC
struct bootloader_message msg;
memset(&msg, 0, sizeof(msg));
char recovery_str[] = "recovery\n--update_package=";
strcpy(msg.command, "boot-recovery");
sprintf(msg.recovery, "%s%s\n", recovery_str, savepath);
memcpy(msg.needupdate, &partition, 4);
if (true == rkdebug) {
strcat(msg.recovery, "--rkdebug\n");
}
if (NULL != ui_rotation) {
strcat(msg.recovery, "--ui_rotation=");
strcat(msg.recovery, ui_rotation);
msg.recovery[strlen(msg.recovery)] = '\n';
}
set_bootloader_message(&msg);
return 0;
}
} else if (slot == 0) {
LOGI("In A system, now upgrade B system.\n");
partition = partition & 0x155ff;
} else if (slot == 1) {
LOGI("In B system, now upgrade A system.\n");
partition = partition & 0x1a9ff;
}
if (!RK_ota_set_partition(partition)) {
LOGE("ota file is error.\n");
return -1;
}
RK_ota_start(handle_upgrade_callback, handle_print_callback);
if (m_status != RK_UPGRADE_FINISHED) {
return -1;
}
return 0;
}
void display(void)
{
LOGI("--misc=now Linux A/B mode: Setting the current partition to bootable.\n");
LOGI("--misc=other Linux A/B mode: Setting another partition to bootable.\n");
LOGI("--misc=update Recovery mode: Setting the partition to be upgraded.\n");
LOGI("--misc=display Display misc info.\n");
LOGI("--misc=wipe_userdata Format data partition.\n");
LOGI("--misc_custom= < op > Operation on misc for custom cmdline");
LOGI(" op: read Read custom cmdline to /tmp/custom_cmdline");
LOGI(" write Write /tmp/custom_cmdline to custom area");
LOGI(" clean clean custom area");
LOGI("--update Upgrade mode.\n");
LOGI("--partition=0x3FFC00 Set the partition to be upgraded.(NOTICE: OTA not support upgrade loader and parameter)\n");
LOGI(" 0x3FFC00: 0011 1111 1111 1100 0000 0000.\n");
LOGI(" uboot trust boot recovery rootfs oem\n");
LOGI(" uboot_a uboot_b boot_a boot_b system_a system_b.\n");
LOGI(" 100000000000000000000000: Upgrade loader\n");
LOGI(" 010000000000000000000000: Upgrade parameter\n");
LOGI(" 001000000000000000000000: Upgrade uboot\n");
LOGI(" 000100000000000000000000: Upgrade trust\n");
LOGI(" 000010000000000000000000: Upgrade boot\n");
LOGI(" 000001000000000000000000: Upgrade recovery\n");
LOGI(" 000000100000000000000000: Upgrade rootfs\n");
LOGI(" 000000010000000000000000: Upgrade oem\n");
LOGI(" 000000001000000000000000: Upgrade uboot_a\n");
LOGI(" 000000000100000000000000: Upgrade uboot_b\n");
LOGI(" 000000000010000000000000: Upgrade boot_a\n");
LOGI(" 000000000001000000000000: Upgrade boot_b\n");
LOGI(" 000000000000100000000000: Upgrade system_a\n");
LOGI(" 000000000000010000000000: Upgrade system_b\n");
LOGI(" 000000000000001000000000: Upgrade misc\n");
LOGI(" 000000000000000100000000: Upgrade userdata\n");
LOGI("--reboot Restart the machine at the end of the program.\n");
LOGI("--version_url=url The path to the file of version.\n");
LOGI("--image_url=url Path to upgrade firmware.\n");
LOGI("--savepath=url save the update.img to url.\n");
LOGI("--version the version of updateEngine\n");
LOGI("--rkdebug Log output to serial port\n");
LOGI("--ui_rotation UI rotation,has 4 angles(0-3).\n");
}
static const struct option engine_options[] = {
{ "update", optional_argument, NULL, 'u' },
{ "version_url", required_argument, NULL, 'v' + 'u' },
{ "image_url", required_argument, NULL, 'i' + 'u'},
{ "check", required_argument, NULL, 'c' },
{ "misc", required_argument, NULL, 'm' },
{ "misc_custom", required_argument, NULL, 'd' },
{ "partition", required_argument, NULL, 'p' },
{ "reboot", no_argument, NULL, 'r' },
{ "help", no_argument, NULL, 'h' },
{ "pipefd", required_argument, NULL, 'p' + 'f' },
{ "savepath", required_argument, NULL, 's'},
{ "version", no_argument, NULL, 'v'},
{ "rkdebug", no_argument, NULL, 'k'},
{ "ui_rotation", required_argument, NULL, 'o'},
{ NULL, 0, NULL, 0 },
};
int main(int argc, char *argv[])
{
LOGI("*** update_engine: %s ***.\n", update_engine_version);
int arg;
char *image_url = NULL;
char *version_url = NULL;
char *misc_func = NULL;
char *save_path = NULL;
char *partition = NULL;
char *custom_define = NULL;
bool is_update = false;
bool is_reboot = false;
int pipefd = -1;
while ((arg = getopt_long(argc, argv, "", engine_options, NULL)) != -1) {
switch (arg) {
case 'u': is_update = true; if (optarg != NULL) is_sdboot = true; continue;
case 'c': version_url = optarg; continue;
case 'm': misc_func = optarg; continue;
case 'p': partition = optarg; continue;
case 's': save_path = optarg; continue;
case 'r': is_reboot = true; continue;
case 'v' + 'u': version_url = optarg; continue;
case 'i' + 'u': image_url = optarg; continue;
case 'p' + 'f': pipefd = atoi(optarg); continue;
case 'h': display(); break;
case 'd': custom_define = optarg; continue;
case 'v': LOGI("*** update_engine: %s ***.\n", update_engine_version); break;
case 'k': rkdebug = true; break;
case 'o': ui_rotation = optarg; break;
case '?':
LOGE("Invalid command argument\n");
continue;
}
}
if (pipefd != -1) {
cmd_pipe = fdopen(pipefd, "wb");
setlinebuf(cmd_pipe);
}
if (is_update) {
if (optarg && (strstr(optarg, "usb") != NULL || strstr(optarg, "udisk") != NULL)) {
is_usbboot = true;
is_sdboot = false;
LOGI("*** will upgrade firmware from udisk ***");
}
if (is_sdboot || is_usbboot) {
int res = 0x3FFC00; //默认升级的分区
LOGI("%s-%d: is %s update.\n", __func__, __LINE__, is_usbboot ? "usbboot" : "sdboot");
if (partition != NULL) {
res = strtol(partition + 2, NULL, 16);
}
RK_ota_set_url(image_url, save_path);
if ( !RK_ota_set_partition(res) ) {
LOGE("ota file is error.\n");
return -1;
}
if (version_url != NULL) {
if (!RK_ota_check_version(version_url) ) {
LOGE("you shouldn't update the device.\n");
return -1;
}
}
RK_ota_start(handle_upgrade_callback, handle_print_callback);
} else {
LOGI("%s-%d: is ota update\n", __func__, __LINE__);
if (MiscUpdate(image_url, partition, save_path) == 0) {
m_status = RK_UPGRADE_FINISHED;
}
}
} else if (misc_func != NULL) {
if (strcmp(misc_func, "now") == 0) {
if (setSlotSucceed() == 0) {
m_status = RK_UPGRADE_FINISHED;
}
} else if (strcmp(misc_func, "other") == 0) {
if (setSlotActivity() == 0) {
m_status = RK_UPGRADE_FINISHED;
}
} else if (strcmp(misc_func, "wipe_userdata") == 0) {
if (wipe_userdata(0) == 0) {
m_status = RK_UPGRADE_FINISHED;
}
} else if (strcmp(misc_func, "update") == 0) {
if (MiscUpdate(image_url, partition, save_path) == 0) {
m_status = RK_UPGRADE_FINISHED;
}
} else if (strcmp(misc_func, "display") == 0) {
miscDisplay();
} else {
LOGE("unknow misc cmdline : %s.\n", misc_func);
return 0;
}
} else if (custom_define != NULL) {
if (strcmp(custom_define, "read") == 0) {
if (readCustomMiscCmdline())
return -1;
} else if (strcmp(custom_define, "write") == 0) {
if (writeCustomMiscCmdline())
return -1;
} else if (strcmp(custom_define, "clean") == 0) {
if (cleanCustomMiscCmdline())
return -1;
} else {
LOGI("Not supported\n");
return m_status;
}
m_status = RK_UPGRADE_FINISHED;
}
if (is_reboot && (m_status == RK_UPGRADE_FINISHED)) {
sync();
//reboot(RB_AUTOBOOT);
if (system(" echo b > /proc/sysrq-trigger ") == -1)
return -1;
}
return m_status;
}