bruh
This commit is contained in:
parent
5a04596287
commit
ae7bf49520
38 changed files with 1814 additions and 129 deletions
|
@ -1,3 +1,2 @@
|
|||
soong_namespace {
|
||||
imports: ["hardware/qcom-caf/bootctrl"],
|
||||
}
|
||||
|
|
|
@ -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)))
|
||||
|
||||
|
|
|
@ -15,4 +15,4 @@
|
|||
#
|
||||
|
||||
PRODUCT_MAKEFILES := \
|
||||
$(LOCAL_DIR)/twrp_odin.mk
|
||||
$(LOCAL_DIR)/twrp_osaka.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
|
||||
|
|
24
bootctrl/1.1/impl/Android.bp
Normal file
24
bootctrl/1.1/impl/Android.bp
Normal file
|
@ -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",
|
||||
],
|
||||
}
|
132
bootctrl/1.1/impl/BootControl.cpp
Normal file
132
bootctrl/1.1/impl/BootControl.cpp
Normal file
|
@ -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 <memory>
|
||||
|
||||
#include <log/log.h>
|
||||
|
||||
#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<uint32_t> BootControl::getNumberSlots() {
|
||||
return get_number_slots();
|
||||
}
|
||||
|
||||
Return<uint32_t> BootControl::getCurrentSlot() {
|
||||
return get_current_slot();
|
||||
}
|
||||
|
||||
Return<void> 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<void> 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<void> 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<BoolResult> 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<BoolResult> 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<void> 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<bool> BootControl::setSnapshotMergeStatus(MergeStatus status) {
|
||||
return set_snapshot_merge_status(status);
|
||||
}
|
||||
|
||||
Return<MergeStatus> BootControl::getSnapshotMergeStatus() {
|
||||
return get_snapshot_merge_status();
|
||||
}
|
||||
|
||||
IBootControl* HIDL_FETCH_IBootControl(const char* /* hal */) {
|
||||
auto module = std::make_unique<BootControl>();
|
||||
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
|
75
bootctrl/1.1/impl/BootControl.h
Normal file
75
bootctrl/1.1/impl/BootControl.h
Normal file
|
@ -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 <android/hardware/boot/1.1/IBootControl.h>
|
||||
#include <hidl/MQDescriptor.h>
|
||||
#include <hidl/Status.h>
|
||||
#include <libboot_control_qti.h>
|
||||
|
||||
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<uint32_t> getNumberSlots() override;
|
||||
Return<uint32_t> getCurrentSlot() override;
|
||||
Return<void> markBootSuccessful(markBootSuccessful_cb _hidl_cb) override;
|
||||
Return<void> setActiveBootSlot(uint32_t slot, setActiveBootSlot_cb _hidl_cb) override;
|
||||
Return<void> setSlotAsUnbootable(uint32_t slot, setSlotAsUnbootable_cb _hidl_cb) override;
|
||||
Return<BoolResult> isSlotBootable(uint32_t slot) override;
|
||||
Return<BoolResult> isSlotMarkedSuccessful(uint32_t slot) override;
|
||||
Return<void> getSuffix(uint32_t slot, getSuffix_cb _hidl_cb) override;
|
||||
|
||||
// Methods from ::android::hardware::boot::V1_1::IBootControl follow.
|
||||
Return<bool> setSnapshotMergeStatus(MergeStatus status) override;
|
||||
Return<MergeStatus> getSnapshotMergeStatus() override;
|
||||
|
||||
};
|
||||
|
||||
extern "C" IBootControl* HIDL_FETCH_IBootControl(const char* name);
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V1_1
|
||||
} // namespace boot
|
||||
} // namespace hardware
|
||||
} // namespace android
|
38
bootctrl/1.1/libboot_control_qti/Android.bp
Normal file
38
bootctrl/1.1/libboot_control_qti/Android.bp
Normal file
|
@ -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"],
|
||||
}
|
679
bootctrl/1.1/libboot_control_qti/libboot_control_qti.cpp
Normal file
679
bootctrl/1.1/libboot_control_qti/libboot_control_qti.cpp
Normal file
|
@ -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 <libboot_control_qti.h>
|
||||
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <errno.h>
|
||||
#define LOG_TAG "bootcontrolhal"
|
||||
#include <cutils/log.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <cutils/properties.h>
|
||||
#include <gpt-utils.h>
|
||||
#include <libboot_control/libboot_control.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,
|
||||
};
|
||||
|
||||
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<string> 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<string>::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<string, vector<string>> ptn_map;
|
||||
vector<string> 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<string, vector<string>>::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]--><partitions on device 1>
|
||||
// [path_to_block_device_2]--><partitions on device 2>
|
||||
// ...
|
||||
// ...
|
||||
// eg:
|
||||
// [/dev/block/sdb]---><system, boot, rpm, tz,....>
|
||||
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;
|
||||
}
|
50
bootctrl/1.1/libboot_control_qti/libboot_control_qti.h
Normal file
50
bootctrl/1.1/libboot_control_qti/libboot_control_qti.h
Normal file
|
@ -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 <string>
|
||||
#include <android/hardware/boot/1.1/IBootControl.h>
|
||||
|
||||
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();
|
|
@ -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"],
|
||||
}
|
||||
|
|
26
bootctrl/NOTICE
Normal file
26
bootctrl/NOTICE
Normal file
|
@ -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.
|
703
bootctrl/boot_control.cpp
Normal file
703
bootctrl/boot_control.cpp
Normal file
|
@ -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 <map>
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#define LOG_TAG "bootcontrolhal"
|
||||
#include <cutils/log.h>
|
||||
#include <hardware/boot_control.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <cutils/properties.h>
|
||||
#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<string> 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<string>::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<string, vector<string>> ptn_map;
|
||||
vector<string> 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<string, vector<string>>::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]--><partitions on device 1>
|
||||
// [path_to_block_device_2]--><partitions on device 2>
|
||||
// ...
|
||||
// ...
|
||||
// eg:
|
||||
// [/dev/block/sdb]---><system, boot, rpm, tz,....>
|
||||
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
|
15
device.mk
15
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 \
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
|
||||
cc_library {
|
||||
name: "libgptutils.odin",
|
||||
name: "libgptutils.osaka",
|
||||
vendor: true,
|
||||
recovery_available: true,
|
||||
shared_libs: [
|
||||
|
|
|
@ -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"
|
||||
|
||||
/******************************************************************************
|
||||
|
|
2
odm.prop
2
odm.prop
|
@ -1,2 +0,0 @@
|
|||
# Audio
|
||||
ro.vendor.qti.va_odm.support=1
|
|
@ -36,15 +36,10 @@
|
|||
|
||||
#<src> <mnt_point> <type> <mnt_flags and options> <fs_mgr_flags>
|
||||
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
|
||||
|
|
|
@ -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
|
||||
|
|
4
recovery/root/system/bin/load_modules.sh
Normal file
4
recovery/root/system/bin/load_modules.sh
Normal file
|
@ -0,0 +1,4 @@
|
|||
#!/system/bin/sh
|
||||
|
||||
insmod /vendor/lib/modules/nova_0flash_mmi.ko
|
||||
insmod /vendor/lib/modules/mmi-smbcharger-iio.ko
|
|
@ -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
|
|
@ -35,16 +35,10 @@
|
|||
# specify MF_CHECK, and must come before any filesystems that do specify MF_CHECK
|
||||
|
||||
#<src> <mnt_point> <type> <mnt_flags and options> <fs_mgr_flags>
|
||||
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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
BIN
recovery/root/vendor/firmware/auo_novatek_ts_fw.bin
vendored
Normal file
BIN
recovery/root/vendor/firmware/auo_novatek_ts_fw.bin
vendored
Normal file
Binary file not shown.
BIN
recovery/root/vendor/firmware/auo_novatek_ts_mp.bin
vendored
Normal file
BIN
recovery/root/vendor/firmware/auo_novatek_ts_mp.bin
vendored
Normal file
Binary file not shown.
BIN
recovery/root/vendor/firmware/bod_novatek_ts_fw.bin
vendored
Normal file
BIN
recovery/root/vendor/firmware/bod_novatek_ts_fw.bin
vendored
Normal file
Binary file not shown.
BIN
recovery/root/vendor/firmware/bod_novatek_ts_mp.bin
vendored
Normal file
BIN
recovery/root/vendor/firmware/bod_novatek_ts_mp.bin
vendored
Normal file
Binary file not shown.
BIN
recovery/root/vendor/firmware/boe_novatek_ts_fw.bin
vendored
Normal file
BIN
recovery/root/vendor/firmware/boe_novatek_ts_fw.bin
vendored
Normal file
Binary file not shown.
BIN
recovery/root/vendor/firmware/boe_novatek_ts_mp.bin
vendored
Normal file
BIN
recovery/root/vendor/firmware/boe_novatek_ts_mp.bin
vendored
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
recovery/root/vendor/firmware/novatek_ts_fw.bin
vendored
Normal file
BIN
recovery/root/vendor/firmware/novatek_ts_fw.bin
vendored
Normal file
Binary file not shown.
BIN
recovery/root/vendor/firmware/novatek_ts_mp.bin
vendored
Normal file
BIN
recovery/root/vendor/firmware/novatek_ts_mp.bin
vendored
Normal file
Binary file not shown.
BIN
recovery/root/vendor/lib/modules/mmi-smbcharger-iio.ko
vendored
Normal file
BIN
recovery/root/vendor/lib/modules/mmi-smbcharger-iio.ko
vendored
Normal file
Binary file not shown.
BIN
recovery/root/vendor/lib/modules/nova_0flash_mmi.ko
vendored
Normal file
BIN
recovery/root/vendor/lib/modules/nova_0flash_mmi.ko
vendored
Normal file
Binary file not shown.
|
@ -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"
|
||||
}
|
||||
]
|
|
@ -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
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue