diff --git a/Android.bp b/Android.bp index dfecee0..9515b25 100644 --- a/Android.bp +++ b/Android.bp @@ -1,3 +1,2 @@ soong_namespace { - imports: ["hardware/qcom-caf/bootctrl"], } diff --git a/Android.mk b/Android.mk index 2684877..7a6b3b6 100644 --- a/Android.mk +++ b/Android.mk @@ -16,7 +16,7 @@ LOCAL_PATH := $(call my-dir) -ifeq ($(TARGET_DEVICE), odin) +ifeq ($(TARGET_DEVICE), osaka) subdir_makefiles=$(call first-makefiles-under,$(LOCAL_PATH)) $(foreach mk,$(subdir_makefiles),$(info including $(mk) ...)$(eval include $(mk))) diff --git a/AndroidProducts.mk b/AndroidProducts.mk index 8adbf57..c46b887 100644 --- a/AndroidProducts.mk +++ b/AndroidProducts.mk @@ -15,4 +15,4 @@ # PRODUCT_MAKEFILES := \ - $(LOCAL_DIR)/twrp_odin.mk + $(LOCAL_DIR)/twrp_osaka.mk diff --git a/BoardConfig.mk b/BoardConfig.mk index 363fc3c..b360ea1 100644 --- a/BoardConfig.mk +++ b/BoardConfig.mk @@ -14,7 +14,7 @@ # limitations under the License. # -DEVICE_PATH := device/xiaomi/odin +DEVICE_PATH := device/motorola/osaka # For building with minimal manifest ALLOW_MISSING_DEPENDENCIES := true @@ -38,7 +38,7 @@ TARGET_2ND_CPU_VARIANT_RUNTIME := cortex-a55 DEXPREOPT_GENERATE_APEX_IMAGE := true # Assert -TARGET_OTA_ASSERT_DEVICE := odin +TARGET_OTA_ASSERT_DEVICE := osaka # A/B AB_OTA_UPDATER := true @@ -46,7 +46,6 @@ AB_OTA_UPDATER := true AB_OTA_PARTITIONS := \ boot \ dtbo \ - odm \ product \ system \ system_ext \ @@ -80,14 +79,12 @@ BOARD_KERNEL_CMDLINE += msm_rtb.filter=0x237 BOARD_KERNEL_CMDLINE += pcie_ports=compat BOARD_KERNEL_CMDLINE += service_locator.enable=1 BOARD_KERNEL_CMDLINE += swiotlb=0 -BOARD_KERNEL_CMDLINE += video=vfb:640x400,bpp=32,memsize=3072000 -KERNEL_LD := LD=ld.lld +KERNEL_LD := LLVM=1 TARGET_KERNEL_ADDITIONAL_FLAGS := DTC_EXT=$(shell pwd)/prebuilts/misc/linux-x86/dtc/dtc TARGET_KERNEL_CLANG_COMPILE := true -TARGET_KERNEL_CONFIG := vendor/odin-qgki_defconfig -TARGET_KERNEL_SOURCE := kernel/xiaomi/odin -NEED_KERNEL_MODULE_RECOVERY := true +TARGET_KERNEL_CONFIG := vendor/osaka_defconfig +TARGET_KERNEL_SOURCE := kernel/motorola/osaka # Metadata BOARD_USES_METADATA_PARTITION := true @@ -95,7 +92,8 @@ BOARD_USES_QCOM_FBE_DECRYPTION := true # Partitions BOARD_FLASH_BLOCK_SIZE := 131072 -BOARD_BOOTIMAGE_PARTITION_SIZE := 201326592 +BOARD_BOOTIMAGE_PARTITION_SIZE := 100663296 + BOARD_VENDOR_BOOTIMAGE_PARTITION_SIZE := 100663296 BOARD_SUPER_PARTITION_GROUPS := qti_dynamic_partitions @@ -108,15 +106,15 @@ TARGET_COPY_OUT_VENDOR := vendor # Platform BOARD_USES_QCOM_HARDWARE := true -TARGET_BOARD_PLATFORM := lahaina +TARGET_BOARD_PLATFORM := holi # Properties -TARGET_ODM_PROP += $(DEVICE_PATH)/odm.prop TARGET_SYSTEM_PROP += $(DEVICE_PATH)/system.prop TARGET_VENDOR_PROP += $(DEVICE_PATH)/vendor.prop # Recovery BOARD_USES_RECOVERY_AS_BOOT := true +TARGET_NO_RECOVERY := true TARGET_RECOVERY_FSTAB := $(DEVICE_PATH)/recovery.fstab TARGET_RECOVERY_PIXEL_FORMAT := "RGBX_8888" TARGET_USERIMAGES_USE_EXT4 := true diff --git a/bootctrl/1.1/impl/Android.bp b/bootctrl/1.1/impl/Android.bp new file mode 100644 index 0000000..3c8e3a7 --- /dev/null +++ b/bootctrl/1.1/impl/Android.bp @@ -0,0 +1,24 @@ +filegroup { + name: "android.hardware.boot@1.1-impl-qti_src", + srcs: ["BootControl.cpp"], +} + +cc_defaults { + name: "android.hardware.boot@1.1-impl-qti_defaults", + defaults: [ + "hidl_defaults", + "libboot_control_qti_defaults", + ], + relative_install_path: "hw", + vendor: true, + recovery_available: true, + srcs: [":android.hardware.boot@1.1-impl-qti_src"], + shared_libs: [ + "liblog", + "libhidlbase", + "libhardware", + "libutils", + "android.hardware.boot@1.0", + "android.hardware.boot@1.1", + ], +} diff --git a/bootctrl/1.1/impl/BootControl.cpp b/bootctrl/1.1/impl/BootControl.cpp new file mode 100644 index 0000000..4094d25 --- /dev/null +++ b/bootctrl/1.1/impl/BootControl.cpp @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define LOG_TAG "android.hardware.boot@1.1-impl-qti" + +#include + +#include + +#include "BootControl.h" + +namespace android { +namespace hardware { +namespace boot { +namespace V1_1 { +namespace implementation { + +using ::android::hardware::boot::V1_0::CommandResult; + +bool BootControl::Init() { + return bootcontrol_init(); +} + +Return BootControl::getNumberSlots() { + return get_number_slots(); +} + +Return BootControl::getCurrentSlot() { + return get_current_slot(); +} + +Return BootControl::markBootSuccessful(markBootSuccessful_cb _hidl_cb) { + int ret = mark_boot_successful(); + struct CommandResult cr; + cr.success = (ret == 0); + cr.errMsg = strerror(-ret); + _hidl_cb(cr); + return Void(); +} + +Return BootControl::setActiveBootSlot(uint32_t slot, setActiveBootSlot_cb _hidl_cb) { + int ret = set_active_boot_slot(slot); + struct CommandResult cr; + cr.success = (ret == 0); + cr.errMsg = strerror(-ret); + _hidl_cb(cr); + return Void(); +} + +Return BootControl::setSlotAsUnbootable(uint32_t slot, setSlotAsUnbootable_cb _hidl_cb) { + int ret = set_slot_as_unbootable(slot); + struct CommandResult cr; + cr.success = (ret == 0); + cr.errMsg = strerror(-ret); + _hidl_cb(cr); + return Void(); +} + +Return BootControl::isSlotBootable(uint32_t slot) { + int32_t ret = is_slot_bootable(slot); + if (ret < 0) { + return BoolResult::INVALID_SLOT; + } + return ret ? BoolResult::TRUE : BoolResult::FALSE; +} + +Return BootControl::isSlotMarkedSuccessful(uint32_t slot) { + int32_t ret = is_slot_marked_successful(slot); + if (ret < 0) { + return BoolResult::INVALID_SLOT; + } + return ret ? BoolResult::TRUE : BoolResult::FALSE; +} + +Return BootControl::getSuffix(uint32_t slot, getSuffix_cb _hidl_cb) { + hidl_string ans; + const char* suffix = get_suffix(slot); + if (suffix) { + ans = suffix; + } + _hidl_cb(ans); + return Void(); +} + +Return BootControl::setSnapshotMergeStatus(MergeStatus status) { + return set_snapshot_merge_status(status); +} + +Return BootControl::getSnapshotMergeStatus() { + return get_snapshot_merge_status(); +} + +IBootControl* HIDL_FETCH_IBootControl(const char* /* hal */) { + auto module = std::make_unique(); + if (!module->Init()) { + ALOGE("Could not initialize BootControl module"); + return nullptr; + } + return module.release(); +} + +} // namespace implementation +} // namespace V1_1 +} // namespace boot +} // namespace hardware +} // namespace android diff --git a/bootctrl/1.1/impl/BootControl.h b/bootctrl/1.1/impl/BootControl.h new file mode 100644 index 0000000..d33ec0c --- /dev/null +++ b/bootctrl/1.1/impl/BootControl.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace boot { +namespace V1_1 { +namespace implementation { + +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::hardware::boot::V1_0::BoolResult; +using ::android::hardware::boot::V1_1::IBootControl; +using ::android::hardware::boot::V1_1::MergeStatus; + +class BootControl : public IBootControl { + public: + bool Init(); + + // Methods from ::android::hardware::boot::V1_0::IBootControl follow. + Return getNumberSlots() override; + Return getCurrentSlot() override; + Return markBootSuccessful(markBootSuccessful_cb _hidl_cb) override; + Return setActiveBootSlot(uint32_t slot, setActiveBootSlot_cb _hidl_cb) override; + Return setSlotAsUnbootable(uint32_t slot, setSlotAsUnbootable_cb _hidl_cb) override; + Return isSlotBootable(uint32_t slot) override; + Return isSlotMarkedSuccessful(uint32_t slot) override; + Return getSuffix(uint32_t slot, getSuffix_cb _hidl_cb) override; + + // Methods from ::android::hardware::boot::V1_1::IBootControl follow. + Return setSnapshotMergeStatus(MergeStatus status) override; + Return getSnapshotMergeStatus() override; + +}; + +extern "C" IBootControl* HIDL_FETCH_IBootControl(const char* name); + +} // namespace implementation +} // namespace V1_1 +} // namespace boot +} // namespace hardware +} // namespace android diff --git a/bootctrl/1.1/libboot_control_qti/Android.bp b/bootctrl/1.1/libboot_control_qti/Android.bp new file mode 100644 index 0000000..10cef14 --- /dev/null +++ b/bootctrl/1.1/libboot_control_qti/Android.bp @@ -0,0 +1,38 @@ +filegroup { + name: "libboot_control_qti_src", + srcs: ["libboot_control_qti.cpp"], +} + +cc_library_headers { + name: "libboot_control_qti_headers", + vendor: true, + recovery_available: true, + export_include_dirs: ["."], +} + +cc_defaults { + name: "libboot_control_qti_defaults", + vendor: true, + recovery_available: true, + shared_libs: [ + "android.hardware.boot@1.1", + "libbase", + "libcutils", + "liblog", + "libz", + ], + static_libs: [ + "libboot_control", + "libbootloader_message_vendor", + "libfstab", + ], + owner: "qti", + cflags: [ + "-Wall", + "-Werror", + ], + srcs: [ + ":libboot_control_qti_src", + ], + header_libs: ["libboot_control_qti_headers"], +} diff --git a/bootctrl/1.1/libboot_control_qti/libboot_control_qti.cpp b/bootctrl/1.1/libboot_control_qti/libboot_control_qti.cpp new file mode 100644 index 0000000..9ff4941 --- /dev/null +++ b/bootctrl/1.1/libboot_control_qti/libboot_control_qti.cpp @@ -0,0 +1,679 @@ +/* + * Copyright (c) 2016,2020, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include +#include +#include +#include +#include +#define LOG_TAG "bootcontrolhal" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BOOTDEV_DIR "/dev/block/bootdevice/by-name" +#define BOOT_IMG_PTN_NAME "boot" +#define LUN_NAME_END_LOC 14 +#define BOOT_SLOT_PROP "ro.boot.slot_suffix" + +#define SLOT_ACTIVE 1 +#define SLOT_INACTIVE 2 +#define UPDATE_SLOT(pentry, guid, slot_state) ({ \ + memcpy(pentry, guid, TYPE_GUID_SIZE); \ + if (slot_state == SLOT_ACTIVE)\ + *(pentry + AB_FLAG_OFFSET) = AB_SLOT_ACTIVE_VAL; \ + else if (slot_state == SLOT_INACTIVE) \ + *(pentry + AB_FLAG_OFFSET) = (*(pentry + AB_FLAG_OFFSET)& \ + ~AB_PARTITION_ATTR_SLOT_ACTIVE); \ + }) + +using namespace std; +const char *slot_suffix_arr[] = { + AB_SLOT_A_SUFFIX, + AB_SLOT_B_SUFFIX, + NULL}; + +enum part_attr_type { + ATTR_SLOT_ACTIVE = 0, + ATTR_BOOT_SUCCESSFUL, + ATTR_UNBOOTABLE, +}; + +using ::android::bootable::GetMiscVirtualAbMergeStatus; +using ::android::bootable::InitMiscVirtualAbMessageIfNeeded; +using ::android::bootable::SetMiscVirtualAbMergeStatus; +using ::android::hardware::boot::V1_1::MergeStatus; + +//Get the value of one of the attribute fields for a partition. +static int get_partition_attribute(char *partname, + enum part_attr_type part_attr) +{ + struct gpt_disk *disk = NULL; + uint8_t *pentry = NULL; + int retval = -1; + uint8_t *attr = NULL; + if (!partname) + goto error; + disk = gpt_disk_alloc(); + if (!disk) { + ALOGE("%s: Failed to alloc disk struct", __func__); + goto error; + } + if (gpt_disk_get_disk_info(partname, disk)) { + ALOGE("%s: Failed to get disk info", __func__); + goto error; + } + pentry = gpt_disk_get_pentry(disk, partname, PRIMARY_GPT); + if (!pentry) { + ALOGE("%s: pentry does not exist in disk struct", + __func__); + goto error; + } + attr = pentry + AB_FLAG_OFFSET; + if (part_attr == ATTR_SLOT_ACTIVE) + retval = !!(*attr & AB_PARTITION_ATTR_SLOT_ACTIVE); + else if (part_attr == ATTR_BOOT_SUCCESSFUL) + retval = !!(*attr & AB_PARTITION_ATTR_BOOT_SUCCESSFUL); + else if (part_attr == ATTR_UNBOOTABLE) + retval = !!(*attr & AB_PARTITION_ATTR_UNBOOTABLE); + else + retval = -1; + gpt_disk_free(disk); + return retval; +error: + if (disk) + gpt_disk_free(disk); + return retval; +} + +//Set a particular attribute for all the partitions in a +//slot +static int update_slot_attribute(const char *slot, + enum part_attr_type ab_attr) +{ + unsigned int i = 0; + char buf[PATH_MAX]; + struct stat st; + struct gpt_disk *disk = NULL; + uint8_t *pentry = NULL; + uint8_t *pentry_bak = NULL; + int rc = -1; + uint8_t *attr = NULL; + uint8_t *attr_bak = NULL; + char partName[MAX_GPT_NAME_SIZE + 1] = {0}; + const char ptn_list[][MAX_GPT_NAME_SIZE] = { AB_PTN_LIST }; + int slot_name_valid = 0; + if (!slot) { + ALOGE("%s: Invalid argument", __func__); + goto error; + } + for (i = 0; slot_suffix_arr[i] != NULL; i++) + { + if (!strncmp(slot, slot_suffix_arr[i], + strlen(slot_suffix_arr[i]))) + slot_name_valid = 1; + } + if (!slot_name_valid) { + ALOGE("%s: Invalid slot name", __func__); + goto error; + } + for (i=0; i < ARRAY_SIZE(ptn_list); i++) { + memset(buf, '\0', sizeof(buf)); + //Check if A/B versions of this ptn exist + snprintf(buf, sizeof(buf) - 1, + "%s/%s%s", + BOOT_DEV_DIR, + ptn_list[i], + AB_SLOT_A_SUFFIX + ); + if (stat(buf, &st)) { + //partition does not have _a version + continue; + } + memset(buf, '\0', sizeof(buf)); + snprintf(buf, sizeof(buf) - 1, + "%s/%s%s", + BOOT_DEV_DIR, + ptn_list[i], + AB_SLOT_B_SUFFIX + ); + if (stat(buf, &st)) { + //partition does not have _a version + continue; + } + memset(partName, '\0', sizeof(partName)); + snprintf(partName, + sizeof(partName) - 1, + "%s%s", + ptn_list[i], + slot); + disk = gpt_disk_alloc(); + if (!disk) { + ALOGE("%s: Failed to alloc disk struct", + __func__); + goto error; + } + rc = gpt_disk_get_disk_info(partName, disk); + if (rc != 0) { + ALOGE("%s: Failed to get disk info for %s", + __func__, + partName); + goto error; + } + pentry = gpt_disk_get_pentry(disk, partName, PRIMARY_GPT); + pentry_bak = gpt_disk_get_pentry(disk, partName, SECONDARY_GPT); + if (!pentry || !pentry_bak) { + ALOGE("%s: Failed to get pentry/pentry_bak for %s", + __func__, + partName); + goto error; + } + attr = pentry + AB_FLAG_OFFSET; + attr_bak = pentry_bak + AB_FLAG_OFFSET; + if (ab_attr == ATTR_BOOT_SUCCESSFUL) { + *attr = (*attr) | AB_PARTITION_ATTR_BOOT_SUCCESSFUL; + *attr_bak = (*attr_bak) | + AB_PARTITION_ATTR_BOOT_SUCCESSFUL; + } else if (ab_attr == ATTR_UNBOOTABLE) { + *attr = (*attr) | AB_PARTITION_ATTR_UNBOOTABLE; + *attr_bak = (*attr_bak) | AB_PARTITION_ATTR_UNBOOTABLE; + } else if (ab_attr == ATTR_SLOT_ACTIVE) { + *attr = (*attr) | AB_PARTITION_ATTR_SLOT_ACTIVE; + *attr_bak = (*attr) | AB_PARTITION_ATTR_SLOT_ACTIVE; + } else { + ALOGE("%s: Unrecognized attr", __func__); + goto error; + } + if (gpt_disk_update_crc(disk)) { + ALOGE("%s: Failed to update crc for %s", + __func__, + partName); + goto error; + } + if (gpt_disk_commit(disk)) { + ALOGE("%s: Failed to write back entry for %s", + __func__, + partName); + goto error; + } + gpt_disk_free(disk); + disk = NULL; + } + return 0; +error: + if (disk) + gpt_disk_free(disk); + return -1; +} + +static int boot_control_check_slot_sanity(unsigned slot) +{ + uint32_t num_slots = get_number_slots(); + if ((num_slots < 1) || (slot > num_slots - 1)) { + ALOGE("Invalid slot number"); + return -1; + } + return 0; + +} + +//Return a gpt disk structure representing the disk that holds +//partition. +static struct gpt_disk* boot_ctl_get_disk_info(char *partition) +{ + struct gpt_disk *disk = NULL; + if (!partition) + return NULL; + disk = gpt_disk_alloc(); + if (!disk) { + ALOGE("%s: Failed to alloc disk", + __func__); + goto error; + } + if (gpt_disk_get_disk_info(partition, disk)) { + ALOGE("failed to get disk info for %s", + partition); + goto error; + } + return disk; +error: + if (disk) + gpt_disk_free(disk); + return NULL; +} + +//The argument here is a vector of partition names(including the slot suffix) +//that lie on a single disk +static int boot_ctl_set_active_slot_for_partitions(vector part_list, + unsigned slot) +{ + char buf[PATH_MAX] = {0}; + struct gpt_disk *diskA = NULL; + struct gpt_disk *diskB = NULL; + char slotA[MAX_GPT_NAME_SIZE + 1] = {0}; + char slotB[MAX_GPT_NAME_SIZE + 1] = {0}; + char active_guid[TYPE_GUID_SIZE + 1] = {0}; + char inactive_guid[TYPE_GUID_SIZE + 1] = {0}; + //Pointer to the partition entry of current 'A' partition + uint8_t *pentryA = NULL; + uint8_t *pentryA_bak = NULL; + //Pointer to partition entry of current 'B' partition + uint8_t *pentryB = NULL; + uint8_t *pentryB_bak = NULL; + struct stat st; + vector::iterator partition_iterator; + + for (partition_iterator = part_list.begin(); + partition_iterator != part_list.end(); + partition_iterator++) { + //Chop off the slot suffix from the partition name to + //make the string easier to work with. + string prefix = *partition_iterator; + if (prefix.size() < (strlen(AB_SLOT_A_SUFFIX) + 1)) { + ALOGE("Invalid partition name: %s", prefix.c_str()); + goto error; + } + prefix.resize(prefix.size() - strlen(AB_SLOT_A_SUFFIX)); + //Check if A/B versions of this ptn exist + snprintf(buf, sizeof(buf) - 1, "%s/%s%s", BOOT_DEV_DIR, + prefix.c_str(), + AB_SLOT_A_SUFFIX); + if (stat(buf, &st)) + continue; + memset(buf, '\0', sizeof(buf)); + snprintf(buf, sizeof(buf) - 1, "%s/%s%s", BOOT_DEV_DIR, + prefix.c_str(), + AB_SLOT_B_SUFFIX); + if (stat(buf, &st)) + continue; + memset(slotA, 0, sizeof(slotA)); + memset(slotB, 0, sizeof(slotB)); + snprintf(slotA, sizeof(slotA) - 1, "%s%s", prefix.c_str(), + AB_SLOT_A_SUFFIX); + snprintf(slotB, sizeof(slotB) - 1,"%s%s", prefix.c_str(), + AB_SLOT_B_SUFFIX); + //Get the disks containing the partitions that were passed in. + if (!diskA) { + diskA = boot_ctl_get_disk_info(slotA); + if (!diskA) + goto error; + } + if (!diskB) { + diskB = boot_ctl_get_disk_info(slotB); + if (!diskB) + goto error; + } + //Get partition entry for slot A & B from the primary + //and backup tables. + pentryA = gpt_disk_get_pentry(diskA, slotA, PRIMARY_GPT); + pentryA_bak = gpt_disk_get_pentry(diskA, slotA, SECONDARY_GPT); + pentryB = gpt_disk_get_pentry(diskB, slotB, PRIMARY_GPT); + pentryB_bak = gpt_disk_get_pentry(diskB, slotB, SECONDARY_GPT); + if ( !pentryA || !pentryA_bak || !pentryB || !pentryB_bak) { + //None of these should be NULL since we have already + //checked for A & B versions earlier. + ALOGE("Slot pentries for %s not found.", + prefix.c_str()); + goto error; + } + memset(active_guid, '\0', sizeof(active_guid)); + memset(inactive_guid, '\0', sizeof(inactive_guid)); + if (get_partition_attribute(slotA, ATTR_SLOT_ACTIVE) == 1) { + //A is the current active slot + memcpy((void*)active_guid, (const void*)pentryA, + TYPE_GUID_SIZE); + memcpy((void*)inactive_guid,(const void*)pentryB, + TYPE_GUID_SIZE); + } else if (get_partition_attribute(slotB, + ATTR_SLOT_ACTIVE) == 1) { + //B is the current active slot + memcpy((void*)active_guid, (const void*)pentryB, + TYPE_GUID_SIZE); + memcpy((void*)inactive_guid, (const void*)pentryA, + TYPE_GUID_SIZE); + } else { + ALOGE("Both A & B for %s are inactive..Aborting", + prefix.c_str()); + goto error; + } + if (!strncmp(slot_suffix_arr[slot], AB_SLOT_A_SUFFIX, + strlen(AB_SLOT_A_SUFFIX))){ + //Mark A as active in primary table + UPDATE_SLOT(pentryA, active_guid, SLOT_ACTIVE); + //Mark A as active in backup table + UPDATE_SLOT(pentryA_bak, active_guid, SLOT_ACTIVE); + //Mark B as inactive in primary table + UPDATE_SLOT(pentryB, inactive_guid, SLOT_INACTIVE); + //Mark B as inactive in backup table + UPDATE_SLOT(pentryB_bak, inactive_guid, SLOT_INACTIVE); + } else if (!strncmp(slot_suffix_arr[slot], AB_SLOT_B_SUFFIX, + strlen(AB_SLOT_B_SUFFIX))){ + //Mark B as active in primary table + UPDATE_SLOT(pentryB, active_guid, SLOT_ACTIVE); + //Mark B as active in backup table + UPDATE_SLOT(pentryB_bak, active_guid, SLOT_ACTIVE); + //Mark A as inavtive in primary table + UPDATE_SLOT(pentryA, inactive_guid, SLOT_INACTIVE); + //Mark A as inactive in backup table + UPDATE_SLOT(pentryA_bak, inactive_guid, SLOT_INACTIVE); + } else { + //Something has gone terribly terribly wrong + ALOGE("%s: Unknown slot suffix!", __func__); + goto error; + } + + if (diskA) { + if (gpt_disk_update_crc(diskA) != 0) { + ALOGE("%s: Failed to update gpt_disk crc", + __func__); + goto error; + } + } + if (diskB) { + if (gpt_disk_update_crc(diskB) != 0) { + ALOGE("%s: Failed to update gpt_disk crc", + __func__); + goto error; + } + } + } + //write updated content to disk + if (diskA) { + if (gpt_disk_commit(diskA)) { + ALOGE("Failed to commit disk entry"); + goto error; + } + gpt_disk_free(diskA); + } + if (diskB) { + if (gpt_disk_commit(diskB)) { + ALOGE("Failed to commit disk entry"); + goto error; + } + gpt_disk_free(diskB); + } + return 0; + +error: + if (diskA) + gpt_disk_free(diskA); + if (diskB) + gpt_disk_free(diskB); + return -1; +} + +bool bootcontrol_init() +{ + return InitMiscVirtualAbMessageIfNeeded(); +} + +unsigned get_number_slots() +{ + struct dirent *de = NULL; + DIR *dir_bootdev = NULL; + unsigned slot_count = 0; + dir_bootdev = opendir(BOOTDEV_DIR); + if (!dir_bootdev) { + ALOGE("%s: Failed to open bootdev dir (%s)", + __func__, + strerror(errno)); + goto error; + } + while ((de = readdir(dir_bootdev))) { + if (de->d_name[0] == '.') + continue; + if (!strncmp(de->d_name, BOOT_IMG_PTN_NAME, + strlen(BOOT_IMG_PTN_NAME))) + slot_count++; + } + closedir(dir_bootdev); + return slot_count; +error: + if (dir_bootdev) + closedir(dir_bootdev); + return 0; +} + +unsigned get_current_slot() +{ + uint32_t num_slots = 0; + char bootSlotProp[PROPERTY_VALUE_MAX] = {'\0'}; + unsigned i = 0; + num_slots = get_number_slots(); + if (num_slots <= 1) { + //Slot 0 is the only slot around. + return 0; + } + property_get(BOOT_SLOT_PROP, bootSlotProp, "N/A"); + if (!strncmp(bootSlotProp, "N/A", strlen("N/A"))) { + ALOGE("%s: Unable to read boot slot property", + __func__); + goto error; + } + //Iterate through a list of partitons named as boot+suffix + //and see which one is currently active. + for (i = 0; slot_suffix_arr[i] != NULL ; i++) { + if (!strncmp(bootSlotProp, + slot_suffix_arr[i], + strlen(slot_suffix_arr[i]))) + return i; + } +error: + //The HAL spec requires that we return a number between + //0 to num_slots - 1. Since something went wrong here we + //are just going to return the default slot. + return 0; +} + +int mark_boot_successful() +{ + unsigned cur_slot = 0; + cur_slot = get_current_slot(); + if (update_slot_attribute(slot_suffix_arr[cur_slot], + ATTR_BOOT_SUCCESSFUL)) { + goto error; + } + return 0; +error: + ALOGE("%s: Failed to mark boot successful", __func__); + return -1; +} + +int set_active_boot_slot(unsigned slot) +{ + map> ptn_map; + vector ptn_vec; + const char ptn_list[][MAX_GPT_NAME_SIZE] = { AB_PTN_LIST }; + uint32_t i; + int rc = -1; + int is_ufs = gpt_utils_is_ufs_device(); + map>::iterator map_iter; + + if (boot_control_check_slot_sanity(slot)) { + ALOGE("%s: Bad arguments", __func__); + goto error; + } + //The partition list just contains prefixes(without the _a/_b) of the + //partitions that support A/B. In order to get the layout we need the + //actual names. To do this we append the slot suffix to every member + //in the list. + for (i = 0; i < ARRAY_SIZE(ptn_list); i++) { + //XBL & XBL_CFG are handled differrently for ufs devices so + //ignore them + if (is_ufs && (!strncmp(ptn_list[i], + PTN_XBL, + strlen(PTN_XBL)) + || !strncmp(ptn_list[i], + PTN_XBL_CFG, + strlen(PTN_XBL_CFG)))) + continue; + //The partition list will be the list of partitions + //corresponding to the slot being set active + string cur_ptn = ptn_list[i]; + cur_ptn.append(slot_suffix_arr[slot]); + ptn_vec.push_back(cur_ptn); + + } + //The partition map gives us info in the following format: + // [path_to_block_device_1]--> + // [path_to_block_device_2]--> + // ... + // ... + // eg: + // [/dev/block/sdb]---> + if (gpt_utils_get_partition_map(ptn_vec, ptn_map)) { + ALOGE("%s: Failed to get partition map", + __func__); + goto error; + } + for (map_iter = ptn_map.begin(); map_iter != ptn_map.end(); map_iter++){ + if (map_iter->second.size() < 1) + continue; + if (boot_ctl_set_active_slot_for_partitions(map_iter->second, + slot)) { + ALOGE("%s: Failed to set active slot", __func__); + goto error; + } + } + if (is_ufs) { + if (!strncmp(slot_suffix_arr[slot], AB_SLOT_A_SUFFIX, + strlen(AB_SLOT_A_SUFFIX))){ + //Set xbl_a as the boot lun + rc = gpt_utils_set_xbl_boot_partition(NORMAL_BOOT); + } else if (!strncmp(slot_suffix_arr[slot], AB_SLOT_B_SUFFIX, + strlen(AB_SLOT_B_SUFFIX))){ + //Set xbl_b as the boot lun + rc = gpt_utils_set_xbl_boot_partition(BACKUP_BOOT); + } else { + //Something has gone terribly terribly wrong + ALOGE("%s: Unknown slot suffix!", __func__); + goto error; + } + if (rc) { + ALOGE("%s: Failed to switch xbl boot partition", + __func__); + goto error; + } + } + return 0; +error: + return -1; +} + +int set_slot_as_unbootable(unsigned slot) +{ + if (boot_control_check_slot_sanity(slot) != 0) { + ALOGE("%s: Argument check failed", __func__); + goto error; + } + if (update_slot_attribute(slot_suffix_arr[slot], + ATTR_UNBOOTABLE)) { + goto error; + } + return 0; +error: + ALOGE("%s: Failed to mark slot unbootable", __func__); + return -1; +} + +int is_slot_bootable(unsigned slot) +{ + int attr = 0; + char bootPartition[MAX_GPT_NAME_SIZE + 1] = {0}; + + if (boot_control_check_slot_sanity(slot) != 0) { + ALOGE("%s: Argument check failed", __func__); + goto error; + } + snprintf(bootPartition, + sizeof(bootPartition) - 1, "boot%s", + slot_suffix_arr[slot]); + attr = get_partition_attribute(bootPartition, ATTR_UNBOOTABLE); + if (attr >= 0) + return !attr; +error: + return -1; +} + +int is_slot_marked_successful(unsigned slot) +{ + int attr = 0; + char bootPartition[MAX_GPT_NAME_SIZE + 1] = {0}; + + if (boot_control_check_slot_sanity(slot) != 0) { + ALOGE("%s: Argument check failed", __func__); + goto error; + } + snprintf(bootPartition, + sizeof(bootPartition) - 1, + "boot%s", slot_suffix_arr[slot]); + attr = get_partition_attribute(bootPartition, ATTR_BOOT_SUCCESSFUL); + if (attr >= 0) + return attr; +error: + return -1; +} + +const char* get_suffix(unsigned slot) +{ + if (boot_control_check_slot_sanity(slot) != 0) + return NULL; + else + return slot_suffix_arr[slot]; +} + +bool set_snapshot_merge_status(MergeStatus status) +{ + bool retval = SetMiscVirtualAbMergeStatus(get_current_slot(), status); + ALOGI("%s: MergeStatus = %d, current_slot = %d, returning: %s \n", __func__, + status, get_current_slot(), retval ? "true" : "false"); + return retval; +} + +MergeStatus get_snapshot_merge_status() +{ + MergeStatus status; + if (!GetMiscVirtualAbMergeStatus(get_current_slot(), &status)) { + ALOGI("%s: MergeStatus read from misc failed, returning unknown\n", __func__); + return MergeStatus::UNKNOWN; + } + ALOGI("%s: Returning MergeStatus = %d\n", __func__, status); + return status; +} diff --git a/bootctrl/1.1/libboot_control_qti/libboot_control_qti.h b/bootctrl/1.1/libboot_control_qti/libboot_control_qti.h new file mode 100644 index 0000000..b055a49 --- /dev/null +++ b/bootctrl/1.1/libboot_control_qti/libboot_control_qti.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include +#include + +using MergeStatus = ::android::hardware::boot::V1_1::MergeStatus; + +// IBootControl 1.0 methods +bool bootcontrol_init(); +unsigned get_number_slots(); +unsigned get_current_slot(); +int mark_boot_successful(); +int set_active_boot_slot(unsigned slot); +int set_slot_as_unbootable(unsigned slot); +int is_slot_bootable(unsigned slot); +int is_slot_marked_successful(unsigned slot); +const char* get_suffix(unsigned slot); + +// IBootControl 1.1 methods +bool set_snapshot_merge_status(MergeStatus status); +MergeStatus get_snapshot_merge_status(); diff --git a/bootctrl/Android.bp b/bootctrl/Android.bp index 5afeaaf..2059c69 100644 --- a/bootctrl/Android.bp +++ b/bootctrl/Android.bp @@ -1,5 +1,5 @@ // -// Copyright (C) 2018 The Android Open Source Project +// Copyright (C) 2019 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -14,15 +14,47 @@ // limitations under the License. // +filegroup { + name: "bootctrl_hal_src", + srcs: [ + "boot_control.cpp", + ], +} + +cc_defaults { + name: "bootctrl_hal_defaults", + proprietary: true, + recovery_available: true, + header_libs: [ + "libhardware_headers", + "libsystem_headers", + ], + shared_libs: [ + "libcutils", + "liblog", + "libz", + ], + owner: "qti", + relative_install_path: "hw", + cflags: [ + "-Wall", + "-Werror", + ], + srcs: [ + ":bootctrl_hal_src", + ], + +} + cc_library { - name: "bootctrl.lahaina", + name: "bootctrl.holi", defaults: ["bootctrl_hal_defaults"], - static_libs: ["libgptutils.odin"], + static_libs: ["libgptutils.osaka"], } cc_library_shared { name: "android.hardware.boot@1.1-impl-qti", stem: "android.hardware.boot@1.0-impl-1.1-qti", defaults: ["android.hardware.boot@1.1-impl-qti_defaults"], - static_libs: ["libgptutils.odin"], + static_libs: ["libgptutils.osaka"], } diff --git a/bootctrl/NOTICE b/bootctrl/NOTICE new file mode 100644 index 0000000..820d40c --- /dev/null +++ b/bootctrl/NOTICE @@ -0,0 +1,26 @@ +Copyright (c) 2016, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/bootctrl/boot_control.cpp b/bootctrl/boot_control.cpp new file mode 100644 index 0000000..726b245 --- /dev/null +++ b/bootctrl/boot_control.cpp @@ -0,0 +1,703 @@ +/* + * Copyright (c) 2016, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#include +#include +#ifdef __cplusplus +extern "C" { +#endif +#include +#define LOG_TAG "bootcontrolhal" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "gpt-utils.h" + +#define BOOTDEV_DIR "/dev/block/bootdevice/by-name" +#define BOOT_IMG_PTN_NAME "boot" +#define LUN_NAME_END_LOC 14 +#define BOOT_SLOT_PROP "ro.boot.slot_suffix" + +#define SLOT_ACTIVE 1 +#define SLOT_INACTIVE 2 +#define UPDATE_SLOT(pentry, guid, slot_state) ({ \ + memcpy(pentry, guid, TYPE_GUID_SIZE); \ + if (slot_state == SLOT_ACTIVE)\ + *(pentry + AB_FLAG_OFFSET) = AB_SLOT_ACTIVE_VAL; \ + else if (slot_state == SLOT_INACTIVE) \ + *(pentry + AB_FLAG_OFFSET) = (*(pentry + AB_FLAG_OFFSET)& \ + ~AB_PARTITION_ATTR_SLOT_ACTIVE); \ + }) + +using namespace std; +const char *slot_suffix_arr[] = { + AB_SLOT_A_SUFFIX, + AB_SLOT_B_SUFFIX, + NULL}; + +enum part_attr_type { + ATTR_SLOT_ACTIVE = 0, + ATTR_BOOT_SUCCESSFUL, + ATTR_UNBOOTABLE, +}; + +void boot_control_init(struct boot_control_module *module) +{ + if (!module) { + ALOGE("Invalid argument passed to %s", __func__); + return; + } + return; +} + +//Get the value of one of the attribute fields for a partition. +static int get_partition_attribute(char *partname, + enum part_attr_type part_attr) +{ + struct gpt_disk *disk = NULL; + uint8_t *pentry = NULL; + int retval = -1; + uint8_t *attr = NULL; + if (!partname) + goto error; + disk = gpt_disk_alloc(); + if (!disk) { + ALOGE("%s: Failed to alloc disk struct", __func__); + goto error; + } + if (gpt_disk_get_disk_info(partname, disk)) { + ALOGE("%s: Failed to get disk info", __func__); + goto error; + } + pentry = gpt_disk_get_pentry(disk, partname, PRIMARY_GPT); + if (!pentry) { + ALOGE("%s: pentry does not exist in disk struct", + __func__); + goto error; + } + attr = pentry + AB_FLAG_OFFSET; + if (part_attr == ATTR_SLOT_ACTIVE) + retval = !!(*attr & AB_PARTITION_ATTR_SLOT_ACTIVE); + else if (part_attr == ATTR_BOOT_SUCCESSFUL) + retval = !!(*attr & AB_PARTITION_ATTR_BOOT_SUCCESSFUL); + else if (part_attr == ATTR_UNBOOTABLE) + retval = !!(*attr & AB_PARTITION_ATTR_UNBOOTABLE); + else + retval = -1; + gpt_disk_free(disk); + return retval; +error: + if (disk) + gpt_disk_free(disk); + return retval; +} + +//Set a particular attribute for all the partitions in a +//slot +static int update_slot_attribute(const char *slot, + enum part_attr_type ab_attr) +{ + unsigned int i = 0; + char buf[PATH_MAX]; + struct stat st; + struct gpt_disk *disk = NULL; + uint8_t *pentry = NULL; + uint8_t *pentry_bak = NULL; + int rc = -1; + uint8_t *attr = NULL; + uint8_t *attr_bak = NULL; + char partName[MAX_GPT_NAME_SIZE + 1] = {0}; + const char ptn_list[][MAX_GPT_NAME_SIZE] = { AB_PTN_LIST }; + int slot_name_valid = 0; + if (!slot) { + ALOGE("%s: Invalid argument", __func__); + goto error; + } + for (i = 0; slot_suffix_arr[i] != NULL; i++) + { + if (!strncmp(slot, slot_suffix_arr[i], + strlen(slot_suffix_arr[i]))) + slot_name_valid = 1; + } + if (!slot_name_valid) { + ALOGE("%s: Invalid slot name", __func__); + goto error; + } + for (i=0; i < ARRAY_SIZE(ptn_list); i++) { + memset(buf, '\0', sizeof(buf)); + //Check if A/B versions of this ptn exist + snprintf(buf, sizeof(buf) - 1, + "%s/%s%s", + BOOT_DEV_DIR, + ptn_list[i], + AB_SLOT_A_SUFFIX + ); + if (stat(buf, &st)) { + //partition does not have _a version + continue; + } + memset(buf, '\0', sizeof(buf)); + snprintf(buf, sizeof(buf) - 1, + "%s/%s%s", + BOOT_DEV_DIR, + ptn_list[i], + AB_SLOT_B_SUFFIX + ); + if (stat(buf, &st)) { + //partition does not have _a version + continue; + } + memset(partName, '\0', sizeof(partName)); + snprintf(partName, + sizeof(partName) - 1, + "%s%s", + ptn_list[i], + slot); + disk = gpt_disk_alloc(); + if (!disk) { + ALOGE("%s: Failed to alloc disk struct", + __func__); + goto error; + } + rc = gpt_disk_get_disk_info(partName, disk); + if (rc != 0) { + ALOGE("%s: Failed to get disk info for %s", + __func__, + partName); + goto error; + } + pentry = gpt_disk_get_pentry(disk, partName, PRIMARY_GPT); + pentry_bak = gpt_disk_get_pentry(disk, partName, SECONDARY_GPT); + if (!pentry || !pentry_bak) { + ALOGE("%s: Failed to get pentry/pentry_bak for %s", + __func__, + partName); + goto error; + } + attr = pentry + AB_FLAG_OFFSET; + attr_bak = pentry_bak + AB_FLAG_OFFSET; + if (ab_attr == ATTR_BOOT_SUCCESSFUL) { + *attr = (*attr) | AB_PARTITION_ATTR_BOOT_SUCCESSFUL; + *attr_bak = (*attr_bak) | + AB_PARTITION_ATTR_BOOT_SUCCESSFUL; + } else if (ab_attr == ATTR_UNBOOTABLE) { + *attr = (*attr) | AB_PARTITION_ATTR_UNBOOTABLE; + *attr_bak = (*attr_bak) | AB_PARTITION_ATTR_UNBOOTABLE; + } else if (ab_attr == ATTR_SLOT_ACTIVE) { + *attr = (*attr) | AB_PARTITION_ATTR_SLOT_ACTIVE; + *attr_bak = (*attr) | AB_PARTITION_ATTR_SLOT_ACTIVE; + } else { + ALOGE("%s: Unrecognized attr", __func__); + goto error; + } + if (gpt_disk_update_crc(disk)) { + ALOGE("%s: Failed to update crc for %s", + __func__, + partName); + goto error; + } + if (gpt_disk_commit(disk)) { + ALOGE("%s: Failed to write back entry for %s", + __func__, + partName); + goto error; + } + gpt_disk_free(disk); + disk = NULL; + } + return 0; +error: + if (disk) + gpt_disk_free(disk); + return -1; +} + +unsigned get_number_slots(struct boot_control_module *module) +{ + struct dirent *de = NULL; + DIR *dir_bootdev = NULL; + unsigned slot_count = 0; + if (!module) { + ALOGE("%s: Invalid argument", __func__); + goto error; + } + dir_bootdev = opendir(BOOTDEV_DIR); + if (!dir_bootdev) { + ALOGE("%s: Failed to open bootdev dir (%s)", + __func__, + strerror(errno)); + goto error; + } + while ((de = readdir(dir_bootdev))) { + if (de->d_name[0] == '.') + continue; + if (!strncmp(de->d_name, BOOT_IMG_PTN_NAME, + strlen(BOOT_IMG_PTN_NAME))) + slot_count++; + } + closedir(dir_bootdev); + return slot_count; +error: + if (dir_bootdev) + closedir(dir_bootdev); + return 0; +} + +unsigned get_current_slot(struct boot_control_module *module) +{ + uint32_t num_slots = 0; + char bootSlotProp[PROPERTY_VALUE_MAX] = {'\0'}; + unsigned i = 0; + if (!module) { + ALOGE("%s: Invalid argument", __func__); + goto error; + } + num_slots = get_number_slots(module); + if (num_slots <= 1) { + //Slot 0 is the only slot around. + return 0; + } + property_get(BOOT_SLOT_PROP, bootSlotProp, "N/A"); + if (!strncmp(bootSlotProp, "N/A", strlen("N/A"))) { + ALOGE("%s: Unable to read boot slot property", + __func__); + goto error; + } + //Iterate through a list of partitons named as boot+suffix + //and see which one is currently active. + for (i = 0; slot_suffix_arr[i] != NULL ; i++) { + if (!strncmp(bootSlotProp, + slot_suffix_arr[i], + strlen(slot_suffix_arr[i]))) + return i; + } +error: + //The HAL spec requires that we return a number between + //0 to num_slots - 1. Since something went wrong here we + //are just going to return the default slot. + return 0; +} + +static int boot_control_check_slot_sanity(struct boot_control_module *module, + unsigned slot) +{ + if (!module) + return -1; + uint32_t num_slots = get_number_slots(module); + if ((num_slots < 1) || (slot > num_slots - 1)) { + ALOGE("Invalid slot number"); + return -1; + } + return 0; + +} + +int mark_boot_successful(struct boot_control_module *module) +{ + unsigned cur_slot = 0; + if (!module) { + ALOGE("%s: Invalid argument", __func__); + goto error; + } + cur_slot = get_current_slot(module); + if (update_slot_attribute(slot_suffix_arr[cur_slot], + ATTR_BOOT_SUCCESSFUL)) { + goto error; + } + return 0; +error: + ALOGE("%s: Failed to mark boot successful", __func__); + return -1; +} + +const char *get_suffix(struct boot_control_module *module, unsigned slot) +{ + if (boot_control_check_slot_sanity(module, slot) != 0) + return NULL; + else + return slot_suffix_arr[slot]; +} + + +//Return a gpt disk structure representing the disk that holds +//partition. +static struct gpt_disk* boot_ctl_get_disk_info(char *partition) +{ + struct gpt_disk *disk = NULL; + if (!partition) + return NULL; + disk = gpt_disk_alloc(); + if (!disk) { + ALOGE("%s: Failed to alloc disk", + __func__); + goto error; + } + if (gpt_disk_get_disk_info(partition, disk)) { + ALOGE("failed to get disk info for %s", + partition); + goto error; + } + return disk; +error: + if (disk) + gpt_disk_free(disk); + return NULL; +} + +//The argument here is a vector of partition names(including the slot suffix) +//that lie on a single disk +static int boot_ctl_set_active_slot_for_partitions(vector part_list, + unsigned slot) +{ + char buf[PATH_MAX] = {0}; + struct gpt_disk *diskA = NULL; + struct gpt_disk *diskB = NULL; + char slotA[MAX_GPT_NAME_SIZE + 1] = {0}; + char slotB[MAX_GPT_NAME_SIZE + 1] = {0}; + char active_guid[TYPE_GUID_SIZE + 1] = {0}; + char inactive_guid[TYPE_GUID_SIZE + 1] = {0}; + //Pointer to the partition entry of current 'A' partition + uint8_t *pentryA = NULL; + uint8_t *pentryA_bak = NULL; + //Pointer to partition entry of current 'B' partition + uint8_t *pentryB = NULL; + uint8_t *pentryB_bak = NULL; + struct stat st; + vector::iterator partition_iterator; + + for (partition_iterator = part_list.begin(); + partition_iterator != part_list.end(); + partition_iterator++) { + //Chop off the slot suffix from the partition name to + //make the string easier to work with. + string prefix = *partition_iterator; + if (prefix.size() < (strlen(AB_SLOT_A_SUFFIX) + 1)) { + ALOGE("Invalid partition name: %s", prefix.c_str()); + goto error; + } + prefix.resize(prefix.size() - strlen(AB_SLOT_A_SUFFIX)); + //Check if A/B versions of this ptn exist + snprintf(buf, sizeof(buf) - 1, "%s/%s%s", BOOT_DEV_DIR, + prefix.c_str(), + AB_SLOT_A_SUFFIX); + if (stat(buf, &st)) + continue; + memset(buf, '\0', sizeof(buf)); + snprintf(buf, sizeof(buf) - 1, "%s/%s%s", BOOT_DEV_DIR, + prefix.c_str(), + AB_SLOT_B_SUFFIX); + if (stat(buf, &st)) + continue; + memset(slotA, 0, sizeof(slotA)); + memset(slotB, 0, sizeof(slotB)); + snprintf(slotA, sizeof(slotA) - 1, "%s%s", prefix.c_str(), + AB_SLOT_A_SUFFIX); + snprintf(slotB, sizeof(slotB) - 1,"%s%s", prefix.c_str(), + AB_SLOT_B_SUFFIX); + //Get the disks containing the partitions that were passed in. + if (!diskA) { + diskA = boot_ctl_get_disk_info(slotA); + if (!diskA) + goto error; + } + if (!diskB) { + diskB = boot_ctl_get_disk_info(slotB); + if (!diskB) + goto error; + } + //Get partition entry for slot A & B from the primary + //and backup tables. + pentryA = gpt_disk_get_pentry(diskA, slotA, PRIMARY_GPT); + pentryA_bak = gpt_disk_get_pentry(diskA, slotA, SECONDARY_GPT); + pentryB = gpt_disk_get_pentry(diskB, slotB, PRIMARY_GPT); + pentryB_bak = gpt_disk_get_pentry(diskB, slotB, SECONDARY_GPT); + if ( !pentryA || !pentryA_bak || !pentryB || !pentryB_bak) { + //None of these should be NULL since we have already + //checked for A & B versions earlier. + ALOGE("Slot pentries for %s not found.", + prefix.c_str()); + goto error; + } + memset(active_guid, '\0', sizeof(active_guid)); + memset(inactive_guid, '\0', sizeof(inactive_guid)); + if (get_partition_attribute(slotA, ATTR_SLOT_ACTIVE) == 1) { + //A is the current active slot + memcpy((void*)active_guid, (const void*)pentryA, + TYPE_GUID_SIZE); + memcpy((void*)inactive_guid,(const void*)pentryB, + TYPE_GUID_SIZE); + } else if (get_partition_attribute(slotB, + ATTR_SLOT_ACTIVE) == 1) { + //B is the current active slot + memcpy((void*)active_guid, (const void*)pentryB, + TYPE_GUID_SIZE); + memcpy((void*)inactive_guid, (const void*)pentryA, + TYPE_GUID_SIZE); + } else { + ALOGE("Both A & B for %s are inactive..Aborting", + prefix.c_str()); + goto error; + } + if (!strncmp(slot_suffix_arr[slot], AB_SLOT_A_SUFFIX, + strlen(AB_SLOT_A_SUFFIX))){ + //Mark A as active in primary table + UPDATE_SLOT(pentryA, active_guid, SLOT_ACTIVE); + //Mark A as active in backup table + UPDATE_SLOT(pentryA_bak, active_guid, SLOT_ACTIVE); + //Mark B as inactive in primary table + UPDATE_SLOT(pentryB, inactive_guid, SLOT_INACTIVE); + //Mark B as inactive in backup table + UPDATE_SLOT(pentryB_bak, inactive_guid, SLOT_INACTIVE); + } else if (!strncmp(slot_suffix_arr[slot], AB_SLOT_B_SUFFIX, + strlen(AB_SLOT_B_SUFFIX))){ + //Mark B as active in primary table + UPDATE_SLOT(pentryB, active_guid, SLOT_ACTIVE); + //Mark B as active in backup table + UPDATE_SLOT(pentryB_bak, active_guid, SLOT_ACTIVE); + //Mark A as inavtive in primary table + UPDATE_SLOT(pentryA, inactive_guid, SLOT_INACTIVE); + //Mark A as inactive in backup table + UPDATE_SLOT(pentryA_bak, inactive_guid, SLOT_INACTIVE); + } else { + //Something has gone terribly terribly wrong + ALOGE("%s: Unknown slot suffix!", __func__); + goto error; + } + + if (diskA) { + if (gpt_disk_update_crc(diskA) != 0) { + ALOGE("%s: Failed to update gpt_disk crc", + __func__); + goto error; + } + } + if (diskB) { + if (gpt_disk_update_crc(diskB) != 0) { + ALOGE("%s: Failed to update gpt_disk crc", + __func__); + goto error; + } + } + } + //write updated content to disk + if (diskA) { + if (gpt_disk_commit(diskA)) { + ALOGE("Failed to commit disk entry"); + goto error; + } + gpt_disk_free(diskA); + } + if (diskB) { + if (gpt_disk_commit(diskB)) { + ALOGE("Failed to commit disk entry"); + goto error; + } + gpt_disk_free(diskB); + } + return 0; + +error: + if (diskA) + gpt_disk_free(diskA); + if (diskB) + gpt_disk_free(diskB); + return -1; +} + +int set_active_boot_slot(struct boot_control_module *module, unsigned slot) +{ + map> ptn_map; + vector ptn_vec; + const char ptn_list[][MAX_GPT_NAME_SIZE] = { AB_PTN_LIST }; + uint32_t i; + int rc = -1; + int is_ufs = gpt_utils_is_ufs_device(); + map>::iterator map_iter; + + if (boot_control_check_slot_sanity(module, slot)) { + ALOGE("%s: Bad arguments", __func__); + goto error; + } + //The partition list just contains prefixes(without the _a/_b) of the + //partitions that support A/B. In order to get the layout we need the + //actual names. To do this we append the slot suffix to every member + //in the list. + for (i = 0; i < ARRAY_SIZE(ptn_list); i++) { + //XBL & XBL_CFG are handled differrently for ufs devices so + //ignore them + if (is_ufs && (!strncmp(ptn_list[i], + PTN_XBL, + strlen(PTN_XBL)) + || !strncmp(ptn_list[i], + PTN_XBL_CFG, + strlen(PTN_XBL_CFG)))) + continue; + //The partition list will be the list of partitions + //corresponding to the slot being set active + string cur_ptn = ptn_list[i]; + cur_ptn.append(slot_suffix_arr[slot]); + ptn_vec.push_back(cur_ptn); + + } + //The partition map gives us info in the following format: + // [path_to_block_device_1]--> + // [path_to_block_device_2]--> + // ... + // ... + // eg: + // [/dev/block/sdb]---> + if (gpt_utils_get_partition_map(ptn_vec, ptn_map)) { + ALOGE("%s: Failed to get partition map", + __func__); + goto error; + } + for (map_iter = ptn_map.begin(); map_iter != ptn_map.end(); map_iter++){ + if (map_iter->second.size() < 1) + continue; + if (boot_ctl_set_active_slot_for_partitions(map_iter->second, + slot)) { + ALOGE("%s: Failed to set active slot", __func__); + goto error; + } + } + if (is_ufs) { + if (!strncmp(slot_suffix_arr[slot], AB_SLOT_A_SUFFIX, + strlen(AB_SLOT_A_SUFFIX))){ + //Set xbl_a as the boot lun + rc = gpt_utils_set_xbl_boot_partition(NORMAL_BOOT); + } else if (!strncmp(slot_suffix_arr[slot], AB_SLOT_B_SUFFIX, + strlen(AB_SLOT_B_SUFFIX))){ + //Set xbl_b as the boot lun + rc = gpt_utils_set_xbl_boot_partition(BACKUP_BOOT); + } else { + //Something has gone terribly terribly wrong + ALOGE("%s: Unknown slot suffix!", __func__); + goto error; + } + if (rc) { + ALOGE("%s: Failed to switch xbl boot partition", + __func__); + goto error; + } + } + return 0; +error: + return -1; +} + +int set_slot_as_unbootable(struct boot_control_module *module, unsigned slot) +{ + if (boot_control_check_slot_sanity(module, slot) != 0) { + ALOGE("%s: Argument check failed", __func__); + goto error; + } + if (update_slot_attribute(slot_suffix_arr[slot], + ATTR_UNBOOTABLE)) { + goto error; + } + return 0; +error: + ALOGE("%s: Failed to mark slot unbootable", __func__); + return -1; +} + +int is_slot_bootable(struct boot_control_module *module, unsigned slot) +{ + int attr = 0; + char bootPartition[MAX_GPT_NAME_SIZE + 1] = {0}; + + if (boot_control_check_slot_sanity(module, slot) != 0) { + ALOGE("%s: Argument check failed", __func__); + goto error; + } + snprintf(bootPartition, + sizeof(bootPartition) - 1, "boot%s", + slot_suffix_arr[slot]); + attr = get_partition_attribute(bootPartition, ATTR_UNBOOTABLE); + if (attr >= 0) + return !attr; +error: + return -1; +} + +int is_slot_marked_successful(struct boot_control_module *module, unsigned slot) +{ + int attr = 0; + char bootPartition[MAX_GPT_NAME_SIZE + 1] = {0}; + + if (boot_control_check_slot_sanity(module, slot) != 0) { + ALOGE("%s: Argument check failed", __func__); + goto error; + } + snprintf(bootPartition, + sizeof(bootPartition) - 1, + "boot%s", slot_suffix_arr[slot]); + attr = get_partition_attribute(bootPartition, ATTR_BOOT_SUCCESSFUL); + if (attr >= 0) + return attr; +error: + return -1; +} + +static hw_module_methods_t boot_control_module_methods = { + .open = NULL, +}; + +boot_control_module_t HAL_MODULE_INFO_SYM = { + .common = { + .tag = HARDWARE_MODULE_TAG, + .module_api_version = 1, + .hal_api_version = 0, + .id = BOOT_CONTROL_HARDWARE_MODULE_ID, + .name = "Boot control HAL", + .author = "Code Aurora Forum", + .methods = &boot_control_module_methods, + }, + .init = boot_control_init, + .getNumberSlots = get_number_slots, + .getCurrentSlot = get_current_slot, + .markBootSuccessful = mark_boot_successful, + .setActiveBootSlot = set_active_boot_slot, + .setSlotAsUnbootable = set_slot_as_unbootable, + .isSlotBootable = is_slot_bootable, + .getSuffix = get_suffix, + .isSlotMarkedSuccessful = is_slot_marked_successful, +}; +#ifdef __cplusplus +} +#endif diff --git a/device.mk b/device.mk index 3682228..5d7166a 100644 --- a/device.mk +++ b/device.mk @@ -21,12 +21,12 @@ $(call inherit-product, $(SRC_TARGET_DIR)/product/emulated_storage.mk) $(call inherit-product, $(SRC_TARGET_DIR)/product/updatable_apex.mk) # Enable virtual A/B OTA -$(call inherit-product, $(SRC_TARGET_DIR)/product/virtual_ab_ota.mk) +#$(call inherit-product, $(SRC_TARGET_DIR)/product/virtual_ab_ota.mk) # Installs gsi keys into ramdisk, to boot a developer GSI with verified boot. $(call inherit-product, $(SRC_TARGET_DIR)/product/gsi_keys.mk) -LOCAL_PATH := device/xiaomi/odin +LOCAL_PATH := device/motorola/osaka # API PRODUCT_SHIPPING_API_LEVEL := 30 @@ -44,7 +44,7 @@ PRODUCT_PACKAGES += \ # Boot control HAL PRODUCT_PACKAGES += \ android.hardware.boot@1.1-impl-qti.recovery \ - bootctrl.lahaina.recovery + bootctrl.holi.recovery PRODUCT_PACKAGES_DEBUG += \ bootctl @@ -86,15 +86,14 @@ TW_INCLUDE_NTFS_3G := true TW_USE_TOOLBOX := true TW_INCLUDE_RESETPROP := true TW_INCLUDE_REPACKTOOLS := true -TW_INPUT_BLACKLIST := "hbtp_vm" TW_BRIGHTNESS_PATH := "/sys/class/backlight/panel0-backlight/brightness" TARGET_USE_CUSTOM_LUN_FILE_PATH := /config/usb_gadget/g1/functions/mass_storage.0/lun.%d/file -TW_Y_OFFSET := 80 -TW_H_OFFSET := -80 +TW_CUSTOM_CPU_TEMP_PATH := "/sys/devices/virtual/thermal/thermal_zone79/temp" +TW_Y_OFFSET := 120 +TW_H_OFFSET := -120 TWRP_INCLUDE_LOGCAT := true TARGET_USES_LOGD := true TARGET_USES_MKE2FS := true -TW_NO_SCREEN_BLANK := true TW_EXCLUDE_APEX := true # Crypto @@ -121,7 +120,7 @@ RECOVERY_LIBRARY_SOURCE_FILES += \ $(TARGET_OUT_SYSTEM_EXT_SHARED_LIBRARIES)/vendor.display.config@2.0.so PRODUCT_COPY_FILES += \ - $(OUT_DIR)/target/product/odin/obj/SHARED_LIBRARIES/libandroidicu_intermediates/libandroidicu.so:$(TARGET_COPY_OUT_RECOVERY)/root/system/lib64/libandroidicu.so + $(OUT_DIR)/target/product/osaka/obj/SHARED_LIBRARIES/libandroidicu_intermediates/libandroidicu.so:$(TARGET_COPY_OUT_RECOVERY)/root/system/lib64/libandroidicu.so PRODUCT_PACKAGES += \ qcom_decrypt \ diff --git a/gpt-utils/Android.bp b/gpt-utils/Android.bp index 45a5e47..1767f32 100644 --- a/gpt-utils/Android.bp +++ b/gpt-utils/Android.bp @@ -16,7 +16,7 @@ cc_library { - name: "libgptutils.odin", + name: "libgptutils.osaka", vendor: true, recovery_available: true, shared_libs: [ diff --git a/gpt-utils/gpt-utils.h b/gpt-utils/gpt-utils.h index 2e356dc..8152641 100644 --- a/gpt-utils/gpt-utils.h +++ b/gpt-utils/gpt-utils.h @@ -80,8 +80,8 @@ extern "C" { #define AB_SLOT_B_SUFFIX "_b" #define PTN_XBL "xbl" #define PTN_XBL_CFG "xbl_config" -#define PTN_SWAP_LIST PTN_XBL, PTN_XBL_CFG, "abl", "aop", "cpucp", "devcfg", "dsp", "dtbo", "featenabler", "hyp", "imagefv", "keymaster", "qupfw", "shrm", "tz", "uefisecapp", "vbmeta", "vbmeta_system" -#define AB_PTN_LIST PTN_SWAP_LIST, "bluetooth", "boot", "modem", "odm", "product", "system", "system_ext", "vendor", "vendor_boot" +#define PTN_SWAP_LIST PTN_XBL, PTN_XBL_CFG, "abl", "devcfg", "hyp", "keymaster", "prov", "qupfw", "rpm", "storsec", "tz", "uefisecapp", "vbmeta", "vbmeta_system" +#define AB_PTN_LIST PTN_SWAP_LIST, "bluetooth", "boot", "vendor_boot", "dsp", "dtbo", "fsg", "logo", "modem" #define BOOT_DEV_DIR "/dev/block/bootdevice/by-name" /****************************************************************************** diff --git a/odm.prop b/odm.prop deleted file mode 100644 index fab6c31..0000000 --- a/odm.prop +++ /dev/null @@ -1,2 +0,0 @@ -# Audio -ro.vendor.qti.va_odm.support=1 diff --git a/recovery.fstab b/recovery.fstab index bcbc033..0cbe34f 100644 --- a/recovery.fstab +++ b/recovery.fstab @@ -36,15 +36,10 @@ # system /system ext4 ro,barrier=1,discard wait,slotselect,avb=vbmeta_system,logical,first_stage_mount,avb_keys=/avb/q-gsi.avbpubkey:/avb/r-gsi.avbpubkey:/avb/s-gsi.avbpubkey -system /system erofs ro wait,slotselect,avb=vbmeta_system,logical,first_stage_mount,avb_keys=/avb/q-gsi.avbpubkey:/avb/r-gsi.avbpubkey:/avb/s-gsi.avbpubkey system_ext /system_ext ext4 ro,barrier=1,discard wait,slotselect,avb=vbmeta_system,logical,first_stage_mount -system_ext /system_ext erofs ro wait,slotselect,avb=vbmeta_system,logical,first_stage_mount product /product ext4 ro,barrier=1,discard wait,slotselect,avb=vbmeta_system,logical,first_stage_mount -product /product erofs ro wait,slotselect,avb=vbmeta_system,logical,first_stage_mount vendor /vendor ext4 ro,barrier=1,discard wait,slotselect,avb,logical,first_stage_mount -vendor /vendor erofs ro wait,slotselect,avb,logical,first_stage_mount -odm /odm ext4 ro,barrier=1,discard wait,slotselect,avb,logical,first_stage_mount -odm /odm erofs ro wait,slotselect,avb,logical,first_stage_mount /dev/block/by-name/metadata /metadata ext4 noatime,nosuid,nodev,discard wait,check,formattable,first_stage_mount -/dev/block/bootdevice/by-name/userdata /data f2fs noatime,nosuid,nodev,discard,inlinecrypt,reserve_root=32768,resgid=1065,fsync_mode=nobarrier latemount,wait,check,formattable,fileencryption=aes-256-xts:aes-256-cts:v2+inlinecrypt_optimized+wrappedkey_v0,keydirectory=/metadata/vold/metadata_encryption,metadata_encryption=aes-256-xts:wrappedkey_v0,quota,reservedsize=512M,sysfs_path=/sys/devices/platform/soc/1d84000.ufshc,checkpoint=fs +/dev/block/bootdevice/by-name/userdata /data f2fs noatime,nosuid,nodev,discard,inlinecrypt,reserve_root=32768,resgid=1065,fsync_mode=nobarrier latemount,wait,check,formattable,fileencryption=aes-256-xts:aes-256-cts:v2+inlinecrypt_optimized+wrappedkey_v0,keydirectory=/metadata/vold/metadata_encryption,metadata_encryption=aes-256-xts:wrappedkey_v0,quota,reservedsize=512M,sysfs_path=/sys/devices/platform/soc/4804000.ufshc,checkpoint=fs /dev/block/bootdevice/by-name/misc /misc emmc defaults defaults +/dev/block/mmcblk1p1 /external_sd auto defaults defaults diff --git a/recovery/root/init.recovery.qcom.rc b/recovery/root/init.recovery.qcom.rc index 5283e13..1f0d1b0 100644 --- a/recovery/root/init.recovery.qcom.rc +++ b/recovery/root/init.recovery.qcom.rc @@ -17,3 +17,12 @@ on fs on boot start health-hal-2-1 setprop sys.usb.config adb + chmod 0777 /system/bin/runatboot.sh + start load_modules + +service load_modules /system/bin/load_modules.sh + user root + group root + disabled + oneshot + seclabel u:r:recovery:s0 diff --git a/recovery/root/system/bin/load_modules.sh b/recovery/root/system/bin/load_modules.sh new file mode 100644 index 0000000..dbf3a4d --- /dev/null +++ b/recovery/root/system/bin/load_modules.sh @@ -0,0 +1,4 @@ +#!/system/bin/sh + +insmod /vendor/lib/modules/nova_0flash_mmi.ko +insmod /vendor/lib/modules/mmi-smbcharger-iio.ko diff --git a/recovery/root/system/bin/postrecoveryboot.sh b/recovery/root/system/bin/postrecoveryboot.sh deleted file mode 100755 index 32abf99..0000000 --- a/recovery/root/system/bin/postrecoveryboot.sh +++ /dev/null @@ -1,49 +0,0 @@ -#!/system/bin/sh - -# find necessary modules for touchscreen, etc. to ensure no mismatch with kernel -copy-modules() { - if grep -Fq twrpfastboot /proc/cmdline; then - echo "using ramdisk modules (fastboot boot)" - return - fi - - if [ -f /lib/modules/modules.load.recovery ] && [ -f /lib/modules/xiaomi_touch.ko ] && lsmod | grep -Fq xiaomi_touch; then - echo "using vendor_boot modules" - exit 0 - fi - - suffix=$(getprop ro.boot.slot_suffix) - if [ -z "$suffix" ]; then - suffix="_$(getprop ro.boot.slot)" - fi - - echo "using vendor$suffix modules" - mkdir /v - mount -t erofs -o ro /dev/block/mapper/vendor"$suffix" /v - rm -f /vendor/lib/modules/* - cp -afR /v/lib/modules/* /vendor/lib/modules/ - umount /v - rmdir /v -} - -install-touch() { - if [ -f /lib/modules/modules.load.recovery ] && [ -f /lib/modules/xiaomi_touch.ko ] && lsmod | grep -Fq xiaomi_touch; then - echo "vendor_boot touchscreen modules already loaded" - exit 0 - fi - - if [ ! -f /vendor/lib/modules/xiaomi_touch.ko ]; then - echo "! vendor touchscreen modules not found" - exit 1 - fi - - echo "loading vendor touchscreen modules" - for module in $(modprobe -D -d /vendor/lib/modules msm_drm fts_touch_spi | grep modules); do - insmod /vendor/lib/modules/"$(basename "$module")" - done -} - -copy-modules -install-touch - -exit 0 diff --git a/recovery/root/system/etc/recovery.fstab b/recovery/root/system/etc/recovery.fstab index 95f20d9..c0c2848 100644 --- a/recovery/root/system/etc/recovery.fstab +++ b/recovery/root/system/etc/recovery.fstab @@ -35,16 +35,10 @@ # specify MF_CHECK, and must come before any filesystems that do specify MF_CHECK # -system /system ext4 ro,barrier=1,discard wait,slotselect -system /system erofs ro wait,slotselect -system_ext /system_ext ext4 ro,barrier=1,discard wait,slotselect -system_ext /system_ext erofs ro wait,slotselect -product /product ext4 ro,barrier=1,discard wait,slotselect -product /product erofs ro wait,slotselect -vendor /vendor ext4 ro,barrier=1,discard wait,slotselect -vendor /vendor erofs ro wait,slotselect -odm /odm ext4 ro,barrier=1,discard wait,slotselect -odm /odm erofs ro wait,slotselect +system /system ext4 ro,barrier=1,discard wait,slotselect,avb=vbmeta_system,logical,first_stage_mount,avb_keys=/avb/q-gsi.avbpubkey:/avb/r-gsi.avbpubkey:/avb/s-gsi.avbpubkey +system_ext /system_ext ext4 ro,barrier=1,discard wait,slotselect,avb=vbmeta_system,logical,first_stage_mount +product /product ext4 ro,barrier=1,discard wait,slotselect,avb=vbmeta_system,logical,first_stage_mount +vendor /vendor ext4 ro,barrier=1,discard wait,slotselect,avb,logical,first_stage_mount /dev/block/by-name/metadata /metadata ext4 noatime,nosuid,nodev,discard wait,check,formattable,first_stage_mount -/dev/block/bootdevice/by-name/userdata /data f2fs noatime,nosuid,nodev,nodiscard,inlinecrypt,reserve_root=32768,resgid=1065,fsync_mode=nobarrier latemount,wait,check,formattable,fileencryption=aes-256-xts:aes-256-cts:v2+inlinecrypt_optimized+wrappedkey_v0,keydirectory=/metadata/vold/metadata_encryption,metadata_encryption=aes-256-xts:wrappedkey_v0,quota,reservedsize=128M,sysfs_path=/sys/devices/platform/soc/1d84000.ufshc,checkpoint=fs +/dev/block/bootdevice/by-name/userdata /data f2fs noatime,nosuid,nodev,discard,inlinecrypt,reserve_root=32768,resgid=1065,fsync_mode=nobarrier latemount,wait,check,formattable,fileencryption=aes-256-xts:aes-256-cts:v2+inlinecrypt_optimized+wrappedkey_v0,keydirectory=/metadata/vold/metadata_encryption,metadata_encryption=aes-256-xts:wrappedkey_v0,quota,reservedsize=512M,sysfs_path=/sys/devices/platform/soc/4804000.ufshc,checkpoint=fs /dev/block/bootdevice/by-name/misc /misc emmc defaults defaults diff --git a/recovery/root/system/etc/twrp.flags b/recovery/root/system/etc/twrp.flags index 809a6b1..6c24077 100644 --- a/recovery/root/system/etc/twrp.flags +++ b/recovery/root/system/etc/twrp.flags @@ -9,7 +9,6 @@ /boot emmc /dev/block/bootdevice/by-name/boot flags=backup=1;flashimg=1;slotselect /dtbo emmc /dev/block/bootdevice/by-name/dtbo flags=backup=1;display="Dtbo";flashimg=1;slotselect /firmware vfat /dev/block/bootdevice/by-name/modem flags=display="Firmware";slotselect;mounttodecrypt;fsflags=ro -/cust ext4 /dev/block/bootdevice/by-name/cust flags=display="Cust" /misc emmc /dev/block/bootdevice/by-name/misc flags=display="Misc" /modem emmc /dev/block/bootdevice/by-name/modem flags=backup=1;display="Modem";slotselect /bluetooth emmc /dev/block/bootdevice/by-name/bluetooth flags=backup=1;subpartitionof=/modem;slotselect @@ -17,7 +16,7 @@ /efs1 emmc /dev/block/bootdevice/by-name/modemst1 flags=backup=1;display=EFS /efs2 emmc /dev/block/bootdevice/by-name/modemst2 flags=backup=1;subpartitionof=/efs1 /efsc emmc /dev/block/bootdevice/by-name/fsc flags=backup=1;subpartitionof=/efs1 -/efsg emmc /dev/block/bootdevice/by-name/fsg flags=backup=1;subpartitionof=/efs1 +/efsg emmc /dev/block/bootdevice/by-name/fsg flags=backup=1;subpartitionof=/efs1;slotselect /persist ext4 /dev/block/bootdevice/by-name/persist flags=display="Persist" /persist_image emmc /dev/block/bootdevice/by-name/persist flags=display="Persist";flashimg=1 diff --git a/recovery/root/vendor/firmware/auo_novatek_ts_fw.bin b/recovery/root/vendor/firmware/auo_novatek_ts_fw.bin new file mode 100644 index 0000000..2d16644 Binary files /dev/null and b/recovery/root/vendor/firmware/auo_novatek_ts_fw.bin differ diff --git a/recovery/root/vendor/firmware/auo_novatek_ts_mp.bin b/recovery/root/vendor/firmware/auo_novatek_ts_mp.bin new file mode 100644 index 0000000..de83766 Binary files /dev/null and b/recovery/root/vendor/firmware/auo_novatek_ts_mp.bin differ diff --git a/recovery/root/vendor/firmware/bod_novatek_ts_fw.bin b/recovery/root/vendor/firmware/bod_novatek_ts_fw.bin new file mode 100644 index 0000000..34bee0e Binary files /dev/null and b/recovery/root/vendor/firmware/bod_novatek_ts_fw.bin differ diff --git a/recovery/root/vendor/firmware/bod_novatek_ts_mp.bin b/recovery/root/vendor/firmware/bod_novatek_ts_mp.bin new file mode 100644 index 0000000..292bea7 Binary files /dev/null and b/recovery/root/vendor/firmware/bod_novatek_ts_mp.bin differ diff --git a/recovery/root/vendor/firmware/boe_novatek_ts_fw.bin b/recovery/root/vendor/firmware/boe_novatek_ts_fw.bin new file mode 100644 index 0000000..34bee0e Binary files /dev/null and b/recovery/root/vendor/firmware/boe_novatek_ts_fw.bin differ diff --git a/recovery/root/vendor/firmware/boe_novatek_ts_mp.bin b/recovery/root/vendor/firmware/boe_novatek_ts_mp.bin new file mode 100644 index 0000000..292bea7 Binary files /dev/null and b/recovery/root/vendor/firmware/boe_novatek_ts_mp.bin differ diff --git a/recovery/root/vendor/firmware/goodix_gt9897t_cfg_k9.bin b/recovery/root/vendor/firmware/goodix_gt9897t_cfg_k9.bin deleted file mode 100644 index 9243353..0000000 Binary files a/recovery/root/vendor/firmware/goodix_gt9897t_cfg_k9.bin and /dev/null differ diff --git a/recovery/root/vendor/firmware/goodix_gt9897t_fw_k9.bin b/recovery/root/vendor/firmware/goodix_gt9897t_fw_k9.bin deleted file mode 100644 index 67035d6..0000000 Binary files a/recovery/root/vendor/firmware/goodix_gt9897t_fw_k9.bin and /dev/null differ diff --git a/recovery/root/vendor/firmware/novatek_ts_fw.bin b/recovery/root/vendor/firmware/novatek_ts_fw.bin new file mode 100644 index 0000000..c093b96 Binary files /dev/null and b/recovery/root/vendor/firmware/novatek_ts_fw.bin differ diff --git a/recovery/root/vendor/firmware/novatek_ts_mp.bin b/recovery/root/vendor/firmware/novatek_ts_mp.bin new file mode 100644 index 0000000..c093b96 Binary files /dev/null and b/recovery/root/vendor/firmware/novatek_ts_mp.bin differ diff --git a/recovery/root/vendor/lib/modules/mmi-smbcharger-iio.ko b/recovery/root/vendor/lib/modules/mmi-smbcharger-iio.ko new file mode 100644 index 0000000..0e36793 Binary files /dev/null and b/recovery/root/vendor/lib/modules/mmi-smbcharger-iio.ko differ diff --git a/recovery/root/vendor/lib/modules/nova_0flash_mmi.ko b/recovery/root/vendor/lib/modules/nova_0flash_mmi.ko new file mode 100644 index 0000000..edfdc7f Binary files /dev/null and b/recovery/root/vendor/lib/modules/nova_0flash_mmi.ko differ diff --git a/twrp.dependencies b/twrp.dependencies deleted file mode 100644 index 1a1e918..0000000 --- a/twrp.dependencies +++ /dev/null @@ -1,20 +0,0 @@ -[ - { - "repository" : "android_device_qcom_twrp-common", - "target_path" : "device/qcom/twrp-common", - "remote" : "TeamWin", - "revision" : "android-11" - }, - { - "repository" : "android_hardware_qcom_bootctrl", - "target_path" : "hardware/qcom-caf/bootctrl", - "remote" : "LineageOS", - "revision" : "lineage-18.1-caf" - }, - { - "repository" : "imjyotiraditya/msm-5.4-odin", - "target_path" : "kernel/xiaomi/odin", - "remote" : "github", - "revision" : "android-11" - } -] diff --git a/twrp_odin.mk b/twrp_osaka.mk similarity index 80% rename from twrp_odin.mk rename to twrp_osaka.mk index d6733c1..3881c02 100644 --- a/twrp_odin.mk +++ b/twrp_osaka.mk @@ -18,15 +18,15 @@ $(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk) $(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_base.mk) -# Inherit from odin device -$(call inherit-product, device/xiaomi/odin/device.mk) +# Inherit from osaka device +$(call inherit-product, device/motorola/osaka/device.mk) # Inherit some common TWRP stuff. $(call inherit-product, vendor/twrp/config/common.mk) # Device identifier. This must come after all inclusions -PRODUCT_DEVICE := odin -PRODUCT_NAME := twrp_odin -PRODUCT_BRAND := Xiaomi -PRODUCT_MODEL := Mi Mix 4 -PRODUCT_MANUFACTURER := Xiaomi +PRODUCT_DEVICE := osaka +PRODUCT_NAME := twrp_osaka +PRODUCT_BRAND := Motorola +PRODUCT_MODEL := moto g stylus 5g +PRODUCT_MANUFACTURER := Motorola diff --git a/vendor.prop b/vendor.prop index da3c1d6..7dac10d 100644 --- a/vendor.prop +++ b/vendor.prop @@ -174,8 +174,8 @@ persist.demo.hdmirotationlock=false persist.sys.sf.color_mode=0 persist.sys.sf.color_saturation=1.0 persist.sys.sf.native_mode=0 -ro.gfx.driver.0=com.oneplus.gpudrivers.lahaina.api30 -ro.gfx.driver.1=com.qualcomm.qti.gpudrivers.lahaina.api30 +ro.gfx.driver.0=com.oneplus.gpudrivers.holi.api30 +ro.gfx.driver.1=com.qualcomm.qti.gpudrivers.holi.api30 ro.hardware.egl=adreno ro.hardware.vulkan=adreno ro.opengles.version=196610