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