Snap for 8414339 from 04bc97d69c45bc0d46cc282705afed36191b96d9 to tm-qpr1-release

Change-Id: Id4262d70a34403480e8fa1db329590eea28fc255
diff --git a/Android.bp b/Android.bp
index cc3cd09..cace5b6 100644
--- a/Android.bp
+++ b/Android.bp
@@ -902,7 +902,6 @@
         "update_engine.conf",
     ],
     static_libs: [
-        "libcurl",
         "libgmock",
         "libpayload_generator",
     ],
@@ -912,6 +911,82 @@
 // ========================================================
 // Main unittest file.
 cc_test {
+    name: "update_engine_http_unittests",
+    defaults: [
+        "ue_defaults",
+        "liblz4diff_defaults",
+        "update_metadata-protos_exports",
+    ],
+    require_root: true,
+    static_libs: [
+        "libbase",
+        "libbrillo-test-helpers",
+        "libchrome_test_helpers",
+        "libcurl",
+        "libcutils",
+        "libdm",
+        "libgmock",
+        "libz",
+    ],
+    shared_libs: [
+        "libssl",
+        "libcrypto",
+        "libziparchive",
+        "liblog",
+    ],
+
+    data: [
+        ":test_http_server",
+        ":test_subprocess",
+        ":ue_unittest_keys",
+        "otacerts.zip",
+        "unittest_key.pem",
+        "unittest_key2.pem",
+        "unittest_key_RSA4096.pem",
+        "unittest_key_EC.pem",
+    ],
+
+    // We cannot use the default generated AndroidTest.xml because of the use of helper modules
+    // (i.e. test_http_server, test_subprocess, ue_unittest_delta_generator).
+    // test_config: "test_config.xml",
+    test_suites: ["device-tests"],
+
+    srcs: [
+        "aosp/platform_constants_android.cc",
+        "certificate_checker.cc",
+        "common/action_processor.cc",
+        "common/boot_control_stub.cc",
+        "common/error_code_utils.cc",
+        "common/file_fetcher.cc",
+        "common/hash_calculator.cc",
+        "common/http_fetcher.cc",
+        "common/multi_range_http_fetcher.cc",
+        "common/http_common.cc",
+        "common/subprocess.cc",
+        "common/test_utils.cc",
+        "common/utils.cc",
+        "common/proxy_resolver.cc",
+        "libcurl_http_fetcher.cc",
+        "payload_consumer/certificate_parser_android.cc",
+        "payload_consumer/payload_verifier.cc",
+        "payload_generator/payload_signer.cc",
+        "update_status_utils.cc",
+
+        "certificate_checker_unittest.cc",
+        "common/http_fetcher_unittest.cc",
+        "common/mock_http_fetcher.cc",
+        "common/proxy_resolver_unittest.cc",
+        "common/subprocess_unittest.cc",
+        "libcurl_http_fetcher_unittest.cc",
+        "payload_consumer/certificate_parser_android_unittest.cc",
+        "update_status_utils_unittest.cc",
+    ],
+}
+
+// update_engine_unittests (type: executable)
+// ========================================================
+// Main unittest file.
+cc_test {
     name: "update_engine_unittests",
     defaults: [
         "ue_defaults",
@@ -933,8 +1008,6 @@
     ],
 
     data: [
-        ":test_http_server",
-        ":test_subprocess",
         ":ue_unittest_delta_generator",
         ":ue_unittest_disk_imgs",
         ":ue_unittest_erofs_imgs",
@@ -966,17 +1039,11 @@
         "aosp/dynamic_partition_control_android_unittest.cc",
         "aosp/update_attempter_android_integration_test.cc",
         "aosp/update_attempter_android_unittest.cc",
-        "certificate_checker_unittest.cc",
-        "common/http_fetcher_unittest.cc",
-        "common/proxy_resolver_unittest.cc",
-        "common/subprocess_unittest.cc",
         "common/utils_unittest.cc",
         "download_action_android_unittest.cc",
-        "libcurl_http_fetcher_unittest.cc",
         "payload_consumer/bzip_extent_writer_unittest.cc",
         "payload_consumer/cached_file_descriptor_unittest.cc",
         "payload_consumer/cow_writer_file_descriptor_unittest.cc",
-        "payload_consumer/certificate_parser_android_unittest.cc",
         "payload_consumer/delta_performer_integration_test.cc",
         "payload_consumer/delta_performer_unittest.cc",
         "payload_consumer/extent_reader_unittest.cc",
@@ -994,7 +1061,6 @@
         "payload_consumer/snapshot_extent_writer_unittest.cc",
         "payload_consumer/vabc_partition_writer_unittest.cc",
         "payload_consumer/xor_extent_writer_unittest.cc",
-        "update_status_utils_unittest.cc",
     ],
 }
 
