update "misc" partition r/w operations

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

@ -3,6 +3,9 @@ package cfig.bootloader_message
import cfig.io.Struct3 import cfig.io.Struct3
import org.junit.Assert import org.junit.Assert
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.lang.IllegalStateException import java.lang.IllegalStateException
data class BootloaderMsg( data class BootloaderMsg(
@ -14,17 +17,55 @@ data class BootloaderMsg(
) { ) {
companion object { companion object {
private const val FORMAT_STRING = "32s32s768s32s1184b" private const val FORMAT_STRING = "32s32s768s32s1184b"
private const val miscFile = "misc.file"
const val SIZE = 2048 const val SIZE = 2048
private val log = LoggerFactory.getLogger("BootloaderMsg") private val log = LoggerFactory.getLogger("BootloaderMsg")
init { init {
Assert.assertEquals(SIZE, Struct3(FORMAT_STRING).calcSize()) Assert.assertEquals(SIZE, Struct3(FORMAT_STRING).calcSize())
} }
}
constructor(fis: FileInputStream) : this() {
val info = Struct3(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 writeBootloaderMessage(options: Array<String>) { fun encode(): ByteArray {
val boot = BootloaderMsg() return Struct3(FORMAT_STRING).pack(
boot.updateBootloaderMessageInStruct(options) this.command,
boot.writeBootloaderMessage() 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 = Struct3(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
} else {
log.info("$miscFile missing")
} }
} }
@ -38,11 +79,17 @@ data class BootloaderMsg(
fun writeBootloaderMessage() { fun writeBootloaderMessage() {
log.info("writing ... $this") 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>) { fun updateBootloaderMessageInStruct(options: Array<String>) {
this.command = "boot-recovery" this.command = "boot-recovery"
this.recovery = "recovery" this.recovery = "recovery\n"
options.forEach { options.forEach {
this.recovery += if (it.endsWith("\n")) { this.recovery += if (it.endsWith("\n")) {
it it

@ -78,7 +78,7 @@ class Reboot {
BootloaderMsg().writeRebootBootloader() BootloaderMsg().writeRebootBootloader()
} else { } else {
log.info("$dynamicPartitionKey=true, using fastbootd") log.info("$dynamicPartitionKey=true, using fastbootd")
BootloaderMsg.writeBootloaderMessage(arrayOf("--fastboot")) BootloaderMsg().writeBootloaderMessage(arrayOf("--fastboot"))
rebootTarget = "recovery" rebootTarget = "recovery"
} }
} }
@ -86,7 +86,7 @@ class Reboot {
BootloaderMsg().writeRebootBootloader() BootloaderMsg().writeRebootBootloader()
} }
"sideload", "sideload-auto-reboot" -> { "sideload", "sideload-auto-reboot" -> {
BootloaderMsg.writeBootloaderMessage( BootloaderMsg().writeBootloaderMessage(
arrayOf("--" + rebootTarget.replace("-", "_"))) arrayOf("--" + rebootTarget.replace("-", "_")))
rebootTarget = "recovery" rebootTarget = "recovery"
} }

@ -0,0 +1,56 @@
package bootloader_message
import cfig.bootloader_message.BootloaderMsg
import org.junit.Test
import org.junit.Assert.*
import org.slf4j.LoggerFactory
class BootloaderMsgTest {
private val log = LoggerFactory.getLogger(BootloaderMsgTest::class.java)
@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"))
}
}

@ -1,4 +1,13 @@
apply plugin: 'java' apply plugin: "java"
buildscript {
repositories {
jcenter()
}
dependencies {
classpath "org.apache.commons:commons-exec:1.3"
}
}
subprojects { subprojects {
tasks.withType(JavaCompile) { tasks.withType(JavaCompile) {
@ -11,6 +20,10 @@ subprojects {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
import java.util.regex.Matcher import java.util.regex.Matcher
import java.util.regex.Pattern 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) { if (parseGradleVersion(gradle.gradleVersion) < 5) {
logger.error("ERROR: Gradle Version MUST >= 5.0, current is {}", gradle.gradleVersion) logger.error("ERROR: Gradle Version MUST >= 5.0, current is {}", gradle.gradleVersion)
throw new RuntimeException("ERROR: Gradle Version") throw new RuntimeException("ERROR: Gradle Version")
@ -93,27 +106,33 @@ task pull() {
} }
doLast { 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")) { if (project.findProperty("group")) {
println("Pull: $group") println("Pull: $group")
} else { } else {
println("Pull /boot, /recovery, /vbmeta") println("Pull /boot, /recovery, /vbmeta")
pullDefault() pullDefault(isAvbEnabled)
} }
} }
} }
void pullDefault() { 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/boot of=/cache/boot.img"])
Run(["adb", "shell", "dd if=/dev/block/by-name/recovery of=/cache/recovery.img"]) Run(["adb", "shell", "dd if=/dev/block/by-name/recovery of=/cache/recovery.img"])
Run(["adb", "shell", "dd if=/dev/block/by-name/vbmeta of=/cache/vbmeta.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/boot.img"])
Run(["adb", "pull", "/cache/recovery.img"]) Run(["adb", "pull", "/cache/recovery.img"])
Run(["adb", "pull", "/cache/vbmeta.img"]) if (avb) Run(["adb", "pull", "/cache/vbmeta.img"])
Run(["adb", "shell", "rm /cache/boot.img"]) Run(["adb", "shell", "rm /cache/boot.img"])
Run(["adb", "shell", "rm /cache/recovery.img"]) Run(["adb", "shell", "rm /cache/recovery.img"])
Run(["adb", "shell", "rm /cache/vbmeta.img"]) if (avb) Run(["adb", "shell", "rm /cache/vbmeta.img"])
} }
void Run(List<String> inCmd, String inWorkdir = null) { void Run(List<String> inCmd, String inWorkdir = null) {
@ -177,7 +196,7 @@ task rr {
} }
int parseGradleVersion(String version) { int parseGradleVersion(String version) {
Pattern VERSION_PATTERN = Pattern.compile("((\\d+)(\\.\\d+)+)(-(\\p{Alpha}+)-(\\w+))?(-(SNAPSHOT|\\d{14}([-+]\\d{4})?))?") Pattern VERSION_PATTERN = Pattern.compile("((\\d+)(\\.\\d+)+)(-(\\p{Alpha}+)-(\\w+))?(-(SNAPSHOT|\\d{14}([-+]\\d{4})?))?")
Matcher matcher = VERSION_PATTERN.matcher(version) Matcher matcher = VERSION_PATTERN.matcher(version)
if (!matcher.matches()) { if (!matcher.matches()) {
throw new IllegalArgumentException(format("'%s' is not a valid Gradle version string (examples: '1.0', '1.0-rc-1')", version)) throw new IllegalArgumentException(format("'%s' is not a valid Gradle version string (examples: '1.0', '1.0-rc-1')", version))
@ -185,5 +204,16 @@ int parseGradleVersion(String version) {
String versionPart = matcher.group(1) String versionPart = matcher.group(1)
int majorPart = Integer.parseInt(matcher.group(2), 10) int majorPart = Integer.parseInt(matcher.group(2), 10)
logger.info("Gradle: versionPart {}, majorPart {}", versionPart, majorPart) logger.info("Gradle: versionPart {}, majorPart {}", versionPart, majorPart)
return 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()
} }

Loading…
Cancel
Save