blob: ec84576ced85e8a035ae4b8824af5aca3a3861f8 [file] [log] [blame]
Hridya Valsaraju31d2c262018-07-20 13:35:50 -07001/*
2 * Copyright (C) 2018 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
17#include "utility.h"
18
David Anderson12211d12018-07-24 15:21:20 -070019#include <android-base/logging.h>
David Anderson88ef0b12018-08-09 10:40:00 -070020#include <fs_mgr_dm_linear.h>
21#include <liblp/liblp.h>
David Anderson12211d12018-07-24 15:21:20 -070022
23#include "fastboot_device.h"
24
David Anderson88ef0b12018-08-09 10:40:00 -070025using namespace android::fs_mgr;
David Anderson12211d12018-07-24 15:21:20 -070026using android::base::unique_fd;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -070027using android::hardware::boot::V1_0::Slot;
28
David Anderson12211d12018-07-24 15:21:20 -070029static bool OpenPhysicalPartition(const std::string& name, PartitionHandle* handle) {
30 std::optional<std::string> path = FindPhysicalPartition(name);
31 if (!path) {
32 return false;
33 }
34 *handle = PartitionHandle(*path);
35 return true;
36}
37
David Anderson88ef0b12018-08-09 10:40:00 -070038static bool OpenLogicalPartition(const std::string& name, const std::string& slot,
39 PartitionHandle* handle) {
40 std::optional<std::string> path = FindPhysicalPartition(LP_METADATA_PARTITION_NAME);
41 if (!path) {
42 return false;
43 }
44 uint32_t slot_number = SlotNumberForSlotSuffix(slot);
45 std::string dm_path;
46 if (!CreateLogicalPartition(path->c_str(), slot_number, name, true, &dm_path)) {
47 LOG(ERROR) << "Could not map partition: " << name;
48 return false;
49 }
50 auto closer = [name]() -> void { DestroyLogicalPartition(name); };
51 *handle = PartitionHandle(dm_path, std::move(closer));
52 return true;
53}
54
55bool OpenPartition(FastbootDevice* device, const std::string& name, PartitionHandle* handle) {
56 // We prioritize logical partitions over physical ones, and do this
57 // consistently for other partition operations (like getvar:partition-size).
58 if (LogicalPartitionExists(name, device->GetCurrentSlot())) {
59 if (!OpenLogicalPartition(name, device->GetCurrentSlot(), handle)) {
60 return false;
61 }
62 } else if (!OpenPhysicalPartition(name, handle)) {
David Anderson12211d12018-07-24 15:21:20 -070063 LOG(ERROR) << "No such partition: " << name;
64 return false;
65 }
66
67 unique_fd fd(TEMP_FAILURE_RETRY(open(handle->path().c_str(), O_WRONLY | O_EXCL)));
68 if (fd < 0) {
69 PLOG(ERROR) << "Failed to open block device: " << handle->path();
70 return false;
71 }
72 handle->set_fd(std::move(fd));
73 return true;
74}
75
76std::optional<std::string> FindPhysicalPartition(const std::string& name) {
77 std::string path = "/dev/block/by-name/" + name;
78 if (access(path.c_str(), R_OK | W_OK) < 0) {
79 return {};
80 }
81 return path;
82}
83
David Anderson88ef0b12018-08-09 10:40:00 -070084static const LpMetadataPartition* FindLogicalPartition(const LpMetadata& metadata,
85 const std::string& name) {
86 for (const auto& partition : metadata.partitions) {
87 if (GetPartitionName(partition) == name) {
88 return &partition;
89 }
90 }
91 return nullptr;
92}
93
94bool LogicalPartitionExists(const std::string& name, const std::string& slot_suffix,
95 bool* is_zero_length) {
96 auto path = FindPhysicalPartition(LP_METADATA_PARTITION_NAME);
97 if (!path) {
98 return false;
99 }
100
101 uint32_t slot_number = SlotNumberForSlotSuffix(slot_suffix);
102 std::unique_ptr<LpMetadata> metadata = ReadMetadata(path->c_str(), slot_number);
103 if (!metadata) {
104 return false;
105 }
106 const LpMetadataPartition* partition = FindLogicalPartition(*metadata.get(), name);
107 if (!partition) {
108 return false;
109 }
110 if (is_zero_length) {
111 *is_zero_length = (partition->num_extents == 0);
112 }
113 return true;
114}
115
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700116bool GetSlotNumber(const std::string& slot, Slot* number) {
117 if (slot.size() != 1) {
118 return false;
119 }
120 if (slot[0] < 'a' || slot[0] > 'z') {
121 return false;
122 }
123 *number = slot[0] - 'a';
124 return true;
125}