@@ -1082,3 +1148,25 @@
         export_proto_headers: true,
     },
 }
+
+cc_binary_host {
+    name: "ota_extractor",
+    defaults: [
+        "ue_defaults",
+        "libpayload_consumer_exports",
+    ],
+    srcs: [
+        "aosp/ota_extractor.cc",
+    ],
+    static_libs: [
+        "liblog",
+        "libbrotli",
+        "libbase",
+        "libpayload_consumer",
+        "libpayload_extent_ranges",
+        "libpayload_extent_utils",
+        "libz",
+        "libgflags",
+        "update_metadata-protos",
+    ],
+}
diff --git a/TEST_MAPPING b/TEST_MAPPING
new file mode 100644
index 0000000..3a9a238
--- /dev/null
+++ b/TEST_MAPPING
@@ -0,0 +1,10 @@
+{
+  "presubmit": [
+    {
+      "name": "update_engine_unittests"
+    },
+    {
+      "name": "update_engine_http_unittests"
+    }
+  ]
+}
diff --git a/aosp/dynamic_partition_control_android.cc b/aosp/dynamic_partition_control_android.cc
index 6d33a09..e39e7bc 100644
--- a/aosp/dynamic_partition_control_android.cc
+++ b/aosp/dynamic_partition_control_android.cc
@@ -465,6 +465,9 @@
   if (!SetTargetBuildVars(manifest)) {
     return false;
   }
+  for (auto& list : dynamic_partition_list_) {
+    list.clear();
+  }
 
   // Although the current build supports dynamic partitions, the given payload
   // doesn't use it for target partitions. This could happen when applying a
@@ -1280,6 +1283,9 @@
   if (!GetVirtualAbFeatureFlag().IsEnabled()) {
     return true;
   }
+  for (auto& list : dynamic_partition_list_) {
+    list.clear();
+  }
 
   LOG(INFO) << __func__ << " resetting update state and deleting snapshots.";
   TEST_AND_RETURN_FALSE(prefs != nullptr);
diff --git a/aosp/dynamic_partition_control_android.h b/aosp/dynamic_partition_control_android.h
index cebca07..457ef18 100644
--- a/aosp/dynamic_partition_control_android.h
+++ b/aosp/dynamic_partition_control_android.h
@@ -21,7 +21,7 @@
 #include <set>
 #include <string>
 #include <string_view>
-#include <vector>
+#include <array>
 
 #include <base/files/file_util.h>
 #include <libsnapshot/auto_device.h>
@@ -348,7 +348,9 @@
 
   uint32_t source_slot_ = UINT32_MAX;
   uint32_t target_slot_ = UINT32_MAX;
-  std::vector<std::vector<std::string>> dynamic_partition_list_{2UL};
+  // We assume that there's only 2 slots, A and B. This assumption is unlikely
+  // to change in the future. And certaintly won't change at runtime.
+  std::array<std::vector<std::string>, 2> dynamic_partition_list_{};
 
   DISALLOW_COPY_AND_ASSIGN(DynamicPartitionControlAndroid);
 };
