Merge "Allow --disable-verification when top-level vbmeta is in 'boot'" am: e7180a796c am: 8665bb749f am: e318d9d5f6
am: 27991c33be
Change-Id: Ibc113d3f2e00aa23df4a35dbf2ecc073bfe04c75
diff --git a/fastboot/Android.bp b/fastboot/Android.bp
index 546bce2..f452a64 100644
--- a/fastboot/Android.bp
+++ b/fastboot/Android.bp
@@ -189,7 +189,11 @@
// will violate ODR.
shared_libs: [],
- header_libs: ["bootimg_headers"],
+ header_libs: [
+ "avb_headers",
+ "bootimg_headers",
+ ],
+
static_libs: [
"libziparchive",
"libsparse",
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index a7fc628..2fe3b1a 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -51,6 +51,7 @@
#include <utility>
#include <vector>
+#include <android-base/endian.h>
#include <android-base/file.h>
#include <android-base/macros.h>
#include <android-base/parseint.h>
@@ -59,6 +60,7 @@
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
#include <build/version.h>
+#include <libavb/libavb.h>
#include <liblp/liblp.h>
#include <platform_tools_version.h>
#include <sparse/sparse.h>
@@ -919,33 +921,50 @@
return load_buf_fd(fd.release(), buf);
}
-static void rewrite_vbmeta_buffer(struct fastboot_buffer* buf) {
+static void rewrite_vbmeta_buffer(struct fastboot_buffer* buf, bool vbmeta_in_boot) {
// Buffer needs to be at least the size of the VBMeta struct which
// is 256 bytes.
if (buf->sz < 256) {
return;
}
- int fd = make_temporary_fd("vbmeta rewriting");
-
std::string data;
if (!android::base::ReadFdToString(buf->fd, &data)) {
die("Failed reading from vbmeta");
}
+ uint64_t vbmeta_offset = 0;
+ if (vbmeta_in_boot) {
+ // Tries to locate top-level vbmeta from boot.img footer.
+ uint64_t footer_offset = buf->sz - AVB_FOOTER_SIZE;
+ if (0 != data.compare(footer_offset, AVB_FOOTER_MAGIC_LEN, AVB_FOOTER_MAGIC)) {
+ die("Failed to find AVB_FOOTER at offset: %" PRId64, footer_offset);
+ }
+ const AvbFooter* footer = reinterpret_cast<const AvbFooter*>(data.c_str() + footer_offset);
+ vbmeta_offset = be64toh(footer->vbmeta_offset);
+ }
+ // Ensures there is AVB_MAGIC at vbmeta_offset.
+ if (0 != data.compare(vbmeta_offset, AVB_MAGIC_LEN, AVB_MAGIC)) {
+ die("Failed to find AVB_MAGIC at offset: %" PRId64, vbmeta_offset);
+ }
+
+ fprintf(stderr, "Rewriting vbmeta struct at offset: %" PRId64 "\n", vbmeta_offset);
+
// There's a 32-bit big endian |flags| field at offset 120 where
// bit 0 corresponds to disable-verity and bit 1 corresponds to
// disable-verification.
//
// See external/avb/libavb/avb_vbmeta_image.h for the layout of
// the VBMeta struct.
+ uint64_t flags_offset = 123 + vbmeta_offset;
if (g_disable_verity) {
- data[123] |= 0x01;
+ data[flags_offset] |= 0x01;
}
if (g_disable_verification) {
- data[123] |= 0x02;
+ data[flags_offset] |= 0x02;
}
+ int fd = make_temporary_fd("vbmeta rewriting");
if (!android::base::WriteStringToFd(data, fd)) {
die("Failed writing to modified vbmeta");
}
@@ -954,14 +973,25 @@
lseek(fd, 0, SEEK_SET);
}
+static bool has_vbmeta_partition() {
+ std::string partition_type;
+ return fb->GetVar("partition-type:vbmeta", &partition_type) == fastboot::SUCCESS ||
+ fb->GetVar("partition-type:vbmeta_a", &partition_type) == fastboot::SUCCESS ||
+ fb->GetVar("partition-type:vbmeta_b", &partition_type) == fastboot::SUCCESS;
+}
+
static void flash_buf(const std::string& partition, struct fastboot_buffer *buf)
{
sparse_file** s;
// Rewrite vbmeta if that's what we're flashing and modification has been requested.
- if ((g_disable_verity || g_disable_verification) &&
- (partition == "vbmeta" || partition == "vbmeta_a" || partition == "vbmeta_b")) {
- rewrite_vbmeta_buffer(buf);
+ if (g_disable_verity || g_disable_verification) {
+ if (partition == "vbmeta" || partition == "vbmeta_a" || partition == "vbmeta_b") {
+ rewrite_vbmeta_buffer(buf, false /* vbmeta_in_boot */);
+ } else if (!has_vbmeta_partition() &&
+ (partition == "boot" || partition == "boot_a" || partition == "boot_b")) {
+ rewrite_vbmeta_buffer(buf, true /* vbmeta_in_boot */ );
+ }
}
switch (buf->type) {