update BootV3 for abe

dev
cfig 10 months ago
parent 585e2fdcd5
commit 71a7d2a07f

@ -174,7 +174,6 @@ class Avb {
fun getJsonFileName(image_file: String): String { fun getJsonFileName(image_file: String): String {
val jsonFile = File(image_file).name.removeSuffix(".img") + ".avb.json" val jsonFile = File(image_file).name.removeSuffix(".img") + ".avb.json"
log.warn("XXXX: json file = " + Helper.joinPath(Helper.prop("workDir")!!, jsonFile))
return Helper.joinPath(Helper.prop("workDir")!!, jsonFile) return Helper.joinPath(Helper.prop("workDir")!!, jsonFile)
} }
@ -201,10 +200,17 @@ class Avb {
} }
fun updateVbmeta(fileName: String, desc: Any = HashDescriptor::class) { fun updateVbmeta(fileName: String, desc: Any = HashDescriptor::class) {
if (File("vbmeta.img").exists()) { val vbmetaCompanion = getJsonFileName("vbmeta.img")
if (File(vbmetaCompanion).exists()) {
log.info("Updating vbmeta.img side by side ...") log.info("Updating vbmeta.img side by side ...")
val readBackInfo = ObjectMapper().readValue(File(getJsonFileName(fileName)), AVBInfo::class.java) val readBackInfo = ObjectMapper().readValue(File(getJsonFileName(fileName)), AVBInfo::class.java)
val newHashDesc = AVBInfo.parseFrom(Dumpling("$fileName.signed")) val intermediateDir = Helper.joinPath(Helper.prop("workDir")!!, "intermediate")
val newHashDesc = if (File(intermediateDir).exists()) {
AVBInfo.parseFrom(Dumpling(Helper.joinPath(intermediateDir, "$fileName.signed")))
} else {
//FIXME: before BootV2 supports abe mode
AVBInfo.parseFrom(Dumpling("$fileName.signed"))
}
when (desc) { when (desc) {
HashDescriptor::class -> { HashDescriptor::class -> {

@ -135,6 +135,7 @@ class Common {
) )
ZipHelper.zcat(s.dumpFile + ".gz", s.dumpFile) ZipHelper.zcat(s.dumpFile + ".gz", s.dumpFile)
} }
ZipHelper.isXz(s.dumpFile) -> { ZipHelper.isXz(s.dumpFile) -> {
log.info("ramdisk is compressed xz") log.info("ramdisk is compressed xz")
Files.move( Files.move(
@ -144,15 +145,17 @@ class Common {
ZipHelper.xzcat(s.dumpFile + ".xz", s.dumpFile) ZipHelper.xzcat(s.dumpFile + ".xz", s.dumpFile)
ret = "xz" ret = "xz"
} }
ZipHelper.isLzma(s.dumpFile) -> { ZipHelper.isLzma(s.dumpFile) -> {
log.info("ramdisk is compressed lzma") log.info("ramdisk is compressed lzma")
Files.move( Files.move(
Paths.get(s.dumpFile), Paths.get(s.dumpFile + ".lzma"), Paths.get(s.dumpFile), Paths.get(s.dumpFile + ".lzma"),
java.nio.file.StandardCopyOption.REPLACE_EXISTING java.nio.file.StandardCopyOption.REPLACE_EXISTING
) )
ZipHelper.lzcat(s.dumpFile + ".lzma", s.dumpFile) ZipHelper.lzcat(s.dumpFile + ".lzma", s.dumpFile)
ret = "lzma" ret = "lzma"
} }
ZipHelper.isLz4(s.dumpFile) -> { ZipHelper.isLz4(s.dumpFile) -> {
log.info("ramdisk is compressed lz4") log.info("ramdisk is compressed lz4")
Files.move( Files.move(
@ -162,6 +165,7 @@ class Common {
ZipHelper.lz4cat(s.dumpFile + ".lz4", s.dumpFile) ZipHelper.lz4cat(s.dumpFile + ".lz4", s.dumpFile)
ret = "lz4" ret = "lz4"
} }
ZipHelper.isAndroidCpio(s.dumpFile) -> { ZipHelper.isAndroidCpio(s.dumpFile) -> {
log.info("ramdisk is uncompressed cpio") log.info("ramdisk is uncompressed cpio")
Files.copy( Files.copy(
@ -170,6 +174,7 @@ class Common {
) )
ret = "cpio" ret = "cpio"
} }
else -> { else -> {
throw IllegalArgumentException("ramdisk is in unknown format") throw IllegalArgumentException("ramdisk is in unknown format")
} }
@ -248,9 +253,11 @@ class Common {
ramdiskGz.endsWith(".gz") -> { ramdiskGz.endsWith(".gz") -> {
ZipHelper.minigzip(ramdiskGz, ByteArrayInputStream(outputStream.toByteArray())) ZipHelper.minigzip(ramdiskGz, ByteArrayInputStream(outputStream.toByteArray()))
} }
ramdiskGz.endsWith(".lz4") -> { ramdiskGz.endsWith(".lz4") -> {
ZipHelper.lz4(ramdiskGz, ByteArrayInputStream(outputStream.toByteArray())) ZipHelper.lz4(ramdiskGz, ByteArrayInputStream(outputStream.toByteArray()))
} }
else -> { else -> {
throw IllegalArgumentException("$ramdiskGz is not supported") throw IllegalArgumentException("$ramdiskGz is not supported")
} }
@ -268,26 +275,31 @@ class Common {
AndroidCpio().pack(root, f, "${f}_filelist.txt") AndroidCpio().pack(root, f, "${f}_filelist.txt")
FileInputStream(f).use { ZipHelper.minigzip(ramdiskGz, it) } FileInputStream(f).use { ZipHelper.minigzip(ramdiskGz, it) }
} }
ramdiskGz.endsWith(".lz4") -> { ramdiskGz.endsWith(".lz4") -> {
val f = ramdiskGz.removeSuffix(".lz4") val f = ramdiskGz.removeSuffix(".lz4")
AndroidCpio().pack(root, f, "${f}_filelist.txt") AndroidCpio().pack(root, f, "${f}_filelist.txt")
FileInputStream(f).use { ZipHelper.lz4(ramdiskGz, it) } FileInputStream(f).use { ZipHelper.lz4(ramdiskGz, it) }
} }
ramdiskGz.endsWith(".lzma") -> { ramdiskGz.endsWith(".lzma") -> {
val f = ramdiskGz.removeSuffix(".lzma") val f = ramdiskGz.removeSuffix(".lzma")
AndroidCpio().pack(root, f, "${f}_filelist.txt") AndroidCpio().pack(root, f, "${f}_filelist.txt")
FileInputStream(f).use { ZipHelper.lzma(ramdiskGz, it) } FileInputStream(f).use { ZipHelper.lzma(ramdiskGz, it) }
} }
ramdiskGz.endsWith(".xz") -> { ramdiskGz.endsWith(".xz") -> {
val f = ramdiskGz.removeSuffix(".xz") val f = ramdiskGz.removeSuffix(".xz")
AndroidCpio().pack(root, f, "${f}_filelist.txt") AndroidCpio().pack(root, f, "${f}_filelist.txt")
FileInputStream(f).use { ZipHelper.xz(ramdiskGz, it, compressorArgs!!) } FileInputStream(f).use { ZipHelper.xz(ramdiskGz, it, compressorArgs!!) }
} }
ramdiskGz.endsWith(".cpio") -> { ramdiskGz.endsWith(".cpio") -> {
val f = ramdiskGz.removeSuffix(".cpio") val f = ramdiskGz.removeSuffix(".cpio")
AndroidCpio().pack(root, f, "${f}_filelist.txt") AndroidCpio().pack(root, f, "${f}_filelist.txt")
File(f).copyTo(File(ramdiskGz), true) File(f).copyTo(File(ramdiskGz), true)
} }
else -> { else -> {
throw IllegalArgumentException("$ramdiskGz is not supported") throw IllegalArgumentException("$ramdiskGz is not supported")
} }
@ -381,9 +393,11 @@ class Common {
log.warn("Os Major exceeds current max $MAX_ANDROID_VER") log.warn("Os Major exceeds current max $MAX_ANDROID_VER")
MAX_ANDROID_VER MAX_ANDROID_VER
} }
ret < 10 -> { ret < 10 -> {
10 10
} }
else -> { else -> {
ret ret
} }
@ -405,7 +419,8 @@ class Common {
com.github.freva.asciitable.Column().header("Where") com.github.freva.asciitable.Column().header("Where")
.headerAlign(HorizontalAlign.CENTER) .headerAlign(HorizontalAlign.CENTER)
.dataAlign(HorizontalAlign.LEFT) .dataAlign(HorizontalAlign.LEFT)
.with { it.second })) .with { it.second })
)
} }
fun printPackSummary(imageName: String) { fun printPackSummary(imageName: String) {
@ -441,5 +456,34 @@ class Common {
log.info("\n\t\t\tPack Summary of ${imageName}\n{}\n{}", tableHeader.render(), tab.render()) log.info("\n\t\t\tPack Summary of ${imageName}\n{}\n{}", tableHeader.render(), tab.render())
} }
} }
fun printPackSummaryInternal(imageName: String) {
val prints: MutableList<Pair<String, String>> = mutableListOf()
val tableHeader = de.vandermeer.asciitable.AsciiTable().apply {
addRule(); addRow("What", "Where"); addRule()
}
val tab = de.vandermeer.asciitable.AsciiTable().let {
it.addRule()
it.addRow("re-packed $imageName", Helper.prop("out.file"))
prints.add(Pair("re-packed $imageName", Helper.prop("out.file")!!))
it.addRule()
it
}
if (File("vbmeta.img").exists()) {
if (File("vbmeta.img.signed").exists()) {
tab.addRow("re-packed vbmeta", "vbmeta.img.signed")
prints.add(Pair("re-packed vbmeta", "vbmeta.img.signed"))
} else {
tab.addRow("re-packed vbmeta", "-")
prints.add(Pair("re-packed vbmeta", "-"))
}
tab.addRule()
}
if (EnvironmentVerifier().isWindows) {
log.info("\n" + Common.table2String(prints))
} else {
log.info("\n\t\t\tPack Summary of ${imageName}\n{}\n{}", tableHeader.render(), tab.render())
}
}
} }
} }

@ -214,27 +214,50 @@ data class BootV3(
} }
fun sign(fileName: String): BootV3 { fun sign(fileName: String): BootV3 {
log.warn("XXXX: sign $fileName") var bSigningNeeded = false
if (File(Avb.getJsonFileName(info.role)).exists()) { if (File(Avb.getJsonFileName(info.role)).exists()) {
bSigningNeeded = true
Signer.signAVB( Signer.signAVB(
Helper.joinPath(Helper.prop("intermediateDir")!!, info.role), Helper.joinPath(Helper.prop("intermediateDir")!!, info.role),
this.info.imageSize, this.info.imageSize,
String.format(Helper.prop("avbtool")!!, "v1.2") String.format(Helper.prop("avbtool")!!, "v1.2")
) )
} else { } else {
bSigningNeeded = false
log.warn("no AVB info found, assume it's clear image") log.warn("no AVB info found, assume it's clear image")
} }
if (fileName != info.role) { if (fileName != info.role) {
File(Helper.joinPath(Helper.prop("intermediateDir")!!, info.role + ".signed")).copyTo(File(fileName), true) Helper.setProp("out.file", fileName)
log.info("Signed image saved as $fileName") if (bSigningNeeded) {
//@formatter:off
File(Helper.joinPath(Helper.prop("intermediateDir")!!, info.role + ".signed"))
.copyTo(File(fileName), true)
//@formatter:on
log.info("Signed image saved as $fileName")
} else {
//@formatter:off
File(Helper.joinPath(Helper.prop("intermediateDir")!!, info.role + ".clear"))
.copyTo(File(fileName), true)
//@formatter:on
log.info("Unsigned image saved as $fileName")
}
} else { } else {
File( if (bSigningNeeded) {
Helper.joinPath( Helper.setProp("out.file", info.role + ".signed")
Helper.prop("intermediateDir")!!, //@formatter:off
info.role + ".signed" File(Helper.joinPath(Helper.prop("intermediateDir")!!, info.role + ".signed"))
) .copyTo(File(info.role + ".signed"), true)
).copyTo(File(info.role + ".signed"), true) //@formatter:on
log.info("Signed image saved as ${info.role}.signed") log.info("Signed image saved as ${info.role}.signed")
} else {
Helper.setProp("out.file", info.role + ".clear")
//@formatter:off
File(Helper.joinPath(Helper.prop("intermediateDir")!!, info.role + ".clear"))
.copyTo(File(info.role + ".clear"), true)
//@formatter:on
log.info("Unsigned image saved as ${info.role}.clear")
}
} }
return this return this
} }
@ -284,11 +307,12 @@ data class BootV3(
fun extractVBMeta(): BootV3 { fun extractVBMeta(): BootV3 {
// vbmeta in image // vbmeta in image
try { try {
log.warn("XXXX: info.output ${info.input}") val vbmetaCompanion = Helper.joinPath(File(info.input).parentFile.normalize().path, "vbmeta.img")
log.info("XXXX: $vbmetaCompanion")
val ai = AVBInfo.parseFrom(Dumpling(info.input)).dumpDefault(info.role) val ai = AVBInfo.parseFrom(Dumpling(info.input)).dumpDefault(info.role)
if (File("vbmeta.img").exists()) { if (File(vbmetaCompanion).exists()) {
log.warn("Found vbmeta.img, parsing ...") log.warn("Found vbmeta.img, parsing ...")
VBMetaParser().unpack("vbmeta.img") VBMetaParser().unpack(vbmetaCompanion)
} }
} catch (e: IllegalArgumentException) { } catch (e: IllegalArgumentException) {
log.warn(e.message) log.warn(e.message)
@ -368,7 +392,6 @@ data class BootV3(
it.addRow("kernel", this.kernel.file) it.addRow("kernel", this.kernel.file)
prints.add(Pair("kernel", this.kernel.file)) prints.add(Pair("kernel", this.kernel.file))
File(Helper.joinPath(workDir, Helper.prop("kernelVersionStem")!!)).let { kernelVersionFile -> File(Helper.joinPath(workDir, Helper.prop("kernelVersionStem")!!)).let { kernelVersionFile ->
log.warn("XXXX: kernelVersionFile ${kernelVersionFile.path}")
if (kernelVersionFile.exists()) { if (kernelVersionFile.exists()) {
it.addRow("\\-- version " + kernelVersionFile.readLines().toString(), kernelVersionFile.path) it.addRow("\\-- version " + kernelVersionFile.readLines().toString(), kernelVersionFile.path)
prints.add( prints.add(
@ -380,7 +403,6 @@ data class BootV3(
} }
} }
File(Helper.joinPath(workDir, Helper.prop("kernelConfigStem")!!)).let { kernelConfigFile -> File(Helper.joinPath(workDir, Helper.prop("kernelConfigStem")!!)).let { kernelConfigFile ->
log.warn("XXXX: kernelConfigFile ${kernelConfigFile.path}")
if (kernelConfigFile.exists()) { if (kernelConfigFile.exists()) {
it.addRow("\\-- config", kernelConfigFile.path) it.addRow("\\-- config", kernelConfigFile.path)
prints.add(Pair("\\-- config", kernelConfigFile.path)) prints.add(Pair("\\-- config", kernelConfigFile.path))
@ -460,14 +482,19 @@ data class BootV3(
it it
} }
val tabVBMeta = AsciiTable().let { val tabVBMeta = AsciiTable().let {
if (File("vbmeta.img").exists()) { val vbmetaCompanion = Helper.joinPath(File(info.input).parentFile.normalize().path, "vbmeta.img")
log.warn("XXXX: vbmetaCompanion: $vbmetaCompanion")
if (File(vbmetaCompanion).exists()) {
log.warn("XXXX: Found vbmeta.img, parsing ...")
//basic
prints.add(Pair("vbmeta.img", Avb.getJsonFileName("vbmeta.img")))
//table
it.addRule() it.addRule()
it.addRow("vbmeta.img", Avb.getJsonFileName("vbmeta.img")) it.addRow("vbmeta.img", Avb.getJsonFileName("vbmeta.img"))
it.addRule() it.addRule()
"\n" + it.render() "\n" + it.render()
//basic
prints.add(Pair("vbmeta.img", Avb.getJsonFileName("vbmeta.img")))
} else { } else {
log.warn("XXXX: no vbmeta.img found")
"" ""
} }
} }
@ -483,7 +510,7 @@ data class BootV3(
} }
fun printPackSummary(fileName: String): BootV3 { fun printPackSummary(fileName: String): BootV3 {
Common.printPackSummary(fileName) Common.printPackSummaryInternal(fileName)
return this return this
} }

@ -49,11 +49,10 @@ class BootImgParser : IPackable {
} }
fun unpackInternal(targetFile: String, fileName: String, unpackDir: String) { fun unpackInternal(targetFile: String, fileName: String, unpackDir: String) {
log.warn("Unpacking $fileName") log.info("unpackInternal(fileName: $fileName, unpackDir: $unpackDir)")
log.warn("fileName: $fileName, unpackDir: $unpackDir")
Helper.setProp("workDir", unpackDir) Helper.setProp("workDir", unpackDir)
clear() clear()
File("$outDir/role").writeText(File(File(fileName).canonicalPath).name) File("$outDir/role").writeText(File(File(targetFile).canonicalPath).name)
val hv = probeHeaderVersion(fileName) val hv = probeHeaderVersion(fileName)
log.info("header version $hv") log.info("header version $hv")
when (hv) { when (hv) {
@ -87,7 +86,7 @@ class BootImgParser : IPackable {
} }
fun packInternal(targetFile: String, workspace: String, fileName: String) { fun packInternal(targetFile: String, workspace: String, fileName: String) {
log.warn("XXXX: targetFile: $targetFile, fileName: $fileName, workspace: $workspace") log.info("packInternal(targetFile: $targetFile, fileName: $fileName, workspace: $workspace)")
Helper.setProp("workDir", workspace) Helper.setProp("workDir", workspace)
val cfgFile = Helper.joinPath(outDir, targetFile.removeSuffix(".img") + ".json") val cfgFile = Helper.joinPath(outDir, targetFile.removeSuffix(".img") + ".json")
log.info("Loading config from $cfgFile") log.info("Loading config from $cfgFile")
@ -113,7 +112,7 @@ class BootImgParser : IPackable {
} }
} }
if (worker == null) { if (worker == null) {
log.warn("XXXX: worker is null") log.error("no worker available")
exitProcess(2) exitProcess(2)
} }
when (worker) { when (worker) {
@ -130,7 +129,7 @@ class BootImgParser : IPackable {
.pack() .pack()
.sign(fileName) .sign(fileName)
.updateVbmeta() .updateVbmeta()
.printPackSummary(fileName) .printPackSummary(worker.info.role)
} }
else -> { else -> {

@ -14,11 +14,10 @@
package cfig.packable package cfig.packable
import rom.sparse.SparseImgParser
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import packable.DeviceTreeParser import packable.DeviceTreeParser
import rom.sparse.SparseImgParser
import java.io.File import java.io.File
import java.util.*
import java.util.regex.Pattern import java.util.regex.Pattern
import kotlin.reflect.KClass import kotlin.reflect.KClass
import kotlin.reflect.full.createInstance import kotlin.reflect.full.createInstance
@ -98,9 +97,9 @@ fun main(args: Array<String>) {
// /* 2 */ no-args & handler : help for Handler // /* 2 */ no-args & handler : help for Handler
// /* 3 */ args & no-handler: do nothing // /* 3 */ args & no-handler: do nothing
// /* 4 */ args & handler : work // /* 4 */ args & handler : work
log.warn("args: ${args.size}, targetHandler: $targetHandler")
when (listOf(args.isNotEmpty(), targetHandler != null)) { when (listOf(args.isNotEmpty(), targetHandler != null)) {
listOf(false, false) -> { /* 1 */ listOf(false, false) -> { /* 1 */
log.warn("args: ${args.size}, targetHandler: $targetHandler")
log.info("help:") log.info("help:")
log.info("available IPackable subcommands are:") log.info("available IPackable subcommands are:")
IPackable::class.declaredFunctions.forEach { IPackable::class.declaredFunctions.forEach {
@ -110,7 +109,6 @@ fun main(args: Array<String>) {
} }
listOf(false, true) -> {/* 2 */ listOf(false, true) -> {/* 2 */
log.warn("args: ${args.size}, targetHandler: $targetHandler")
log.info("available ${targetHandler!!.simpleName} subcommands are:") log.info("available ${targetHandler!!.simpleName} subcommands are:")
targetHandler!!.declaredFunctions.forEach { targetHandler!!.declaredFunctions.forEach {
log.info("\t" + it.name) log.info("\t" + it.name)
@ -119,13 +117,11 @@ fun main(args: Array<String>) {
} }
listOf(true, false) -> {/* 3 */ listOf(true, false) -> {/* 3 */
log.warn("args: ${args.size}, targetHandler: $targetHandler")
log.warn("No handler is activated, DO NOTHING!") log.warn("No handler is activated, DO NOTHING!")
exitProcess(2) exitProcess(2)
} }
listOf(true, true) -> {/* 4 */ listOf(true, true) -> {/* 4 */
log.warn("args: ${args.size}, targetHandler: $targetHandler")
log.info("continue ...") log.info("continue ...")
} }
} }

@ -23,8 +23,17 @@ unpack
``` ```
abe unpack boot.img out abe unpack boot.img out
``` ```
pack pack
``` ```
abe pack out boot.img abe pack out boot.img
``` ```
properties: "out.file": the final output file
### something interesting in abe
a zsh script, parse the input command line parameters, for example,
if args are: "unpack file dir", the shell script will print 'gradle unpack --args="unpackInternal file dir"';
if args are "pack dir file", the shell script will print 'gradle pack --args="packInternal dir file"'.
if args are "unpack", the shell script will print "gradle unpack"
if args are "pack", the shell script will print "gradle pack"

@ -0,0 +1,44 @@
#!/bin/zsh
baseDir=${0:a:h}
export baseDir
set -e
# Parse command line arguments
if [[ $# -eq 0 ]]; then
echo "Usage: $0 <operation> [<file> <dir>]"
exit 1
fi
operation=$1
# Determine which operation to perform
case $operation in
"unpack")
if [[ $# -eq 3 ]]; then
file=`realpath $2`
dir=`realpath $3`
cd ${baseDir}/../
gradle unpack --args="unpackInternal $file $dir"
else
cd ${baseDir}/../
gradle unpack
fi
;;
"pack")
if [[ $# -eq 3 ]]; then
dir=`realpath $2`
file=`realpath $3`
cd ${baseDir}/../
gradle pack --args="packInternal $dir $file"
else
cd ${baseDir}/../
gradle pack
fi
;;
*)
echo "Invalid operation: $operation. Please choose 'unpack' or 'pack'."
exit 1
;;
esac
Loading…
Cancel
Save