blob: eb15d20d5bc75a92aa9afe6b37efa5dd003f2b14 [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.
177 uint8_t reserved1[8];
178 // CRC32 of all 28 bytes preceding this field (little endian
179 // format).
180 uint32_t crc32_le;
181}bootloader_control;
182
183#define MISC_VIRTUAL_AB_MESSAGE_VERSION 2
184#define MISC_VIRTUAL_AB_MAGIC_HEADER 0x56740AB0
185
Xindong Xu0afe60a2024-05-21 16:15:13 +0800186unsigned int kDefaultBootAttempts = 6;
Xindong Xu495e9682023-02-24 04:50:07 +0000187
188/* Magic for the A/B struct when serialized. */
189#define AVB_AB_MAGIC "\0AB0"
190#define AVB_AB_MAGIC_LEN 4
191
192/* Versioning for the on-disk A/B metadata - keep in sync with avbtool. */
193#define AVB_AB_MAJOR_VERSION 1
194#define AVB_AB_MINOR_VERSION 0
195
196/* Size of AvbABData struct. */
197#define AVB_AB_DATA_SIZE 32
198
199/* Maximum values for slot data */
200#define AVB_AB_MAX_PRIORITY 15
201#define AVB_AB_MAX_TRIES_REMAINING 7
202
203/* Struct used for recording per-slot metadata.
204 *
205 * When serialized, data is stored in network byte-order.
206 */
207typedef struct AvbABSlotData {
208 /* Slot priority. Valid values range from 0 to AVB_AB_MAX_PRIORITY,
209 * both inclusive with 1 being the lowest and AVB_AB_MAX_PRIORITY
210 * being the highest. The special value 0 is used to indicate the
211 * slot is unbootable.
212 */
213 uint8_t priority;
214
215 /* Number of times left attempting to boot this slot ranging from 0
216 * to AVB_AB_MAX_TRIES_REMAINING.
217 */
218 uint8_t tries_remaining;
219
220 /* Non-zero if this slot has booted successfully, 0 otherwise. */
221 uint8_t successful_boot;
222
223 /* Reserved for future use. */
224 uint8_t reserved[1];
225} AvbABSlotData;
226
227/* Struct used for recording A/B metadata.
228 *
229 * When serialized, data is stored in network byte-order.
230 */
231typedef struct AvbABData {
232 /* Magic number used for identification - see AVB_AB_MAGIC. */
233 uint8_t magic[AVB_AB_MAGIC_LEN];
234
235 /* Version of on-disk struct - see AVB_AB_{MAJOR,MINOR}_VERSION. */
236 uint8_t version_major;
237 uint8_t version_minor;
238
239 /* Padding to ensure |slots| field start eight bytes in. */
240 uint8_t reserved1[2];
241
242 /* Per-slot metadata. */
243 AvbABSlotData slots[2];
244
245 /* Reserved for future use. */
246 uint8_t reserved2[12];
247
248 /* CRC32 of all 28 bytes preceding this field. */
249 uint32_t crc32;
250}AvbABData;
251
252#ifdef CONFIG_UNIFY_BOOTLOADER
253bootctl_func_handles vab_cmd_bootctrl_handles = {0};
254#endif
255
256static bool boot_info_validate(bootloader_control *info)
257{
258 if (info->magic != BOOT_CTRL_MAGIC) {
259 printf("Magic 0x%x is incorrect.\n", info->magic);
260 return false;
261 }
262 return true;
263}
264
265bool boot_info_validate_normalAB(AvbABData* info)
266{
267 if (memcmp(info->magic, AVB_AB_MAGIC, AVB_AB_MAGIC_LEN) != 0) {
268 printf("Magic %s is incorrect.\n", info->magic);
269 return false;
270 }
271 if (info->version_major > AVB_AB_MAJOR_VERSION) {
272 printf("No support for given major version.\n");
273 return false;
274 }
275 return true;
276}
277
278
279void boot_info_reset(bootloader_control* boot_ctrl)
280{
281 int slot;
282
283 memset(boot_ctrl, '\0', sizeof(bootloader_control));
284 memcpy(boot_ctrl->slot_suffix, "_a", 2);
285 boot_ctrl->magic = BOOT_CTRL_MAGIC;
286 boot_ctrl->version = BOOT_CTRL_VERSION;
287 boot_ctrl->nb_slot = 2;
288 boot_ctrl->roll_flag = 0;
289
290 for (slot = 0; slot < 4; ++slot) {
291 slot_metadata entry = {};
292
293 if (slot < boot_ctrl->nb_slot) {
294 entry.priority = 7;
Xindong Xu0afe60a2024-05-21 16:15:13 +0800295 entry.tries_remaining = 0;
Xindong Xu495e9682023-02-24 04:50:07 +0000296 entry.successful_boot = 0;
297 } else {
298 entry.priority = 0; // Unbootable
299 entry.tries_remaining = 0;
300 entry.successful_boot = 0;
301 }
302
303 boot_ctrl->slot_info[slot] = entry;
304 }
Xindong Xu0afe60a2024-05-21 16:15:13 +0800305 boot_ctrl->slot_info[0].priority = 15;
306 boot_ctrl->slot_info[0].tries_remaining = kDefaultBootAttempts;
307 boot_ctrl->slot_info[0].successful_boot = 0;
Xindong Xu495e9682023-02-24 04:50:07 +0000308 boot_ctrl->recovery_tries_remaining = 0;
309}
310
311static void dump_boot_info(bootloader_control *boot_ctrl)
312{
313#if 0
314 int slot;
315
316 printf("boot_ctrl->slot_suffix = %s\n", boot_ctrl->slot_suffix);
317 printf("boot_ctrl->magic = 0x%x\n", boot_ctrl->magic);
318 printf("boot_ctrl->version = %d\n", boot_ctrl->version);
319 printf("boot_ctrl->nb_slot = %d\n", boot_ctrl->nb_slot);
320 for (slot = 0; slot < 4; ++slot) {
321 printf("boot_ctrl->slot_info[%d].priority = %d\n",
322 slot, boot_ctrl->slot_info[slot].priority);
323 printf("boot_ctrl->slot_info[%d].tries_remaining = %d\n",
324 slot, boot_ctrl->slot_info[slot].tries_remaining);
325 printf("boot_ctrl->slot_info[%d].successful_boot = %d\n",
326 slot, boot_ctrl->slot_info[slot].successful_boot);
327 }
328 printf("boot_ctrl->recovery_tries_remaining = %d\n",
329 boot_ctrl->recovery_tries_remaining);
330#endif
331}
332
333static bool slot_is_bootable(slot_metadata* slot) {
334 return slot->tries_remaining != 0;
335}
336
337static int get_active_slot(bootloader_control *info)
338{
339 if (info->slot_info[0].priority > info->slot_info[1].priority) {
340 return 0;
341 } else if (info->slot_info[0].priority == info->slot_info[1].priority) {
342 if (info->slot_info[0].successful_boot == 1)
343 return 0;
344 else
345 return 1;
346 } else {
347 return 1;
348 }
349}
350
351static bool slot_is_bootable_normalAB(AvbABSlotData* slot) {
352 return slot->priority > 0 &&
353 (slot->successful_boot || (slot->tries_remaining > 0));
354}
355
356int get_active_slot_normalAB(AvbABData* info) {
357 if (info->slots[0].priority > info->slots[1].priority)
358 return 0;
359 else
360 return 1;
361}
362
363static uint32_t vab_crc32(const uint8_t *buf, size_t size)
364{
365 static uint32_t crc_table[256];
366 uint32_t ret = -1;
367
368 // Compute the CRC-32 table only once.
369 if (!crc_table[1]) {
370 for (uint32_t i = 0; i < 256; ++i) {
371 uint32_t crc = i;
372
373 for (uint32_t j = 0; j < 8; ++j) {
374 uint32_t mask = -(crc & 1);
375
376 crc = (crc >> 1) ^ (0xEDB88320 & mask);
377 }
378 crc_table[i] = crc;
379 }
380 }
381
382 for (size_t i = 0; i < size; ++i)
383 ret = (ret >> 8) ^ crc_table[(ret ^ buf[i]) & 0xFF];
384
385 return ~ret;
386}
387
388static int boot_info_set_active_slot(bootloader_control *bootctrl, int slot)
389{
390 int i;
391 // Set every other slot with a lower priority than the new "active" slot.
392 const unsigned int kActivePriority = 15;
393 const unsigned int kActiveTries = 6;
394
395 for (i = 0; i < bootctrl->nb_slot; ++i) {
396 if (i != slot) {
397 //bootctrl->slot_info[i].priority -= 1;
398 if (bootctrl->slot_info[i].priority >= kActivePriority)
399 bootctrl->slot_info[i].priority = kActivePriority - 1;
400 }
401 printf("bootctrl->slot_info[%d].priority = %d\n", i,
402 bootctrl->slot_info[i].priority);
403 }
404
405 // Note that setting a slot as active doesn't change the successful bit.
406 // The successful bit will only be changed by setSlotAsUnbootable().
407 bootctrl->slot_info[slot].priority = kActivePriority;
408 bootctrl->slot_info[slot].tries_remaining = kActiveTries;
409
410 printf("bootctrl->slot_info[%d].priority = %d\n", slot,
411 bootctrl->slot_info[slot].priority);
412 printf("bootctrl->slot_info[%d].tries_remaining = %d\n",
413 slot, bootctrl->slot_info[slot].tries_remaining);
414
415 // Setting the current slot as active is a way to revert the operation that
416 // set *another* slot as active at the end of an updater. This is commonly
417 // used to cancel the pending update. We should only reset the verity_corrpted
418 // bit when attempting a new slot, otherwise the verity bit on the current
419 // slot would be flip.
420 if (slot != get_active_slot(bootctrl))
421 bootctrl->slot_info[slot].verity_corrupted = 0;
422
423 dump_boot_info(bootctrl);
424
425 return 0;
426}
427
428static bool boot_info_load(bootloader_control *out_info, char *miscbuf)
429{
430 memcpy(out_info, miscbuf + AB_METADATA_MISC_PARTITION_OFFSET, sizeof(bootloader_control));
431 dump_boot_info(out_info);
432 return true;
433}
434
435bool boot_info_load_normalAB(AvbABData *out_info, char *miscbuf)
436{
437 memcpy(out_info, miscbuf + AB_METADATA_MISC_PARTITION_OFFSET, AVB_AB_DATA_SIZE);
438 return true;
439}
440
441static bool boot_info_save(bootloader_control *info, char *miscbuf)
442{
443 char *partition = "misc";
444 int ret = 0;
445
446 printf("save boot-info\n");
447 info->crc32_le = vab_crc32((const uint8_t *)info,
448 sizeof(bootloader_control) - sizeof(uint32_t));
449
450 memcpy(miscbuf + AB_METADATA_MISC_PARTITION_OFFSET, info, sizeof(bootloader_control));
451 dump_boot_info(info);
Xindong Xue5d4d172023-04-10 10:30:25 +0800452
453#ifdef CONFIG_AML_MTD
454 enum boot_type_e device_boot_flag = store_get_type();
455
456 if (device_boot_flag == BOOT_NAND_NFTL || device_boot_flag == BOOT_NAND_MTD ||
457 device_boot_flag == BOOT_SNAND) {
458 int ret = 0;
459
460 ret = run_command("store erase misc 0 0x4000", 0);
461 if (ret != 0) {
462 printf("erase partition misc failed!\n");
463 return false;
464 }
Xindong Xu495e9682023-02-24 04:50:07 +0000465 }
Xindong Xue5d4d172023-04-10 10:30:25 +0800466#endif
467
Xindong Xu495e9682023-02-24 04:50:07 +0000468 ret = store_logic_write((const char *)partition, 0, MISCBUF_SIZE, (unsigned char *)miscbuf);
469 if (ret) {
470 printf("store logic write failed at %s\n", partition);
471 return false;
472 }
473 return true;
474}
475
476static int is_BootSame(int srcindex, int dstindex)
477{
478 int iRet = 0;
479 int ret = -1;
480 unsigned char *buffer_src = NULL;
481 unsigned char *buffer_dest = NULL;
482 const int SHA1SUMLEN = 20;
483 u8 gensum0[SHA1SUMLEN * 2];
484 u8 *gensum1 = gensum0 + SHA1SUMLEN;
485 int capacity_boot = 0;
486
487#ifdef CONFIG_MMC_MESON_GX
488 struct mmc *mmc = NULL;
489
490 if (store_get_type() == BOOT_EMMC)
491 mmc = find_mmc_device(1);
492
493 if (mmc)
494 capacity_boot = mmc->capacity_boot;
495#endif
496
497 printf("is_BootSame_capacity_boot: %x\n", capacity_boot);
498
499 buffer_src = (unsigned char *)malloc(capacity_boot);
500 if (!buffer_src) {
501 printf("ERROR! fail to allocate memory ...\n");
502 goto exit;
503 }
504 memset(buffer_src, 0, capacity_boot);
505
506 iRet = store_boot_read("bootloader", srcindex, 0, buffer_src);
507 if (iRet) {
508 printf("Fail read bootloader %d\n", srcindex);
509 goto exit;
510 }
511 sha1_csum(buffer_src, capacity_boot, gensum0);
512
513 buffer_dest = buffer_src;
514 memset(buffer_dest, 0, capacity_boot);
515 iRet = store_boot_read("bootloader", dstindex, 0, buffer_dest);
516 if (iRet) {
517 printf("Fail read bootloader %d\n", dstindex);
518 goto exit;
519 }
520 sha1_csum(buffer_dest, capacity_boot, gensum1);
521
522 ret = memcmp(gensum0, gensum1, SHA1SUMLEN);
523 printf("bootloader %d & %d %s same\n", srcindex, dstindex, ret ? "NOT" : "DO");
524
525exit:
526 if (buffer_src) {
527 free(buffer_src);
528 buffer_src = NULL;
529 }
530 return ret;
531}
532
533static int write_bootloader(int copy, int dstindex)
534{
535 int iRet = 0;
536 int ret = -1;
537 unsigned char *buffer = NULL;
538 int capacity_boot = 0;
539
540#ifdef CONFIG_MMC_MESON_GX
541 struct mmc *mmc = NULL;
542
543 if (store_get_type() == BOOT_EMMC)
544 mmc = find_mmc_device(1);
545#endif
546
547 if (mmc)
548 capacity_boot = mmc->capacity_boot;
549
550 printf("write_bootloader_capacity_boot: %x\n", capacity_boot);
551
552 buffer = (unsigned char *)malloc(capacity_boot);
553 if (!buffer) {
554 printf("ERROR! fail to allocate memory ...\n");
555 goto exit;
556 }
557 memset(buffer, 0, capacity_boot);
558 printf("copy from boot%d to boot%d\n", copy, dstindex);
559 iRet = store_boot_read("bootloader", copy, 0, buffer);
560 if (iRet) {
561 printf("Fail read bootloader from rsv with sz\n");
562 goto exit;
563 }
564 iRet = store_boot_write("bootloader", dstindex, 0, buffer);
565 if (iRet) {
566 printf("Failed to write bootloader\n");
567 goto exit;
568 } else {
569 ret = 0;
570 }
571
572exit:
573 if (buffer) {
574 free(buffer);
575 buffer = NULL;
576 }
577 return ret;
578}
579
Xindong Xu15e83fa2024-03-15 08:56:00 +0800580static void set_ddr_size(void)
581{
582 char ddr_size_str[32];
583 unsigned int ddr_size = 0;
584
585 memset(ddr_size_str, 0, 32);
586 ddr_size = (readl(SYSCTRL_SEC_STATUS_REG4) & 0xFFF00000) << 4;
587
588 sprintf(ddr_size_str, "%u%c", ddr_size, 'B');
589 printf("ddr_size_str = %s\n", ddr_size_str);
590 env_set("ddr_size", ddr_size_str);
591}
592
593static void update_after_failed_rollback(void)
594{
Xindong Xu0afe60a2024-05-21 16:15:13 +0800595 run_command("run init_display; run storeargs; run enter_fastboot;", 0);
Xindong Xu15e83fa2024-03-15 08:56:00 +0800596}
597
598void rollback_failure_handler(void) __attribute__((weak, alias("update_after_failed_rollback")));
599
Xindong Xu495e9682023-02-24 04:50:07 +0000600static int do_GetValidSlot(
601 cmd_tbl_t *cmdtp,
602 int flag,
603 int argc,
604 char * const argv[])
605{
606 char miscbuf[MISCBUF_SIZE] = {0};
607 bootloader_control boot_ctrl;
608 AvbABData info;
609 int slot;
610 int AB_mode = 0;
611 bool bootable_a, bootable_b;
612 bool nocs_mode = false;
Xindong Xu591b9f42024-07-03 08:52:40 +0800613 char *rebootmode = env_get("reboot_mode");
Xindong Xu495e9682023-02-24 04:50:07 +0000614
615 if (argc != 1)
616 return cmd_usage(cmdtp);
617
Xindong Xu15e83fa2024-03-15 08:56:00 +0800618 set_ddr_size();
619
Xindong Xu495e9682023-02-24 04:50:07 +0000620 boot_info_open_partition(miscbuf);
621 boot_info_load(&boot_ctrl, miscbuf);
622
623 if (!boot_info_validate(&boot_ctrl)) {
624 printf("boot-info virtual ab is invalid. Try normal ab.\n");
625 boot_info_load_normalAB(&info, miscbuf);
626 if (!boot_info_validate_normalAB(&info)) {
627 printf("boot-info is invalid. Resetting.\n");
628 boot_info_reset(&boot_ctrl);
629 boot_info_save(&boot_ctrl, miscbuf);
630 } else {
631 printf("update from normal ab to virtual ab\n");
Xindong Xu15e83fa2024-03-15 08:56:00 +0800632 env_set("normal_to_virtual", "1");
Xindong Xu495e9682023-02-24 04:50:07 +0000633 AB_mode = 1;
634 }
635 }
636
637 if (AB_mode == 1) {
638 slot = get_active_slot_normalAB(&info);
639 printf("active slot = %d\n", slot);
640 bootable_a = slot_is_bootable_normalAB(&info.slots[0]);
641 bootable_b = slot_is_bootable_normalAB(&info.slots[1]);
642 boot_info_reset(&boot_ctrl);
643 boot_ctrl.slot_info[0].successful_boot = info.slots[0].successful_boot;
644 boot_ctrl.slot_info[1].successful_boot = info.slots[1].successful_boot;
645 boot_info_set_active_slot(&boot_ctrl, slot);
646 boot_info_save(&boot_ctrl, miscbuf);
647 slot = get_active_slot(&boot_ctrl);
648 } else {
649 slot = get_active_slot(&boot_ctrl);
650 printf("active slot = %d\n", slot);
651 bootable_a = slot_is_bootable(&boot_ctrl.slot_info[0]);
652 bootable_b = slot_is_bootable(&boot_ctrl.slot_info[1]);
653 }
654
655 if (dynamic_partition)
656 env_set("partition_mode", "dynamic");
657 else
658 env_set("partition_mode", "normal");
659
660 if (gpt_partition)
661 env_set("gpt_mode", "true");
662 else
663 env_set("gpt_mode", "false");
664
665 if (vendor_boot_partition) {
666 env_set("vendor_boot_mode", "true");
667 printf("set vendor_boot_mode true\n");
668 } else {
669 env_set("vendor_boot_mode", "false");
670 printf("set vendor_boot_mode false\n");
671 }
672
673 if (slot == 0) {
674 if (bootable_a) {
675 if (has_boot_slot == 1) {
676 env_set("active_slot", "_a");
677 env_set("boot_part", "boot_a");
678 env_set("recovery_part", "recovery_a");
679 env_set("slot-suffixes", "0");
680 } else {
681 env_set("active_slot", "normal");
682 env_set("boot_part", "boot");
683 env_set("recovery_part", "recovery");
684 env_set("slot-suffixes", "-1");
685 }
686 return 0;
687 } else if (bootable_b) {
688 printf("slot a is unbootable, back to b\n");
689 boot_ctrl.roll_flag = 1;
690 boot_info_save(&boot_ctrl, miscbuf);
691 run_command("set_active_slot b", 0);
692 env_set("update_env", "1");
693 env_set("reboot_status", "reboot_next");
694
695#if defined(CONFIG_EFUSE_OBJ_API) && defined(CONFIG_CMD_EFUSE)
696 run_command("efuse_obj get FEAT_DISABLE_EMMC_USER", 0);
697 if (*efuse_field.data == 1)
698 nocs_mode = true;
699#endif//#ifdef CONFIG_EFUSE_OBJ_API
700 if (gpt_partition || nocs_mode) {
701 printf("gpt or nocs mode\n");
702 write_bootloader(2, 1);
703 env_set("expect_index", "1");
704 } else {
705 printf("normal mode\n");
706 write_bootloader(2, 0);
707 env_set("expect_index", "0");
708 }
709 run_command("saveenv", 0);
Xindong Xu591b9f42024-07-03 08:52:40 +0800710 if (rebootmode && (strcmp(rebootmode, "quiescent") == 0))
711 run_command("reboot quiescent", 0);
712 else
713 run_command("reboot", 0);
Xindong Xu495e9682023-02-24 04:50:07 +0000714 } else {
Xindong Xu0afe60a2024-05-21 16:15:13 +0800715 boot_info_reset(&boot_ctrl);
716 boot_info_save(&boot_ctrl, miscbuf);
Xindong Xu15e83fa2024-03-15 08:56:00 +0800717 rollback_failure_handler();
Xindong Xu495e9682023-02-24 04:50:07 +0000718 }
719 }
720
721 if (slot == 1) {
722 if (bootable_b) {
723 if (has_boot_slot == 1) {
724 env_set("active_slot", "_b");
725 env_set("boot_part", "boot_b");
726 env_set("recovery_part", "recovery_b");
727 env_set("slot-suffixes", "1");
728 } else {
729 env_set("active_slot", "normal");
730 env_set("boot_part", "boot");
731 env_set("recovery_part", "recovery");
732 env_set("slot-suffixes", "-1");
733 }
734 return 0;
735 } else if (bootable_a) {
736 printf("slot b is unbootable, back to a\n");
737 boot_ctrl.roll_flag = 1;
738 boot_info_save(&boot_ctrl, miscbuf);
739 run_command("set_active_slot a", 0);
740 env_set("update_env", "1");
741 env_set("reboot_status", "reboot_next");
742
743#if defined(CONFIG_EFUSE_OBJ_API) && defined(CONFIG_CMD_EFUSE)
744 run_command("efuse_obj get FEAT_DISABLE_EMMC_USER", 0);
745 if (*efuse_field.data == 1)
746 nocs_mode = true;
747#endif//#ifdef CONFIG_EFUSE_OBJ_API
748 if (gpt_partition || nocs_mode) {
749 printf("gpt or nocs mode\n");
750 write_bootloader(2, 1);
751 env_set("expect_index", "1");
752 } else {
753 printf("normal mode\n");
754 write_bootloader(1, 0);
755 env_set("expect_index", "0");
756 }
757 run_command("saveenv", 0);
Xindong Xu591b9f42024-07-03 08:52:40 +0800758 if (rebootmode && (strcmp(rebootmode, "quiescent") == 0))
759 run_command("reboot quiescent", 0);
760 else
761 run_command("reboot", 0);
Xindong Xu495e9682023-02-24 04:50:07 +0000762 } else {
Xindong Xu0afe60a2024-05-21 16:15:13 +0800763 boot_info_reset(&boot_ctrl);
764 boot_info_save(&boot_ctrl, miscbuf);
Xindong Xu15e83fa2024-03-15 08:56:00 +0800765 rollback_failure_handler();
Xindong Xu495e9682023-02-24 04:50:07 +0000766 }
767 }
768
769 return 0;
770}
771
772static int do_SetActiveSlot(
773 cmd_tbl_t *cmdtp,
774 int flag,
775 int argc,
776 char * const argv[])
777{
778 char miscbuf[MISCBUF_SIZE] = {0};
779 bootloader_control info;
780
781 if (argc != 2)
782 return cmd_usage(cmdtp);
783
784 if (has_boot_slot == 0) {
785 printf("device is not ab mode\n");
786 return -1;
787 }
788
789 boot_info_open_partition(miscbuf);
790 boot_info_load(&info, miscbuf);
791
792 if (!boot_info_validate(&info)) {
793 printf("boot-info is invalid. Resetting.\n");
794 boot_info_reset(&info);
795 boot_info_save(&info, miscbuf);
796 }
797
798 if (strcmp(argv[1], "a") == 0) {
799 env_set("active_slot", "_a");
800 env_set("slot-suffixes", "0");
801 env_set("boot_part", "boot_a");
802 env_set("recovery_part", "recovery_a");
803 printf("set active slot a\n");
804 boot_info_set_active_slot(&info, 0);
805 } else if (strcmp(argv[1], "b") == 0) {
806 env_set("active_slot", "_b");
807 env_set("slot-suffixes", "1");
808 env_set("boot_part", "boot_b");
809 env_set("recovery_part", "recovery_b");
810 printf("set active slot b\n");
811 boot_info_set_active_slot(&info, 1);
812 } else {
813 printf("error input slot\n");
814 return -1;
815 }
816
817 boot_info_save(&info, miscbuf);
818
819 printf("info.roll_flag = %d\n", info.roll_flag);
820
821 if (!gpt_partition && info.roll_flag == 1) {
822 printf("if null gpt, write dtb back when rollback\n");
823 if (run_command("imgread dtb ${boot_part} ${dtb_mem_addr}", 0)) {
824 printf("Fail in load dtb\n");
825 } else {
826 printf("write dtb back\n");
827 run_command("emmc dtb_write ${dtb_mem_addr} 0", 0);
828 }
829 }
830
831 return 0;
832}
833
834static int do_SetRollFlag
835(cmd_tbl_t *cmdtp,
836 int flag,
837 int argc,
838 char * const argv[])
839{
840 char miscbuf[MISCBUF_SIZE] = {0};
841 bootloader_control info;
842
843 if (argc != 2)
844 return cmd_usage(cmdtp);
845
846 if (has_boot_slot == 0) {
847 printf("device is not ab mode\n");
848 return -1;
849 }
850
851 boot_info_open_partition(miscbuf);
852 boot_info_load(&info, miscbuf);
853
854 if (!boot_info_validate(&info)) {
855 printf("boot-info is invalid. Resetting.\n");
856 return 0;
857 }
858
859 if (strcmp(argv[1], "1") == 0)
860 info.roll_flag = 1;
861 else
862 info.roll_flag = 0;
863
864 boot_info_save(&info, miscbuf);
865
866 printf("set info.roll_flag = %d\n", info.roll_flag);
867
868 return 0;
869}
870
871static int do_SetUpdateTries(
872 cmd_tbl_t *cmdtp,
873 int flag,
874 int argc,
875 char * const argv[])
876{
877 char miscbuf[MISCBUF_SIZE] = {0};
878 bootloader_control boot_ctrl;
879 bool bootable_a, bootable_b;
880 int slot;
881 int ret = -1;
882 bool nocs_mode = false;
Xindong Xue5d4d172023-04-10 10:30:25 +0800883 int update_flag = 0;
Xindong Xu0afe60a2024-05-21 16:15:13 +0800884 char *rebootmode = env_get("reboot_mode");
Xindong Xu495e9682023-02-24 04:50:07 +0000885
886 if (has_boot_slot == 0) {
887 printf("device is not ab mode\n");
888 return -1;
889 }
890
891 boot_info_open_partition(miscbuf);
892 boot_info_load(&boot_ctrl, miscbuf);
893
894 if (!boot_info_validate(&boot_ctrl)) {
895 printf("boot-info is invalid. Resetting\n");
896 boot_info_reset(&boot_ctrl);
897 boot_info_save(&boot_ctrl, miscbuf);
898 }
899
900 slot = get_active_slot(&boot_ctrl);
901 bootable_a = slot_is_bootable(&boot_ctrl.slot_info[0]);
902 bootable_b = slot_is_bootable(&boot_ctrl.slot_info[1]);
903
904 if (slot == 0) {
905 if (bootable_a) {
Xindong Xu0afe60a2024-05-21 16:15:13 +0800906 if (boot_ctrl.slot_info[0].successful_boot == 0 &&
907 rebootmode && strcmp(rebootmode, "fastboot")) {
Xindong Xu495e9682023-02-24 04:50:07 +0000908 boot_ctrl.slot_info[0].tries_remaining -= 1;
Xindong Xue5d4d172023-04-10 10:30:25 +0800909 update_flag = 1;
910 }
Xindong Xu495e9682023-02-24 04:50:07 +0000911 }
912 }
913
914 if (slot == 1) {
915 if (bootable_b) {
Xindong Xu0afe60a2024-05-21 16:15:13 +0800916 if (boot_ctrl.slot_info[1].successful_boot == 0 &&
917 rebootmode && strcmp(rebootmode, "fastboot")) {
Xindong Xu495e9682023-02-24 04:50:07 +0000918 boot_ctrl.slot_info[1].tries_remaining -= 1;
Xindong Xue5d4d172023-04-10 10:30:25 +0800919 update_flag = 1;
920 }
Xindong Xu495e9682023-02-24 04:50:07 +0000921 }
922 }
923
Xindong Xue5d4d172023-04-10 10:30:25 +0800924 if (update_flag == 1)
925 boot_info_save(&boot_ctrl, miscbuf);
Xindong Xu495e9682023-02-24 04:50:07 +0000926
927 printf("do_SetUpdateTries boot_ctrl.roll_flag = %d\n", boot_ctrl.roll_flag);
928 if (boot_ctrl.roll_flag == 1) {
929 env_set("rollback_flag", "1");
930 }
931
932#if defined(CONFIG_EFUSE_OBJ_API) && defined(CONFIG_CMD_EFUSE)
933 run_command("efuse_obj get FEAT_DISABLE_EMMC_USER", 0);
934 if (*efuse_field.data == 1)
935 nocs_mode = true;
936#endif//#ifdef CONFIG_EFUSE_OBJ_API
937
938 if (boot_ctrl.slot_info[slot].successful_boot == 1) {
939 if (gpt_partition || nocs_mode) {
940 char *bootloaderindex = NULL;
941
942 printf("current slot %d is successful_boot\n", slot);
943 bootloaderindex = env_get("forUpgrade_bootloaderIndex");
944 printf("bootloaderindex: %s\n", bootloaderindex);
945 /*if boot from boot1, means boot0 is bab, don't need to copyback*/
946 if (bootloaderindex && strcmp(bootloaderindex, "2")) {
947 printf("check if boot0 = boot1\n");
948 ret = is_BootSame(1, 2);
949 if (ret) {
950 printf("boot0 doesn't = boot1, write boot0 to boot1\n");
951 write_bootloader(1, 2);
952 printf("after write boot0 to boot1\n");
953 }
954 }
955 }
956 }
Xindong Xu0afe60a2024-05-21 16:15:13 +0800957
958 bootable_a = slot_is_bootable(&boot_ctrl.slot_info[0]);
959 bootable_b = slot_is_bootable(&boot_ctrl.slot_info[1]);
960 if (!bootable_a && !bootable_b) {
961 printf("both a & b can't bootup, enter fastboot\n");
962 boot_info_reset(&boot_ctrl);
963 boot_info_save(&boot_ctrl, miscbuf);
964 run_command("run init_display; run storeargs; run enter_fastboot;", 0);
965 }
966
Xindong Xu495e9682023-02-24 04:50:07 +0000967 return 0;
968}
969
Xindong Xu15e83fa2024-03-15 08:56:00 +0800970static int do_CheckABState(cmd_tbl_t *cmdtp,
971 int flag,
972 int argc,
973 char * const argv[])
974{
975 char miscbuf[MISCBUF_SIZE] = {0};
976 bootloader_control boot_ctrl;
977 bool bootable_a, bootable_b;
978 int slot;
979 int retry_times = 0;
Xindong Xu591b9f42024-07-03 08:52:40 +0800980 char *rebootmode = env_get("reboot_mode");
Xindong Xu15e83fa2024-03-15 08:56:00 +0800981
982 if (has_boot_slot == 0) {
983 printf("device is not ab mode\n");
984 return -1;
985 }
986
987 boot_info_open_partition(miscbuf);
988 boot_info_load(&boot_ctrl, miscbuf);
989
990 if (!boot_info_validate(&boot_ctrl)) {
991 printf("boot-info is invalid. Resetting\n");
992 boot_info_reset(&boot_ctrl);
993 boot_info_save(&boot_ctrl, miscbuf);
994 }
995
996 slot = get_active_slot(&boot_ctrl);
997 bootable_a = slot_is_bootable(&boot_ctrl.slot_info[0]);
998 bootable_b = slot_is_bootable(&boot_ctrl.slot_info[1]);
999
1000 if ((slot == 0 && bootable_a &&
1001 boot_ctrl.slot_info[0].successful_boot == 1) ||
1002 (slot == 1 && bootable_b &&
1003 boot_ctrl.slot_info[1].successful_boot == 1) ||
1004 (!bootable_a && !bootable_b))
1005 return 0;
1006
1007 if (slot == 0 && bootable_a &&
1008 boot_ctrl.slot_info[0].successful_boot == 0)
1009 retry_times = boot_ctrl.slot_info[0].tries_remaining;
1010
1011 if (slot == 1 && bootable_b &&
1012 boot_ctrl.slot_info[1].successful_boot == 0)
1013 retry_times = boot_ctrl.slot_info[1].tries_remaining;
1014
1015 printf("ab update mode, try %d times again\n", retry_times + 1);
Xindong Xu591b9f42024-07-03 08:52:40 +08001016 if (rebootmode && (strcmp(rebootmode, "quiescent") == 0))
1017 run_command("reboot quiescent", 0);
1018 else
1019 run_command("reboot", 0);
Xindong Xu15e83fa2024-03-15 08:56:00 +08001020 return 0;
1021}
1022
Xindong Xu495e9682023-02-24 04:50:07 +00001023static int do_CopySlot(
1024 cmd_tbl_t *cmdtp,
1025 int flag,
1026 int argc,
1027 char * const argv[])
1028{
1029 char miscbuf[MISCBUF_SIZE] = {0};
1030 bootloader_control boot_ctrl;
1031 int copy = -1;
1032 int dest = -1;
1033
1034 boot_info_open_partition(miscbuf);
1035 boot_info_load(&boot_ctrl, miscbuf);
1036
1037 if (!boot_info_validate(&boot_ctrl)) {
1038 printf("boot-info is invalid. Resetting\n");
1039 boot_info_reset(&boot_ctrl);
1040 boot_info_save(&boot_ctrl, miscbuf);
1041 }
1042
1043 if (strcmp(argv[1], "1") == 0)
1044 copy = 1;
1045 else if (strcmp(argv[1], "2") == 0)
1046 copy = 2;
1047 else if (strcmp(argv[1], "0") == 0)
1048 copy = 0;
1049
1050 if (strcmp(argv[2], "1") == 0)
1051 dest = 1;
1052 else if (strcmp(argv[2], "2") == 0)
1053 dest = 2;
1054 else if (strcmp(argv[2], "0") == 0)
1055 dest = 0;
1056
Xindong Xu22e8daf2024-03-12 18:08:41 +08001057 char *fastboot_step = env_get("fastboot_step");
1058
Xindong Xu495e9682023-02-24 04:50:07 +00001059 if (copy == 1) {
Xindong Xu22e8daf2024-03-12 18:08:41 +08001060 if ((fastboot_step && (strcmp(fastboot_step, "2") == 0)) ||
1061 boot_ctrl.slot_info[0].successful_boot == 1)
Xindong Xu495e9682023-02-24 04:50:07 +00001062 write_bootloader(copy, dest);
1063 } else if (copy == 2) {
Xindong Xu22e8daf2024-03-12 18:08:41 +08001064 if ((fastboot_step && (strcmp(fastboot_step, "2") == 0)) ||
1065 boot_ctrl.slot_info[1].successful_boot == 1) {
Xindong Xu495e9682023-02-24 04:50:07 +00001066 write_bootloader(copy, dest);
1067 } else {
1068 env_set("update_env", "1");
1069 env_set("reboot_status", "reboot_next");
1070 env_set("expect_index", "2");
1071 run_command("saveenv", 0);
1072 }
1073 }
1074
1075 return 0;
1076}
1077
1078static int do_GetSystemMode(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1079{
1080#ifdef CONFIG_SYSTEM_AS_ROOT
1081 env_set("system_mode", "1");
1082#else
1083 env_set("system_mode", "0");
1084#endif
1085
1086 return 0;
1087}
1088
1089static int do_GetAvbMode(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1090{
1091#ifdef CONFIG_AVB2
1092 env_set("avb2", "1");
1093#else
1094 env_set("avb2", "0");
1095#endif
1096
1097 return 0;
1098}
1099
Xindong Xue5d4d172023-04-10 10:30:25 +08001100static int do_UpdateDt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
Xindong Xu495e9682023-02-24 04:50:07 +00001101{
1102 char *update_dt = env_get("update_dt");
Xindong Xu591b9f42024-07-03 08:52:40 +08001103 char *rebootmode = env_get("reboot_mode");
Xindong Xu495e9682023-02-24 04:50:07 +00001104
Xindong Xu15e83fa2024-03-15 08:56:00 +08001105 printf("update_dt %s\n", update_dt);
Xindong Xu495e9682023-02-24 04:50:07 +00001106 if (update_dt && (!strcmp(update_dt, "1"))) {
Xindong Xu15e83fa2024-03-15 08:56:00 +08001107 printf("write dtb from ${boot_part}\n");
Xindong Xu495e9682023-02-24 04:50:07 +00001108 run_command("imgread dtb ${boot_part} ${dtb_mem_addr}", 0);
1109 run_command("emmc dtb_write ${dtb_mem_addr} 0", 0);
1110
1111 env_set("update_dt", "0");
Xindong Xu15e83fa2024-03-15 08:56:00 +08001112#if CONFIG_IS_ENABLED(AML_UPDATE_ENV)
1113 run_command("update_env_part -p update_dt;", 0);
1114#else
Xindong Xu495e9682023-02-24 04:50:07 +00001115 run_command("saveenv", 0);
Xindong Xu15e83fa2024-03-15 08:56:00 +08001116#endif
Xindong Xu495e9682023-02-24 04:50:07 +00001117
Xindong Xu15e83fa2024-03-15 08:56:00 +08001118 char *part_changed = env_get("part_changed");
Xindong Xu495e9682023-02-24 04:50:07 +00001119 if (part_changed && (!strcmp(part_changed, "1"))) {
1120 env_set("part_changed", "0");
Xindong Xu15e83fa2024-03-15 08:56:00 +08001121#if CONFIG_IS_ENABLED(AML_UPDATE_ENV)
1122 run_command("update_env_part -p part_changed;", 0);
1123#else
Xindong Xu495e9682023-02-24 04:50:07 +00001124 run_command("saveenv", 0);
Xindong Xu15e83fa2024-03-15 08:56:00 +08001125#endif
Xindong Xu495e9682023-02-24 04:50:07 +00001126
Xindong Xu15e83fa2024-03-15 08:56:00 +08001127 printf("part changes, reset\n");
Xindong Xu591b9f42024-07-03 08:52:40 +08001128 if (rebootmode && (strcmp(rebootmode, "quiescent") == 0))
1129 run_command("reboot quiescent", 0);
1130 else
1131 run_command("reboot", 0);
Xindong Xu495e9682023-02-24 04:50:07 +00001132 }
1133 }
1134 return 0;
1135}
1136
1137#endif /* CONFIG_BOOTLOADER_CONTROL_BLOCK */
1138
1139#ifdef CONFIG_UNIFY_BOOTLOADER
1140bootctl_func_handles *get_bootctl_cmd_func_vab(void)
1141{
1142 vab_cmd_bootctrl_handles.do_GetValidSlot_func = do_GetValidSlot;
1143 vab_cmd_bootctrl_handles.do_SetActiveSlot_func = do_SetActiveSlot;
1144 vab_cmd_bootctrl_handles.do_SetRollFlag_func = do_SetRollFlag;
1145 vab_cmd_bootctrl_handles.do_CopySlot_func = do_CopySlot;
1146 vab_cmd_bootctrl_handles.do_SetUpdateTries_func = do_SetUpdateTries;
1147 vab_cmd_bootctrl_handles.do_GetSystemMode_func = do_GetSystemMode;
1148 vab_cmd_bootctrl_handles.do_GetAvbMode_func = do_GetAvbMode;
Xindong Xue5d4d172023-04-10 10:30:25 +08001149 vab_cmd_bootctrl_handles.do_UpdateDt_func = do_UpdateDt;
Xindong Xu15e83fa2024-03-15 08:56:00 +08001150 vab_cmd_bootctrl_handles.do_CheckABState_func = do_CheckABState;
Xindong Xu495e9682023-02-24 04:50:07 +00001151
1152 return &vab_cmd_bootctrl_handles;
1153}
1154
1155#else
1156
1157U_BOOT_CMD(
1158 get_valid_slot, 2, 0, do_GetValidSlot,
1159 "get_valid_slot",
1160 "\nThis command will choose valid slot to boot up which saved in misc\n"
1161 "partition by mark to decide whether execute command!\n"
1162 "So you can execute command: get_valid_slot"
1163);
1164
1165U_BOOT_CMD(
1166 set_active_slot, 2, 1, do_SetActiveSlot,
1167 "set_active_slot",
1168 "\nThis command will set active slot\n"
1169 "So you can execute command: set_active_slot a"
1170);
1171
1172U_BOOT_CMD(
1173 set_roll_flag, 2, 1, do_SetRollFlag,
1174 "set_roll_flag",
1175 "\nThis command will set active slot\n"
1176 "So you can execute command: set_active_slot a"
1177);
1178
1179U_BOOT_CMD
1180(copy_slot_bootable, 3, 1, do_CopySlot,
1181 "copy_slot_bootable",
1182 "\nThis command will set active slot\n"
1183 "So you can execute command: copy_slot_bootable 2 1"
1184);
1185
Xindong Xu15e83fa2024-03-15 08:56:00 +08001186U_BOOT_CMD
1187(check_ab, 2, 0, do_CheckABState,
1188 "check_ab",
1189 "\nThis command will check ab sate\n"
1190 "So you can execute command: check_ab"
1191);
1192
Xindong Xu495e9682023-02-24 04:50:07 +00001193U_BOOT_CMD(
1194 update_tries, 2, 0, do_SetUpdateTries,
1195 "update_tries",
1196 "\nThis command will change tries_remaining in misc\n"
1197 "So you can execute command: update_tries"
1198);
1199
1200U_BOOT_CMD(
1201 get_system_as_root_mode, 1, 0, do_GetSystemMode,
1202 "get_system_as_root_mode",
1203 "\nThis command will get system_as_root_mode\n"
1204 "So you can execute command: get_system_as_root_mode"
1205);
1206
1207U_BOOT_CMD(
1208 get_avb_mode, 1, 0, do_GetAvbMode,
1209 "get_avb_mode",
1210 "\nThis command will get avb mode\n"
1211 "So you can execute command: get_avb_mode"
1212);
1213U_BOOT_CMD
1214(update_dt, 1, 0, do_UpdateDt,
1215 "update_dt",
1216 "\nThis command will update dt\n"
1217 "So you can execute command: update_dt"
1218);
1219#endif
Mingyen Hung6e468002023-01-04 23:43:04 -08001220
1221int set_successful_boot(void) {
1222 char miscbuf[MISCBUF_SIZE] = {0};
1223 AvbABData info;
1224 int slot_num = 0;
1225 bootloader_control boot_ctrl;
1226 bool bootable = 0;
1227 int AB_mode = 0;
1228
1229 boot_info_open_partition(miscbuf);
1230 boot_info_load(&boot_ctrl, miscbuf);
1231
1232 if (!boot_info_validate(&boot_ctrl)) {
1233 printf("boot-info virtual ab is invalid. Try normal ab.\n");
1234 boot_info_load_normalAB(&info, miscbuf);
1235 if (!boot_info_validate_normalAB(&info)) {
1236 printf("boot-info is invalid.\n");
1237 /*printf("boot-info is invalid. Resetting.\n");
1238 boot_info_reset(&boot_ctrl);
1239 boot_info_save(&boot_ctrl, miscbuf);*/
1240 } else {
1241 printf("update from normal ab to virtual ab\n");
1242 AB_mode = 1;
1243 }
1244 }
1245
1246 if (AB_mode == 1) {
1247 slot_num = get_active_slot_normalAB(&info);
1248 printf("active slot = %d\n", slot_num);
1249 bootable = slot_is_bootable_normalAB(&info.slots[slot_num]);
1250 //bootable_b = slot_is_bootable_normalAB(&info.slots[1]);
1251 /*boot_info_reset(&boot_ctrl);
1252 boot_ctrl.slot_info[0].successful_boot = info.slots[0].successful_boot;
1253 boot_ctrl.slot_info[1].successful_boot = info.slots[1].successful_boot;
1254 boot_info_set_active_slot(&boot_ctrl, slot);
1255 boot_info_save(&boot_ctrl, miscbuf);
1256 slot = get_active_slot(&boot_ctrl);*/
1257 } else {
1258 slot_num = get_active_slot(&boot_ctrl);
1259 printf("active slot = %d\n", slot_num);
1260 bootable = slot_is_bootable(&boot_ctrl.slot_info[slot_num]);
1261 //bootable_b = slot_is_bootable(&boot_ctrl.slot_info[1]);
1262 }
1263
1264 if (bootable) {
1265 printf("slots[%d] is bootable\n", slot_num);
1266 return 0;
1267 }
1268
1269 return -1;
1270}
1271