Issue #84: support misc.img

Actions:
  unpack
  pack
  pull
  flash
Signed-off-by: cfig <yuyezhong@gmail.com>
pull/94/head
cfig 3 years ago
parent 54be7a4fae
commit f716e34d6d
No known key found for this signature in database
GPG Key ID: B104C307F0FDABB7

@ -15,7 +15,7 @@
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
kotlin("jvm") version "1.6.10"
kotlin("jvm") version "1.6.20"
application
}
@ -59,8 +59,8 @@ application {
tasks.withType<KotlinCompile>().all {
kotlinOptions {
freeCompilerArgs += "-Xopt-in=kotlin.RequiresOptIn"
freeCompilerArgs += "-Xopt-in=kotlin.ExperimentalUnsignedTypes"
freeCompilerArgs += "-opt-in=kotlin.RequiresOptIn"
freeCompilerArgs += "-opt-in=kotlin.ExperimentalUnsignedTypes"
jvmTarget = "11"
}
}

@ -1,135 +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 cfig.bcb
import cc.cfig.io.Struct
import org.slf4j.LoggerFactory
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.lang.IllegalStateException
data class BootloaderMsg(//offset 0, size 2k
var command: String = "",
var status: String = "",
var recovery: String = "",
var stage: String = "",
var reserved: ByteArray = byteArrayOf()
) {
companion object {
private const val FORMAT_STRING = "32s32s768s32s1184b"
const val miscFile = "misc.file"
const val SIZE = 2048
private val log = LoggerFactory.getLogger("BootloaderMsg")
init {
assert(SIZE == Struct(FORMAT_STRING).calcSize())
}
}
constructor(fis: FileInputStream) : this() {
val info = Struct(FORMAT_STRING).unpack(fis)
this.command = info[0] as String
this.status = info[1] as String
this.recovery = info[2] as String
this.stage = info[3] as String
this.reserved = info[4] as ByteArray
}
fun encode(): ByteArray {
return Struct(FORMAT_STRING).pack(
this.command,
this.stage,
this.recovery,
this.stage,
byteArrayOf())
}
fun clearBootloaderMessage() {
val boot = BootloaderMsg()
boot.writeBootloaderMessage()
}
fun writeBootloaderMessage(options: Array<String>) {
this.updateBootloaderMessageInStruct(options)
this.writeBootloaderMessage()
}
fun readBootloaderMsg() {
if (File(miscFile).exists()) {
log.info("readBootloaderMsg() from $miscFile")
val fis = FileInputStream(miscFile)
val info = Struct(FORMAT_STRING).unpack(fis)
this.command = info[0] as String
this.status = info[1] as String
this.recovery = info[2] as String
this.stage = info[3] as String
this.reserved = info[4] as ByteArray
fis.close()
} else {
log.info("$miscFile missing")
}
}
fun writeRebootBootloader() {
if (this.command.isNotBlank()) {
throw IllegalStateException("Bootloader command pending.")
}
this.command = "bootonce-bootloader"
writeBootloaderMessage()
}
fun writeBootloaderMessage() {
log.info("writing ... $this")
if (!File(miscFile).exists()) {
File(miscFile).createNewFile()
}
FileOutputStream(miscFile, false).use { fos ->
fos.write(this.encode())
}
}
fun updateBootloaderMessageInStruct(options: Array<String>) {
this.command = "boot-recovery"
this.recovery = "recovery\n"
options.forEach {
this.recovery += if (it.endsWith("\n")) {
it
} else {
it + "\n"
}
}
}
fun updateBootloaderMessage(command: String, recovery: String, options: Array<String>?) {
this.command = command
this.recovery = "$recovery\n"
options?.forEach {
this.recovery += if (it.endsWith("\n")) {
it
} else {
it + "\n"
}
}
}
/*
https://android-review.googlesource.com/c/platform/bootable/recovery/+/735984
*/
fun updateBootFastboot() {
this.command = "boot-fastboot"
this.recovery = ""
}
}

@ -1,49 +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 cfig.bcb
import cc.cfig.io.Struct
import org.slf4j.LoggerFactory
import java.io.FileInputStream
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 == Struct(FORMAT_STRING).calcSize())
}
}
constructor(fis: FileInputStream) : this() {
val info = Struct(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 Struct(FORMAT_STRING).pack(
this.slotSuffix,
this.updateChannel,
byteArrayOf())
}
}

