blob: a3cbf969217c51fe08386a5383de3c2ccdf1c542 [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 "commands.h"
18
19#include <sys/socket.h>
20#include <sys/un.h>
21
22#include <android-base/logging.h>
23#include <android-base/parseint.h>
24#include <android-base/properties.h>
25#include <android-base/stringprintf.h>
26#include <android-base/strings.h>
27#include <android-base/unique_fd.h>
28#include <cutils/android_reboot.h>
29
30#include "fastboot_device.h"
31
32bool DownloadHandler(FastbootDevice* device, const std::vector<std::string>& args) {
33 if (args.size() < 2) {
34 return device->WriteStatus(FastbootResult::FAIL, "size argument unspecified");
35 }
36 // arg[0] is the command name, arg[1] contains size of data to be downloaded
37 unsigned int size;
38 if (!android::base::ParseUint("0x" + args[1], &size, UINT_MAX)) {
39 return device->WriteStatus(FastbootResult::FAIL, "Invalid size");
40 }
41 device->get_download_data().resize(size);
42 if (!device->WriteStatus(FastbootResult::DATA, android::base::StringPrintf("%08x", size))) {
43 return false;
44 }
45
46 if (device->HandleData(true, &device->get_download_data())) {
47 return device->WriteStatus(FastbootResult::OKAY, "");
48 }
49
50 PLOG(ERROR) << "Couldn't download data";
51 return device->WriteStatus(FastbootResult::FAIL, "Couldn't download data");
52}
53
54bool SetActiveHandler(FastbootDevice* device, const std::vector<std::string>& /* args */) {
55 return device->WriteStatus(FastbootResult::OKAY, "");
56}
57
58bool ShutDownHandler(FastbootDevice* device, const std::vector<std::string>& /* args */) {
59 auto result = device->WriteStatus(FastbootResult::OKAY, "Shutting down");
60 android::base::SetProperty(ANDROID_RB_PROPERTY, "shutdown,fastboot");
61 device->CloseDevice();
62 TEMP_FAILURE_RETRY(pause());
63 return result;
64}
65
66bool RebootHandler(FastbootDevice* device, const std::vector<std::string>& /* args */) {
67 auto result = device->WriteStatus(FastbootResult::OKAY, "Rebooting");
68 android::base::SetProperty(ANDROID_RB_PROPERTY, "reboot,from_fastboot");
69 device->CloseDevice();
70 TEMP_FAILURE_RETRY(pause());
71 return result;
72}
73
74bool RebootBootloaderHandler(FastbootDevice* device, const std::vector<std::string>& /* args */) {
75 auto result = device->WriteStatus(FastbootResult::OKAY, "Rebooting bootloader");
76 android::base::SetProperty(ANDROID_RB_PROPERTY, "reboot,bootloader");
77 device->CloseDevice();
78 TEMP_FAILURE_RETRY(pause());
79 return result;
80}
81
82bool RebootFastbootHandler(FastbootDevice* device, const std::vector<std::string>& /* args */) {
83 auto result = device->WriteStatus(FastbootResult::OKAY, "Rebooting fastboot");
84 android::base::SetProperty(ANDROID_RB_PROPERTY, "reboot,fastboot");
85 device->CloseDevice();
86 TEMP_FAILURE_RETRY(pause());
87 return result;
88}
89
90static bool EnterRecovery() {
91 const char msg_switch_to_recovery = 'r';
92
93 android::base::unique_fd sock(socket(AF_UNIX, SOCK_STREAM, 0));
94 if (sock < 0) {
95 PLOG(ERROR) << "Couldn't create sock";
96 return false;
97 }
98
99 struct sockaddr_un addr = {.sun_family = AF_UNIX};
100 strncpy(addr.sun_path, "/dev/socket/recovery", sizeof(addr.sun_path) - 1);
101 if (connect(sock, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
102 PLOG(ERROR) << "Couldn't connect to recovery";
103 return false;
104 }
105 // Switch to recovery will not update the boot reason since it does not
106 // require a reboot.
107 auto ret = write(sock, &msg_switch_to_recovery, sizeof(msg_switch_to_recovery));
108 if (ret != sizeof(msg_switch_to_recovery)) {
109 PLOG(ERROR) << "Couldn't write message to switch to recovery";
110 return false;
111 }
112
113 return true;
114}
115
116bool RebootRecoveryHandler(FastbootDevice* device, const std::vector<std::string>& /* args */) {
117 auto status = true;
118 if (EnterRecovery()) {
119 status = device->WriteStatus(FastbootResult::OKAY, "Rebooting to recovery");
120 } else {
121 status = device->WriteStatus(FastbootResult::FAIL, "Unable to reboot to recovery");
122 }
123 device->CloseDevice();
124 TEMP_FAILURE_RETRY(pause());
125 return status;
126}