diff --git a/README.md b/README.md
index e513281..93047d7 100644
--- a/README.md
+++ b/README.md
@@ -68,6 +68,7 @@ Please note that the boot.img MUST follows AOSP verified boot flow, either [Boot
| Device Model | Manufacturer | Compatible | Android Version | Note |
|--------------------------------|--------------|----------------------|--------------------------|------|
+| Pixel 3 (blueline) | Google | Y | 12 (spp2.210219.008,
2021)| |
| Pixel 3 (blueline) | Google | Y | 11 (RP1A.200720.009,
2020)| [more ...](doc/additional_tricks.md#pixel-3-blueline) |
| Pixel 3 (blueline) | Google | Y | Q preview (qpp2.190228.023,
2019)| [more ...](doc/additional_tricks.md#pixel-3-blueline) |
| Pixel XL (marlin) | HTC | Y | 9.0.0 (PPR2.180905.006,
Sep 2018)| [more ...](doc/additional_tricks.md#pixel-xl-marlin) |
@@ -79,31 +80,64 @@ Please note that the boot.img MUST follows AOSP verified boot flow, either [Boot
| X7 (PD1602_A_3.12.8) | VIVO | N | ? | [Issue 35](https://github.com/cfig/Android_boot_image_editor/issues/35) |
## more examples
+
+ working with recovery.img
-* recovery.img
+Please remember to clean the work directory first.
-If you are working with recovery.img, the steps are similar:
+```bash
+rm *.img
+cp recovery.img
+./gradlew unpack
+./gradlew pack
+```
- cp recovery.img
- ./gradlew unpack
- ./gradlew pack
+
+
+
+ working with vbmeta.img
-* vbmeta.img
```bash
+rm *.img
cp vbmeta.img
./gradlew unpack
./gradlew pack
```
-* boot.img and vbmeta.img
+
+
+
+ working with boot.img and vbmeta.img
+
+If your vbmeta.img contains hash of boot.img, you MUST update vbmeta image together.
+
```bash
+rm *.img
cp boot.img
cp vbmeta.img
./gradlew unpack
./gradlew pack
```
-Your boot.img.signed and vbmeta.img.signd will be updated together.
+Your boot.img.signed and vbmeta.img.signd will be updated together, then you can flash them to your device.
+
+
+
+
+ How to disable AVB verification
+
+The idea is to set flag=2 in main vbmeta.
+
+```bash
+rm *.img
+cp vbmeta.img
+./gradlew unpack
+vim -u NONE -N build/unzip_boot/vbmeta.avb.json -c ":19s/0/2/g" -c ":wq"
+./gradlew pack
+```
+Then flash vbmeta.img.signed to your device.
+
+
## boot.img layout
Read [layout](doc/layout.md) of Android boot.img and vendor\_boot.img.
diff --git a/bbootimg/src/main/kotlin/bootimg/v3/BootHeaderV3.kt b/bbootimg/src/main/kotlin/bootimg/v3/BootHeaderV3.kt
index aa007b3..4cabbee 100644
--- a/bbootimg/src/main/kotlin/bootimg/v3/BootHeaderV3.kt
+++ b/bbootimg/src/main/kotlin/bootimg/v3/BootHeaderV3.kt
@@ -7,22 +7,23 @@ import java.io.InputStream
@OptIn(ExperimentalUnsignedTypes::class)
class BootHeaderV3(
- var kernelSize: Int = 0,
- var ramdiskSize: Int = 0,
- var osVersion: String = "",
- var osPatchLevel: String = "",
- var headerSize: Int = 0,
- var headerVersion: Int = 0,
- var cmdline: String = ""
+ var kernelSize: Int = 0,
+ var ramdiskSize: Int = 0,
+ var osVersion: String = "",
+ var osPatchLevel: String = "",
+ var headerSize: Int = 0,
+ var headerVersion: Int = 0,
+ var cmdline: String = "",
+ var signatureSize: Int = 0
) {
@Throws(IllegalArgumentException::class)
constructor(iS: InputStream?) : this() {
if (iS == null) {
return
}
- log.warn("BootImgHeaderV3 constructor")
+ log.warn("BootImgHeaderV3/V4 constructor")
val info = Struct3(FORMAT_STRING).unpack(iS)
- assert(11 == info.size)
+ assert(12 == info.size)
if (info[0] != magic) {
throw IllegalArgumentException("stream doesn't look like Android Boot Image V3 Header")
}
@@ -39,22 +40,26 @@ class BootHeaderV3(
this.cmdline = info[10] as String
- assert(this.headerSize in intArrayOf(BOOT_IMAGE_HEADER_V3_SIZE))
+ this.signatureSize = (info[11] as UInt).toInt()
+
+ assert(this.headerSize in intArrayOf(BOOT_IMAGE_HEADER_V3_SIZE, BOOT_IMAGE_HEADER_V4_SIZE))
}
fun encode(): ByteArray {
return Struct3(FORMAT_STRING).pack(
- magic,
- kernelSize,
- ramdiskSize,
- (Common.packOsVersion(osVersion) shl 11) or Common.packOsPatchLevel(osPatchLevel),
- headerSize,
- 0,
- 0,
- 0,
- 0,
- headerVersion,
- cmdline)
+ magic,
+ kernelSize,
+ ramdiskSize,
+ (Common.packOsVersion(osVersion) shl 11) or Common.packOsPatchLevel(osPatchLevel),
+ headerSize,
+ 0,
+ 0,
+ 0,
+ 0,
+ headerVersion,
+ cmdline,
+ signatureSize
+ )
}
override fun toString(): String {
@@ -65,16 +70,18 @@ class BootHeaderV3(
internal val log = LoggerFactory.getLogger(BootHeaderV3::class.java)
const val magic = "ANDROID!"
const val FORMAT_STRING = "8s" + //"ANDROID!"
- "4I" + //kernel size, ramdisk size, os_version/patch, header size
- "4I" + //reserved
- "I" + //header version
- "1536s" //cmdline
+ "4I" + //kernel size, ramdisk size, os_version/patch, header size
+ "4I" + //reserved
+ "I" + //header version
+ "1536s" + //cmdline
+ "I" //signature size
private const val BOOT_IMAGE_HEADER_V3_SIZE = 1580
+ private const val BOOT_IMAGE_HEADER_V4_SIZE = 1584
const val pageSize: Int = 4096
init {
- assert(BOOT_IMAGE_HEADER_V3_SIZE == Struct3(FORMAT_STRING).calcSize()) {
- "internal error: expected size $BOOT_IMAGE_HEADER_V3_SIZE "
+ assert(BOOT_IMAGE_HEADER_V4_SIZE == Struct3(FORMAT_STRING).calcSize()) {
+ "internal error: expected size $BOOT_IMAGE_HEADER_V4_SIZE "
}
}
}
diff --git a/bbootimg/src/main/kotlin/bootimg/v3/BootV3.kt b/bbootimg/src/main/kotlin/bootimg/v3/BootV3.kt
index 506eb88..ffab8f8 100644
--- a/bbootimg/src/main/kotlin/bootimg/v3/BootV3.kt
+++ b/bbootimg/src/main/kotlin/bootimg/v3/BootV3.kt
@@ -41,6 +41,7 @@ data class BootV3(var info: MiscInfo = MiscInfo(),
ret.info.osVersion = header.osVersion
ret.info.osPatchLevel = header.osPatchLevel
ret.info.pageSize = BootHeaderV3.pageSize
+ ret.info.signatureSize = header.signatureSize
//kernel
ret.kernel.file = workDir + "kernel"
ret.kernel.size = header.kernelSize
@@ -65,7 +66,8 @@ data class BootV3(var info: MiscInfo = MiscInfo(),
var cmdline: String = "",
var osVersion: String = "",
var osPatchLevel: String = "",
- var imageSize: Long = 0
+ var imageSize: Long = 0,
+ var signatureSize: Int = 0
)
data class CommArgs(
diff --git a/bbootimg/src/main/kotlin/bootimg/v3/VendorBootHeader.kt b/bbootimg/src/main/kotlin/bootimg/v3/VendorBootHeader.kt
index bc4e741..0b06fa3 100644
--- a/bbootimg/src/main/kotlin/bootimg/v3/VendorBootHeader.kt
+++ b/bbootimg/src/main/kotlin/bootimg/v3/VendorBootHeader.kt
@@ -6,17 +6,21 @@ import java.io.InputStream
@OptIn(ExperimentalUnsignedTypes::class)
class VendorBootHeader(
- var headerVersion: Int = 0,
- var pageSize: Int = 0,
- var kernelLoadAddr: Long = 0,
- var ramdiskLoadAddr: Long = 0,
- var vndRamdiskSize: Int = 0,
- var cmdline: String = "",
- var tagsLoadAddr: Long = 0,
- var product: String = "",
- var headerSize: Int = 0,
- var dtbSize: Int = 0,
- var dtbLoadAddr: Long = 0
+ var headerVersion: Int = 0,
+ var pageSize: Int = 0,
+ var kernelLoadAddr: Long = 0,
+ var ramdiskLoadAddr: Long = 0,
+ var vndRamdiskSize: Int = 0,
+ var cmdline: String = "",
+ var tagsLoadAddr: Long = 0,
+ var product: String = "",
+ var headerSize: Int = 0,
+ var dtbSize: Int = 0,
+ var dtbLoadAddr: Long = 0,
+ var vrtSize: Int = 0,
+ var vrtEntryNum: Int = 0,
+ var vrtEntrySize: Int = 0,
+ var bootconfigSize: Int = 0
) {
@Throws(IllegalArgumentException::class)
constructor(iS: InputStream?) : this() {
@@ -25,7 +29,7 @@ class VendorBootHeader(
}
log.warn("VendorBootHeader constructor")
val info = Struct3(FORMAT_STRING).unpack(iS)
- assert(12 == info.size)
+ assert(16 == info.size)
if (info[0] != magic) {
throw IllegalArgumentException("stream doesn't look like Android Vendor Boot Image")
}
@@ -40,35 +44,45 @@ class VendorBootHeader(
this.headerSize = (info[9] as UInt).toInt()
this.dtbSize = (info[10] as UInt).toInt()
this.dtbLoadAddr = (info[11] as ULong).toLong()
+ this.vrtSize = (info[12] as UInt).toInt()
+ this.vrtEntryNum = (info[13] as UInt).toInt()
+ this.vrtEntrySize = (info[14] as UInt).toInt()
+ this.bootconfigSize = (info[15] as UInt).toInt()
- if (this.headerSize !in arrayOf(VENDOR_BOOT_IMAGE_HEADER_V3_SIZE)) {
+ if (this.headerSize !in arrayOf(VENDOR_BOOT_IMAGE_HEADER_V3_SIZE, VENDOR_BOOT_IMAGE_HEADER_V4_SIZE)) {
throw IllegalArgumentException("header size " + this.headerSize + " invalid")
}
- if (this.headerVersion != 3) {
+ if (this.headerVersion !in 3..4) {
throw IllegalArgumentException("header version " + this.headerVersion + " invalid")
}
}
fun encode(): ByteArray {
return Struct3(FORMAT_STRING).pack(
- magic,
- headerVersion,
- pageSize,
- kernelLoadAddr,
- ramdiskLoadAddr,
- vndRamdiskSize,
- cmdline,
- tagsLoadAddr,
- product,
- headerSize,
- dtbSize,
- dtbLoadAddr)
+ magic,
+ headerVersion,
+ pageSize,
+ kernelLoadAddr,
+ ramdiskLoadAddr,
+ vndRamdiskSize,
+ cmdline,
+ tagsLoadAddr,
+ product,
+ headerSize,
+ dtbSize,
+ dtbLoadAddr,
+ vrtSize,
+ vrtEntryNum,
+ vrtEntrySize,
+ bootconfigSize
+ )
}
companion object {
private val log = LoggerFactory.getLogger(VendorBootHeader::class.java)
const val magic = "VNDRBOOT"
const val VENDOR_BOOT_IMAGE_HEADER_V3_SIZE = 2112
+ const val VENDOR_BOOT_IMAGE_HEADER_V4_SIZE = 2128
const val FORMAT_STRING = "8s" + //magic
"I" + //header version
"I" + //page size
@@ -80,13 +94,20 @@ class VendorBootHeader(
"16s" + //product name
"I" + //header size
"I" + //dtb size
- "Q" //dtb physical load addr
+ "Q" + //dtb physical load addr
+ "I" + //[v4] vendor ramdisk table size
+ "I" + //[v4] vendor ramdisk table entry num
+ "I" + //[v4] vendor ramdisk table entry size
+ "I" //[v4] bootconfig size
+
init {
- assert(Struct3(FORMAT_STRING).calcSize() == VENDOR_BOOT_IMAGE_HEADER_V3_SIZE)
+ assert(Struct3(FORMAT_STRING).calcSize() == VENDOR_BOOT_IMAGE_HEADER_V4_SIZE)
}
}
override fun toString(): String {
- return "VendorBootHeader(headerVersion=$headerVersion, pageSize=$pageSize, kernelLoadAddr=$kernelLoadAddr, ramdiskLoadAddr=$ramdiskLoadAddr, vndRamdiskSize=$vndRamdiskSize, cmdline='$cmdline', tagsLoadAddr=$tagsLoadAddr, product='$product', headerSize=$headerSize, dtbSize=$dtbSize, dtbLoadAddr=$dtbLoadAddr)"
+ return "VendorBootHeader(headerVersion=$headerVersion, pageSize=$pageSize, kernelLoadAddr=$kernelLoadAddr, ramdiskLoadAddr=$ramdiskLoadAddr, vndRamdiskSize=$vndRamdiskSize, cmdline='$cmdline', tagsLoadAddr=$tagsLoadAddr, product='$product', headerSize=$headerSize, dtbSize=$dtbSize, dtbLoadAddr=$dtbLoadAddr, vrtSize=$vrtSize, vrtEntryNum=$vrtEntryNum, vrtEntrySize=$vrtEntrySize, bootconfigSize=$bootconfigSize)"
}
+
+
}
diff --git a/bbootimg/src/main/kotlin/packable/BootImgParser.kt b/bbootimg/src/main/kotlin/packable/BootImgParser.kt
index bbeedf4..876ed09 100644
--- a/bbootimg/src/main/kotlin/packable/BootImgParser.kt
+++ b/bbootimg/src/main/kotlin/packable/BootImgParser.kt
@@ -27,21 +27,20 @@ class BootImgParser() : IPackable {
try {
val hv = probeHeaderVersion(fileName)
log.info("header version $hv")
- if (hv == 3) {
- val b3 = BootV3
+ if (hv in 0..2) {
+ val b2 = BootV2
.parse(fileName)
.extractImages()
.extractVBMeta()
.printSummary()
- log.debug(b3.toString())
- return
+ log.debug(b2.toString())
} else {
- val b2 = BootV2
+ val b3 = BootV3
.parse(fileName)
.extractImages()
.extractVBMeta()
.printSummary()
- log.debug(b2.toString())
+ log.debug(b3.toString())
}
} catch (e: IllegalArgumentException) {
log.error(e.message)
diff --git a/doc/layout.md b/doc/layout.md
index 797d289..2423b9a 100644
--- a/doc/layout.md
+++ b/doc/layout.md
@@ -1,23 +1,20 @@
# layout of [vendor\_]boot.img
-## Image Content Index
+[1. boot.img v0-v2](#1-bootimg-v0-v2)
-[1 header part](#1-header-part)
- - [1.1 boot.img v0-v2](#11-bootimg-header-v0-v2)
- - [1.2 boot.img v3](#12-bootimg-header-v3)
- - [1.3 vendor\_boot.img v3](#13-vendor_bootimg-header-v3)
+[2. boot.img v3-v4](#2-bootimg-v3-v4)
-[2 data part](#2-data-part)
+[3. vendor_boot.img v3-v4](#3-vendor_bootimg-v3-v4)
-[3 signature part](#3-signature-part)
+[4. signature part](#4-signature-part)
- - [3.1 Boot Image Signature](#31-boot-image-signature-vboot-10)
+ - [4.1 Boot Image Signature](#41-boot-image-signature-vboot-10)
- - [3.2 AVB Footer](#32-avb-footer-vboot-20)
+ - [4.2 AVB Footer](#42-avb-footer-vboot-20)
-## 1. header part
-### 1.1 boot.img header v0-v2
-value at 0x28 is 0x00,0x01,0x02
+## 1. boot.img v0-v2
+### header
+Value at 0x28 is one of {0x00,0x01,0x02,0x03,0x04}, this filed should be read first to identify header version.
item size in bytes position
+-----------------------------------------------------------+ --> 0
@@ -38,7 +35,7 @@ value at 0x28 is 0x00,0x01,0x02
| | 4 |
|--------------------------------+--------------------------| --> 36
| | 4 |
- |--------------------------------+--------------------------| --> 40
+ |--------------------------------+--------------------------| --> 40 (0x28)
| | 4 (value in [0,1,2]) |
|--------------------------------+--------------------------| --> 44
| | 4 |
@@ -66,7 +63,41 @@ value at 0x28 is 0x00,0x01,0x02
| | - header_size) |
+--------------------------------+--------------------------+ --> pagesize
-### 1.2 boot.img header v3
+### data
+
+ +-----------------------------------------------------------+ --> pagesize
+ | | kernel length |
+ |--------------------------------+--------------------------|
+ | | min(n * page_size - len) |
+ +-----------------------------------------------------------+
+
+ +-----------------------------------------------------------+
+ | | ramdisk length |
+ |--------------------------------+--------------------------|
+ | | min(n * page_size - len) |
+ +-----------------------------------------------------------+
+
+ +-----------------------------------------------------------+
+ | | second bootloader length |
+ |--------------------------------+--------------------------|
+ | | min(n * page_size - len) |
+ +-----------------------------------------------------------+
+
+ +-----------------------------------------------------------+
+ | [v1] | recovery dtbo length |
+ |--------------------------------+--------------------------|
+ | [v1] | min(n * page_size - len) |
+ +-----------------------------------------------------------+
+
+ +-----------------------------------------------------------+
+ | [v2] | dtb length |
+ |--------------------------------+--------------------------|
+ | [v2] | min(n * page_size - len) |
+ +-----------------------------------------------------------+ --> end of data part
+
+## 2. boot.img v3-v4
+
+### header
item size in bytes position
+-----------------------------------------------------------+ --> 0
@@ -81,16 +112,37 @@ value at 0x28 is 0x00,0x01,0x02
| | 4 |
|--------------------------------+--------------------------| --> 24
| | 4 * 4 |
- |--------------------------------+--------------------------| --> 40
- | | 4 (value=3) |
+ |--------------------------------+--------------------------| --> 40 (0x28)
+ | | 4 (value in [3|4]) |
|--------------------------------+--------------------------| --> 44
| | 1024+512=1536 |
- |--------------------------------+--------------------------| --> 1580
+ |--------------------------------+--------------------------| --> 44
+ | (v4 only) | 4 |
+ |--------------------------------+--------------------------| --> 1584
| | min(n * page_size |
| | - header_size) |
+--------------------------------+--------------------------+ --> pagesize=4096
-### 1.3 vendor\_boot.img header v3
+### data
+
+```
+ +-----------------------------------------------------------+ --> pagesize
+ | | kernel length |
+ +-----------------------------------------------------------+
+ | | ramdisk length |
+ +-----------------------------------------------------------+
+ | (v4 only) | boot signature length |
+ +--------------------------------+--------------------------+
+
+ padding calculation:
+ | | min(n * page_size - len) |
+```
+
+
+
+## 3. vendor\_boot.img v3-v4
+
+### header
item size in bytes position
+-----------------------------------------------------------+ --> 0
@@ -118,45 +170,37 @@ value at 0x28 is 0x00,0x01,0x02
|--------------------------------+--------------------------| --> 2104
| | 8 |
|--------------------------------+--------------------------| --> 2112
+ | | 4 (v4 only) |
+ |--------------------------------+--------------------------| --> 2116
+ || 4 (v4 only) |
+ |--------------------------------+--------------------------| --> 2120
+ | 2124
+ | | 4 (v4 only) |
+ |--------------------------------+--------------------------| --> 2128
| | min(n * page_size |
| | - header_size) |
+--------------------------------+--------------------------+ --> pagesize
-## 2. data part
+### data
+```
+-----------------------------------------------------------+ --> pagesize
- | | kernel length |
- |--------------------------------+--------------------------|
- | | min(n * page_size - len) |
- +-----------------------------------------------------------+
-
- +-----------------------------------------------------------+
- | | ramdisk length |
- |--------------------------------+--------------------------|
- | | min(n * page_size - len) |
- +-----------------------------------------------------------+
-
- +-----------------------------------------------------------+
- | | second bootloader length |
- |--------------------------------+--------------------------|
- | | min(n * page_size - len) |
+ | | padded len |
+ +--------------------------------+--------------------------+
+ | | padded len |
+ +--------------------------------+--------------------------+
+ | | padded len |
+-----------------------------------------------------------+
+ | | padded len |
+ +--------------------------------+--------------------------+
+```
- +-----------------------------------------------------------+
- | [v1] | recovery dtbo length |
- |--------------------------------+--------------------------|
- | [v1] | min(n * page_size - len) |
- +-----------------------------------------------------------+
- +-----------------------------------------------------------+
- | [v2] | dtb length |
- |--------------------------------+--------------------------|
- | [v2] | min(n * page_size - len) |
- +-----------------------------------------------------------+ --> end of data part
-## 3. signature part
+## 4. signature part
-### 3.1 Boot Image Signature (VBoot 1.0)
+### 4.1 Boot Image Signature (VBoot 1.0)
+--------------------------------+--------------------------+ --> end of data part
| | signature length |
@@ -164,7 +208,7 @@ value at 0x28 is 0x00,0x01,0x02
| | defined by boot_signer |
+--------------------------------+--------------------------+
-### 3.2 AVB Footer (VBoot 2.0)
+### 4.2 AVB Footer (VBoot 2.0)
item size in bytes position
+------+--------------------------------+-------------------------+ --> end of data part (say locaton +0)