diff --git a/.travis.yml b/.travis.yml index 89a703f..9a0e907 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,4 @@ -dist: bionic +dist: focal language: java before_install: - sudo apt -qq update diff --git a/bbootimg/build.gradle.kts b/bbootimg/build.gradle.kts index 3362dd7..fe461c7 100644 --- a/bbootimg/build.gradle.kts +++ b/bbootimg/build.gradle.kts @@ -1,7 +1,8 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { - id("org.jetbrains.kotlin.jvm").version("1.3.71") + kotlin("jvm") version "1.4.0" + kotlin("plugin.serialization") version "1.4.0" application } @@ -13,10 +14,11 @@ dependencies { implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") implementation("org.jetbrains.kotlin:kotlin-reflect") - implementation("org.slf4j:slf4j-simple:1.7.29") - implementation("org.slf4j:slf4j-api:1.7.29") - implementation("com.fasterxml.jackson.core:jackson-annotations:2.10.1") - implementation("com.fasterxml.jackson.core:jackson-databind:2.10.1") + implementation("org.slf4j:slf4j-simple:1.7.30") + implementation("org.slf4j:slf4j-api:1.7.30") + implementation("com.fasterxml.jackson.core:jackson-annotations:2.11.2") + implementation("com.fasterxml.jackson.core:jackson-databind:2.11.2") + implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:1.0.0-RC") implementation("com.google.guava:guava:18.0") implementation("org.apache.commons:commons-exec:1.3") implementation("org.apache.commons:commons-compress:1.16.1") diff --git a/bbootimg/src/main/kotlin/EnvironmentVerifier.kt b/bbootimg/src/main/kotlin/EnvironmentVerifier.kt index b4ecae1..962d620 100644 --- a/bbootimg/src/main/kotlin/EnvironmentVerifier.kt +++ b/bbootimg/src/main/kotlin/EnvironmentVerifier.kt @@ -46,6 +46,9 @@ class EnvironmentVerifier { log.debug("lz4 available") } catch (e: Exception) { log.warn("lz4 not installed") + if (isMacOS) { + log.warn("For Mac OS: \n\n\tbrew install lz4\n") + } return false } return true diff --git a/bbootimg/src/main/kotlin/Helper.kt b/bbootimg/src/main/kotlin/Helper.kt index c605aff..c729397 100644 --- a/bbootimg/src/main/kotlin/Helper.kt +++ b/bbootimg/src/main/kotlin/Helper.kt @@ -205,6 +205,15 @@ class Helper { } } + fun round_to_multiple(size: Int, page: Int): Int { + val remainder = size % page + return if (remainder == 0) { + size + } else { + size + page - remainder + } + } + /* read RSA private key assert exp == 65537 diff --git a/bbootimg/src/main/kotlin/avb/Avb.kt b/bbootimg/src/main/kotlin/avb/Avb.kt index 4c54f4b..32e3ff5 100644 --- a/bbootimg/src/main/kotlin/avb/Avb.kt +++ b/bbootimg/src/main/kotlin/avb/Avb.kt @@ -74,9 +74,9 @@ class Avb { // + AvbFooter + padding newAvbInfo.footer!!.apply { - originalImageSize = newImageSize.toULong() - vbMetaOffset = vbmetaOffset.toULong() - vbMetaSize = vbmetaBlob.size.toULong() + originalImageSize = newImageSize + vbMetaOffset = vbmetaOffset + vbMetaSize = vbmetaBlob.size.toLong() } log.info(newAvbInfo.footer.toString()) val footerBlobWithPadding = newAvbInfo.footer!!.encode().paddingWith(BLOCK_SIZE.toUInt(), true) @@ -113,7 +113,7 @@ class Avb { FileOutputStream(File(image_file), true).channel.use { fc -> log.info("original image $image_file has AVB footer, " + "truncate it to original SIZE: ${it.originalImageSize}") - fc.truncate(it.originalImageSize.toLong()) + fc.truncate(it.originalImageSize) } } } @@ -146,7 +146,7 @@ class Avb { log.info("parsing $image_file ...") val jsonFile = getJsonFileName(image_file) var footer: Footer? = null - var vbMetaOffset: ULong = 0U + var vbMetaOffset: Long = 0 // footer FileInputStream(image_file).use { fis -> fis.skip(File(image_file).length() - Footer.SIZE) @@ -160,26 +160,26 @@ class Avb { } // header - var vbMetaHeader = Header() + var vbMetaHeader: Header FileInputStream(image_file).use { fis -> - fis.skip(vbMetaOffset.toLong()) + fis.skip(vbMetaOffset) vbMetaHeader = Header(fis) } log.info(vbMetaHeader.toString()) log.debug(ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(vbMetaHeader)) - val authBlockOffset = vbMetaOffset + Header.SIZE.toUInt() + val authBlockOffset = vbMetaOffset + Header.SIZE val auxBlockOffset = authBlockOffset + vbMetaHeader.authentication_data_block_size val descStartOffset = auxBlockOffset + vbMetaHeader.descriptors_offset val ai = AVBInfo(vbMetaHeader, null, AuxBlob(), footer) // Auth blob - if (vbMetaHeader.authentication_data_block_size > 0U) { + if (vbMetaHeader.authentication_data_block_size > 0) { FileInputStream(image_file).use { fis -> - fis.skip(vbMetaOffset.toLong()) + fis.skip(vbMetaOffset) fis.skip(Header.SIZE.toLong()) - fis.skip(vbMetaHeader.hash_offset.toLong()) + fis.skip(vbMetaHeader.hash_offset) val ba = ByteArray(vbMetaHeader.hash_size.toInt()) fis.read(ba) log.debug("Parsed Auth Hash (Header & Aux Blob): " + Hex.encodeHexString(ba)) @@ -197,10 +197,10 @@ class Avb { // aux - desc var descriptors: List = mutableListOf() - if (vbMetaHeader.descriptors_size > 0U) { + if (vbMetaHeader.descriptors_size > 0) { FileInputStream(image_file).use { fis -> - fis.skip(descStartOffset.toLong()) - descriptors = UnknownDescriptor.parseDescriptors2(fis, vbMetaHeader.descriptors_size.toLong()) + fis.skip(descStartOffset) + descriptors = UnknownDescriptor.parseDescriptors2(fis, vbMetaHeader.descriptors_size) } descriptors.forEach { log.debug(it.toString()) @@ -230,28 +230,28 @@ class Avb { } } // aux - pubkey - if (vbMetaHeader.public_key_size > 0U) { + if (vbMetaHeader.public_key_size > 0) { ai.auxBlob!!.pubkey = AuxBlob.PubKeyInfo() - ai.auxBlob!!.pubkey!!.offset = vbMetaHeader.public_key_offset.toLong() - ai.auxBlob!!.pubkey!!.size = vbMetaHeader.public_key_size.toLong() + ai.auxBlob!!.pubkey!!.offset = vbMetaHeader.public_key_offset + ai.auxBlob!!.pubkey!!.size = vbMetaHeader.public_key_size FileInputStream(image_file).use { fis -> - fis.skip(auxBlockOffset.toLong()) - fis.skip(vbMetaHeader.public_key_offset.toLong()) + fis.skip(auxBlockOffset) + fis.skip(vbMetaHeader.public_key_offset) ai.auxBlob!!.pubkey!!.pubkey = ByteArray(vbMetaHeader.public_key_size.toInt()) fis.read(ai.auxBlob!!.pubkey!!.pubkey) log.debug("Parsed Pub Key: " + Hex.encodeHexString(ai.auxBlob!!.pubkey!!.pubkey)) } } // aux - pkmd - if (vbMetaHeader.public_key_metadata_size > 0U) { + if (vbMetaHeader.public_key_metadata_size > 0) { ai.auxBlob!!.pubkeyMeta = AuxBlob.PubKeyMetadataInfo() - ai.auxBlob!!.pubkeyMeta!!.offset = vbMetaHeader.public_key_metadata_offset.toLong() - ai.auxBlob!!.pubkeyMeta!!.size = vbMetaHeader.public_key_metadata_size.toLong() + ai.auxBlob!!.pubkeyMeta!!.offset = vbMetaHeader.public_key_metadata_offset + ai.auxBlob!!.pubkeyMeta!!.size = vbMetaHeader.public_key_metadata_size FileInputStream(image_file).use { fis -> - fis.skip(auxBlockOffset.toLong()) - fis.skip(vbMetaHeader.public_key_metadata_offset.toLong()) + fis.skip(auxBlockOffset) + fis.skip(vbMetaHeader.public_key_metadata_offset) ai.auxBlob!!.pubkeyMeta!!.pkmd = ByteArray(vbMetaHeader.public_key_metadata_size.toInt()) fis.read(ai.auxBlob!!.pubkeyMeta!!.pkmd) log.debug("Parsed Pub Key Metadata: " + Helper.toHexString(ai.auxBlob!!.pubkeyMeta!!.pkmd)) @@ -271,30 +271,30 @@ class Avb { private fun packVbMeta(info: AVBInfo? = null, image_file: String? = null): ByteArray { val ai = info ?: ObjectMapper().readValue(File(getJsonFileName(image_file!!)), AVBInfo::class.java) - val alg = Algorithms.get(ai.header!!.algorithm_type.toInt())!! + val alg = Algorithms.get(ai.header!!.algorithm_type)!! //3 - whole aux blob val auxBlob = ai.auxBlob?.encode(alg) ?: byteArrayOf() //1 - whole header blob val headerBlob = ai.header!!.apply { - auxiliary_data_block_size = auxBlob.size.toULong() + auxiliary_data_block_size = auxBlob.size.toLong() authentication_data_block_size = Helper.round_to_multiple( - (alg.hash_num_bytes + alg.signature_num_bytes).toLong(), 64).toULong() + (alg.hash_num_bytes + alg.signature_num_bytes).toLong(), 64) - descriptors_offset = 0U - descriptors_size = ai.auxBlob?.descriptorSize?.toULong() ?: 0U + descriptors_offset = 0 + descriptors_size = ai.auxBlob?.descriptorSize?.toLong() ?: 0 - hash_offset = 0U - hash_size = alg.hash_num_bytes.toULong() + hash_offset = 0 + hash_size = alg.hash_num_bytes.toLong() - signature_offset = alg.hash_num_bytes.toULong() - signature_size = alg.signature_num_bytes.toULong() + signature_offset = alg.hash_num_bytes.toLong() + signature_size = alg.signature_num_bytes.toLong() public_key_offset = descriptors_size - public_key_size = AuxBlob.encodePubKey(alg).size.toULong() + public_key_size = AuxBlob.encodePubKey(alg).size.toLong() - public_key_metadata_size = ai.auxBlob!!.pubkeyMeta?.pkmd?.size?.toULong() ?: 0U + public_key_metadata_size = ai.auxBlob!!.pubkeyMeta?.pkmd?.size?.toLong() ?: 0L public_key_metadata_offset = public_key_offset + public_key_size log.info("pkmd size: $public_key_metadata_size, pkmd offset : $public_key_metadata_offset") }.encode() @@ -316,8 +316,8 @@ class Avb { companion object { private val log = LoggerFactory.getLogger(Avb::class.java) - const val AVB_VERSION_MAJOR = 1U - const val AVB_VERSION_MINOR = 1U + const val AVB_VERSION_MAJOR = 1 + const val AVB_VERSION_MINOR = 1 const val AVB_VERSION_SUB = 0 fun getJsonFileName(image_file: String): String { diff --git a/bbootimg/src/main/kotlin/avb/blob/AuthBlob.kt b/bbootimg/src/main/kotlin/avb/blob/AuthBlob.kt index 44d81a1..7ef719c 100644 --- a/bbootimg/src/main/kotlin/avb/blob/AuthBlob.kt +++ b/bbootimg/src/main/kotlin/avb/blob/AuthBlob.kt @@ -8,8 +8,8 @@ import java.security.MessageDigest @OptIn(ExperimentalUnsignedTypes::class) data class AuthBlob( - var offset: ULong = 0U, - var size: ULong = 0U, + var offset: Long = 0, + var size: Long = 0, var hash: String? = null, var signature: String? = null) { companion object { diff --git a/bbootimg/src/main/kotlin/avb/blob/Footer.kt b/bbootimg/src/main/kotlin/avb/blob/Footer.kt index f1e29e9..6a1a525 100644 --- a/bbootimg/src/main/kotlin/avb/blob/Footer.kt +++ b/bbootimg/src/main/kotlin/avb/blob/Footer.kt @@ -25,11 +25,11 @@ https://github.com/cfig/Android_boot_image_editor/blob/master/doc/layout.md#32-a @OptIn(ExperimentalUnsignedTypes::class) data class Footer constructor( - var versionMajor: UInt = FOOTER_VERSION_MAJOR, - var versionMinor: UInt = FOOTER_VERSION_MINOR, - var originalImageSize: ULong = 0U, - var vbMetaOffset: ULong = 0U, - var vbMetaSize: ULong = 0U + var versionMajor: Int = FOOTER_VERSION_MAJOR, + var versionMinor: Int = FOOTER_VERSION_MINOR, + var originalImageSize: Long = 0, + var vbMetaOffset: Long = 0, + var vbMetaSize: Long = 0 ) { @Throws(IllegalArgumentException::class) constructor(iS: InputStream) : this() { @@ -38,14 +38,14 @@ data class Footer constructor( if (MAGIC != (info[0] as String)) { throw IllegalArgumentException("stream doesn't look like valid AVB Footer") } - versionMajor = info[1] as UInt - versionMinor = info[2] as UInt - originalImageSize = info[3] as ULong - vbMetaOffset = info[4] as ULong - vbMetaSize = info[5] as ULong + versionMajor = (info[1] as UInt).toInt() + versionMinor = (info[2] as UInt).toInt() + originalImageSize = (info[3] as ULong).toLong() + vbMetaOffset = (info[4] as ULong).toLong() + vbMetaSize = (info[5] as ULong).toLong() } - constructor(originalImageSize: ULong, vbMetaOffset: ULong, vbMetaSize: ULong) + constructor(originalImageSize: Long, vbMetaOffset: Long, vbMetaSize: Long) : this(FOOTER_VERSION_MAJOR, FOOTER_VERSION_MINOR, originalImageSize, vbMetaOffset, vbMetaSize) @Throws(IllegalArgumentException::class) @@ -75,8 +75,8 @@ data class Footer constructor( private const val MAGIC = "AVBf" const val SIZE = 64 private const val RESERVED = 28 - private const val FOOTER_VERSION_MAJOR = 1U - private const val FOOTER_VERSION_MINOR = 0U + private const val FOOTER_VERSION_MAJOR = 1 + private const val FOOTER_VERSION_MINOR = 0 private const val FORMAT_STRING = "!4s2L3Q${RESERVED}x" init { diff --git a/bbootimg/src/main/kotlin/avb/blob/Header.kt b/bbootimg/src/main/kotlin/avb/blob/Header.kt index b196005..d025d5b 100644 --- a/bbootimg/src/main/kotlin/avb/blob/Header.kt +++ b/bbootimg/src/main/kotlin/avb/blob/Header.kt @@ -7,23 +7,23 @@ import java.io.InputStream //avbtool::AvbVBMetaHeader @OptIn(ExperimentalUnsignedTypes::class) data class Header( - var required_libavb_version_major: UInt = Avb.AVB_VERSION_MAJOR, - var required_libavb_version_minor: UInt = 0U, - var authentication_data_block_size: ULong = 0U, - var auxiliary_data_block_size: ULong = 0U, - var algorithm_type: UInt = 0U, - var hash_offset: ULong = 0U, - var hash_size: ULong = 0U, - var signature_offset: ULong = 0U, - var signature_size: ULong = 0U, - var public_key_offset: ULong = 0U, - var public_key_size: ULong = 0U, - var public_key_metadata_offset: ULong = 0U, - var public_key_metadata_size: ULong = 0U, - var descriptors_offset: ULong = 0U, - var descriptors_size: ULong = 0U, - var rollback_index: ULong = 0U, - var flags: UInt = 0U, + var required_libavb_version_major: Int = Avb.AVB_VERSION_MAJOR, + var required_libavb_version_minor: Int = 0, + var authentication_data_block_size: Long = 0, + var auxiliary_data_block_size: Long = 0, + var algorithm_type: Int = 0, + var hash_offset: Long = 0, + var hash_size: Long = 0, + var signature_offset: Long = 0, + var signature_size: Long = 0, + var public_key_offset: Long = 0, + var public_key_size: Long = 0, + var public_key_metadata_offset: Long = 0, + var public_key_metadata_size: Long = 0, + var descriptors_offset: Long = 0, + var descriptors_size: Long = 0, + var rollback_index: Long = 0, + var flags: Int = 0, var release_string: String = "avbtool ${Avb.AVB_VERSION_MAJOR}.${Avb.AVB_VERSION_MINOR}.${Avb.AVB_VERSION_SUB}") { @Throws(IllegalArgumentException::class) constructor(iS: InputStream) : this() { @@ -32,23 +32,23 @@ data class Header( if (info[0] != magic) { throw IllegalArgumentException("stream doesn't look like valid VBMeta Header") } - this.required_libavb_version_major = info[1] as UInt - this.required_libavb_version_minor = info[2] as UInt - this.authentication_data_block_size = info[3] as ULong - this.auxiliary_data_block_size = info[4] as ULong - this.algorithm_type = info[5] as UInt - this.hash_offset = info[6] as ULong - this.hash_size = info[7] as ULong - this.signature_offset = info[8] as ULong - this.signature_size = info[9] as ULong - this.public_key_offset = info[10] as ULong - this.public_key_size = info[11] as ULong - this.public_key_metadata_offset = info[12] as ULong - this.public_key_metadata_size = info[13] as ULong - this.descriptors_offset = info[14] as ULong - this.descriptors_size = info[15] as ULong - this.rollback_index = info[16] as ULong - this.flags = info[17] as UInt + this.required_libavb_version_major = (info[1] as UInt).toInt() + this.required_libavb_version_minor = (info[2] as UInt).toInt() + this.authentication_data_block_size = (info[3] as ULong).toLong() + this.auxiliary_data_block_size = (info[4] as ULong).toLong() + this.algorithm_type = (info[5] as UInt).toInt() + this.hash_offset = (info[6] as ULong).toLong() + this.hash_size = (info[7] as ULong).toLong() + this.signature_offset = (info[8] as ULong).toLong() + this.signature_size = (info[9] as ULong).toLong() + this.public_key_offset = (info[10] as ULong).toLong() + this.public_key_size = (info[11] as ULong).toLong() + this.public_key_metadata_offset = (info[12] as ULong).toLong() + this.public_key_metadata_size = (info[13] as ULong).toLong() + this.descriptors_offset = (info[14] as ULong).toLong() + this.descriptors_size = (info[15] as ULong).toLong() + this.rollback_index = (info[16] as ULong).toLong() + this.flags = (info[17] as UInt).toInt() //padding: info[18] this.release_string = info[19] as String } @@ -72,7 +72,7 @@ data class Header( null) //${REVERSED}x } - fun bump_required_libavb_version_minor(minor: UInt) { + fun bump_required_libavb_version_minor(minor: Int) { this.required_libavb_version_minor = maxOf(required_libavb_version_minor, minor) } diff --git a/bbootimg/src/main/kotlin/avb/desc/ChainPartitionDescriptor.kt b/bbootimg/src/main/kotlin/avb/desc/ChainPartitionDescriptor.kt index 06f26af..a86e61e 100644 --- a/bbootimg/src/main/kotlin/avb/desc/ChainPartitionDescriptor.kt +++ b/bbootimg/src/main/kotlin/avb/desc/ChainPartitionDescriptor.kt @@ -8,22 +8,22 @@ import java.util.* @OptIn(ExperimentalUnsignedTypes::class) class ChainPartitionDescriptor( - var rollback_index_location: UInt = 0U, - var partition_name_len: UInt = 0U, - var public_key_len: UInt = 0U, + var rollback_index_location: Int = 0, + var partition_name_len: Int = 0, + var public_key_len: Int = 0, var partition_name: String = "", var pubkey: ByteArray = byteArrayOf(), var pubkey_sha1: String = "" -) : Descriptor(TAG, 0U, 0) { +) : Descriptor(TAG, 0, 0) { override fun encode(): ByteArray { - this.partition_name_len = this.partition_name.length.toUInt() - this.public_key_len = this.pubkey.size.toUInt() - this.num_bytes_following = (SIZE.toUInt() + this.partition_name_len + this.public_key_len - 16U).toULong() - val nbf_with_padding = Helper.round_to_multiple(this.num_bytes_following.toLong(), 8).toULong() - val padding_size = nbf_with_padding - this.num_bytes_following + this.partition_name_len = this.partition_name.length + this.public_key_len = this.pubkey.size + this.num_bytes_following = SIZE + this.partition_name_len + this.public_key_len - 16 + val nbf_with_padding = Helper.round_to_multiple(this.num_bytes_following, 8).toULong() + val padding_size = nbf_with_padding - this.num_bytes_following.toUInt() val desc = Struct3(FORMAT_STRING + "${RESERVED}x").pack( TAG, - nbf_with_padding.toULong(), + nbf_with_padding, this.rollback_index_location, this.partition_name.length.toUInt(), this.public_key_len, @@ -33,7 +33,7 @@ class ChainPartitionDescriptor( } companion object { - const val TAG: ULong = 4U + const val TAG: Long = 4L const val RESERVED = 64 const val SIZE = 28L + RESERVED const val FORMAT_STRING = "!2Q3L" @@ -45,14 +45,14 @@ class ChainPartitionDescriptor( } this.sequence = seq val info = Struct3(FORMAT_STRING + "${RESERVED}s").unpack(data) - this.tag = info[0] as ULong - this.num_bytes_following = info[1] as ULong - this.rollback_index_location = info[2] as UInt - this.partition_name_len = info[3] as UInt - this.public_key_len = info[4] as UInt + this.tag = (info[0] as ULong).toLong() + this.num_bytes_following = (info[1] as ULong).toLong() + this.rollback_index_location = (info[2] as UInt).toInt() + this.partition_name_len = (info[3] as UInt).toInt() + this.public_key_len = (info[4] as UInt).toInt() val expectedSize = Helper.round_to_multiple( - SIZE.toUInt() - 16U + this.partition_name_len + this.public_key_len, 8U) - if (this.tag != TAG || this.num_bytes_following != expectedSize.toULong()) { + SIZE - 16 + this.partition_name_len + this.public_key_len, 8) + if (this.tag != TAG || this.num_bytes_following != expectedSize.toLong()) { throw IllegalArgumentException("Given data does not look like a chain/delegation descriptor") } val info2 = Struct3("${this.partition_name_len}s${this.public_key_len}b").unpack(data) diff --git a/bbootimg/src/main/kotlin/avb/desc/Descriptor.kt b/bbootimg/src/main/kotlin/avb/desc/Descriptor.kt index 79aea1d..e31dc02 100644 --- a/bbootimg/src/main/kotlin/avb/desc/Descriptor.kt +++ b/bbootimg/src/main/kotlin/avb/desc/Descriptor.kt @@ -1,6 +1,6 @@ package avb.desc @OptIn(ExperimentalUnsignedTypes::class) -abstract class Descriptor(var tag: ULong, var num_bytes_following: ULong, var sequence: Int = 0) { +abstract class Descriptor(var tag: Long, var num_bytes_following: Long, var sequence: Int = 0) { abstract fun encode(): ByteArray } diff --git a/bbootimg/src/main/kotlin/avb/desc/HashDescriptor.kt b/bbootimg/src/main/kotlin/avb/desc/HashDescriptor.kt index e84ea1c..2d6ae82 100644 --- a/bbootimg/src/main/kotlin/avb/desc/HashDescriptor.kt +++ b/bbootimg/src/main/kotlin/avb/desc/HashDescriptor.kt @@ -11,19 +11,19 @@ import java.io.InputStream import java.security.MessageDigest @OptIn(ExperimentalUnsignedTypes::class) -class HashDescriptor(var flags: UInt = 0U, +class HashDescriptor(var flags: Int = 0, var partition_name: String = "", var hash_algorithm: String = "", - var image_size: ULong = 0U, + var image_size: Long = 0, var salt: ByteArray = byteArrayOf(), var digest: ByteArray = byteArrayOf(), - var partition_name_len: UInt = 0U, - var salt_len: UInt = 0U, - var digest_len: UInt = 0U) - : Descriptor(TAG, 0U, 0) { + var partition_name_len: Int = 0, + var salt_len: Int = 0, + var digest_len: Int = 0) + : Descriptor(TAG, 0, 0) { var flagsInterpretation: String = "" get() { - return if (this.flags and Header.HashDescriptorFlags.AVB_HASH_DESCRIPTOR_FLAGS_DO_NOT_USE_AB.inFlags.toUInt() == 1U) { + return if (this.flags and Header.HashDescriptorFlags.AVB_HASH_DESCRIPTOR_FLAGS_DO_NOT_USE_AB.inFlags == 1) { "1:no-A/B system" } else { "0:A/B system" @@ -32,17 +32,17 @@ class HashDescriptor(var flags: UInt = 0U, constructor(data: InputStream, seq: Int = 0) : this() { val info = Struct3(FORMAT_STRING).unpack(data) - this.tag = info[0] as ULong - this.num_bytes_following = info[1] as ULong - this.image_size = info[2] as ULong + this.tag = (info[0] as ULong).toLong() + this.num_bytes_following = (info[1] as ULong).toLong() + this.image_size = (info[2] as ULong).toLong() this.hash_algorithm = info[3] as String - this.partition_name_len = info[4] as UInt - this.salt_len = info[5] as UInt - this.digest_len = info[6] as UInt - this.flags = info[7] as UInt + this.partition_name_len = (info[4] as UInt).toInt() + this.salt_len = (info[5] as UInt).toInt() + this.digest_len = (info[6] as UInt).toInt() + this.flags = (info[7] as UInt).toInt() this.sequence = seq val expectedSize = Helper.round_to_multiple( - SIZE - 16 + (partition_name_len + salt_len + digest_len).toLong(), 8).toULong() + SIZE - 16 + (partition_name_len + salt_len + digest_len).toLong(), 8) if (this.tag != TAG || expectedSize != this.num_bytes_following) { throw IllegalArgumentException("Given data does not look like a |hash| descriptor") } @@ -55,8 +55,8 @@ class HashDescriptor(var flags: UInt = 0U, override fun encode(): ByteArray { val payload_bytes_following = SIZE + this.partition_name.length + this.salt.size + this.digest.size - 16L - this.num_bytes_following = Helper.round_to_multiple(payload_bytes_following, 8).toULong() - val padding_size = num_bytes_following - payload_bytes_following.toUInt() + this.num_bytes_following = Helper.round_to_multiple(payload_bytes_following, 8) + val padding_size = num_bytes_following - payload_bytes_following val desc = Struct3(FORMAT_STRING).pack( TAG, this.num_bytes_following, @@ -88,17 +88,17 @@ class HashDescriptor(var flags: UInt = 0U, it.read(randomSalt) log.warn("salt is empty, using random salt[$expectedDigestSize]: " + Helper.toHexString(randomSalt)) this.salt = randomSalt - this.salt_len = this.salt.size.toUInt() + this.salt_len = this.salt.size } } else { log.info("preset salt[${this.salt.size}] is valid: ${Hex.encodeHexString(this.salt)}") } //size - this.image_size = File(image_file).length().toULong() + this.image_size = File(image_file).length() //flags - if (this.flags and 1U == 1U) { + if (this.flags and 1 == 1) { log.info("flag: use_ab = 0") } else { log.info("flag: use_ab = 1") @@ -112,14 +112,14 @@ class HashDescriptor(var flags: UInt = 0U, }.digest() log.info("Digest(salt + file): " + Helper.toHexString(newDigest)) this.digest = newDigest - this.digest_len = this.digest.size.toUInt() + this.digest_len = this.digest.size } return this } companion object { - const val TAG: ULong = 2U + const val TAG: Long = 2L private const val RESERVED = 60 private const val SIZE = 72 + RESERVED private const val FORMAT_STRING = "!3Q32s4L${RESERVED}x" diff --git a/bbootimg/src/main/kotlin/avb/desc/HashTreeDescriptor.kt b/bbootimg/src/main/kotlin/avb/desc/HashTreeDescriptor.kt index b903b06..446d3a0 100644 --- a/bbootimg/src/main/kotlin/avb/desc/HashTreeDescriptor.kt +++ b/bbootimg/src/main/kotlin/avb/desc/HashTreeDescriptor.kt @@ -8,24 +8,24 @@ import java.util.* @OptIn(ExperimentalUnsignedTypes::class) class HashTreeDescriptor( - var flags: UInt = 0U, - var dm_verity_version: UInt = 0u, - var image_size: ULong = 0UL, - var tree_offset: ULong = 0UL, - var tree_size: ULong = 0UL, - var data_block_size: UInt = 0U, - var hash_block_size: UInt = 0U, - var fec_num_roots: UInt = 0U, - var fec_offset: ULong = 0U, - var fec_size: ULong = 0U, + var flags: Int = 0, + var dm_verity_version: Int = 0, + var image_size: Long = 0, + var tree_offset: Long = 0, + var tree_size: Long = 0, + var data_block_size: Int = 0, + var hash_block_size: Int = 0, + var fec_num_roots: Int = 0, + var fec_offset: Long = 0, + var fec_size: Long = 0, var hash_algorithm: String = "", var partition_name: String = "", var salt: ByteArray = byteArrayOf(), - var root_digest: ByteArray = byteArrayOf()) : Descriptor(TAG, 0U, 0) { + var root_digest: ByteArray = byteArrayOf()) : Descriptor(TAG, 0, 0) { var flagsInterpretation: String = "" get() { var ret = "" - if (this.flags and Header.HashTreeDescriptorFlags.AVB_HASHTREE_DESCRIPTOR_FLAGS_DO_NOT_USE_AB.inFlags.toUInt() == 1U) { + if (this.flags and Header.HashTreeDescriptorFlags.AVB_HASHTREE_DESCRIPTOR_FLAGS_DO_NOT_USE_AB.inFlags == 1) { ret += "1:no-A/B system" } else { ret += "0:A/B system" @@ -36,24 +36,24 @@ class HashTreeDescriptor( constructor(data: InputStream, seq: Int = 0) : this() { this.sequence = seq val info = Struct3(FORMAT_STRING).unpack(data) - this.tag = info[0] as ULong - this.num_bytes_following = info[1] as ULong - this.dm_verity_version = info[2] as UInt - this.image_size = info[3] as ULong - this.tree_offset = info[4] as ULong - this.tree_size = info[5] as ULong - this.data_block_size = info[6] as UInt - this.hash_block_size = info[7] as UInt - this.fec_num_roots = info[8] as UInt - this.fec_offset = info[9] as ULong - this.fec_size = info[10] as ULong + this.tag = (info[0] as ULong).toLong() + this.num_bytes_following = (info[1] as ULong).toLong() + this.dm_verity_version = (info[2] as UInt).toInt() + this.image_size = (info[3] as ULong).toLong() + this.tree_offset = (info[4] as ULong).toLong() + this.tree_size = (info[5] as ULong).toLong() + this.data_block_size = (info[6] as UInt).toInt() + this.hash_block_size = (info[7] as UInt).toInt() + this.fec_num_roots = (info[8] as UInt).toInt() + this.fec_offset = (info[9] as ULong).toLong() + this.fec_size = (info[10] as ULong).toLong() this.hash_algorithm = info[11] as String val partition_name_len = info[12] as UInt val salt_len = info[13] as UInt val root_digest_len = info[14] as UInt - this.flags = info[15] as UInt + this.flags = (info[15] as UInt).toInt() val expectedSize = Helper.round_to_multiple(SIZE.toUInt() - 16U + partition_name_len + salt_len + root_digest_len, 8U) - if (this.tag != TAG || this.num_bytes_following != expectedSize.toULong()) { + if (this.tag != TAG || this.num_bytes_following != expectedSize.toLong()) { throw IllegalArgumentException("Given data does not look like a hashtree descriptor") } @@ -64,7 +64,7 @@ class HashTreeDescriptor( } override fun encode(): ByteArray { - this.num_bytes_following = (SIZE + this.partition_name.length + this.salt.size + this.root_digest.size - 16).toULong() + this.num_bytes_following = SIZE + this.partition_name.length + this.salt.size + this.root_digest.size - 16 val nbf_with_padding = Helper.round_to_multiple(this.num_bytes_following.toLong(), 8) val padding_size = nbf_with_padding - this.num_bytes_following.toLong() val desc = Struct3(FORMAT_STRING).pack( @@ -94,7 +94,7 @@ class HashTreeDescriptor( } companion object { - const val TAG: ULong = 1U + const val TAG: Long = 1L private const val RESERVED = 60L private const val SIZE = 120 + RESERVED private const val FORMAT_STRING = "!2QL3Q3L2Q32s4L${RESERVED}x" diff --git a/bbootimg/src/main/kotlin/avb/desc/KernelCmdlineDescriptor.kt b/bbootimg/src/main/kotlin/avb/desc/KernelCmdlineDescriptor.kt index 7b15b63..8ee79af 100644 --- a/bbootimg/src/main/kotlin/avb/desc/KernelCmdlineDescriptor.kt +++ b/bbootimg/src/main/kotlin/avb/desc/KernelCmdlineDescriptor.kt @@ -9,7 +9,7 @@ class KernelCmdlineDescriptor( var flags: UInt = 0U, var cmdlineLength: UInt = 0U, var cmdline: String = "") - : Descriptor(TAG, 0U, 0) { + : Descriptor(TAG, 0, 0) { var flagsInterpretation: String = "" get() { var ret = "" @@ -24,13 +24,13 @@ class KernelCmdlineDescriptor( @Throws(IllegalArgumentException::class) constructor(data: InputStream, seq: Int = 0) : this() { val info = Struct3(FORMAT_STRING).unpack(data) - this.tag = info[0] as ULong - this.num_bytes_following = info[1] as ULong + this.tag = (info[0] as ULong).toLong() + this.num_bytes_following = (info[1] as ULong).toLong() this.flags = info[2] as UInt this.cmdlineLength = info[3] as UInt this.sequence = seq val expectedSize = Helper.round_to_multiple(SIZE.toUInt() - 16U + this.cmdlineLength, 8U) - if ((this.tag != TAG) || (this.num_bytes_following != expectedSize.toULong())) { + if ((this.tag != TAG) || (this.num_bytes_following != expectedSize.toLong())) { throw IllegalArgumentException("Given data does not look like a kernel cmdline descriptor") } this.cmdline = Struct3("${this.cmdlineLength}s").unpack(data)[0] as String @@ -50,7 +50,7 @@ class KernelCmdlineDescriptor( } companion object { - const val TAG: ULong = 3U + const val TAG: Long = 3L const val SIZE = 24 const val FORMAT_STRING = "!2Q2L" //# tag, num_bytes_following (descriptor header), flags, cmdline length (bytes) //AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_NOT_DISABLED diff --git a/bbootimg/src/main/kotlin/avb/desc/PropertyDescriptor.kt b/bbootimg/src/main/kotlin/avb/desc/PropertyDescriptor.kt index 4bd8693..1b92b79 100644 --- a/bbootimg/src/main/kotlin/avb/desc/PropertyDescriptor.kt +++ b/bbootimg/src/main/kotlin/avb/desc/PropertyDescriptor.kt @@ -7,14 +7,14 @@ import java.io.InputStream @OptIn(ExperimentalUnsignedTypes::class) class PropertyDescriptor( var key: String = "", - var value: String = "") : Descriptor(TAG, 0U, 0) { + var value: String = "") : Descriptor(TAG, 0, 0) { override fun encode(): ByteArray { if (SIZE != Struct3(FORMAT_STRING).calcSize().toUInt()) { throw RuntimeException() } - this.num_bytes_following = (SIZE + this.key.length.toUInt() + this.value.length.toUInt() + 2U - 16U).toULong() + this.num_bytes_following = (SIZE + this.key.length.toUInt() + this.value.length.toUInt() + 2U - 16U).toLong() val nbfWithPadding = Helper.round_to_multiple(this.num_bytes_following.toLong(), 8).toULong() - val paddingSize = nbfWithPadding - num_bytes_following + val paddingSize = nbfWithPadding - num_bytes_following.toUInt() val padding = Struct3("${paddingSize}x").pack(0) val desc = Struct3(FORMAT_STRING).pack( TAG, @@ -29,12 +29,12 @@ class PropertyDescriptor( constructor(data: InputStream, seq: Int = 0) : this() { val info = Struct3(FORMAT_STRING).unpack(data) - this.tag = info[0] as ULong - this.num_bytes_following = info[1] as ULong + this.tag = (info[0] as ULong).toLong() + this.num_bytes_following = (info[1] as ULong).toLong() val keySize = (info[2] as ULong).toUInt() val valueSize = (info[3] as ULong).toUInt() val expectedSize = Helper.round_to_multiple(SIZE - 16U + keySize + 1U + valueSize + 1U, 8U) - if (this.tag != TAG || expectedSize.toULong() != this.num_bytes_following) { + if (this.tag != TAG || expectedSize.toLong() != this.num_bytes_following) { throw IllegalArgumentException("Given data does not look like a |property| descriptor") } this.sequence = seq @@ -45,7 +45,7 @@ class PropertyDescriptor( } companion object { - const val TAG: ULong = 0U + const val TAG: Long = 0L const val SIZE = 32U const val FORMAT_STRING = "!4Q" } diff --git a/bbootimg/src/main/kotlin/avb/desc/UnknownDescriptor.kt b/bbootimg/src/main/kotlin/avb/desc/UnknownDescriptor.kt index 1c14274..9d1af66 100644 --- a/bbootimg/src/main/kotlin/avb/desc/UnknownDescriptor.kt +++ b/bbootimg/src/main/kotlin/avb/desc/UnknownDescriptor.kt @@ -8,13 +8,13 @@ import java.io.ByteArrayInputStream import java.io.InputStream @OptIn(ExperimentalUnsignedTypes::class) -class UnknownDescriptor(var data: ByteArray = byteArrayOf()) : Descriptor(0U, 0U, 0) { +class UnknownDescriptor(var data: ByteArray = byteArrayOf()) : Descriptor(0, 0, 0) { @Throws(IllegalArgumentException::class) constructor(stream: InputStream, seq: Int = 0) : this() { this.sequence = seq val info = Struct3(FORMAT).unpack(stream) - this.tag = info[0] as ULong - this.num_bytes_following = info[1] as ULong + this.tag = (info[0] as ULong).toLong() + this.num_bytes_following = (info[1] as ULong).toLong() log.debug("UnknownDescriptor: tag = $tag, len = ${this.num_bytes_following}") this.data = ByteArray(this.num_bytes_following.toInt()) if (this.num_bytes_following.toInt() != stream.read(data)) { diff --git a/bbootimg/src/main/kotlin/bootimg/v2/BootHeaderV2.kt b/bbootimg/src/main/kotlin/bootimg/v2/BootHeaderV2.kt index e4b565e..7be9283 100644 --- a/bbootimg/src/main/kotlin/bootimg/v2/BootHeaderV2.kt +++ b/bbootimg/src/main/kotlin/bootimg/v2/BootHeaderV2.kt @@ -9,27 +9,27 @@ import kotlin.math.pow @OptIn(ExperimentalUnsignedTypes::class) open class BootHeaderV2( - var kernelLength: UInt = 0U, - var kernelOffset: UInt = 0U, + var kernelLength: Int = 0, + var kernelOffset: Long = 0L, //UInt - var ramdiskLength: UInt = 0U, - var ramdiskOffset: UInt = 0U, + var ramdiskLength: Int = 0, + var ramdiskOffset: Long = 0L, //UInt - var secondBootloaderLength: UInt = 0U, - var secondBootloaderOffset: UInt = 0U, + var secondBootloaderLength: Int = 0, + var secondBootloaderOffset: Long = 0L, //UInt - var recoveryDtboLength: UInt = 0U, - var recoveryDtboOffset: ULong = 0UL,//Q + var recoveryDtboLength: Int = 0, + var recoveryDtboOffset: Long = 0L,//Q - var dtbLength: UInt = 0U, - var dtbOffset: ULong = 0UL,//Q + var dtbLength: Int = 0, + var dtbOffset: Long = 0L,//Q - var tagsOffset: UInt = 0U, + var tagsOffset: Long = 0L, //UInt - var pageSize: UInt = 0U, + var pageSize: Int = 0, - var headerSize: UInt = 0U, - var headerVersion: UInt = 0U, + var headerSize: Int = 0, + var headerVersion: Int = 0, var board: String = "", @@ -50,15 +50,15 @@ open class BootHeaderV2( if (info[0] != magic) { throw IllegalArgumentException("stream doesn't look like Android Boot Image Header") } - this.kernelLength = info[1] as UInt - this.kernelOffset = info[2] as UInt - this.ramdiskLength = info[3] as UInt - this.ramdiskOffset = info[4] as UInt - this.secondBootloaderLength = info[5] as UInt - this.secondBootloaderOffset = info[6] as UInt - this.tagsOffset = info[7] as UInt - this.pageSize = info[8] as UInt - this.headerVersion = info[9] as UInt + this.kernelLength = (info[1] as UInt).toInt() + this.kernelOffset = (info[2] as UInt).toLong() + this.ramdiskLength = (info[3] as UInt).toInt() + this.ramdiskOffset = (info[4] as UInt).toLong() + this.secondBootloaderLength = (info[5] as UInt).toInt() + this.secondBootloaderOffset = (info[6] as UInt).toLong() + this.tagsOffset = (info[7] as UInt).toLong() + this.pageSize = (info[8] as UInt).toInt() + this.headerVersion = (info[9] as UInt).toInt() val osNPatch = info[10] as UInt if (0U != osNPatch) { //treated as 'reserved' in this boot image this.osVersion = Common.parseOsVersion(osNPatch.toInt() shr 11) @@ -68,25 +68,25 @@ open class BootHeaderV2( this.cmdline = (info[12] as String) + (info[14] as String) this.hash = info[13] as ByteArray - if (this.headerVersion > 0U) { - this.recoveryDtboLength = info[15] as UInt - this.recoveryDtboOffset = info[16] as ULong + if (this.headerVersion > 0) { + this.recoveryDtboLength = (info[15] as UInt).toInt() + this.recoveryDtboOffset = (info[16] as ULong).toLong() } - this.headerSize = info[17] as UInt + this.headerSize = (info[17] as UInt).toInt() assert(this.headerSize.toInt() in intArrayOf(BOOT_IMAGE_HEADER_V2_SIZE, BOOT_IMAGE_HEADER_V1_SIZE, BOOT_IMAGE_HEADER_V0_SIZE)) { "header size ${this.headerSize} illegal" } - if (this.headerVersion > 1U) { - this.dtbLength = info[18] as UInt - this.dtbOffset = info[19] as ULong + if (this.headerVersion > 1) { + this.dtbLength = (info[18] as UInt).toInt() + this.dtbOffset = (info[19] as ULong).toLong() } } - private fun get_recovery_dtbo_offset(): UInt { - return Helper.round_to_multiple(this.headerSize, pageSize) + + private fun get_recovery_dtbo_offset(): Long { + return Helper.round_to_multiple(this.headerSize.toLong(), pageSize) + Helper.round_to_multiple(this.kernelLength, pageSize) + Helper.round_to_multiple(this.ramdiskLength, pageSize) + Helper.round_to_multiple(this.secondBootloaderLength, pageSize) @@ -121,18 +121,18 @@ open class BootHeaderV2( //I recoveryDtboLength, //Q - if (headerVersion > 0U) recoveryDtboOffset else 0, + if (headerVersion > 0) recoveryDtboOffset else 0, //I when (headerVersion) { - 0U -> BOOT_IMAGE_HEADER_V0_SIZE - 1U -> BOOT_IMAGE_HEADER_V1_SIZE - 2U -> BOOT_IMAGE_HEADER_V2_SIZE + 0 -> BOOT_IMAGE_HEADER_V0_SIZE + 1 -> BOOT_IMAGE_HEADER_V1_SIZE + 2 -> BOOT_IMAGE_HEADER_V2_SIZE else -> java.lang.IllegalArgumentException("headerVersion $headerVersion illegal") }, //I dtbLength, //Q - if (headerVersion > 1U) dtbOffset else 0 + if (headerVersion > 1) dtbOffset else 0 ) } diff --git a/bbootimg/src/main/kotlin/bootimg/v2/BootV2.kt b/bbootimg/src/main/kotlin/bootimg/v2/BootV2.kt index e3eb12f..2ca0856 100644 --- a/bbootimg/src/main/kotlin/bootimg/v2/BootV2.kt +++ b/bbootimg/src/main/kotlin/bootimg/v2/BootV2.kt @@ -30,12 +30,12 @@ data class BootV2( data class MiscInfo( var output: String = "", var json: String = "", - var headerVersion: UInt = 0U, - var headerSize: UInt = 0U, - var loadBase: UInt = 0U, - var tagsOffset: UInt = 0U, + var headerVersion: Int = 0, + var headerSize: Int = 0, + var loadBase: Long = 0, + var tagsOffset: Long = 0, var board: String? = null, - var pageSize: UInt = 0U, + var pageSize: Int = 0, var cmdline: String = "", var osVersion: String? = null, var osPatchLevel: String? = null, @@ -45,15 +45,15 @@ data class BootV2( data class CommArgs( var file: String? = null, - var position: UInt = 0U, + var position: Long = 0, var size: Int = 0, - var loadOffset: UInt = 0U) + var loadOffset: Long = 0) data class CommArgsLong( var file: String? = null, - var position: UInt = 0U, - var size: UInt = 0U, - var loadOffset: ULong = 0U) + var position: Long = 0, + var size: Int = 0, + var loadOffset: Long = 0) companion object { private val log = LoggerFactory.getLogger(BootV2::class.java) @@ -93,25 +93,25 @@ data class BootV2( theRamdisk.size = bh2.ramdiskLength.toInt() theRamdisk.loadOffset = bh2.ramdiskOffset theRamdisk.position = ret.getRamdiskPosition() - if (bh2.ramdiskLength > 0U) { + if (bh2.ramdiskLength > 0) { theRamdisk.file = "${workDir}ramdisk.img.gz" } } - if (bh2.secondBootloaderLength > 0U) { + if (bh2.secondBootloaderLength > 0) { ret.secondBootloader = CommArgs() ret.secondBootloader!!.size = bh2.secondBootloaderLength.toInt() ret.secondBootloader!!.loadOffset = bh2.secondBootloaderOffset ret.secondBootloader!!.file = "${workDir}second" ret.secondBootloader!!.position = ret.getSecondBootloaderPosition() } - if (bh2.recoveryDtboLength > 0U) { + if (bh2.recoveryDtboLength > 0) { ret.recoveryDtbo = CommArgsLong() ret.recoveryDtbo!!.size = bh2.recoveryDtboLength ret.recoveryDtbo!!.loadOffset = bh2.recoveryDtboOffset //Q ret.recoveryDtbo!!.file = "${workDir}recoveryDtbo" - ret.recoveryDtbo!!.position = ret.getRecoveryDtboPosition().toUInt() + ret.recoveryDtbo!!.position = ret.getRecoveryDtboPosition() } - if (bh2.dtbLength > 0U) { + if (bh2.dtbLength > 0) { ret.dtb = CommArgsLong() ret.dtb!!.size = bh2.dtbLength ret.dtb!!.loadOffset = bh2.dtbOffset //Q @@ -123,35 +123,35 @@ data class BootV2( } } - private fun getHeaderSize(pageSize: UInt): UInt { - val pad = (pageSize - (1648U and (pageSize - 1U))) and (pageSize - 1U) - return pad + 1648U + private fun getHeaderSize(pageSize: Int): Int { + val pad = (pageSize - (1648 and (pageSize - 1))) and (pageSize - 1) + return pad + 1648 } - private fun getKernelPosition(): UInt { - return getHeaderSize(info.pageSize) + private fun getKernelPosition(): Long { + return getHeaderSize(info.pageSize).toLong() } - private fun getRamdiskPosition(): UInt { - return (getKernelPosition() + kernel.size.toUInt() + - Common.getPaddingSize(kernel.size.toUInt(), info.pageSize)) + private fun getRamdiskPosition(): Long { + return (getKernelPosition() + kernel.size + + Common.getPaddingSize(kernel.size, info.pageSize)) } - private fun getSecondBootloaderPosition(): UInt { - return getRamdiskPosition() + ramdisk.size.toUInt() + - Common.getPaddingSize(ramdisk.size.toUInt(), info.pageSize) + private fun getSecondBootloaderPosition(): Long { + return getRamdiskPosition() + ramdisk.size + + Common.getPaddingSize(ramdisk.size, info.pageSize) } - private fun getRecoveryDtboPosition(): UInt { + private fun getRecoveryDtboPosition(): Long { return if (this.secondBootloader == null) { getSecondBootloaderPosition() } else { - getSecondBootloaderPosition() + secondBootloader!!.size.toUInt() + - Common.getPaddingSize(secondBootloader!!.size.toUInt(), info.pageSize) + getSecondBootloaderPosition() + secondBootloader!!.size + + Common.getPaddingSize(secondBootloader!!.size, info.pageSize) } } - private fun getDtbPosition(): UInt { + private fun getDtbPosition(): Long { return if (this.recoveryDtbo == null) { getRecoveryDtboPosition() } else { @@ -244,14 +244,14 @@ data class BootV2( } //dtbo this.recoveryDtbo?.let { theDtbo -> - if (theDtbo.size > 0U) { + if (theDtbo.size > 0) { it.addRule() it.addRow("recovery dtbo", theDtbo.file) } } //dtb this.dtb?.let { theDtb -> - if (theDtb.size > 0u) { + if (theDtb.size > 0) { it.addRule() it.addRow("dtb", theDtb.file) if (File(theDtb.file + ".src").exists()) { @@ -280,16 +280,16 @@ data class BootV2( private fun toHeader(): BootHeaderV2 { return BootHeaderV2( - kernelLength = kernel.size.toUInt(), + kernelLength = kernel.size, kernelOffset = kernel.loadOffset, - ramdiskLength = ramdisk.size.toUInt(), + ramdiskLength = ramdisk.size, ramdiskOffset = ramdisk.loadOffset, - secondBootloaderLength = if (secondBootloader != null) secondBootloader!!.size.toUInt() else 0U, - secondBootloaderOffset = if (secondBootloader != null) secondBootloader!!.loadOffset else 0U, - recoveryDtboLength = if (recoveryDtbo != null) recoveryDtbo!!.size.toUInt() else 0U, - recoveryDtboOffset = if (recoveryDtbo != null) recoveryDtbo!!.loadOffset else 0U, - dtbLength = if (dtb != null) dtb!!.size else 0U, - dtbOffset = if (dtb != null) dtb!!.loadOffset else 0U, + secondBootloaderLength = if (secondBootloader != null) secondBootloader!!.size else 0, + secondBootloaderOffset = if (secondBootloader != null) secondBootloader!!.loadOffset else 0, + recoveryDtboLength = if (recoveryDtbo != null) recoveryDtbo!!.size else 0, + recoveryDtboOffset = if (recoveryDtbo != null) recoveryDtbo!!.loadOffset else 0, + dtbLength = if (dtb != null) dtb!!.size else 0, + dtbOffset = if (dtb != null) dtb!!.loadOffset else 0, tagsOffset = info.tagsOffset, pageSize = info.pageSize, headerSize = info.headerSize, @@ -318,7 +318,7 @@ data class BootV2( //refresh ramdisk size if (this.ramdisk.file.isNullOrBlank()) { ramdisk.file = null - ramdisk.loadOffset = 0U + ramdisk.loadOffset = 0 } else { if (File(this.ramdisk.file!!).exists() && !File(workDir + "root").exists()) { //do nothing if we have ramdisk.img.gz but no /root @@ -336,24 +336,24 @@ data class BootV2( } //refresh recovery dtbo size recoveryDtbo?.let { theDtbo -> - theDtbo.size = File(theDtbo.file!!).length().toUInt() - theDtbo.loadOffset = getRecoveryDtboPosition().toULong() + theDtbo.size = File(theDtbo.file!!).length().toInt() + theDtbo.loadOffset = getRecoveryDtboPosition() log.warn("using fake recoveryDtboOffset ${theDtbo.loadOffset} (as is in AOSP avbtool)") } //refresh dtb size dtb?.let { theDtb -> - theDtb.size = File(theDtb.file!!).length().toUInt() + theDtb.size = File(theDtb.file!!).length().toInt() } //refresh image hash info.hash = when (info.headerVersion) { - 0U -> { + 0 -> { Common.hashFileAndSize(kernel.file, ramdisk.file, secondBootloader?.file) } - 1U -> { + 1 -> { Common.hashFileAndSize(kernel.file, ramdisk.file, secondBootloader?.file, recoveryDtbo?.file) } - 2U -> { + 2 -> { Common.hashFileAndSize(kernel.file, ramdisk.file, secondBootloader?.file, recoveryDtbo?.file, dtb?.file) } @@ -367,7 +367,7 @@ data class BootV2( //write FileOutputStream("${info.output}.clear", false).use { fos -> fos.write(encodedHeader) - fos.write(ByteArray((Helper.round_to_multiple(encodedHeader.size.toUInt(), info.pageSize) - encodedHeader.size.toUInt()).toInt())) + fos.write(ByteArray((Helper.round_to_multiple(encodedHeader.size, info.pageSize) - encodedHeader.size))) } log.info("Writing data ...") @@ -431,13 +431,13 @@ data class BootV2( ret.addArgument(" --board ") ret.addArgument(info.board) } - if (info.headerVersion > 0U) { + if (info.headerVersion > 0) { if (recoveryDtbo != null) { ret.addArgument(" --recovery_dtbo ") ret.addArgument(recoveryDtbo!!.file!!) } } - if (info.headerVersion > 1U) { + if (info.headerVersion > 1) { if (dtb != null) { ret.addArgument("--dtb ") ret.addArgument(dtb!!.file!!) diff --git a/bbootimg/src/main/kotlin/bootimg/v3/BootHeaderV3.kt b/bbootimg/src/main/kotlin/bootimg/v3/BootHeaderV3.kt index a337f7a..aa007b3 100644 --- a/bbootimg/src/main/kotlin/bootimg/v3/BootHeaderV3.kt +++ b/bbootimg/src/main/kotlin/bootimg/v3/BootHeaderV3.kt @@ -7,12 +7,12 @@ import java.io.InputStream @OptIn(ExperimentalUnsignedTypes::class) class BootHeaderV3( - var kernelSize: UInt = 0U, - var ramdiskSize: UInt = 0U, + var kernelSize: Int = 0, + var ramdiskSize: Int = 0, var osVersion: String = "", var osPatchLevel: String = "", - var headerSize: UInt = 0U, - var headerVersion: UInt = 0U, + var headerSize: Int = 0, + var headerVersion: Int = 0, var cmdline: String = "" ) { @Throws(IllegalArgumentException::class) @@ -26,20 +26,20 @@ class BootHeaderV3( if (info[0] != magic) { throw IllegalArgumentException("stream doesn't look like Android Boot Image V3 Header") } - this.kernelSize = info[1] as UInt - this.ramdiskSize = info[2] as UInt + this.kernelSize = (info[1] as UInt).toInt() + this.ramdiskSize = (info[2] as UInt).toInt() val osNPatch = info[3] as UInt if (0U != osNPatch) { //treated as 'reserved' in this boot image this.osVersion = Common.parseOsVersion(osNPatch.toInt() shr 11) this.osPatchLevel = Common.parseOsPatchLevel((osNPatch and 0x7ff.toUInt()).toInt()) } - this.headerSize = info[4] as UInt + this.headerSize = (info[4] as UInt).toInt() //5,6,7,8 reserved - this.headerVersion = info[9] as UInt + this.headerVersion = (info[9] as UInt).toInt() this.cmdline = info[10] as String - assert(this.headerSize.toInt() in intArrayOf(BOOT_IMAGE_HEADER_V3_SIZE)) + assert(this.headerSize in intArrayOf(BOOT_IMAGE_HEADER_V3_SIZE)) } fun encode(): ByteArray { @@ -70,7 +70,7 @@ class BootHeaderV3( "I" + //header version "1536s" //cmdline private const val BOOT_IMAGE_HEADER_V3_SIZE = 1580 - val pageSize: UInt = 4096U + const val pageSize: Int = 4096 init { assert(BOOT_IMAGE_HEADER_V3_SIZE == Struct3(FORMAT_STRING).calcSize()) { diff --git a/bbootimg/src/main/kotlin/bootimg/v3/BootV3.kt b/bbootimg/src/main/kotlin/bootimg/v3/BootV3.kt index 43fd6d7..f7ddc8b 100644 --- a/bbootimg/src/main/kotlin/bootimg/v3/BootV3.kt +++ b/bbootimg/src/main/kotlin/bootimg/v3/BootV3.kt @@ -42,13 +42,13 @@ data class BootV3(var info: MiscInfo = MiscInfo(), ret.info.pageSize = BootHeaderV3.pageSize //kernel ret.kernel.file = workDir + "kernel" - ret.kernel.size = header.kernelSize.toInt() - ret.kernel.position = BootHeaderV3.pageSize.toInt() + ret.kernel.size = header.kernelSize + ret.kernel.position = BootHeaderV3.pageSize //ramdisk ret.ramdisk.file = workDir + "ramdisk.img.gz" - ret.ramdisk.size = header.ramdiskSize.toInt() - ret.ramdisk.position = ret.kernel.position + header.kernelSize.toInt() + - getPaddingSize(header.kernelSize, BootHeaderV3.pageSize).toInt() + ret.ramdisk.size = header.ramdiskSize + ret.ramdisk.position = ret.kernel.position + header.kernelSize + + getPaddingSize(header.kernelSize, BootHeaderV3.pageSize) } ret.info.imageSize = File(fileName).length() return ret @@ -58,9 +58,9 @@ data class BootV3(var info: MiscInfo = MiscInfo(), data class MiscInfo( var output: String = "", var json: String = "", - var headerVersion: UInt = 0U, - var headerSize: UInt = 0U, - var pageSize: UInt = 0U, + var headerVersion: Int = 0, + var headerSize: Int = 0, + var pageSize: Int = 0, var cmdline: String = "", var osVersion: String = "", var osPatchLevel: String = "", @@ -97,10 +97,9 @@ data class BootV3(var info: MiscInfo = MiscInfo(), FileOutputStream(this.info.output + ".clear", false).use { fos -> val encodedHeader = this.toHeader().encode() fos.write(encodedHeader) - fos.write(ByteArray(( - Helper.round_to_multiple(encodedHeader.size.toUInt(), - this.info.pageSize) - encodedHeader.size.toUInt()).toInt() - )) + fos.write(ByteArray( + Helper.round_to_multiple(encodedHeader.size, + this.info.pageSize) - encodedHeader.size)) } //data @@ -131,8 +130,8 @@ data class BootV3(var info: MiscInfo = MiscInfo(), private fun toHeader(): BootHeaderV3 { return BootHeaderV3( - kernelSize = kernel.size.toUInt(), - ramdiskSize = ramdisk.size.toUInt(), + kernelSize = kernel.size, + ramdiskSize = ramdisk.size, headerVersion = info.headerVersion, osVersion = info.osVersion, osPatchLevel = info.osPatchLevel, diff --git a/bbootimg/src/main/kotlin/bootimg/v3/VendorBoot.kt b/bbootimg/src/main/kotlin/bootimg/v3/VendorBoot.kt index bb3678f..a512d12 100644 --- a/bbootimg/src/main/kotlin/bootimg/v3/VendorBoot.kt +++ b/bbootimg/src/main/kotlin/bootimg/v3/VendorBoot.kt @@ -23,20 +23,20 @@ data class VendorBoot(var info: MiscInfo = MiscInfo(), var dtb: CommArgs = CommArgs()) { data class CommArgs( var file: String = "", - var position: UInt = 0U, - var size: UInt = 0U, - var loadAddr: UInt = 0U) + var position: Long = 0, + var size: Int = 0, + var loadAddr: Long = 0) data class MiscInfo( var output: String = "", var json: String = "", - var headerVersion: UInt = 0U, + var headerVersion: Int = 0, var product: String = "", - var headerSize: UInt = 0U, - var pageSize: UInt = 0U, + var headerSize: Int = 0, + var pageSize: Int = 0, var cmdline: String = "", - var tagsLoadAddr: UInt = 0U, - var kernelLoadAddr: UInt = 0U, + var tagsLoadAddr: Long = 0, + var kernelLoadAddr: Long = 0, var imageSize: Long = 0 ) @@ -61,12 +61,12 @@ data class VendorBoot(var info: MiscInfo = MiscInfo(), ret.ramdisk.size = header.vndRamdiskSize ret.ramdisk.loadAddr = header.ramdiskLoadAddr ret.ramdisk.position = Helper.round_to_multiple( - VendorBootHeader.VENDOR_BOOT_IMAGE_HEADER_V3_SIZE, + VendorBootHeader.VENDOR_BOOT_IMAGE_HEADER_V3_SIZE.toLong(), header.pageSize) //dtb ret.dtb.file = workDir + "dtb" ret.dtb.size = header.dtbSize - ret.dtb.loadAddr = header.dtbLoadAddr.toUInt() + ret.dtb.loadAddr = header.dtbLoadAddr ret.dtb.position = ret.ramdisk.position + Helper.round_to_multiple(ret.ramdisk.size, header.pageSize) } @@ -89,16 +89,15 @@ data class VendorBoot(var info: MiscInfo = MiscInfo(), File(this.ramdisk.file.removeSuffix(".gz")).deleleIfExists() C.packRootfs("$workDir/root", this.ramdisk.file, parseOsMajor()) } - this.ramdisk.size = File(this.ramdisk.file).length().toUInt() - this.dtb.size = File(this.dtb.file).length().toUInt() + this.ramdisk.size = File(this.ramdisk.file).length().toInt() + this.dtb.size = File(this.dtb.file).length().toInt() //header FileOutputStream(this.info.output + ".clear", false).use { fos -> val encodedHeader = this.toHeader().encode() fos.write(encodedHeader) - fos.write(ByteArray(( - Helper.round_to_multiple(encodedHeader.size.toUInt(), - this.info.pageSize) - encodedHeader.size.toUInt()).toInt() - )) + fos.write(ByteArray( + Helper.round_to_multiple(encodedHeader.size, + this.info.pageSize) - encodedHeader.size)) } //data log.info("Writing data ...") @@ -138,7 +137,7 @@ data class VendorBoot(var info: MiscInfo = MiscInfo(), product = info.product, headerSize = info.headerSize, dtbSize = dtb.size, - dtbLoadAddr = dtb.loadAddr.toULong() + dtbLoadAddr = dtb.loadAddr ) } diff --git a/bbootimg/src/main/kotlin/bootimg/v3/VendorBootHeader.kt b/bbootimg/src/main/kotlin/bootimg/v3/VendorBootHeader.kt index bb3c53e..bc4e741 100644 --- a/bbootimg/src/main/kotlin/bootimg/v3/VendorBootHeader.kt +++ b/bbootimg/src/main/kotlin/bootimg/v3/VendorBootHeader.kt @@ -6,17 +6,17 @@ import java.io.InputStream @OptIn(ExperimentalUnsignedTypes::class) class VendorBootHeader( - var headerVersion: UInt = 0U, - var pageSize: UInt = 0U, - var kernelLoadAddr: UInt = 0U, - var ramdiskLoadAddr: UInt = 0U, - var vndRamdiskSize: UInt = 0U, + var headerVersion: Int = 0, + var pageSize: Int = 0, + var kernelLoadAddr: Long = 0, + var ramdiskLoadAddr: Long = 0, + var vndRamdiskSize: Int = 0, var cmdline: String = "", - var tagsLoadAddr: UInt = 0U, + var tagsLoadAddr: Long = 0, var product: String = "", - var headerSize: UInt = 0U, - var dtbSize: UInt = 0U, - var dtbLoadAddr: ULong = 0U + var headerSize: Int = 0, + var dtbSize: Int = 0, + var dtbLoadAddr: Long = 0 ) { @Throws(IllegalArgumentException::class) constructor(iS: InputStream?) : this() { @@ -29,20 +29,24 @@ class VendorBootHeader( if (info[0] != magic) { throw IllegalArgumentException("stream doesn't look like Android Vendor Boot Image") } - this.headerVersion = info[1] as UInt - this.pageSize = info[2] as UInt - this.kernelLoadAddr = info[3] as UInt - this.ramdiskLoadAddr = info[4] as UInt - this.vndRamdiskSize = info[5] as UInt + this.headerVersion = (info[1] as UInt).toInt() + this.pageSize = (info[2] as UInt).toInt() + this.kernelLoadAddr = (info[3] as UInt).toLong() + this.ramdiskLoadAddr = (info[4] as UInt).toLong() + this.vndRamdiskSize = (info[5] as UInt).toInt() this.cmdline = info[6] as String - this.tagsLoadAddr = info[7] as UInt + this.tagsLoadAddr = (info[7] as UInt).toLong() this.product = info[8] as String - this.headerSize = info[9] as UInt - this.dtbSize = info[10] as UInt - this.dtbLoadAddr = info[11] as ULong + this.headerSize = (info[9] as UInt).toInt() + this.dtbSize = (info[10] as UInt).toInt() + this.dtbLoadAddr = (info[11] as ULong).toLong() - assert(this.headerSize in arrayOf(VENDOR_BOOT_IMAGE_HEADER_V3_SIZE)) - assert(this.headerVersion == 3U) + if (this.headerSize !in arrayOf(VENDOR_BOOT_IMAGE_HEADER_V3_SIZE)) { + throw IllegalArgumentException("header size " + this.headerSize + " invalid") + } + if (this.headerVersion != 3) { + throw IllegalArgumentException("header version " + this.headerVersion + " invalid") + } } fun encode(): ByteArray { @@ -64,7 +68,7 @@ class VendorBootHeader( companion object { private val log = LoggerFactory.getLogger(VendorBootHeader::class.java) const val magic = "VNDRBOOT" - const val VENDOR_BOOT_IMAGE_HEADER_V3_SIZE = 2112U + const val VENDOR_BOOT_IMAGE_HEADER_V3_SIZE = 2112 const val FORMAT_STRING = "8s" + //magic "I" + //header version "I" + //page size @@ -78,7 +82,7 @@ class VendorBootHeader( "I" + //dtb size "Q" //dtb physical load addr init { - assert(Struct3(FORMAT_STRING).calcSize().toUInt() == VENDOR_BOOT_IMAGE_HEADER_V3_SIZE) + assert(Struct3(FORMAT_STRING).calcSize() == VENDOR_BOOT_IMAGE_HEADER_V3_SIZE) } } diff --git a/bbootimg/src/main/kotlin/bootloader_message/BootControl.kt b/bbootimg/src/main/kotlin/bootloader_message/BootControl.kt new file mode 100644 index 0000000..9b9d0e1 --- /dev/null +++ b/bbootimg/src/main/kotlin/bootloader_message/BootControl.kt @@ -0,0 +1,23 @@ +package cfig.bootloader_message + +class BootControl { + data class SlotMetadata(//size: 16 + var priority: Int = 0, + var triesRemaining: Int = 0, + var successfulBoot: Boolean = false, + var verityCorrupted: Boolean = false, + var reserved: ByteArray = byteArrayOf() + ) + + class BootloaderControl( + var slotSuffix: String = "", + var magic: ByteArray = byteArrayOf(), + var version: Int = 0, + var slots: Int = 0, + var recoveryTriesRemaining: Int = 0, + var mergeStatus: Int = 0, + var slotMetaData: ByteArray= byteArrayOf(), + var reserved: ByteArray = byteArrayOf(), + var crc32: Int = 0 + ) +} diff --git a/bbootimg/src/main/kotlin/bootloader_message/BootloaderMsg.kt b/bbootimg/src/main/kotlin/bootloader_message/BootloaderMsg.kt index 545eba2..0d65dd8 100644 --- a/bbootimg/src/main/kotlin/bootloader_message/BootloaderMsg.kt +++ b/bbootimg/src/main/kotlin/bootloader_message/BootloaderMsg.kt @@ -8,7 +8,7 @@ import java.io.FileOutputStream import java.lang.IllegalStateException @OptIn(ExperimentalUnsignedTypes::class) -data class BootloaderMsg( +data class BootloaderMsg(//offset 0, size 2k var command: String = "", var status: String = "", var recovery: String = "", diff --git a/bbootimg/src/main/kotlin/bootloader_message/BootloaderMsgAB.kt b/bbootimg/src/main/kotlin/bootloader_message/BootloaderMsgAB.kt new file mode 100644 index 0000000..b176bff --- /dev/null +++ b/bbootimg/src/main/kotlin/bootloader_message/BootloaderMsgAB.kt @@ -0,0 +1,36 @@ +package cfig.bootloader_message + +import cfig.io.Struct3 +import org.slf4j.LoggerFactory +import java.io.FileInputStream + +@OptIn(ExperimentalUnsignedTypes::class) +class BootloaderMsgAB( //offset 2k, size 2k + var slotSuffix: String = "", + var updateChannel: String = "", + var reserved: ByteArray = byteArrayOf() +) { + companion object { + private const val FORMAT_STRING = "32s128s1888b" + const val SIZE = 2048 + private val log = LoggerFactory.getLogger(BootloaderMsgAB::class.java.simpleName) + + init { + assert(SIZE == Struct3(FORMAT_STRING).calcSize()) + } + } + + constructor(fis: FileInputStream) : this() { + val info = Struct3(FORMAT_STRING).unpack(fis) + this.slotSuffix = info[0] as String + this.updateChannel = info[1] as String + this.reserved = info[2] as ByteArray + } + + fun encode(): ByteArray { + return Struct3(FORMAT_STRING).pack( + this.slotSuffix, + this.updateChannel, + byteArrayOf()) + } +} diff --git a/bbootimg/src/main/kotlin/bootloader_message/VirtualABMsg.kt b/bbootimg/src/main/kotlin/bootloader_message/VirtualABMsg.kt new file mode 100644 index 0000000..6e739af --- /dev/null +++ b/bbootimg/src/main/kotlin/bootloader_message/VirtualABMsg.kt @@ -0,0 +1,42 @@ +package cfig.bootloader_message + +import cfig.io.Struct3 +import org.slf4j.LoggerFactory +import java.io.FileInputStream + +@OptIn(ExperimentalUnsignedTypes::class) +data class VirtualABMsg( + var version: Int = 0, + var magic: ByteArray = byteArrayOf(), + var mergeStatus: Int = 0, + var sourceSlot: Int = 0, + var reserved: ByteArray = byteArrayOf() +) { + companion object { + private const val FORMAT_STRING = "b4bbb57b" + const val SIZE = 64 + private val log = LoggerFactory.getLogger("VirtualABMsg") + + init { + assert(SIZE == Struct3(FORMAT_STRING).calcSize()) + } + } + + constructor(fis: FileInputStream) : this() { + val info = Struct3(FORMAT_STRING).unpack(fis) + this.version = info[0] as Int + this.magic = info[1] as ByteArray + this.mergeStatus = info[2] as Int + this.sourceSlot = info[3] as Int + this.reserved = info[4] as ByteArray + } + + fun encode(): ByteArray { + return Struct3(FORMAT_STRING).pack( + this.version, + this.magic, + this.mergeStatus, + this.sourceSlot, + 0) + } +}