blob: cd66e71c860900d1509567074da521ac285aef67 [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;
Xindong Xue33fe762024-08-05 17:53:42 +0800178 u8 firstboot;
179 u8 boot_tries_remaining;
180 u8 reserved1[5];
Xindong Xu495e9682023-02-24 04:50:07 +0000181 // CRC32 of all 28 bytes preceding this field (little endian
182 // format).
183 uint32_t crc32_le;
184}bootloader_control;
185
186#define MISC_VIRTUAL_AB_MESSAGE_VERSION 2
187#define MISC_VIRTUAL_AB_MAGIC_HEADER 0x56740AB0
188
Xindong Xue33fe762024-08-05 17:53:42 +0800189#define BOOT_ATTEMPTS 4
Xindong Xu495e9682023-02-24 04:50:07 +0000190
191/* Magic for the A/B struct when serialized. */
192#define AVB_AB_MAGIC "\0AB0"
193#define AVB_AB_MAGIC_LEN 4
194
195/* Versioning for the on-disk A/B metadata - keep in sync with avbtool. */
196#define AVB_AB_MAJOR_VERSION 1
197#define AVB_AB_MINOR_VERSION 0
198
199/* Size of AvbABData struct. */
200#define AVB_AB_DATA_SIZE 32
201
202/* Maximum values for slot data */
203#define AVB_AB_MAX_PRIORITY 15
204#define AVB_AB_MAX_TRIES_REMAINING 7
205
206/* Struct used for recording per-slot metadata.
207 *
208 * When serialized, data is stored in network byte-order.
209 */
210typedef struct AvbABSlotData {
211 /* Slot priority. Valid values range from 0 to AVB_AB_MAX_PRIORITY,
212 * both inclusive with 1 being the lowest and AVB_AB_MAX_PRIORITY
213 * being the highest. The special value 0 is used to indicate the
214 * slot is unbootable.
215 */
216 uint8_t priority;
217
218 /* Number of times left attempting to boot this slot ranging from 0
219 * to AVB_AB_MAX_TRIES_REMAINING.
220 */
221 uint8_t tries_remaining;
222
223 /* Non-zero if this slot has booted successfully, 0 otherwise. */
224 uint8_t successful_boot;
225
226 /* Reserved for future use. */
227 uint8_t reserved[1];
228} AvbABSlotData;
229
230/* Struct used for recording A/B metadata.
231 *
232 * When serialized, data is stored in network byte-order.
233 */
234typedef struct AvbABData {
235 /* Magic number used for identification - see AVB_AB_MAGIC. */
236 uint8_t magic[AVB_AB_MAGIC_LEN];
237
238 /* Version of on-disk struct - see AVB_AB_{MAJOR,MINOR}_VERSION. */
239 uint8_t version_major;
240 uint8_t version_minor;
241
242 /* Padding to ensure |slots| field start eight bytes in. */
243 uint8_t reserved1[2];
244
245 /* Per-slot metadata. */
246 AvbABSlotData slots[2];
247
248 /* Reserved for future use. */
249 uint8_t reserved2[12];
250
251 /* CRC32 of all 28 bytes preceding this field. */
252 uint32_t crc32;
253}AvbABData;
254
255#ifdef CONFIG_UNIFY_BOOTLOADER
256bootctl_func_handles vab_cmd_bootctrl_handles = {0};
257#endif
258
259static bool boot_info_validate(bootloader_control *info)
260{
261 if (info->magic != BOOT_CTRL_MAGIC) {
262 printf("Magic 0x%x is incorrect.\n", info->magic);
263 return false;
264 }
265 return true;
266}
267
268bool boot_info_validate_normalAB(AvbABData* info)
269{
270 if (memcmp(info->magic, AVB_AB_MAGIC, AVB_AB_MAGIC_LEN) != 0) {
271 printf("Magic %s is incorrect.\n", info->magic);
272 return false;
273 }
274 if (info->version_major > AVB_AB_MAJOR_VERSION) {
275 printf("No support for given major version.\n");
276 return false;
277 }
278 return true;
279}
280
281
282void boot_info_reset(bootloader_control* boot_ctrl)
283{
284 int slot;
285
286 memset(boot_ctrl, '\0', sizeof(bootloader_control));
287 memcpy(boot_ctrl->slot_suffix, "_a", 2);
288 boot_ctrl->magic = BOOT_CTRL_MAGIC;
289 boot_ctrl->version = BOOT_CTRL_VERSION;
290 boot_ctrl->nb_slot = 2;
291 boot_ctrl->roll_flag = 0;
Xindong Xua6618952024-07-12 15:15:10 +0800292 boot_ctrl->merge_flag = -1;
Xindong Xue33fe762024-08-05 17:53:42 +0800293 boot_ctrl->firstboot = 1;
294 boot_ctrl->boot_tries_remaining = BOOT_ATTEMPTS;
Xindong Xu495e9682023-02-24 04:50:07 +0000295
296 for (slot = 0; slot < 4; ++slot) {
297 slot_metadata entry = {};
298
299 if (slot < boot_ctrl->nb_slot) {
300 entry.priority = 7;
Xindong Xu0afe60a2024-05-21 16:15:13 +0800301 entry.tries_remaining = 0;
Xindong Xu495e9682023-02-24 04:50:07 +0000302 entry.successful_boot = 0;
303 } else {
304 entry.priority = 0; // Unbootable
305 entry.tries_remaining = 0;
306 entry.successful_boot = 0;
307 }
308
309 boot_ctrl->slot_info[slot] = entry;
310 }
Xindong Xu0afe60a2024-05-21 16:15:13 +0800311 boot_ctrl->slot_info[0].priority = 15;
Xindong Xue33fe762024-08-05 17:53:42 +0800312 boot_ctrl->slot_info[0].tries_remaining = BOOT_ATTEMPTS;
313 boot_ctrl->slot_info[0].successful_boot = 1;
Xindong Xu495e9682023-02-24 04:50:07 +0000314 boot_ctrl->recovery_tries_remaining = 0;
315}
316
317static void dump_boot_info(bootloader_control *boot_ctrl)
318{
319#if 0
320 int slot;
321
322 printf("boot_ctrl->slot_suffix = %s\n", boot_ctrl->slot_suffix);
323 printf("boot_ctrl->magic = 0x%x\n", boot_ctrl->magic);
324 printf("boot_ctrl->version = %d\n", boot_ctrl->version);
325 printf("boot_ctrl->nb_slot = %d\n", boot_ctrl->nb_slot);
Xindong Xue33fe762024-08-05 17:53:42 +0800326 printf("boot_ctrl->firstboot = %d\n", boot_ctrl->firstboot);
327 printf("boot_ctrl->boot_tries_remaining = %d\n",
328 boot_ctrl->boot_tries_remaining);
Xindong Xu495e9682023-02-24 04:50:07 +0000329 for (slot = 0; slot < 4; ++slot) {
330 printf("boot_ctrl->slot_info[%d].priority = %d\n",
331 slot, boot_ctrl->slot_info[slot].priority);
332 printf("boot_ctrl->slot_info[%d].tries_remaining = %d\n",
333 slot, boot_ctrl->slot_info[slot].tries_remaining);
334 printf("boot_ctrl->slot_info[%d].successful_boot = %d\n",
335 slot, boot_ctrl->slot_info[slot].successful_boot);
336 }
337 printf("boot_ctrl->recovery_tries_remaining = %d\n",
338 boot_ctrl->recovery_tries_remaining);
339#endif
340}
341
342static bool slot_is_bootable(slot_metadata* slot) {
343 return slot->tries_remaining != 0;
344}
345
346static int get_active_slot(bootloader_control *info)
347{
348 if (info->slot_info[0].priority > info->slot_info[1].priority) {
349 return 0;
350 } else if (info->slot_info[0].priority == info->slot_info[1].priority) {
351 if (info->slot_info[0].successful_boot == 1)
352 return 0;
353 else
354 return 1;
355 } else {
356 return 1;
357 }
358}
359
360static bool slot_is_bootable_normalAB(AvbABSlotData* slot) {
361 return slot->priority > 0 &&
362 (slot->successful_boot || (slot->tries_remaining > 0));
363}
364
365int get_active_slot_normalAB(AvbABData* info) {
366 if (info->slots[0].priority > info->slots[1].priority)
367 return 0;
368 else
369 return 1;
370}
371
372static uint32_t vab_crc32(const uint8_t *buf, size_t size)
373{
374 static uint32_t crc_table[256];
375 uint32_t ret = -1;
376
377 // Compute the CRC-32 table only once.
378 if (!crc_table[1]) {
379 for (uint32_t i = 0; i < 256; ++i) {
380 uint32_t crc = i;
381
382 for (uint32_t j = 0; j < 8; ++j) {
383 uint32_t mask = -(crc & 1);
384
385 crc = (crc >> 1) ^ (0xEDB88320 & mask);
386 }
387 crc_table[i] = crc;
388 }
389 }
390
391 for (size_t i = 0; i < size; ++i)
392 ret = (ret >> 8) ^ crc_table[(ret ^ buf[i]) & 0xFF];
393
394 return ~ret;
395}
396
397static int boot_info_set_active_slot(bootloader_control *bootctrl, int slot)
398{
399 int i;
400 // Set every other slot with a lower priority than the new "active" slot.
401 const unsigned int kActivePriority = 15;
402 const unsigned int kActiveTries = 6;
403
404 for (i = 0; i < bootctrl->nb_slot; ++i) {
405 if (i != slot) {
406 //bootctrl->slot_info[i].priority -= 1;
407 if (bootctrl->slot_info[i].priority >= kActivePriority)
408 bootctrl->slot_info[i].priority = kActivePriority - 1;
409 }
410 printf("bootctrl->slot_info[%d].priority = %d\n", i,
411 bootctrl->slot_info[i].priority);
412 }
413
414 // Note that setting a slot as active doesn't change the successful bit.
415 // The successful bit will only be changed by setSlotAsUnbootable().
416 bootctrl->slot_info[slot].priority = kActivePriority;
417 bootctrl->slot_info[slot].tries_remaining = kActiveTries;
418
419 printf("bootctrl->slot_info[%d].priority = %d\n", slot,
420 bootctrl->slot_info[slot].priority);
421 printf("bootctrl->slot_info[%d].tries_remaining = %d\n",
422 slot, bootctrl->slot_info[slot].tries_remaining);
423
424 // Setting the current slot as active is a way to revert the operation that
425 // set *another* slot as active at the end of an updater. This is commonly
426 // used to cancel the pending update. We should only reset the verity_corrpted
427 // bit when attempting a new slot, otherwise the verity bit on the current
428 // slot would be flip.
429 if (slot != get_active_slot(bootctrl))
430 bootctrl->slot_info[slot].verity_corrupted = 0;
431
432 dump_boot_info(bootctrl);
433
434 return 0;
435}
436
437static bool boot_info_load(bootloader_control *out_info, char *miscbuf)
438{
439 memcpy(out_info, miscbuf + AB_METADATA_MISC_PARTITION_OFFSET, sizeof(bootloader_control));
440 dump_boot_info(out_info);
441 return true;
442}
443
444bool boot_info_load_normalAB(AvbABData *out_info, char *miscbuf)
445{
446 memcpy(out_info, miscbuf + AB_METADATA_MISC_PARTITION_OFFSET, AVB_AB_DATA_SIZE);
447 return true;
448}
449
450static bool boot_info_save(bootloader_control *info, char *miscbuf)
451{
452 char *partition = "misc";
453 int ret = 0;
454
455 printf("save boot-info\n");
456 info->crc32_le = vab_crc32((const uint8_t *)info,
457 sizeof(bootloader_control) - sizeof(uint32_t));
458
459 memcpy(miscbuf + AB_METADATA_MISC_PARTITION_OFFSET, info, sizeof(bootloader_control));
460 dump_boot_info(info);
Xindong Xue5d4d172023-04-10 10:30:25 +0800461
462#ifdef CONFIG_AML_MTD
463 enum boot_type_e device_boot_flag = store_get_type();
464
465 if (device_boot_flag == BOOT_NAND_NFTL || device_boot_flag == BOOT_NAND_MTD ||
466 device_boot_flag == BOOT_SNAND) {
467 int ret = 0;
468
469 ret = run_command("store erase misc 0 0x4000", 0);
470 if (ret != 0) {
471 printf("erase partition misc failed!\n");
472 return false;
473 }
Xindong Xu495e9682023-02-24 04:50:07 +0000474 }
Xindong Xue5d4d172023-04-10 10:30:25 +0800475#endif
476
Xindong Xu495e9682023-02-24 04:50:07 +0000477 ret = store_logic_write((const char *)partition, 0, MISCBUF_SIZE, (unsigned char *)miscbuf);
478 if (ret) {
479 printf("store logic write failed at %s\n", partition);
480 return false;
481 }
482 return true;
483}
484
485static int is_BootSame(int srcindex, int dstindex)
486{
487 int iRet = 0;
488 int ret = -1;
489 unsigned char *buffer_src = NULL;
490 unsigned char *buffer_dest = NULL;
491 const int SHA1SUMLEN = 20;
492 u8 gensum0[SHA1SUMLEN * 2];
493 u8 *gensum1 = gensum0 + SHA1SUMLEN;
494 int capacity_boot = 0;
495
496#ifdef CONFIG_MMC_MESON_GX
497 struct mmc *mmc = NULL;
498
499 if (store_get_type() == BOOT_EMMC)
500 mmc = find_mmc_device(1);
501
502 if (mmc)
503 capacity_boot = mmc->capacity_boot;
504#endif
505
506 printf("is_BootSame_capacity_boot: %x\n", capacity_boot);
507
508 buffer_src = (unsigned char *)malloc(capacity_boot);
509 if (!buffer_src) {
510 printf("ERROR! fail to allocate memory ...\n");
511 goto exit;
512 }
513 memset(buffer_src, 0, capacity_boot);
514
515 iRet = store_boot_read("bootloader", srcindex, 0, buffer_src);
516 if (iRet) {
517 printf("Fail read bootloader %d\n", srcindex);
518 goto exit;
519 }
520 sha1_csum(buffer_src, capacity_boot, gensum0);
521
522 buffer_dest = buffer_src;
523 memset(buffer_dest, 0, capacity_boot);
524 iRet = store_boot_read("bootloader", dstindex, 0, buffer_dest);
525 if (iRet) {
526 printf("Fail read bootloader %d\n", dstindex);
527 goto exit;
528 }
529 sha1_csum(buffer_dest, capacity_boot, gensum1);
530
531 ret = memcmp(gensum0, gensum1, SHA1SUMLEN);
532 printf("bootloader %d & %d %s same\n", srcindex, dstindex, ret ? "NOT" : "DO");
533
534exit:
535 if (buffer_src) {
536 free(buffer_src);
537 buffer_src = NULL;
538 }
539 return ret;
540}
541
542static int write_bootloader(int copy, int dstindex)
543{
544 int iRet = 0;
545 int ret = -1;
546 unsigned char *buffer = NULL;
547 int capacity_boot = 0;
548
549#ifdef CONFIG_MMC_MESON_GX
550 struct mmc *mmc = NULL;
551
552 if (store_get_type() == BOOT_EMMC)
553 mmc = find_mmc_device(1);
554#endif
555
556 if (mmc)
557 capacity_boot = mmc->capacity_boot;
558
559 printf("write_bootloader_capacity_boot: %x\n", capacity_boot);
560
561 buffer = (unsigned char *)malloc(capacity_boot);
562 if (!buffer) {
563 printf("ERROR! fail to allocate memory ...\n");
564 goto exit;
565 }
566 memset(buffer, 0, capacity_boot);
567 printf("copy from boot%d to boot%d\n", copy, dstindex);
568 iRet = store_boot_read("bootloader", copy, 0, buffer);
569 if (iRet) {
570 printf("Fail read bootloader from rsv with sz\n");
571 goto exit;
572 }
573 iRet = store_boot_write("bootloader", dstindex, 0, buffer);
574 if (iRet) {
575 printf("Failed to write bootloader\n");
576 goto exit;
577 } else {
578 ret = 0;
579 }
580
581exit:
582 if (buffer) {
583 free(buffer);
584 buffer = NULL;
585 }
586 return ret;
587}
588
Xindong Xu15e83fa2024-03-15 08:56:00 +0800589static void set_ddr_size(void)
590{
591 char ddr_size_str[32];
592 unsigned int ddr_size = 0;
593
594 memset(ddr_size_str, 0, 32);
595 ddr_size = (readl(SYSCTRL_SEC_STATUS_REG4) & 0xFFF00000) << 4;
596
597 sprintf(ddr_size_str, "%u%c", ddr_size, 'B');
598 printf("ddr_size_str = %s\n", ddr_size_str);
599 env_set("ddr_size", ddr_size_str);
600}
601
602static void update_after_failed_rollback(void)
603{
Xindong Xu0afe60a2024-05-21 16:15:13 +0800604 run_command("run init_display; run storeargs; run enter_fastboot;", 0);
Xindong Xu15e83fa2024-03-15 08:56:00 +0800605}
606
607void rollback_failure_handler(void) __attribute__((weak, alias("update_after_failed_rollback")));
608
Xindong Xu495e9682023-02-24 04:50:07 +0000609static int do_GetValidSlot(
610 cmd_tbl_t *cmdtp,
611 int flag,
612 int argc,
613 char * const argv[])
614{
615 char miscbuf[MISCBUF_SIZE] = {0};
616 bootloader_control boot_ctrl;
617 AvbABData info;
618 int slot;
619 int AB_mode = 0;
620 bool bootable_a, bootable_b;
621 bool nocs_mode = false;
Xindong Xu591b9f42024-07-03 08:52:40 +0800622 char *rebootmode = env_get("reboot_mode");
Xindong Xu495e9682023-02-24 04:50:07 +0000623
624 if (argc != 1)
625 return cmd_usage(cmdtp);
626
Xindong Xu15e83fa2024-03-15 08:56:00 +0800627 set_ddr_size();
628
Xindong Xu495e9682023-02-24 04:50:07 +0000629 boot_info_open_partition(miscbuf);
630 boot_info_load(&boot_ctrl, miscbuf);
631
632 if (!boot_info_validate(&boot_ctrl)) {
633 printf("boot-info virtual ab is invalid. Try normal ab.\n");
634 boot_info_load_normalAB(&info, miscbuf);
635 if (!boot_info_validate_normalAB(&info)) {
636 printf("boot-info is invalid. Resetting.\n");
637 boot_info_reset(&boot_ctrl);
638 boot_info_save(&boot_ctrl, miscbuf);
639 } else {
640 printf("update from normal ab to virtual ab\n");
Xindong Xu15e83fa2024-03-15 08:56:00 +0800641 env_set("normal_to_virtual", "1");
Xindong Xu495e9682023-02-24 04:50:07 +0000642 AB_mode = 1;
643 }
644 }
645
646 if (AB_mode == 1) {
647 slot = get_active_slot_normalAB(&info);
648 printf("active slot = %d\n", slot);
649 bootable_a = slot_is_bootable_normalAB(&info.slots[0]);
650 bootable_b = slot_is_bootable_normalAB(&info.slots[1]);
651 boot_info_reset(&boot_ctrl);
652 boot_ctrl.slot_info[0].successful_boot = info.slots[0].successful_boot;
653 boot_ctrl.slot_info[1].successful_boot = info.slots[1].successful_boot;
654 boot_info_set_active_slot(&boot_ctrl, slot);
655 boot_info_save(&boot_ctrl, miscbuf);
656 slot = get_active_slot(&boot_ctrl);
657 } else {
658 slot = get_active_slot(&boot_ctrl);
659 printf("active slot = %d\n", slot);
660 bootable_a = slot_is_bootable(&boot_ctrl.slot_info[0]);
661 bootable_b = slot_is_bootable(&boot_ctrl.slot_info[1]);
662 }
663
664 if (dynamic_partition)
665 env_set("partition_mode", "dynamic");
666 else
667 env_set("partition_mode", "normal");
668
669 if (gpt_partition)
670 env_set("gpt_mode", "true");
671 else
672 env_set("gpt_mode", "false");
673
674 if (vendor_boot_partition) {
675 env_set("vendor_boot_mode", "true");
676 printf("set vendor_boot_mode true\n");
677 } else {
678 env_set("vendor_boot_mode", "false");
679 printf("set vendor_boot_mode false\n");
680 }
681
682 if (slot == 0) {
683 if (bootable_a) {
684 if (has_boot_slot == 1) {
685 env_set("active_slot", "_a");
686 env_set("boot_part", "boot_a");
687 env_set("recovery_part", "recovery_a");
688 env_set("slot-suffixes", "0");
689 } else {
690 env_set("active_slot", "normal");
691 env_set("boot_part", "boot");
692 env_set("recovery_part", "recovery");
693 env_set("slot-suffixes", "-1");
694 }
695 return 0;
696 } else if (bootable_b) {
697 printf("slot a is unbootable, back to b\n");
698 boot_ctrl.roll_flag = 1;
699 boot_info_save(&boot_ctrl, miscbuf);
700 run_command("set_active_slot b", 0);
701 env_set("update_env", "1");
702 env_set("reboot_status", "reboot_next");
703
704#if defined(CONFIG_EFUSE_OBJ_API) && defined(CONFIG_CMD_EFUSE)
705 run_command("efuse_obj get FEAT_DISABLE_EMMC_USER", 0);
706 if (*efuse_field.data == 1)
707 nocs_mode = true;
708#endif//#ifdef CONFIG_EFUSE_OBJ_API
709 if (gpt_partition || nocs_mode) {
710 printf("gpt or nocs mode\n");
711 write_bootloader(2, 1);
712 env_set("expect_index", "1");
713 } else {
714 printf("normal mode\n");
715 write_bootloader(2, 0);
716 env_set("expect_index", "0");
717 }
718 run_command("saveenv", 0);
Xindong Xu591b9f42024-07-03 08:52:40 +0800719 if (rebootmode && (strcmp(rebootmode, "quiescent") == 0))
720 run_command("reboot quiescent", 0);
721 else
722 run_command("reboot", 0);
Xindong Xu495e9682023-02-24 04:50:07 +0000723 } else {
Xindong Xu0afe60a2024-05-21 16:15:13 +0800724 boot_info_reset(&boot_ctrl);
725 boot_info_save(&boot_ctrl, miscbuf);
Xindong Xu15e83fa2024-03-15 08:56:00 +0800726 rollback_failure_handler();
Xindong Xu495e9682023-02-24 04:50:07 +0000727 }
728 }
729
730 if (slot == 1) {
731 if (bootable_b) {
732 if (has_boot_slot == 1) {
733 env_set("active_slot", "_b");
734 env_set("boot_part", "boot_b");
735 env_set("recovery_part", "recovery_b");
736 env_set("slot-suffixes", "1");
737 } else {
738 env_set("active_slot", "normal");
739 env_set("boot_part", "boot");
740 env_set("recovery_part", "recovery");
741 env_set("slot-suffixes", "-1");
742 }
743 return 0;
744 } else if (bootable_a) {
745 printf("slot b is unbootable, back to a\n");
746 boot_ctrl.roll_flag = 1;
747 boot_info_save(&boot_ctrl, miscbuf);
748 run_command("set_active_slot a", 0);
749 env_set("update_env", "1");
750 env_set("reboot_status", "reboot_next");
751
752#if defined(CONFIG_EFUSE_OBJ_API) && defined(CONFIG_CMD_EFUSE)
753 run_command("efuse_obj get FEAT_DISABLE_EMMC_USER", 0);
754 if (*efuse_field.data == 1)
755 nocs_mode = true;
756#endif//#ifdef CONFIG_EFUSE_OBJ_API
757 if (gpt_partition || nocs_mode) {
758 printf("gpt or nocs mode\n");
759 write_bootloader(2, 1);
760 env_set("expect_index", "1");
761 } else {
762 printf("normal mode\n");
763 write_bootloader(1, 0);
764 env_set("expect_index", "0");
765 }
766 run_command("saveenv", 0);
Xindong Xu591b9f42024-07-03 08:52:40 +0800767 if (rebootmode && (strcmp(rebootmode, "quiescent") == 0))
768 run_command("reboot quiescent", 0);
769 else
770 run_command("reboot", 0);
Xindong Xu495e9682023-02-24 04:50:07 +0000771 } else {
Xindong Xu0afe60a2024-05-21 16:15:13 +0800772 boot_info_reset(&boot_ctrl);
773 boot_info_save(&boot_ctrl, miscbuf);
Xindong Xu15e83fa2024-03-15 08:56:00 +0800774 rollback_failure_handler();
Xindong Xu495e9682023-02-24 04:50:07 +0000775 }
776 }
777
778 return 0;
779}
780
781static int do_SetActiveSlot(
782 cmd_tbl_t *cmdtp,
783 int flag,
784 int argc,
785 char * const argv[])
786{
787 char miscbuf[MISCBUF_SIZE] = {0};
788 bootloader_control info;
789
790 if (argc != 2)
791 return cmd_usage(cmdtp);
792
793 if (has_boot_slot == 0) {
794 printf("device is not ab mode\n");
795 return -1;
796 }
797
798 boot_info_open_partition(miscbuf);
799 boot_info_load(&info, miscbuf);
800
801 if (!boot_info_validate(&info)) {
802 printf("boot-info is invalid. Resetting.\n");
803 boot_info_reset(&info);
804 boot_info_save(&info, miscbuf);
805 }
806
807 if (strcmp(argv[1], "a") == 0) {
808 env_set("active_slot", "_a");
809 env_set("slot-suffixes", "0");
810 env_set("boot_part", "boot_a");
811 env_set("recovery_part", "recovery_a");
812 printf("set active slot a\n");
813 boot_info_set_active_slot(&info, 0);
814 } else if (strcmp(argv[1], "b") == 0) {
815 env_set("active_slot", "_b");
816 env_set("slot-suffixes", "1");
817 env_set("boot_part", "boot_b");
818 env_set("recovery_part", "recovery_b");
819 printf("set active slot b\n");
820 boot_info_set_active_slot(&info, 1);
821 } else {
822 printf("error input slot\n");
823 return -1;
824 }
825
826 boot_info_save(&info, miscbuf);
827
828 printf("info.roll_flag = %d\n", info.roll_flag);
829
830 if (!gpt_partition && info.roll_flag == 1) {
831 printf("if null gpt, write dtb back when rollback\n");
832 if (run_command("imgread dtb ${boot_part} ${dtb_mem_addr}", 0)) {
833 printf("Fail in load dtb\n");
834 } else {
835 printf("write dtb back\n");
836 run_command("emmc dtb_write ${dtb_mem_addr} 0", 0);
837 }
838 }
839
840 return 0;
841}
842
843static int do_SetRollFlag
844(cmd_tbl_t *cmdtp,
845 int flag,
846 int argc,
847 char * const argv[])
848{
849 char miscbuf[MISCBUF_SIZE] = {0};
850 bootloader_control info;
851
852 if (argc != 2)
853 return cmd_usage(cmdtp);
854
855 if (has_boot_slot == 0) {
856 printf("device is not ab mode\n");
857 return -1;
858 }
859
860 boot_info_open_partition(miscbuf);
861 boot_info_load(&info, miscbuf);
862
863 if (!boot_info_validate(&info)) {
864 printf("boot-info is invalid. Resetting.\n");
865 return 0;
866 }
867
868 if (strcmp(argv[1], "1") == 0)
869 info.roll_flag = 1;
870 else
871 info.roll_flag = 0;
872
873 boot_info_save(&info, miscbuf);
874
875 printf("set info.roll_flag = %d\n", info.roll_flag);
876
877 return 0;
878}
879
880static int do_SetUpdateTries(
881 cmd_tbl_t *cmdtp,
882 int flag,
883 int argc,
884 char * const argv[])
885{
886 char miscbuf[MISCBUF_SIZE] = {0};
887 bootloader_control boot_ctrl;
888 bool bootable_a, bootable_b;
889 int slot;
890 int ret = -1;
891 bool nocs_mode = false;
Xindong Xue5d4d172023-04-10 10:30:25 +0800892 int update_flag = 0;
Xindong Xua6618952024-07-12 15:15:10 +0800893 int success_flag = -1;
894 int merge_ret = -1;
Xindong Xu0afe60a2024-05-21 16:15:13 +0800895 char *rebootmode = env_get("reboot_mode");
Xindong Xu495e9682023-02-24 04:50:07 +0000896
897 if (has_boot_slot == 0) {
898 printf("device is not ab mode\n");
899 return -1;
900 }
901
902 boot_info_open_partition(miscbuf);
903 boot_info_load(&boot_ctrl, miscbuf);
904
905 if (!boot_info_validate(&boot_ctrl)) {
906 printf("boot-info is invalid. Resetting\n");
907 boot_info_reset(&boot_ctrl);
908 boot_info_save(&boot_ctrl, miscbuf);
909 }
910
911 slot = get_active_slot(&boot_ctrl);
912 bootable_a = slot_is_bootable(&boot_ctrl.slot_info[0]);
913 bootable_b = slot_is_bootable(&boot_ctrl.slot_info[1]);
914
915 if (slot == 0) {
916 if (bootable_a) {
Xindong Xua6618952024-07-12 15:15:10 +0800917 if (boot_ctrl.slot_info[0].successful_boot == 0) {
918 success_flag = 0;
919 if (rebootmode && strcmp(rebootmode, "fastboot")) {
920 boot_ctrl.slot_info[0].tries_remaining -= 1;
921 update_flag = 1;
922 }
Xindong Xue5d4d172023-04-10 10:30:25 +0800923 }
Xindong Xu495e9682023-02-24 04:50:07 +0000924 }
925 }
926
927 if (slot == 1) {
928 if (bootable_b) {
Xindong Xua6618952024-07-12 15:15:10 +0800929 if (boot_ctrl.slot_info[1].successful_boot == 0) {
930 success_flag = 0;
931 if (rebootmode && strcmp(rebootmode, "fastboot")) {
932 boot_ctrl.slot_info[1].tries_remaining -= 1;
933 update_flag = 1;
934 }
Xindong Xue5d4d172023-04-10 10:30:25 +0800935 }
Xindong Xu495e9682023-02-24 04:50:07 +0000936 }
937 }
938
Xindong Xue33fe762024-08-05 17:53:42 +0800939 if (boot_ctrl.firstboot == 1) {
940 if (rebootmode && strcmp(rebootmode, "fastboot")) {
941 boot_ctrl.boot_tries_remaining -= 1;
942 update_flag = 1;
943 }
944 }
945
Xindong Xua6618952024-07-12 15:15:10 +0800946 printf("boot_ctrl.merge_flag = %d\n", boot_ctrl.merge_flag);
947
Xindong Xue5d4d172023-04-10 10:30:25 +0800948 if (update_flag == 1)
949 boot_info_save(&boot_ctrl, miscbuf);
Xindong Xu495e9682023-02-24 04:50:07 +0000950
Xindong Xua6618952024-07-12 15:15:10 +0800951 if (boot_ctrl.merge_flag == SNAPSHOTTED) {
952 printf("merge_flag is SNAPSHOTTED\n");
953 merge_ret = 1;
954 }
955
956 if (rebootmode && (!strcmp(rebootmode, "fastboot")) &&
957 success_flag == 0 &&
958 merge_ret == 1) {
959 printf("reboot bootloader during merge, rollback\n");
960 if (slot == 0 && bootable_a) {
961 if (boot_ctrl.slot_info[0].successful_boot == 0)
962 boot_ctrl.slot_info[0].tries_remaining = 0;
963 } else if (slot == 1 && bootable_b) {
964 if (boot_ctrl.slot_info[1].successful_boot == 0)
965 boot_ctrl.slot_info[1].tries_remaining = 0;
966 }
967 boot_info_save(&boot_ctrl, miscbuf);
968 if (rebootmode && (strcmp(rebootmode, "quiescent") == 0))
969 run_command("reboot quiescent", 0);
970 else
971 run_command("reboot", 0);
972 }
973
Xindong Xu495e9682023-02-24 04:50:07 +0000974 printf("do_SetUpdateTries boot_ctrl.roll_flag = %d\n", boot_ctrl.roll_flag);
975 if (boot_ctrl.roll_flag == 1) {
976 env_set("rollback_flag", "1");
977 }
978
979#if defined(CONFIG_EFUSE_OBJ_API) && defined(CONFIG_CMD_EFUSE)
980 run_command("efuse_obj get FEAT_DISABLE_EMMC_USER", 0);
981 if (*efuse_field.data == 1)
982 nocs_mode = true;
983#endif//#ifdef CONFIG_EFUSE_OBJ_API
984
985 if (boot_ctrl.slot_info[slot].successful_boot == 1) {
986 if (gpt_partition || nocs_mode) {
987 char *bootloaderindex = NULL;
988
989 printf("current slot %d is successful_boot\n", slot);
990 bootloaderindex = env_get("forUpgrade_bootloaderIndex");
991 printf("bootloaderindex: %s\n", bootloaderindex);
992 /*if boot from boot1, means boot0 is bab, don't need to copyback*/
993 if (bootloaderindex && strcmp(bootloaderindex, "2")) {
994 printf("check if boot0 = boot1\n");
995 ret = is_BootSame(1, 2);
996 if (ret) {
997 printf("boot0 doesn't = boot1, write boot0 to boot1\n");
998 write_bootloader(1, 2);
999 printf("after write boot0 to boot1\n");
1000 }
1001 }
1002 }
1003 }
Xindong Xu0afe60a2024-05-21 16:15:13 +08001004
1005 bootable_a = slot_is_bootable(&boot_ctrl.slot_info[0]);
1006 bootable_b = slot_is_bootable(&boot_ctrl.slot_info[1]);
Xindong Xue33fe762024-08-05 17:53:42 +08001007 if ((!bootable_a && !bootable_b) ||
1008 (boot_ctrl.firstboot == 1 && boot_ctrl.boot_tries_remaining <= 0)) {
Xindong Xu0afe60a2024-05-21 16:15:13 +08001009 printf("both a & b can't bootup, enter fastboot\n");
1010 boot_info_reset(&boot_ctrl);
1011 boot_info_save(&boot_ctrl, miscbuf);
1012 run_command("run init_display; run storeargs; run enter_fastboot;", 0);
1013 }
1014
Xindong Xu495e9682023-02-24 04:50:07 +00001015 return 0;
1016}
1017
Xindong Xu15e83fa2024-03-15 08:56:00 +08001018static int do_CheckABState(cmd_tbl_t *cmdtp,
1019 int flag,
1020 int argc,
1021 char * const argv[])
1022{
1023 char miscbuf[MISCBUF_SIZE] = {0};
1024 bootloader_control boot_ctrl;
1025 bool bootable_a, bootable_b;
1026 int slot;
1027 int retry_times = 0;
Xindong Xu591b9f42024-07-03 08:52:40 +08001028 char *rebootmode = env_get("reboot_mode");
Xindong Xu15e83fa2024-03-15 08:56:00 +08001029
1030 if (has_boot_slot == 0) {
1031 printf("device is not ab mode\n");
1032 return -1;
1033 }
1034
1035 boot_info_open_partition(miscbuf);
1036 boot_info_load(&boot_ctrl, miscbuf);
1037
1038 if (!boot_info_validate(&boot_ctrl)) {
1039 printf("boot-info is invalid. Resetting\n");
1040 boot_info_reset(&boot_ctrl);
1041 boot_info_save(&boot_ctrl, miscbuf);
1042 }
1043
1044 slot = get_active_slot(&boot_ctrl);
1045 bootable_a = slot_is_bootable(&boot_ctrl.slot_info[0]);
1046 bootable_b = slot_is_bootable(&boot_ctrl.slot_info[1]);
1047
1048 if ((slot == 0 && bootable_a &&
1049 boot_ctrl.slot_info[0].successful_boot == 1) ||
1050 (slot == 1 && bootable_b &&
1051 boot_ctrl.slot_info[1].successful_boot == 1) ||
1052 (!bootable_a && !bootable_b))
1053 return 0;
1054
1055 if (slot == 0 && bootable_a &&
1056 boot_ctrl.slot_info[0].successful_boot == 0)
1057 retry_times = boot_ctrl.slot_info[0].tries_remaining;
1058
1059 if (slot == 1 && bootable_b &&
1060 boot_ctrl.slot_info[1].successful_boot == 0)
1061 retry_times = boot_ctrl.slot_info[1].tries_remaining;
1062
1063 printf("ab update mode, try %d times again\n", retry_times + 1);
Xindong Xu591b9f42024-07-03 08:52:40 +08001064 if (rebootmode && (strcmp(rebootmode, "quiescent") == 0))
1065 run_command("reboot quiescent", 0);
1066 else
1067 run_command("reboot", 0);
Xindong Xu15e83fa2024-03-15 08:56:00 +08001068 return 0;
1069}
1070
Xindong Xu495e9682023-02-24 04:50:07 +00001071static int do_CopySlot(
1072 cmd_tbl_t *cmdtp,
1073 int flag,
1074 int argc,
1075 char * const argv[])
1076{
1077 char miscbuf[MISCBUF_SIZE] = {0};
1078 bootloader_control boot_ctrl;
1079 int copy = -1;
1080 int dest = -1;
1081
1082 boot_info_open_partition(miscbuf);
1083 boot_info_load(&boot_ctrl, miscbuf);
1084
1085 if (!boot_info_validate(&boot_ctrl)) {
1086 printf("boot-info is invalid. Resetting\n");
1087 boot_info_reset(&boot_ctrl);
1088 boot_info_save(&boot_ctrl, miscbuf);
1089 }
1090
1091 if (strcmp(argv[1], "1") == 0)
1092 copy = 1;
1093 else if (strcmp(argv[1], "2") == 0)
1094 copy = 2;
1095 else if (strcmp(argv[1], "0") == 0)
1096 copy = 0;
1097
1098 if (strcmp(argv[2], "1") == 0)
1099 dest = 1;
1100 else if (strcmp(argv[2], "2") == 0)
1101 dest = 2;
1102 else if (strcmp(argv[2], "0") == 0)
1103 dest = 0;
1104
Xindong Xu22e8daf2024-03-12 18:08:41 +08001105 char *fastboot_step = env_get("fastboot_step");
1106
Xindong Xu495e9682023-02-24 04:50:07 +00001107 if (copy == 1) {
Xindong Xu22e8daf2024-03-12 18:08:41 +08001108 if ((fastboot_step && (strcmp(fastboot_step, "2") == 0)) ||
1109 boot_ctrl.slot_info[0].successful_boot == 1)
Xindong Xu495e9682023-02-24 04:50:07 +00001110 write_bootloader(copy, dest);
1111 } else if (copy == 2) {
Xindong Xu22e8daf2024-03-12 18:08:41 +08001112 if ((fastboot_step && (strcmp(fastboot_step, "2") == 0)) ||
1113 boot_ctrl.slot_info[1].successful_boot == 1) {
Xindong Xu495e9682023-02-24 04:50:07 +00001114 write_bootloader(copy, dest);
1115 } else {
1116 env_set("update_env", "1");
1117 env_set("reboot_status", "reboot_next");
1118 env_set("expect_index", "2");
1119 run_command("saveenv", 0);
1120 }
1121 }
1122
1123 return 0;
1124}
1125
1126static int do_GetSystemMode(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1127{
1128#ifdef CONFIG_SYSTEM_AS_ROOT
1129 env_set("system_mode", "1");
1130#else
1131 env_set("system_mode", "0");
1132#endif
1133
1134 return 0;
1135}
1136
1137static int do_GetAvbMode(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1138{
1139#ifdef CONFIG_AVB2
1140 env_set("avb2", "1");
1141#else
1142 env_set("avb2", "0");
1143#endif
1144
1145 return 0;
1146}
1147
Xindong Xue5d4d172023-04-10 10:30:25 +08001148static int do_UpdateDt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
Xindong Xu495e9682023-02-24 04:50:07 +00001149{
1150 char *update_dt = env_get("update_dt");
Xindong Xu591b9f42024-07-03 08:52:40 +08001151 char *rebootmode = env_get("reboot_mode");
Xindong Xu495e9682023-02-24 04:50:07 +00001152
Xindong Xu15e83fa2024-03-15 08:56:00 +08001153 printf("update_dt %s\n", update_dt);
Xindong Xu495e9682023-02-24 04:50:07 +00001154 if (update_dt && (!strcmp(update_dt, "1"))) {
Xindong Xu15e83fa2024-03-15 08:56:00 +08001155 printf("write dtb from ${boot_part}\n");
Xindong Xu495e9682023-02-24 04:50:07 +00001156 run_command("imgread dtb ${boot_part} ${dtb_mem_addr}", 0);
1157 run_command("emmc dtb_write ${dtb_mem_addr} 0", 0);
1158
1159 env_set("update_dt", "0");
Xindong Xu15e83fa2024-03-15 08:56:00 +08001160#if CONFIG_IS_ENABLED(AML_UPDATE_ENV)
1161 run_command("update_env_part -p update_dt;", 0);
1162#else
Xindong Xu495e9682023-02-24 04:50:07 +00001163 run_command("saveenv", 0);
Xindong Xu15e83fa2024-03-15 08:56:00 +08001164#endif
Xindong Xu495e9682023-02-24 04:50:07 +00001165
Xindong Xu15e83fa2024-03-15 08:56:00 +08001166 char *part_changed = env_get("part_changed");
Xindong Xu495e9682023-02-24 04:50:07 +00001167 if (part_changed && (!strcmp(part_changed, "1"))) {
1168 env_set("part_changed", "0");
Xindong Xu15e83fa2024-03-15 08:56:00 +08001169#if CONFIG_IS_ENABLED(AML_UPDATE_ENV)
1170 run_command("update_env_part -p part_changed;", 0);
1171#else
Xindong Xu495e9682023-02-24 04:50:07 +00001172 run_command("saveenv", 0);
Xindong Xu15e83fa2024-03-15 08:56:00 +08001173#endif
Xindong Xu495e9682023-02-24 04:50:07 +00001174
Xindong Xu15e83fa2024-03-15 08:56:00 +08001175 printf("part changes, reset\n");
Xindong Xu591b9f42024-07-03 08:52:40 +08001176 if (rebootmode && (strcmp(rebootmode, "quiescent") == 0))
1177 run_command("reboot quiescent", 0);
1178 else
1179 run_command("reboot", 0);
Xindong Xu495e9682023-02-24 04:50:07 +00001180 }
1181 }
1182 return 0;
1183}
1184
1185#endif /* CONFIG_BOOTLOADER_CONTROL_BLOCK */
1186
1187#ifdef CONFIG_UNIFY_BOOTLOADER
1188bootctl_func_handles *get_bootctl_cmd_func_vab(void)
1189{
1190 vab_cmd_bootctrl_handles.do_GetValidSlot_func = do_GetValidSlot;
1191 vab_cmd_bootctrl_handles.do_SetActiveSlot_func = do_SetActiveSlot;
1192 vab_cmd_bootctrl_handles.do_SetRollFlag_func = do_SetRollFlag;
1193 vab_cmd_bootctrl_handles.do_CopySlot_func = do_CopySlot;
1194 vab_cmd_bootctrl_handles.do_SetUpdateTries_func = do_SetUpdateTries;
1195 vab_cmd_bootctrl_handles.do_GetSystemMode_func = do_GetSystemMode;
1196 vab_cmd_bootctrl_handles.do_GetAvbMode_func = do_GetAvbMode;
Xindong Xue5d4d172023-04-10 10:30:25 +08001197 vab_cmd_bootctrl_handles.do_UpdateDt_func = do_UpdateDt;
Xindong Xu15e83fa2024-03-15 08:56:00 +08001198 vab_cmd_bootctrl_handles.do_CheckABState_func = do_CheckABState;
Xindong Xu495e9682023-02-24 04:50:07 +00001199
1200 return &vab_cmd_bootctrl_handles;
1201}
1202
1203#else
1204
1205U_BOOT_CMD(
1206 get_valid_slot, 2, 0, do_GetValidSlot,
1207 "get_valid_slot",
1208 "\nThis command will choose valid slot to boot up which saved in misc\n"
1209 "partition by mark to decide whether execute command!\n"
1210 "So you can execute command: get_valid_slot"
1211);
1212
1213U_BOOT_CMD(
1214 set_active_slot, 2, 1, do_SetActiveSlot,
1215 "set_active_slot",
1216 "\nThis command will set active slot\n"
1217 "So you can execute command: set_active_slot a"
1218);
1219
1220U_BOOT_CMD(
1221 set_roll_flag, 2, 1, do_SetRollFlag,
1222 "set_roll_flag",
1223 "\nThis command will set active slot\n"
1224 "So you can execute command: set_active_slot a"
1225);
1226
1227U_BOOT_CMD
1228(copy_slot_bootable, 3, 1, do_CopySlot,
1229 "copy_slot_bootable",
1230 "\nThis command will set active slot\n"
1231 "So you can execute command: copy_slot_bootable 2 1"
1232);
1233
Xindong Xu15e83fa2024-03-15 08:56:00 +08001234U_BOOT_CMD
1235(check_ab, 2, 0, do_CheckABState,
1236 "check_ab",
1237 "\nThis command will check ab sate\n"
1238 "So you can execute command: check_ab"
1239);
1240
Xindong Xu495e9682023-02-24 04:50:07 +00001241U_BOOT_CMD(
1242 update_tries, 2, 0, do_SetUpdateTries,
1243 "update_tries",
1244 "\nThis command will change tries_remaining in misc\n"
1245 "So you can execute command: update_tries"
1246);
1247
1248U_BOOT_CMD(
1249 get_system_as_root_mode, 1, 0, do_GetSystemMode,
1250 "get_system_as_root_mode",
1251 "\nThis command will get system_as_root_mode\n"
1252 "So you can execute command: get_system_as_root_mode"
1253);
1254
1255U_BOOT_CMD(
1256 get_avb_mode, 1, 0, do_GetAvbMode,
1257 "get_avb_mode",
1258 "\nThis command will get avb mode\n"
1259 "So you can execute command: get_avb_mode"
1260);
1261U_BOOT_CMD
1262(update_dt, 1, 0, do_UpdateDt,
1263 "update_dt",
1264 "\nThis command will update dt\n"
1265 "So you can execute command: update_dt"
1266);
1267#endif
Mingyen Hung6e468002023-01-04 23:43:04 -08001268
1269int set_successful_boot(void) {
1270 char miscbuf[MISCBUF_SIZE] = {0};
1271 AvbABData info;
1272 int slot_num = 0;
1273 bootloader_control boot_ctrl;
1274 bool bootable = 0;
1275 int AB_mode = 0;
1276
1277 boot_info_open_partition(miscbuf);
1278 boot_info_load(&boot_ctrl, miscbuf);
1279
1280 if (!boot_info_validate(&boot_ctrl)) {
1281 printf("boot-info virtual ab is invalid. Try normal ab.\n");
1282 boot_info_load_normalAB(&info, miscbuf);
1283 if (!boot_info_validate_normalAB(&info)) {
1284 printf("boot-info is invalid.\n");
1285 /*printf("boot-info is invalid. Resetting.\n");
1286 boot_info_reset(&boot_ctrl);
1287 boot_info_save(&boot_ctrl, miscbuf);*/
1288 } else {
1289 printf("update from normal ab to virtual ab\n");
1290 AB_mode = 1;
1291 }
1292 }
1293
1294 if (AB_mode == 1) {
1295 slot_num = get_active_slot_normalAB(&info);
1296 printf("active slot = %d\n", slot_num);
1297 bootable = slot_is_bootable_normalAB(&info.slots[slot_num]);
1298 //bootable_b = slot_is_bootable_normalAB(&info.slots[1]);
1299 /*boot_info_reset(&boot_ctrl);
1300 boot_ctrl.slot_info[0].successful_boot = info.slots[0].successful_boot;
1301 boot_ctrl.slot_info[1].successful_boot = info.slots[1].successful_boot;
1302 boot_info_set_active_slot(&boot_ctrl, slot);
1303 boot_info_save(&boot_ctrl, miscbuf);
1304 slot = get_active_slot(&boot_ctrl);*/
1305 } else {
1306 slot_num = get_active_slot(&boot_ctrl);
1307 printf("active slot = %d\n", slot_num);
1308 bootable = slot_is_bootable(&boot_ctrl.slot_info[slot_num]);
1309 //bootable_b = slot_is_bootable(&boot_ctrl.slot_info[1]);
1310 }
1311
1312 if (bootable) {
1313 printf("slots[%d] is bootable\n", slot_num);
1314 return 0;
1315 }
1316
1317 return -1;
1318}
1319