diff --git a/aosp/ota_extractor.cc b/aosp/ota_extractor.cc
new file mode 100644
index 0000000..80bb74b
--- /dev/null
+++ b/aosp/ota_extractor.cc
@@ -0,0 +1,181 @@
+//
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <fcntl.h>
+
+#include <cstdint>
+#include <cstdio>
+#include <iterator>
+#include <memory>
+
+#include <sys/mman.h>
+#include <sys/stat.h>
+
+#include <android-base/strings.h>
+#include <base/files/file_path.h>
+#include <gflags/gflags.h>
+#include <unistd.h>
+
+#include "update_engine/common/utils.h"
+#include "update_engine/common/hash_calculator.h"
+#include "update_engine/payload_consumer/file_descriptor.h"
+#include "update_engine/payload_consumer/install_operation_executor.h"
+#include "update_engine/payload_consumer/payload_metadata.h"
+#include "update_engine/update_metadata.pb.h"
+#include "xz.h"
+
+DEFINE_string(payload, "", "Path to payload.bin");
+DEFINE_string(output_dir, "", "Directory to put output images");
+DEFINE_int64(payload_offset,
+             0,
+             "Offset to start of payload.bin. Useful if payload path actually "
+             "points to a .zip file containing payload.bin");
+DEFINE_string(partitions,
+              "",
+              "Comma separated list of partitions to extract, leave empty for "
+              "extracting all partitions");
+
+using chromeos_update_engine::DeltaArchiveManifest;
+using chromeos_update_engine::PayloadMetadata;
+
+namespace chromeos_update_engine {
+
+bool ExtractImagesFromOTA(const DeltaArchiveManifest& manifest,
+                          const PayloadMetadata& metadata,
+                          int payload_fd,
+                          size_t payload_offset,
+                          std::string_view output_dir,
+                          const std::set<std::string>& partitions) {
+  InstallOperationExecutor executor(manifest.block_size());
+  const size_t data_begin = metadata.GetMetadataSize() +
+                            metadata.GetMetadataSignatureSize() +
+                            payload_offset;
+  const base::FilePath path(
+      base::StringPiece(output_dir.data(), output_dir.size()));
+  std::vector<unsigned char> blob;
+  for (const auto& partition : manifest.partitions()) {
+    if (!partitions.empty() &&
+        partitions.count(partition.partition_name()) == 0) {
+      continue;
+    }
+    LOG(INFO) << "Extracting partition " << partition.partition_name()
+              << " size: " << partition.new_partition_info().size();
+    const auto output_path =
+        path.Append(partition.partition_name() + ".img").value();
+    auto fd =
+        std::make_shared<chromeos_update_engine::EintrSafeFileDescriptor>();
+    TEST_AND_RETURN_FALSE_ERRNO(
+        fd->Open(output_path.c_str(), O_RDWR | O_CREAT, 0644));
+    for (const auto& op : partition.operations()) {
+      blob.resize(op.data_length());
+      const auto op_data_offset = data_begin + op.data_offset();
+      ssize_t bytes_read = 0;
+      TEST_AND_RETURN_FALSE(utils::PReadAll(
+          payload_fd, blob.data(), blob.size(), op_data_offset, &bytes_read));
+      auto direct_writer = std::make_unique<DirectExtentWriter>(fd);
+      if (op.type() == InstallOperation::ZERO) {
+        TEST_AND_RETURN_FALSE(executor.ExecuteZeroOrDiscardOperation(
+            op, std::move(direct_writer)));
+      } else if (op.type() == InstallOperation::REPLACE ||
+                 op.type() == InstallOperation::REPLACE_BZ ||
+                 op.type() == InstallOperation::REPLACE_XZ) {
+        TEST_AND_RETURN_FALSE(executor.ExecuteReplaceOperation(
+            op, std::move(direct_writer), blob.data(), blob.size()));
+      } else {
+        LOG(ERROR) << "Unsupported operation type: " << op.type() << ", "
+                   << InstallOperation::Type_Name(op.type());
+        return false;
+      }
+    }
+    int err =
+        truncate64(output_path.c_str(), partition.new_partition_info().size());
+    if (err) {
+      PLOG(ERROR) << "Failed to truncate " << output_path << " to "
+                  << partition.new_partition_info().size();
+    }
+    brillo::Blob actual_hash;
+    TEST_AND_RETURN_FALSE(
+        HashCalculator::RawHashOfFile(output_path, &actual_hash));
+    CHECK_EQ(HexEncode(ToStringView(actual_hash)),
+             HexEncode(partition.new_partition_info().hash()));
+  }
+  return true;
+}
+
+}  // namespace chromeos_update_engine
+
+int main(int argc, char* argv[]) {
+  gflags::ParseCommandLineFlags(&argc, &argv, true);
+  xz_crc32_init();
+  auto tokens = android::base::Tokenize(FLAGS_partitions, ",");
+  const std::set<std::string> partitions(
+      std::make_move_iterator(tokens.begin()),
+      std::make_move_iterator(tokens.end()));
+  if (FLAGS_payload.empty()) {
+    LOG(ERROR) << "--payload <payload path> is required";
+    return 1;
+  }
+  if (!partitions.empty()) {
+    LOG(INFO) << "Extracting " << android::base::Join(partitions, ", ");
+  }
+  int payload_fd = open(FLAGS_payload.c_str(), O_RDONLY | O_CLOEXEC);
+  if (payload_fd < 0) {
+    PLOG(ERROR) << "Failed to open payload file";
+    return 1;
+  }
+  chromeos_update_engine::ScopedFdCloser closer{&payload_fd};
+  auto payload_size = chromeos_update_engine::utils::FileSize(payload_fd);
+  if (payload_size <= 0) {
+    PLOG(ERROR)
+        << "Couldn't determine size of payload file, or payload file is empty";
+    return 1;
+  }
+
+  PayloadMetadata payload_metadata;
+  auto payload = static_cast<unsigned char*>(
+      mmap(nullptr, payload_size, PROT_READ, MAP_PRIVATE, payload_fd, 0));
+
+  if (payload == MAP_FAILED) {
+    PLOG(ERROR) << "Failed to mmap() payload file";
+    return 1;
+  }
+
+  auto munmap_deleter = [payload_size](auto payload) {
+    munmap(payload, payload_size);
+  };
+  std::unique_ptr<unsigned char, decltype(munmap_deleter)> munmapper{
+      payload, munmap_deleter};
+  if (payload_metadata.ParsePayloadHeader(payload + FLAGS_payload_offset,
+                                          payload_size - FLAGS_payload_offset,
+                                          nullptr) !=
+      chromeos_update_engine::MetadataParseResult::kSuccess) {
+    LOG(ERROR) << "Payload header parse failed!";
+    return 1;
+  }
+  DeltaArchiveManifest manifest;
+  if (!payload_metadata.GetManifest(payload + FLAGS_payload_offset,
+                                    payload_size - FLAGS_payload_offset,
+                                    &manifest)) {
+    LOG(ERROR) << "Failed to parse manifest!";
+    return 1;
+  }
+  return !ExtractImagesFromOTA(manifest,
+                               payload_metadata,
+                               payload_fd,
+                               FLAGS_payload_offset,
+                               FLAGS_output_dir,
+                               partitions);
+}
diff --git a/aosp/update_attempter_android.cc b/aosp/update_attempter_android.cc
index 4e609d4..a3485ea 100644
--- a/aosp/update_attempter_android.cc
+++ b/aosp/update_attempter_android.cc
@@ -400,6 +400,10 @@
 bool UpdateAttempterAndroid::ResetStatus(brillo::ErrorPtr* error) {
   LOG(INFO) << "Attempting to reset state from "
             << UpdateStatusToString(status_) << " to UpdateStatus::IDLE";
+  if (processor_->IsRunning()) {
+    return LogAndSetError(
+        error, FROM_HERE, "Already processing an update, cancel it first.");
+  }
 
   if (apex_handler_android_ != nullptr) {
     LOG(INFO) << "Cleaning up reserved space for compressed APEX (if any)";
@@ -416,12 +420,12 @@
                           "ClearUpdateCompletedMarker() failed");
   }
 
