• 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 <android-base/logging.h>
20 #include <android-base/strings.h>
21 #include <android/hardware/boot/1.0/IBootControl.h>
22 #include <android/hardware/fastboot/1.0/IFastboot.h>
23 #include <healthhalutils/HealthHalUtils.h>
24 
25 #include <algorithm>
26 
27 #include "constants.h"
28 #include "flashing.h"
29 #include "usb_client.h"
30 
31 using ::android::hardware::hidl_string;
32 using ::android::hardware::boot::V1_0::IBootControl;
33 using ::android::hardware::boot::V1_0::Slot;
34 using ::android::hardware::fastboot::V1_0::IFastboot;
35 using ::android::hardware::health::V2_0::get_health_service;
36 
37 namespace sph = std::placeholders;
38 
FastbootDevice()39 FastbootDevice::FastbootDevice()
40     : kCommandMap({
41               {FB_CMD_SET_ACTIVE, SetActiveHandler},
42               {FB_CMD_DOWNLOAD, DownloadHandler},
43               {FB_CMD_GETVAR, GetVarHandler},
44               {FB_CMD_SHUTDOWN, ShutDownHandler},
45               {FB_CMD_REBOOT, RebootHandler},
46               {FB_CMD_REBOOT_BOOTLOADER, RebootBootloaderHandler},
47               {FB_CMD_REBOOT_FASTBOOT, RebootFastbootHandler},
48               {FB_CMD_REBOOT_RECOVERY, RebootRecoveryHandler},
49               {FB_CMD_ERASE, EraseHandler},
50               {FB_CMD_FLASH, FlashHandler},
51               {FB_CMD_CREATE_PARTITION, CreatePartitionHandler},
52               {FB_CMD_DELETE_PARTITION, DeletePartitionHandler},
53               {FB_CMD_RESIZE_PARTITION, ResizePartitionHandler},
54               {FB_CMD_UPDATE_SUPER, UpdateSuperHandler},
55               {FB_CMD_OEM, OemCmdHandler},
56               {FB_CMD_GSI, GsiHandler},
57       }),
58       transport_(std::make_unique<ClientUsbTransport>()),
59       boot_control_hal_(IBootControl::getService()),
60       health_hal_(get_health_service()),
61       fastboot_hal_(IFastboot::getService()),
62       active_slot_("") {}
63 
~FastbootDevice()64 FastbootDevice::~FastbootDevice() {
65     CloseDevice();
66 }
67 
CloseDevice()68 void FastbootDevice::CloseDevice() {
69     transport_->Close();
70 }
71 
GetCurrentSlot()72 std::string FastbootDevice::GetCurrentSlot() {
73     // Check if a set_active ccommand was issued earlier since the boot control HAL
74     // returns the slot that is currently booted into.
75     if (!active_slot_.empty()) {
76         return active_slot_;
77     }
78     // Non-A/B devices must not have boot control HALs.
79     if (!boot_control_hal_) {
80         return "";
81     }
82     std::string suffix;
83     auto cb = [&suffix](hidl_string s) { suffix = s; };
84     boot_control_hal_->getSuffix(boot_control_hal_->getCurrentSlot(), cb);
85     return suffix;
86 }
87 
WriteStatus(FastbootResult result,const std::string & message)88 bool FastbootDevice::WriteStatus(FastbootResult result, const std::string& message) {
89     constexpr size_t kResponseReasonSize = 4;
90     constexpr size_t kNumResponseTypes = 4;  // "FAIL", "OKAY", "INFO", "DATA"
91 
92     char buf[FB_RESPONSE_SZ];
93     constexpr size_t kMaxMessageSize = sizeof(buf) - kResponseReasonSize;
94     size_t msg_len = std::min(kMaxMessageSize, message.size());
95 
96     constexpr const char* kResultStrings[kNumResponseTypes] = {RESPONSE_OKAY, RESPONSE_FAIL,
97                                                                RESPONSE_INFO, RESPONSE_DATA};
98 
99     if (static_cast<size_t>(result) >= kNumResponseTypes) {
100         return false;
101     }
102 
103     memcpy(buf, kResultStrings[static_cast<size_t>(result)], kResponseReasonSize);
104     memcpy(buf + kResponseReasonSize, message.c_str(), msg_len);
105 
106     size_t response_len = kResponseReasonSize + msg_len;
107     auto write_ret = this->get_transport()->Write(buf, response_len);
108     if (write_ret != static_cast<ssize_t>(response_len)) {
109         PLOG(ERROR) << "Failed to write " << message;
110         return false;
111     }
112 
113     return true;
114 }
115 
HandleData(bool read,std::vector<char> * data)116 bool FastbootDevice::HandleData(bool read, std::vector<char>* data) {
117     auto read_write_data_size = read ? this->get_transport()->Read(data->data(), data->size())
118                                      : this->get_transport()->Write(data->data(), data->size());
119     if (read_write_data_size == -1 || static_cast<size_t>(read_write_data_size) != data->size()) {
120         return false;
121     }
122     return true;
123 }
124 
ExecuteCommands()125 void FastbootDevice::ExecuteCommands() {
126     char command[FB_RESPONSE_SZ + 1];
127     for (;;) {
128         auto bytes_read = transport_->Read(command, FB_RESPONSE_SZ);
129         if (bytes_read == -1) {
130             PLOG(ERROR) << "Couldn't read command";
131             return;
132         }
133         command[bytes_read] = '\0';
134 
135         LOG(INFO) << "Fastboot command: " << command;
136 
137         std::vector<std::string> args;
138         std::string cmd_name;
139         if (android::base::StartsWith(command, "oem ")) {
140             args = {command};
141             cmd_name = FB_CMD_OEM;
142         } else {
143             args = android::base::Split(command, ":");
144             cmd_name = args[0];
145         }
146 
147         auto found_command = kCommandMap.find(cmd_name);
148         if (found_command == kCommandMap.end()) {
149             WriteStatus(FastbootResult::FAIL, "Unrecognized command " + args[0]);
150             continue;
151         }
152         if (!found_command->second(this, args)) {
153             return;
154         }
155     }
156 }
157 
WriteOkay(const std::string & message)158 bool FastbootDevice::WriteOkay(const std::string& message) {
159     return WriteStatus(FastbootResult::OKAY, message);
160 }
161 
WriteFail(const std::string & message)162 bool FastbootDevice::WriteFail(const std::string& message) {
163     return WriteStatus(FastbootResult::FAIL, message);
164 }
165 
WriteInfo(const std::string & message)166 bool FastbootDevice::WriteInfo(const std::string& message) {
167     return WriteStatus(FastbootResult::INFO, message);
168 }
169