| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664 |
- /* Copyright Statement:
- *
- * This software/firmware and related documentation ("MediaTek Software") are
- * protected under relevant copyright laws. The information contained herein is
- * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
- * the prior written permission of MediaTek inc. and/or its licensors, any
- * reproduction, modification, use or disclosure of MediaTek Software, and
- * information contained herein, in whole or in part, shall be strictly
- * prohibited.
- *
- * MediaTek Inc. (C) 2016. All rights reserved.
- *
- * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
- * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
- * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
- * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
- * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
- * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
- * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
- * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
- * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
- * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
- * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
- * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
- * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
- * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
- * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
- * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
- * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
- * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
- *
- * The following software/firmware and/or related documentation ("MediaTek
- * Software") have been modified by MediaTek Inc. All revisions are subject to
- * any receiver's applicable license agreements with MediaTek Inc.
- */
- #include "bootctrl.h"
- #include "platform.h"
- #include "avb_util.h"
- #include "storage_api.h"
- #include <partition_api.h>
- #include <partition_active.h>
- #include <pal_log.h>
- #define BOOTCTR_MISC_PARTITION "misc"
- #define BOOTCTR_PARA_PARTITION "para"
- #define MOD "bootctrl"
- /******************************************************************************
- * DEBUG
- ******************************************************************************/
- static const char* suffix[2] = {BOOTCTRL_SUFFIX_A, BOOTCTRL_SUFFIX_B};
- static AvbABData metadata_saved;
- static int metadata_read = 0;
- static boot_ctrl_t zero_metadata;
- int check_suffix_with_slot(const char *suffix)
- {
- int slot = -1;
- if(suffix == NULL) {
- pal_log_err("suffix NULL\n");
- return -1;
- }
- if(strcmp(suffix, BOOTCTRL_SUFFIX_A) == 0) {
- slot = 0;
- }
- else if(strcmp(suffix, BOOTCTRL_SUFFIX_B) == 0) {
- slot = 1;
- }
- return slot;
- }
- static int read_write_partition_info_backup_restore_bootctrlv1(boot_ctrl_t *bctrl ,int mode,int offset)
- {
- blkdev_t *bootdev = NULL;
- part_t *part = NULL;
- u64 src = 0;
- u32 part_id = 0;
- int ret = -1, storage_type = 0;
- storage_type = ab_get_storage_type();
- if(storage_type == -1) {
- pal_log_err("unknown device\n");
- return -1;
- }
- if (NULL == (bootdev = blkdev_get(CFG_BOOT_DEV))) {
- pal_log_err("[%s] can't find boot device(%d)\n", MOD, CFG_BOOT_DEV);
- return -1;
- }
- part = part_get(BOOTCTR_MISC_PARTITION);
- if(part == NULL)
- part = part_get(BOOTCTR_PARA_PARTITION);
- if(part == NULL) {
- #if (CFG_DRAM_CALIB_OPTIMIZATION || EARLY_PARTITION_ACCESS)
- pal_log_debug("[%s] Try to query by sram\n", MOD);
- /* The fail might caused by dram not init yet, using sram query then */
- src = get_part_addr(BOOTCTR_MISC_PARTITION);
- if (src == 0) {
- pal_log_err("[%s] get part misc fail try para\n", MOD);
- src = get_part_addr(BOOTCTR_PARA_PARTITION);
- if (src == 0)
- pal_log_err("[%s] get part para fail\n", MOD);
- }
- part_id = storage_get_part_id(STORAGE_PHYS_PART_USER);
- #else
- pal_log_err("[%s] part_get fail\n", MOD);
- #endif
- } else {
- src = (u64)part->start_sect * bootdev->blksz;
- part_id = part->part_id;
- }
- src += OFFSETOF_SLOT_SUFFIX + offset;
- if(bctrl == NULL) {
- pal_log_err("bctrl is NULL\n");
- return ret;
- }
- if(mode == READ_PARTITION) {
- if (-1 == blkdev_read(bootdev, src, (u32)sizeof(boot_ctrl_t), (char *)bctrl, part_id)) {
- pal_log_err("[%s] part_load fail\n", MOD);
- return ret;
- }
- }
- else if(mode == WRITE_PARTITION) {
- if (-1 == blkdev_write(bootdev, src, (u32)sizeof(boot_ctrl_t), (char *)bctrl, part_id)) {
- pal_log_err("[%s] part_load fail\n", MOD);
- return ret;
- }
- }
- else {
- pal_log_err("unknown mode\n");
- return ret;
- }
- ret = 0;
- return ret;
- }
- static int read_write_partition_info(AvbABData *bctrl ,int mode)
- {
- blkdev_t *bootdev = NULL;
- part_t *part = NULL;
- u64 src = 0;
- u32 part_id = 0;
- int ret = -1, storage_type = 0;
- storage_type = ab_get_storage_type();
- if(storage_type == -1) {
- pal_log_err("unknown device\n");
- return -1;
- }
- if (NULL == (bootdev = blkdev_get(CFG_BOOT_DEV))) {
- pal_log_err("[%s] can't find boot device(%d)\n", MOD, CFG_BOOT_DEV);
- return -1;
- }
- part = part_get(BOOTCTR_MISC_PARTITION);
- if(part == NULL)
- part = part_get(BOOTCTR_PARA_PARTITION);
- if(part == NULL) {
- #if (CFG_DRAM_CALIB_OPTIMIZATION || EARLY_PARTITION_ACCESS)
- pal_log_debug("[%s] Try to query by sram\n", MOD);
- /* The fail might caused by dram not init yet, using sram query then */
- src = get_part_addr(BOOTCTR_MISC_PARTITION);
- if (src == 0) {
- pal_log_err("[%s] get part misc fail try para\n", MOD);
- src = get_part_addr(BOOTCTR_PARA_PARTITION);
- if (src == 0)
- pal_log_err("[%s] get part para fail\n", MOD);
- }
- part_id = storage_get_part_id(STORAGE_PHYS_PART_USER);
- #else
- pal_log_err("[%s] part_get fail\n", MOD);
- #endif
- } else {
- src = (u64)part->start_sect * bootdev->blksz;
- part_id = part->part_id;
- }
- src += OFFSETOF_SLOT_SUFFIX;
- if(bctrl == NULL) {
- pal_log_err("bctrl is NULL\n");
- return ret;
- }
- if(mode == READ_PARTITION) {
- if ((metadata_read) && (!memcmp(metadata_saved.magic ,AVB_AB_MAGIC, AVB_AB_MAGIC_LEN))) {
- memcpy(bctrl, &metadata_saved, sizeof(AvbABData));
- }
- else {
- if (-1 == blkdev_read(bootdev, src, (u32)sizeof(AvbABData), (char *)bctrl, part_id)) {
- pal_log_err("[%s] part_load fail\n", MOD);
- return ret;
- }
- else {
- memcpy(&metadata_saved, bctrl, sizeof(AvbABData));
- metadata_read = 1;
- }
- }
- }
- else if(mode == WRITE_PARTITION) {
- bctrl->crc32 = avb_htobe32(
- avb_crc32((const uint8_t*)bctrl, sizeof(AvbABData) - sizeof(uint32_t)));
- if (-1 == blkdev_write(bootdev, src, (u32)sizeof(AvbABData), (char *)bctrl, part_id)) {
- pal_log_err("[%s] part_load fail\n", MOD);
- return ret;
- }
- else {
- metadata_read = 0; //force to read from partition after successful blkdev_write()
- }
- }
- else {
- pal_log_err("unknown mode\n");
- return ret;
- }
- ret = 0;
- return ret;
- }
- static int ab_metadata_init(const char *suffix) {
- int slot = 0 ,slot1 = 0;
- int ret = -1 ,storage_type = -1;
- AvbABSlotData *slotp;
- AvbABData metadata;
- slot = check_suffix_with_slot(suffix);
- storage_type = ab_get_storage_type();
- if(storage_type == -1) {
- pal_log_err("unknown device\n");
- return -1;
- }
- if(slot == -1) {
- pal_log_err("ab init fail, slot: 0x%x\n", slot);
- return -1;
- }
- if(suffix == NULL) {
- pal_log_err("suffix is NULL\n");
- return -1;
- }
- ret = read_write_partition_info(&metadata, READ_PARTITION);
- if(ret < 0) {
- pal_log_err("partition_read fail, ret: 0x%x\n", ret);
- return -1;
- }
- memcpy(metadata.magic ,AVB_AB_MAGIC, AVB_AB_MAGIC_LEN);
- /* Set highest priority and reset retry count */
- slotp = &metadata.slots[slot];
- slotp->successful_boot = 0;
- slotp->priority = AVB_AB_MAX_PRIORITY;
- slotp->tries_remaining = AVB_AB_MAX_TRIES_REMAINING;
- /* Re-set arg to another slot */
- slot1 = (slot == 0) ? 1 : 0;
- slotp = &metadata.slots[slot1];
- slotp->successful_boot = 0;
- slotp->priority = AVB_AB_MAX_PRIORITY - 1;
- slotp->tries_remaining = AVB_AB_MAX_TRIES_REMAINING;
- ret = read_write_partition_info(&metadata, WRITE_PARTITION);
- if (ret < 0) {
- pal_log_err("partition_write fail, ret: 0x%x\n", ret);
- return -1;
- }
- return 0;
- }
- const char *get_suffix(void)
- {
- int slot = 0, ret = -1;
- AvbABData metadata;
- boot_ctrl_t metadatabootctrlv1;
- boot_ctrl_t metadatabootctrlv2;
- boot_part_t bootpart =BOOT_PART_NONE;
- int slot_bootctrlv1 = 0;
- ret = read_write_partition_info(&metadata, READ_PARTITION);
- if (ret < 0) {
- pal_log_err("get_suffix fail, ret: 0x%x\n", ret);
- return NULL;
- }
- if(memcmp(metadata.magic , AVB_AB_MAGIC, AVB_AB_MAGIC_LEN) != 0) {
- pal_log_err("booctrl magic not match init default value\n");
- read_write_partition_info_backup_restore_bootctrlv1(&metadatabootctrlv1,READ_PARTITION,0);
- if(metadatabootctrlv1.magic == BOOTCTRL_MAGIC){
- if(metadatabootctrlv1.slot_info[0].priority > metadatabootctrlv1.slot_info[1].priority){
- //bootctrlv1 in B part, so we need to backup bootctrv1
- read_write_partition_info_backup_restore_bootctrlv1(&metadatabootctrlv2,READ_PARTITION,32);
- //if not backup need backup (mark)
- if(metadatabootctrlv2.magic != BOOTCTRL_MAGIC)
- read_write_partition_info_backup_restore_bootctrlv1(&metadatabootctrlv1,WRITE_PARTITION,32);
- slot = 0;
- pal_log_err("reinit to BOOTCTRL_SUFFIX_A \n");
- ab_metadata_init(BOOTCTRL_SUFFIX_A);
- }else{
- //bootctrv1 in A part,no need deal, if hasbackup,need wipe
- read_write_partition_info_backup_restore_bootctrlv1(&metadatabootctrlv2,READ_PARTITION,32);
- if(metadatabootctrlv2.magic == BOOTCTRL_MAGIC){
- //wipe out
- memcpy(&metadatabootctrlv2,&zero_metadata,sizeof(boot_ctrl_t));
- read_write_partition_info_backup_restore_bootctrlv1(&metadatabootctrlv2,WRITE_PARTITION,32);
- }
- slot = 1;
- pal_log_err("reinit to BOOTCTRL_SUFFIX_B \n");
- ab_metadata_init(BOOTCTRL_SUFFIX_B);
-
- }
- }else{
- slot = 0;
- pal_log_err("reinit to BOOTCTRL_SUFFIX_A \n");
- ab_metadata_init(BOOTCTRL_SUFFIX_A);
- }
- }
- else {
- if(metadata.slots[0].priority >= metadata.slots[1].priority)
- slot = 0;
- else if (metadata.slots[0].priority < metadata.slots[1].priority)
- slot = 1;
- }
- return suffix[slot];
- }
- int rollback_slot(const char *suffix) {
- int slot = 0 ,slot1 = 0;
- int ret = -1;
- AvbABSlotData *slotp;
- AvbABData metadata;
- slot = check_suffix_with_slot(suffix);
- if(slot == -1) {
- pal_log_err("rollback_slot fail, slot: 0x%x\n", slot);
- return -1;
- }
- if(suffix == NULL) {
- pal_log_err("suffix NULL\n");
- return -1;
- }
- ret = read_write_partition_info(&metadata, READ_PARTITION);
- if(ret < 0) {
- pal_log_err("rollback_slot fail, ret: 0x%x\n", ret);
- return -1;
- }
- memcpy(metadata.magic ,AVB_AB_MAGIC, AVB_AB_MAGIC_LEN);
- /* Set highest priority and reset retry count */
- slotp = &metadata.slots[slot];
- slotp->priority = AVB_AB_MAX_PRIORITY;
- /* Ensure other slot doesn't have as high a priority. */
- slot1 = (slot == 0) ? 1 : 0;
- slotp = &metadata.slots[slot1];
- if(slotp->priority == AVB_AB_MAX_PRIORITY)
- slotp->priority = AVB_AB_MAX_PRIORITY - 1;
- ret = read_write_partition_info(&metadata, WRITE_PARTITION);
- if (ret < 0) {
- pal_log_err("partition_write fail, ret: 0x%x\n", ret);
- return -1;
- }
- return 0;
- }
- uint8_t get_retry_count(const char *suffix)
- {
- int slot = 0;
- int ret = -1;
- AvbABSlotData *slotp;
- AvbABData metadata;
- slot = check_suffix_with_slot(suffix);
- if(slot == -1) {
- pal_log_err("check fail, slot: 0x%x\n", slot);
- return -1;
- }
- ret = read_write_partition_info(&metadata, READ_PARTITION);
- if (ret < 0) {
- pal_log_err("partition_read fail, ret: 0x%x\n", ret);
- return -1;
- }
- slotp = &metadata.slots[slot];
- return slotp->tries_remaining;
- }
- int reduce_retry_count(const char *suffix)
- {
- int slot = 0, ret = -1;
- AvbABSlotData *slotp;
- AvbABData metadata;
- slot = check_suffix_with_slot(suffix);
- if(slot == -1) {
- pal_log_err("check fail, slot: 0x%x\n", slot);
- return -1;
- }
- ret = read_write_partition_info(&metadata, READ_PARTITION);
- if(ret < 0) {
- pal_log_err("partition_read fail, ret: 0x%x\n", ret);
- return -1;
- }
- slotp = &metadata.slots[slot];
- if(slotp->tries_remaining > 0)
- slotp->tries_remaining--;
- ret = read_write_partition_info(&metadata, WRITE_PARTITION);
- if(ret < 0) {
- pal_log_err("partition_write fail, ret: 0x%x\n", ret);
- return -1;
- }
- return 0;
- }
- int check_valid_slot(void)
- {
- int slot = 0, ret = -1;
- AvbABData metadata;
- ret = read_write_partition_info(&metadata, READ_PARTITION);
- if (ret < 0) {
- pal_log_err("write partition fail, ret: 0x%x\n", ret);
- return -1;
- }
- if(metadata.slots[0].priority > 0)
- return 0;
- else if (metadata.slots[1].priority > 0)
- return 0;
- return -1;
- }
- int mark_slot_invalid(const char *suffix)
- {
- int slot = 0, slot2 = 0, ret = -1;
- AvbABSlotData *slotp;
- AvbABData metadata;
- slot = check_suffix_with_slot(suffix);
- if(slot == -1) {
- pal_log_err("invliad slot , slot: 0x%x\n", slot);
- return -1;
- }
- ret = read_write_partition_info(&metadata, READ_PARTITION);
- if(ret < 0) {
- pal_log_err("part read fail, ret: 0x%x\n", ret);
- return -1;
- }
- slotp = &metadata.slots[slot];
- slotp->successful_boot = 0;
- slotp->priority = 0;
- ret = read_write_partition_info(&metadata, WRITE_PARTITION);
- if(ret < 0) {
- pal_log_err("part write fail, ret: 0x%x\n", ret);
- return -1;
- }
- return 0;
- }
- int get_bootup_status(const char *suffix)
- {
- int slot = 0, ret = -1;
- AvbABSlotData *slotp;
- AvbABData metadata;
- slot = check_suffix_with_slot(suffix);
- if(slot == -1) {
- pal_log_err("invliad slot, slot: 0x%x\n", slot);
- return -1;
- }
- ret = read_write_partition_info(&metadata, READ_PARTITION);
- if(ret < 0) {
- pal_log_err("part read fail, ret: 0x%x\n", ret);
- return -1;
- }
- slotp = &metadata.slots[slot];
- return slotp->successful_boot;
- return 0;
- }
- int ab_get_storage_type(void)
- {
- blkdev_t *bootdev = NULL;
- bootdev = blkdev_get(CFG_BOOT_DEV);
- if (bootdev == NULL) {
- pal_log_debug("%s can't find boot device(%d)\n", MOD, CFG_BOOT_DEV);
- return -1;
- }
- if (bootdev->type == BOOTDEV_SDMMC) {
- pal_log_debug("device is EMMC\n");
- return BOOTDEV_SDMMC;
- } else if (bootdev->type == BOOTDEV_UFS) {
- pal_log_debug("device is UFS\n");
- return BOOTDEV_UFS;
- }
- pal_log_debug("unknown device\n");
- return -1;
- }
- int ab_get_boot_part(u32 *bootpart)
- {
- int ret = 0, storage_type = 0;
- u32 boot_part = 0;
- storage_type = ab_get_storage_type();
- if(storage_type == -1) {
- pal_log_debug("unknown device\n");
- return -1;
- }
- if (storage_type == BOOTDEV_SDMMC) {
- ret = mmc_get_boot_part(&boot_part);
- if(boot_part == EMMC_PART_BOOT1)
- *bootpart = BOOT_PART_A;
- else if(boot_part == EMMC_PART_BOOT2)
- *bootpart = BOOT_PART_B;
- } else if (storage_type == BOOTDEV_UFS) {
- ret = ufs_get_boot_part(&boot_part);
- if(boot_part == STORAGE_PHYS_PART_BOOT1)
- *bootpart = BOOT_PART_A;
- else if(boot_part == STORAGE_PHYS_PART_BOOT2)
- *bootpart = BOOT_PART_B;
- }
- return ret;
- }
- int ab_set_boot_part(u32 bootpart)
- {
- int storage_type = 0;
- int slot = 0;
- boot_ctrl_t metadatabootctrlv1;
- if (bootpart ==BOOT_PART_B)
- restore_bootctrv1_slotB();
- storage_type = ab_get_storage_type();
- if(storage_type == -1) {
- pal_log_debug("unknown device\n");
- return -1;
- }
- if (storage_type == BOOTDEV_SDMMC) {
- return mmc_set_boot_part(bootpart);
- } else if (storage_type == BOOTDEV_UFS) {
- if (bootpart == BOOT_PART_A)
- bootpart = STORAGE_PHYS_PART_BOOT1;
- else if (bootpart == BOOT_PART_B)
- bootpart = STORAGE_PHYS_PART_BOOT2;
- return ufs_set_boot_part(bootpart);
- }
- }
- int restore_bootctrv1_slotB()
- {
- boot_ctrl_t metadatabootctrlv1;
- read_write_partition_info_backup_restore_bootctrlv1(&metadatabootctrlv1,READ_PARTITION,32);
- if(metadatabootctrlv1.magic == BOOTCTRL_MAGIC){
- set_active_slot(BOOTCTRL_SUFFIX_B);
- }
- return 0;
- }
- int set_active_slot(const char *suffix) {
- int slot = 0 ,slot1 = 0;
- int ret = -1;
- slot_metadata_t *slotp;
- boot_ctrl_t metadata;
- slot = check_suffix_with_slot(suffix);
- if(slot == -1) {
- pal_log_err("set_active_slot failed, slot: 0x%x\n", slot);
- return -1;
- }
- if(suffix == NULL) {
- pal_log_err("input suffix is NULL\n");
- return -1;
- }
- ret = read_write_partition_info_backup_restore_bootctrlv1(&metadata,READ_PARTITION,0);
- if(ret < 0) {
- pal_log_err("partition_read failed, ret: 0x%x\n", ret);
- return -1;
- }
- metadata.magic = BOOTCTRL_MAGIC;
- /* Set highest priority and reset retry count */
- slotp = &metadata.slot_info[slot];
- slotp->successful_boot = 0;
- slotp->priority = 7;
- slotp->retry_count = 3;
- slotp->normal_boot = 1;
- /* Re-set arg to another slot */
- slot1 = (slot == 0) ? 1 : 0;
- slotp = &metadata.slot_info[slot1];
- slotp->successful_boot = 0;
- slotp->priority = 0;
- slotp->retry_count = 0;
- slotp->normal_boot = 0;
- ret = read_write_partition_info_backup_restore_bootctrlv1(&metadata,WRITE_PARTITION,0);
- if (ret < 0) {
- pal_log_err("partition_write failed, ret: 0x%x\n", ret);
- return -1;
- }
- return 0;
- }
|