change recoveryDtboOffset calculation in accordance with AOSP

although google's algorithm is not good enough
pull/31/head
cfig 6 years ago
parent 79b84baf68
commit af7de300d2
No known key found for this signature in database
GPG Key ID: B104C307F0FDABB7

11
avb/Makefile vendored

@ -1,11 +0,0 @@
t:
cp boot.img boot.img.orig
./avbtool add_hash_footer \
--image boot.img \
--partition_size 33554432 \
--partition_name boot \
--algorithm SHA256_RSA4096 \
--key avb_test_data/testkey_rsa4096.pem
./avbtool info_image --image boot.img
./avbtool erase_footer --image boot.img
-./avbtool info_image --image boot.img

@ -11,6 +11,7 @@ import cfig.Helper.Companion.paddingWith
import cfig.io.Struct3
import com.fasterxml.jackson.databind.ObjectMapper
import org.apache.commons.codec.binary.Hex
import org.junit.Assert
import org.slf4j.LoggerFactory
import java.io.File
import java.io.FileInputStream
@ -63,7 +64,7 @@ class Avb {
val imgPaddingNeeded = Helper.round_to_multiple(newImageSize, BLOCK_SIZE) - newImageSize
// + vbmeta + padding
val vbmetaOffset = File(image_file).length()
val vbmetaOffset = newImageSize + imgPaddingNeeded
val vbmetaBlobWithPadding = vbmetaBlob.paddingWith(BLOCK_SIZE.toUInt())
// + DONT_CARE chunk
@ -92,7 +93,7 @@ class Avb {
log.info("4/4 Appending AVB footer (${footerBlobWithPadding.size} bytes)...")
fos.write(footerBlobWithPadding)
}
Assert.assertEquals("generated file size mismatch", partition_size, File(image_file).length())
log.info("addHashFooter($image_file) done.")
}

