add 'flash' task for vbmeta/boot

pull/31/head
cfig 6 years ago
parent 1bcf9389a0
commit b8aba9992e
No known key found for this signature in database
GPG Key ID: B104C307F0FDABB7

@ -23,7 +23,6 @@ import java.util.zip.GZIPOutputStream
import javax.crypto.Cipher
class Helper {
@ExperimentalStdlibApi
@ExperimentalUnsignedTypes
companion object {
fun joinWithNulls(vararg source: ByteArray?): ByteArray {
@ -311,14 +310,28 @@ class Helper {
ret = true
} catch (e: java.lang.IllegalArgumentException) {
log.error("$e: can not parse command: [$this]")
throw e
} catch (e: ExecuteException) {
log.error("$e: can not exec command")
throw e
} catch (e: IOException) {
log.error("$e: can not exec command")
throw e
}
return ret
}
fun String.check_output(): String {
val outputStream = ByteArrayOutputStream()
log.info(this)
DefaultExecutor().let {
it.streamHandler = PumpStreamHandler(outputStream)
it.execute(CommandLine.parse(this))
}
log.info(outputStream.toString())
return outputStream.toString().trim()
}
private val log = LoggerFactory.getLogger("Helper")
}
}

@ -10,7 +10,6 @@ import java.nio.ByteOrder
import java.util.*
import java.util.regex.Pattern
@ExperimentalStdlibApi
@ExperimentalUnsignedTypes
class Struct3 {
private val log = LoggerFactory.getLogger(Struct3::class.java)
@ -411,7 +410,7 @@ class Struct3 {
if (format[0] === String) {
val data = ByteArray(format[1] as Int)
Assert.assertEquals(format[1] as Int, iS.read(data))
ret.add(data.decodeToString())
ret.add(Helper.toCString(data))
continue
}

@ -9,10 +9,6 @@ import java.lang.IllegalArgumentException
@ExperimentalUnsignedTypes
class BootImgParser : IPackable {
override fun flash(fileName: String) {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
private val log = LoggerFactory.getLogger(BootImgParser::class.java)
override fun capabilities(): List<String> {
@ -53,4 +49,9 @@ class BootImgParser : IPackable {
Packer().pack(mkbootfsBin = "./aosp/mkbootfs/build/install/main/release/$osSuffix/mkbootfs")
Signer.sign(avbtool = "avb/avbtool", bootSigner = "aosp/boot_signer/build/libs/boot_signer.jar")
}
override fun flash(fileName: String, deviceName: String) {
val stem = fileName.substring(0, fileName.indexOf("."))
super.flash("$fileName.signed", stem)
}
}

@ -12,10 +12,6 @@ import java.util.*
@ExperimentalUnsignedTypes
class DtboParser(val workDir: File) : IPackable {
override fun flash(fileName: String) {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
constructor() : this(File("."))
private val log = LoggerFactory.getLogger(DtboParser::class.java)
@ -33,17 +29,7 @@ class DtboParser(val workDir: File) : IPackable {
it.addArguments("--dtb $dtbPath")
it.addArguments("--output $headerPath")
}
DefaultExecutor().let {
it.workingDirectory = this.workDir
try {
log.info(cmd.toString())
it.execute(cmd)
} catch (e: org.apache.commons.exec.ExecuteException) {
log.error("can not parse $fileName")
return
}
}
execInDirectory(cmd, this.workDir)
val props = Properties()
props.load(FileInputStream(File(headerPath)))
@ -75,14 +61,17 @@ class DtboParser(val workDir: File) : IPackable {
}
it
}
execInDirectory(cmd, this.workDir)
}
private fun execInDirectory(cmd: CommandLine, inWorkDir: File) {
DefaultExecutor().let {
it.workingDirectory = this.workDir
it.workingDirectory = inWorkDir
try {
log.info(cmd.toString())
it.execute(cmd)
} catch (e: org.apache.commons.exec.ExecuteException) {
log.error("can not parse $fileName")
log.error("can not exec command")
return
}
}

@ -1,12 +1,33 @@
package cfig.packable
import cfig.Helper.Companion.check_call
import cfig.Helper.Companion.check_output
import org.slf4j.Logger
import org.slf4j.LoggerFactory
interface IPackable {
fun capabilities(): List<String> {
return listOf("^dtbo\\.img$")
}
fun unpack(fileName: String = "dtbo.img")
fun pack(fileName: String = "dtbo.img")
fun flash(fileName: String = "dtbo.img") {
fun flash(fileName: String = "dtbo.img", deviceName: String = "dtbo") {
"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") {
"adb shell getprop ro.boot.slot_suffix".check_output()
} else {
""
}
log.info("slot suffix = $slotSuffix")
"adb push $fileName /cache/file.to.burn".check_call()
"adb shell dd if=/cache/file.to.burn of=/dev/block/by-name/$deviceName$slotSuffix".check_call()
"adb shell rm /cache/file.to.burn".check_call()
}
companion object {
val log: Logger = LoggerFactory.getLogger(IPackable::class.java)
}
}

@ -28,7 +28,7 @@ fun main(args: Array<String>) {
packablePool.forEach { p ->
for (item in p.key) {
if (Pattern.compile(item).matcher(file.name).matches()) {
log.debug("Found: " + file.name + ", " + item)
log.debug("Found: " + file.name + ", " + item)
targetFile = file.name
targetHandler = p.value
return@found
@ -49,6 +49,9 @@ fun main(args: Array<String>) {
"pack" -> {
targetHandler!!.createInstance().pack(targetFile!!)
}
"flash" -> {
targetHandler!!.createInstance().flash(targetFile!!)
}
else -> {
log.error("Unknown cmd: " + args[0])
}

@ -4,10 +4,6 @@ import cfig.Avb
@ExperimentalUnsignedTypes
class VBMetaParser: IPackable {
override fun flash(fileName: String) {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun capabilities(): List<String> {
return listOf("^vbmeta\\.img$", "^vbmeta\\_[a-z]+.img$")
}
@ -19,4 +15,9 @@ class VBMetaParser: IPackable {
override fun pack(fileName: String) {
Avb().packVbMetaWithPadding(fileName)
}
override fun flash(fileName: String, deviceName: String) {
val stem = fileName.substring(0, fileName.indexOf("."))
super.flash("$fileName.signed", stem)
}
}

@ -44,4 +44,8 @@ class SparseImg : IPackable {
"file $sparseOut".check_call()
log.info("transformed Android sparse image: $flatIn -> $sparseOut")
}
override fun flash(fileName: String, deviceName: String) {
TODO("not implemented")
}
}

@ -1,167 +0,0 @@
apply plugin: "java"
buildscript {
repositories {
jcenter()
}
dependencies {
classpath "org.apache.commons:commons-exec:1.3"
}
}
subprojects {
tasks.withType(JavaCompile) {
//options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation"
}
}
// ----------------------------------------------------------------------------
// global
// ----------------------------------------------------------------------------
import java.util.regex.Matcher
import java.util.regex.Pattern
import org.apache.commons.exec.CommandLine
import org.apache.commons.exec.DefaultExecutor
import org.apache.commons.exec.PumpStreamHandler
if (parseGradleVersion(gradle.gradleVersion) < 5) {
logger.error("ERROR: Gradle Version MUST >= 5.0, current is {}", gradle.gradleVersion)
throw new RuntimeException("ERROR: Gradle Version")
} else {
logger.info("Gradle Version {}", gradle.gradleVersion)
}
def GROUP_ANDROID = "Android"
project.ext.bootSigner = new File("boot_signer/build/libs/boot_signer.jar").getAbsolutePath()
// ----------------------------------------------------------------------------
// tasks
// ----------------------------------------------------------------------------
task _setup(type: Copy) {
group GROUP_ANDROID
from 'src/test/resources/boot.img'
into '.'
}
task pull() {
group GROUP_ANDROID
doFirst {
println("Pulling ...")
}
doLast {
String avb_version = adbCmd("getprop ro.boot.avb_version2")
Boolean isAvbEnabled = false
if (avb_version.isEmpty()) {
isAvbEnabled = true
}
println("AVB: $isAvbEnabled")
if (project.findProperty("group")) {
println("Pull: $group")
} else {
println("Pull /boot, /recovery, /vbmeta")
pullDefault(isAvbEnabled)
}
}
}
void pullDefault(Boolean avb = true) {
Run(["adb", "shell", "dd if=/dev/block/by-name/boot of=/cache/boot.img"])
Run(["adb", "shell", "dd if=/dev/block/by-name/recovery of=/cache/recovery.img"])
if (avb) Run(["adb", "shell", "dd if=/dev/block/by-name/vbmeta of=/cache/vbmeta.img"])
Run(["adb", "pull", "/cache/boot.img"])
Run(["adb", "pull", "/cache/recovery.img"])
if (avb) Run(["adb", "pull", "/cache/vbmeta.img"])
Run(["adb", "shell", "rm /cache/boot.img"])
Run(["adb", "shell", "rm /cache/recovery.img"])
if (avb) Run(["adb", "shell", "rm /cache/vbmeta.img"])
}
void Run(List<String> inCmd, String inWorkdir = null) {
println("CMD:" + inCmd)
if (inWorkdir == null) {
inWorkdir = ".";
}
ProcessBuilder pb = new ProcessBuilder(inCmd)
.directory(new File(inWorkdir))
.redirectErrorStream(true);
Process p = pb.start()
p.inputStream.eachLine { println it }
p.waitFor();
assert 0 == p.exitValue()
}
void Run(String inCmd, String inWorkdir = null) {
Run(Arrays.asList(inCmd.split()), inWorkdir);
}
void rebootRecovery() {
Run("adb reboot recovery")
}
task rr {
group GROUP_ANDROID
doLast {
rebootRecovery()
}
}
task unpack(type: JavaExec, dependsOn: ["bbootimg:jar"]) {
group GROUP_ANDROID
main = "cfig.packable.PackableLauncherKt"
classpath = files("bbootimg/build/libs/bbootimg.jar")
maxHeapSize '512m'
args "unpack"
}
task pack(type: JavaExec, dependsOn: ["bbootimg:jar", "aosp:boot_signer:build"]) {
group GROUP_ANDROID
main = "cfig.packable.PackableLauncherKt"
classpath = files("bbootimg/build/libs/bbootimg.jar")
maxHeapSize '512m'
args "pack"
}
task flash(type: JavaExec, dependsOn: ["bbootimg:jar"]) {
group GROUP_ANDROID
main = "cfig.packable.PackableLauncherKt"
classpath = files("bbootimg/build/libs/bbootimg.jar")
maxHeapSize '512m'
args "flash"
}
//sparse image dependencies
if (System.getProperty("os.name").contains("Mac")) {
unpack.dependsOn("aosp:libsparse:simg2img:installReleaseMacos")
pack.dependsOn("aosp:libsparse:img2simg:installReleaseMacos")
pack.dependsOn("aosp:mkbootfs:installReleaseMacos")
} else {
unpack.dependsOn("aosp:libsparse:simg2img:installReleaseLinux")
pack.dependsOn("aosp:libsparse:img2simg:installReleaseLinux")
pack.dependsOn("aosp:mkbootfs:installReleaseLinux")
}
int parseGradleVersion(String version) {
Pattern VERSION_PATTERN = Pattern.compile("((\\d+)(\\.\\d+)+)(-(\\p{Alpha}+)-(\\w+))?(-(SNAPSHOT|\\d{14}([-+]\\d{4})?))?")
Matcher matcher = VERSION_PATTERN.matcher(version)
if (!matcher.matches()) {
throw new IllegalArgumentException(format("'%s' is not a valid Gradle version string (examples: '1.0', '1.0-rc-1')", version))
}
String versionPart = matcher.group(1)
int majorPart = Integer.parseInt(matcher.group(2), 10)
logger.info("Gradle: versionPart {}, majorPart {}", versionPart, majorPart)
return majorPart
}
String adbCmd(String cmd) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream()
def exec = new DefaultExecutor()
exec.streamHandler = new PumpStreamHandler(outputStream)
def cmdline = "adb shell $cmd"
//println(cmdline)
exec.execute(CommandLine.parse(cmdline))
//println(outputStream)
return outputStream.toString().trim()
}

@ -0,0 +1,74 @@
import java.util.regex.Matcher
import java.util.regex.Pattern
import org.apache.commons.exec.CommandLine
import org.apache.commons.exec.DefaultExecutor
import org.apache.commons.exec.PumpStreamHandler
val GROUP_ANDROID = "android"
if (parseGradleVersion(gradle.gradleVersion) < 5) {
logger.error("ERROR: Gradle Version MUST >= 5.0, current is {}", gradle.gradleVersion)
throw RuntimeException("ERROR: Gradle Version")
} else {
logger.info("Gradle Version {}", gradle.gradleVersion)
}
buildscript {
repositories {
jcenter()
}
dependencies {
classpath("org.apache.commons:commons-exec:1.3")
}
}
tasks {
val unpackTask by register<JavaExec>("unpack") {
group = GROUP_ANDROID
main = "cfig.packable.PackableLauncherKt"
classpath = files("bbootimg/build/libs/bbootimg.jar")
this.maxHeapSize = "512m"
args("unpack")
}
unpackTask.dependsOn("bbootimg:jar")
val packTask by register<JavaExec>("pack") {
group = GROUP_ANDROID
main = "cfig.packable.PackableLauncherKt"
classpath = files("bbootimg/build/libs/bbootimg.jar")
this.maxHeapSize = "512m"
args("pack")
}
packTask.dependsOn("bbootimg:jar", "aosp:boot_signer:build")
val flashTask by register("flash", JavaExec::class) {
group = GROUP_ANDROID
main = "cfig.packable.PackableLauncherKt"
classpath = files("bbootimg/build/libs/bbootimg.jar")
this.maxHeapSize = "512m"
args("flash")
}
flashTask.dependsOn("bbootimg:jar")
//sparse image dependencies
if (System.getProperty("os.name").contains("Mac")) {
unpackTask.dependsOn("aosp:libsparse:simg2img:installReleaseMacos")
packTask.dependsOn("aosp:libsparse:img2simg:installReleaseMacos")
packTask.dependsOn("aosp:mkbootfs:installReleaseMacos")
} else {
unpackTask.dependsOn("aosp:libsparse:simg2img:installReleaseLinux")
packTask.dependsOn("aosp:libsparse:img2simg:installReleaseLinux")
packTask.dependsOn("aosp:mkbootfs:installReleaseLinux")
}
}
fun parseGradleVersion(version: String): Int {
val VERSION_PATTERN = Pattern.compile("((\\d+)(\\.\\d+)+)(-(\\p{Alpha}+)-(\\w+))?(-(SNAPSHOT|\\d{14}([-+]\\d{4})?))?")
val matcher = VERSION_PATTERN.matcher(version)
if (!matcher.matches()) {
throw IllegalArgumentException(String.format("'%s' is not a valid Gradle version string (examples: '1.0', '1.0-rc-1')", version))
}
val versionPart: String = matcher.group(1)
val majorPart = Integer.parseInt(matcher.group(2), 10)
logger.info("Gradle: versionPart {}, majorPart {}", versionPart, majorPart)
return majorPart
}

@ -1,9 +0,0 @@
include "bbootimg"
include "aosp:boot_signer"
include "aosp:mkbootfs"
include "aosp:libsparse:base"
include "aosp:libsparse:sparse"
include "aosp:libsparse:img2simg"
include "aosp:libsparse:simg2img"
include "aosp:libsparse:simg2simg"
include "aosp:libsparse:append2simg"

@ -0,0 +1,9 @@
include("bbootimg")
include("aosp:boot_signer")
include("aosp:mkbootfs")
include("aosp:libsparse:base")
include("aosp:libsparse:sparse")
include("aosp:libsparse:img2simg")
include("aosp:libsparse:simg2img")
include("aosp:libsparse:simg2simg")
include("aosp:libsparse:append2simg")
Loading…
Cancel
Save