1 #include "host/commands/launch/flags.h" 2 3 #include <iostream> 4 5 #include <gflags/gflags.h> 6 #include <glog/logging.h> 7 8 #include "common/libs/strings/str_split.h" 9 #include "common/libs/utils/environment.h" 10 #include "common/libs/utils/files.h" 11 #include "common/vsoc/lib/vsoc_memory.h" 12 #include "host/commands/launch/boot_image_unpacker.h" 13 #include "host/commands/launch/data_image.h" 14 #include "host/commands/launch/launch.h" 15 #include "host/commands/launch/launcher_defs.h" 16 #include "host/commands/launch/ril_config.h" 17 #include "host/libs/vm_manager/crosvm_manager.h" 18 #include "host/libs/vm_manager/qemu_manager.h" 19 #include "host/libs/vm_manager/vm_manager.h" 20 21 using vsoc::GetPerInstanceDefault; 22 using cvd::LauncherExitCodes; 23 24 DEFINE_string( 25 system_image, "", 26 "Path to the system image, if empty it is assumed to be a file named " 27 "system.img in the directory specified by -system_image_dir"); 28 DEFINE_string(cache_image, "", "Location of the cache partition image."); 29 DEFINE_string(metadata_image, "", "Location of the metadata partition image " 30 "to be generated."); 31 DEFINE_int32(blank_metadata_image_mb, 16, 32 "The size of the blank metadata image to generate, MB."); 33 DEFINE_int32(cpus, 2, "Virtual CPU count."); 34 DEFINE_string(data_image, "", "Location of the data partition image."); 35 DEFINE_string(data_policy, "use_existing", "How to handle userdata partition." 36 " Either 'use_existing', 'create_if_missing', 'resize_up_to', or " 37 "'always_create'."); 38 DEFINE_int32(blank_data_image_mb, 0, 39 "The size of the blank data image to generate, MB."); 40 DEFINE_string(blank_data_image_fmt, "ext4", 41 "The fs format for the blank data image. Used with mkfs."); 42 DEFINE_string(qemu_gdb, "", 43 "Debug flag to pass to qemu. e.g. -qemu_gdb=tcp::1234"); 44 45 DEFINE_int32(x_res, 720, "Width of the screen in pixels"); 46 DEFINE_int32(y_res, 1280, "Height of the screen in pixels"); 47 DEFINE_int32(dpi, 160, "Pixels per inch for the screen"); 48 DEFINE_int32(refresh_rate_hz, 60, "Screen refresh rate in Hertz"); 49 DEFINE_int32(num_screen_buffers, 3, "The number of screen buffers"); 50 DEFINE_string(kernel_path, "", 51 "Path to the kernel. Overrides the one from the boot image"); 52 DEFINE_bool(decompress_kernel, false, 53 "Whether to decompress the kernel image. Required for crosvm."); 54 DEFINE_string(kernel_decompresser_executable, 55 vsoc::DefaultHostArtifactsPath("bin/extract-vmlinux"), 56 "Path to the extract-vmlinux executable."); 57 DEFINE_string(extra_kernel_cmdline, "", 58 "Additional flags to put on the kernel command line"); 59 DEFINE_int32(loop_max_part, 7, "Maximum number of loop partitions"); 60 DEFINE_string(console, "ttyS0", "Console device for the guest kernel."); 61 DEFINE_string(androidboot_console, "ttyS1", 62 "Console device for the Android framework"); 63 DEFINE_string( 64 hardware_name, "", 65 "The codename of the device's hardware, one of {cutf_ivsh, cutf_cvm}"); 66 DEFINE_string(guest_security, "selinux", 67 "The security module to use in the guest"); 68 DEFINE_bool(guest_enforce_security, true, 69 "Whether to run in enforcing mode (non permissive). Ignored if " 70 "-guest_security is empty."); 71 DEFINE_bool(guest_audit_security, true, 72 "Whether to log security audits."); 73 DEFINE_string(boot_image, "", "Location of cuttlefish boot image."); 74 DEFINE_int32(memory_mb, 2048, 75 "Total amount of memory available for guest, MB."); 76 std::string g_default_mempath{vsoc::GetDefaultMempath()}; 77 DEFINE_string(mempath, g_default_mempath.c_str(), 78 "Target location for the shmem file."); 79 DEFINE_string(mobile_interface, "", // default handled on ParseCommandLine 80 "Network interface to use for mobile networking"); 81 DEFINE_string(mobile_tap_name, "", // default handled on ParseCommandLine 82 "The name of the tap interface to use for mobile"); 83 std::string g_default_serial_number{GetPerInstanceDefault("CUTTLEFISHCVD")}; 84 DEFINE_string(serial_number, g_default_serial_number.c_str(), 85 "Serial number to use for the device"); 86 DEFINE_string(instance_dir, "", // default handled on ParseCommandLine 87 "A directory to put all instance specific files"); 88 DEFINE_string( 89 vm_manager, vm_manager::CrosvmManager::name(), 90 "What virtual machine manager to use, one of {qemu_cli, crosvm}"); 91 DEFINE_string(system_image_dir, vsoc::DefaultGuestImagePath(""), 92 "Location of the system partition images."); 93 DEFINE_string(vendor_image, "", "Location of the vendor partition image."); 94 DEFINE_string(product_image, "", "Location of the product partition image."); 95 DEFINE_string(super_image, "", "Location of the super partition image."); 96 97 DEFINE_bool(deprecated_boot_completed, false, "Log boot completed message to" 98 " host kernel. This is only used during transition of our clients." 99 " Will be deprecated soon."); 100 DEFINE_bool(start_vnc_server, true, "Whether to start the vnc server process."); 101 DEFINE_string(vnc_server_binary, 102 vsoc::DefaultHostArtifactsPath("bin/vnc_server"), 103 "Location of the vnc server binary."); 104 DEFINE_bool(start_stream_audio, false, 105 "Whether to start the stream audio process."); 106 DEFINE_string(stream_audio_binary, 107 vsoc::DefaultHostArtifactsPath("bin/stream_audio"), 108 "Location of the stream_audio binary."); 109 DEFINE_string(virtual_usb_manager_binary, 110 vsoc::DefaultHostArtifactsPath("bin/virtual_usb_manager"), 111 "Location of the virtual usb manager binary."); 112 DEFINE_string(kernel_log_monitor_binary, 113 vsoc::DefaultHostArtifactsPath("bin/kernel_log_monitor"), 114 "Location of the log monitor binary."); 115 DEFINE_string(ivserver_binary, 116 vsoc::DefaultHostArtifactsPath("bin/ivserver"), 117 "Location of the ivshmem server binary."); 118 DEFINE_int32(vnc_server_port, GetPerInstanceDefault(6444), 119 "The port on which the vnc server should listen"); 120 DEFINE_int32(stream_audio_port, GetPerInstanceDefault(7444), 121 "The port on which stream_audio should listen."); 122 DEFINE_string(socket_forward_proxy_binary, 123 vsoc::DefaultHostArtifactsPath("bin/socket_forward_proxy"), 124 "Location of the socket_forward_proxy binary."); 125 DEFINE_string(socket_vsock_proxy_binary, 126 vsoc::DefaultHostArtifactsPath("bin/socket_vsock_proxy"), 127 "Location of the socket_vsock_proxy binary."); 128 DEFINE_string(adb_mode, "vsock_half_tunnel", 129 "Mode for ADB connection. Can be 'usb' for USB forwarding, " 130 "'tunnel' for a TCP connection tunneled through VSoC, " 131 "'vsock_tunnel' for a TCP connection tunneled through vsock, " 132 "'native_vsock' for a direct connection to the guest ADB over " 133 "vsock, 'vsock_half_tunnel' for a TCP connection forwarded to " 134 "the guest ADB server, or a comma separated list of types as in " 135 "'usb,tunnel'"); 136 DEFINE_bool(run_adb_connector, true, 137 "Maintain adb connection by sending 'adb connect' commands to the " 138 "server. Only relevant with -adb_mode=tunnel or vsock_tunnel"); 139 DEFINE_string(adb_connector_binary, 140 vsoc::DefaultHostArtifactsPath("bin/adb_connector"), 141 "Location of the adb_connector binary. Only relevant if " 142 "-run_adb_connector is true"); 143 DEFINE_int32(vhci_port, GetPerInstanceDefault(0), "VHCI port to use for usb"); 144 DEFINE_string(guest_mac_address, 145 GetPerInstanceDefault("00:43:56:44:80:"), // 00:43:56:44:80:0x 146 "MAC address of the wifi interface to be created on the guest."); 147 DEFINE_string(host_mac_address, 148 "42:00:00:00:00:00", 149 "MAC address of the wifi interface running on the host."); 150 DEFINE_string(wifi_tap_name, "", // default handled on ParseCommandLine 151 "The name of the tap interface to use for wifi"); 152 DEFINE_int32(vsock_guest_cid, 153 vsoc::GetDefaultPerInstanceVsockCid(), 154 "Guest identifier for vsock. Disabled if under 3."); 155 156 // TODO(b/72969289) This should be generated 157 DEFINE_string(dtb, "", "Path to the cuttlefish.dtb file"); 158 DEFINE_string(gsi_fstab, 159 vsoc::DefaultHostArtifactsPath("config/gsi.fstab"), 160 "Path to the GSI fstab file"); 161 162 DEFINE_string(uuid, vsoc::GetPerInstanceDefault(vsoc::kDefaultUuidPrefix), 163 "UUID to use for the device. Random if not specified"); 164 DEFINE_bool(daemon, false, 165 "Run cuttlefish in background, the launcher exits on boot " 166 "completed/failed"); 167 168 DEFINE_string(device_title, "", "Human readable name for the instance, " 169 "used by the vnc_server for its server title"); 170 DEFINE_string(setupwizard_mode, "DISABLED", 171 "One of DISABLED,OPTIONAL,REQUIRED"); 172 173 DEFINE_string(qemu_binary, 174 "/usr/bin/qemu-system-x86_64", 175 "The qemu binary to use"); 176 DEFINE_string(crosvm_binary, 177 vsoc::DefaultHostArtifactsPath("bin/crosvm"), 178 "The Crosvm binary to use"); 179 DEFINE_bool(restart_subprocesses, true, "Restart any crashed host process"); 180 DEFINE_bool(run_e2e_test, true, "Run e2e test after device launches"); 181 DEFINE_string(e2e_test_binary, 182 vsoc::DefaultHostArtifactsPath("bin/host_region_e2e_test"), 183 "Location of the region end to end test binary"); 184 DEFINE_string(logcat_receiver_binary, 185 vsoc::DefaultHostArtifactsPath("bin/logcat_receiver"), 186 "Binary for the logcat server"); 187 DEFINE_string(logcat_mode, "", "How to send android's log messages from " 188 "guest to host. One of [serial, vsock]"); 189 DEFINE_int32(logcat_vsock_port, vsoc::GetPerInstanceDefault(5620), 190 "The port for logcat over vsock"); 191 DEFINE_int32(frames_vsock_port, vsoc::GetPerInstanceDefault(5580), 192 "The vsock port to receive frames from the guest on"); 193 namespace { 194 195 template<typename S, typename T> 196 static std::string concat(const S& s, const T& t) { 197 std::ostringstream os; 198 os << s << t; 199 return os.str(); 200 } 201 202 bool ResolveInstanceFiles() { 203 if (FLAGS_system_image_dir.empty()) { 204 LOG(ERROR) << "--system_image_dir must be specified."; 205 return false; 206 } 207 208 // If user did not specify location of either of these files, expect them to 209 // be placed in --system_image_dir location. 210 std::string default_system_image = FLAGS_system_image_dir + "/system.img"; 211 SetCommandLineOptionWithMode("system_image", default_system_image.c_str(), 212 google::FlagSettingMode::SET_FLAGS_DEFAULT); 213 std::string default_boot_image = FLAGS_system_image_dir + "/boot.img"; 214 SetCommandLineOptionWithMode("boot_image", default_boot_image.c_str(), 215 google::FlagSettingMode::SET_FLAGS_DEFAULT); 216 std::string default_cache_image = FLAGS_system_image_dir + "/cache.img"; 217 SetCommandLineOptionWithMode("cache_image", default_cache_image.c_str(), 218 google::FlagSettingMode::SET_FLAGS_DEFAULT); 219 std::string default_data_image = FLAGS_system_image_dir + "/userdata.img"; 220 SetCommandLineOptionWithMode("data_image", default_data_image.c_str(), 221 google::FlagSettingMode::SET_FLAGS_DEFAULT); 222 std::string default_vendor_image = FLAGS_system_image_dir + "/vendor.img"; 223 SetCommandLineOptionWithMode("vendor_image", default_vendor_image.c_str(), 224 google::FlagSettingMode::SET_FLAGS_DEFAULT); 225 std::string default_metadata_image = FLAGS_system_image_dir + "/metadata.img"; 226 SetCommandLineOptionWithMode("metadata_image", default_metadata_image.c_str(), 227 google::FlagSettingMode::SET_FLAGS_DEFAULT); 228 std::string default_product_image = FLAGS_system_image_dir + "/product.img"; 229 SetCommandLineOptionWithMode("product_image", default_product_image.c_str(), 230 google::FlagSettingMode::SET_FLAGS_DEFAULT); 231 std::string default_super_image = FLAGS_system_image_dir + "/super.img"; 232 SetCommandLineOptionWithMode("super_image", default_super_image.c_str(), 233 google::FlagSettingMode::SET_FLAGS_DEFAULT); 234 235 return true; 236 } 237 238 std::string GetCuttlefishEnvPath() { 239 return cvd::StringFromEnv("HOME", ".") + "/.cuttlefish.sh"; 240 } 241 242 // Initializes the config object and saves it to file. It doesn't return it, all 243 // further uses of the config should happen through the singleton 244 bool InitializeCuttlefishConfiguration( 245 const cvd::BootImageUnpacker& boot_image_unpacker) { 246 vsoc::CuttlefishConfig tmp_config_obj; 247 auto& memory_layout = *vsoc::VSoCMemoryLayout::Get(); 248 // Set this first so that calls to PerInstancePath below are correct 249 tmp_config_obj.set_instance_dir(FLAGS_instance_dir); 250 if (!vm_manager::VmManager::IsValidName(FLAGS_vm_manager)) { 251 LOG(ERROR) << "Invalid vm_manager: " << FLAGS_vm_manager; 252 return false; 253 } 254 tmp_config_obj.set_vm_manager(FLAGS_vm_manager); 255 256 // TODO(b/77276633): This should be handled as part of the GPU configuration 257 tmp_config_obj.add_kernel_cmdline("androidboot.hardware.egl=swiftshader"); 258 259 vm_manager::VmManager::ConfigureBootDevices(&tmp_config_obj); 260 261 tmp_config_obj.set_serial_number(FLAGS_serial_number); 262 263 tmp_config_obj.set_cpus(FLAGS_cpus); 264 tmp_config_obj.set_memory_mb(FLAGS_memory_mb); 265 266 tmp_config_obj.set_dpi(FLAGS_dpi); 267 tmp_config_obj.set_setupwizard_mode(FLAGS_setupwizard_mode); 268 tmp_config_obj.set_x_res(FLAGS_x_res); 269 tmp_config_obj.set_y_res(FLAGS_y_res); 270 tmp_config_obj.set_num_screen_buffers(FLAGS_num_screen_buffers); 271 tmp_config_obj.set_refresh_rate_hz(FLAGS_refresh_rate_hz); 272 tmp_config_obj.set_gdb_flag(FLAGS_qemu_gdb); 273 std::vector<std::string> adb = cvd::StrSplit(FLAGS_adb_mode, ','); 274 tmp_config_obj.set_adb_mode(std::set<std::string>(adb.begin(), adb.end())); 275 tmp_config_obj.set_adb_ip_and_port("127.0.0.1:" + std::to_string(GetHostPort())); 276 277 tmp_config_obj.set_device_title(FLAGS_device_title); 278 if (FLAGS_kernel_path.size()) { 279 tmp_config_obj.set_kernel_image_path(FLAGS_kernel_path); 280 tmp_config_obj.set_use_unpacked_kernel(false); 281 } else { 282 tmp_config_obj.set_kernel_image_path( 283 tmp_config_obj.PerInstancePath("kernel")); 284 tmp_config_obj.set_use_unpacked_kernel(true); 285 } 286 tmp_config_obj.set_decompress_kernel(FLAGS_decompress_kernel); 287 if (FLAGS_decompress_kernel) { 288 tmp_config_obj.set_decompressed_kernel_image_path( 289 tmp_config_obj.PerInstancePath("vmlinux")); 290 } 291 292 auto ramdisk_path = tmp_config_obj.PerInstancePath("ramdisk.img"); 293 bool use_ramdisk = boot_image_unpacker.HasRamdiskImage(); 294 if (!use_ramdisk) { 295 LOG(INFO) << "No ramdisk present; assuming system-as-root build"; 296 ramdisk_path = ""; 297 } 298 299 // Fallback for older builds, or builds from branches without DAP 300 if (!FLAGS_super_image.empty() && !cvd::FileHasContent(FLAGS_super_image.c_str())) { 301 LOG(INFO) << "No super image detected; assuming non-DAP build"; 302 FLAGS_super_image.clear(); 303 } 304 305 // This needs to be done here because the dtb path depends on the presence of 306 // the ramdisk. If we are booting a super image, the fstab is passed through 307 // from the ramdisk, it should never be defined by dt. 308 if (FLAGS_super_image.empty() && FLAGS_dtb.empty()) { 309 if (use_ramdisk) { 310 FLAGS_dtb = vsoc::DefaultHostArtifactsPath("config/initrd-root.dtb"); 311 } else { 312 FLAGS_dtb = vsoc::DefaultHostArtifactsPath("config/system-root.dtb"); 313 } 314 } 315 316 tmp_config_obj.add_kernel_cmdline(boot_image_unpacker.kernel_cmdline()); 317 if (!use_ramdisk) { 318 tmp_config_obj.add_kernel_cmdline("root=/dev/vda"); 319 } 320 if (!FLAGS_super_image.empty()) { 321 tmp_config_obj.add_kernel_cmdline("androidboot.super_partition=vda"); 322 } 323 tmp_config_obj.add_kernel_cmdline("init=/init"); 324 tmp_config_obj.add_kernel_cmdline( 325 concat("androidboot.serialno=", FLAGS_serial_number)); 326 tmp_config_obj.add_kernel_cmdline("mac80211_hwsim.radios=0"); 327 tmp_config_obj.add_kernel_cmdline(concat("androidboot.lcd_density=", FLAGS_dpi)); 328 tmp_config_obj.add_kernel_cmdline( 329 concat("androidboot.setupwizard_mode=", FLAGS_setupwizard_mode)); 330 tmp_config_obj.add_kernel_cmdline(concat("loop.max_part=", FLAGS_loop_max_part)); 331 if (!FLAGS_console.empty()) { 332 tmp_config_obj.add_kernel_cmdline(concat("console=", FLAGS_console)); 333 } 334 if (!FLAGS_androidboot_console.empty()) { 335 tmp_config_obj.add_kernel_cmdline( 336 concat("androidboot.console=", FLAGS_androidboot_console)); 337 } 338 if (!FLAGS_hardware_name.empty()) { 339 tmp_config_obj.add_kernel_cmdline( 340 concat("androidboot.hardware=", FLAGS_hardware_name)); 341 } 342 if (FLAGS_logcat_mode == cvd::kLogcatVsockMode) { 343 tmp_config_obj.add_kernel_cmdline(concat("androidboot.vsock_logcat_port=", 344 FLAGS_logcat_vsock_port)); 345 } 346 tmp_config_obj.set_hardware_name(FLAGS_hardware_name); 347 if (!FLAGS_guest_security.empty()) { 348 tmp_config_obj.add_kernel_cmdline(concat("security=", FLAGS_guest_security)); 349 if (FLAGS_guest_enforce_security) { 350 tmp_config_obj.add_kernel_cmdline("enforcing=1"); 351 } else { 352 tmp_config_obj.add_kernel_cmdline("enforcing=0"); 353 tmp_config_obj.add_kernel_cmdline("androidboot.selinux=permissive"); 354 } 355 if (FLAGS_guest_audit_security) { 356 tmp_config_obj.add_kernel_cmdline("audit=1"); 357 } else { 358 tmp_config_obj.add_kernel_cmdline("audit=0"); 359 } 360 } 361 if (FLAGS_run_e2e_test) { 362 tmp_config_obj.add_kernel_cmdline("androidboot.vsoc_e2e_test=1"); 363 } 364 if (FLAGS_extra_kernel_cmdline.size()) { 365 tmp_config_obj.add_kernel_cmdline(FLAGS_extra_kernel_cmdline); 366 } 367 368 if (FLAGS_super_image.empty()) { 369 tmp_config_obj.set_system_image_path(FLAGS_system_image); 370 tmp_config_obj.set_vendor_image_path(FLAGS_vendor_image); 371 tmp_config_obj.set_product_image_path(FLAGS_product_image); 372 tmp_config_obj.set_super_image_path(""); 373 tmp_config_obj.set_dtb_path(FLAGS_dtb); 374 tmp_config_obj.set_gsi_fstab_path(FLAGS_gsi_fstab); 375 } else { 376 tmp_config_obj.set_system_image_path(""); 377 tmp_config_obj.set_vendor_image_path(""); 378 tmp_config_obj.set_product_image_path(""); 379 tmp_config_obj.set_super_image_path(FLAGS_super_image); 380 tmp_config_obj.set_dtb_path(""); 381 tmp_config_obj.set_gsi_fstab_path(""); 382 } 383 384 tmp_config_obj.set_ramdisk_image_path(ramdisk_path); 385 tmp_config_obj.set_cache_image_path(FLAGS_cache_image); 386 tmp_config_obj.set_data_image_path(FLAGS_data_image); 387 tmp_config_obj.set_metadata_image_path(FLAGS_metadata_image); 388 389 tmp_config_obj.set_mempath(FLAGS_mempath); 390 tmp_config_obj.set_ivshmem_qemu_socket_path( 391 tmp_config_obj.PerInstancePath("ivshmem_socket_qemu")); 392 tmp_config_obj.set_ivshmem_client_socket_path( 393 tmp_config_obj.PerInstancePath("ivshmem_socket_client")); 394 tmp_config_obj.set_ivshmem_vector_count(memory_layout.GetRegions().size()); 395 396 if (AdbUsbEnabled(tmp_config_obj)) { 397 tmp_config_obj.set_usb_v1_socket_name(tmp_config_obj.PerInstancePath("usb-v1")); 398 tmp_config_obj.set_vhci_port(FLAGS_vhci_port); 399 tmp_config_obj.set_usb_ip_socket_name(tmp_config_obj.PerInstancePath("usb-ip")); 400 } 401 402 tmp_config_obj.set_kernel_log_socket_name(tmp_config_obj.PerInstancePath("kernel-log")); 403 tmp_config_obj.set_deprecated_boot_completed(FLAGS_deprecated_boot_completed); 404 tmp_config_obj.set_console_path(tmp_config_obj.PerInstancePath("console")); 405 tmp_config_obj.set_logcat_path(tmp_config_obj.PerInstancePath("logcat")); 406 tmp_config_obj.set_logcat_receiver_binary(FLAGS_logcat_receiver_binary); 407 tmp_config_obj.set_launcher_log_path(tmp_config_obj.PerInstancePath("launcher.log")); 408 tmp_config_obj.set_launcher_monitor_socket_path( 409 tmp_config_obj.PerInstancePath("launcher_monitor.sock")); 410 411 tmp_config_obj.set_mobile_bridge_name(FLAGS_mobile_interface); 412 tmp_config_obj.set_mobile_tap_name(FLAGS_mobile_tap_name); 413 ConfigureRil(&tmp_config_obj); 414 415 tmp_config_obj.set_wifi_tap_name(FLAGS_wifi_tap_name); 416 417 tmp_config_obj.set_wifi_guest_mac_addr(FLAGS_guest_mac_address); 418 tmp_config_obj.set_wifi_host_mac_addr(FLAGS_host_mac_address); 419 420 tmp_config_obj.set_vsock_guest_cid(FLAGS_vsock_guest_cid); 421 422 tmp_config_obj.set_entropy_source("/dev/urandom"); 423 tmp_config_obj.set_uuid(FLAGS_uuid); 424 425 tmp_config_obj.set_qemu_binary(FLAGS_qemu_binary); 426 tmp_config_obj.set_crosvm_binary(FLAGS_crosvm_binary); 427 tmp_config_obj.set_ivserver_binary(FLAGS_ivserver_binary); 428 tmp_config_obj.set_kernel_log_monitor_binary(FLAGS_kernel_log_monitor_binary); 429 430 tmp_config_obj.set_enable_vnc_server(FLAGS_start_vnc_server); 431 tmp_config_obj.set_vnc_server_binary(FLAGS_vnc_server_binary); 432 tmp_config_obj.set_vnc_server_port(FLAGS_vnc_server_port); 433 434 tmp_config_obj.set_enable_stream_audio(FLAGS_start_stream_audio); 435 tmp_config_obj.set_stream_audio_binary(FLAGS_stream_audio_binary); 436 tmp_config_obj.set_stream_audio_port(FLAGS_stream_audio_port); 437 438 tmp_config_obj.set_restart_subprocesses(FLAGS_restart_subprocesses); 439 tmp_config_obj.set_run_adb_connector(FLAGS_run_adb_connector); 440 tmp_config_obj.set_adb_connector_binary(FLAGS_adb_connector_binary); 441 tmp_config_obj.set_virtual_usb_manager_binary( 442 FLAGS_virtual_usb_manager_binary); 443 tmp_config_obj.set_socket_forward_proxy_binary( 444 FLAGS_socket_forward_proxy_binary); 445 tmp_config_obj.set_socket_vsock_proxy_binary(FLAGS_socket_vsock_proxy_binary); 446 tmp_config_obj.set_run_as_daemon(FLAGS_daemon); 447 tmp_config_obj.set_run_e2e_test(FLAGS_run_e2e_test); 448 tmp_config_obj.set_e2e_test_binary(FLAGS_e2e_test_binary); 449 450 tmp_config_obj.set_data_policy(FLAGS_data_policy); 451 tmp_config_obj.set_blank_data_image_mb(FLAGS_blank_data_image_mb); 452 tmp_config_obj.set_blank_data_image_fmt(FLAGS_blank_data_image_fmt); 453 454 if(!AdbUsbEnabled(tmp_config_obj)) { 455 tmp_config_obj.disable_usb_adb(); 456 } 457 458 tmp_config_obj.set_logcat_mode(FLAGS_logcat_mode); 459 tmp_config_obj.set_logcat_vsock_port(FLAGS_logcat_vsock_port); 460 tmp_config_obj.set_frames_vsock_port(FLAGS_frames_vsock_port); 461 if (!tmp_config_obj.enable_ivserver()) { 462 tmp_config_obj.add_kernel_cmdline(concat("androidboot.vsock_frames_port=", 463 FLAGS_frames_vsock_port)); 464 } 465 466 tmp_config_obj.set_cuttlefish_env_path(GetCuttlefishEnvPath()); 467 468 auto config_file = GetConfigFilePath(tmp_config_obj); 469 auto config_link = vsoc::GetGlobalConfigFileLink(); 470 // Save the config object before starting any host process 471 if (!tmp_config_obj.SaveToFile(config_file)) { 472 LOG(ERROR) << "Unable to save config object"; 473 return false; 474 } 475 setenv(vsoc::kCuttlefishConfigEnvVarName, config_file.c_str(), true); 476 if (symlink(config_file.c_str(), config_link.c_str()) != 0) { 477 LOG(ERROR) << "Failed to create symlink to config file at " << config_link 478 << ": " << strerror(errno); 479 return false; 480 } 481 482 return true; 483 } 484 485 void SetDefaultFlagsForQemu() { 486 auto default_mobile_interface = GetPerInstanceDefault("cvd-mbr-"); 487 SetCommandLineOptionWithMode("mobile_interface", 488 default_mobile_interface.c_str(), 489 google::FlagSettingMode::SET_FLAGS_DEFAULT); 490 auto default_mobile_tap_name = GetPerInstanceDefault("cvd-mtap-"); 491 SetCommandLineOptionWithMode("mobile_tap_name", 492 default_mobile_tap_name.c_str(), 493 google::FlagSettingMode::SET_FLAGS_DEFAULT); 494 auto default_wifi_tap_name = GetPerInstanceDefault("cvd-wtap-"); 495 SetCommandLineOptionWithMode("wifi_tap_name", 496 default_wifi_tap_name.c_str(), 497 google::FlagSettingMode::SET_FLAGS_DEFAULT); 498 auto default_instance_dir = 499 cvd::StringFromEnv("HOME", ".") + "/cuttlefish_runtime"; 500 SetCommandLineOptionWithMode("instance_dir", 501 default_instance_dir.c_str(), 502 google::FlagSettingMode::SET_FLAGS_DEFAULT); 503 SetCommandLineOptionWithMode("hardware_name", "cutf_ivsh", 504 google::FlagSettingMode::SET_FLAGS_DEFAULT); 505 SetCommandLineOptionWithMode("decompress_kernel", "false", 506 google::FlagSettingMode::SET_FLAGS_DEFAULT); 507 SetCommandLineOptionWithMode("logcat_mode", cvd::kLogcatSerialMode, 508 google::FlagSettingMode::SET_FLAGS_DEFAULT); 509 } 510 511 void SetDefaultFlagsForCrosvm() { 512 auto default_mobile_interface = GetPerInstanceDefault("cvd-mbr-"); 513 SetCommandLineOptionWithMode("mobile_interface", 514 default_mobile_interface.c_str(), 515 google::FlagSettingMode::SET_FLAGS_DEFAULT); 516 auto default_mobile_tap_name = GetPerInstanceDefault("cvd-mtap-"); 517 SetCommandLineOptionWithMode("mobile_tap_name", 518 default_mobile_tap_name.c_str(), 519 google::FlagSettingMode::SET_FLAGS_DEFAULT); 520 auto default_wifi_tap_name = GetPerInstanceDefault("cvd-wtap-"); 521 SetCommandLineOptionWithMode("wifi_tap_name", 522 default_wifi_tap_name.c_str(), 523 google::FlagSettingMode::SET_FLAGS_DEFAULT); 524 auto default_instance_dir = 525 cvd::StringFromEnv("HOME", ".") + "/cuttlefish_runtime"; 526 SetCommandLineOptionWithMode("instance_dir", 527 default_instance_dir.c_str(), 528 google::FlagSettingMode::SET_FLAGS_DEFAULT); 529 SetCommandLineOptionWithMode("hardware_name", "cutf_cvm", 530 google::FlagSettingMode::SET_FLAGS_DEFAULT); 531 SetCommandLineOptionWithMode("decompress_kernel", "true", 532 google::FlagSettingMode::SET_FLAGS_DEFAULT); 533 SetCommandLineOptionWithMode("run_e2e_test", "false", 534 google::FlagSettingMode::SET_FLAGS_DEFAULT); 535 SetCommandLineOptionWithMode("logcat_mode", cvd::kLogcatVsockMode, 536 google::FlagSettingMode::SET_FLAGS_DEFAULT); 537 } 538 539 bool ParseCommandLineFlags(int* argc, char*** argv) { 540 // The config_file is created by the launcher, so the launcher is the only 541 // host process that doesn't use the flag. 542 // Set the default to empty. 543 google::SetCommandLineOptionWithMode("config_file", "", 544 gflags::SET_FLAGS_DEFAULT); 545 google::ParseCommandLineNonHelpFlags(argc, argv, true); 546 bool invalid_manager = false; 547 if (FLAGS_vm_manager == vm_manager::QemuManager::name()) { 548 SetDefaultFlagsForQemu(); 549 } else if (FLAGS_vm_manager == vm_manager::CrosvmManager::name()) { 550 SetDefaultFlagsForCrosvm(); 551 } else { 552 std::cerr << "Unknown Virtual Machine Manager: " << FLAGS_vm_manager 553 << std::endl; 554 invalid_manager = true; 555 } 556 google::HandleCommandLineHelpFlags(); 557 if (invalid_manager) { 558 return false; 559 } 560 // Set the env variable to empty (in case the caller passed a value for it). 561 unsetenv(vsoc::kCuttlefishConfigEnvVarName); 562 563 return ResolveInstanceFiles(); 564 } 565 566 bool CleanPriorFiles() { 567 // Everything on the instance directory 568 std::string prior_files = FLAGS_instance_dir + "/*"; 569 // The shared memory file 570 prior_files += " " + FLAGS_mempath; 571 // The environment file 572 prior_files += " " + GetCuttlefishEnvPath(); 573 // The global link to the config file 574 prior_files += " " + vsoc::GetGlobalConfigFileLink(); 575 LOG(INFO) << "Assuming prior files of " << prior_files; 576 std::string fuser_cmd = "fuser " + prior_files + " 2> /dev/null"; 577 int rval = std::system(fuser_cmd.c_str()); 578 // fuser returns 0 if any of the files are open 579 if (WEXITSTATUS(rval) == 0) { 580 LOG(ERROR) << "Clean aborted: files are in use"; 581 return false; 582 } 583 std::string clean_command = "rm -rf " + prior_files; 584 rval = std::system(clean_command.c_str()); 585 if (WEXITSTATUS(rval) != 0) { 586 LOG(ERROR) << "Remove of files failed"; 587 return false; 588 } 589 return true; 590 } 591 592 bool DecompressKernel(const std::string& src, const std::string& dst) { 593 cvd::Command decomp_cmd(FLAGS_kernel_decompresser_executable); 594 decomp_cmd.AddParameter(src); 595 auto output_file = cvd::SharedFD::Creat(dst.c_str(), 0666); 596 if (!output_file->IsOpen()) { 597 LOG(ERROR) << "Unable to create decompressed image file: " 598 << output_file->StrError(); 599 return false; 600 } 601 decomp_cmd.RedirectStdIO(cvd::Subprocess::StdIOChannel::kStdOut, output_file); 602 auto decomp_proc = decomp_cmd.Start(false); 603 return decomp_proc.Started() && decomp_proc.Wait() == 0; 604 } 605 } // namespace 606 607 vsoc::CuttlefishConfig* InitFilesystemAndCreateConfig(int* argc, char*** argv) { 608 if (!ParseCommandLineFlags(argc, argv)) { 609 LOG(ERROR) << "Failed to parse command arguments"; 610 exit(LauncherExitCodes::kArgumentParsingError); 611 } 612 613 // Clean up prior files before saving the config file (doing it after would 614 // delete it) 615 if (!CleanPriorFiles()) { 616 LOG(ERROR) << "Failed to clean prior files"; 617 exit(LauncherExitCodes::kPrioFilesCleanupError); 618 } 619 // Create instance directory if it doesn't exist. 620 if (!cvd::DirectoryExists(FLAGS_instance_dir.c_str())) { 621 LOG(INFO) << "Setting up " << FLAGS_instance_dir; 622 if (mkdir(FLAGS_instance_dir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) < 0) { 623 LOG(ERROR) << "Failed to create instance directory: " 624 << FLAGS_instance_dir << ". Error: " << errno; 625 exit(LauncherExitCodes::kInstanceDirCreationError); 626 } 627 } 628 629 if (!cvd::FileHasContent(FLAGS_boot_image)) { 630 LOG(ERROR) << "File not found: " << FLAGS_boot_image; 631 exit(cvd::kCuttlefishConfigurationInitError); 632 } 633 634 auto boot_img_unpacker = cvd::BootImageUnpacker::FromImage(FLAGS_boot_image); 635 636 if (!InitializeCuttlefishConfiguration(*boot_img_unpacker)) { 637 LOG(ERROR) << "Failed to initialize configuration"; 638 exit(LauncherExitCodes::kCuttlefishConfigurationInitError); 639 } 640 // Do this early so that the config object is ready for anything that needs it 641 auto config = vsoc::CuttlefishConfig::Get(); 642 if (!config) { 643 LOG(ERROR) << "Failed to obtain config singleton"; 644 exit(LauncherExitCodes::kCuttlefishConfigurationInitError); 645 } 646 647 if (!boot_img_unpacker->Unpack(config->ramdisk_image_path(), 648 config->use_unpacked_kernel() 649 ? config->kernel_image_path() 650 : "")) { 651 LOG(ERROR) << "Failed to unpack boot image"; 652 exit(LauncherExitCodes::kBootImageUnpackError); 653 } 654 655 if (config->decompress_kernel()) { 656 if (!DecompressKernel(config->kernel_image_path(), 657 config->decompressed_kernel_image_path())) { 658 LOG(ERROR) << "Failed to decompress kernel"; 659 exit(LauncherExitCodes::kKernelDecompressError); 660 } 661 } 662 663 ValidateAdbModeFlag(*config); 664 665 // Create data if necessary 666 if (!ApplyDataImagePolicy(*config)) { 667 exit(cvd::kCuttlefishConfigurationInitError); 668 } 669 670 CreateBlankImage(FLAGS_metadata_image, FLAGS_blank_metadata_image_mb, "none"); 671 672 // Check that the files exist 673 for (const auto& file : 674 {config->system_image_path(), config->cache_image_path(), 675 config->data_image_path(), config->vendor_image_path(), 676 config->metadata_image_path(), config->product_image_path(), 677 config->super_image_path()}) { 678 if (!file.empty() && !cvd::FileHasContent(file.c_str())) { 679 LOG(ERROR) << "File not found: " << file; 680 exit(cvd::kCuttlefishConfigurationInitError); 681 } 682 } 683 684 return config; 685 } 686 687 std::string GetConfigFilePath(const vsoc::CuttlefishConfig& config) { 688 return config.PerInstancePath("cuttlefish_config.json"); 689 } 690