2018-07-20 22:35:50 +02:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "utility.h"
|
|
|
|
|
2018-09-01 01:44:25 +02:00
|
|
|
#include <dirent.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
2018-09-25 01:01:35 +02:00
|
|
|
#include <android-base/file.h>
|
2018-07-25 00:21:20 +02:00
|
|
|
#include <android-base/logging.h>
|
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-10 05:41:33 +01:00
|
|
|
#include <android-base/properties.h>
|
2018-10-08 20:06:38 +02:00
|
|
|
#include <android-base/strings.h>
|
2018-09-27 19:53:04 +02:00
|
|
|
#include <fs_mgr.h>
|
2019-12-17 09:58:31 +01:00
|
|
|
#include <fs_mgr/roots.h>
|
2018-08-09 19:40:00 +02:00
|
|
|
#include <fs_mgr_dm_linear.h>
|
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-10 05:41:33 +01:00
|
|
|
#include <liblp/builder.h>
|
2018-08-09 19:40:00 +02:00
|
|
|
#include <liblp/liblp.h>
|
2018-07-25 00:21:20 +02:00
|
|
|
|
|
|
|
#include "fastboot_device.h"
|
|
|
|
|
2018-08-09 19:40:00 +02:00
|
|
|
using namespace android::fs_mgr;
|
2018-09-07 02:25:03 +02:00
|
|
|
using namespace std::chrono_literals;
|
2018-07-25 00:21:20 +02:00
|
|
|
using android::base::unique_fd;
|
2018-07-20 22:35:50 +02:00
|
|
|
using android::hardware::boot::V1_0::Slot;
|
|
|
|
|
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-10 05:41:33 +01:00
|
|
|
namespace {
|
|
|
|
|
|
|
|
bool OpenPhysicalPartition(const std::string& name, PartitionHandle* handle) {
|
2018-07-25 00:21:20 +02:00
|
|
|
std::optional<std::string> path = FindPhysicalPartition(name);
|
|
|
|
if (!path) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
*handle = PartitionHandle(*path);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
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-10 05:41:33 +01:00
|
|
|
bool OpenLogicalPartition(FastbootDevice* device, const std::string& partition_name,
|
|
|
|
PartitionHandle* handle) {
|
|
|
|
std::string slot_suffix = GetSuperSlotSuffix(device, partition_name);
|
|
|
|
uint32_t slot_number = SlotNumberForSlotSuffix(slot_suffix);
|
|
|
|
auto path = FindPhysicalPartition(fs_mgr_get_super_partition_name(slot_number));
|
2018-08-09 19:40:00 +02:00
|
|
|
if (!path) {
|
|
|
|
return false;
|
|
|
|
}
|
2019-08-13 02:07:50 +02:00
|
|
|
|
|
|
|
CreateLogicalPartitionParams params = {
|
|
|
|
.block_device = *path,
|
|
|
|
.metadata_slot = slot_number,
|
|
|
|
.partition_name = partition_name,
|
|
|
|
.force_writable = true,
|
|
|
|
.timeout_ms = 5s,
|
|
|
|
};
|
2018-08-09 19:40:00 +02:00
|
|
|
std::string dm_path;
|
2019-08-13 02:07:50 +02:00
|
|
|
if (!CreateLogicalPartition(params, &dm_path)) {
|
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-10 05:41:33 +01:00
|
|
|
LOG(ERROR) << "Could not map partition: " << partition_name;
|
2018-08-09 19:40:00 +02:00
|
|
|
return false;
|
|
|
|
}
|
2019-07-11 03:09:50 +02:00
|
|
|
auto closer = [partition_name]() -> void { DestroyLogicalPartition(partition_name); };
|
2018-08-09 19:40:00 +02:00
|
|
|
*handle = PartitionHandle(dm_path, std::move(closer));
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
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-10 05:41:33 +01:00
|
|
|
} // namespace
|
|
|
|
|
2021-02-18 21:35:42 +01:00
|
|
|
bool OpenPartition(FastbootDevice* device, const std::string& name, PartitionHandle* handle,
|
2021-11-04 18:27:06 +01:00
|
|
|
int flags) {
|
2018-08-09 19:40:00 +02:00
|
|
|
// We prioritize logical partitions over physical ones, and do this
|
|
|
|
// consistently for other partition operations (like getvar:partition-size).
|
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-10 05:41:33 +01:00
|
|
|
if (LogicalPartitionExists(device, name)) {
|
|
|
|
if (!OpenLogicalPartition(device, name, handle)) {
|
2018-08-09 19:40:00 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} else if (!OpenPhysicalPartition(name, handle)) {
|
2018-07-25 00:21:20 +02:00
|
|
|
LOG(ERROR) << "No such partition: " << name;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-02-19 01:03:59 +01:00
|
|
|
flags |= (O_EXCL | O_CLOEXEC | O_BINARY);
|
2021-02-18 21:35:42 +01:00
|
|
|
unique_fd fd(TEMP_FAILURE_RETRY(open(handle->path().c_str(), flags)));
|
2018-07-25 00:21:20 +02:00
|
|
|
if (fd < 0) {
|
|
|
|
PLOG(ERROR) << "Failed to open block device: " << handle->path();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
handle->set_fd(std::move(fd));
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::optional<std::string> FindPhysicalPartition(const std::string& name) {
|
2018-10-08 20:06:38 +02:00
|
|
|
// Check for an invalid file name
|
|
|
|
if (android::base::StartsWith(name, "../") || name.find("/../") != std::string::npos) {
|
|
|
|
return {};
|
|
|
|
}
|
2018-07-25 00:21:20 +02:00
|
|
|
std::string path = "/dev/block/by-name/" + name;
|
2018-09-05 21:07:33 +02:00
|
|
|
if (access(path.c_str(), W_OK) < 0) {
|
2018-07-25 00:21:20 +02:00
|
|
|
return {};
|
|
|
|
}
|
|
|
|
return path;
|
|
|
|
}
|
|
|
|
|
2018-08-09 19:40:00 +02:00
|
|
|
static const LpMetadataPartition* FindLogicalPartition(const LpMetadata& metadata,
|
|
|
|
const std::string& name) {
|
|
|
|
for (const auto& partition : metadata.partitions) {
|
|
|
|
if (GetPartitionName(partition) == name) {
|
|
|
|
return &partition;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
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-10 05:41:33 +01:00
|
|
|
bool LogicalPartitionExists(FastbootDevice* device, const std::string& name, bool* is_zero_length) {
|
|
|
|
std::string slot_suffix = GetSuperSlotSuffix(device, name);
|
|
|
|
uint32_t slot_number = SlotNumberForSlotSuffix(slot_suffix);
|
|
|
|
auto path = FindPhysicalPartition(fs_mgr_get_super_partition_name(slot_number));
|
2018-08-09 19:40:00 +02:00
|
|
|
if (!path) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::unique_ptr<LpMetadata> metadata = ReadMetadata(path->c_str(), slot_number);
|
|
|
|
if (!metadata) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
const LpMetadataPartition* partition = FindLogicalPartition(*metadata.get(), name);
|
|
|
|
if (!partition) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (is_zero_length) {
|
|
|
|
*is_zero_length = (partition->num_extents == 0);
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-07-20 22:35:50 +02:00
|
|
|
bool GetSlotNumber(const std::string& slot, Slot* number) {
|
|
|
|
if (slot.size() != 1) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (slot[0] < 'a' || slot[0] > 'z') {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
*number = slot[0] - 'a';
|
|
|
|
return true;
|
|
|
|
}
|
2018-09-01 01:44:25 +02:00
|
|
|
|
|
|
|
std::vector<std::string> ListPartitions(FastbootDevice* device) {
|
|
|
|
std::vector<std::string> partitions;
|
|
|
|
|
|
|
|
// First get physical partitions.
|
|
|
|
struct dirent* de;
|
|
|
|
std::unique_ptr<DIR, decltype(&closedir)> by_name(opendir("/dev/block/by-name"), closedir);
|
|
|
|
while ((de = readdir(by_name.get())) != nullptr) {
|
|
|
|
if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
struct stat s;
|
|
|
|
std::string path = "/dev/block/by-name/" + std::string(de->d_name);
|
|
|
|
if (!stat(path.c_str(), &s) && S_ISBLK(s.st_mode)) {
|
|
|
|
partitions.emplace_back(de->d_name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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-10 05:41:33 +01:00
|
|
|
// Find metadata in each super partition (on retrofit devices, there will
|
|
|
|
// be two).
|
|
|
|
std::vector<std::unique_ptr<LpMetadata>> metadata_list;
|
|
|
|
|
|
|
|
uint32_t current_slot = SlotNumberForSlotSuffix(device->GetCurrentSlot());
|
|
|
|
std::string super_name = fs_mgr_get_super_partition_name(current_slot);
|
|
|
|
if (auto metadata = ReadMetadata(super_name, current_slot)) {
|
|
|
|
metadata_list.emplace_back(std::move(metadata));
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t other_slot = (current_slot == 0) ? 1 : 0;
|
|
|
|
std::string other_super = fs_mgr_get_super_partition_name(other_slot);
|
|
|
|
if (super_name != other_super) {
|
|
|
|
if (auto metadata = ReadMetadata(other_super, other_slot)) {
|
|
|
|
metadata_list.emplace_back(std::move(metadata));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (const auto& metadata : metadata_list) {
|
|
|
|
for (const auto& partition : metadata->partitions) {
|
|
|
|
std::string partition_name = GetPartitionName(partition);
|
|
|
|
if (std::find(partitions.begin(), partitions.end(), partition_name) ==
|
|
|
|
partitions.end()) {
|
2018-09-01 01:44:25 +02:00
|
|
|
partitions.emplace_back(partition_name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return partitions;
|
|
|
|
}
|
2018-09-25 01:01:35 +02:00
|
|
|
|
|
|
|
bool GetDeviceLockStatus() {
|
2021-03-25 19:41:38 +01:00
|
|
|
return android::base::GetProperty("ro.boot.verifiedbootstate", "") != "orange";
|
2018-09-25 01:01:35 +02:00
|
|
|
}
|
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-10 05:41:33 +01:00
|
|
|
|
2018-12-18 02:07:34 +01:00
|
|
|
bool UpdateAllPartitionMetadata(FastbootDevice* device, const std::string& super_name,
|
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-10 05:41:33 +01:00
|
|
|
const android::fs_mgr::LpMetadata& metadata) {
|
2018-12-18 02:07:34 +01:00
|
|
|
size_t num_slots = 1;
|
|
|
|
auto boot_control_hal = device->boot_control_hal();
|
|
|
|
if (boot_control_hal) {
|
|
|
|
num_slots = boot_control_hal->getNumberSlots();
|
|
|
|
}
|
|
|
|
|
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-10 05:41:33 +01:00
|
|
|
bool ok = true;
|
2018-12-18 02:07:34 +01:00
|
|
|
for (size_t i = 0; i < num_slots; i++) {
|
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-10 05:41:33 +01:00
|
|
|
ok &= UpdatePartitionTable(super_name, metadata, i);
|
|
|
|
}
|
|
|
|
return ok;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string GetSuperSlotSuffix(FastbootDevice* device, const std::string& partition_name) {
|
|
|
|
// If the super partition does not have a slot suffix, this is not a
|
|
|
|
// retrofit device, and we should take the current slot.
|
|
|
|
std::string current_slot_suffix = device->GetCurrentSlot();
|
|
|
|
uint32_t current_slot_number = SlotNumberForSlotSuffix(current_slot_suffix);
|
|
|
|
std::string super_partition = fs_mgr_get_super_partition_name(current_slot_number);
|
|
|
|
if (GetPartitionSlotSuffix(super_partition).empty()) {
|
|
|
|
return current_slot_suffix;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise, infer the slot from the partition name.
|
|
|
|
std::string slot_suffix = GetPartitionSlotSuffix(partition_name);
|
|
|
|
if (!slot_suffix.empty()) {
|
|
|
|
return slot_suffix;
|
|
|
|
}
|
|
|
|
return current_slot_suffix;
|
|
|
|
}
|
2019-12-17 09:58:31 +01:00
|
|
|
|
|
|
|
AutoMountMetadata::AutoMountMetadata() {
|
|
|
|
android::fs_mgr::Fstab proc_mounts;
|
|
|
|
if (!ReadFstabFromFile("/proc/mounts", &proc_mounts)) {
|
|
|
|
LOG(ERROR) << "Could not read /proc/mounts";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (GetEntryForMountPoint(&proc_mounts, "/metadata")) {
|
|
|
|
mounted_ = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!ReadDefaultFstab(&fstab_)) {
|
|
|
|
LOG(ERROR) << "Could not read default fstab";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
mounted_ = EnsurePathMounted(&fstab_, "/metadata");
|
|
|
|
should_unmount_ = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
AutoMountMetadata::~AutoMountMetadata() {
|
|
|
|
if (mounted_ && should_unmount_) {
|
|
|
|
EnsurePathUnmounted(&fstab_, "/metadata");
|
|
|
|
}
|
|
|
|
}
|