1*e7c364b6SAndroid Build Coastguard Worker /*
2*e7c364b6SAndroid Build Coastguard Worker * Copyright (C) 2018 The Android Open Source Project
3*e7c364b6SAndroid Build Coastguard Worker *
4*e7c364b6SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*e7c364b6SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*e7c364b6SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*e7c364b6SAndroid Build Coastguard Worker *
8*e7c364b6SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*e7c364b6SAndroid Build Coastguard Worker *
10*e7c364b6SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*e7c364b6SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*e7c364b6SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*e7c364b6SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*e7c364b6SAndroid Build Coastguard Worker * limitations under the License.
15*e7c364b6SAndroid Build Coastguard Worker */
16*e7c364b6SAndroid Build Coastguard Worker
17*e7c364b6SAndroid Build Coastguard Worker #include "fastboot.h"
18*e7c364b6SAndroid Build Coastguard Worker
19*e7c364b6SAndroid Build Coastguard Worker #include <stdio.h>
20*e7c364b6SAndroid Build Coastguard Worker #include <stdlib.h>
21*e7c364b6SAndroid Build Coastguard Worker
22*e7c364b6SAndroid Build Coastguard Worker #include <algorithm>
23*e7c364b6SAndroid Build Coastguard Worker #include <string>
24*e7c364b6SAndroid Build Coastguard Worker #include <vector>
25*e7c364b6SAndroid Build Coastguard Worker
26*e7c364b6SAndroid Build Coastguard Worker #include <android-base/logging.h>
27*e7c364b6SAndroid Build Coastguard Worker #include <android-base/properties.h>
28*e7c364b6SAndroid Build Coastguard Worker #include <bootloader_message/bootloader_message.h>
29*e7c364b6SAndroid Build Coastguard Worker
30*e7c364b6SAndroid Build Coastguard Worker #include "recovery_ui/ui.h"
31*e7c364b6SAndroid Build Coastguard Worker
32*e7c364b6SAndroid Build Coastguard Worker static const std::vector<std::pair<std::string, Device::BuiltinAction>> kFastbootMenuActions{
33*e7c364b6SAndroid Build Coastguard Worker { "Reboot system now", Device::REBOOT_FROM_FASTBOOT },
34*e7c364b6SAndroid Build Coastguard Worker { "Enter recovery", Device::ENTER_RECOVERY },
35*e7c364b6SAndroid Build Coastguard Worker { "Reboot to bootloader", Device::REBOOT_BOOTLOADER },
36*e7c364b6SAndroid Build Coastguard Worker { "Power off", Device::SHUTDOWN_FROM_FASTBOOT },
37*e7c364b6SAndroid Build Coastguard Worker };
38*e7c364b6SAndroid Build Coastguard Worker
FillDefaultFastbootLines(std::vector<std::string> & title_lines)39*e7c364b6SAndroid Build Coastguard Worker void FillDefaultFastbootLines(std::vector<std::string>& title_lines) {
40*e7c364b6SAndroid Build Coastguard Worker title_lines.push_back("Android Fastboot");
41*e7c364b6SAndroid Build Coastguard Worker title_lines.push_back("Product name - " + android::base::GetProperty("ro.product.device", ""));
42*e7c364b6SAndroid Build Coastguard Worker title_lines.push_back("Bootloader version - " + android::base::GetProperty("ro.bootloader", ""));
43*e7c364b6SAndroid Build Coastguard Worker title_lines.push_back("Baseband version - " +
44*e7c364b6SAndroid Build Coastguard Worker android::base::GetProperty("ro.build.expect.baseband", ""));
45*e7c364b6SAndroid Build Coastguard Worker title_lines.push_back("Serial number - " + android::base::GetProperty("ro.serialno", ""));
46*e7c364b6SAndroid Build Coastguard Worker title_lines.push_back(std::string("Secure boot - ") +
47*e7c364b6SAndroid Build Coastguard Worker ((android::base::GetProperty("ro.secure", "") == "1") ? "yes" : "no"));
48*e7c364b6SAndroid Build Coastguard Worker title_lines.push_back("HW version - " + android::base::GetProperty("ro.revision", ""));
49*e7c364b6SAndroid Build Coastguard Worker }
50*e7c364b6SAndroid Build Coastguard Worker
FillWearableFastbootLines(std::vector<std::string> & title_lines)51*e7c364b6SAndroid Build Coastguard Worker void FillWearableFastbootLines(std::vector<std::string>& title_lines) {
52*e7c364b6SAndroid Build Coastguard Worker title_lines.push_back("Android Fastboot");
53*e7c364b6SAndroid Build Coastguard Worker title_lines.push_back(android::base::GetProperty("ro.product.device", "") + " - " +
54*e7c364b6SAndroid Build Coastguard Worker android::base::GetProperty("ro.revision", ""));
55*e7c364b6SAndroid Build Coastguard Worker title_lines.push_back(android::base::GetProperty("ro.bootloader", ""));
56*e7c364b6SAndroid Build Coastguard Worker
57*e7c364b6SAndroid Build Coastguard Worker const size_t max_baseband_len = 24;
58*e7c364b6SAndroid Build Coastguard Worker const std::string& baseband = android::base::GetProperty("ro.build.expect.baseband", "");
59*e7c364b6SAndroid Build Coastguard Worker title_lines.push_back(baseband.length() > max_baseband_len
60*e7c364b6SAndroid Build Coastguard Worker ? baseband.substr(0, max_baseband_len - 3) + "..."
61*e7c364b6SAndroid Build Coastguard Worker : baseband);
62*e7c364b6SAndroid Build Coastguard Worker
63*e7c364b6SAndroid Build Coastguard Worker title_lines.push_back("Serial #: " + android::base::GetProperty("ro.serialno", ""));
64*e7c364b6SAndroid Build Coastguard Worker }
65*e7c364b6SAndroid Build Coastguard Worker
StartFastboot(Device * device,const std::vector<std::string> &)66*e7c364b6SAndroid Build Coastguard Worker Device::BuiltinAction StartFastboot(Device* device, const std::vector<std::string>& /* args */) {
67*e7c364b6SAndroid Build Coastguard Worker RecoveryUI* ui = device->GetUI();
68*e7c364b6SAndroid Build Coastguard Worker std::vector<std::string> title_lines;
69*e7c364b6SAndroid Build Coastguard Worker
70*e7c364b6SAndroid Build Coastguard Worker if (ui->IsWearable()) {
71*e7c364b6SAndroid Build Coastguard Worker FillWearableFastbootLines(title_lines);
72*e7c364b6SAndroid Build Coastguard Worker } else {
73*e7c364b6SAndroid Build Coastguard Worker ui->SetEnableFastbootdLogo(true);
74*e7c364b6SAndroid Build Coastguard Worker FillDefaultFastbootLines(title_lines);
75*e7c364b6SAndroid Build Coastguard Worker }
76*e7c364b6SAndroid Build Coastguard Worker
77*e7c364b6SAndroid Build Coastguard Worker ui->ResetKeyInterruptStatus();
78*e7c364b6SAndroid Build Coastguard Worker ui->SetTitle(title_lines);
79*e7c364b6SAndroid Build Coastguard Worker ui->ShowText(true);
80*e7c364b6SAndroid Build Coastguard Worker device->StartFastboot();
81*e7c364b6SAndroid Build Coastguard Worker
82*e7c364b6SAndroid Build Coastguard Worker // Reset to normal system boot so recovery won't cycle indefinitely.
83*e7c364b6SAndroid Build Coastguard Worker // TODO(b/112277594) Clear only if 'recovery' field of BCB is empty. If not,
84*e7c364b6SAndroid Build Coastguard Worker // set the 'command' field of BCB to 'boot-recovery' so the next boot is into recovery
85*e7c364b6SAndroid Build Coastguard Worker // to finish any interrupted tasks.
86*e7c364b6SAndroid Build Coastguard Worker std::string err;
87*e7c364b6SAndroid Build Coastguard Worker if (!clear_bootloader_message(&err)) {
88*e7c364b6SAndroid Build Coastguard Worker LOG(ERROR) << "Failed to clear BCB message: " << err;
89*e7c364b6SAndroid Build Coastguard Worker }
90*e7c364b6SAndroid Build Coastguard Worker
91*e7c364b6SAndroid Build Coastguard Worker std::vector<std::string> fastboot_menu_items;
92*e7c364b6SAndroid Build Coastguard Worker std::transform(kFastbootMenuActions.cbegin(), kFastbootMenuActions.cend(),
93*e7c364b6SAndroid Build Coastguard Worker std::back_inserter(fastboot_menu_items),
94*e7c364b6SAndroid Build Coastguard Worker [](const auto& entry) { return entry.first; });
95*e7c364b6SAndroid Build Coastguard Worker
96*e7c364b6SAndroid Build Coastguard Worker auto chosen_item = ui->ShowMenu(
97*e7c364b6SAndroid Build Coastguard Worker {}, fastboot_menu_items, 0, false,
98*e7c364b6SAndroid Build Coastguard Worker std::bind(&Device::HandleMenuKey, device, std::placeholders::_1, std::placeholders::_2));
99*e7c364b6SAndroid Build Coastguard Worker
100*e7c364b6SAndroid Build Coastguard Worker if (chosen_item == static_cast<size_t>(RecoveryUI::KeyError::INTERRUPTED)) {
101*e7c364b6SAndroid Build Coastguard Worker return Device::KEY_INTERRUPTED;
102*e7c364b6SAndroid Build Coastguard Worker }
103*e7c364b6SAndroid Build Coastguard Worker if (chosen_item == static_cast<size_t>(RecoveryUI::KeyError::TIMED_OUT)) {
104*e7c364b6SAndroid Build Coastguard Worker return Device::BuiltinAction::NO_ACTION;
105*e7c364b6SAndroid Build Coastguard Worker }
106*e7c364b6SAndroid Build Coastguard Worker return kFastbootMenuActions[chosen_item].second;
107*e7c364b6SAndroid Build Coastguard Worker }
108