1 /*
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 "fastboot_device.h"
18 
19 #include <algorithm>
20 
21 #include <BootControlClient.h>
22 #include <android-base/logging.h>
23 #include <android-base/properties.h>
24 #include <android-base/strings.h>
25 #include <android/binder_manager.h>
26 #include <android/hardware/boot/1.0/IBootControl.h>
27 #include <android/hardware/fastboot/1.1/IFastboot.h>
28 #include <fastbootshim.h>
29 #include <fs_mgr.h>
30 #include <fs_mgr/roots.h>
31 #include <health-shim/shim.h>
32 #include <healthhalutils/HealthHalUtils.h>
33 
34 #include "constants.h"
35 #include "flashing.h"
36 #include "tcp_client.h"
37 #include "usb_client.h"
38 
39 using std::string_literals::operator""s;
40 using android::fs_mgr::EnsurePathUnmounted;
41 using android::fs_mgr::Fstab;
42 using ::android::hardware::hidl_string;
43 using ::android::hardware::fastboot::V1_1::IFastboot;
44 using BootControlClient = FastbootDevice::BootControlClient;
45 
46 namespace sph = std::placeholders;
47 
get_health_service()48 std::shared_ptr<aidl::android::hardware::health::IHealth> get_health_service() {
49     using aidl::android::hardware::health::IHealth;
50     using HidlHealth = android::hardware::health::V2_0::IHealth;
51     using aidl::android::hardware::health::HealthShim;
52     auto service_name = IHealth::descriptor + "/default"s;
53     if (AServiceManager_isDeclared(service_name.c_str())) {
54         ndk::SpAIBinder binder(AServiceManager_waitForService(service_name.c_str()));
55         std::shared_ptr<IHealth> health = IHealth::fromBinder(binder);
56         if (health != nullptr) return health;
57         LOG(WARNING) << "AIDL health service is declared, but it cannot be retrieved.";
58     }
59     LOG(INFO) << "Unable to get AIDL health service, trying HIDL...";
60     android::sp<HidlHealth> hidl_health = android::hardware::health::V2_0::get_health_service();
61     if (hidl_health != nullptr) {
62         return ndk::SharedRefBase::make<HealthShim>(hidl_health);
63     }
64     LOG(WARNING) << "No health implementation is found.";
65     return nullptr;
66 }
67 
get_fastboot_service()68 std::shared_ptr<aidl::android::hardware::fastboot::IFastboot> get_fastboot_service() {
69     using aidl::android::hardware::fastboot::IFastboot;
70     using HidlFastboot = android::hardware::fastboot::V1_1::IFastboot;
71     using aidl::android::hardware::fastboot::FastbootShim;
72     auto service_name = IFastboot::descriptor + "/default"s;
73     if (AServiceManager_isDeclared(service_name.c_str())) {
74         ndk::SpAIBinder binder(AServiceManager_waitForService(service_name.c_str()));
75         std::shared_ptr<IFastboot> fastboot = IFastboot::fromBinder(binder);
76         if (fastboot != nullptr) {
77             LOG(INFO) << "Found and using AIDL fastboot service";
78             return fastboot;
79         }
80         LOG(WARNING) << "AIDL fastboot service is declared, but it cannot be retrieved.";
81     }
82     LOG(INFO) << "Unable to get AIDL fastboot service, trying HIDL...";
83     android::sp<HidlFastboot> hidl_fastboot = HidlFastboot::getService();
84     if (hidl_fastboot != nullptr) {
85         LOG(INFO) << "Found and now using fastboot HIDL implementation";
86         return ndk::SharedRefBase::make<FastbootShim>(hidl_fastboot);
87     }
88     LOG(WARNING) << "No fastboot implementation is found.";
89     return nullptr;
90 }
91 
FastbootDevice()92 FastbootDevice::FastbootDevice()
93     : kCommandMap({
94               {FB_CMD_SET_ACTIVE, SetActiveHandler},
95               {FB_CMD_DOWNLOAD, DownloadHandler},
96               {FB_CMD_GETVAR, GetVarHandler},
97               {FB_CMD_SHUTDOWN, ShutDownHandler},
98               {FB_CMD_REBOOT, RebootHandler},
99               {FB_CMD_REBOOT_BOOTLOADER, RebootBootloaderHandler},
100               {FB_CMD_REBOOT_FASTBOOT, RebootFastbootHandler},
101               {FB_CMD_REBOOT_RECOVERY, RebootRecoveryHandler},
102               {FB_CMD_ERASE, EraseHandler},
103               {FB_CMD_FLASH, FlashHandler},
104               {FB_CMD_CREATE_PARTITION, CreatePartitionHandler},
105               {FB_CMD_DELETE_PARTITION, DeletePartitionHandler},
106               {FB_CMD_RESIZE_PARTITION, ResizePartitionHandler},
107               {FB_CMD_UPDATE_SUPER, UpdateSuperHandler},
108               {FB_CMD_OEM, OemCmdHandler},
109               {FB_CMD_GSI, GsiHandler},
110               {FB_CMD_SNAPSHOT_UPDATE, SnapshotUpdateHandler},
111               {FB_CMD_FETCH, FetchHandler},
112       }),
113       boot_control_hal_(BootControlClient::WaitForService()),
114       health_hal_(get_health_service()),
115       fastboot_hal_(get_fastboot_service()),
116       active_slot_("") {
117     if (android::base::GetProperty("fastbootd.protocol", "usb") == "tcp") {
118         transport_ = std::make_unique<ClientTcpTransport>();
119     } else {
120         transport_ = std::make_unique<ClientUsbTransport>();
121     }
122 
123     // Make sure cache is unmounted, since recovery will have mounted it for
124     // logging.
125     Fstab fstab;
126     if (ReadDefaultFstab(&fstab)) {
127         EnsurePathUnmounted(&fstab, "/cache");
128     }
129 }
130 
~FastbootDevice()131 FastbootDevice::~FastbootDevice() {
132     CloseDevice();
133 }
134 
CloseDevice()135 void FastbootDevice::CloseDevice() {
136     transport_->Close();
137 }
138 
GetCurrentSlot()139 std::string FastbootDevice::GetCurrentSlot() {
140     // Check if a set_active ccommand was issued earlier since the boot control HAL
141     // returns the slot that is currently booted into.
142     if (!active_slot_.empty()) {
143         return active_slot_;
144     }
145     // Non-A/B devices must not have boot control HALs.
146     if (!boot_control_hal_) {
147         return "";
148     }
149     std::string suffix = boot_control_hal_->GetSuffix(boot_control_hal_->GetCurrentSlot());
150     return suffix;
151 }
152 
boot1_1() const153 BootControlClient* FastbootDevice::boot1_1() const {
154     if (boot_control_hal_ &&
155         boot_control_hal_->GetVersion() >= android::hal::BootControlVersion::BOOTCTL_V1_1) {
156         return boot_control_hal_.get();
157     }
158     return nullptr;
159 }
160 
WriteStatus(FastbootResult result,const std::string & message)161 bool FastbootDevice::WriteStatus(FastbootResult result, const std::string& message) {
162     constexpr size_t kResponseReasonSize = 4;
163     constexpr size_t kNumResponseTypes = 4;  // "FAIL", "OKAY", "INFO", "DATA"
164 
165     char buf[FB_RESPONSE_SZ];
166     constexpr size_t kMaxMessageSize = sizeof(buf) - kResponseReasonSize;
167     size_t msg_len = std::min(kMaxMessageSize, message.size());
168 
169     constexpr const char* kResultStrings[kNumResponseTypes] = {RESPONSE_OKAY, RESPONSE_FAIL,
170                                                                RESPONSE_INFO, RESPONSE_DATA};
171 
172     if (static_cast<size_t>(result) >= kNumResponseTypes) {
173         return false;
174     }
175 
176     memcpy(buf, kResultStrings[static_cast<size_t>(result)], kResponseReasonSize);
177     memcpy(buf + kResponseReasonSize, message.c_str(), msg_len);
178 
179     size_t response_len = kResponseReasonSize + msg_len;
180     auto write_ret = this->get_transport()->Write(buf, response_len);
181     if (write_ret != static_cast<ssize_t>(response_len)) {
182         PLOG(ERROR) << "Failed to write " << message;
183         return false;
184     }
185 
186     return true;
187 }
188 
HandleData(bool read,std::vector<char> * data)189 bool FastbootDevice::HandleData(bool read, std::vector<char>* data) {
190     return HandleData(read, data->data(), data->size());
191 }
192 
HandleData(bool read,char * data,uint64_t size)193 bool FastbootDevice::HandleData(bool read, char* data, uint64_t size) {
194     auto read_write_data_size = read ? this->get_transport()->Read(data, size)
195                                      : this->get_transport()->Write(data, size);
196     if (read_write_data_size == -1) {
197         LOG(ERROR) << (read ? "read from" : "write to") << " transport failed";
198         return false;
199     }
200     if (static_cast<size_t>(read_write_data_size) != size) {
201         LOG(ERROR) << (read ? "read" : "write") << " expected " << size << " bytes, got "
202                    << read_write_data_size;
203         return false;
204     }
205     return true;
206 }
207 
ExecuteCommands()208 void FastbootDevice::ExecuteCommands() {
209     char command[FB_RESPONSE_SZ + 1];
210     for (;;) {
211         auto bytes_read = transport_->Read(command, FB_RESPONSE_SZ);
212         if (bytes_read == -1) {
213             PLOG(ERROR) << "Couldn't read command";
214             return;
215         }
216         if (std::count_if(command, command + bytes_read, iscntrl) != 0) {
217             WriteStatus(FastbootResult::FAIL,
218                         "Command contains control character");
219             continue;
220         }
221         command[bytes_read] = '\0';
222 
223         LOG(INFO) << "Fastboot command: " << command;
224 
225         std::vector<std::string> args;
226         std::string cmd_name;
227         if (android::base::StartsWith(command, "oem ")) {
228             args = {command};
229             cmd_name = FB_CMD_OEM;
230         } else {
231             args = android::base::Split(command, ":");
232             cmd_name = args[0];
233         }
234 
235         auto found_command = kCommandMap.find(cmd_name);
236         if (found_command == kCommandMap.end()) {
237             WriteStatus(FastbootResult::FAIL, "Unrecognized command " + args[0]);
238             continue;
239         }
240         if (!found_command->second(this, args)) {
241             return;
242         }
243     }
244 }
245 
WriteOkay(const std::string & message)246 bool FastbootDevice::WriteOkay(const std::string& message) {
247     return WriteStatus(FastbootResult::OKAY, message);
248 }
249 
WriteFail(const std::string & message)250 bool FastbootDevice::WriteFail(const std::string& message) {
251     return WriteStatus(FastbootResult::FAIL, message);
252 }
253 
WriteInfo(const std::string & message)254 bool FastbootDevice::WriteInfo(const std::string& message) {
255     return WriteStatus(FastbootResult::INFO, message);
256 }
257