diff options
Diffstat (limited to 'payload_generator/generate_delta_main.cc')
-rw-r--r-- | payload_generator/generate_delta_main.cc | 113 |
1 files changed, 101 insertions, 12 deletions
diff --git a/payload_generator/generate_delta_main.cc b/payload_generator/generate_delta_main.cc index fe0a10be..5c1fb476 100644 --- a/payload_generator/generate_delta_main.cc +++ b/payload_generator/generate_delta_main.cc @@ -14,6 +14,7 @@ // limitations under the License. // +#include <map> #include <string> #include <vector> @@ -22,6 +23,7 @@ #include <base/logging.h> #include <base/strings/string_number_conversions.h> #include <base/strings/string_split.h> +#include <base/strings/string_util.h> #include <brillo/flag_helper.h> #include <brillo/key_value_store.h> #include <brillo/message_loops/base_message_loop.h> @@ -47,6 +49,7 @@ // and an output file as arguments and the path to an output file and // generates a delta that can be sent to Chrome OS clients. +using std::map; using std::string; using std::vector; @@ -58,18 +61,15 @@ constexpr char kPayloadPropertiesFormatKeyValue[] = "key-value"; constexpr char kPayloadPropertiesFormatJson[] = "json"; void ParseSignatureSizes(const string& signature_sizes_flag, - vector<int>* signature_sizes) { + vector<size_t>* signature_sizes) { signature_sizes->clear(); vector<string> split_strings = base::SplitString( signature_sizes_flag, ":", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); for (const string& str : split_strings) { - int size = 0; - bool parsing_successful = base::StringToInt(str, &size); + size_t size = 0; + bool parsing_successful = base::StringToSizeT(str, &size); LOG_IF(FATAL, !parsing_successful) << "Invalid signature size: " << str; - LOG_IF(FATAL, size != (2048 / 8)) - << "Only signature sizes of 256 bytes are supported."; - signature_sizes->push_back(size); } } @@ -106,7 +106,7 @@ bool ParseImageInfo(const string& channel, return true; } -void CalculateHashForSigning(const vector<int>& sizes, +void CalculateHashForSigning(const vector<size_t>& sizes, const string& out_hash_file, const string& out_metadata_hash_file, const string& in_file) { @@ -142,6 +142,7 @@ void SignatureFileFlagToBlobs(const string& signature_file_flag, void SignPayload(const string& in_file, const string& out_file, + const vector<size_t>& signature_sizes, const string& payload_signature_file, const string& metadata_signature_file, const string& out_metadata_size_file) { @@ -155,6 +156,7 @@ void SignPayload(const string& in_file, SignatureFileFlagToBlobs(metadata_signature_file, &metadata_signatures); uint64_t final_metadata_size; CHECK(PayloadSigner::AddSignatureToPayload(in_file, + signature_sizes, payload_signatures, metadata_signatures, out_file, @@ -253,8 +255,8 @@ bool ApplyPayload(const string& payload_file, nullptr, new FileFetcher(), true /* interactive */); - auto filesystem_verifier_action = - std::make_unique<FilesystemVerifierAction>(); + auto filesystem_verifier_action = std::make_unique<FilesystemVerifierAction>( + fake_boot_control.GetDynamicPartitionControl()); BondActions(install_plan_action.get(), download_action.get()); BondActions(download_action.get(), filesystem_verifier_action.get()); @@ -295,6 +297,39 @@ bool ExtractProperties(const string& payload_path, return true; } +template <typename Key, typename Val> +string ToString(const map<Key, Val>& map) { + vector<string> result; + result.reserve(map.size()); + for (const auto& it : map) { + result.emplace_back(it.first + ": " + it.second); + } + return "{" + base::JoinString(result, ",") + "}"; +} + +bool ParsePerPartitionTimestamps(const string& partition_timestamps, + PayloadGenerationConfig* config) { + base::StringPairs pairs; + CHECK(base::SplitStringIntoKeyValuePairs( + partition_timestamps, ':', ',', &pairs)) + << "--partition_timestamps accepts commad " + "separated pairs. e.x. system:1234,vendor:5678"; + map<string, string> partition_timestamps_map{ + std::move_iterator(pairs.begin()), std::move_iterator(pairs.end())}; + for (auto&& partition : config->target.partitions) { + auto&& it = partition_timestamps_map.find(partition.name); + if (it != partition_timestamps_map.end()) { + partition.version = std::move(it->second); + partition_timestamps_map.erase(it); + } + } + if (!partition_timestamps_map.empty()) { + LOG(ERROR) << "Unused timestamps: " << ToString(partition_timestamps_map); + return false; + } + return true; +} + int Main(int argc, char** argv) { DEFINE_string(old_image, "", "Path to the old rootfs"); DEFINE_string(new_image, "", "Path to the new rootfs"); @@ -385,6 +420,11 @@ int Main(int argc, char** argv) { 0, "The maximum timestamp of the OS allowed to apply this " "payload."); + DEFINE_string( + partition_timestamps, + "", + "The per-partition maximum timestamps which the OS allowed to apply this " + "payload. Passed in comma separated pairs, e.x. system:1234,vendor:5678"); DEFINE_string(old_channel, "", @@ -439,6 +479,17 @@ int Main(int argc, char** argv) { "", "An info file specifying dynamic partition metadata. " "Only allowed in major version 2 or newer."); + DEFINE_bool(disable_fec_computation, + false, + "Disables the fec data computation on device."); + DEFINE_string( + out_maximum_signature_size_file, + "", + "Path to the output maximum signature size given a private key."); + DEFINE_bool(is_partial_update, + false, + "The payload only targets a subset of partitions on the device," + "e.g. generic kernel image update."); brillo::FlagHelper::Init( argc, @@ -464,8 +515,34 @@ int Main(int argc, char** argv) { // Initialize the Xz compressor. XzCompressInit(); - vector<int> signature_sizes; - ParseSignatureSizes(FLAGS_signature_size, &signature_sizes); + if (!FLAGS_out_maximum_signature_size_file.empty()) { + LOG_IF(FATAL, FLAGS_private_key.empty()) + << "Private key is not provided when calculating the maximum signature " + "size."; + + size_t maximum_signature_size; + if (!PayloadSigner::GetMaximumSignatureSize(FLAGS_private_key, + &maximum_signature_size)) { + LOG(ERROR) << "Failed to get the maximum signature size of private key: " + << FLAGS_private_key; + return 1; + } + // Write the size string to output file. + string signature_size_string = std::to_string(maximum_signature_size); + if (!utils::WriteFile(FLAGS_out_maximum_signature_size_file.c_str(), + signature_size_string.c_str(), + signature_size_string.size())) { + PLOG(ERROR) << "Failed to write the maximum signature size to " + << FLAGS_out_maximum_signature_size_file << "."; + return 1; + } + return 0; + } + + vector<size_t> signature_sizes; + if (!FLAGS_signature_size.empty()) { + ParseSignatureSizes(FLAGS_signature_size, &signature_sizes); + } if (!FLAGS_out_hash_file.empty() || !FLAGS_out_metadata_hash_file.empty()) { CHECK(FLAGS_out_metadata_size_file.empty()); @@ -478,6 +555,7 @@ int Main(int argc, char** argv) { if (!FLAGS_payload_signature_file.empty()) { SignPayload(FLAGS_in_file, FLAGS_out_file, + signature_sizes, FLAGS_payload_signature_file, FLAGS_metadata_signature_file, FLAGS_out_metadata_size_file); @@ -546,6 +624,8 @@ int Main(int argc, char** argv) { << "Partition name can't be empty, see --partition_names."; payload_config.target.partitions.emplace_back(partition_names[i]); payload_config.target.partitions.back().path = new_partitions[i]; + payload_config.target.partitions.back().disable_fec_computation = + FLAGS_disable_fec_computation; if (i < new_mapfiles.size()) payload_config.target.partitions.back().mapfile_path = new_mapfiles[i]; } @@ -598,6 +678,10 @@ int Main(int argc, char** argv) { CHECK(payload_config.target.ValidateDynamicPartitionMetadata()); } + if (FLAGS_is_partial_update) { + payload_config.is_partial_update = true; + } + CHECK(!FLAGS_out_file.empty()); // Ignore failures. These are optional arguments. @@ -670,8 +754,13 @@ int Main(int argc, char** argv) { } payload_config.max_timestamp = FLAGS_max_timestamp; + if (!FLAGS_partition_timestamps.empty()) { + CHECK(ParsePerPartitionTimestamps(FLAGS_partition_timestamps, + &payload_config)); + } - if (payload_config.version.minor >= kVerityMinorPayloadVersion) + if (payload_config.is_delta && + payload_config.version.minor >= kVerityMinorPayloadVersion) CHECK(payload_config.target.LoadVerityConfig()); LOG(INFO) << "Generating " << (payload_config.is_delta ? "delta" : "full") |