fastbootd: Implement the getvar command.

This implements basic "fastboot getvar" support, including commands supported
by IBootControl.

Bug: 78793464
Test: fastboot getvar <fastboot variable>

Change-Id: Iee1a7b3f43dea46f80dcdf73c45034e2ffe4727d
This commit is contained in:
Hridya Valsaraju 2018-07-20 13:35:50 -07:00 committed by David Anderson
parent 7d4e7d3156
commit 31d2c26409
10 changed files with 306 additions and 6 deletions

View File

@ -96,6 +96,8 @@ cc_binary {
"device/fastboot_device.cpp",
"device/main.cpp",
"device/usb_client.cpp",
"device/utility.cpp",
"device/variables.cpp",
],
shared_libs: [
@ -103,6 +105,7 @@ cc_binary {
"libext4_utils",
"libsparse",
"liblog",
"android.hardware.boot@1.0",
"libbootloader_message",
"libhidltransport",
"libhidlbase",

View File

@ -51,3 +51,5 @@
#define FB_VAR_HAS_SLOT "has-slot"
#define FB_VAR_SLOT_COUNT "slot-count"
#define FB_VAR_PARTITION_SIZE "partition-size"
#define FB_VAR_SLOT_SUCCESSFUL "slot-successful"
#define FB_VAR_SLOT_UNBOOTABLE "slot-unbootable"

View File

@ -27,7 +27,43 @@
#include <android-base/unique_fd.h>
#include <cutils/android_reboot.h>
#include "constants.h"
#include "fastboot_device.h"
#include "utility.h"
using ::android::hardware::hidl_string;
using ::android::hardware::boot::V1_0::BoolResult;
using ::android::hardware::boot::V1_0::CommandResult;
using ::android::hardware::boot::V1_0::Slot;
bool GetVarHandler(FastbootDevice* device, const std::vector<std::string>& args) {
using VariableHandler =
std::function<std::string(FastbootDevice*, const std::vector<std::string>&)>;
const std::unordered_map<std::string, VariableHandler> kVariableMap = {
{FB_VAR_VERSION, GetVersion},
{FB_VAR_VERSION_BOOTLOADER, GetBootloaderVersion},
{FB_VAR_VERSION_BASEBAND, GetBasebandVersion},
{FB_VAR_PRODUCT, GetProduct},
{FB_VAR_SERIALNO, GetSerial},
{FB_VAR_SECURE, GetSecure},
{FB_VAR_UNLOCKED, GetUnlocked},
{FB_VAR_MAX_DOWNLOAD_SIZE, GetMaxDownloadSize},
{FB_VAR_CURRENT_SLOT, ::GetCurrentSlot},
{FB_VAR_SLOT_COUNT, GetSlotCount},
{FB_VAR_HAS_SLOT, GetHasSlot},
{FB_VAR_SLOT_SUCCESSFUL, GetSlotSuccessful},
{FB_VAR_SLOT_UNBOOTABLE, GetSlotUnbootable}};
// args[0] is command name, args[1] is variable.
auto found_variable = kVariableMap.find(args[1]);
if (found_variable == kVariableMap.end()) {
return device->WriteStatus(FastbootResult::FAIL, "Unknown variable");
}
std::vector<std::string> getvar_args(args.begin() + 2, args.end());
auto result = found_variable->second(device, getvar_args);
return device->WriteStatus(FastbootResult::OKAY, result);
}
bool DownloadHandler(FastbootDevice* device, const std::vector<std::string>& args) {
if (args.size() < 2) {
@ -51,8 +87,31 @@ bool DownloadHandler(FastbootDevice* device, const std::vector<std::string>& arg
return device->WriteStatus(FastbootResult::FAIL, "Couldn't download data");
}
bool SetActiveHandler(FastbootDevice* device, const std::vector<std::string>& /* args */) {
return device->WriteStatus(FastbootResult::OKAY, "");
bool SetActiveHandler(FastbootDevice* device, const std::vector<std::string>& args) {
if (args.size() < 2) {
return device->WriteStatus(FastbootResult::FAIL, "Missing slot argument");
}
// Slot suffix needs to be between 'a' and 'z'.
Slot slot;
if (!GetSlotNumber(args[1], &slot)) {
return device->WriteStatus(FastbootResult::FAIL, "Bad slot suffix");
}
// Non-A/B devices will not have a boot control HAL.
auto boot_control_hal = device->boot_control_hal();
if (!boot_control_hal) {
return device->WriteStatus(FastbootResult::FAIL,
"Cannot set slot: boot control HAL absent");
}
if (slot >= boot_control_hal->getNumberSlots()) {
return device->WriteStatus(FastbootResult::FAIL, "Slot out of range");
}
CommandResult ret;
auto cb = [&ret](CommandResult result) { ret = result; };
auto result = boot_control_hal->setActiveBootSlot(slot, cb);
if (result.isOk() && ret.success) return device->WriteStatus(FastbootResult::OKAY, "");
return device->WriteStatus(FastbootResult::FAIL, "Unable to set slot");
}
bool ShutDownHandler(FastbootDevice* device, const std::vector<std::string>& /* args */) {

View File

@ -38,3 +38,4 @@ bool RebootHandler(FastbootDevice* device, const std::vector<std::string>& args)
bool RebootBootloaderHandler(FastbootDevice* device, const std::vector<std::string>& args);
bool RebootFastbootHandler(FastbootDevice* device, const std::vector<std::string>& args);
bool RebootRecoveryHandler(FastbootDevice* device, const std::vector<std::string>& args);
bool GetVarHandler(FastbootDevice* device, const std::vector<std::string>& args);

View File

@ -18,23 +18,31 @@
#include <android-base/logging.h>
#include <android-base/strings.h>
#include <android/hardware/boot/1.0/IBootControl.h>
#include <algorithm>
#include "constants.h"
#include "usb_client.h"
using ::android::hardware::hidl_string;
using ::android::hardware::boot::V1_0::IBootControl;
using ::android::hardware::boot::V1_0::Slot;
namespace sph = std::placeholders;
FastbootDevice::FastbootDevice()
: kCommandMap({
{FB_CMD_SET_ACTIVE, SetActiveHandler},
{FB_CMD_DOWNLOAD, DownloadHandler},
{FB_CMD_GETVAR, GetVarHandler},
{FB_CMD_SHUTDOWN, ShutDownHandler},
{FB_CMD_REBOOT, RebootHandler},
{FB_CMD_REBOOT_BOOTLOADER, RebootBootloaderHandler},
{FB_CMD_REBOOT_FASTBOOT, RebootFastbootHandler},
{FB_CMD_REBOOT_RECOVERY, RebootRecoveryHandler},
}),
transport_(std::make_unique<ClientUsbTransport>()) {}
transport_(std::make_unique<ClientUsbTransport>()),
boot_control_hal_(IBootControl::getService()) {}
FastbootDevice::~FastbootDevice() {
CloseDevice();
@ -44,9 +52,21 @@ void FastbootDevice::CloseDevice() {
transport_->Close();
}
std::string FastbootDevice::GetCurrentSlot() {
// Non-A/B devices must not have boot control HALs.
if (!boot_control_hal_) {
return "";
}
std::string suffix;
auto cb = [&suffix](hidl_string s) { suffix = s; };
boot_control_hal_->getSuffix(boot_control_hal_->getCurrentSlot(), cb);
return suffix;
}
bool FastbootDevice::WriteStatus(FastbootResult result, const std::string& message) {
constexpr size_t kResponseReasonSize = 4;
constexpr size_t kNumResponseTypes = 4; // "FAIL", "OKAY", "INFO", "DATA"
char buf[FB_RESPONSE_SZ];
constexpr size_t kMaxMessageSize = sizeof(buf) - kResponseReasonSize;
size_t msg_len = std::min(kMaxMessageSize, message.size());

View File

@ -22,10 +22,11 @@
#include <utility>
#include <vector>
#include <android/hardware/boot/1.0/IBootControl.h>
#include "commands.h"
#include "transport.h"
class FastbootDevice;
#include "variables.h"
class FastbootDevice {
public:
@ -36,17 +37,21 @@ class FastbootDevice {
void ExecuteCommands();
bool WriteStatus(FastbootResult result, const std::string& message);
bool HandleData(bool read, std::vector<char>* data);
std::string GetCurrentSlot();
std::vector<char>& get_download_data() { return download_data_; }
void set_upload_data(const std::vector<char>& data) { upload_data_ = data; }
void set_upload_data(std::vector<char>&& data) { upload_data_ = std::move(data); }
Transport* get_transport() { return transport_.get(); }
android::sp<android::hardware::boot::V1_0::IBootControl> boot_control_hal() {
return boot_control_hal_;
}
private:
const std::unordered_map<std::string, CommandHandler> kCommandMap;
std::unique_ptr<Transport> transport_;
android::sp<android::hardware::boot::V1_0::IBootControl> boot_control_hal_;
std::vector<char> download_data_;
std::vector<char> upload_data_;
};

View File

@ -0,0 +1,30 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "utility.h"
using android::hardware::boot::V1_0::Slot;
bool GetSlotNumber(const std::string& slot, Slot* number) {
if (slot.size() != 1) {
return false;
}
if (slot[0] < 'a' || slot[0] > 'z') {
return false;
}
*number = slot[0] - 'a';
return true;
}

22
fastboot/device/utility.h Normal file
View File

@ -0,0 +1,22 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <string>
#include <android/hardware/boot/1.0/IBootControl.h>
bool GetSlotNumber(const std::string& slot, android::hardware::boot::V1_0::Slot* number);

View File

@ -0,0 +1,122 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "variables.h"
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <ext4_utils/ext4_utils.h>
#include "fastboot_device.h"
#include "utility.h"
using ::android::hardware::boot::V1_0::BoolResult;
using ::android::hardware::boot::V1_0::Slot;
constexpr int kMaxDownloadSizeDefault = 0x20000000;
constexpr char kFastbootProtocolVersion[] = "0.4";
std::string GetVersion(FastbootDevice* /* device */, const std::vector<std::string>& /* args */) {
return kFastbootProtocolVersion;
}
std::string GetBootloaderVersion(FastbootDevice* /* device */,
const std::vector<std::string>& /* args */) {
return android::base::GetProperty("ro.bootloader", "");
}
std::string GetBasebandVersion(FastbootDevice* /* device */,
const std::vector<std::string>& /* args */) {
return android::base::GetProperty("ro.build.expect.baseband", "");
}
std::string GetProduct(FastbootDevice* /* device */, const std::vector<std::string>& /* args */) {
return android::base::GetProperty("ro.product.device", "");
}
std::string GetSerial(FastbootDevice* /* device */, const std::vector<std::string>& /* args */) {
return android::base::GetProperty("ro.serialno", "");
}
std::string GetSecure(FastbootDevice* /* device */, const std::vector<std::string>& /* args */) {
return android::base::GetBoolProperty("ro.secure", "") ? "yes" : "no";
}
std::string GetCurrentSlot(FastbootDevice* device, const std::vector<std::string>& /* args */) {
std::string suffix = device->GetCurrentSlot();
return suffix.size() == 2 ? suffix.substr(1) : suffix;
}
std::string GetSlotCount(FastbootDevice* device, const std::vector<std::string>& /* args */) {
auto boot_control_hal = device->boot_control_hal();
if (!boot_control_hal) {
return "0";
}
return std::to_string(boot_control_hal->getNumberSlots());
}
std::string GetSlotSuccessful(FastbootDevice* device, const std::vector<std::string>& args) {
if (args.empty()) {
return "no";
}
Slot slot;
if (!GetSlotNumber(args[0], &slot)) {
return "no";
}
auto boot_control_hal = device->boot_control_hal();
if (!boot_control_hal) {
return "no";
}
return boot_control_hal->isSlotMarkedSuccessful(slot) == BoolResult::TRUE ? "yes" : "no";
}
std::string GetSlotUnbootable(FastbootDevice* device, const std::vector<std::string>& args) {
if (args.empty()) {
return "no";
}
Slot slot;
if (!GetSlotNumber(args[0], &slot)) {
return "no";
}
auto boot_control_hal = device->boot_control_hal();
if (!boot_control_hal) {
return "no";
}
return boot_control_hal->isSlotBootable(slot) == BoolResult::TRUE ? "no" : "yes";
}
std::string GetMaxDownloadSize(FastbootDevice* /* device */,
const std::vector<std::string>& /* args */) {
return std::to_string(kMaxDownloadSizeDefault);
}
std::string GetUnlocked(FastbootDevice* /* device */, const std::vector<std::string>& /* args */) {
return "yes";
}
std::string GetHasSlot(FastbootDevice* device, const std::vector<std::string>& args) {
if (args.empty()) {
return "no";
}
std::string slot_suffix = device->GetCurrentSlot();
if (slot_suffix.empty()) {
return "no";
}
return args[0] == "userdata" ? "no" : "yes";
}

View File

@ -0,0 +1,36 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <functional>
#include <string>
#include <vector>
class FastbootDevice;
std::string GetVersion(FastbootDevice* device, const std::vector<std::string>& args);
std::string GetBootloaderVersion(FastbootDevice* device, const std::vector<std::string>& args);
std::string GetBasebandVersion(FastbootDevice* device, const std::vector<std::string>& args);
std::string GetProduct(FastbootDevice* device, const std::vector<std::string>& args);
std::string GetSerial(FastbootDevice* device, const std::vector<std::string>& args);
std::string GetSecure(FastbootDevice* device, const std::vector<std::string>& args);
std::string GetCurrentSlot(FastbootDevice* device, const std::vector<std::string>& args);
std::string GetSlotCount(FastbootDevice* device, const std::vector<std::string>& args);
std::string GetSlotSuccessful(FastbootDevice* device, const std::vector<std::string>& args);
std::string GetSlotUnbootable(FastbootDevice* device, const std::vector<std::string>& args);
std::string GetMaxDownloadSize(FastbootDevice* device, const std::vector<std::string>& args);
std::string GetUnlocked(FastbootDevice* device, const std::vector<std::string>& args);
std::string GetHasSlot(FastbootDevice* device, const std::vector<std::string>& args);