From cc0f55b66420a066f256d0e0f4c62bd5efcaa1d8 Mon Sep 17 00:00:00 2001 From: Jan Altensen Date: Fri, 5 Nov 2021 11:33:48 +0100 Subject: [PATCH 1/2] universal8890: Support firmware upgrade Change-Id: Ia64f238358bbc6ef09364039ab0bed594fa5b241 --- BoardConfigCommon.mk | 1 + recovery/Android.bp | 28 +++++++++++ recovery/recovery_updater.cpp | 92 +++++++++++++++++++++++++++++++++++ releasetools/releasetools.py | 81 ++++++++++++++++++++++++++++++ 4 files changed, 202 insertions(+) create mode 100644 recovery/Android.bp create mode 100644 recovery/recovery_updater.cpp diff --git a/BoardConfigCommon.mk b/BoardConfigCommon.mk index 132435b..b51ef4b 100644 --- a/BoardConfigCommon.mk +++ b/BoardConfigCommon.mk @@ -148,6 +148,7 @@ TARGET_RECOVERY_FSTAB := $(COMMON_PATH)/ramdisk/etc/fstab.samsungexynos8890 endif # Releasetools +TARGET_RECOVERY_UPDATER_LIBS := librecovery_updater_universal8890 TARGET_RELEASETOOLS_EXTENSIONS := $(COMMON_PATH)/releasetools # Renderscript diff --git a/recovery/Android.bp b/recovery/Android.bp new file mode 100644 index 0000000..a6cc317 --- /dev/null +++ b/recovery/Android.bp @@ -0,0 +1,28 @@ +// +// Copyright (C) 2021 The LineageOS Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +cc_library_static { + name: "librecovery_updater_universal8890", + srcs: [ + "recovery_updater.cpp", + ], + include_dirs: [ + "system/core/base/include", + "bootable/recovery", + "bootable/recovery/edify/include", + "bootable/recovery/otautil/include" + ], +} diff --git a/recovery/recovery_updater.cpp b/recovery/recovery_updater.cpp new file mode 100644 index 0000000..52f7c4d --- /dev/null +++ b/recovery/recovery_updater.cpp @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2021, The LineageOS Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "edify/expr.h" +#include "otautil/error_code.h" +Value *CompareVariant(const char *name, State *state, + const std::vector> &argv) { + int ret = 0; + std::string bootloader = android::base::GetProperty("ro.boot.bootloader", ""); + if (bootloader.empty()) { + return ErrorAbort(state, kFileGetPropFailure, + "%s() failed to read current bootloader version", name); + } + + std::string target_variant_arg; + if (argv.empty() || !Evaluate(state, argv[0], &target_variant_arg)) { + return ErrorAbort(state, kArgsParsingFailure, + "%s() error parsing arguments", name); + } + + if (target_variant_arg.compare(bootloader.substr(4, target_variant_arg.length())) == 0) { + ret = 1; + } + + return StringValue(std::to_string(ret)); +} + +Value *VerifyBootloaderMin(const char *name, State *state, + const std::vector> &argv __unused) { + int ret = 0; + std::string required_bootloader_version; + std::string bootloader = android::base::GetProperty("ro.boot.bootloader", ""); + if (bootloader.empty()) { + return ErrorAbort(state, kFileGetPropFailure, + "%s() failed to read current bootloader version", name); + } + + if (bootloader.substr(4, 1).compare("F") == 0 || /* matches F and FD */ + bootloader.substr(4, 2).compare("W8") == 0) { + required_bootloader_version = "8"; + } else if (bootloader.substr(4, 1).compare("S") == 0 || + bootloader.substr(4, 1).compare("K") == 0 || + bootloader.substr(4, 1).compare("L") == 0) { + required_bootloader_version = "3"; + } + + if (bootloader.substr(bootloader.length()-5, 1).compare(required_bootloader_version) == 0) + ret = 1; + + return StringValue(std::to_string(ret)); +} + +Value *VerifyBootloaderModel(const char *name, State *state, + const std::vector> &argv __unused) { + int ret = 0; + std::string bootloader = android::base::GetProperty("ro.boot.bootloader", ""); + if (bootloader.empty()) { + return ErrorAbort(state, kFileGetPropFailure, + "%s() failed to read current bootloader version", name); + } + + if (bootloader.substr(4, 1).compare("F") == 0 || /* matches F and FD */ + bootloader.substr(4, 1).compare("S") == 0 || + bootloader.substr(4, 1).compare("K") == 0 || + bootloader.substr(4, 1).compare("L") == 0 || + bootloader.substr(4, 2).compare("W8") == 0) { + ret = 1; + } + + return StringValue(std::to_string(ret)); +} + +void Register_librecovery_updater_universal8890() { + RegisterFunction("universal8890.compare_variant", CompareVariant); + RegisterFunction("universal8890.verify_bootloader_min", VerifyBootloaderMin); + RegisterFunction("universal8890.verify_bootloader_models", VerifyBootloaderModel); +} diff --git a/releasetools/releasetools.py b/releasetools/releasetools.py index 2767da6..d6f87f8 100644 --- a/releasetools/releasetools.py +++ b/releasetools/releasetools.py @@ -15,8 +15,89 @@ # limitations under the License. # +import common +import re + +def FullOTA_Assertions(info): + # If we are shipping firmware make sure that we only flash on F variant + if "RADIO/filemap" in info.input_zip.namelist(): + AddBlModelAssertion(info) + +def FullOTA_InstallEnd(info): + skip_firmware = False + + # Skip Firmware if filemap or any of the images are not present + if "RADIO/filemap" not in info.input_zip.namelist(): + skip_firmware = True + else: + filemap = info.input_zip.read("RADIO/filemap").decode('utf-8').splitlines() + for file in filemap: + filename = file.split(" ")[0] + if "RADIO/{}".format(filename) not in info.input_zip.namelist(): + skip_firmware = True + break + + if not skip_firmware: + CopyFirmware(info.input_zip, info.output_zip) + AddFirmwareUpdate(info, filemap) + def FullOTA_PostValidate(info): info.script.AppendExtra('run_program("/tmp/install/bin/e2fsck_static", "-fy", "/dev/block/platform/155a0000.ufs/by-name/SYSTEM");'); info.script.AppendExtra('run_program("/tmp/install/bin/resize2fs_static", "/dev/block/platform/155a0000.ufs/by-name/SYSTEM");'); info.script.AppendExtra('run_program("/tmp/install/bin/e2fsck_static", "-fy", "/dev/block/platform/155a0000.ufs/by-name/SYSTEM");'); +def CopyFirmware(input_zip, output_zip): + for info in input_zip.infolist(): + f = info.filename + # Copy files in 'RADIO' to output zip 'firmware-update' + if f.startswith("RADIO/") and (f.__len__() > len("RADIO/")): + fn = f[6:] + common.ZipWriteStr(output_zip, "firmware-update/" + fn, input_zip.read(f)) + +def AddBlModelAssertion(info): + info.script.AppendExtra('ifelse(universal8890.verify_bootloader_models() != "1",') + info.script.AppendExtra('ui_print("=============================================");'); + info.script.AppendExtra('ui_print("=============================================");'); + info.script.AppendExtra('ui_print(" ERROR: ");'); + info.script.AppendExtra('ui_print(" Package contains firmware! ");'); + info.script.AppendExtra('ui_print(" Only the following models ");'); + info.script.AppendExtra('ui_print(" are supported: F, FD, S, K, L, W8 ");'); + info.script.AppendExtra('ui_print(" Cross flashing will brick! ");'); + info.script.AppendExtra('ui_print("=============================================");'); + info.script.AppendExtra('ui_print("============NO CHANGE HAS BEEN MADE==========");'); + info.script.AppendExtra('abort(" ");') + info.script.AppendExtra(');') + +def CheckVariant(info, filemap, target_variant): + # check if firmware for the variant is present + if "RADIO/" + target_variant + "_sboot.bin" in info.input_zip.namelist(): + info.script.AppendExtra('ifelse(universal8890.compare_variant("' + target_variant + '") == "1",') + info.script.AppendExtra('(') + for file in filemap: + filename = file.split(" ")[0] + filepath = file.split(" ")[-1] + filevariant = filename.split("_")[0] + if filevariant == target_variant: + info.script.AppendExtra('package_extract_file("firmware-update/' + filename + '", "' + filepath + '");') + info.script.AppendExtra(')') + info.script.AppendExtra(');') + +def AddFirmwareUpdate(info, filemap): + info.script.AppendExtra('ifelse(universal8890.verify_bootloader_min() != "1",') + info.script.AppendExtra('(') + info.script.AppendExtra('ui_print("Upgrading firmware");') + + # supported models are the same for s7 and s7 edge + # F and FD are the same + CheckVariant(info, filemap, "F") + CheckVariant(info, filemap, "S") + CheckVariant(info, filemap, "K") + CheckVariant(info, filemap, "L") + CheckVariant(info, filemap, "W8") + + info.script.AppendExtra('run_program("/sbin/reboot","fota_bl");') + info.script.AppendExtra('),') + info.script.AppendExtra('(') + info.script.AppendExtra('ui_print("Firmware is up-to-date");') + info.script.AppendExtra(')') + info.script.AppendExtra(');') -- GitLab From 0981329904ae55d2eb9db62a8023f33d84b269be Mon Sep 17 00:00:00 2001 From: Jan Altensen Date: Mon, 22 Nov 2021 12:20:55 +0100 Subject: [PATCH 2/2] universal8890: compare full bootloader version for upgrade decision Change-Id: I361f7902ee06eb28be3e04a640174a8cb8b97dd3 --- recovery/recovery_updater.cpp | 37 +++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/recovery/recovery_updater.cpp b/recovery/recovery_updater.cpp index 52f7c4d..3bfcdfa 100644 --- a/recovery/recovery_updater.cpp +++ b/recovery/recovery_updater.cpp @@ -40,6 +40,21 @@ Value *CompareVariant(const char *name, State *state, return StringValue(std::to_string(ret)); } +/** + * for more informations + * see https://android.stackexchange.com/questions/202491/what-do-the-numbers-and-letters-in-the-samsung-firmware-mean/202494#202494 + */ +int compareBootloader(std::string a, std::string b) { + /* compare bootloader version */ + if (std::stoi(a.substr(a.length() - 5), nullptr, 32) < std::stoi(b.substr(b.length() - 5), nullptr, 32)) { + return 0; + } + + // if version on the device is the same or newer dont upgrade + return 1; +} + + Value *VerifyBootloaderMin(const char *name, State *state, const std::vector> &argv __unused) { int ret = 0; @@ -50,17 +65,19 @@ Value *VerifyBootloaderMin(const char *name, State *state, "%s() failed to read current bootloader version", name); } - if (bootloader.substr(4, 1).compare("F") == 0 || /* matches F and FD */ - bootloader.substr(4, 2).compare("W8") == 0) { - required_bootloader_version = "8"; - } else if (bootloader.substr(4, 1).compare("S") == 0 || - bootloader.substr(4, 1).compare("K") == 0 || - bootloader.substr(4, 1).compare("L") == 0) { - required_bootloader_version = "3"; - } + bool isHero2 = bootloader.substr(0, 4).compare("G935") == 0; - if (bootloader.substr(bootloader.length()-5, 1).compare(required_bootloader_version) == 0) - ret = 1; + if (bootloader.substr(4, 1).compare("F") == 0) { /* matches F and FD */ + ret = compareBootloader(bootloader, isHero2 ? "G935FXXU8ETI2" : "G930FXXU8ETI2"); + } else if(bootloader.substr(4, 1).compare("K") == 0) { + ret = compareBootloader(bootloader, isHero2 ? "G935KKKU3ETJ1" : "G930KKKU3ETJ1"); + } else if(bootloader.substr(4, 1).compare("L") == 0) { + ret = compareBootloader(bootloader, isHero2 ? "G935LKLU3ETJ1" : "G930LKLU3ETJ1"); + } else if(bootloader.substr(4, 1).compare("S") == 0) { + ret = compareBootloader(bootloader, isHero2 ? "G935SKSU3ETJ1" : "G930SKSU3ETJ1"); + } else if(bootloader.substr(4, 2).compare("W8") == 0) { + ret = compareBootloader(bootloader, isHero2 ? "G935W8VLS8CTI1" : "G930W8VLS8CTI1"); + } return StringValue(std::to_string(ret)); } -- GitLab