1 //
2 // Copyright (C) 2023 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 #include <unordered_set>
17 #include <vector>
18
19 #include <android-base/logging.h>
20 #include <fruit/fruit.h>
21 #include <json/json.h>
22
23 #include "common/libs/utils/files.h"
24 #include "common/libs/utils/result.h"
25 #include "host/commands/run_cvd/launch/launch.h"
26 #include "host/commands/run_cvd/launch/log_tee_creator.h"
27 #include "host/libs/config/command_source.h"
28 #include "host/libs/config/cuttlefish_config.h"
29 #include "host/libs/config/known_paths.h"
30
31
32 // timeout for the MCU channels to be created after the start command is issued
33 #define MCU_START_TIMEOUT 30
34
35 namespace cuttlefish {
36 namespace {
37
38 class Mcu : public vm_manager::VmmDependencyCommand {
39 public:
INJECT(Mcu (const CuttlefishConfig::InstanceSpecific & instance,LogTeeCreator & log_tee))40 INJECT(Mcu(const CuttlefishConfig::InstanceSpecific& instance,
41 LogTeeCreator& log_tee))
42 :instance_(instance), log_tee_(log_tee) {}
43
ResultSetup()44 Result<void> ResultSetup() override {
45 if (!Enabled()) {
46 return {};
47 }
48
49 mcu_dir_ = instance_.PerInstanceInternalPath("/mcu/");
50 CF_EXPECT(EnsureDirectoryExists(mcu_dir_),
51 "MCU directory cannot be created.");
52 return {};
53 }
54
55 // CommandSource
Commands()56 Result<std::vector<MonitorCommand>> Commands() override {
57 if (!Enabled()) {
58 return {};
59 }
60
61 auto start = instance_.mcu()["start-cmd"];
62 CF_EXPECT(start.type() == Json::arrayValue,
63 "mcu: config: start-cmd: array expected");
64 CF_EXPECT(start.size() > 0, "mcu: config: empty start-cmd");
65 Command command(android::base::StringReplace(start[0].asString(), "${bin}",
66 HostBinaryPath(""), true));
67
68 for (unsigned int i = 1; i < start.size(); i++) {
69 auto param = start[i].asString();
70 param = android::base::StringReplace(param, "${wdir}", mcu_dir_, true);
71 param = android::base::StringReplace(param, "${bin}", HostBinaryPath(""),
72 true);
73 command.AddParameter(param);
74 }
75
76 std::vector<MonitorCommand> commands;
77 commands.emplace_back(CF_EXPECT(log_tee_.CreateLogTee(command, "mcu")));
78 commands.emplace_back(std::move(command));
79 return commands;
80 }
81
82 // SetupFeature
Name() const83 std::string Name() const override { return "MCU"; }
Enabled() const84 bool Enabled() const override {
85 return instance_.mcu().type() != Json::nullValue;
86 }
87
88 // StatusCheckCommandSource
WaitForAvailability() const89 Result<void> WaitForAvailability() const {
90 if (!Enabled()) {
91 return {};
92 }
93
94 auto control = instance_.mcu()["control"]["path"];
95 if (control.type() == Json::stringValue) {
96 CF_EXPECT(WaitForFile(mcu_dir_ + "/" + control.asString(),
97 MCU_START_TIMEOUT));
98 }
99 auto uart0 = instance_.mcu()["uart0"]["path"];
100 if (uart0.type() == Json::stringValue) {
101 CF_EXPECT(WaitForFile(mcu_dir_ + "/" + uart0.asString(),
102 MCU_START_TIMEOUT));
103 }
104 return {};
105 }
106
107 private:
Dependencies() const108 std::unordered_set<SetupFeature*> Dependencies() const override { return {}; }
109
110 std::string mcu_dir_;
111 const CuttlefishConfig::InstanceSpecific& instance_;
112 LogTeeCreator& log_tee_;
113 };
114
115 } // namespace
116
117 fruit::Component<
118 fruit::Required<const CuttlefishConfig,
119 const CuttlefishConfig::InstanceSpecific, LogTeeCreator>>
McuComponent()120 McuComponent() {
121 return fruit::createComponent()
122 .addMultibinding<vm_manager::VmmDependencyCommand, Mcu>()
123 .addMultibinding<CommandSource, Mcu>()
124 .addMultibinding<SetupFeature, Mcu>();
125 }
126
127 } // namespace cuttlefish
128