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