diff --git a/bbootimg/src/main/kotlin/Signer.kt b/bbootimg/src/main/kotlin/Signer.kt index 6811dac..e181e83 100644 --- a/bbootimg/src/main/kotlin/Signer.kt +++ b/bbootimg/src/main/kotlin/Signer.kt @@ -44,22 +44,23 @@ class Signer { partition_name = bootDesc.partition_name, newAvbInfo = ObjectMapper().readValue(File(getJsonFileName(cfg.info.output)), AVBInfo::class.java)) //original signer - File(cfg.info.output + ".clear").copyTo(File(cfg.info.output + ".signed2")) - var cmdlineStr = "$avbtool add_hash_footer " + - "--image ${cfg.info.output}.signed2 " + - "--partition_size ${info2.imageSize} " + - "--salt ${Helper.toHexString(bootDesc.salt)} " + - "--partition_name ${bootDesc.partition_name} " + - "--hash_algorithm ${bootDesc.hash_algorithm} " + - "--algorithm ${alg!!.name} " - if (alg.defaultKey.isNotBlank()) { - cmdlineStr += "--key ${alg.defaultKey}" + CommandLine.parse("$avbtool add_hash_footer").apply { + addArguments("--image ${cfg.info.output}.signed2") + addArguments("--partition_size ${info2.imageSize}") + addArguments("--salt ${Helper.toHexString(bootDesc.salt)}") + addArguments("--partition_name ${bootDesc.partition_name}") + addArguments("--hash_algorithm ${bootDesc.hash_algorithm}") + addArguments("--algorithm ${alg!!.name}") + if (alg.defaultKey.isNotBlank()) { + addArguments("--key ${alg.defaultKey}") + } + addArgument("--internal_release_string") + addArgument(ai.header!!.release_string, false) + log.warn(this.toString()) + + File(cfg.info.output + ".clear").copyTo(File(cfg.info.output + ".signed2")) + DefaultExecutor().execute(this) } - log.warn(cmdlineStr) - val cmdLine = CommandLine.parse(cmdlineStr) - cmdLine.addArgument("--internal_release_string") - cmdLine.addArgument(ai.header!!.release_string, false) - DefaultExecutor().execute(cmdLine) Parser.verifyAVBIntegrity(cfg.info.output, avbtool) } } diff --git a/bbootimg/src/main/kotlin/avb/Avb.kt b/bbootimg/src/main/kotlin/avb/Avb.kt index 7280bbe..28f2c81 100644 --- a/bbootimg/src/main/kotlin/avb/Avb.kt +++ b/bbootimg/src/main/kotlin/avb/Avb.kt @@ -141,7 +141,7 @@ class Avb { } } - fun parseVbMeta(image_file: String): AVBInfo { + fun parseVbMeta(image_file: String, dumpFile: Boolean = true): AVBInfo { log.info("parsing $image_file ...") val jsonFile = getJsonFileName(image_file) var footer: Footer? = null @@ -257,8 +257,13 @@ class Avb { } } - ObjectMapper().writerWithDefaultPrettyPrinter().writeValue(File(jsonFile), ai) - log.info("vbmeta info written to $jsonFile") + if (dumpFile) { + ObjectMapper().writerWithDefaultPrettyPrinter().writeValue(File(jsonFile), ai) + log.info("vbmeta info of [$image_file] has been analyzed") + log.info("vbmeta info written to $jsonFile") + } else { + log.warn("vbmeta info of [$image_file] has been analyzed, no dummping") + } return ai } diff --git a/bbootimg/src/main/kotlin/packable/BootImgParser.kt b/bbootimg/src/main/kotlin/packable/BootImgParser.kt index 85456b0..45e50b0 100644 --- a/bbootimg/src/main/kotlin/packable/BootImgParser.kt +++ b/bbootimg/src/main/kotlin/packable/BootImgParser.kt @@ -1,20 +1,34 @@ package cfig.packable +import avb.AVBInfo import cfig.* import cfig.bootimg.BootImgInfo +import com.fasterxml.jackson.databind.ObjectMapper import de.vandermeer.asciitable.AsciiTable import org.slf4j.LoggerFactory import java.io.File import java.lang.IllegalArgumentException @ExperimentalUnsignedTypes -class BootImgParser : IPackable { +class BootImgParser() : IPackable { + override val loopNo: Int + get() = 0 private val log = LoggerFactory.getLogger(BootImgParser::class.java) override fun capabilities(): List { return listOf("^boot\\.img$", "^recovery\\.img$", "^recovery-two-step\\.img$") } + private fun unpackVBMeta(): Boolean { + if (File("vbmeta.img").exists()) { + log.warn("Found vbmeta.img, parsing ...") + VBMetaParser().unpack("vbmeta.img") + return true + } else { + return false + } + } + override fun unpack(fileName: String) { if (File(UnifiedConfig.workDir).exists()) File(UnifiedConfig.workDir).deleteRecursively() File(UnifiedConfig.workDir).mkdirs() @@ -29,6 +43,7 @@ class BootImgParser : IPackable { InfoTable.instance.addRow("AVB info", Avb.getJsonFileName(fileName)) } Parser().extractBootImg(fileName, info2 = info) + val unpackedVbmeta = unpackVBMeta() InfoTable.instance.addRule() val tableHeader = AsciiTable().apply { @@ -37,6 +52,14 @@ class BootImgParser : IPackable { addRule() } log.info("\n\t\t\tUnpack Summary of $fileName\n{}\n{}", tableHeader.render(), InfoTable.instance.render()) + if (unpackedVbmeta) { + val tableFooter = AsciiTable().apply { + addRule() + addRow("vbmeta.img", Avb.getJsonFileName("vbmeta.img")) + addRule() + } + LoggerFactory.getLogger("vbmeta").info("\n" + tableFooter.render()) + } log.info("Following components are not present: ${InfoTable.missingParts}") } catch (e: IllegalArgumentException) { log.error(e.message) @@ -47,6 +70,28 @@ class BootImgParser : IPackable { override fun pack(fileName: String) { Packer().pack(mkbootfsBin = "./aosp/mkbootfs/build/exe/mkbootfs/mkbootfs") Signer.sign(avbtool = "avb/avbtool", bootSigner = "aosp/boot_signer/build/libs/boot_signer.jar") + if (File("vbmeta.img").exists()) { + val partitionName = ObjectMapper().readValue(File(Avb.getJsonFileName(fileName)), AVBInfo::class.java).let { + it.auxBlob!!.hashDescriptors.get(0).partition_name + } + val newHashDesc = Avb().parseVbMeta("$fileName.signed", dumpFile = false) + assert(newHashDesc.auxBlob!!.hashDescriptors.size == 1) + val mainVBMeta = ObjectMapper().readValue(File(Avb.getJsonFileName("vbmeta.img")), AVBInfo::class.java).apply { + val itr = this.auxBlob!!.hashDescriptors.iterator() + var seq = 0 + while (itr.hasNext()) { + val itrValue = itr.next() + if (itrValue.partition_name == partitionName) { + seq = itrValue.sequence + itr.remove() + break + } + } + val hd = newHashDesc.auxBlob!!.hashDescriptors.get(0).apply { this.sequence = seq } + this.auxBlob!!.hashDescriptors.add(hd) + } + Avb().packVbMetaWithPadding("vbmeta.img", mainVBMeta) + } } override fun flash(fileName: String, deviceName: String) { diff --git a/bbootimg/src/main/kotlin/packable/DtboParser.kt b/bbootimg/src/main/kotlin/packable/DtboParser.kt index 6ade4e0..c078aab 100644 --- a/bbootimg/src/main/kotlin/packable/DtboParser.kt +++ b/bbootimg/src/main/kotlin/packable/DtboParser.kt @@ -12,6 +12,9 @@ import java.util.* @ExperimentalUnsignedTypes class DtboParser(val workDir: File) : IPackable { + override val loopNo: Int + get() = 0 + constructor() : this(File(".")) private val log = LoggerFactory.getLogger(DtboParser::class.java) diff --git a/bbootimg/src/main/kotlin/packable/IPackable.kt b/bbootimg/src/main/kotlin/packable/IPackable.kt index 2411b75..2c6ec67 100644 --- a/bbootimg/src/main/kotlin/packable/IPackable.kt +++ b/bbootimg/src/main/kotlin/packable/IPackable.kt @@ -6,6 +6,7 @@ import org.slf4j.Logger import org.slf4j.LoggerFactory interface IPackable { + val loopNo: Int fun capabilities(): List { return listOf("^dtbo\\.img$") } diff --git a/bbootimg/src/main/kotlin/packable/PackableLauncher.kt b/bbootimg/src/main/kotlin/packable/PackableLauncher.kt index ac6f09b..0bbf7c8 100644 --- a/bbootimg/src/main/kotlin/packable/PackableLauncher.kt +++ b/bbootimg/src/main/kotlin/packable/PackableLauncher.kt @@ -25,16 +25,33 @@ fun main(args: Array) { var targetHandler: KClass? = null run found@{ File(".").listFiles().forEach { file -> - packablePool.forEach { p -> - for (item in p.key) { - if (Pattern.compile(item).matcher(file.name).matches()) { - log.debug("Found: " + file.name + ", " + item) - targetFile = file.name - targetHandler = p.value - return@found + packablePool + .filter { it.value.createInstance().loopNo == 0 } + .forEach { p -> + for (item in p.key) { + if (Pattern.compile(item).matcher(file.name).matches()) { + log.debug("Found: " + file.name + ", " + item) + targetFile = file.name + targetHandler = p.value + return@found + } + } + } + } + + File(".").listFiles().forEach { file -> + packablePool + .filter { it.value.createInstance().loopNo != 0 } + .forEach { p -> + for (item in p.key) { + if (Pattern.compile(item).matcher(file.name).matches()) { + log.debug("Found: " + file.name + ", " + item) + targetFile = file.name + targetHandler = p.value + return@found + } + } } - } - } } } diff --git a/bbootimg/src/main/kotlin/packable/VBMetaParser.kt b/bbootimg/src/main/kotlin/packable/VBMetaParser.kt index 853349d..8f366ea 100644 --- a/bbootimg/src/main/kotlin/packable/VBMetaParser.kt +++ b/bbootimg/src/main/kotlin/packable/VBMetaParser.kt @@ -4,6 +4,9 @@ import cfig.Avb @ExperimentalUnsignedTypes class VBMetaParser: IPackable { + override val loopNo: Int + get() = 1 + override fun capabilities(): List { return listOf("^vbmeta\\.img$", "^vbmeta\\_[a-z]+.img$") } diff --git a/bbootimg/src/main/kotlin/sparse_util/SparseImg.kt b/bbootimg/src/main/kotlin/sparse_util/SparseImg.kt index 7517cbb..fa8067a 100644 --- a/bbootimg/src/main/kotlin/sparse_util/SparseImg.kt +++ b/bbootimg/src/main/kotlin/sparse_util/SparseImg.kt @@ -7,6 +7,8 @@ import cfig.Helper.Companion.check_call @ExperimentalUnsignedTypes class SparseImg : IPackable { + override val loopNo: Int + get() = 0 private val log = LoggerFactory.getLogger(SparseImg::class.java) private val simg2imgBin: String private val img2simgBin: String diff --git a/src/integrationTest/resources b/src/integrationTest/resources index 9c8f314..2b95308 160000 --- a/src/integrationTest/resources +++ b/src/integrationTest/resources @@ -1 +1 @@ -Subproject commit 9c8f314279c08d9d06720b5be86b5894f872682c +Subproject commit 2b95308b91c2c0a564451b744354b2ef1428311d