8541E-A90 bootloader部分适配鸿蒙升级逻辑之代码解读
一、方案拟定
通过修改uboot的启动参数即挂载的分区节点,确定启动主系统还是recovery系统。从而实现通过同一个uboot、同一个kernel启动两个分区的目的,并通过misc分区保存数据实现分区的自由切换。
二、代码逻辑修改
2.1、涉及的代码文件
device/kaihong/8541e/common/bsp/bootloader/u-boot15/common/loader/recv_mode.c
device/kaihong/8541e/common/bsp/bootloader/u-boot15/common/cmd_cboot.c
device/kaihong/8541e/common/bsp/bootloader/u-boot15/common/loader/sprd_fdt_support.c
device/kaihong/8541e/common/bsp/bootloader/u-boot15/include/boot_mode.h
2.2、代码逻辑实现
2.2.1 misc分区结构体适配
**Tips:**标‘*’部分是改动行,其中注掉的部分是原始的代码,没有注掉的为新增的代码
vi device/kaihong/8541e/common/bsp/bootloader/u-boot15/common/loader/recv_mode.c
1 #include <common.h>
2 #include <boot_mode.h>
3 #include <part_efi.h>
4 #include "loader_common.h"
5 #include <sprd_common_rw.h>
6
* 7 int is_recovery = 0; //定义启动recovery分区的flag
8 extern void reboot_devices(unsigned reboot_mode);
9
10 /* Recovery Message */
* 11 // struct recovery_message {
* 12 // char command[32];
* 13 // char status[32];
* 14 // char recovery[1024];
* 15 // };
* 16 struct recovery_message {
* 17 char command[20];
* 18 char update[100];
* 19 };
*
20 int get_recovery_message(struct recovery_message *out)
21 {
......
79 int get_mode_from_file(void)
80 {
81 debugf("!!!!!!!!!! %s:%d entry\n", __FUNCTION__, __LINE__);
82 struct recovery_message msg;
83 char partition_name[32];
84 unsigned valid_command = 0;
85
86 /*get recovery message */
87 if (get_recovery_message(&msg)) {
89 return CMD_UNKNOW_REBOOT_MODE;
90 }
91 if (msg.command[0] != 0 && msg.command[0] != 255) {
92 debugf("Recovery command: %.*s\n", sizeof(msg.command), msg.command);
93 }
94 /*Ensure termination */
95 msg.command[sizeof(msg.command) - 1] = '\0';
* 96 //if (!strcmp("boot-recovery", msg.command)) {
* 97 if (!strcmp("boot_updater", msg.command)) { //和鸿蒙的填充内容保持一致
* 98 is_recovery = 1; //flag赋值1
99 debugf("%s:Message in misc indicate the RECOVERY MODE is_recovery = %d\n", __FUNCTION__, is_recovery);
100 return CMD_RECOVERY_MODE;
101 } else if (!strcmp("update-radio", msg.command)) {
* 102 // strcpy(msg.status, "OKAY");
* 103 // strcpy(msg.command, "boot-recovery");
* 104 strcpy(msg.command, "boot_updater");
105 /*send recovery message */
106 set_recovery_message(&msg);
107 reboot_devices(0);
108 return CMD_UNKNOW_REBOOT_MODE;
109 } else {
110 return 0;
111 }
112 }
113 /* set recovery message to boot fastbootd */
114 int set_recovery_run_fastbootd(void)
115 {
116 struct recovery_message msg = {0};
117
118 strcpy(msg.command, "boot-fastboot");
* 119 strcpy(msg.update, "recovery\n");
* 120 strcpy(msg.update, "--fastboot\n");
121
122 set_recovery_message(&msg);
123 return 0;
124 }
125
126 /* clear recovery message for boot fastbootd */
127 int clear_recovery_not_run_fastbootd(void)
128 {
129 struct recovery_message msg = {0};
130
* 131 strcpy(msg.command, "boot_updater");
* 132 strcpy(msg.update, "recovery\n");
133
134 set_recovery_message(&msg);
135 return 0 ;
vi device/kaihong/8541e/common/bsp/bootloader/u-boot15/include/boot_mode.h
......
97 do{\
98 array[index] = fun;\
99 }while(0)
100
* 101 extern int is_recovery; //把flag在头文件里声明,方便其他文件访问
102 int get_mode_from_file(void);
103 int set_recovery_run_fastbootd(void);
104 int clear_recovery_not_run_fastbootd(
......
2.2.1 修改启动方式
vi device/kaihong/8541e/common/bsp/bootloader/u-boot15/common/cmd_cboot.c
151 /*1 get mode from file, just for recovery mode now*/
152 boot_mode_enum_type get_mode_from_file_extend(void)
153 {
154 debugf("!!!!!!!!!!!!!!!!!! %s:%d entry\n", __FUNCTION__, __LINE__);
155 switch (get_mode_from_file()) {
156 case CMD_RECOVERY_MODE:
157 debugf("cboot:get mode from file:recovery, is_recovery = %d\n", is_recovery);
* 158 // return CMD_RECOVERY_MODE;
* 159 return CMD_NORMAL_MODE; //均按照主分区的方式启动
160 default:
161 debugf("!!!!!!!!!!!!!!!!!! %s:%d CMD_UNDEFINED_MODE", __FUNCTION__, __LINE__);
162 return CMD_UNDEFINED_MODE;
163 }
164 debugf("!!!!!!!!!!!!!!!!!! %s:%d CMD_UNDEFINED_MODE", __FUNCTION__, __LINE__);
165 return CMD_UNDEFINED_MODE;
166 }
2.2.2 适配分区的挂载节点
vi device/kaihong/8541e/common/bsp/bootloader/u-boot15/common/loader/sprd_fdt_support.c
1651 int fdt_fixup_system_mount_part_num(void *fdt)
1652 {
1653 int ret = 0;
1654
1655 #ifndef CONFIG_NAND_BOOT
1656 if (gd->boot_device == BOOT_DEVICE_EMMC) {
1657 unsigned int num;
1658 int nodeoffset;
1659 const char *path;
1660 char buf[128];
1661 int str_len;
1662
1663 char *path_copy, *s, *v, *v_copy, *k;
1664 //get_img_partition_id("system", &num);
* 1664 if(is_recovery) { //挂载主分区还是recovery分区,为填充启动参数做准备
* 1665 get_img_partition_id("recovery", &num);
* 1666 } else {
* 1667 get_img_partition_id("system", &num);
* 1668 }
1669 memset(buf, 0, sizeof(buf));
1670
1671 /* Find the "chosen" node */
1672 nodeoffset = fdt_path_offset(fdt, "/chosen");
1673 /* If there is no "chosen" node in the blob, leave */
1674 if (nodeoffset < 0) {
1675 errorf("fdt_chosen_bootargs_replace: cann't find chosen");
1676 return -1;
1677 }
三、切换分区的命令
**1、**在主分区命令行执行 reboot updater可以切换到recovery分区
**2、**在recovery分区执行 updater_reboot 可以切换到主分区,但是由于recovery分区的串口无法输入,目前无法执行该命令。
以上两种方式均是通过修改misc分区来实现分区切换,现提供hi3516dv300的misc分区的数据结构如下: