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:
parent
7d4e7d3156
commit
31d2c26409
|
@ -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",
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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 */) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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_;
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
|
@ -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";
|
||||
}
|
|
@ -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);
|
Loading…
Reference in New Issue