@ -77,6 +77,30 @@ data class Header(
this.required_libavb_version_minor = maxOf(required_libavb_version_minor, minor)
}
//toplevel flags
enum class AvbVBMetaImageFlags(val inFlags: Int) {
AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED(1),
AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED(2 shl 1)
}
//verify flags
enum class AvbSlotVerifyFlags(val inFlags: Int) {
AVB_SLOT_VERIFY_FLAGS_NONE(0),
AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR(1),
AVB_SLOT_VERIFY_FLAGS_RESTART_CAUSED_BY_HASHTREE_CORRUPTION(2),
AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION(4)
}
//hash descriptor flags
enum class HashDescriptorFlags(val inFlags: Int) {
AVB_HASH_DESCRIPTOR_FLAGS_DO_NOT_USE_AB(1)
}
//hash tree descriptor flags
enum class HashTreeDescriptorFlags(val inFlags: Int) {
AVB_HASHTREE_DESCRIPTOR_FLAGS_DO_NOT_USE_AB(1)
}
companion object {
private const val magic: String = "AVB0"
const val SIZE = 256

@ -1,5 +1,6 @@
package avb.desc
import avb.blob.Header
import cfig.Helper
import cfig.io.Struct3
import org.apache.commons.codec.binary.Hex
@ -24,7 +25,7 @@ class HashDescriptor(var flags: UInt = 0U,
var flagsInterpretation: String = ""
get() {
var ret = ""
if (this.flags and AVB_HASH_DESCRIPTOR_FLAGS_DO_NOT_USE_AB == 1U) {
if (this.flags and Header.HashDescriptorFlags.AVB_HASH_DESCRIPTOR_FLAGS_DO_NOT_USE_AB.inFlags.toUInt() == 1U) {
ret += "1:no-A/B system"
} else {
ret += "0:A/B system"
@ -124,7 +125,6 @@ class HashDescriptor(var flags: UInt = 0U,
private const val SIZE = 72 + RESERVED
private const val FORMAT_STRING = "!3Q32s4L${RESERVED}x"
private val log = LoggerFactory.getLogger(HashDescriptor::class.java)
private const val AVB_HASH_DESCRIPTOR_FLAGS_DO_NOT_USE_AB = 1U
}
override fun toString(): String {

@ -1,5 +1,6 @@
package avb.desc
import avb.blob.Header
import cfig.Helper
import cfig.io.Struct3
import java.io.InputStream
@ -24,7 +25,7 @@ class HashTreeDescriptor(
var flagsInterpretation: String = ""
get() {
var ret = ""
if (this.flags and AVB_HASHTREE_DESCRIPTOR_FLAGS_DO_NOT_USE_AB == 1U) {
if (this.flags and Header.HashTreeDescriptorFlags.AVB_HASHTREE_DESCRIPTOR_FLAGS_DO_NOT_USE_AB.inFlags.toUInt() == 1U) {
ret += "1:no-A/B system"
} else {
ret += "0:A/B system"
@ -97,6 +98,5 @@ class HashTreeDescriptor(
private const val RESERVED = 60L
private const val SIZE = 120 + RESERVED
private const val FORMAT_STRING = "!2QL3Q3L2Q32s4L${RESERVED}x"
private const val AVB_HASHTREE_DESCRIPTOR_FLAGS_DO_NOT_USE_AB = 1U
}
}

@ -12,6 +12,7 @@ import java.nio.ByteBuffer
import java.nio.ByteOrder
import java.security.MessageDigest
import java.util.regex.Pattern
import kotlin.math.pow
@ExperimentalUnsignedTypes
open class BootImgHeader(
@ -178,6 +179,13 @@ open class BootImgHeader(
return md.digest()
}
private fun get_recovery_dtbo_offset(): UInt {
return Helper.round_to_multiple(this.headerSize, pageSize) +
Helper.round_to_multiple(this.kernelLength, pageSize) +
Helper.round_to_multiple(this.ramdiskLength, pageSize) +
Helper.round_to_multiple(this.secondBootloaderLength, pageSize)
}
private fun refresh() {
val param = ParamConfig()
//refresh kernel size
@ -205,14 +213,15 @@ open class BootImgHeader(
this.recoveryDtboOffset = 0U
} else {
this.recoveryDtboLength = File(param.dtbo!!).length().toUInt()
this.recoveryDtboOffset = get_recovery_dtbo_offset().toULong()
log.warn("using fake recoveryDtboOffset $recoveryDtboOffset (as is in AOSP avbtool)")
}
//refresh recovery dtbo size
//refresh dtb size
if (0U == this.dtbLength) {
param.dtb = null
} else {
this.dtbLength = File(param.dtb!!).length().toUInt()
}
//refresh image hash
val imageId = when (this.headerVersion) {
0U -> {
@ -233,6 +242,11 @@ open class BootImgHeader(
fun encode(): ByteArray {
this.refresh()
val pageSizeChoices: MutableSet<Long> = mutableSetOf<Long>().apply {
(11..14).forEach { add(2.0.pow(it).toLong()) }
}
Assert.assertTrue("invalid parameter [pageSize=$pageSize], (choose from $pageSizeChoices)",
pageSizeChoices.contains(pageSize.toLong()))
return Struct3(FORMAT_STRING).pack(
"ANDROID!",
//10I

@ -150,7 +150,7 @@ class Packer {
//write
FileOutputStream(cfg.info.output + ".clear", false).use { fos ->
fos.write(encodedHeader)
fos.write(ByteArray(info2.pageSize.toInt() - encodedHeader.size))
fos.write(ByteArray((Helper.round_to_multiple(encodedHeader.size.toUInt(), info2.pageSize) - encodedHeader.size.toUInt()).toInt()))
}
writeData(info2, cfg.info.output)

@ -9,6 +9,10 @@ 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> {

@ -12,6 +12,10 @@ 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)

@ -6,4 +6,7 @@ interface IPackable {
}
fun unpack(fileName: String = "dtbo.img")
fun pack(fileName: String = "dtbo.img")
fun flash(fileName: String = "dtbo.img") {
}
}

@ -4,6 +4,10 @@ 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$")
}

@ -31,30 +31,8 @@ if (parseGradleVersion(gradle.gradleVersion) < 5) {
logger.info("Gradle Version {}", gradle.gradleVersion)
}
def workdir = 'build/unzip_boot'
def GROUP_ANDROID = "Android"
project.ext.rootWorkDir = new File(workdir).getAbsolutePath()
String activeImg = "boot.img"
String activePath = "/boot"
if (new File("boot.img").exists()) {
activeImg = "boot.img"
activePath = "/boot"
} else if (new File("recovery.img").exists()) {
activeImg = "recovery.img"
activePath = "/recovery"
} else if (new File("recovery-two-step.img").exists()) {
activeImg = "recovery-two-step.img"
activePath = "/boot"
} else if (new File("vbmeta.img").exists()) {
activeImg = "vbmeta.img"
activePath = "/vbmeta"
}
project.ext.outClearIMg = new File(String.format("%s.clear", activeImg)).getAbsolutePath()
project.ext.mkbootimgBin = new File("tools/mkbootimg").getAbsolutePath()
project.ext.mkbootfsBin = new File("mkbootfs/build/exe/mkbootfs/mkbootfs").getAbsolutePath()
project.ext.avbtool = new File("avb/avbtool").getAbsolutePath()
project.ext.bootSigner = new File("boot_signer/build/libs/boot_signer.jar").getAbsolutePath()
logger.warn("Active image target: " + activeImg)
// ----------------------------------------------------------------------------
// tasks
@ -119,39 +97,6 @@ void Run(String inCmd, String inWorkdir = null) {
Run(Arrays.asList(inCmd.split()), inWorkdir);
}
void updateBootImage(String activeImg) {
String flashTarget = null;
switch (activeImg) {
case "boot.img":
case "recovery-two-step.img":
flashTarget = "/dev/block/by-name/boot";
break;
case "recovery.img":
flashTarget = "/dev/block/by-name/recovery";
break;
case "vbmeta.img":
flashTarget = "/dev/block/by-name/vbmeta";
if (!new File(activeImg + ".signed").exists()) {
return;
}
break;
}
Run("adb root")
Run("adb push " + activeImg + ".signed /cache/")
List<String> cmd2 = ["adb", "shell", "dd if=/cache/" + activeImg + ".signed of=" + flashTarget]
Run(cmd2)
cmd2 = ["adb", "shell", "rm -f /cache/" + activeImg + ".signed"];
Run(cmd2)
}
task flash {
group GROUP_ANDROID
doLast {
updateBootImage(activeImg)
updateBootImage("vbmeta.img")
}
}
void rebootRecovery() {
Run("adb reboot recovery")
}
@ -179,6 +124,14 @@ task pack(type: JavaExec, dependsOn: ["bbootimg:jar", "mkbootfs:mkbootfsExecutab
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"
}
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)

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python2
# Copyright 2015, The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");

Loading…
Cancel
Save