@ -1,74 +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 cfig.bcb
import cc.cfig.io.Struct
import cfig.helper.Helper
import org.slf4j.LoggerFactory
import java.io.FileInputStream
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")
private const val MAGIC = "b00a7456"
init {
assert(SIZE == Struct(FORMAT_STRING).calcSize())
}
}
constructor(fis: FileInputStream) : this() {
val info = Struct(FORMAT_STRING).unpack(fis)
this.version = (info[0] as ByteArray)[0].toInt()
this.magic = info[1] as ByteArray
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 {
return Struct(FORMAT_STRING).pack(
this.version,
this.magic,
this.mergeStatus,
this.sourceSlot,
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,7 +14,7 @@
package cfig.init
import cfig.bcb.BootloaderMsg
import miscimg.MiscImage
import org.slf4j.LoggerFactory
import java.util.*
@ -87,23 +87,28 @@ class Reboot {
}
when (rebootTarget) {
"fastboot" -> {
val bcb: MiscImage.BootloaderMessage
if (bDynamicPartition == null || bDynamicPartition == false) {
log.warn("$dynamicPartitionKey=false, using 'bootloader fastboot' instead of 'fastbootd'")
rebootTarget = "bootloader"
BootloaderMsg().writeRebootBootloader()
bcb = MiscImage.BootloaderMessage.rebootBootloader()
log.info(bcb.toString())
} else {
log.info("$dynamicPartitionKey=true, using fastbootd")
BootloaderMsg().writeBootloaderMessage(arrayOf("--fastboot"))
bcb = MiscImage.BootloaderMessage.rebootFastboot2()
rebootTarget = "recovery"
}
log.info(bcb.toString())
}
"bootloader" -> {
BootloaderMsg().writeRebootBootloader()
val bcb = MiscImage.BootloaderMessage.rebootBootloader()
log.info(bcb.toString())
}
"sideload", "sideload-auto-reboot" -> {
BootloaderMsg().writeBootloaderMessage(
arrayOf("--" + rebootTarget.replace("-", "_"))
)
val bcb = MiscImage.BootloaderMessage().apply {
updateBootloaderMessageInStruct(arrayOf("--" + rebootTarget.replace("-", "_")))
}
log.info(bcb.toString())
rebootTarget = "recovery"
}
else -> {

@ -0,0 +1,231 @@
package miscimg
import cc.cfig.io.Struct
import cfig.helper.Helper
import com.fasterxml.jackson.databind.ObjectMapper
import org.slf4j.LoggerFactory
import java.io.FileInputStream
data class MiscImage(
var bcb: BootloaderMessage = BootloaderMessage(),
var virtualAB: VirtualABMessage? = null
) {
companion object {
private val log = LoggerFactory.getLogger(MiscImage::class.java)
private val mapper = ObjectMapper()
private val workDir = Helper.prop("workDir")
fun parse(fileName: String): MiscImage {
val ret = MiscImage()
FileInputStream(fileName).use { fis ->
ret.bcb = BootloaderMessage(fis)
}
FileInputStream(fileName).use { fis ->
fis.skip(32 * 1024)
try {
ret.virtualAB = VirtualABMessage(fis)
} catch (e: IllegalArgumentException) {
log.info(e.toString())
}
}
return ret
}
}
//offset 0, size 2k
data class BootloaderMessage(
var command: String = "",
var status: String = "",
var recovery: String = "",
var stage: String = "",
var reserved: ByteArray = byteArrayOf()
) {
constructor(fis: FileInputStream) : this() {
val info = Struct(FORMAT_STRING).unpack(fis)
this.command = info[0] as String
this.status = info[1] as String
this.recovery = info[2] as String
this.stage = info[3] as String
//this.reserved = info[4] as ByteArray
}
fun encode(): ByteArray {
return Struct(FORMAT_STRING).pack(
this.command,
this.stage,
this.recovery,
this.stage,
byteArrayOf()
)
}
fun updateBootloaderMessageInStruct(options: Array<String>) {
this.command = "boot-recovery"
this.recovery = "recovery\n"
options.forEach {
this.recovery += if (it.endsWith("\n")) {
it
} else {
it + "\n"
}
}
}
fun updateBootloaderMessage(command: String, recovery: String, options: Array<String>?) {
this.command = command
this.recovery = "$recovery\n"
options?.forEach {
this.recovery += if (it.endsWith("\n")) {
it
} else {
it + "\n"
}
}
}
companion object {
private const val FORMAT_STRING = "32s32s768s32s1184b"
private val log = LoggerFactory.getLogger(BootloaderMessage::class.java)
const val SIZE = 2048
init {
assert(SIZE == Struct(FORMAT_STRING).calcSize())
}
/*
https://android-review.googlesource.com/c/platform/bootable/recovery/+/735984
*/
fun rebootFastboot1(): BootloaderMessage {
return BootloaderMessage().apply {
command = "boot-fastboot"
}
}
fun rebootFastboot2(): BootloaderMessage {
return BootloaderMessage().apply {
updateBootloaderMessageInStruct(arrayOf("--fastboot"))
}
}
fun rebootBootloader(): BootloaderMessage {
return BootloaderMessage().apply {
command = "bootonce-bootloader"
}
}
fun rebootRecovery(): BootloaderMessage {
return BootloaderMessage().apply {
this.updateBootloaderMessageInStruct(arrayOf())
}
}
fun rebootCrash(): BootloaderMessage {
return BootloaderMessage().apply {
//@formatter:off
updateBootloaderMessageInStruct(arrayOf(
"--prompt_and_wipe_data",
"--reason=RescueParty",
"--locale=en_US"))
//@formatter:on
}
}
fun rebootOTA(): BootloaderMessage {
return BootloaderMessage().apply {
updateBootloaderMessageInStruct(arrayOf("--update_package=/cache/update.zip", "--security"))
}
}
fun rebootWipeData(): BootloaderMessage {
return BootloaderMessage().apply {
//@formatter:off
updateBootloaderMessageInStruct(arrayOf(
"--wipe_data",
"--reason=convert_fbe",
"--locale=en_US"))
//@formatter:on
}
}
fun rebootWipeAb(): BootloaderMessage {
return BootloaderMessage().apply {
//@formatter:off
updateBootloaderMessageInStruct(arrayOf(
"--wipe_ab",
"--wipe_package_size=1024",
"--locale=en_US"))
//@formatter:on
}
}
fun generateSamples(): MutableList<BootloaderMessage> {
return mutableListOf(
rebootFastboot1(),
rebootFastboot2(),
rebootBootloader(),
rebootRecovery(),
rebootCrash(),
rebootOTA(),
rebootWipeData(),
rebootWipeAb()
)
}
}
}
//offset 32KB, size 64B
data class VirtualABMessage(
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"
private val log = LoggerFactory.getLogger("VirtualABMsg")
private const val MAGIC = "b00a7456"
const val SIZE = 64
init {
assert(SIZE == Struct(FORMAT_STRING).calcSize())
}
}
constructor(fis: FileInputStream) : this() {
val info = Struct(FORMAT_STRING).unpack(fis)
this.version = (info[0] as ByteArray)[0].toInt()
this.magic = info[1] as ByteArray
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 {
return Struct(FORMAT_STRING).pack(
byteArrayOf(this.version.toByte()),
this.magic,
byteArrayOf(this.mergeStatus.toByte()),
byteArrayOf(this.sourceSlot.toByte()),
byteArrayOf(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)
}
}
}

@ -38,7 +38,7 @@ interface IPackable {
"adb root".check_call()
val abUpdateProp = "adb shell getprop ro.build.ab_update".check_output()
log.info("ro.build.ab_update=$abUpdateProp")
val slotSuffix = if (abUpdateProp == "true") {
val slotSuffix = if (abUpdateProp == "true" && !fileName.startsWith("misc.img")) {
"adb shell getprop ro.boot.slot_suffix".check_output()
} else {
""
@ -53,7 +53,7 @@ interface IPackable {
"adb root".check_call()
val abUpdateProp = "adb shell getprop ro.build.ab_update".check_output()
log.info("ro.build.ab_update=$abUpdateProp")
val slotSuffix = if (abUpdateProp == "true") {
val slotSuffix = if (abUpdateProp == "true" && !fileName.startsWith("misc.img")) {
"adb shell getprop ro.boot.slot_suffix".check_output()
} else {
""

@ -0,0 +1,87 @@
// Copyright 2022 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 cfig.packable
import cc.cfig.io.Struct
import miscimg.MiscImage
import cfig.helper.Helper.Companion.deleteIfExists
import com.fasterxml.jackson.databind.ObjectMapper
import org.slf4j.LoggerFactory
import java.io.File
import java.io.FileOutputStream
import java.io.RandomAccessFile
class MiscImgParser : IPackable {
override val loopNo: Int
get() = 0
override fun capabilities(): List<String> {
return listOf("^misc\\.img$")
}
override fun unpack(fileName: String) {
cleanUp()
val misc = MiscImage.parse(fileName)
log.info(misc.toString())
ObjectMapper().writerWithDefaultPrettyPrinter()
.writeValue(File(File(fileName).name.removeSuffix(".img") + ".json"), misc)
ObjectMapper().writerWithDefaultPrettyPrinter().writeValue(
File("sample.json"),
MiscImage.BootloaderMessage.generateSamples()
)
}
override fun pack(fileName: String) {
val misc = ObjectMapper().readValue(
File(File(fileName).name.removeSuffix(".img") + ".json"),
MiscImage::class.java
)
val out = File("$fileName.new")
File(fileName).copyTo(out, true)
RandomAccessFile(out.name, "rw").use { raf ->
raf.write(misc.bcb.encode())
raf.seek(32 * 1024)
if (misc.virtualAB != null) {
raf.write(misc.virtualAB!!.encode())
}
}
log.info("${out.name} is ready")
}
override fun flash(fileName: String, deviceName: String) {
val stem = fileName.substring(0, fileName.indexOf("."))
super.flash("$fileName.new", stem)
}
override fun `@verify`(fileName: String) {
super.`@verify`(fileName)
}
override fun pull(fileName: String, deviceName: String) {
super.pull(fileName, deviceName)
}
fun clean(fileName: String) {
super.cleanUp()
listOf("", ".clear", ".google", ".clear", ".signed", ".signed2").forEach {
"$fileName$it".deleteIfExists()
}
VBMetaParser().clean("vbmeta.img")
}
companion object {
private val log = LoggerFactory.getLogger(MiscImgParser::class.java)
}
}

@ -28,7 +28,10 @@ class PackableLauncher
fun main(args: Array<String>) {
val log = LoggerFactory.getLogger(PackableLauncher::class.java)
val packablePool = mutableMapOf<List<String>, KClass<IPackable>>()
listOf(DtboParser(), VBMetaParser(), BootImgParser(), SparseImgParser(), VendorBootParser(), PayloadBinParser()).forEach {
listOf(
DtboParser(), VBMetaParser(), BootImgParser(), SparseImgParser(), VendorBootParser(), PayloadBinParser(),
MiscImgParser()
).forEach {
@Suppress("UNCHECKED_CAST")
packablePool.put(it.capabilities(), it::class as KClass<IPackable>)
}
@ -41,17 +44,17 @@ fun main(args: Array<String>) {
for (currentLoopNo in 0..1) { //currently we have only 2 loops
File(".").listFiles()!!.forEach { file ->
packablePool
.filter { it.value.createInstance().loopNo == currentLoopNo }
.forEach { p ->
for (item in p.key) {
if (Pattern.compile(item).matcher(file.name).matches()) {
log.debug("Found: " + file.name + ", " + item)
targetFile = file.name
targetHandler = p.value
return@found
}
.filter { it.value.createInstance().loopNo == currentLoopNo }
.forEach { p ->
for (item in p.key) {
if (Pattern.compile(item).matcher(file.name).matches()) {
log.debug("Found: " + file.name + ", " + item)
targetFile = file.name
targetHandler = p.value
return@found
}
}
}
}//end-of-file-traversing
}//end-of-range-loop
}//end-of-found@
@ -105,7 +108,7 @@ fun main(args: Array<String>) {
functions[0].call(it.createInstance(), targetFile!!)
}
3 -> {
if (args.size != 2 ) {
if (args.size != 2) {
log.info("invoke: ${it.qualifiedName}, $targetFile, " + targetFile!!.removeSuffix(".img"))
functions[0].call(it.createInstance(), targetFile!!, targetFile!!.removeSuffix(".img"))
} else {

@ -1,94 +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 bcb
import cfig.bcb.BootloaderMsg
import cfig.bootimg.Common.Companion.deleleIfExists
import org.junit.After
import org.junit.Test
import org.slf4j.LoggerFactory
import java.io.File
class BootloaderMsgTest {
private val log = LoggerFactory.getLogger(BootloaderMsgTest::class.java)
@After
fun tearDown() {
File(BootloaderMsg.miscFile).deleleIfExists()
}
@Test
fun writeRebootBootloaderTest() {
val msg = BootloaderMsg()
msg.clearBootloaderMessage()
}
@Test
fun readBootloaderMsgTest() {
val msg = BootloaderMsg()
msg.readBootloaderMsg()
log.info(msg.toString())
}
@Test
fun writeOptions() {
val msg = BootloaderMsg()
msg.updateBootloaderMessageInStruct(arrayOf(
"--prompt_and_wipe_data",
"--locale=zh_CN"))
msg.writeBootloaderMessage()
}
@Test
fun rebootRecovery() {
val msg = BootloaderMsg()
msg.updateBootloaderMessageInStruct(arrayOf())
msg.writeBootloaderMessage()
}
@Test
fun rebootCrash() {
val msg = BootloaderMsg()
msg.writeBootloaderMessage(arrayOf(
"--prompt_and_wipe_data",
"--reason=RescueParty",
"--locale=en_US"))
}
@Test
fun rebootOTA() {
val msg = BootloaderMsg()
msg.writeBootloaderMessage(arrayOf("--update_package=/cache/update.zip", "--security"))
}
@Test
fun rebootWipeAb() {
val msg = BootloaderMsg()
msg.writeBootloaderMessage(arrayOf(
"--wipe_ab",
"--wipe_package_size=1024",
"--locale=en_US"))
}
@Test
fun rebootWipeData() {
val msg = BootloaderMsg()
msg.writeBootloaderMessage(arrayOf(
"--wipe_data",
"--reason=convert_fbe",
"--locale=en_US"))
}
}

@ -1,46 +0,0 @@
package bcb
import cfig.bcb.VirtualABMsg
import cfig.bootimg.Common.Companion.deleleIfExists
import cfig.helper.Helper
import cfig.helper.Helper.Companion.check_call
import org.apache.commons.exec.CommandLine
import org.junit.*
import org.slf4j.LoggerFactory
import java.io.File
import java.io.FileInputStream
import java.io.IOException
class VirtualABMsgTest {
private val log = LoggerFactory.getLogger(VirtualABMsgTest::class.java)
@Before
fun setUp() {
Assume.assumeTrue(
try {
"adb --version".check_call()
true
} catch (e: IOException) {
false
}
)
Assume.assumeTrue(Helper.powerRun3(CommandLine.parse("adb root"), null)[0] as Boolean)
"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
fun parseVAB() {
FileInputStream("debug.misc").use {
val vab = VirtualABMsg(it)
log.info("VAB msg: $vab")
}
}
@After
fun tearDown() {
File("debug.misc").deleleIfExists()
}
}

@ -14,13 +14,11 @@
package init
import cfig.bcb.BootloaderMsg
import miscimg.MiscImage
import org.junit.Test
import org.junit.After
import java.io.File
import java.util.*
import cfig.init.Reboot
import cfig.bootimg.Common.Companion.deleleIfExists
import org.slf4j.LoggerFactory
class RebootTest {
@ -28,7 +26,6 @@ class RebootTest {
@After
fun tearDown() {
File(BootloaderMsg.miscFile).deleleIfExists()
}
@Test
@ -86,10 +83,8 @@ class RebootTest {
put(Reboot.dynamicPartitionKey, "true")
})
log.info("fastbootd test 2")
BootloaderMsg().let {
it.updateBootloaderMessage("boot-fastboot", "recovery", null)
it.writeBootloaderMessage()
}
val bcb = MiscImage.BootloaderMessage(command = "boot-fastboot", recovery = "recovery")
log.info(bcb.toString())
log.info("fastbootd test 3: not supported, change to bootloader")
Reboot.handlePowerctlMessage("reboot,fastboot", Properties())
}
@ -103,10 +98,8 @@ class RebootTest {
@Test
fun recovery_rescue() {
log.info("recovery test 1: rescue")
BootloaderMsg().let {
it.updateBootloaderMessage("boot-rescue", "recovery", null)
it.writeBootloaderMessage()
}
val bcb = MiscImage.BootloaderMessage(command = "boot-rescue", recovery = "recovery")
log.info(bcb.toString())
log.info("recovery test 2: rescue")
Reboot.handlePowerctlMessage("reboot,rescue")
}

@ -15,7 +15,7 @@
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
id("org.jetbrains.kotlin.jvm") version "1.6.10"
id("org.jetbrains.kotlin.jvm") version "1.6.20"
`java-library`
application
}
@ -52,8 +52,8 @@ dependencies {
tasks.withType<KotlinCompile>().all {
kotlinOptions {
freeCompilerArgs += "-Xopt-in=kotlin.RequiresOptIn"
freeCompilerArgs += "-Xopt-in=kotlin.ExperimentalUnsignedTypes"
freeCompilerArgs += "-opt-in=kotlin.RequiresOptIn"
freeCompilerArgs += "-opt-in=kotlin.ExperimentalUnsignedTypes"
jvmTarget = "11"
}
}

@ -42,6 +42,8 @@ def cleanUp():
"boot.img", "boot.img.clear", "boot.img.google", "boot.img.signed", "boot.img.signed2",
"recovery.img", "recovery.img.clear", "recovery.img.google", "recovery.img.signed", "recovery.img.signed2",
"vbmeta.img", "vbmeta.img.signed",
"dtbo.img", "dtbo.img.clear", "dtbo.img.signed", "dtbo.img.signed2",
"misc.img", "misc.img.new",
"payload.bin",
"init_boot.img", "init_boot.img.signed",
"vendor_boot.img", "vendor_boot.img.clear", "vendor_boot.img.google", "vendor_boot.img.signed", "vendor_boot.img.signed2",

Loading…
Cancel
Save