routine mass checkin

- VirtualABMsg: read and parse VAB info from misc
- Clear some detekt warnings
- dtbo: supress warnings
pull/80/head
cfig 4 years ago
parent 62bc8004c4
commit 1e2592c1c4
No known key found for this signature in database
GPG Key ID: B104C307F0FDABB7

1
.gitignore vendored

@ -1,5 +1,4 @@
.idea
.gradle
build/
boot.img*
local.properties

@ -10,7 +10,7 @@ A tool for reverse engineering Android ROM images.
Mac: `brew install lz4 xz dtc`
Linux: `sudo apt install git device-tree-compiler lz4 xz-utils zlib1g-dev openjdk-11-jdk gcc g++ python3`
Linux: `sudo apt install git device-tree-compiler lz4 xz-utils zlib1g-dev openjdk-11-jdk gcc g++ python3 python-is-python3`
Windows Subsystem for Linux(WSL): `sudo apt install git device-tree-compiler lz4 xz-utils zlib1g-dev openjdk-11-jdk gcc g++ python`

@ -15,7 +15,7 @@
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
kotlin("jvm") version "1.5.30"
kotlin("jvm") version "1.5.31"
application
}
@ -56,7 +56,10 @@ application {
}
tasks.withType<KotlinCompile>().all {
kotlinOptions.freeCompilerArgs += "-Xopt-in=kotlin.RequiresOptIn"
kotlinOptions {
freeCompilerArgs += "-Xopt-in=kotlin.RequiresOptIn"
jvmTarget = "11"
}
}
tasks {

@ -88,122 +88,94 @@ class AVBInfo(
private val log = LoggerFactory.getLogger(AVBInfo::class.java)
private val mapper = ObjectMapper()
fun parseFrom(imageFile: String): AVBInfo {
log.info("parseFrom($imageFile) ...")
var footer: Footer? = null
var vbMetaOffset: Long = 0
private data class Glance(
var footer: Footer?,
var vbMetaOffset: Long
)
private fun imageGlance(imageFile: String): Glance {
val ret = Glance(null, 0)
// footer
FileInputStream(imageFile).use { fis ->
fis.skip(File(imageFile).length() - Footer.SIZE)
try {
footer = Footer(fis)
vbMetaOffset = footer!!.vbMetaOffset
log.info("$imageFile: $footer")
ret.footer = Footer(fis)
ret.vbMetaOffset = ret.footer!!.vbMetaOffset
log.info("$imageFile: $ret.footer")
} catch (e: IllegalArgumentException) {
log.info("image $imageFile has no AVB Footer")
}
}
// header
val rawHeaderBlob = ByteArray(Header.SIZE).apply {
FileInputStream(imageFile).use { fis ->
fis.skip(vbMetaOffset)
fis.read(this)
}
return ret
}
val vbMetaHeader = Header(ByteArrayInputStream(rawHeaderBlob))
log.debug(vbMetaHeader.toString())
fun parseFrom(imageFile: String): AVBInfo {
log.info("parseFrom($imageFile) ...")
// glance
val (footer, vbMetaOffset) = imageGlance(imageFile)
// header
val vbMetaHeader = Header(ByteArrayInputStream(Helper.readFully(imageFile, vbMetaOffset, Header.SIZE)))
log.debug(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(vbMetaHeader))
val authBlockOffset = vbMetaOffset + Header.SIZE
val auxBlockOffset = authBlockOffset + vbMetaHeader.authentication_data_block_size
val atlas = mutableMapOf<String, Pair<Long, Int>>()
atlas["auth"] =
Pair(vbMetaOffset + Header.SIZE, vbMetaHeader.authentication_data_block_size.toInt())
atlas["auth.hash"] =
Pair(atlas["auth"]!!.first + vbMetaHeader.hash_offset, vbMetaHeader.hash_size.toInt())
atlas["auth.sig"] =
Pair(atlas["auth.hash"]!!.first + atlas["auth.hash"]!!.second, vbMetaHeader.signature_size.toInt())
atlas["aux"] =
Pair(atlas["auth"]!!.first + atlas["auth"]!!.second, vbMetaHeader.auxiliary_data_block_size.toInt())
val ai = AVBInfo(vbMetaHeader, null, AuxBlob(), footer)
// Auth blob
if (vbMetaHeader.authentication_data_block_size > 0) {
FileInputStream(imageFile).use { fis ->
fis.skip(vbMetaOffset)
fis.skip(Header.SIZE.toLong())
fis.skip(vbMetaHeader.hash_offset)
val ba = ByteArray(vbMetaHeader.hash_size.toInt())
fis.read(ba)
val ba = Helper.readFully(imageFile, atlas["auth.hash"]!!)
log.debug("Parsed Auth Hash (Header & Aux Blob): " + Hex.encodeHexString(ba))
val bb = ByteArray(vbMetaHeader.signature_size.toInt())
fis.read(bb)
val bb = Helper.readFully(imageFile, atlas["auth.sig"]!!)
log.debug("Parsed Auth Signature (of hash): " + Hex.encodeHexString(bb))
ai.authBlob = AuthBlob()
ai.authBlob!!.offset = authBlockOffset
ai.authBlob!!.size = vbMetaHeader.authentication_data_block_size
ai.authBlob!!.offset = atlas["auth"]!!.first
ai.authBlob!!.size = atlas["auth"]!!.second.toLong()
ai.authBlob!!.hash = Hex.encodeHexString(ba)
ai.authBlob!!.signature = Hex.encodeHexString(bb)
}
}
// aux
val rawAuxBlob = ByteArray(vbMetaHeader.auxiliary_data_block_size.toInt()).apply {
FileInputStream(imageFile).use { fis ->
fis.skip(auxBlockOffset)
fis.read(this)
}
}
val rawAuxBlob = Helper.readFully(imageFile, atlas["aux"]!!)
// aux - desc
var descriptors: List<Any>
if (vbMetaHeader.descriptors_size > 0) {
ByteArrayInputStream(rawAuxBlob).use { bis ->
bis.skip(vbMetaHeader.descriptors_offset)
descriptors = UnknownDescriptor.parseDescriptors2(bis, vbMetaHeader.descriptors_size)
}
descriptors.forEach {
log.debug(it.toString())
when (it) {
is PropertyDescriptor -> {
ai.auxBlob!!.propertyDescriptors.add(it)
}
is HashDescriptor -> {
ai.auxBlob!!.hashDescriptors.add(it)
}
is KernelCmdlineDescriptor -> {
ai.auxBlob!!.kernelCmdlineDescriptors.add(it)
}
is HashTreeDescriptor -> {
ai.auxBlob!!.hashTreeDescriptors.add(it)
}
is ChainPartitionDescriptor -> {
ai.auxBlob!!.chainPartitionDescriptors.add(it)
}
is UnknownDescriptor -> {
ai.auxBlob!!.unknownDescriptors.add(it)
}
else -> {
throw IllegalArgumentException("invalid descriptor: $it")
}
}
}
val descriptors = UnknownDescriptor.parseDescriptors2(
ByteArrayInputStream(
rawAuxBlob.copyOfRange(vbMetaHeader.descriptors_offset.toInt(), rawAuxBlob.size)
),
vbMetaHeader.descriptors_size
)
ai.auxBlob!!.populateDescriptors(descriptors)
} else {
log.warn("no descriptors in AVB aux blob")
}
// aux - pubkey
if (vbMetaHeader.public_key_size > 0) {
ai.auxBlob!!.pubkey = AuxBlob.PubKeyInfo()
ai.auxBlob!!.pubkey!!.offset = vbMetaHeader.public_key_offset
ai.auxBlob!!.pubkey!!.size = vbMetaHeader.public_key_size
ByteArrayInputStream(rawAuxBlob).use { bis ->
bis.skip(vbMetaHeader.public_key_offset)
ai.auxBlob!!.pubkey!!.pubkey = ByteArray(vbMetaHeader.public_key_size.toInt())
bis.read(ai.auxBlob!!.pubkey!!.pubkey)
ai.auxBlob!!.pubkey!!.pubkey = rawAuxBlob.copyOfRange(
vbMetaHeader.public_key_offset.toInt(),
(vbMetaHeader.public_key_offset + vbMetaHeader.public_key_size).toInt()
)
log.debug("Parsed Pub Key: " + Hex.encodeHexString(ai.auxBlob!!.pubkey!!.pubkey))
}
}
// aux - pkmd
if (vbMetaHeader.public_key_metadata_size > 0) {
ai.auxBlob!!.pubkeyMeta = AuxBlob.PubKeyMetadataInfo()
ai.auxBlob!!.pubkeyMeta!!.offset = vbMetaHeader.public_key_metadata_offset
ai.auxBlob!!.pubkeyMeta!!.size = vbMetaHeader.public_key_metadata_size
ByteArrayInputStream(rawAuxBlob).use { bis ->
bis.skip(vbMetaHeader.public_key_metadata_offset)
ai.auxBlob!!.pubkeyMeta!!.pkmd = ByteArray(vbMetaHeader.public_key_metadata_size.toInt())
bis.read(ai.auxBlob!!.pubkeyMeta!!.pkmd)
ai.auxBlob!!.pubkeyMeta!!.pkmd = rawAuxBlob.copyOfRange(
vbMetaHeader.public_key_metadata_offset.toInt(),
(vbMetaHeader.public_key_metadata_offset + vbMetaHeader.public_key_metadata_size).toInt()
)
log.debug("Parsed Pub Key Metadata: " + Helper.toHexString(ai.auxBlob!!.pubkeyMeta!!.pkmd))
}
}
log.debug("vbmeta info of [$imageFile] has been analyzed")
return ai
}

@ -14,6 +14,7 @@
package avb.blob
import avb.AVBInfo
import avb.alg.Algorithm
import avb.desc.*
import cfig.helper.Helper
@ -101,6 +102,36 @@ class AuxBlob(
return Struct3("${auxSize}b").pack(Helper.join(encodedDesc, encodedKey, encodedPkmd))
}
fun populateDescriptors(descriptors: List<Descriptor>): AuxBlob {
descriptors.forEach {
log.debug(it.toString())
when (it) {
is PropertyDescriptor -> {
this.propertyDescriptors.add(it)
}
is HashDescriptor -> {
this.hashDescriptors.add(it)
}
is KernelCmdlineDescriptor -> {
this.kernelCmdlineDescriptors.add(it)
}
is HashTreeDescriptor -> {
this.hashTreeDescriptors.add(it)
}
is ChainPartitionDescriptor -> {
this.chainPartitionDescriptors.add(it)
}
is UnknownDescriptor -> {
this.unknownDescriptors.add(it)
}
else -> {
throw IllegalArgumentException("invalid descriptor: $it")
}
}
}
return this
}
companion object {
fun encodePubKey(alg: Algorithm, key: ByteArray? = null): ByteArray {
var encodedKey = byteArrayOf()

@ -58,7 +58,7 @@ class ChainPartitionDescriptor(
constructor(data: InputStream, seq: Int = 0) : this() {
if (SIZE - RESERVED != Struct3(FORMAT_STRING).calcSize().toLong()) {
throw RuntimeException()
throw RuntimeException("ChainPartitionDescriptor size check failed")
}
this.sequence = seq
val info = Struct3(FORMAT_STRING + "${RESERVED}s").unpack(data)

@ -245,7 +245,7 @@ class HashTreeDescriptor(
var hashOffset: Long = 0
) {
override fun toString(): String {
return String.format(
return String.format(Locale.getDefault(),
"MT{data: %10s(%6s blocks), hash: %7s @%-5s}",
dataSize,
dataBlockCount,

@ -23,7 +23,7 @@ class PropertyDescriptor(
var value: String = "") : Descriptor(TAG, 0, 0) {
override fun encode(): ByteArray {
if (SIZE != Struct3(FORMAT_STRING).calcSize().toUInt()) {
throw RuntimeException()
throw RuntimeException("PropertyDesc size check failed")
}
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()

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package cfig.bootloader_message
package cfig.bcb
class BootControl {
data class SlotMetadata(//size: 16

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package cfig.bootloader_message
package cfig.bcb
import cfig.io.Struct3
import org.slf4j.LoggerFactory

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package cfig.bootloader_message
package cfig.bcb
import cfig.io.Struct3
import org.slf4j.LoggerFactory

@ -12,8 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package cfig.bootloader_message
package cfig.bcb
import cfig.helper.Helper
import cfig.io.Struct3
import org.slf4j.LoggerFactory
import java.io.FileInputStream
@ -29,6 +30,7 @@ data class VirtualABMsg(
private const val FORMAT_STRING = "b4bbb57b"
const val SIZE = 64
private val log = LoggerFactory.getLogger("VirtualABMsg")
private const val MAGIC = "b00a7456"
init {
assert(SIZE == Struct3(FORMAT_STRING).calcSize())
@ -37,11 +39,14 @@ data class VirtualABMsg(
constructor(fis: FileInputStream) : this() {
val info = Struct3(FORMAT_STRING).unpack(fis)
this.version = info[0] as Int
this.version = (info[0] as ByteArray)[0].toInt()
this.magic = info[1] as ByteArray
this.mergeStatus = info[2] as Int
this.sourceSlot = info[3] as Int
this.mergeStatus = (info[2] as ByteArray)[0].toInt()
this.sourceSlot = (info[3] as ByteArray)[0].toInt()
this.reserved = info[4] as ByteArray
if (MAGIC != Helper.Companion.toHexString(this.magic)) {
throw IllegalArgumentException("stream is not VirtualAB message")
}
}
fun encode(): ByteArray {
@ -50,6 +55,20 @@ data class VirtualABMsg(
this.magic,
this.mergeStatus,
this.sourceSlot,
0)
0
)
}
override fun toString(): String {
return "VABMsg(v=$version, magic=${Helper.toHexString(magic)}, mergeStatus=$mergeStatus:${MergeStatus.values().get(this.mergeStatus)}, sourceSlot=$sourceSlot)"
}
enum class MergeStatus(val status: Int) {
NONE(0),
UNKNOWN(1),
SNAPSHOTTED(2),
MERGING(3),
CANCELLED(4)
}
}

@ -14,13 +14,13 @@
package cfig.bootimg
import cfig.EnvironmentVerifier
import cfig.utils.EnvironmentVerifier
import cfig.bootimg.cpio.AndroidCpio
import cfig.dtb_util.DTC
import cfig.utils.DTC
import cfig.helper.Helper
import cfig.helper.ZipHelper
import cfig.io.Struct3.InputStreamExt.Companion.getInt
import cfig.kernel_util.KernelExtractor
import cfig.utils.KernelExtractor
import org.apache.commons.exec.CommandLine
import org.apache.commons.exec.DefaultExecutor
import org.apache.commons.exec.PumpStreamHandler
@ -35,6 +35,7 @@ import java.lang.NumberFormatException
import java.nio.ByteBuffer
import java.nio.ByteOrder
import java.security.MessageDigest
import java.util.*
import java.util.regex.Pattern
class Common {
@ -78,7 +79,7 @@ class Common {
val a = x shr 14
val b = x - (a shl 14) shr 7
val c = x and 0x7f
return String.format("%d.%d.%d", a, b, c)
return String.format(Locale.getDefault(), "%d.%d.%d", a, b, c)
}
fun packOsPatchLevel(x: String?): Int {
@ -234,7 +235,7 @@ class Common {
//using mkbootfs
fun packRootfs(rootDir: String, ramdiskGz: String, osMajor: Int = 10) {
val mkbootfs = String.format(Helper.prop("mkbootfsBin"), osMajor)
val mkbootfs = String.format(Locale.getDefault(), Helper.prop("mkbootfsBin"), osMajor)
log.info("Packing rootfs $rootDir ...")
val outputStream = ByteArrayOutputStream()
DefaultExecutor().let { exec ->

@ -24,7 +24,7 @@ import org.apache.commons.exec.CommandLine
import org.apache.commons.exec.DefaultExecutor
import org.slf4j.LoggerFactory
import java.io.File
import cfig.EnvironmentVerifier
import cfig.utils.EnvironmentVerifier
class Signer {
companion object {

@ -15,16 +15,16 @@
package cfig.bootimg.cpio
import cfig.helper.Helper
import cfig.EnvironmentVerifier
import cfig.utils.EnvironmentVerifier
import com.fasterxml.jackson.core.JsonParser
import com.fasterxml.jackson.databind.ObjectMapper
import org.apache.commons.compress.archivers.cpio.CpioArchiveInputStream
import org.apache.commons.compress.archivers.cpio.CpioConstants
import org.slf4j.LoggerFactory
import java.io.*
import java.nio.charset.Charset
import java.nio.file.Files
import java.nio.file.Paths
import java.util.*
import java.util.regex.Pattern
class AndroidCpio {
@ -213,7 +213,7 @@ class AndroidCpio {
name = entry.name,
statMode = entry.mode,
ino = entry.inode,
note = String.format("%6s", java.lang.Long.toOctalString(entry.mode))
note = String.format(Locale.getDefault(), "%6s", java.lang.Long.toOctalString(entry.mode))
)
if (!cis.canReadEntryData(entry)) {
throw RuntimeException("can not read entry ??")
@ -224,7 +224,7 @@ class AndroidCpio {
if (((entry.mode and PERM_MASK).shr(7)).toInt() != 0b11) {
//@formatter:off
log.warn(" root/${entry.name} has improper file mode "
+ String.format("%03o, ", entry.mode and PERM_MASK) + "fix it"
+ String.format(Locale.getDefault(), "%03o, ", entry.mode and PERM_MASK) + "fix it"
)
//@formatter:on
}

@ -16,6 +16,7 @@ package cfig.bootimg.cpio
import cfig.io.Struct3
import org.apache.commons.compress.archivers.cpio.CpioConstants
import java.util.*
/*
cpio "New ASCII Format" with 070701 as magic
@ -38,26 +39,26 @@ class NewAsciiCpio(
) {
init {
if (SIZE != Struct3(FORMAT_STRING).calcSize()) {
throw RuntimeException()
throw RuntimeException("cpio format check failed")
}
}
fun encode(): ByteArray {
return Struct3(FORMAT_STRING).pack(
String.format("%s", c_magic),
String.format("%08x", c_ino),
String.format("%08x", c_mode),
String.format("%08x", c_uid),
String.format("%08x", c_gid),
String.format("%08x", c_nlink),
String.format("%08x", c_mtime),
String.format("%08x", c_filesize),
String.format("%08x", c_devmajor),
String.format("%08x", c_devminor),
String.format("%08x", c_rdevmajor),
String.format("%08x", c_rdevminor),
String.format("%08x", c_namesize),
String.format("%08x", c_check),
String.format(Locale.getDefault(), "%s", c_magic),
String.format(Locale.getDefault(), "%08x", c_ino),
String.format(Locale.getDefault(), "%08x", c_mode),
String.format(Locale.getDefault(),"%08x", c_uid),
String.format(Locale.getDefault(),"%08x", c_gid),
String.format(Locale.getDefault(),"%08x", c_nlink),
String.format(Locale.getDefault(),"%08x", c_mtime),
String.format(Locale.getDefault(),"%08x", c_filesize),
String.format(Locale.getDefault(),"%08x", c_devmajor),
String.format(Locale.getDefault(),"%08x", c_devminor),
String.format(Locale.getDefault(),"%08x", c_rdevmajor),
String.format(Locale.getDefault(),"%08x", c_rdevminor),
String.format(Locale.getDefault(),"%08x", c_namesize),
String.format(Locale.getDefault(),"%08x", c_check),
)
}

@ -16,7 +16,7 @@ package cfig.bootimg.v2
import avb.AVBInfo
import cfig.Avb
import cfig.EnvironmentVerifier
import cfig.utils.EnvironmentVerifier
import cfig.bootimg.Common
import cfig.bootimg.Common.Companion.deleleIfExists
import cfig.bootimg.Signer

@ -18,7 +18,7 @@ import avb.AVBInfo
import avb.alg.Algorithms
import avb.blob.AuxBlob
import cfig.Avb
import cfig.EnvironmentVerifier
import cfig.utils.EnvironmentVerifier
import cfig.bootimg.Common.Companion.deleleIfExists
import cfig.bootimg.Common.Companion.getPaddingSize
import cfig.bootimg.Signer

@ -16,7 +16,7 @@ package cfig.bootimg.v3
import avb.AVBInfo
import cfig.Avb
import cfig.EnvironmentVerifier
import cfig.utils.EnvironmentVerifier
import cfig.bootimg.Common.Companion.deleleIfExists
import cfig.bootimg.Signer
import cfig.helper.Helper
@ -73,7 +73,7 @@ data class VendorBoot(
PLATFORM.ordinal -> PLATFORM
RECOVERY.ordinal -> RECOVERY
DLKM.ordinal -> DLKM
else -> throw IllegalArgumentException()
else -> throw IllegalArgumentException("illegal VrtType $value")
}
}
}

@ -14,7 +14,7 @@
package cfig.init
import cfig.bootloader_message.BootloaderMsg
import cfig.bcb.BootloaderMsg
import org.slf4j.LoggerFactory
import java.util.*

@ -26,7 +26,7 @@ import org.slf4j.LoggerFactory
import java.io.File
import java.io.FileInputStream
class BootImgParser() : IPackable {
class BootImgParser : IPackable {
override val loopNo: Int
get() = 0
private val workDir = Helper.prop("workDir")

@ -15,10 +15,9 @@
package cfig.packable
import avb.blob.Footer
import cfig.EnvironmentVerifier
import cfig.dtb_util.DTC
import cfig.utils.EnvironmentVerifier
import cfig.utils.DTC
import cfig.helper.Helper
import cfig.Avb
import com.fasterxml.jackson.databind.ObjectMapper
import org.apache.commons.exec.CommandLine
import org.apache.commons.exec.DefaultExecutor
@ -46,7 +45,8 @@ class DtboParser(val workDir: File) : IPackable {
cleanUp()
val dtbPath = File("$outDir/dtb").path
val headerPath = File("$outDir/dtbo.header").path
val cmd = CommandLine.parse("$dtboMaker dump $fileName").let {
val cmdPrefix = if (EnvironmentVerifier().isWindows) "python " else ""
val cmd = CommandLine.parse("$cmdPrefix$dtboMaker dump $fileName").let {
it.addArguments("--dtb $dtbPath")
it.addArguments("--output $headerPath")
}

@ -14,7 +14,7 @@
package cfig.packable
import cfig.sparse_util.SparseImgParser
import cfig.utils.SparseImgParser
import org.slf4j.LoggerFactory
import java.io.File
import java.util.regex.Pattern

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package cfig.dtb_util
package cfig.utils
import org.apache.commons.exec.CommandLine
import org.apache.commons.exec.DefaultExecutor
@ -23,7 +23,7 @@ class DTC {
fun decompile(dtbFile: String, outFile: String): Boolean {
log.info("parsing DTB: $dtbFile")
val cmd = CommandLine.parse("dtc -I dtb -O dts").let {
val cmd = CommandLine.parse("dtc -q -I dtb -O dts").let {
it.addArguments("$dtbFile")
it.addArguments("-o $outFile")
}
@ -46,7 +46,7 @@ class DTC {
fun compile(dtsFile: String, outFile: String): Boolean {
log.info("compiling DTS: $dtsFile")
val cmd = CommandLine.parse("dtc -I dts -O dtb").let {
val cmd = CommandLine.parse("dtc -q -I dts -O dtb").let {
it.addArguments("$dtsFile")
it.addArguments("-o $outFile")
}

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package cfig
package cfig.utils
import org.apache.commons.exec.CommandLine
import org.apache.commons.exec.DefaultExecutor

@ -12,9 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package cfig.kernel_util
package cfig.utils
import cfig.EnvironmentVerifier
import cfig.helper.Helper
import org.apache.commons.exec.CommandLine
import org.apache.commons.exec.DefaultExecutor

@ -12,9 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package cfig.sparse_util
package cfig.utils
import cfig.EnvironmentVerifier
import cfig.packable.IPackable
import org.slf4j.LoggerFactory
import cfig.helper.Helper.Companion.check_call
@ -22,7 +21,6 @@ import java.io.FileInputStream
import java.io.File
import com.fasterxml.jackson.databind.ObjectMapper
import avb.blob.Footer
import cfig.Avb
class SparseImgParser : IPackable {
override val loopNo: Int

@ -12,12 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import cfig.EnvironmentVerifier
import cfig.utils.EnvironmentVerifier
import org.junit.Test
import org.junit.Assert.*
import org.junit.Before
class EnvironmentVerifierTest {
private val envv = EnvironmentVerifier()

@ -278,16 +278,20 @@ class ReadTest {
fun String.executeCmd(inServices: MutableList<Service>,
inTriggers: List<Trigger>, inIndent: String) {
val aPre = inIndent + " "
val aPre = "$inIndent "
if (this.startsWith("trigger ")) {
println(aPre + "|-- " + this)
println("$aPre|-- $this")
queueEventTrigger(inServices, inTriggers, this.substring(8).trim(), aPre + "| ")
} else if (this.startsWith("chmod")) {
//ignore
} else if (this.startsWith("chown")) {
//ignore
} else if (this.startsWith("mkdir")) {
//ignore
} else if (this.startsWith("write")) {
//ignore
} else if (Pattern.compile("class_start\\s+\\S+").matcher(this).find()) {
println(aPre + "|-- " + this)
println("$aPre|-- $this")
val m = Pattern.compile("class_start\\s+(\\S+)$").matcher(this)
if (m.find()) {
inServices
@ -304,15 +308,15 @@ class ReadTest {
println("$aPre|-- $this")
println("""$aPre| \-- Starting ${this.substring(5).trim()}...""")
} else {
println(aPre + "|-- " + this)
println("$aPre|-- $this")
}
}
@Test
fun parseTest() {
System.out.println(System.getProperty("user.dir"))
var gTriggers: MutableList<Trigger> = mutableListOf()
var gServices: MutableList<Service> = mutableListOf()
val gTriggers: MutableList<Trigger> = mutableListOf()
val gServices: MutableList<Service> = mutableListOf()
parseConfig("__temp/", "/init.rc", gTriggers, gServices)
parseConfig("__temp/", "/system/etc/init", gTriggers, gServices)

@ -44,6 +44,7 @@ class FooterTest {
Footer(it)
assertEquals("Should never reach here", true, false)
} catch (e: IllegalArgumentException) {
//expected
}
}
}

@ -1,27 +0,0 @@
// Copyright 2021 yuyezhong@gmail.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package avb.alg
import org.junit.Test
import org.junit.Assert.*
import java.nio.ByteBuffer
class AlgorithmTest {
@Test
fun getName() {
}
}

@ -21,10 +21,10 @@ import org.junit.Test
class AlgorithmsTest {
@Test
fun test1() {
val alg = Algorithms.get("NONE")!!
Assert.assertEquals(Helper.toHexString(Algorithms.get("SHA256_RSA4096")!!.padding),
"0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003031300d060960864801650304020105000420")
println(alg)
Assert.assertEquals(
Helper.toHexString(Algorithms.get("SHA256_RSA4096")!!.padding),
"0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003031300d060960864801650304020105000420"
)
println(Algorithms.get("NONE")!!)
}
}

@ -12,10 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package bootloader_message
package bcb
import cfig.bcb.BootloaderMsg
import cfig.bootimg.Common.Companion.deleleIfExists
import cfig.bootloader_message.BootloaderMsg
import org.junit.After
import org.junit.Test
import org.slf4j.LoggerFactory

@ -0,0 +1,37 @@
package bcb
import cfig.bcb.VirtualABMsg
import cfig.bootimg.Common.Companion.deleleIfExists
import cfig.helper.Helper.Companion.check_call
import org.junit.After
import org.junit.Before
import org.junit.Ignore
import org.junit.Test
import org.slf4j.LoggerFactory
import java.io.File
import java.io.FileInputStream
class VirtualABMsgTest {
private val log = LoggerFactory.getLogger(VirtualABMsgTest::class.java)
@Before
fun setUp() {
"adb root".check_call()
"adb wait-for-device".check_call()
"adb shell dd if=/dev/block/by-name/misc of=/data/vendor/debug.misc skip=512 bs=64 count=1".check_call()
"adb pull /data/vendor/debug.misc".check_call()
}
@Test
@Ignore
fun parseVAB() {
val vab = VirtualABMsg(FileInputStream("debug.misc"))
log.info("VAB msg: $vab")
}
@After
fun tearDown() {
File("debug.misc").deleleIfExists()
}
}

@ -14,11 +14,11 @@
package init
import cfig.bcb.BootloaderMsg
import org.junit.Test
import org.junit.After
import java.io.File
import java.util.*
import cfig.bootloader_message.BootloaderMsg
import cfig.init.Reboot
import cfig.bootimg.Common.Companion.deleleIfExists
import org.slf4j.LoggerFactory

@ -15,7 +15,7 @@
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
id("org.jetbrains.kotlin.jvm") version "1.5.30"
id("org.jetbrains.kotlin.jvm") version "1.5.31"
`java-library`
}
@ -49,5 +49,5 @@ dependencies {
tasks.withType<KotlinCompile>().all {
kotlinOptions.freeCompilerArgs += "-Xopt-in=kotlin.RequiresOptIn"
kotlinOptions.jvmTarget = "1.8"
kotlinOptions.jvmTarget = "11"
}

@ -369,6 +369,20 @@ class Helper {
return String.format("%.1f %ciB", value / 1024.0, ci.current())
}
fun readFully(fileName: String, offset: Long, byteCount: Int): ByteArray {
val data = ByteArray(byteCount).apply {
FileInputStream(fileName).use { fis ->
fis.skip(offset)
fis.read(this)
}
}
return data
}
fun readFully(fileName: String, coordinate: Pair<Long, Int>): ByteArray {
return readFully(fileName, coordinate.first, coordinate.second)
}
private val log = LoggerFactory.getLogger("Helper")
}
}

@ -19,6 +19,7 @@ import org.junit.Assert
import org.junit.Test
import java.io.ByteArrayInputStream
@OptIn(kotlin.ExperimentalUnsignedTypes::class)
class Struct3Test {
private fun getConvertedFormats(inStruct: Struct3): ArrayList<Map<String, Int>> {
val f = inStruct.javaClass.getDeclaredField("formats")

Loading…
Cancel
Save