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

328 lines
12 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* 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;
}