android_system_core/fastboot/device/utility.h
David Anderson d25f1c3775 fastbootd: Support two super partitions for retrofit devices.
Retrofit devices will have two super partitions, spanning the A and B
slots separately. By design an OTA will never cause "A" or "B"
partitions to be assigned to the wrong super. However, the same is not
true of fastbootd, where it is possible to flash the inactive slot. We
do not want, for example, logical "system_a" flashing to super_b.

When interacting with partitions, fastbootd now extracts the slot suffix
from a GetSuperSlotSuffix() helper. On retrofit devices, if the partition
name has a slot, that slot will override FastbootDevice::GetCurrentSlot.
This forces partitions in the inactive slot to be assigned to the correct
super.

There are two consequences of this. First, partitions with no slot
suffix will default to the current slot. That means it is possible to
wind up with two "scratch" partitions, if "adb remount" is used on both
the "A" and "B" slots. However, only the active slot's "scratch" will be
visible to the user (either through adb or fastboot).

Second, if one slot does not have dynamic partitions, flashing will
default to fixed partitions. For example, if the A slot is logical and B
is not, flashing "system_a" will be logical and "system_b" will be
fixed. This works no matter which slot is active. We do not try to
upgrade the inactive slot to dynamic partitions.

Bug: 116802789
Test: fastboot set_active a
      fastboot flashall # dynamic partitions
      fastboot getvar is-logical:system_a # true
      fastboot getvar is-logical:system_b # false
      fastboot set_active b
      fastboot flashall --skip-secondary
      fastboot getvar is-logical:system_a # true
      fastboot getvar is-logical:system_b # true
      Booting both slots works.

Change-Id: Ib3c91944aaee1a96b2f5ad69c90e215bd6c5a2e8
2018-11-20 13:47:01 -08:00

72 lines
2.8 KiB
C++

/*
* Copyright (C) 2018 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.
*/
#pragma once
#include <optional>
#include <string>
#include <android-base/unique_fd.h>
#include <android/hardware/boot/1.0/IBootControl.h>
#include <liblp/liblp.h>
// Logical partitions are only mapped to a block device as needed, and
// immediately unmapped when no longer needed. In order to enforce this we
// require accessing partitions through a Handle abstraction, which may perform
// additional operations after closing its file descriptor.
class PartitionHandle {
public:
PartitionHandle() {}
explicit PartitionHandle(const std::string& path) : path_(path) {}
PartitionHandle(const std::string& path, std::function<void()>&& closer)
: path_(path), closer_(std::move(closer)) {}
PartitionHandle(PartitionHandle&& other) = default;
PartitionHandle& operator=(PartitionHandle&& other) = default;
~PartitionHandle() {
if (closer_) {
// Make sure the device is closed first.
fd_ = {};
closer_();
}
}
const std::string& path() const { return path_; }
int fd() const { return fd_.get(); }
void set_fd(android::base::unique_fd&& fd) { fd_ = std::move(fd); }
private:
std::string path_;
android::base::unique_fd fd_;
std::function<void()> closer_;
};
class FastbootDevice;
// On normal devices, the super partition is always named "super". On retrofit
// devices, the name must be derived from the partition name or current slot.
// This helper assists in choosing the correct super for a given partition
// name.
std::string GetSuperSlotSuffix(FastbootDevice* device, const std::string& partition_name);
std::optional<std::string> FindPhysicalPartition(const std::string& name);
bool LogicalPartitionExists(FastbootDevice* device, const std::string& name,
bool* is_zero_length = nullptr);
bool OpenPartition(FastbootDevice* device, const std::string& name, PartitionHandle* handle);
bool GetSlotNumber(const std::string& slot, android::hardware::boot::V1_0::Slot* number);
std::vector<std::string> ListPartitions(FastbootDevice* device);
bool GetDeviceLockStatus();
// Update all copies of metadata.
bool UpdateAllPartitionMetadata(const std::string& super_name,
const android::fs_mgr::LpMetadata& metadata);