blob: 6d819e416aee5e37098029f8d239bfea6df043aa [file] [log] [blame]
Xindong Xu495e9682023-02-24 04:50:07 +00001// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
2/*
3 * Copyright (c) 2019 Amlogic, Inc. All rights reserved.
4 */
5
6#include <common.h>
7#include <command.h>
8#include <env.h>
9#include <malloc.h>
Xindong Xu15e83fa2024-03-15 08:56:00 +080010#ifdef CONFIG_AML_MTD
11#include <linux/mtd/mtd.h>
12#endif
Xindong Xu495e9682023-02-24 04:50:07 +000013#include <asm/byteorder.h>
14#include <config.h>
15#include <asm/amlogic/arch/io.h>
16#include <amlogic/partition_table.h>
17#include <amlogic/libavb/libavb.h>
18#include <version.h>
19#include <amlogic/storage.h>
20#include <fastboot.h>
21#include <u-boot/sha1.h>
22#include <asm/amlogic/arch/efuse.h>
23#include <amlogic/emmc_partitions.h>
Xindong Xue5d4d172023-04-10 10:30:25 +080024#if (IS_ENABLED(CONFIG_UNIFY_BOOTLOADER))
Xindong Xu495e9682023-02-24 04:50:07 +000025#include "cmd_bootctl_wrapper.h"
26#endif
27#include "cmd_bootctl_utils.h"
28#include <amlogic/store_wrapper.h>
29
Xindong Xu15e83fa2024-03-15 08:56:00 +080030#include <asm/amlogic/arch/secure_apb.h>
31
Xindong Xu495e9682023-02-24 04:50:07 +000032#if defined(CONFIG_EFUSE_OBJ_API) && defined(CONFIG_CMD_EFUSE)
33extern efuse_obj_field_t efuse_field;
34#endif//#ifdef CONFIG_EFUSE_OBJ_API
35
36#ifdef CONFIG_BOOTLOADER_CONTROL_BLOCK
37
38// Spaces used by misc partition are as below:
39// 0 - 2K For bootloader_message
40// 2K - 16K Used by Vendor's bootloader (the 2K - 4K range may be optionally used
41// as bootloader_message_ab struct)
42// 16K - 32K Used by uncrypt and recovery to store wipe_package for A/B devices
43// 32K - 64K System space, used for miscellanious AOSP features. See below.
44// Note that these offsets are admitted by bootloader,recovery and uncrypt, so they
45// are not configurable without changing all of them.
46#define BOOTLOADER_MESSAGE_OFFSET_IN_MISC 0
47#define VENDOR_SPACE_OFFSET_IN_MISC 2 * 1024
48#define WIPE_PACKAGE_OFFSET_IN_MISC 16 * 1024
49#define SYSTEM_SPACE_OFFSET_IN_MISC 32 * 1024
50#define SYSTEM_SPACE_SIZE_IN_MISC 32 * 1024
51
52
53#define AB_METADATA_MISC_PARTITION_OFFSET 2048
54
55#define MISCBUF_SIZE 2080
56
57/* Bootloader Message (2-KiB)
58 *
59 * This structure describes the content of a block in flash
60 * that is used for recovery and the bootloader to talk to
61 * each other.
62 *
63 * The command field is updated by linux when it wants to
64 * reboot into recovery or to update radio or bootloader firmware.
65 * It is also updated by the bootloader when firmware update
66 * is complete (to boot into recovery for any final cleanup)
67 *
68 * The status field was used by the bootloader after the completion
69 * of an "update-radio" or "update-hboot" command, which has been
70 * deprecated since Froyo.
71 *
72 * The recovery field is only written by linux and used
73 * for the system to send a message to recovery or the
74 * other way around.
75 *
76 * The stage field is written by packages which restart themselves
77 * multiple times, so that the UI can reflect which invocation of the
78 * package it is. If the value is of the format "#/#" (eg, "1/3"),
79 * the UI will add a simple indicator of that status.
80 *
81 * We used to have slot_suffix field for A/B boot control metadata in
82 * this struct, which gets unintentionally cleared by recovery or
83 * uncrypt. Move it into struct bootloader_message_ab to avoid the
84 * issue.
85 */
86struct bootloader_message {
87 char command[32];
88 char status[32];
89 char recovery[768];
90
91 // The 'recovery' field used to be 1024 bytes. It has only ever
92 // been used to store the recovery command line, so 768 bytes
93 // should be plenty. We carve off the last 256 bytes to store the
94 // stage string (for multistage packages) and possible future
95 // expansion.
96 char stage[32];
97
98 // The 'reserved' field used to be 224 bytes when it was initially
99 // carved off from the 1024-byte recovery field. Bump it up to
100 // 1184-byte so that the entire bootloader_message struct rounds up
101 // to 2048-byte.
102 char reserved[1184];
103};
104
105/**
106 * The A/B-specific bootloader message structure (4-KiB).
107 *
108 * We separate A/B boot control metadata from the regular bootloader
109 * message struct and keep it here. Everything that's A/B-specific
110 * stays after struct bootloader_message, which should be managed by
111 * the A/B-bootloader or boot control HAL.
112 *
113 * The slot_suffix field is used for A/B implementations where the
114 * bootloader does not set the androidboot.ro.boot.slot_suffix kernel
115 * commandline parameter. This is used by fs_mgr to mount /system and
116 * other partitions with the slotselect flag set in fstab. A/B
117 * implementations are free to use all 32 bytes and may store private
118 * data past the first NUL-byte in this field. It is encouraged, but
119 * not mandatory, to use 'struct bootloader_control' described below.
120 *
121 * The update_channel field is used to store the Omaha update channel
122 * if update_engine is compiled with Omaha support.
123 */
124struct bootloader_message_ab {
125 struct bootloader_message message;
126 char slot_suffix[32];
127 char update_channel[128];
128
129 // Round up the entire struct to 4096-byte.
130 char reserved[1888];
131};
132
133#define BOOT_CTRL_MAGIC 0x42414342 /* Bootloader Control AB */
134#define BOOT_CTRL_VERSION 1
135
136typedef struct slot_metadata {
137 // Slot priority with 15 meaning highest priority, 1 lowest
138 // priority and 0 the slot is unbootable.
139 uint8_t priority : 4;
140 // Number of times left attempting to boot this slot.
141 uint8_t tries_remaining : 3;
142 // 1 if this slot has booted successfully, 0 otherwise.
143 uint8_t successful_boot : 1;
144 // 1 if this slot is corrupted from a dm-verity corruption, 0
145 // otherwise.
146 uint8_t verity_corrupted : 1;
147 // Reserved for further use.
148 uint8_t reserved : 7;
149} slot_metadata;
150
151/* Bootloader Control AB
152 *
153 * This struct can be used to manage A/B metadata. It is designed to
154 * be put in the 'slot_suffix' field of the 'bootloader_message'
155 * structure described above. It is encouraged to use the
156 * 'bootloader_control' structure to store the A/B metadata, but not
157 * mandatory.
158 */
159typedef struct bootloader_control {
160 // NUL terminated active slot suffix.
161 char slot_suffix[4];
162 // Bootloader Control AB magic number (see BOOT_CTRL_MAGIC).
163 uint32_t magic;
164 // Version of struct being used (see BOOT_CTRL_VERSION).
165 uint8_t version;
166 // Number of slots being managed.
167 uint8_t nb_slot : 3;
168 // Number of times left attempting to boot recovery.
169 uint8_t recovery_tries_remaining : 3;
170 // Status of any pending snapshot merge of dynamic partitions.
171 uint8_t merge_status : 3;
172 // Ensure 4-bytes alignment for slot_info field.
173 uint8_t roll_flag;
174 // Per-slot information. Up to 4 slots.
175 struct slot_metadata slot_info[4];
176 // Reserved for further use.
Xindong Xua6618952024-07-12 15:15:10 +0800177 uint8_t merge_flag;
178 uint8_t reserved1[7];
Xindong Xu495e9682023-02-24 04:50:07 +0000179 // CRC32 of all 28 bytes preceding this field (little endian
180 // format).
181 uint32_t crc32_le;
182}bootloader_control;
183
184#define MISC_VIRTUAL_AB_MESSAGE_VERSION 2
185#define MISC_VIRTUAL_AB_MAGIC_HEADER 0x56740AB0
186
Xindong Xu0afe60a2024-05-21 16:15:13 +0800187unsigned int kDefaultBootAttempts = 6;
Xindong Xu495e9682023-02-24 04:50:07 +0000188
189/* Magic for the A/B struct when serialized. */
190#define AVB_AB_MAGIC "\0AB0"
191#define AVB_AB_MAGIC_LEN 4
192
193/* Versioning for the on-disk A/B metadata - keep in sync with avbtool. */
194#define AVB_AB_MAJOR_VERSION 1
195#define AVB_AB_MINOR_VERSION 0
196
197/* Size of AvbABData struct. */
198#define AVB_AB_DATA_SIZE 32
199
200/* Maximum values for slot data */
201#define AVB_AB_MAX_PRIORITY 15
202#define AVB_AB_MAX_TRIES_REMAINING 7
203
204/* Struct used for recording per-slot metadata.
205 *
206 * When serialized, data is stored in network byte-order.
207 */
208typedef struct AvbABSlotData {
209 /* Slot priority. Valid values range from 0 to AVB_AB_MAX_PRIORITY,
210 * both inclusive with 1 being the lowest and AVB_AB_MAX_PRIORITY
211 * being the highest. The special value 0 is used to indicate the
212 * slot is unbootable.
213 */
214 uint8_t priority;
215
216 /* Number of times left attempting to boot this slot ranging from 0
217 * to AVB_AB_MAX_TRIES_REMAINING.
218 */
219 uint8_t tries_remaining;
220
221 /* Non-zero if this slot has booted successfully, 0 otherwise. */
222 uint8_t successful_boot;
223
224 /* Reserved for future use. */
225 uint8_t reserved[1];
226} AvbABSlotData;
227
228/* Struct used for recording A/B metadata.
229 *
230 * When serialized, data is stored in network byte-order.
231 */
232typedef struct AvbABData {
233 /* Magic number used for identification - see AVB_AB_MAGIC. */
234 uint8_t magic[AVB_AB_MAGIC_LEN];
235
236 /* Version of on-disk struct - see AVB_AB_{MAJOR,MINOR}_VERSION. */
237 uint8_t version_major;
238 uint8_t version_minor;
239
240 /* Padding to ensure |slots| field start eight bytes in. */
241 uint8_t reserved1[2];
242
243 /* Per-slot metadata. */
244 AvbABSlotData slots[2];
245
246 /* Reserved for future use. */
247 uint8_t reserved2[12];
248
249 /* CRC32 of all 28 bytes preceding this field. */
250 uint32_t crc32;
251}AvbABData;
252
253#ifdef CONFIG_UNIFY_BOOTLOADER
254bootctl_func_handles vab_cmd_bootctrl_handles = {0};
255#endif
256
257static bool boot_info_validate(bootloader_control *info)
258{
259 if (info->magic != BOOT_CTRL_MAGIC) {
260 printf("Magic 0x%x is incorrect.\n", info->magic);
261 return false;
262 }
263 return true;
264}
265
266bool boot_info_validate_normalAB(AvbABData* info)
267{
268 if (memcmp(info->magic, AVB_AB_MAGIC, AVB_AB_MAGIC_LEN) != 0) {
269 printf("Magic %s is incorrect.\n", info->magic);
270 return false;
271 }
272 if (info->version_major > AVB_AB_MAJOR_VERSION) {
273 printf("No support for given major version.\n");
274 return false;
275 }
276 return true;
277}
278
279
280void boot_info_reset(bootloader_control* boot_ctrl)
281{
282 int slot;
283
284 memset(boot_ctrl, '\0', sizeof(bootloader_control));
285 memcpy(boot_ctrl->slot_suffix, "_a", 2);
286 boot_ctrl->magic = BOOT_CTRL_MAGIC;
287 boot_ctrl->version = BOOT_CTRL_VERSION;
288 boot_ctrl->nb_slot = 2;
289 boot_ctrl->roll_flag = 0;
Xindong Xua6618952024-07-12 15:15:10 +0800290 boot_ctrl->merge_flag = -1;
Xindong Xu495e9682023-02-24 04:50:07 +0000291
292 for (slot = 0; slot < 4; ++slot) {
293 slot_metadata entry = {};
294
295 if (slot < boot_ctrl->nb_slot) {
296 entry.priority = 7;
Xindong Xu0afe60a2024-05-21 16:15:13 +0800297 entry.tries_remaining = 0;
Xindong Xu495e9682023-02-24 04:50:07 +0000298 entry.successful_boot = 0;
299 } else {
300 entry.priority = 0; // Unbootable
301 entry.tries_remaining = 0;
302 entry.successful_boot = 0;
303 }
304
305 boot_ctrl->slot_info[slot] = entry;
306 }
Xindong Xu0afe60a2024-05-21 16:15:13 +0800307 boot_ctrl->slot_info[0].priority = 15;
308 boot_ctrl->slot_info[0].tries_remaining = kDefaultBootAttempts;
309 boot_ctrl->slot_info[0].successful_boot = 0;
Xindong Xu495e9682023-02-24 04:50:07 +0000310 boot_ctrl->recovery_tries_remaining = 0;
311}
312
313static void dump_boot_info(bootloader_control *boot_ctrl)
314{
315#if 0
316 int slot;
317
318 printf("boot_ctrl->slot_suffix = %s\n", boot_ctrl->slot_suffix);
319 printf("boot_ctrl->magic = 0x%x\n", boot_ctrl->magic);
320 printf("boot_ctrl->version = %d\n", boot_ctrl->version);
321 printf("boot_ctrl->nb_slot = %d\n", boot_ctrl->nb_slot);
322 for (slot = 0; slot < 4; ++slot) {
323 printf("boot_ctrl->slot_info[%d].priority = %d\n",
324 slot, boot_ctrl->slot_info[slot].priority);
325 printf("boot_ctrl->slot_info[%d].tries_remaining = %d\n",
326 slot, boot_ctrl->slot_info[slot].tries_remaining);
327 printf("boot_ctrl->slot_info[%d].successful_boot = %d\n",
328 slot, boot_ctrl->slot_info[slot].successful_boot);
329 }
330 printf("boot_ctrl->recovery_tries_remaining = %d\n",
331 boot_ctrl->recovery_tries_remaining);
332#endif
333}
334
335static bool slot_is_bootable(slot_metadata* slot) {
336 return slot->tries_remaining != 0;
337}
338
339static int get_active_slot(bootloader_control *info)
340{
341 if (info->slot_info[0].priority > info->slot_info[1].priority) {
342 return 0;
343 } else if (info->slot_info[0].priority == info->slot_info[1].priority) {
344 if (info->slot_info[0].successful_boot == 1)
345 return 0;
346 else
347 return 1;
348 } else {
349 return 1;
350 }
351}
352
353static bool slot_is_bootable_normalAB(AvbABSlotData* slot) {
354 return slot->priority > 0 &&
355 (slot->successful_boot || (slot->tries_remaining > 0));
356}
357
358int get_active_slot_normalAB(AvbABData* info) {
359 if (info->slots[0].priority > info->slots[1].priority)
360 return 0;
361 else
362 return 1;
363}
364
365static uint32_t vab_crc32(const uint8_t *buf, size_t size)
366{
367 static uint32_t crc_table[256];
368 uint32_t ret = -1;
369
370 // Compute the CRC-32 table only once.
371 if (!crc_table[1]) {
372 for (uint32_t i = 0; i < 256; ++i) {
373 uint32_t crc = i;
374
375 for (uint32_t j = 0; j < 8; ++j) {
376 uint32_t mask = -(crc & 1);
377
378 crc = (crc >> 1) ^ (0xEDB88320 & mask);
379 }
380 crc_table[i] = crc;
381 }
382 }
383
384 for (size_t i = 0; i < size; ++i)
385 ret = (ret >> 8) ^ crc_table[(ret ^ buf[i]) & 0xFF];
386
387 return ~ret;
388}
389
390static int boot_info_set_active_slot(bootloader_control *bootctrl, int slot)
391{
392 int i;
393 // Set every other slot with a lower priority than the new "active" slot.
394 const unsigned int kActivePriority = 15;
395 const unsigned int kActiveTries = 6;
396
397 for (i = 0; i < bootctrl->nb_slot; ++i) {
398 if (i != slot) {
399 //bootctrl->slot_info[i].priority -= 1;
400 if (bootctrl->slot_info[i].priority >= kActivePriority)
401 bootctrl->slot_info[i].priority = kActivePriority - 1;
402 }
403 printf("bootctrl->slot_info[%d].priority = %d\n", i,
404 bootctrl->slot_info[i].priority);
405 }
406
407 // Note that setting a slot as active doesn't change the successful bit.
408 // The successful bit will only be changed by setSlotAsUnbootable().
409 bootctrl->slot_info[slot].priority = kActivePriority;
410 bootctrl->slot_info[slot].tries_remaining = kActiveTries;
411
412 printf("bootctrl->slot_info[%d].priority = %d\n", slot,
413 bootctrl->slot_info[slot].priority);
414 printf("bootctrl->slot_info[%d].tries_remaining = %d\n",
415 slot, bootctrl->slot_info[slot].tries_remaining);
416
417 // Setting the current slot as active is a way to revert the operation that
418 // set *another* slot as active at the end of an updater. This is commonly
419 // used to cancel the pending update. We should only reset the verity_corrpted
420 // bit when attempting a new slot, otherwise the verity bit on the current
421 // slot would be flip.
422 if (slot != get_active_slot(bootctrl))
423 bootctrl->slot_info[slot].verity_corrupted = 0;
424
425 dump_boot_info(bootctrl);
426
427 return 0;
428}
429
430static bool boot_info_load(bootloader_control *out_info, char *miscbuf)
431{
432 memcpy(out_info, miscbuf + AB_METADATA_MISC_PARTITION_OFFSET, sizeof(bootloader_control));
433 dump_boot_info(out_info);
434 return true;
435}
436
437bool boot_info_load_normalAB(AvbABData *out_info, char *miscbuf)
438{
439 memcpy(out_info, miscbuf + AB_METADATA_MISC_PARTITION_OFFSET, AVB_AB_DATA_SIZE);
440 return true;
441}
442
443static bool boot_info_save(bootloader_control *info, char *miscbuf)
444{
445 char *partition = "misc";
446 int ret = 0;
447
448 printf("save boot-info\n");
449 info->crc32_le = vab_crc32((const uint8_t *)info,
450 sizeof(bootloader_control) - sizeof(uint32_t));
451
452 memcpy(miscbuf + AB_METADATA_MISC_PARTITION_OFFSET, info, sizeof(bootloader_control));
453 dump_boot_info(info);
Xindong Xue5d4d172023-04-10 10:30:25 +0800454
455#ifdef CONFIG_AML_MTD
456 enum boot_type_e device_boot_flag = store_get_type();
457
458 if (device_boot_flag == BOOT_NAND_NFTL || device_boot_flag == BOOT_NAND_MTD ||
459 device_boot_flag == BOOT_SNAND) {
460 int ret = 0;
461
462 ret = run_command("store erase misc 0 0x4000", 0);
463 if (ret != 0) {
464 printf("erase partition misc failed!\n");
465 return false;
466 }
Xindong Xu495e9682023-02-24 04:50:07 +0000467 }
Xindong Xue5d4d172023-04-10 10:30:25 +0800468#endif
469
Xindong Xu495e9682023-02-24 04:50:07 +0000470 ret = store_logic_write((const char *)partition, 0, MISCBUF_SIZE, (unsigned char *)miscbuf);
471 if (ret) {
472 printf("store logic write failed at %s\n", partition);
473 return false;
474 }
475 return true;
476}
477
478static int is_BootSame(int srcindex, int dstindex)
479{
480 int iRet = 0;
481 int ret = -1;
482 unsigned char *buffer_src = NULL;
483 unsigned char *buffer_dest = NULL;
484 const int SHA1SUMLEN = 20;
485 u8 gensum0[SHA1SUMLEN * 2];
486 u8 *gensum1 = gensum0 + SHA1SUMLEN;
487 int capacity_boot = 0;
488
489#ifdef CONFIG_MMC_MESON_GX
490 struct mmc *mmc = NULL;
491
492 if (store_get_type() == BOOT_EMMC)
493 mmc = find_mmc_device(1);
494
495 if (mmc)
496 capacity_boot = mmc->capacity_boot;
497#endif
498
499 printf("is_BootSame_capacity_boot: %x\n", capacity_boot);
500
501 buffer_src = (unsigned char *)malloc(capacity_boot);
502 if (!buffer_src) {
503 printf("ERROR! fail to allocate memory ...\n");
504 goto exit;
505 }
506 memset(buffer_src, 0, capacity_boot);
507
508 iRet = store_boot_read("bootloader", srcindex, 0, buffer_src);
509 if (iRet) {
510 printf("Fail read bootloader %d\n", srcindex);
511 goto exit;
512 }
513 sha1_csum(buffer_src, capacity_boot, gensum0);
514
515 buffer_dest = buffer_src;
516 memset(buffer_dest, 0, capacity_boot);
517 iRet = store_boot_read("bootloader", dstindex, 0, buffer_dest);
518 if (iRet) {
519 printf("Fail read bootloader %d\n", dstindex);
520 goto exit;
521 }
522 sha1_csum(buffer_dest, capacity_boot, gensum1);
523
524 ret = memcmp(gensum0, gensum1, SHA1SUMLEN);
525 printf("bootloader %d & %d %s same\n", srcindex, dstindex, ret ? "NOT" : "DO");
526
527exit:
528 if (buffer_src) {
529 free(buffer_src);
530 buffer_src = NULL;
531 }
532 return ret;
533}
534
535static int write_bootloader(int copy, int dstindex)
536{
537 int iRet = 0;
538 int ret = -1;
539 unsigned char *buffer = NULL;
540 int capacity_boot = 0;
541
542#ifdef CONFIG_MMC_MESON_GX
543 struct mmc *mmc = NULL;
544
545 if (store_get_type() == BOOT_EMMC)
546 mmc = find_mmc_device(1);
547#endif
548
549 if (mmc)
550 capacity_boot = mmc->capacity_boot;
551
552 printf("write_bootloader_capacity_boot: %x\n", capacity_boot);
553
554 buffer = (unsigned char *)malloc(capacity_boot);
555 if (!buffer) {
556 printf("ERROR! fail to allocate memory ...\n");
557 goto exit;
558 }
559 memset(buffer, 0, capacity_boot);
560 printf("copy from boot%d to boot%d\n", copy, dstindex);
561 iRet = store_boot_read("bootloader", copy, 0, buffer);
562 if (iRet) {
563 printf("Fail read bootloader from rsv with sz\n");
564 goto exit;
565 }
566 iRet = store_boot_write("bootloader", dstindex, 0, buffer);
567 if (iRet) {
568 printf("Failed to write bootloader\n");
569 goto exit;
570 } else {
571 ret = 0;
572 }
573
574exit:
575 if (buffer) {
576 free(buffer);
577 buffer = NULL;
578 }
579 return ret;
580}
581
Xindong Xu15e83fa2024-03-15 08:56:00 +0800582static void set_ddr_size(void)
583{
584 char ddr_size_str[32];
585 unsigned int ddr_size = 0;
586
587 memset(ddr_size_str, 0, 32);
588 ddr_size = (readl(SYSCTRL_SEC_STATUS_REG4) & 0xFFF00000) << 4;
589
590 sprintf(ddr_size_str, "%u%c", ddr_size, 'B');
591 printf("ddr_size_str = %s\n", ddr_size_str);
592 env_set("ddr_size", ddr_size_str);
593}
594
595static void update_after_failed_rollback(void)
596{
Xindong Xu0afe60a2024-05-21 16:15:13 +0800597 run_command("run init_display; run storeargs; run enter_fastboot;", 0);
Xindong Xu15e83fa2024-03-15 08:56:00 +0800598}
599
600void rollback_failure_handler(void) __attribute__((weak, alias("update_after_failed_rollback")));
601
Xindong Xu495e9682023-02-24 04:50:07 +0000602static int do_GetValidSlot(
603 cmd_tbl_t *cmdtp,
604 int flag,
605 int argc,
606 char * const argv[])
607{
608 char miscbuf[MISCBUF_SIZE] = {0};
609 bootloader_control boot_ctrl;
610 AvbABData info;
611 int slot;
612 int AB_mode = 0;
613 bool bootable_a, bootable_b;
614 bool nocs_mode = false;
Xindong Xu591b9f42024-07-03 08:52:40 +0800615 char *rebootmode = env_get("reboot_mode");
Xindong Xu495e9682023-02-24 04:50:07 +0000616
617 if (argc != 1)
618 return cmd_usage(cmdtp);
619
Xindong Xu15e83fa2024-03-15 08:56:00 +0800620 set_ddr_size();
621
Xindong Xu495e9682023-02-24 04:50:07 +0000622 boot_info_open_partition(miscbuf);
623 boot_info_load(&boot_ctrl, miscbuf);
624
625 if (!boot_info_validate(&boot_ctrl)) {
626 printf("boot-info virtual ab is invalid. Try normal ab.\n");
627 boot_info_load_normalAB(&info, miscbuf);
628 if (!boot_info_validate_normalAB(&info)) {
629 printf("boot-info is invalid. Resetting.\n");
630 boot_info_reset(&boot_ctrl);
631 boot_info_save(&boot_ctrl, miscbuf);
632 } else {
633 printf("update from normal ab to virtual ab\n");
Xindong Xu15e83fa2024-03-15 08:56:00 +0800634 env_set("normal_to_virtual", "1");
Xindong Xu495e9682023-02-24 04:50:07 +0000635 AB_mode = 1;
636 }
637 }
638
639 if (AB_mode == 1) {
640 slot = get_active_slot_normalAB(&info);
641 printf("active slot = %d\n", slot);
642 bootable_a = slot_is_bootable_normalAB(&info.slots[0]);
643 bootable_b = slot_is_bootable_normalAB(&info.slots[1]);
644 boot_info_reset(&boot_ctrl);
645 boot_ctrl.slot_info[0].successful_boot = info.slots[0].successful_boot;
646 boot_ctrl.slot_info[1].successful_boot = info.slots[1].successful_boot;
647 boot_info_set_active_slot(&boot_ctrl, slot);
648 boot_info_save(&boot_ctrl, miscbuf);
649 slot = get_active_slot(&boot_ctrl);
650 } else {
651 slot = get_active_slot(&boot_ctrl);
652 printf("active slot = %d\n", slot);
653 bootable_a = slot_is_bootable(&boot_ctrl.slot_info[0]);
654 bootable_b = slot_is_bootable(&boot_ctrl.slot_info[1]);
655 }
656
657 if (dynamic_partition)
658 env_set("partition_mode", "dynamic");
659 else
660 env_set("partition_mode", "normal");
661
662 if (gpt_partition)
663 env_set("gpt_mode", "true");
664 else
665 env_set("gpt_mode", "false");
666
667 if (vendor_boot_partition) {
668 env_set("vendor_boot_mode", "true");
669 printf("set vendor_boot_mode true\n");
670 } else {
671 env_set("vendor_boot_mode", "false");
672 printf("set vendor_boot_mode false\n");
673 }
674
675 if (slot == 0) {
676 if (bootable_a) {
677 if (has_boot_slot == 1) {
678 env_set("active_slot", "_a");
679 env_set("boot_part", "boot_a");
680 env_set("recovery_part", "recovery_a");
681 env_set("slot-suffixes", "0");
682 } else {
683 env_set("active_slot", "normal");
684 env_set("boot_part", "boot");
685 env_set("recovery_part", "recovery");
686 env_set("slot-suffixes", "-1");
687 }
688 return 0;
689 } else if (bootable_b) {
690 printf("slot a is unbootable, back to b\n");
691 boot_ctrl.roll_flag = 1;
692 boot_info_save(&boot_ctrl, miscbuf);
693 run_command("set_active_slot b", 0);
694 env_set("update_env", "1");
695 env_set("reboot_status", "reboot_next");
696
697#if defined(CONFIG_EFUSE_OBJ_API) && defined(CONFIG_CMD_EFUSE)
698 run_command("efuse_obj get FEAT_DISABLE_EMMC_USER", 0);
699 if (*efuse_field.data == 1)
700 nocs_mode = true;
701#endif//#ifdef CONFIG_EFUSE_OBJ_API
702 if (gpt_partition || nocs_mode) {
703 printf("gpt or nocs mode\n");
704 write_bootloader(2, 1);
705 env_set("expect_index", "1");
706 } else {
707 printf("normal mode\n");
708 write_bootloader(2, 0);
709 env_set("expect_index", "0");
710 }
711 run_command("saveenv", 0);
Xindong Xu591b9f42024-07-03 08:52:40 +0800712 if (rebootmode && (strcmp(rebootmode, "quiescent") == 0))
713 run_command("reboot quiescent", 0);
714 else
715 run_command("reboot", 0);
Xindong Xu495e9682023-02-24 04:50:07 +0000716 } else {
Xindong Xu0afe60a2024-05-21 16:15:13 +0800717 boot_info_reset(&boot_ctrl);
718 boot_info_save(&boot_ctrl, miscbuf);
Xindong Xu15e83fa2024-03-15 08:56:00 +0800719 rollback_failure_handler();
Xindong Xu495e9682023-02-24 04:50:07 +0000720 }
721 }
722
723 if (slot == 1) {
724 if (bootable_b) {
725 if (has_boot_slot == 1) {
726 env_set("active_slot", "_b");
727 env_set("boot_part", "boot_b");
728 env_set("recovery_part", "recovery_b");
729 env_set("slot-suffixes", "1");
730 } else {
731 env_set("active_slot", "normal");
732 env_set("boot_part", "boot");
733 env_set("recovery_part", "recovery");
734 env_set("slot-suffixes", "-1");
735 }
736 return 0;
737 } else if (bootable_a) {
738 printf("slot b is unbootable, back to a\n");
739 boot_ctrl.roll_flag = 1;
740 boot_info_save(&boot_ctrl, miscbuf);
741 run_command("set_active_slot a", 0);
742 env_set("update_env", "1");
743 env_set("reboot_status", "reboot_next");
744
745#if defined(CONFIG_EFUSE_OBJ_API) && defined(CONFIG_CMD_EFUSE)
746 run_command("efuse_obj get FEAT_DISABLE_EMMC_USER", 0);
747 if (*efuse_field.data == 1)
748 nocs_mode = true;
749#endif//#ifdef CONFIG_EFUSE_OBJ_API
750 if (gpt_partition || nocs_mode) {
751 printf("gpt or nocs mode\n");
752 write_bootloader(2, 1);
753 env_set("expect_index", "1");
754 } else {
755 printf("normal mode\n");
756 write_bootloader(1, 0);
757 env_set("expect_index", "0");
758 }
759 run_command("saveenv", 0);
Xindong Xu591b9f42024-07-03 08:52:40 +0800760 if (rebootmode && (strcmp(rebootmode, "quiescent") == 0))
761 run_command("reboot quiescent", 0);
762 else
763 run_command("reboot", 0);
Xindong Xu495e9682023-02-24 04:50:07 +0000764 } else {
Xindong Xu0afe60a2024-05-21 16:15:13 +0800765 boot_info_reset(&boot_ctrl);
766 boot_info_save(&boot_ctrl, miscbuf);
Xindong Xu15e83fa2024-03-15 08:56:00 +0800767 rollback_failure_handler();
Xindong Xu495e9682023-02-24 04:50:07 +0000768 }
769 }
770
771 return 0;
772}
773
774static int do_SetActiveSlot(
775 cmd_tbl_t *cmdtp,
776 int flag,
777 int argc,
778 char * const argv[])
779{
780 char miscbuf[MISCBUF_SIZE] = {0};
781 bootloader_control info;
782
783 if (argc != 2)
784 return cmd_usage(cmdtp);
785
786 if (has_boot_slot == 0) {
787 printf("device is not ab mode\n");
788 return -1;
789 }
790
791 boot_info_open_partition(miscbuf);
792 boot_info_load(&info, miscbuf);
793
794 if (!boot_info_validate(&info)) {
795 printf("boot-info is invalid. Resetting.\n");
796 boot_info_reset(&info);
797 boot_info_save(&info, miscbuf);
798 }
799
800 if (strcmp(argv[1], "a") == 0) {
801 env_set("active_slot", "_a");
802 env_set("slot-suffixes", "0");
803 env_set("boot_part", "boot_a");
804 env_set("recovery_part", "recovery_a");
805 printf("set active slot a\n");
806 boot_info_set_active_slot(&info, 0);
807 } else if (strcmp(argv[1], "b") == 0) {
808 env_set("active_slot", "_b");
809 env_set("slot-suffixes", "1");
810 env_set("boot_part", "boot_b");
811 env_set("recovery_part", "recovery_b");
812 printf("set active slot b\n");
813 boot_info_set_active_slot(&info, 1);
814 } else {
815 printf("error input slot\n");
816 return -1;
817 }
818
819 boot_info_save(&info, miscbuf);
820
821 printf("info.roll_flag = %d\n", info.roll_flag);
822
823 if (!gpt_partition && info.roll_flag == 1) {
824 printf("if null gpt, write dtb back when rollback\n");
825 if (run_command("imgread dtb ${boot_part} ${dtb_mem_addr}", 0)) {
826 printf("Fail in load dtb\n");
827 } else {
828 printf("write dtb back\n");
829 run_command("emmc dtb_write ${dtb_mem_addr} 0", 0);
830 }
831 }
832
833 return 0;
834}
835
836static int do_SetRollFlag
837(cmd_tbl_t *cmdtp,
838 int flag,
839 int argc,
840 char * const argv[])
841{
842 char miscbuf[MISCBUF_SIZE] = {0};
843 bootloader_control info;
844
845 if (argc != 2)
846 return cmd_usage(cmdtp);
847
848 if (has_boot_slot == 0) {
849 printf("device is not ab mode\n");
850 return -1;
851 }
852
853 boot_info_open_partition(miscbuf);
854 boot_info_load(&info, miscbuf);
855
856 if (!boot_info_validate(&info)) {
857 printf("boot-info is invalid. Resetting.\n");
858 return 0;
859 }
860
861 if (strcmp(argv[1], "1") == 0)
862 info.roll_flag = 1;
863 else
864 info.roll_flag = 0;
865
866 boot_info_save(&info, miscbuf);
867
868 printf("set info.roll_flag = %d\n", info.roll_flag);
869
870 return 0;
871}
872
873static int do_SetUpdateTries(
874 cmd_tbl_t *cmdtp,
875 int flag,
876 int argc,
877 char * const argv[])
878{
879 char miscbuf[MISCBUF_SIZE] = {0};
880 bootloader_control boot_ctrl;
881 bool bootable_a, bootable_b;
882 int slot;
883 int ret = -1;
884 bool nocs_mode = false;
Xindong Xue5d4d172023-04-10 10:30:25 +0800885 int update_flag = 0;
Xindong Xua6618952024-07-12 15:15:10 +0800886 int success_flag = -1;
887 int merge_ret = -1;
Xindong Xu0afe60a2024-05-21 16:15:13 +0800888 char *rebootmode = env_get("reboot_mode");
Xindong Xu495e9682023-02-24 04:50:07 +0000889
890 if (has_boot_slot == 0) {
891 printf("device is not ab mode\n");
892 return -1;
893 }
894
895 boot_info_open_partition(miscbuf);
896 boot_info_load(&boot_ctrl, miscbuf);
897
898 if (!boot_info_validate(&boot_ctrl)) {
899 printf("boot-info is invalid. Resetting\n");
900 boot_info_reset(&boot_ctrl);
901 boot_info_save(&boot_ctrl, miscbuf);
902 }
903
904 slot = get_active_slot(&boot_ctrl);
905 bootable_a = slot_is_bootable(&boot_ctrl.slot_info[0]);
906 bootable_b = slot_is_bootable(&boot_ctrl.slot_info[1]);
907
908 if (slot == 0) {
909 if (bootable_a) {
Xindong Xua6618952024-07-12 15:15:10 +0800910 if (boot_ctrl.slot_info[0].successful_boot == 0) {
911 success_flag = 0;
912 if (rebootmode && strcmp(rebootmode, "fastboot")) {
913 boot_ctrl.slot_info[0].tries_remaining -= 1;
914 update_flag = 1;
915 }
Xindong Xue5d4d172023-04-10 10:30:25 +0800916 }
Xindong Xu495e9682023-02-24 04:50:07 +0000917 }
918 }
919
920 if (slot == 1) {
921 if (bootable_b) {
Xindong Xua6618952024-07-12 15:15:10 +0800922 if (boot_ctrl.slot_info[1].successful_boot == 0) {
923 success_flag = 0;
924 if (rebootmode && strcmp(rebootmode, "fastboot")) {
925 boot_ctrl.slot_info[1].tries_remaining -= 1;
926 update_flag = 1;
927 }
Xindong Xue5d4d172023-04-10 10:30:25 +0800928 }
Xindong Xu495e9682023-02-24 04:50:07 +0000929 }
930 }
931
Xindong Xua6618952024-07-12 15:15:10 +0800932 printf("boot_ctrl.merge_flag = %d\n", boot_ctrl.merge_flag);
933
Xindong Xue5d4d172023-04-10 10:30:25 +0800934 if (update_flag == 1)
935 boot_info_save(&boot_ctrl, miscbuf);
Xindong Xu495e9682023-02-24 04:50:07 +0000936
Xindong Xua6618952024-07-12 15:15:10 +0800937 if (boot_ctrl.merge_flag == SNAPSHOTTED) {
938 printf("merge_flag is SNAPSHOTTED\n");
939 merge_ret = 1;
940 }
941
942 if (rebootmode && (!strcmp(rebootmode, "fastboot")) &&
943 success_flag == 0 &&
944 merge_ret == 1) {
945 printf("reboot bootloader during merge, rollback\n");
946 if (slot == 0 && bootable_a) {
947 if (boot_ctrl.slot_info[0].successful_boot == 0)
948 boot_ctrl.slot_info[0].tries_remaining = 0;
949 } else if (slot == 1 && bootable_b) {
950 if (boot_ctrl.slot_info[1].successful_boot == 0)
951 boot_ctrl.slot_info[1].tries_remaining = 0;
952 }
953 boot_info_save(&boot_ctrl, miscbuf);
954 if (rebootmode && (strcmp(rebootmode, "quiescent") == 0))
955 run_command("reboot quiescent", 0);
956 else
957 run_command("reboot", 0);
958 }
959
Xindong Xu495e9682023-02-24 04:50:07 +0000960 printf("do_SetUpdateTries boot_ctrl.roll_flag = %d\n", boot_ctrl.roll_flag);
961 if (boot_ctrl.roll_flag == 1) {
962 env_set("rollback_flag", "1");
963 }
964
965#if defined(CONFIG_EFUSE_OBJ_API) && defined(CONFIG_CMD_EFUSE)
966 run_command("efuse_obj get FEAT_DISABLE_EMMC_USER", 0);
967 if (*efuse_field.data == 1)
968 nocs_mode = true;
969#endif//#ifdef CONFIG_EFUSE_OBJ_API
970
971 if (boot_ctrl.slot_info[slot].successful_boot == 1) {
972 if (gpt_partition || nocs_mode) {
973 char *bootloaderindex = NULL;
974
975 printf("current slot %d is successful_boot\n", slot);
976 bootloaderindex = env_get("forUpgrade_bootloaderIndex");
977 printf("bootloaderindex: %s\n", bootloaderindex);
978 /*if boot from boot1, means boot0 is bab, don't need to copyback*/
979 if (bootloaderindex && strcmp(bootloaderindex, "2")) {
980 printf("check if boot0 = boot1\n");
981 ret = is_BootSame(1, 2);
982 if (ret) {
983 printf("boot0 doesn't = boot1, write boot0 to boot1\n");
984 write_bootloader(1, 2);
985 printf("after write boot0 to boot1\n");
986 }
987 }
988 }
989 }
Xindong Xu0afe60a2024-05-21 16:15:13 +0800990
991 bootable_a = slot_is_bootable(&boot_ctrl.slot_info[0]);
992 bootable_b = slot_is_bootable(&boot_ctrl.slot_info[1]);
993 if (!bootable_a && !bootable_b) {
994 printf("both a & b can't bootup, enter fastboot\n");
995 boot_info_reset(&boot_ctrl);
996 boot_info_save(&boot_ctrl, miscbuf);
997 run_command("run init_display; run storeargs; run enter_fastboot;", 0);
998 }
999
Xindong Xu495e9682023-02-24 04:50:07 +00001000 return 0;
1001}
1002
Xindong Xu15e83fa2024-03-15 08:56:00 +08001003static int do_CheckABState(cmd_tbl_t *cmdtp,
1004 int flag,
1005 int argc,
1006 char * const argv[])
1007{
1008 char miscbuf[MISCBUF_SIZE] = {0};
1009 bootloader_control boot_ctrl;
1010 bool bootable_a, bootable_b;
1011 int slot;
1012 int retry_times = 0;
Xindong Xu591b9f42024-07-03 08:52:40 +08001013 char *rebootmode = env_get("reboot_mode");
Xindong Xu15e83fa2024-03-15 08:56:00 +08001014
1015 if (has_boot_slot == 0) {
1016 printf("device is not ab mode\n");
1017 return -1;
1018 }
1019
1020 boot_info_open_partition(miscbuf);
1021 boot_info_load(&boot_ctrl, miscbuf);
1022
1023 if (!boot_info_validate(&boot_ctrl)) {
1024 printf("boot-info is invalid. Resetting\n");
1025 boot_info_reset(&boot_ctrl);
1026 boot_info_save(&boot_ctrl, miscbuf);
1027 }
1028
1029 slot = get_active_slot(&boot_ctrl);
1030 bootable_a = slot_is_bootable(&boot_ctrl.slot_info[0]);
1031 bootable_b = slot_is_bootable(&boot_ctrl.slot_info[1]);
1032
1033 if ((slot == 0 && bootable_a &&
1034 boot_ctrl.slot_info[0].successful_boot == 1) ||
1035 (slot == 1 && bootable_b &&
1036 boot_ctrl.slot_info[1].successful_boot == 1) ||
1037 (!bootable_a && !bootable_b))
1038 return 0;
1039
1040 if (slot == 0 && bootable_a &&
1041 boot_ctrl.slot_info[0].successful_boot == 0)
1042 retry_times = boot_ctrl.slot_info[0].tries_remaining;
1043
1044 if (slot == 1 && bootable_b &&
1045 boot_ctrl.slot_info[1].successful_boot == 0)
1046 retry_times = boot_ctrl.slot_info[1].tries_remaining;
1047
1048 printf("ab update mode, try %d times again\n", retry_times + 1);
Xindong Xu591b9f42024-07-03 08:52:40 +08001049 if (rebootmode && (strcmp(rebootmode, "quiescent") == 0))
1050 run_command("reboot quiescent", 0);
1051 else
1052 run_command("reboot", 0);
Xindong Xu15e83fa2024-03-15 08:56:00 +08001053 return 0;
1054}
1055
Xindong Xu495e9682023-02-24 04:50:07 +00001056static int do_CopySlot(
1057 cmd_tbl_t *cmdtp,
1058 int flag,
1059 int argc,
1060 char * const argv[])
1061{
1062 char miscbuf[MISCBUF_SIZE] = {0};
1063 bootloader_control boot_ctrl;
1064 int copy = -1;
1065 int dest = -1;
1066
1067 boot_info_open_partition(miscbuf);
1068 boot_info_load(&boot_ctrl, miscbuf);
1069
1070 if (!boot_info_validate(&boot_ctrl)) {
1071 printf("boot-info is invalid. Resetting\n");
1072 boot_info_reset(&boot_ctrl);
1073 boot_info_save(&boot_ctrl, miscbuf);
1074 }
1075
1076 if (strcmp(argv[1], "1") == 0)
1077 copy = 1;
1078 else if (strcmp(argv[1], "2") == 0)
1079 copy = 2;
1080 else if (strcmp(argv[1], "0") == 0)
1081 copy = 0;
1082
1083 if (strcmp(argv[2], "1") == 0)
1084 dest = 1;
1085 else if (strcmp(argv[2], "2") == 0)
1086 dest = 2;
1087 else if (strcmp(argv[2], "0") == 0)
1088 dest = 0;
1089
Xindong Xu22e8daf2024-03-12 18:08:41 +08001090 char *fastboot_step = env_get("fastboot_step");
1091
Xindong Xu495e9682023-02-24 04:50:07 +00001092 if (copy == 1) {
Xindong Xu22e8daf2024-03-12 18:08:41 +08001093 if ((fastboot_step && (strcmp(fastboot_step, "2") == 0)) ||
1094 boot_ctrl.slot_info[0].successful_boot == 1)
Xindong Xu495e9682023-02-24 04:50:07 +00001095 write_bootloader(copy, dest);
1096 } else if (copy == 2) {
Xindong Xu22e8daf2024-03-12 18:08:41 +08001097 if ((fastboot_step && (strcmp(fastboot_step, "2") == 0)) ||
1098 boot_ctrl.slot_info[1].successful_boot == 1) {
Xindong Xu495e9682023-02-24 04:50:07 +00001099 write_bootloader(copy, dest);
1100 } else {
1101 env_set("update_env", "1");
1102 env_set("reboot_status", "reboot_next");
1103 env_set("expect_index", "2");
1104 run_command("saveenv", 0);
1105 }
1106 }
1107
1108 return 0;
1109}
1110
1111static int do_GetSystemMode(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1112{
1113#ifdef CONFIG_SYSTEM_AS_ROOT
1114 env_set("system_mode", "1");
1115#else
1116 env_set("system_mode", "0");
1117#endif
1118
1119 return 0;
1120}
1121
1122static int do_GetAvbMode(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1123{
1124#ifdef CONFIG_AVB2
1125 env_set("avb2", "1");
1126#else
1127 env_set("avb2", "0");
1128#endif
1129
1130 return 0;
1131}
1132
Xindong Xue5d4d172023-04-10 10:30:25 +08001133static int do_UpdateDt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
Xindong Xu495e9682023-02-24 04:50:07 +00001134{
1135 char *update_dt = env_get("update_dt");
Xindong Xu591b9f42024-07-03 08:52:40 +08001136 char *rebootmode = env_get("reboot_mode");
Xindong Xu495e9682023-02-24 04:50:07 +00001137
Xindong Xu15e83fa2024-03-15 08:56:00 +08001138 printf("update_dt %s\n", update_dt);
Xindong Xu495e9682023-02-24 04:50:07 +00001139 if (update_dt && (!strcmp(update_dt, "1"))) {
Xindong Xu15e83fa2024-03-15 08:56:00 +08001140 printf("write dtb from ${boot_part}\n");
Xindong Xu495e9682023-02-24 04:50:07 +00001141 run_command("imgread dtb ${boot_part} ${dtb_mem_addr}", 0);
1142 run_command("emmc dtb_write ${dtb_mem_addr} 0", 0);
1143
1144 env_set("update_dt", "0");
Xindong Xu15e83fa2024-03-15 08:56:00 +08001145#if CONFIG_IS_ENABLED(AML_UPDATE_ENV)
1146 run_command("update_env_part -p update_dt;", 0);
1147#else
Xindong Xu495e9682023-02-24 04:50:07 +00001148 run_command("saveenv", 0);
Xindong Xu15e83fa2024-03-15 08:56:00 +08001149#endif
Xindong Xu495e9682023-02-24 04:50:07 +00001150
Xindong Xu15e83fa2024-03-15 08:56:00 +08001151 char *part_changed = env_get("part_changed");
Xindong Xu495e9682023-02-24 04:50:07 +00001152 if (part_changed && (!strcmp(part_changed, "1"))) {
1153 env_set("part_changed", "0");
Xindong Xu15e83fa2024-03-15 08:56:00 +08001154#if CONFIG_IS_ENABLED(AML_UPDATE_ENV)
1155 run_command("update_env_part -p part_changed;", 0);
1156#else
Xindong Xu495e9682023-02-24 04:50:07 +00001157 run_command("saveenv", 0);
Xindong Xu15e83fa2024-03-15 08:56:00 +08001158#endif
Xindong Xu495e9682023-02-24 04:50:07 +00001159
Xindong Xu15e83fa2024-03-15 08:56:00 +08001160 printf("part changes, reset\n");
Xindong Xu591b9f42024-07-03 08:52:40 +08001161 if (rebootmode && (strcmp(rebootmode, "quiescent") == 0))
1162 run_command("reboot quiescent", 0);
1163 else
1164 run_command("reboot", 0);
Xindong Xu495e9682023-02-24 04:50:07 +00001165 }
1166 }
1167 return 0;
1168}
1169
1170#endif /* CONFIG_BOOTLOADER_CONTROL_BLOCK */
1171
1172#ifdef CONFIG_UNIFY_BOOTLOADER
1173bootctl_func_handles *get_bootctl_cmd_func_vab(void)
1174{
1175 vab_cmd_bootctrl_handles.do_GetValidSlot_func = do_GetValidSlot;
1176 vab_cmd_bootctrl_handles.do_SetActiveSlot_func = do_SetActiveSlot;
1177 vab_cmd_bootctrl_handles.do_SetRollFlag_func = do_SetRollFlag;
1178 vab_cmd_bootctrl_handles.do_CopySlot_func = do_CopySlot;
1179 vab_cmd_bootctrl_handles.do_SetUpdateTries_func = do_SetUpdateTries;
1180 vab_cmd_bootctrl_handles.do_GetSystemMode_func = do_GetSystemMode;
1181 vab_cmd_bootctrl_handles.do_GetAvbMode_func = do_GetAvbMode;
Xindong Xue5d4d172023-04-10 10:30:25 +08001182 vab_cmd_bootctrl_handles.do_UpdateDt_func = do_UpdateDt;
Xindong Xu15e83fa2024-03-15 08:56:00 +08001183 vab_cmd_bootctrl_handles.do_CheckABState_func = do_CheckABState;
Xindong Xu495e9682023-02-24 04:50:07 +00001184
1185 return &vab_cmd_bootctrl_handles;
1186}
1187
1188#else
1189
1190U_BOOT_CMD(
1191 get_valid_slot, 2, 0, do_GetValidSlot,
1192 "get_valid_slot",
1193 "\nThis command will choose valid slot to boot up which saved in misc\n"
1194 "partition by mark to decide whether execute command!\n"
1195 "So you can execute command: get_valid_slot"
1196);
1197
1198U_BOOT_CMD(
1199 set_active_slot, 2, 1, do_SetActiveSlot,
1200 "set_active_slot",
1201 "\nThis command will set active slot\n"
1202 "So you can execute command: set_active_slot a"
1203);
1204
1205U_BOOT_CMD(
1206 set_roll_flag, 2, 1, do_SetRollFlag,
1207 "set_roll_flag",
1208 "\nThis command will set active slot\n"
1209 "So you can execute command: set_active_slot a"
1210);
1211
1212U_BOOT_CMD
1213(copy_slot_bootable, 3, 1, do_CopySlot,
1214 "copy_slot_bootable",
1215 "\nThis command will set active slot\n"
1216 "So you can execute command: copy_slot_bootable 2 1"
1217);
1218
Xindong Xu15e83fa2024-03-15 08:56:00 +08001219U_BOOT_CMD
1220(check_ab, 2, 0, do_CheckABState,
1221 "check_ab",
1222 "\nThis command will check ab sate\n"
1223 "So you can execute command: check_ab"
1224);
1225
Xindong Xu495e9682023-02-24 04:50:07 +00001226U_BOOT_CMD(
1227 update_tries, 2, 0, do_SetUpdateTries,
1228 "update_tries",
1229 "\nThis command will change tries_remaining in misc\n"
1230 "So you can execute command: update_tries"
1231);
1232
1233U_BOOT_CMD(
1234 get_system_as_root_mode, 1, 0, do_GetSystemMode,
1235 "get_system_as_root_mode",
1236 "\nThis command will get system_as_root_mode\n"
1237 "So you can execute command: get_system_as_root_mode"
1238);
1239
1240U_BOOT_CMD(
1241 get_avb_mode, 1, 0, do_GetAvbMode,
1242 "get_avb_mode",
1243 "\nThis command will get avb mode\n"
1244 "So you can execute command: get_avb_mode"
1245);
1246U_BOOT_CMD
1247(update_dt, 1, 0, do_UpdateDt,
1248 "update_dt",
1249 "\nThis command will update dt\n"
1250 "So you can execute command: update_dt"
1251);
1252#endif
Mingyen Hung6e468002023-01-04 23:43:04 -08001253
1254int set_successful_boot(void) {
1255 char miscbuf[MISCBUF_SIZE] = {0};
1256 AvbABData info;
1257 int slot_num = 0;
1258 bootloader_control boot_ctrl;
1259 bool bootable = 0;
1260 int AB_mode = 0;
1261
1262 boot_info_open_partition(miscbuf);
1263 boot_info_load(&boot_ctrl, miscbuf);
1264
1265 if (!boot_info_validate(&boot_ctrl)) {
1266 printf("boot-info virtual ab is invalid. Try normal ab.\n");
1267 boot_info_load_normalAB(&info, miscbuf);
1268 if (!boot_info_validate_normalAB(&info)) {
1269 printf("boot-info is invalid.\n");
1270 /*printf("boot-info is invalid. Resetting.\n");
1271 boot_info_reset(&boot_ctrl);
1272 boot_info_save(&boot_ctrl, miscbuf);*/
1273 } else {
1274 printf("update from normal ab to virtual ab\n");
1275 AB_mode = 1;
1276 }
1277 }
1278
1279 if (AB_mode == 1) {
1280 slot_num = get_active_slot_normalAB(&info);
1281 printf("active slot = %d\n", slot_num);
1282 bootable = slot_is_bootable_normalAB(&info.slots[slot_num]);
1283 //bootable_b = slot_is_bootable_normalAB(&info.slots[1]);
1284 /*boot_info_reset(&boot_ctrl);
1285 boot_ctrl.slot_info[0].successful_boot = info.slots[0].successful_boot;
1286 boot_ctrl.slot_info[1].successful_boot = info.slots[1].successful_boot;
1287 boot_info_set_active_slot(&boot_ctrl, slot);
1288 boot_info_save(&boot_ctrl, miscbuf);
1289 slot = get_active_slot(&boot_ctrl);*/
1290 } else {
1291 slot_num = get_active_slot(&boot_ctrl);
1292 printf("active slot = %d\n", slot_num);
1293 bootable = slot_is_bootable(&boot_ctrl.slot_info[slot_num]);
1294 //bootable_b = slot_is_bootable(&boot_ctrl.slot_info[1]);
1295 }
1296
1297 if (bootable) {
1298 printf("slots[%d] is bootable\n", slot_num);
1299 return 0;
1300 }
1301
1302 return -1;
1303}
1304