+  if (!boot_control_->GetDynamicPartitionControl()->ResetUpdate(prefs_)) {
+    LOG(WARNING) << "Failed to reset snapshots. UpdateStatus is IDLE but"
+                  << "space might not be freed.";
+  }
   switch (status_) {
     case UpdateStatus::IDLE: {
-      if (!boot_control_->GetDynamicPartitionControl()->ResetUpdate(prefs_)) {
-        LOG(WARNING) << "Failed to reset snapshots. UpdateStatus is IDLE but"
-                     << "space might not be freed.";
-      }
       return true;
     }
 
diff --git a/common/mock_http_fetcher.h b/common/mock_http_fetcher.h
index ea5b83d..3d7859b 100644
--- a/common/mock_http_fetcher.h
+++ b/common/mock_http_fetcher.h
@@ -36,7 +36,7 @@
 // MockHttpFetcher will send a chunk of data down in each call to BeginTransfer
 // and Unpause. For the other chunks of data, a callback is put on the run
 // loop and when that's called, another chunk is sent down.
-const size_t kMockHttpFetcherChunkSize(65536);
+static constexpr size_t kMockHttpFetcherChunkSize(65536);
 
 class MockHttpFetcher : public HttpFetcher {
  public:
diff --git a/payload_consumer/delta_performer.cc b/payload_consumer/delta_performer.cc
index 19877db..fc8858f 100644
--- a/payload_consumer/delta_performer.cc
+++ b/payload_consumer/delta_performer.cc
@@ -1117,11 +1117,11 @@
 
   if (calculated_op_hash != expected_op_hash) {
     LOG(ERROR) << "Hash verification failed for operation "
-               << next_operation_num_ << ". Expected hash = ";
-    utils::HexDumpVector(expected_op_hash);
+               << next_operation_num_
+               << ". Expected hash = " << HexEncode(expected_op_hash);
     LOG(ERROR) << "Calculated hash over " << operation.data_length()
-               << " bytes at offset: " << operation.data_offset() << " = ";
-    utils::HexDumpVector(calculated_op_hash);
+               << " bytes at offset: " << operation.data_offset() << " = "
+               << HexEncode(calculated_op_hash);
     return ErrorCode::kDownloadOperationHashMismatch;
   }
 
diff --git a/payload_consumer/partition_writer.cc b/payload_consumer/partition_writer.cc
index b94f8c7..1fb929e 100644
--- a/payload_consumer/partition_writer.cc
+++ b/payload_consumer/partition_writer.cc
@@ -295,6 +295,16 @@
   return std::make_unique<DirectExtentWriter>(target_fd_);
 }
 
+bool PartitionWriter::ValidateSourceHash(const InstallOperation& operation,
+                                         const FileDescriptorPtr source_fd,
+                                         size_t block_size,
+                                         ErrorCode* error) {
+  brillo::Blob source_hash;
+  TEST_AND_RETURN_FALSE_ERRNO(fd_utils::ReadAndHashExtents(
+      source_fd, operation.src_extents(), block_size, &source_hash));
+  return ValidateSourceHash(source_hash, operation, source_fd, error);
+}
+
 bool PartitionWriter::ValidateSourceHash(const brillo::Blob& calculated_hash,
                                          const InstallOperation& operation,
                                          const FileDescriptorPtr source_fd,
diff --git a/payload_consumer/partition_writer.h b/payload_consumer/partition_writer.h
index 89e5884..e620c47 100644
--- a/payload_consumer/partition_writer.h
+++ b/payload_consumer/partition_writer.h
@@ -46,6 +46,10 @@
                                  const InstallOperation& operation,
                                  const FileDescriptorPtr source_fd,
                                  ErrorCode* error);
+  static bool ValidateSourceHash(const InstallOperation& operation,
+                                 const FileDescriptorPtr source_fd,
+                                 size_t block_size,
+                                 ErrorCode* error);
 
   // Perform necessary initialization work before InstallOperation can be
   // applied to this partition
diff --git a/payload_consumer/vabc_partition_writer.cc b/payload_consumer/vabc_partition_writer.cc
index 9db88a9..54aea86 100644
--- a/payload_consumer/vabc_partition_writer.cc
+++ b/payload_consumer/vabc_partition_writer.cc
@@ -33,6 +33,7 @@
 #include "update_engine/payload_consumer/extent_map.h"
 #include "update_engine/payload_consumer/extent_reader.h"
 #include "update_engine/payload_consumer/file_descriptor.h"
+#include "update_engine/payload_consumer/file_descriptor_utils.h"
 #include "update_engine/payload_consumer/install_plan.h"
 #include "update_engine/payload_consumer/partition_writer.h"
 #include "update_engine/payload_consumer/snapshot_extent_writer.h"
@@ -267,9 +268,16 @@
 
 [[nodiscard]] bool VABCPartitionWriter::PerformSourceCopyOperation(
     const InstallOperation& operation, ErrorCode* error) {
-  // TODO(zhangkelvin) Probably just ignore SOURCE_COPY? They should be taken
-  // care of during Init();
-  return true;
+  // COPY ops are already handled during Init(), no need to do actual work, but
+  // we still want to verify that all blocks contain expected data.
+  auto source_fd = std::make_shared<EintrSafeFileDescriptor>();
+  TEST_AND_RETURN_FALSE_ERRNO(
+      source_fd->Open(install_part_.source_path.c_str(), O_RDONLY));
+  if (!operation.has_src_sha256_hash()) {
+    return true;
+  }
+  return PartitionWriter::ValidateSourceHash(
+      operation, source_fd, block_size_, error);
 }
 
 bool VABCPartitionWriter::PerformReplaceOperation(const InstallOperation& op,
diff --git a/payload_generator/payload_generation_config.h b/payload_generator/payload_generation_config.h
index a7ddee4..7124cb0 100644
--- a/payload_generator/payload_generation_config.h
+++ b/payload_generator/payload_generation_config.h
@@ -25,7 +25,6 @@
 
 #include <brillo/key_value_store.h>
 #include <brillo/secure_blob.h>
-#include <lz4diff/lz4diff.pb.h>
 
 #include "bsdiff/constants.h"
 #include "update_engine/payload_consumer/payload_constants.h"
diff --git a/scripts/simulate_ota.py b/scripts/simulate_ota.py
index 40f463f..bf1fc98 100644
--- a/scripts/simulate_ota.py
+++ b/scripts/simulate_ota.py
@@ -110,6 +110,7 @@
   delta_generator_args.append("--partition_names=" + ":".join(partition_names))
   delta_generator_args.append("--new_partitions=" + ":".join(new_partitions))
 
+  print("Running ", " ".join(delta_generator_args))
   subprocess.check_output(delta_generator_args)
 
   valid = True
diff --git a/scripts/update_device.py b/scripts/update_device.py
index db653dc..72cee49 100755
--- a/scripts/update_device.py
+++ b/scripts/update_device.py
@@ -442,6 +442,8 @@
                       help='Perform slot switch for this OTA package')
   parser.add_argument('--perform-reset-slot-switch', action='store_true',
                       help='Perform reset slot switch for this OTA package')
+  parser.add_argument('--wipe-user-data', action='store_true',
+                      help='Wipe userdata after installing OTA')
   args = parser.parse_args()
   logging.basicConfig(
       level=logging.WARNING if args.no_verbose else logging.INFO)
@@ -493,6 +495,8 @@
     args.extra_headers += "\nSWITCH_SLOT_ON_REBOOT=0"
   if args.no_postinstall:
     args.extra_headers += "\nRUN_POST_INSTALL=0"
+  if args.wipe_user_data:
+    args.extra_headers += "\nPOWERWASH=1"
 
   with zipfile.ZipFile(args.otafile) as zfp:
     CARE_MAP_ENTRY_NAME = "care_map.pb"
diff --git a/update_metadata.proto b/update_metadata.proto
index d318a62..3f454ad 100644
--- a/update_metadata.proto
+++ b/update_metadata.proto
@@ -146,25 +146,6 @@
   optional bytes hash = 2;
 }
 
