kotlin: upgrade to 1.4.0

travis: upgrade to Ubuntu 20.04 Focal
for/win
cfig 5 years ago
parent 2665fd0098
commit a39b870033
No known key found for this signature in database
GPG Key ID: B104C307F0FDABB7

@ -1,4 +1,4 @@
dist: bionic
dist: focal
language: java
before_install:
- sudo apt -qq update

@ -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")

@ -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

@ -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

@ -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<Any> = 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 {

@ -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 {

@ -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 {

@ -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)
}

@ -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)

@ -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
}

@ -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"

@ -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"

@ -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

@ -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"
}

@ -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)) {

@ -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
)
}

@ -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!!)

@ -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()) {

@ -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,

@ -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
)
}

@ -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)
}
}

@ -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
)
}

@ -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 = "",

@ -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())
}
}

@ -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)
}
}
Loading…
Cancel
Save