blob: 35f3de020cb6d8cc7a157bfe74d72df86aabd03f [file] [log] [blame]
Hridya Valsarajudea91b42018-07-17 11:14:01 -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 "fastboot_device.h"
18
David Anderson2ffc31b2020-03-23 23:43:45 -070019#include <algorithm>
20
Hridya Valsarajudea91b42018-07-17 11:14:01 -070021#include <android-base/logging.h>
Hongguang Chen1e239282020-04-22 14:25:45 -070022#include <android-base/properties.h>
Hridya Valsarajudea91b42018-07-17 11:14:01 -070023#include <android-base/strings.h>
Hridya Valsaraju31d2c262018-07-20 13:35:50 -070024#include <android/hardware/boot/1.0/IBootControl.h>
josephjang29069752020-09-23 16:28:03 +080025#include <android/hardware/fastboot/1.1/IFastboot.h>
David Anderson2ffc31b2020-03-23 23:43:45 -070026#include <fs_mgr.h>
27#include <fs_mgr/roots.h>
Hridya Valsaraju47658ca2018-09-28 11:41:22 -070028#include <healthhalutils/HealthHalUtils.h>
29
Hridya Valsarajudea91b42018-07-17 11:14:01 -070030#include "constants.h"
David Anderson12211d12018-07-24 15:21:20 -070031#include "flashing.h"
Hongguang Chen1e239282020-04-22 14:25:45 -070032#include "tcp_client.h"
Hridya Valsarajudea91b42018-07-17 11:14:01 -070033#include "usb_client.h"
34
David Anderson2ffc31b2020-03-23 23:43:45 -070035using android::fs_mgr::EnsurePathUnmounted;
36using android::fs_mgr::Fstab;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -070037using ::android::hardware::hidl_string;
38using ::android::hardware::boot::V1_0::IBootControl;
39using ::android::hardware::boot::V1_0::Slot;
josephjang29069752020-09-23 16:28:03 +080040using ::android::hardware::fastboot::V1_1::IFastboot;
Hridya Valsaraju47658ca2018-09-28 11:41:22 -070041using ::android::hardware::health::V2_0::get_health_service;
42
Hridya Valsaraju31d2c262018-07-20 13:35:50 -070043namespace sph = std::placeholders;
44
Hridya Valsarajudea91b42018-07-17 11:14:01 -070045FastbootDevice::FastbootDevice()
46 : kCommandMap({
47 {FB_CMD_SET_ACTIVE, SetActiveHandler},
48 {FB_CMD_DOWNLOAD, DownloadHandler},
Hridya Valsaraju31d2c262018-07-20 13:35:50 -070049 {FB_CMD_GETVAR, GetVarHandler},
Hridya Valsarajudea91b42018-07-17 11:14:01 -070050 {FB_CMD_SHUTDOWN, ShutDownHandler},
51 {FB_CMD_REBOOT, RebootHandler},
52 {FB_CMD_REBOOT_BOOTLOADER, RebootBootloaderHandler},
53 {FB_CMD_REBOOT_FASTBOOT, RebootFastbootHandler},
54 {FB_CMD_REBOOT_RECOVERY, RebootRecoveryHandler},
David Anderson12211d12018-07-24 15:21:20 -070055 {FB_CMD_ERASE, EraseHandler},
56 {FB_CMD_FLASH, FlashHandler},
David Anderson0d4277d2018-07-31 13:27:37 -070057 {FB_CMD_CREATE_PARTITION, CreatePartitionHandler},
58 {FB_CMD_DELETE_PARTITION, DeletePartitionHandler},
59 {FB_CMD_RESIZE_PARTITION, ResizePartitionHandler},
David Anderson38b3c7a2018-08-15 16:27:42 -070060 {FB_CMD_UPDATE_SUPER, UpdateSuperHandler},
Hridya Valsarajua15fe312018-09-14 13:58:21 -070061 {FB_CMD_OEM, OemCmdHandler},
David Anderson1d504e32019-01-15 14:38:20 -080062 {FB_CMD_GSI, GsiHandler},
David Andersonab8f4662019-10-21 16:45:59 -070063 {FB_CMD_SNAPSHOT_UPDATE, SnapshotUpdateHandler},
Hridya Valsarajudea91b42018-07-17 11:14:01 -070064 }),
Hridya Valsarajubf9f8d12018-09-05 16:57:24 -070065 boot_control_hal_(IBootControl::getService()),
Hridya Valsaraju47658ca2018-09-28 11:41:22 -070066 health_hal_(get_health_service()),
Hridya Valsaraju20bdf892018-10-10 11:02:19 -070067 fastboot_hal_(IFastboot::getService()),
David Anderson220ddb12019-10-31 18:02:41 -070068 active_slot_("") {
Hongguang Chen1e239282020-04-22 14:25:45 -070069 if (android::base::GetProperty("fastbootd.protocol", "usb") == "tcp") {
70 transport_ = std::make_unique<ClientTcpTransport>();
71 } else {
72 transport_ = std::make_unique<ClientUsbTransport>();
73 }
74
David Anderson220ddb12019-10-31 18:02:41 -070075 if (boot_control_hal_) {
76 boot1_1_ = android::hardware::boot::V1_1::IBootControl::castFrom(boot_control_hal_);
77 }
David Anderson2ffc31b2020-03-23 23:43:45 -070078
79 // Make sure cache is unmounted, since recovery will have mounted it for
80 // logging.
81 Fstab fstab;
82 if (ReadDefaultFstab(&fstab)) {
83 EnsurePathUnmounted(&fstab, "/cache");
84 }
David Anderson220ddb12019-10-31 18:02:41 -070085}
Hridya Valsarajudea91b42018-07-17 11:14:01 -070086
87FastbootDevice::~FastbootDevice() {
88 CloseDevice();
89}
90
91void FastbootDevice::CloseDevice() {
92 transport_->Close();
93}
94
Hridya Valsaraju31d2c262018-07-20 13:35:50 -070095std::string FastbootDevice::GetCurrentSlot() {
Hridya Valsaraju20bdf892018-10-10 11:02:19 -070096 // Check if a set_active ccommand was issued earlier since the boot control HAL
97 // returns the slot that is currently booted into.
98 if (!active_slot_.empty()) {
99 return active_slot_;
100 }
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700101 // Non-A/B devices must not have boot control HALs.
102 if (!boot_control_hal_) {
103 return "";
104 }
105 std::string suffix;
106 auto cb = [&suffix](hidl_string s) { suffix = s; };
107 boot_control_hal_->getSuffix(boot_control_hal_->getCurrentSlot(), cb);
108 return suffix;
109}
110
Hridya Valsarajudea91b42018-07-17 11:14:01 -0700111bool FastbootDevice::WriteStatus(FastbootResult result, const std::string& message) {
112 constexpr size_t kResponseReasonSize = 4;
113 constexpr size_t kNumResponseTypes = 4; // "FAIL", "OKAY", "INFO", "DATA"
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700114
Hridya Valsarajudea91b42018-07-17 11:14:01 -0700115 char buf[FB_RESPONSE_SZ];
116 constexpr size_t kMaxMessageSize = sizeof(buf) - kResponseReasonSize;
117 size_t msg_len = std::min(kMaxMessageSize, message.size());
118
119 constexpr const char* kResultStrings[kNumResponseTypes] = {RESPONSE_OKAY, RESPONSE_FAIL,
120 RESPONSE_INFO, RESPONSE_DATA};
121
122 if (static_cast<size_t>(result) >= kNumResponseTypes) {
123 return false;
124 }
125
126 memcpy(buf, kResultStrings[static_cast<size_t>(result)], kResponseReasonSize);
127 memcpy(buf + kResponseReasonSize, message.c_str(), msg_len);
128
129 size_t response_len = kResponseReasonSize + msg_len;
130 auto write_ret = this->get_transport()->Write(buf, response_len);
131 if (write_ret != static_cast<ssize_t>(response_len)) {
132 PLOG(ERROR) << "Failed to write " << message;
133 return false;
134 }
135
136 return true;
137}
138
139bool FastbootDevice::HandleData(bool read, std::vector<char>* data) {
140 auto read_write_data_size = read ? this->get_transport()->Read(data->data(), data->size())
141 : this->get_transport()->Write(data->data(), data->size());
David Andersonf74c1a92020-10-12 15:54:49 -0700142 if (read_write_data_size == -1) {
143 LOG(ERROR) << (read ? "read from" : "write to") << " transport failed";
144 return false;
145 }
146 if (static_cast<size_t>(read_write_data_size) != data->size()) {
147 LOG(ERROR) << (read ? "read" : "write") << " expected " << data->size() << " bytes, got "
148 << read_write_data_size;
Hridya Valsarajudea91b42018-07-17 11:14:01 -0700149 return false;
150 }
151 return true;
152}
153
154void FastbootDevice::ExecuteCommands() {
155 char command[FB_RESPONSE_SZ + 1];
156 for (;;) {
157 auto bytes_read = transport_->Read(command, FB_RESPONSE_SZ);
158 if (bytes_read == -1) {
159 PLOG(ERROR) << "Couldn't read command";
160 return;
161 }
162 command[bytes_read] = '\0';
163
164 LOG(INFO) << "Fastboot command: " << command;
Hridya Valsarajua15fe312018-09-14 13:58:21 -0700165
166 std::vector<std::string> args;
167 std::string cmd_name;
168 if (android::base::StartsWith(command, "oem ")) {
169 args = {command};
Mark Salyzyn8e7e9cb2018-08-29 10:44:33 -0700170 cmd_name = FB_CMD_OEM;
Hridya Valsarajua15fe312018-09-14 13:58:21 -0700171 } else {
172 args = android::base::Split(command, ":");
173 cmd_name = args[0];
174 }
175
176 auto found_command = kCommandMap.find(cmd_name);
Hridya Valsarajudea91b42018-07-17 11:14:01 -0700177 if (found_command == kCommandMap.end()) {
Hridya Valsarajua15fe312018-09-14 13:58:21 -0700178 WriteStatus(FastbootResult::FAIL, "Unrecognized command " + args[0]);
Hridya Valsarajudea91b42018-07-17 11:14:01 -0700179 continue;
180 }
181 if (!found_command->second(this, args)) {
182 return;
183 }
184 }
185}
David Anderson856b7ec2018-08-08 17:58:56 -0700186
187bool FastbootDevice::WriteOkay(const std::string& message) {
188 return WriteStatus(FastbootResult::OKAY, message);
189}
190
191bool FastbootDevice::WriteFail(const std::string& message) {
192 return WriteStatus(FastbootResult::FAIL, message);
193}
David Anderson0f626632018-08-31 16:44:25 -0700194
195bool FastbootDevice::WriteInfo(const std::string& message) {
196 return WriteStatus(FastbootResult::INFO, message);
197}