-// Describe an image we are based on in a human friendly way.
-// Examples:
-//   dev-channel, x86-alex, 1.2.3, mp-v3
-//   nplusone-channel, x86-alex, 1.2.4, mp-v3, dev-channel, 1.2.3
-//
-// All fields will be set, if this message is present.
-message ImageInfo {
-  optional string board = 1 [deprecated = true];
-  optional string key = 2 [deprecated = true];
-  optional string channel = 3 [deprecated = true];
-  optional string version = 4 [deprecated = true];
-
-  // If these values aren't present, they should be assumed to match
-  // the equivalent value above. They are normally only different for
-  // special image types such as nplusone images.
-  optional string build_channel = 5 [deprecated = true];
-  optional string build_version = 6 [deprecated = true];
-}
-
 message InstallOperation {
   enum Type {
     REPLACE = 0;     // Replace destination extents w/ attached data.
@@ -401,8 +382,7 @@
   // Only present in major version = 1. List of install operations for the
   // kernel and rootfs partitions. For major version = 2 see the |partitions|
   // field.
-  repeated InstallOperation install_operations = 1 [deprecated = true];
-  repeated InstallOperation kernel_install_operations = 2 [deprecated = true];
+  reserved 1, 2;
 
   // (At time of writing) usually 4096
   optional uint32 block_size = 3 [default = 4096];
@@ -415,17 +395,8 @@
   optional uint64 signatures_offset = 4;
   optional uint64 signatures_size = 5;
 
-  // Only present in major version = 1. Partition metadata used to validate the
-  // update. For major version = 2 see the |partitions| field.
-  optional PartitionInfo old_kernel_info = 6 [deprecated = true];
-  optional PartitionInfo new_kernel_info = 7 [deprecated = true];
-  optional PartitionInfo old_rootfs_info = 8 [deprecated = true];
-  optional PartitionInfo new_rootfs_info = 9 [deprecated = true];
-
-  // old_image_info will only be present for delta images.
-  optional ImageInfo old_image_info = 10 [deprecated = true];
-
-  optional ImageInfo new_image_info = 11 [deprecated = true];
+  // Fields deprecated in major version 2.
+  reserved 6,7,8,9,10,11;
 
   // The minor version, also referred as "delta version", of the payload.
   // Minor version 0 is full payload, everything else is delta payload.