1 /*
2 * Copyright (C) 2021 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 "host/libs/config/bootconfig_args.h"
18
19 #include <array>
20 #include <sstream>
21 #include <string>
22 #include <vector>
23
24 #include "common/libs/utils/environment.h"
25 #include "common/libs/utils/files.h"
26 #include "host/libs/config/cuttlefish_config.h"
27 #include "host/libs/config/known_paths.h"
28 #include "host/libs/vm_manager/crosvm_manager.h"
29 #include "host/libs/vm_manager/qemu_manager.h"
30 #include "host/libs/vm_manager/vm_manager.h"
31
32 namespace cuttlefish {
33
34 using vm_manager::CrosvmManager;
35 using vm_manager::QemuManager;
36
37 namespace {
38
39 template <typename T>
AppendVector(std::vector<T> * destination,const std::vector<T> & source)40 void AppendVector(std::vector<T>* destination, const std::vector<T>& source) {
41 destination->insert(destination->end(), source.begin(), source.end());
42 }
43
44 template <typename S, typename T>
concat(const S & s,const T & t)45 std::string concat(const S& s, const T& t) {
46 std::ostringstream os;
47 os << s << t;
48 return os.str();
49 }
50
51 // TODO(schuffelen): Move more of this into host/libs/vm_manager, as a
52 // substitute for the vm_manager comparisons.
VmManagerBootconfig(const CuttlefishConfig & config)53 std::vector<std::string> VmManagerBootconfig(const CuttlefishConfig& config) {
54 std::vector<std::string> vm_manager_cmdline;
55 if (config.console()) {
56 vm_manager_cmdline.push_back("androidboot.console=" + config.console_dev());
57 } else {
58 // Specify an invalid path under /dev, so the init process will disable the
59 // console service due to the console not being found. On physical devices,
60 // it is enough to not specify androidboot.console= *and* not specify the
61 // console= kernel command line parameter, because the console and kernel
62 // dmesg are muxed. However, on cuttlefish, we don't need to mux, and would
63 // prefer to retain the kernel dmesg logging, so we must work around init
64 // falling back to the check for /dev/console (which we'll always have).
65 vm_manager_cmdline.push_back("androidboot.console=invalid");
66 }
67 return vm_manager_cmdline;
68 }
69
70 } // namespace
71
BootconfigArgsFromConfig(const CuttlefishConfig & config,const CuttlefishConfig::InstanceSpecific & instance)72 std::vector<std::string> BootconfigArgsFromConfig(
73 const CuttlefishConfig& config,
74 const CuttlefishConfig::InstanceSpecific& instance) {
75 std::vector<std::string> bootconfig_args;
76
77 AppendVector(&bootconfig_args, VmManagerBootconfig(config));
78 auto vmm = vm_manager::GetVmManager(config.vm_manager(), config.target_arch());
79 bootconfig_args.push_back(
80 vmm->ConfigureBootDevices(instance.virtual_disk_paths().size()));
81 AppendVector(&bootconfig_args, vmm->ConfigureGraphics(config));
82
83 bootconfig_args.push_back(
84 concat("androidboot.serialno=", instance.serial_number()));
85
86 // TODO(b/131884992): update to specify multiple once supported.
87 const auto display_configs = config.display_configs();
88 CHECK_GE(display_configs.size(), 1);
89 bootconfig_args.push_back(
90 concat("androidboot.lcd_density=", display_configs[0].dpi));
91
92 bootconfig_args.push_back(
93 concat("androidboot.setupwizard_mode=", config.setupwizard_mode()));
94 if (!config.guest_enforce_security()) {
95 bootconfig_args.push_back("androidboot.selinux=permissive");
96 }
97
98 if (instance.tombstone_receiver_port()) {
99 bootconfig_args.push_back(concat("androidboot.vsock_tombstone_port=",
100 instance.tombstone_receiver_port()));
101 }
102
103 if (instance.confui_host_vsock_port()) {
104 bootconfig_args.push_back(concat("androidboot.vsock_confirmationui_port=",
105 instance.confui_host_vsock_port()));
106 }
107
108 if (instance.config_server_port()) {
109 bootconfig_args.push_back(
110 concat("androidboot.cuttlefish_config_server_port=",
111 instance.config_server_port()));
112 }
113
114 if (instance.keyboard_server_port()) {
115 bootconfig_args.push_back(concat("androidboot.vsock_keyboard_port=",
116 instance.keyboard_server_port()));
117 }
118
119 if (instance.touch_server_port()) {
120 bootconfig_args.push_back(
121 concat("androidboot.vsock_touch_port=", instance.touch_server_port()));
122 }
123
124 if (config.enable_vehicle_hal_grpc_server() &&
125 instance.vehicle_hal_server_port() &&
126 FileExists(VehicleHalGrpcServerBinary())) {
127 constexpr int vehicle_hal_server_cid = 2;
128 bootconfig_args.push_back(concat(
129 "androidboot.vendor.vehiclehal.server.cid=", vehicle_hal_server_cid));
130 bootconfig_args.push_back(
131 concat("androidboot.vendor.vehiclehal.server.port=",
132 instance.vehicle_hal_server_port()));
133 }
134
135 if (instance.audiocontrol_server_port()) {
136 bootconfig_args.push_back(
137 concat("androidboot.vendor.audiocontrol.server.cid=",
138 instance.vsock_guest_cid()));
139 bootconfig_args.push_back(
140 concat("androidboot.vendor.audiocontrol.server.port=",
141 instance.audiocontrol_server_port()));
142 }
143
144 if (instance.camera_server_port()) {
145 bootconfig_args.push_back(concat("androidboot.vsock_camera_port=",
146 instance.camera_server_port()));
147 bootconfig_args.push_back(
148 concat("androidboot.vsock_camera_cid=", instance.vsock_guest_cid()));
149 }
150
151 if (config.enable_modem_simulator() &&
152 instance.modem_simulator_ports() != "") {
153 bootconfig_args.push_back(concat("androidboot.modem_simulator_ports=",
154 instance.modem_simulator_ports()));
155 }
156
157 bootconfig_args.push_back(concat("androidboot.fstab_suffix=",
158 config.userdata_format()));
159
160 bootconfig_args.push_back(
161 concat("androidboot.wifi_mac_prefix=", instance.wifi_mac_prefix()));
162
163 // Non-native architecture implies a significantly slower execution speed, so
164 // set a large timeout multiplier.
165 if (!IsHostCompatible(config.target_arch())) {
166 bootconfig_args.push_back("androidboot.hw_timeout_multiplier=50");
167 }
168
169 // TODO(b/217564326): improve this checks for a hypervisor in the VM.
170 if (config.target_arch() == Arch::X86 ||
171 config.target_arch() == Arch::X86_64) {
172 bootconfig_args.push_back(
173 concat("androidboot.hypervisor.version=cf-", config.vm_manager()));
174 bootconfig_args.push_back("androidboot.hypervisor.vm.supported=1");
175 bootconfig_args.push_back(
176 "androidboot.hypervisor.protected_vm.supported=0");
177 }
178
179 AppendVector(&bootconfig_args, config.extra_bootconfig_args());
180
181 return bootconfig_args;
182 }
183
184 } // namespace cuttlefish
185