diff --git a/app/aboot/aboot.c b/app/aboot/aboot.c index 8ff43f59eb..02d12f83eb 100644 --- a/app/aboot/aboot.c +++ b/app/aboot/aboot.c @@ -1576,6 +1576,56 @@ void get_recovery_dtbo_info(uint32_t *dtbo_size, void **dtbo_buf) return; } +bool detect_android_from_mmc(void) +{ + const char *ptn_names[] = {"boot", "real_boot"}; + unsigned int i; + int index = INVALID_PTN; + unsigned long long ptn = 0; + uint64_t image_size = 0; + bool partition_found = false; + boot_img_hdr *hdr = (void*) buf; + static bool detected = false, result = false; + + if (detected) + return result; + + for (i = 0; i < ARRAY_SIZE(ptn_names); i++) { + index = partition_get_index(ptn_names[i]); + if (index != INVALID_PTN) { + ptn = partition_get_offset(index); + image_size = partition_get_size(index); + } + if (index != INVALID_PTN && ptn != 0 && image_size != 0) { + partition_found = true; + break; + } + dprintf(CRITICAL, "ERROR: No %s partition found\n", ptn_names[i]); + } + + if (!partition_found) { + detected = true; + return result; + } + + /* Set Lun for boot & recovery partitions */ + mmc_set_lun(partition_get_lun(index)); + + if (mmc_read(ptn, (uint32_t *) buf, page_size)) { + dprintf(CRITICAL, "ERROR: Cannot read boot image header\n"); + detected = true; + return result; + } + + if (strstr((const char *)hdr->cmdline, "androidboot.")) { + dprintf(INFO, "Detected Android boot parameter\n"); + result = true; + } + + detected = true; + return result; +} + int boot_linux_from_mmc(void) { boot_img_hdr *hdr = (void*) buf; @@ -1625,8 +1675,9 @@ int boot_linux_from_mmc(void) #endif struct kernel64_hdr *kptr = NULL; int current_active_slot = INVALID; + bool try_alternate_partition = false; - if (!IS_ENABLED(ABOOT_STANDALONE) && check_format_bit()) + if (detect_android_from_mmc() && check_format_bit()) boot_into_recovery = 1; if (!IS_ENABLED(ABOOT_STANDALONE) && !boot_into_recovery) { @@ -1653,6 +1704,7 @@ int boot_linux_from_mmc(void) } } +retry_boot: index = partition_get_index(ptn_name); ptn = partition_get_offset(index); image_size = partition_get_size(index); @@ -1670,8 +1722,21 @@ int boot_linux_from_mmc(void) } if (memcmp(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)) { - dprintf(CRITICAL, "ERROR: Invalid boot image header\n"); - return ERR_INVALID_BOOT_MAGIC; + dprintf(CRITICAL, "ERROR: Invalid boot image header on partition %s\n", ptn_name); + if (IS_ENABLED(WITH_LK2ND_DEVICE_2ND) && !try_alternate_partition) { + try_alternate_partition = true; + if (strcmp(ptn_name, "boot") == 0) { + ptn_name = "real_boot"; + } else if (strcmp(ptn_name, "recovery") == 0) { + ptn_name = "real_recovery"; + } else { + dprintf(CRITICAL, "No alternate partition for %s, Abort.\n", ptn_name); + return ERR_INVALID_BOOT_MAGIC; + } + dprintf(CRITICAL, "Retrying boot with %s partition\n", ptn_name); + goto retry_boot; + } + return ERR_INVALID_BOOT_MAGIC; } if (hdr->page_size && (hdr->page_size != page_size)) { @@ -3168,7 +3233,9 @@ void cmd_boot(const char *arg, void *data, unsigned sz) unsigned int kernel_size = 0; enum boot_type boot_type = 0; #if DEVICE_TREE + void * image_buf = NULL; uint8_t dtb_copied = 0; + unsigned dtb_image_size = 0; unsigned int scratch_offset = 0; #endif #if VERIFIED_BOOT_2 @@ -3184,6 +3251,9 @@ void cmd_boot(const char *arg, void *data, unsigned sz) static bool is_mdtp_activated = 0; #endif /* MDTP_SUPPORT */ #endif +#ifdef OSVERSION_IN_BOOTIMAGE + uint32_t dtb_image_offset = 0; +#endif #if FBCON_DISPLAY_MSG /* Exit keys' detection thread firstly */ @@ -3221,6 +3291,7 @@ void cmd_boot(const char *arg, void *data, unsigned sz) dt_size = hdr->dt_size; #endif dt_actual = ROUND_TO_PAGE(dt_size, page_mask); + dtb_image_size = hdr->kernel_size; #endif image_actual = ADD_OF(page_size, kernel_actual); @@ -3228,6 +3299,31 @@ void cmd_boot(const char *arg, void *data, unsigned sz) image_actual = ADD_OF(image_actual, second_actual); image_actual = ADD_OF(image_actual, dt_actual); +#ifdef OSVERSION_IN_BOOTIMAGE + if (hdr->header_version == BOOT_HEADER_VERSION_TWO) { + struct boot_img_hdr_v1 *hdr1 = + (struct boot_img_hdr_v1 *) (data + sizeof(boot_img_hdr)); + struct boot_img_hdr_v2 *hdr2 = (struct boot_img_hdr_v2 *) + (data + sizeof(boot_img_hdr) + + BOOT_IMAGE_HEADER_V2_OFFSET); + unsigned int recovery_dtbo_actual = 0; + + recovery_dtbo_actual = + ROUND_TO_PAGE(hdr1->recovery_dtbo_size, page_mask); + image_actual += recovery_dtbo_actual; + + image_actual += ROUND_TO_PAGE(hdr2->dtb_size, page_mask); + + + dtb_image_offset = page_size +/* patched_kernel_hdr_size +*/ + kernel_actual + ramdisk_actual + second_actual + + recovery_dtbo_actual; + + dprintf(SPEW, "Header version: %d\n", hdr->header_version); + dprintf(SPEW, "Dtb image offset 0x%x\n", dtb_image_offset); + } +#endif + /* Checking to prevent oob access in read_der_message_length */ if (image_actual > sz) { fastboot_fail("bootimage header fields are invalid"); @@ -3439,10 +3535,20 @@ void cmd_boot(const char *arg, void *data, unsigned sz) * memory address to the DTB appended location on RAM. * Else update with the atags address in the kernel header */ + image_buf = (void*)(ptr + page_size); + +#ifdef OSVERSION_IN_BOOTIMAGE + if ( hdr->header_version == BOOT_HEADER_VERSION_TWO) { + image_buf = (void*)(ptr); + dtb_offset = dtb_image_offset; + dtb_image_size = image_actual; + } +#endif + if (!dtb_copied) { void *dtb; - dtb = dev_tree_appended((void*)(ptr + page_size), - hdr->kernel_size, dtb_offset, + dtb = dev_tree_appended(image_buf, + dtb_image_size, dtb_offset, (void *)hdr->tags_addr); #if WITH_LK2ND_DEVICE_2ND if (!dtb && lk2nd_device2nd_have_atags()) @@ -5658,7 +5764,7 @@ void aboot_init(const struct app_descriptor *app) if (target_is_emmc_boot()) { - if(!IS_ENABLED(ABOOT_STANDALONE) && emmc_recovery_init()) + if(detect_android_from_mmc() && emmc_recovery_init()) dprintf(ALWAYS,"error in emmc_recovery_init\n"); if(target_use_signed_kernel()) { diff --git a/app/aboot/recovery.c b/app/aboot/recovery.c index b1ad21cc54..8128836617 100644 --- a/app/aboot/recovery.c +++ b/app/aboot/recovery.c @@ -396,7 +396,7 @@ int send_recovery_cmd(const char *command) int _emmc_recovery_init(void) { - int update_status = 0; + int update_status __attribute__((unused)) = 0; struct recovery_message *msg; uint32_t block_size = 0; @@ -428,6 +428,7 @@ int _emmc_recovery_init(void) boot_into_recovery = 1; } +#if !ABOOT_STANDALONE if (!strcmp("update-radio",msg->command)) { /* We're now here due to radio update, so check for update status */ @@ -460,6 +461,7 @@ int _emmc_recovery_init(void) emmc_set_recovery_msg(msg); // send recovery message out: +#endif if(msg) free(msg); return 0; diff --git a/app/aboot/rules.mk b/app/aboot/rules.mk index de0a3c8ca3..ccb777e511 100644 --- a/app/aboot/rules.mk +++ b/app/aboot/rules.mk @@ -13,7 +13,6 @@ OBJS += \ ifeq ($(ABOOT_STANDALONE), 1) DEFINES += ABOOT_STANDALONE=1 -OBJS := $(filter-out $(LOCAL_DIR)/recovery.o, $(OBJS)) DEFINES := $(filter-out SSD_ENABLE TZ_SAVE_KERNEL_HASH TZ_TAMPER_FUSE, $(DEFINES)) endif diff --git a/lk2nd/device/2nd/partition.c b/lk2nd/device/2nd/partition.c index 5021f88ce6..7c7f810e9e 100644 --- a/lk2nd/device/2nd/partition.c +++ b/lk2nd/device/2nd/partition.c @@ -13,7 +13,7 @@ static void partition_split_mmc(const char *base_name, const char *name, uint32_t num_blocks, bool end) { - struct partition_entry *base, *split; + struct partition_entry *backup, *base, *split; int index = partition_get_index(base_name); if (index == INVALID_PTN) { @@ -29,6 +29,15 @@ static void partition_split_mmc(const char *base_name, const char *name, return; } + backup = partition_allocate(); + if (backup) { + memcpy(backup, base, sizeof(*backup)); + snprintf((char*)backup->name, sizeof(backup->name), "real_%s", base_name); + } else { + dprintf(CRITICAL, "Too many partitions, cannot backup %s partition entry\n", + base_name); + } + split = partition_allocate(); if (split) { memcpy(split, base, sizeof(*split)); @@ -67,6 +76,16 @@ static void partition_split_flash(struct ptable *ptable, const char *base_name, return; } + if (ptable_size(ptable) < MAX_PTABLE_PARTS) { + char backup_name[MAX_PTENTRY_NAME]; + snprintf(backup_name, sizeof(backup_name), "real_%s", base_name); + ptable_add(ptable, backup_name, base->start, base->length, + base->flags, base->type, base->perm); + } else { + dprintf(CRITICAL, "Too many partitions, cannot backup %s partition entry\n", + base_name); + } + if (ptable_size(ptable) < MAX_PTABLE_PARTS) { unsigned start = base->start; if (end) @@ -88,9 +107,15 @@ static void lk2nd_partition_split_mmc(void) { uint32_t block_size __UNUSED = mmc_get_device_blocksize(); -#ifdef LK2ND_PARTITION_SIZE - partition_split_mmc(LK2ND_PARTITION_BASE, LK2ND_PARTITION_NAME, - LK2ND_PARTITION_SIZE / block_size, false); +#ifdef LK2ND_BOOT_PARTITION_SIZE + partition_split_mmc(LK2ND_BOOT_PARTITION_BASE, + LK2ND_BOOT_PARTITION_NAME, + LK2ND_BOOT_PARTITION_SIZE / block_size, false); +#endif +#ifdef LK2ND_RECOVERY_PARTITION_SIZE + partition_split_mmc(LK2ND_RECOVERY_PARTITION_BASE, + LK2ND_RECOVERY_PARTITION_NAME, + LK2ND_RECOVERY_PARTITION_SIZE / block_size, false); #endif } @@ -102,9 +127,15 @@ static void lk2nd_partition_split_flash(void) if (!ptable) return; -#ifdef LK2ND_PARTITION_SIZE - partition_split_flash(ptable, LK2ND_PARTITION_BASE, LK2ND_PARTITION_NAME, - LK2ND_PARTITION_SIZE / block_size, false); +#ifdef LK2ND_BOOT_PARTITION_SIZE + partition_split_flash(ptable, LK2ND_BOOT_PARTITION_BASE, + LK2ND_BOOT_PARTITION_NAME, + LK2ND_BOOT_PARTITION_SIZE / block_size, false); +#endif +#ifdef LK2ND_RECOVERY_PARTITION_SIZE + partition_split_flash(ptable, LK2ND_RECOVERY_PARTITION_BASE, + LK2ND_RECOVERY_PARTITION_NAME, + LK2ND_RECOVERY_PARTITION_SIZE / block_size, false); #endif } diff --git a/lk2nd/device/2nd/rules.mk b/lk2nd/device/2nd/rules.mk index 06d2dd523b..b20f16ae88 100644 --- a/lk2nd/device/2nd/rules.mk +++ b/lk2nd/device/2nd/rules.mk @@ -15,11 +15,17 @@ OBJS += \ $(LOCAL_DIR)/samsung-muic-reset.o \ $(if $(filter %/mdss_spi.o, $(OBJS)), $(LOCAL_DIR)/spi-display.o) \ -ifneq ($(LK2ND_PARTITION_SIZE),) +ifneq ($(LK2ND_BOOT_PARTITION_SIZE),) DEFINES += \ - LK2ND_PARTITION_BASE="$(LK2ND_PARTITION_BASE)" \ - LK2ND_PARTITION_NAME="$(LK2ND_PARTITION_NAME)" \ - LK2ND_PARTITION_SIZE=($(LK2ND_PARTITION_SIZE)) + LK2ND_BOOT_PARTITION_BASE="$(LK2ND_BOOT_PARTITION_BASE)" \ + LK2ND_BOOT_PARTITION_NAME="$(LK2ND_BOOT_PARTITION_NAME)" \ + LK2ND_BOOT_PARTITION_SIZE=($(LK2ND_BOOT_PARTITION_SIZE)) +endif +ifneq ($(LK2ND_RECOVERY_PARTITION_SIZE),) +DEFINES += \ + LK2ND_RECOVERY_PARTITION_BASE="$(LK2ND_RECOVERY_PARTITION_BASE)" \ + LK2ND_RECOVERY_PARTITION_NAME="$(LK2ND_RECOVERY_PARTITION_NAME)" \ + LK2ND_RECOVERY_PARTITION_SIZE=($(LK2ND_RECOVERY_PARTITION_SIZE)) endif include $(if $(BUILD_GPL),$(LOCAL_DIR)/gpl/rules.mk) diff --git a/lk2nd/project/base.mk b/lk2nd/project/base.mk index 92b5510f37..2816e9f8af 100644 --- a/lk2nd/project/base.mk +++ b/lk2nd/project/base.mk @@ -66,9 +66,15 @@ DEFINES += GENERATE_CMDLINE_ONLY_FOR_ANDROID=1 # Disable reading splash partition to avoid crashes on some devices DEFINES += DISABLE_SPLASH_PARTITION=1 +# Disable updating Android fstab devicetree node +DEFINES += SKIP_UPDATE_ANDROID_FSTAB=1 + # Enable "fastboot oem help" for a list of supported fastboot commands DEFINES += FASTBOOT_HELP=1 +# Enable Android dynamic partitions support +DEFINES += DYNAMIC_PARTITION_SUPPORT=1 + # Allow entering fastboot after forced reset DEFINES := $(filter-out USER_FORCE_RESET_SUPPORT=1, $(DEFINES)) diff --git a/lk2nd/project/lk2nd.mk b/lk2nd/project/lk2nd.mk index 9d8ab85260..d426ff2d49 100644 --- a/lk2nd/project/lk2nd.mk +++ b/lk2nd/project/lk2nd.mk @@ -11,11 +11,14 @@ ifneq ($(ENABLE_FBCON_DISPLAY_MSG),1) MODULES += $(if $(filter $(MODULES), lk2nd/display), lk2nd/device/menu) endif -# Use part of the "boot" partition for the lk2nd boot image. The real Android -# boot image can be placed in the partition with 512 KiB offset. -LK2ND_PARTITION_BASE ?= boot -LK2ND_PARTITION_NAME ?= lk2nd -LK2ND_PARTITION_SIZE ?= 512*1024 +# Use part of the "boot" and "recovery" partition for the lk2nd boot image. +# The real Android boot image can be placed in the partition with 512 KiB offset. +LK2ND_BOOT_PARTITION_BASE ?= boot +LK2ND_BOOT_PARTITION_NAME ?= lk2nd +LK2ND_BOOT_PARTITION_SIZE ?= 512*1024 +LK2ND_RECOVERY_PARTITION_BASE ?= recovery +LK2ND_RECOVERY_PARTITION_NAME ?= lk2nd_recovery +LK2ND_RECOVERY_PARTITION_SIZE ?= 512*1024 # The primary bootloader will implement LONG_PRESS_POWER_ON if needed. # If we do it again in lk2nd we might accidentally shutdown the device because diff --git a/makefile b/makefile index 11224ad6c2..fade492fbc 100644 --- a/makefile +++ b/makefile @@ -134,6 +134,10 @@ ifeq ($(DYNAMIC_PARTITION_SUPPORT),1) DEFINES += DYNAMIC_PARTITION_SUPPORT=1 endif +ifeq ($(SKIP_UPDATE_ANDROID_FSTAB),1) + DEFINES += SKIP_UPDATE_ANDROID_FSTAB=1 +endif + ifeq ($(TARGET_DTBO_NOT_SUPPORTED),1) DEFINES += TARGET_DTBO_NOT_SUPPORTED=1 endif diff --git a/platform/msm_shared/dev_tree.c b/platform/msm_shared/dev_tree.c index 86757c0641..9d27600843 100644 --- a/platform/msm_shared/dev_tree.c +++ b/platform/msm_shared/dev_tree.c @@ -75,7 +75,7 @@ struct dt_entry_v1 uint32_t size; }; -#if ENABLE_BOOTDEVICE_MOUNT || DYNAMIC_PARTITION_SUPPORT +#if !SKIP_UPDATE_ANDROID_FSTAB && (ENABLE_BOOTDEVICE_MOUNT || DYNAMIC_PARTITION_SUPPORT) /* Look up table for fstab node */ struct fstab_node { @@ -2334,7 +2334,7 @@ int update_device_tree(void *fdt, const char *cmdline, enum boot_type boot_type, } } -#if ENABLE_BOOTDEVICE_MOUNT || DYNAMIC_PARTITION_SUPPORT +#if !SKIP_UPDATE_ANDROID_FSTAB && (ENABLE_BOOTDEVICE_MOUNT || DYNAMIC_PARTITION_SUPPORT) /* Update fstab node */ dprintf(SPEW, "Start of fstab node update:%zu ms\n", platform_get_sclk_count()); if (update_fstab_node(fdt) != 0) { @@ -2357,7 +2357,7 @@ int update_device_tree(void *fdt, const char *cmdline, enum boot_type boot_type, return ret; } -#if ENABLE_BOOTDEVICE_MOUNT || DYNAMIC_PARTITION_SUPPORT +#if !SKIP_UPDATE_ANDROID_FSTAB && (ENABLE_BOOTDEVICE_MOUNT || DYNAMIC_PARTITION_SUPPORT) /*Update device tree for fstab node */ static int update_fstab_node(void *fdt) {