payload_generation_config.cc revision 2d3b2d635e50c6886e285afb86c3187d9e0bd360
1// Copyright 2015 The Chromium OS Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "update_engine/payload_generator/payload_generation_config.h" 6 7#include <base/logging.h> 8 9#include "update_engine/delta_performer.h" 10#include "update_engine/payload_generator/delta_diff_generator.h" 11#include "update_engine/payload_generator/ext2_filesystem.h" 12#include "update_engine/payload_generator/raw_filesystem.h" 13#include "update_engine/payload_generator/verity_utils.h" 14#include "update_engine/utils.h" 15 16namespace chromeos_update_engine { 17 18std::string PartitionNameString(PartitionName name) { 19 switch (name) { 20 case PartitionName::kKernel: 21 return "kernel"; 22 case PartitionName::kRootfs: 23 return "rootfs"; 24 } 25 return "other"; 26} 27 28bool PartitionConfig::ValidateExists() const { 29 TEST_AND_RETURN_FALSE(!path.empty()); 30 TEST_AND_RETURN_FALSE(utils::FileExists(path.c_str())); 31 TEST_AND_RETURN_FALSE(size > 0); 32 // The requested size is within the limits of the file. 33 TEST_AND_RETURN_FALSE(static_cast<off_t>(size) <= 34 utils::FileSize(path.c_str())); 35 return true; 36} 37 38bool PartitionConfig::OpenFilesystem() { 39 if (path.empty()) 40 return true; 41 fs_interface.reset(); 42 if (name == PartitionName::kRootfs) { 43 fs_interface = Ext2Filesystem::CreateFromFile(path); 44 } 45 46 if (!fs_interface) { 47 // Fall back to a RAW filesystem. 48 TEST_AND_RETURN_FALSE(size % kBlockSize == 0); 49 fs_interface = RawFilesystem::Create( 50 "<" + PartitionNameString(name) + "-partition>", 51 kBlockSize, 52 size / kBlockSize); 53 } 54 return true; 55} 56 57bool ImageConfig::ValidateIsEmpty() const { 58 TEST_AND_RETURN_FALSE(ImageInfoIsEmpty()); 59 60 TEST_AND_RETURN_FALSE(rootfs.path.empty()); 61 TEST_AND_RETURN_FALSE(rootfs.size == 0); 62 TEST_AND_RETURN_FALSE(kernel.path.empty()); 63 TEST_AND_RETURN_FALSE(kernel.size == 0); 64 return true; 65} 66 67bool ImageConfig::LoadImageSize() { 68 TEST_AND_RETURN_FALSE(!rootfs.path.empty()); 69 int rootfs_block_count, rootfs_block_size; 70 TEST_AND_RETURN_FALSE(utils::GetFilesystemSize(rootfs.path, 71 &rootfs_block_count, 72 &rootfs_block_size)); 73 rootfs.size = static_cast<uint64_t>(rootfs_block_count) * rootfs_block_size; 74 if (!kernel.path.empty()) 75 kernel.size = utils::FileSize(kernel.path); 76 77 // TODO(deymo): The delta generator algorithm doesn't support a block size 78 // different than 4 KiB. Remove this check once that's fixed. crbug.com/455045 79 if (rootfs_block_size != 4096) { 80 LOG(ERROR) << "The filesystem provided in " << rootfs.path 81 << " has a block size of " << rootfs_block_size 82 << " but delta_generator only supports 4096."; 83 return false; 84 } 85 return true; 86} 87 88bool ImageConfig::LoadVerityRootfsSize() { 89 if (kernel.path.empty()) 90 return false; 91 uint64_t verity_rootfs_size = 0; 92 if (!GetVerityRootfsSize(kernel.path, &verity_rootfs_size)) { 93 LOG(INFO) << "Couldn't find verity options in source kernel config, will " 94 << "use the rootfs filesystem size instead: " << rootfs.size; 95 return false; 96 } 97 if (rootfs.size != verity_rootfs_size) { 98 LOG(WARNING) << "Using the rootfs size found in the kernel config (" 99 << verity_rootfs_size << ") instead of the rootfs filesystem " 100 << " size (" << rootfs.size << ")."; 101 rootfs.size = verity_rootfs_size; 102 } 103 return true; 104} 105 106bool ImageConfig::ImageInfoIsEmpty() const { 107 return image_info.board().empty() 108 && image_info.key().empty() 109 && image_info.channel().empty() 110 && image_info.version().empty() 111 && image_info.build_channel().empty() 112 && image_info.build_version().empty(); 113} 114 115bool PayloadGenerationConfig::Validate() const { 116 if (is_delta) { 117 TEST_AND_RETURN_FALSE(source.rootfs.ValidateExists()); 118 TEST_AND_RETURN_FALSE(source.rootfs.size % block_size == 0); 119 120 if (!source.kernel.path.empty()) { 121 TEST_AND_RETURN_FALSE(source.kernel.ValidateExists()); 122 TEST_AND_RETURN_FALSE(source.kernel.size % block_size == 0); 123 } 124 125 // Check for the supported minor_version values. 126 TEST_AND_RETURN_FALSE(minor_version == kInPlaceMinorPayloadVersion || 127 minor_version == kSourceMinorPayloadVersion); 128 129 // If new_image_info is present, old_image_info must be present. 130 TEST_AND_RETURN_FALSE(source.ImageInfoIsEmpty() == 131 target.ImageInfoIsEmpty()); 132 } else { 133 // All the "source" image fields must be empty for full payloads. 134 TEST_AND_RETURN_FALSE(source.ValidateIsEmpty()); 135 TEST_AND_RETURN_FALSE(minor_version == 136 DeltaPerformer::kFullPayloadMinorVersion); 137 } 138 139 // In all cases, the target image must exists. 140 TEST_AND_RETURN_FALSE(target.rootfs.ValidateExists()); 141 TEST_AND_RETURN_FALSE(target.kernel.ValidateExists()); 142 TEST_AND_RETURN_FALSE(target.rootfs.size % block_size == 0); 143 TEST_AND_RETURN_FALSE(target.kernel.size % block_size == 0); 144 145 TEST_AND_RETURN_FALSE(hard_chunk_size == -1 || 146 hard_chunk_size % block_size == 0); 147 TEST_AND_RETURN_FALSE(soft_chunk_size % block_size == 0); 148 149 TEST_AND_RETURN_FALSE(rootfs_partition_size % block_size == 0); 150 TEST_AND_RETURN_FALSE(rootfs_partition_size >= target.rootfs.size); 151 152 return true; 153} 154 155} // namespace chromeos_update_engine 156