blob: c42c8d753e005832498b1e3f9b529f09a814cbc5 [file] [log] [blame]
Alex Deymob17327c2015-09-04 10:29:00 -07001//
2// Copyright (C) 2015 The Android Open Source Project
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
16
Alex Deymo1b03f9f2015-12-09 00:38:36 -080017#include "update_engine/boot_control_android.h"
Alex Deymob17327c2015-09-04 10:29:00 -070018
Sen Jiangd944faa2018-08-22 18:46:39 -070019#include <memory>
20#include <utility>
Yifan Hongd4db07e2018-10-18 17:46:27 -070021#include <vector>
Sen Jiangd944faa2018-08-22 18:46:39 -070022
Alex Deymoaa26f622015-09-16 18:21:27 -070023#include <base/bind.h>
Alex Deymoaa26f622015-09-16 18:21:27 -070024#include <base/logging.h>
Yifan Hongd4db07e2018-10-18 17:46:27 -070025#include <base/strings/string_util.h>
Sen Jiangd944faa2018-08-22 18:46:39 -070026#include <bootloader_message/bootloader_message.h>
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070027#include <brillo/message_loops/message_loop.h>
David Andersond63cb3c2018-10-01 14:15:00 -070028#include <fs_mgr.h>
Alex Deymob17327c2015-09-04 10:29:00 -070029
Alex Deymo39910dc2015-11-09 17:04:30 -080030#include "update_engine/common/utils.h"
Yifan Hong537802d2018-08-15 13:15:42 -070031#include "update_engine/dynamic_partition_control_android.h"
Alex Deymob17327c2015-09-04 10:29:00 -070032
33using std::string;
34
Yifan Hong537802d2018-08-15 13:15:42 -070035using android::dm::DmDeviceState;
Yifan Hong537802d2018-08-15 13:15:42 -070036using android::fs_mgr::Partition;
Yifan Hong537802d2018-08-15 13:15:42 -070037using android::hardware::hidl_string;
Connor O'Briencee6ad92016-11-21 13:53:52 -080038using android::hardware::Return;
39using android::hardware::boot::V1_0::BoolResult;
40using android::hardware::boot::V1_0::CommandResult;
41using android::hardware::boot::V1_0::IBootControl;
Yifan Hong537802d2018-08-15 13:15:42 -070042using Slot = chromeos_update_engine::BootControlInterface::Slot;
Yifan Hong6b0a9842018-10-16 16:54:18 -070043using PartitionMetadata =
44 chromeos_update_engine::BootControlInterface::PartitionMetadata;
Connor O'Briencee6ad92016-11-21 13:53:52 -080045
46namespace {
Yifan Hong537802d2018-08-15 13:15:42 -070047
Connor O'Briencee6ad92016-11-21 13:53:52 -080048auto StoreResultCallback(CommandResult* dest) {
49 return [dest](const CommandResult& result) { *dest = result; };
50}
51} // namespace
Alex Deymo44348e02016-07-29 16:22:26 -070052
Alex Deymob17327c2015-09-04 10:29:00 -070053namespace chromeos_update_engine {
54
55namespace boot_control {
56
57// Factory defined in boot_control.h.
58std::unique_ptr<BootControlInterface> CreateBootControl() {
Yifan Hong537802d2018-08-15 13:15:42 -070059 auto boot_control = std::make_unique<BootControlAndroid>();
David Zeuthen753fadc2015-09-15 16:34:09 -040060 if (!boot_control->Init()) {
61 return nullptr;
62 }
Alex Vakulenkoce8c8ee2016-04-08 08:59:26 -070063 return std::move(boot_control);
Alex Deymob17327c2015-09-04 10:29:00 -070064}
65
66} // namespace boot_control
67
David Zeuthen753fadc2015-09-15 16:34:09 -040068bool BootControlAndroid::Init() {
Chris Phoenixafde8e82017-01-17 23:14:58 -080069 module_ = IBootControl::getService();
Connor O'Briencee6ad92016-11-21 13:53:52 -080070 if (module_ == nullptr) {
Steven Moreland927e00d2017-01-04 12:58:40 -080071 LOG(ERROR) << "Error getting bootctrl HIDL module.";
David Zeuthen753fadc2015-09-15 16:34:09 -040072 return false;
73 }
74
Steven Moreland927e00d2017-01-04 12:58:40 -080075 LOG(INFO) << "Loaded boot control hidl hal.";
David Zeuthen753fadc2015-09-15 16:34:09 -040076
Yifan Hong537802d2018-08-15 13:15:42 -070077 dynamic_control_ = std::make_unique<DynamicPartitionControlAndroid>();
78
David Zeuthen753fadc2015-09-15 16:34:09 -040079 return true;
80}
Alex Deymob17327c2015-09-04 10:29:00 -070081
Yifan Hong537802d2018-08-15 13:15:42 -070082void BootControlAndroid::Cleanup() {
83 dynamic_control_->Cleanup();
84}
85
Alex Deymob17327c2015-09-04 10:29:00 -070086unsigned int BootControlAndroid::GetNumSlots() const {
Connor O'Briencee6ad92016-11-21 13:53:52 -080087 return module_->getNumberSlots();
Alex Deymob17327c2015-09-04 10:29:00 -070088}
89
90BootControlInterface::Slot BootControlAndroid::GetCurrentSlot() const {
Connor O'Briencee6ad92016-11-21 13:53:52 -080091 return module_->getCurrentSlot();
Alex Deymob17327c2015-09-04 10:29:00 -070092}
93
Yifan Hong537802d2018-08-15 13:15:42 -070094bool BootControlAndroid::GetSuffix(Slot slot, string* suffix) const {
Connor O'Briencee6ad92016-11-21 13:53:52 -080095 auto store_suffix_cb = [&suffix](hidl_string cb_suffix) {
Yifan Hong537802d2018-08-15 13:15:42 -070096 *suffix = cb_suffix.c_str();
Connor O'Briencee6ad92016-11-21 13:53:52 -080097 };
98 Return<void> ret = module_->getSuffix(slot, store_suffix_cb);
99
Yifan Hong7b514b42016-12-21 13:02:00 -0800100 if (!ret.isOk()) {
Alex Deymo31d95ac2015-09-17 11:56:18 -0700101 LOG(ERROR) << "boot_control impl returned no suffix for slot "
102 << SlotName(slot);
David Zeuthen753fadc2015-09-15 16:34:09 -0400103 return false;
104 }
Yifan Hong537802d2018-08-15 13:15:42 -0700105 return true;
106}
107
Yifan Hong124a4602018-11-14 13:17:01 -0800108bool BootControlAndroid::IsSuperBlockDevice(
109 const base::FilePath& device_dir,
110 Slot slot,
111 const string& partition_name_suffix) const {
112 string source_device =
113 device_dir.Append(fs_mgr_get_super_partition_name(slot)).value();
114 auto source_metadata = dynamic_control_->LoadMetadataBuilder(
115 source_device, slot, BootControlInterface::kInvalidSlot);
116 return source_metadata->HasBlockDevice(partition_name_suffix);
117}
Yifan Hongae04e192018-10-29 11:00:28 -0700118
Yifan Hong124a4602018-11-14 13:17:01 -0800119BootControlAndroid::DynamicPartitionDeviceStatus
120BootControlAndroid::GetDynamicPartitionDevice(
121 const base::FilePath& device_dir,
Yifan Hongae04e192018-10-29 11:00:28 -0700122 const string& partition_name_suffix,
123 Slot slot,
Yifan Hong124a4602018-11-14 13:17:01 -0800124 string* device) const {
Yifan Hong124a4602018-11-14 13:17:01 -0800125 string super_device =
126 device_dir.Append(fs_mgr_get_super_partition_name(slot)).value();
127
128 auto builder = dynamic_control_->LoadMetadataBuilder(
Yifan Hong6e706b12018-11-09 16:50:51 -0800129 super_device, slot, BootControlInterface::kInvalidSlot);
Yifan Hongae04e192018-10-29 11:00:28 -0700130
131 if (builder == nullptr) {
Yifan Hongae04e192018-10-29 11:00:28 -0700132 LOG(ERROR) << "No metadata in slot "
133 << BootControlInterface::SlotName(slot);
134 return DynamicPartitionDeviceStatus::ERROR;
135 }
136
137 if (builder->FindPartition(partition_name_suffix) == nullptr) {
138 LOG(INFO) << partition_name_suffix
139 << " is not in super partition metadata.";
Yifan Hong124a4602018-11-14 13:17:01 -0800140
141 Slot current_slot = GetCurrentSlot();
142 if (IsSuperBlockDevice(device_dir, current_slot, partition_name_suffix)) {
143 LOG(ERROR) << "The static partition " << partition_name_suffix
144 << " is a block device for current metadata ("
145 << fs_mgr_get_super_partition_name(current_slot) << ", slot "
146 << BootControlInterface::SlotName(current_slot)
147 << "). It cannot be used as a logical partition.";
148 return DynamicPartitionDeviceStatus::ERROR;
149 }
150
Yifan Hongae04e192018-10-29 11:00:28 -0700151 return DynamicPartitionDeviceStatus::TRY_STATIC;
152 }
153
Yifan Hong124a4602018-11-14 13:17:01 -0800154 DmDeviceState state = dynamic_control_->GetState(partition_name_suffix);
Yifan Hongae04e192018-10-29 11:00:28 -0700155
Yifan Hong35410ed2018-12-05 03:30:10 +0000156 // Device is mapped in the previous GetPartitionDevice() call. Just return
157 // the path.
Yifan Hongae04e192018-10-29 11:00:28 -0700158 if (state == DmDeviceState::ACTIVE) {
Yifan Hong124a4602018-11-14 13:17:01 -0800159 if (dynamic_control_->GetDmDevicePathByName(partition_name_suffix,
160 device)) {
Yifan Hongae04e192018-10-29 11:00:28 -0700161 LOG(INFO) << partition_name_suffix
162 << " is mapped on device mapper: " << *device;
163 return DynamicPartitionDeviceStatus::SUCCESS;
164 }
165 LOG(ERROR) << partition_name_suffix << " is mapped but path is unknown.";
166 return DynamicPartitionDeviceStatus::ERROR;
167 }
168
Yifan Hongae04e192018-10-29 11:00:28 -0700169 if (state == DmDeviceState::INVALID) {
Yifan Hong35410ed2018-12-05 03:30:10 +0000170 bool force_writable = slot != GetCurrentSlot();
Yifan Hong124a4602018-11-14 13:17:01 -0800171 if (dynamic_control_->MapPartitionOnDeviceMapper(super_device,
172 partition_name_suffix,
173 slot,
Yifan Hong35410ed2018-12-05 03:30:10 +0000174 force_writable,
Yifan Hong124a4602018-11-14 13:17:01 -0800175 device)) {
Yifan Hongae04e192018-10-29 11:00:28 -0700176 return DynamicPartitionDeviceStatus::SUCCESS;
177 }
178 return DynamicPartitionDeviceStatus::ERROR;
179 }
180
181 LOG(ERROR) << partition_name_suffix
182 << " is mapped on device mapper but state is unknown: "
183 << static_cast<std::underlying_type_t<DmDeviceState>>(state);
184 return DynamicPartitionDeviceStatus::ERROR;
185}
Yifan Hongae04e192018-10-29 11:00:28 -0700186
Yifan Hong537802d2018-08-15 13:15:42 -0700187bool BootControlAndroid::GetPartitionDevice(const string& partition_name,
188 Slot slot,
189 string* device) const {
190 string suffix;
191 if (!GetSuffix(slot, &suffix)) {
192 return false;
193 }
Yifan Hongae04e192018-10-29 11:00:28 -0700194 const string partition_name_suffix = partition_name + suffix;
Yifan Hong537802d2018-08-15 13:15:42 -0700195
196 string device_dir_str;
197 if (!dynamic_control_->GetDeviceDir(&device_dir_str)) {
198 return false;
199 }
Yifan Hongae04e192018-10-29 11:00:28 -0700200 base::FilePath device_dir(device_dir_str);
David Zeuthen753fadc2015-09-15 16:34:09 -0400201
Yifan Hong1d9077f2018-12-07 12:09:37 -0800202 // When looking up target partition devices, treat them as static if the
203 // current payload doesn't encode them as dynamic partitions. This may happen
204 // when applying a retrofit update on top of a dynamic-partitions-enabled
205 // build.
206 if (dynamic_control_->IsDynamicPartitionsEnabled() &&
207 (slot == GetCurrentSlot() || is_target_dynamic_)) {
208 switch (GetDynamicPartitionDevice(
209 device_dir, partition_name_suffix, slot, device)) {
210 case DynamicPartitionDeviceStatus::SUCCESS:
211 return true;
212 case DynamicPartitionDeviceStatus::TRY_STATIC:
213 break;
214 case DynamicPartitionDeviceStatus::ERROR: // fallthrough
215 default:
216 return false;
217 }
Yifan Hongae04e192018-10-29 11:00:28 -0700218 }
219
220 base::FilePath path = device_dir.Append(partition_name_suffix);
Yifan Hong537802d2018-08-15 13:15:42 -0700221 if (!dynamic_control_->DeviceExists(path.value())) {
David Zeuthen753fadc2015-09-15 16:34:09 -0400222 LOG(ERROR) << "Device file " << path.value() << " does not exist.";
223 return false;
224 }
225
226 *device = path.value();
227 return true;
Alex Deymob17327c2015-09-04 10:29:00 -0700228}
229
230bool BootControlAndroid::IsSlotBootable(Slot slot) const {
Connor O'Briencee6ad92016-11-21 13:53:52 -0800231 Return<BoolResult> ret = module_->isSlotBootable(slot);
Yifan Hong7b514b42016-12-21 13:02:00 -0800232 if (!ret.isOk()) {
Alex Deymo31d95ac2015-09-17 11:56:18 -0700233 LOG(ERROR) << "Unable to determine if slot " << SlotName(slot)
Connor O'Briencee6ad92016-11-21 13:53:52 -0800234 << " is bootable: "
Yifan Hong7b514b42016-12-21 13:02:00 -0800235 << ret.description();
David Zeuthen753fadc2015-09-15 16:34:09 -0400236 return false;
237 }
Connor O'Briencee6ad92016-11-21 13:53:52 -0800238 if (ret == BoolResult::INVALID_SLOT) {
239 LOG(ERROR) << "Invalid slot: " << SlotName(slot);
240 return false;
241 }
242 return ret == BoolResult::TRUE;
Alex Deymob17327c2015-09-04 10:29:00 -0700243}
244
245bool BootControlAndroid::MarkSlotUnbootable(Slot slot) {
Connor O'Briencee6ad92016-11-21 13:53:52 -0800246 CommandResult result;
247 auto ret = module_->setSlotAsUnbootable(slot, StoreResultCallback(&result));
Yifan Hong7b514b42016-12-21 13:02:00 -0800248 if (!ret.isOk()) {
Connor O'Briencee6ad92016-11-21 13:53:52 -0800249 LOG(ERROR) << "Unable to call MarkSlotUnbootable for slot "
250 << SlotName(slot) << ": "
Yifan Hong7b514b42016-12-21 13:02:00 -0800251 << ret.description();
David Zeuthen753fadc2015-09-15 16:34:09 -0400252 return false;
253 }
Connor O'Briencee6ad92016-11-21 13:53:52 -0800254 if (!result.success) {
255 LOG(ERROR) << "Unable to mark slot " << SlotName(slot)
256 << " as unbootable: " << result.errMsg.c_str();
257 }
258 return result.success;
Alex Deymob17327c2015-09-04 10:29:00 -0700259}
260
Alex Deymo31d95ac2015-09-17 11:56:18 -0700261bool BootControlAndroid::SetActiveBootSlot(Slot slot) {
Connor O'Briencee6ad92016-11-21 13:53:52 -0800262 CommandResult result;
263 auto ret = module_->setActiveBootSlot(slot, StoreResultCallback(&result));
Yifan Hong7b514b42016-12-21 13:02:00 -0800264 if (!ret.isOk()) {
Connor O'Briencee6ad92016-11-21 13:53:52 -0800265 LOG(ERROR) << "Unable to call SetActiveBootSlot for slot " << SlotName(slot)
Yifan Hong7b514b42016-12-21 13:02:00 -0800266 << ": " << ret.description();
Connor O'Briencee6ad92016-11-21 13:53:52 -0800267 return false;
Alex Deymo29dcbf32016-10-06 13:33:20 -0700268 }
Connor O'Briencee6ad92016-11-21 13:53:52 -0800269 if (!result.success) {
270 LOG(ERROR) << "Unable to set the active slot to slot " << SlotName(slot)
271 << ": " << result.errMsg.c_str();
272 }
273 return result.success;
Alex Deymo31d95ac2015-09-17 11:56:18 -0700274}
275
Alex Deymoaa26f622015-09-16 18:21:27 -0700276bool BootControlAndroid::MarkBootSuccessfulAsync(
277 base::Callback<void(bool)> callback) {
Connor O'Briencee6ad92016-11-21 13:53:52 -0800278 CommandResult result;
279 auto ret = module_->markBootSuccessful(StoreResultCallback(&result));
Yifan Hong7b514b42016-12-21 13:02:00 -0800280 if (!ret.isOk()) {
Connor O'Briencee6ad92016-11-21 13:53:52 -0800281 LOG(ERROR) << "Unable to call MarkBootSuccessful: "
Yifan Hong7b514b42016-12-21 13:02:00 -0800282 << ret.description();
Connor O'Briencee6ad92016-11-21 13:53:52 -0800283 return false;
284 }
285 if (!result.success) {
286 LOG(ERROR) << "Unable to mark boot successful: " << result.errMsg.c_str();
Alex Deymoaa26f622015-09-16 18:21:27 -0700287 }
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700288 return brillo::MessageLoop::current()->PostTask(
Connor O'Briencee6ad92016-11-21 13:53:52 -0800289 FROM_HERE, base::Bind(callback, result.success)) !=
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700290 brillo::MessageLoop::kTaskIdNull;
Alex Deymoaa26f622015-09-16 18:21:27 -0700291}
292
Yifan Hong537802d2018-08-15 13:15:42 -0700293namespace {
294
Yifan Hong1d9077f2018-12-07 12:09:37 -0800295bool UpdatePartitionMetadata(DynamicPartitionControlInterface* dynamic_control,
296 Slot source_slot,
297 Slot target_slot,
298 const string& target_suffix,
299 const PartitionMetadata& partition_metadata) {
300 string device_dir_str;
301 if (!dynamic_control->GetDeviceDir(&device_dir_str)) {
302 return false;
303 }
304 base::FilePath device_dir(device_dir_str);
305 auto source_device =
306 device_dir.Append(fs_mgr_get_super_partition_name(source_slot)).value();
307
Yifan Hong6e706b12018-11-09 16:50:51 -0800308 auto builder = dynamic_control->LoadMetadataBuilder(
Yifan Hongb97e3ab2018-11-14 13:50:39 -0800309 source_device, source_slot, target_slot);
Yifan Hongd4db07e2018-10-18 17:46:27 -0700310 if (builder == nullptr) {
311 // TODO(elsk): allow reconstructing metadata from partition_metadata
312 // in recovery sideload.
313 LOG(ERROR) << "No metadata at "
314 << BootControlInterface::SlotName(source_slot);
Yifan Hong537802d2018-08-15 13:15:42 -0700315 return false;
316 }
317
Yifan Hongd4db07e2018-10-18 17:46:27 -0700318 std::vector<string> groups = builder->ListGroups();
319 for (const auto& group_name : groups) {
320 if (base::EndsWith(
321 group_name, target_suffix, base::CompareCase::SENSITIVE)) {
322 LOG(INFO) << "Removing group " << group_name;
323 builder->RemoveGroupAndPartitions(group_name);
324 }
325 }
326
327 uint64_t total_size = 0;
328 for (const auto& group : partition_metadata.groups) {
329 total_size += group.size;
330 }
331
Yifan Hong6e38b352018-11-19 14:12:37 -0800332 string expr;
333 uint64_t allocatable_space = builder->AllocatableSpace();
334 if (!dynamic_control->IsDynamicPartitionsRetrofit()) {
335 allocatable_space /= 2;
336 expr = "half of ";
337 }
338 if (total_size > allocatable_space) {
339 LOG(ERROR) << "The maximum size of all groups with suffix " << target_suffix
340 << " (" << total_size << ") has exceeded " << expr
Yifan Hong1d9077f2018-12-07 12:09:37 -0800341 << " allocatable space for dynamic partitions "
Yifan Hong6e38b352018-11-19 14:12:37 -0800342 << allocatable_space << ".";
Yifan Hong537802d2018-08-15 13:15:42 -0700343 return false;
344 }
345
Yifan Hongd4db07e2018-10-18 17:46:27 -0700346 for (const auto& group : partition_metadata.groups) {
347 auto group_name_suffix = group.name + target_suffix;
348 if (!builder->AddGroup(group_name_suffix, group.size)) {
349 LOG(ERROR) << "Cannot add group " << group_name_suffix << " with size "
350 << group.size;
351 return false;
352 }
353 LOG(INFO) << "Added group " << group_name_suffix << " with size "
354 << group.size;
355
356 for (const auto& partition : group.partitions) {
Yifan Honga7897f32018-11-15 14:28:50 -0800357 auto partition_name_suffix = partition.name + target_suffix;
Yifan Hongd4db07e2018-10-18 17:46:27 -0700358 Partition* p = builder->AddPartition(
Yifan Honga7897f32018-11-15 14:28:50 -0800359 partition_name_suffix, group_name_suffix, LP_PARTITION_ATTR_READONLY);
Yifan Hongd4db07e2018-10-18 17:46:27 -0700360 if (!p) {
Yifan Honga7897f32018-11-15 14:28:50 -0800361 LOG(ERROR) << "Cannot add partition " << partition_name_suffix
Yifan Hongd4db07e2018-10-18 17:46:27 -0700362 << " to group " << group_name_suffix;
363 return false;
364 }
365 if (!builder->ResizePartition(p, partition.size)) {
Yifan Honga7897f32018-11-15 14:28:50 -0800366 LOG(ERROR) << "Cannot resize partition " << partition_name_suffix
Yifan Hongd4db07e2018-10-18 17:46:27 -0700367 << " to size " << partition.size << ". Not enough space?";
368 return false;
369 }
Yifan Honga7897f32018-11-15 14:28:50 -0800370 LOG(INFO) << "Added partition " << partition_name_suffix << " to group "
Yifan Hongd4db07e2018-10-18 17:46:27 -0700371 << group_name_suffix << " with size " << partition.size;
372 }
Yifan Hong537802d2018-08-15 13:15:42 -0700373 }
374
Yifan Hong1d9077f2018-12-07 12:09:37 -0800375 auto target_device =
376 device_dir.Append(fs_mgr_get_super_partition_name(target_slot)).value();
Yifan Hongd4db07e2018-10-18 17:46:27 -0700377 return dynamic_control->StoreMetadata(
Yifan Hongb97e3ab2018-11-14 13:50:39 -0800378 target_device, builder.get(), target_slot);
Yifan Hong537802d2018-08-15 13:15:42 -0700379}
380
Yifan Hong1d9077f2018-12-07 12:09:37 -0800381bool UnmapTargetPartitions(DynamicPartitionControlInterface* dynamic_control,
382 const string& target_suffix,
383 const PartitionMetadata& partition_metadata) {
Yifan Hongd4db07e2018-10-18 17:46:27 -0700384 for (const auto& group : partition_metadata.groups) {
385 for (const auto& partition : group.partitions) {
386 if (!dynamic_control->UnmapPartitionOnDeviceMapper(
387 partition.name + target_suffix, true /* wait */)) {
388 return false;
389 }
Yifan Hong537802d2018-08-15 13:15:42 -0700390 }
Yifan Hong537802d2018-08-15 13:15:42 -0700391 }
392 return true;
393}
394
Yifan Hong537802d2018-08-15 13:15:42 -0700395} // namespace
396
397bool BootControlAndroid::InitPartitionMetadata(
Yifan Hong6b0a9842018-10-16 16:54:18 -0700398 Slot target_slot, const PartitionMetadata& partition_metadata) {
Yifan Hong537802d2018-08-15 13:15:42 -0700399 if (!dynamic_control_->IsDynamicPartitionsEnabled()) {
400 return true;
401 }
402
Yifan Hong1d9077f2018-12-07 12:09:37 -0800403 auto source_slot = GetCurrentSlot();
404 if (target_slot == source_slot) {
Yifan Hong537802d2018-08-15 13:15:42 -0700405 LOG(ERROR) << "Cannot call InitPartitionMetadata on current slot.";
406 return false;
407 }
408
Yifan Hong537802d2018-08-15 13:15:42 -0700409 string target_suffix;
410 if (!GetSuffix(target_slot, &target_suffix)) {
411 return false;
412 }
413
Yifan Hong1d9077f2018-12-07 12:09:37 -0800414 // Although the current build supports dynamic partitions, the given payload
415 // doesn't use it for target partitions. This could happen when applying a
416 // retrofit update. Skip updating the partition metadata for the target slot.
417 is_target_dynamic_ = !partition_metadata.groups.empty();
418 if (!is_target_dynamic_) {
419 return true;
420 }
421
422 // Unmap all the target dynamic partitions because they would become
423 // inconsistent with the new metadata.
424 if (!UnmapTargetPartitions(
425 dynamic_control_.get(), target_suffix, partition_metadata)) {
Yifan Hong537802d2018-08-15 13:15:42 -0700426 return false;
427 }
428
Yifan Hong1d9077f2018-12-07 12:09:37 -0800429 if (!UpdatePartitionMetadata(dynamic_control_.get(),
430 source_slot,
431 target_slot,
432 target_suffix,
433 partition_metadata)) {
Yifan Hong537802d2018-08-15 13:15:42 -0700434 return false;
435 }
436
Yifan Hong537802d2018-08-15 13:15:42 -0700437 return true;
438}
439
Alex Deymob17327c2015-09-04 10:29:00 -0700440} // namespace chromeos_update_engine