From 312d8af1c912957845f5b9915519fbf8dbe37554 Mon Sep 17 00:00:00 2001 From: Brian Daniels Date: Wed, 16 Sep 2026 14:24:03 +0000 Subject: [PATCH] Add flag to fetch and use vendor_boot-debug.img. vendor_boot.img can be replaced with vendor_boot-debug.img to enable root on user builds. This is required for certain tests. This is already possible when using the `cvd create --vendor_boot_image=path/to/vendor_boot-debug.img` flag, however it isn't possible to do this when using config files (`cvd create --config_file config.json`). This change adds a `use_vendor_boot_debug` field to the config files to allow fetching (if necessar) and then using the `vendor_boot-debug.img` for a build. It also works with local builds. It is also now possible to specify `--use_vendor_boot_debug` when calling `cvd create`. If this is set when `--vendor_boot_image` is also set, `--use_vendor_boot_debug` is ignored. Bug: 542722431 Test: Create a file named `config.json` with the follwing format: { "common": { "host_package": "@ab/git_26Q4-release/cf_x86_64_auto-user" }, "instances": [ { "@import": "auto", "disk": { "default_build": "@ab/git_26Q4-release/cf_x86_64_auto-user" }, "boot": { "use_vendor_boot_debug": true } } ] } Then run: `cvd create --config_file config.json` After the target boots, you should be able to run `adb root`. --- .../commands/assemble_cvd/assemble_cvd.cc | 2 +- .../commands/assemble_cvd/flags/BUILD.bazel | 2 + .../assemble_cvd/flags/vendor_boot_image.cc | 53 ++++++++++--- .../assemble_cvd/flags/vendor_boot_image.h | 8 +- .../commands/assemble_cvd/flags_defaults.h | 1 + .../cvd/cli/parser/fetch_config_parser.cpp | 10 +++ .../cli/parser/instance/boot_configs_test.cc | 77 +++++++++++++++++++ .../cli/parser/instance/cf_boot_configs.cpp | 7 ++ .../commands/cvd/cli/parser/load_config.proto | 1 + .../host/commands/cvd/fetch/download_flags.cc | 4 + .../host/commands/cvd/fetch/download_flags.h | 1 + .../host/commands/cvd/fetch/fetch_cvd.cc | 22 +++++- .../host/commands/cvd/fetch/vector_flags.cc | 4 + .../host/commands/cvd/fetch/vector_flags.h | 2 + 14 files changed, 178 insertions(+), 16 deletions(-) diff --git a/base/cvd/cuttlefish/host/commands/assemble_cvd/assemble_cvd.cc b/base/cvd/cuttlefish/host/commands/assemble_cvd/assemble_cvd.cc index 6424bc842c0..5436b7e1b61 100644 --- a/base/cvd/cuttlefish/host/commands/assemble_cvd/assemble_cvd.cc +++ b/base/cvd/cuttlefish/host/commands/assemble_cvd/assemble_cvd.cc @@ -666,7 +666,7 @@ Result AssembleCvdMain(int argc, char** argv) { SuperImageFlag::FromGlobalGflags(system_image_dir); VendorBootImageFlag vendor_boot_image = - VendorBootImageFlag::FromGlobalGflags(system_image_dir); + CF_EXPECT(VendorBootImageFlag::FromGlobalGflags(system_image_dir)); fruit::Injector<> injector(FlagsComponent, &system_image_dir); diff --git a/base/cvd/cuttlefish/host/commands/assemble_cvd/flags/BUILD.bazel b/base/cvd/cuttlefish/host/commands/assemble_cvd/flags/BUILD.bazel index af491dbbbac..2892f8f8080 100644 --- a/base/cvd/cuttlefish/host/commands/assemble_cvd/flags/BUILD.bazel +++ b/base/cvd/cuttlefish/host/commands/assemble_cvd/flags/BUILD.bazel @@ -335,7 +335,9 @@ cf_cc_library( hdrs = ["vendor_boot_image.h"], deps = [ "//cuttlefish/host/commands/assemble_cvd:flags_defaults", + "//cuttlefish/host/commands/assemble_cvd/flags:from_gflags", "//cuttlefish/host/commands/assemble_cvd/flags:system_image_dir", + "//cuttlefish/result", "@abseil-cpp//absl/strings", "@gflags", ], diff --git a/base/cvd/cuttlefish/host/commands/assemble_cvd/flags/vendor_boot_image.cc b/base/cvd/cuttlefish/host/commands/assemble_cvd/flags/vendor_boot_image.cc index 1a810e22cfe..4eba15e9ed3 100644 --- a/base/cvd/cuttlefish/host/commands/assemble_cvd/flags/vendor_boot_image.cc +++ b/base/cvd/cuttlefish/host/commands/assemble_cvd/flags/vendor_boot_image.cc @@ -24,31 +24,62 @@ #include "absl/strings/str_split.h" #include "gflags/gflags.h" +#include "cuttlefish/host/commands/assemble_cvd/flags/from_gflags.h" #include "cuttlefish/host/commands/assemble_cvd/flags/system_image_dir.h" #include "cuttlefish/host/commands/assemble_cvd/flags_defaults.h" +#include "cuttlefish/result/result.h" + +DEFINE_string(use_vendor_boot_debug, + CF_DEFAULTS_USE_VENDOR_BOOT_DEBUG ? "true" : "false", + "Use vendor_boot-debug.img in the system_image_dir instead of " + "vendor_boot.img. Has no effect if -vendor_boot_image is set."); DEFINE_string( vendor_boot_image, CF_DEFAULTS_VENDOR_BOOT_IMAGE, - "Location of cuttlefish vendor boot image. If empty it is assumed to " - "be vendor_boot.img in the directory specified by -system_image_dir."); + "Location of cuttlefish vendor boot image. If empty, the image is " + "selected from the directory specified by -system_image-dir based on " + "the value of -use_vendor_boot_debug."); namespace cuttlefish { -VendorBootImageFlag VendorBootImageFlag::FromGlobalGflags( +Result VendorBootImageFlag::FromGlobalGflags( const SystemImageDirFlag& system_image_dir) { - gflags::CommandLineFlagInfo flag_info = + gflags::CommandLineFlagInfo vendor_boot_image_flag_info = gflags::GetCommandLineFlagInfoOrDie("vendor_boot_image"); + gflags::CommandLineFlagInfo use_vendor_boot_debug_flag_info = + gflags::GetCommandLineFlagInfoOrDie("use_vendor_boot_debug"); + + FromGflags use_vendor_boot_debug_flag = CF_EXPECT( + BoolFromGlobalGflags(use_vendor_boot_debug_flag_info, "vendor_boot_image", + CF_DEFAULTS_USE_VENDOR_BOOT_DEBUG)); std::vector vendor_boot_images = - flag_info.is_default ? std::vector{} - : absl::StrSplit(FLAGS_vendor_boot_image, ','); + vendor_boot_image_flag_info.is_default + ? std::vector{} + : absl::StrSplit(FLAGS_vendor_boot_image, ','); - return VendorBootImageFlag(system_image_dir, vendor_boot_images); + return VendorBootImageFlag(system_image_dir, vendor_boot_images, + use_vendor_boot_debug_flag.values); } std::string VendorBootImageFlag::VendorBootImageForIndex(size_t index) const { if (vendor_boot_images_.empty()) { - return system_image_dir_.ForIndex(index) + "/vendor_boot.img"; + std::string dir = system_image_dir_.ForIndex(index); + bool use_vendor_boot_debug = false; + + if (index < use_vendor_boot_debugs_.size()) { + use_vendor_boot_debug = use_vendor_boot_debugs_[index]; + } else if (!use_vendor_boot_debugs_.empty()) { + use_vendor_boot_debug = use_vendor_boot_debugs_[0]; + } + + if (use_vendor_boot_debug) { + dir += "/vendor_boot-debug.img"; + } else { + dir += "/vendor_boot.img"; + } + + return dir; } else if (index < vendor_boot_images_.size()) { return vendor_boot_images_[index]; } else { @@ -62,8 +93,10 @@ bool VendorBootImageFlag::IsDefault() const { VendorBootImageFlag::VendorBootImageFlag( const SystemImageDirFlag& system_image_dir, - std::vector vendor_boot_images) + std::vector vendor_boot_images, + std::vector use_vendor_boot_debugs) : system_image_dir_(system_image_dir), - vendor_boot_images_(std::move(vendor_boot_images)) {} + vendor_boot_images_(std::move(vendor_boot_images)), + use_vendor_boot_debugs_(std::move(use_vendor_boot_debugs)) {} } // namespace cuttlefish diff --git a/base/cvd/cuttlefish/host/commands/assemble_cvd/flags/vendor_boot_image.h b/base/cvd/cuttlefish/host/commands/assemble_cvd/flags/vendor_boot_image.h index 95c2ef111f4..2f8a1859510 100644 --- a/base/cvd/cuttlefish/host/commands/assemble_cvd/flags/vendor_boot_image.h +++ b/base/cvd/cuttlefish/host/commands/assemble_cvd/flags/vendor_boot_image.h @@ -21,23 +21,27 @@ #include #include "cuttlefish/host/commands/assemble_cvd/flags/system_image_dir.h" +#include "cuttlefish/result/result.h" namespace cuttlefish { /* Vendor boot image flag, `--vendor_boot_image` */ class VendorBootImageFlag { public: - static VendorBootImageFlag FromGlobalGflags(const SystemImageDirFlag&); + static Result FromGlobalGflags( + const SystemImageDirFlag&); std::string VendorBootImageForIndex(size_t index) const; bool IsDefault() const; private: - VendorBootImageFlag(const SystemImageDirFlag&, std::vector); + VendorBootImageFlag(const SystemImageDirFlag&, std::vector, + std::vector); const SystemImageDirFlag& system_image_dir_; std::vector vendor_boot_images_; + std::vector use_vendor_boot_debugs_; }; } // namespace cuttlefish diff --git a/base/cvd/cuttlefish/host/commands/assemble_cvd/flags_defaults.h b/base/cvd/cuttlefish/host/commands/assemble_cvd/flags_defaults.h index 5b9e990250b..e309aacbbd0 100644 --- a/base/cvd/cuttlefish/host/commands/assemble_cvd/flags_defaults.h +++ b/base/cvd/cuttlefish/host/commands/assemble_cvd/flags_defaults.h @@ -131,6 +131,7 @@ #define CF_DEFAULTS_VBMETA_SYSTEM_IMAGE CF_DEFAULTS_DYNAMIC_STRING #define CF_DEFAULTS_VBMETA_VENDOR_DLKM_IMAGE CF_DEFAULTS_DYNAMIC_STRING #define CF_DEFAULTS_VBMETA_SYSTEM_DLKM_IMAGE CF_DEFAULTS_DYNAMIC_STRING +#define CF_DEFAULTS_USE_VENDOR_BOOT_DEBUG false #define CF_DEFAULTS_VENDOR_BOOT_IMAGE CF_DEFAULTS_DYNAMIC_STRING #define CF_DEFAULTS_DEFAULT_VVMTRUSTSTORE_FILE_NAME CF_DEFAULTS_DYNAMIC_STRING #define CF_DEFAULTS_VVMTRUSTSTORE_PATH CF_DEFAULTS_DYNAMIC_STRING diff --git a/base/cvd/cuttlefish/host/commands/cvd/cli/parser/fetch_config_parser.cpp b/base/cvd/cuttlefish/host/commands/cvd/cli/parser/fetch_config_parser.cpp index 5ad0bec4967..a5656e23005 100644 --- a/base/cvd/cuttlefish/host/commands/cvd/cli/parser/fetch_config_parser.cpp +++ b/base/cvd/cuttlefish/host/commands/cvd/cli/parser/fetch_config_parser.cpp @@ -137,6 +137,14 @@ static bool DownloadTargetFilesZip(const Instance& instance) { } } +static bool UseVendorBootDebug(const Instance& instance) { + if (instance.boot().has_use_vendor_boot_debug()) { + return instance.boot().use_vendor_boot_debug(); + } else { + return kDefaultUseVendorBootDebug; + } +} + } // namespace Result> ParseFetchCvdConfigs( @@ -211,6 +219,8 @@ Result> ParseFetchCvdConfigs( DownloadImgZip)); result.emplace_back(GenerateInstanceFlag( "download_target_files_zip", fetch_instances, DownloadTargetFilesZip)); + result.emplace_back(GenerateInstanceFlag( + "download_vendor_boot_debug", fetch_instances, UseVendorBootDebug)); return result; } diff --git a/base/cvd/cuttlefish/host/commands/cvd/cli/parser/instance/boot_configs_test.cc b/base/cvd/cuttlefish/host/commands/cvd/cli/parser/instance/boot_configs_test.cc index b254d2a289f..b137308a5d6 100644 --- a/base/cvd/cuttlefish/host/commands/cvd/cli/parser/instance/boot_configs_test.cc +++ b/base/cvd/cuttlefish/host/commands/cvd/cli/parser/instance/boot_configs_test.cc @@ -133,6 +133,83 @@ TEST(BootFlagsParserTest, ParseTwoInstancesBootAnimationFlagFullJson) { << "enable_bootanimation flag is missing or wrongly formatted"; } +TEST(BootFlagsParserTest, ParseTwoInstancesUseVendorBootDebugFlagPartialJson) { + const char* test_string = R""""( +{ + "instances" : + [ + { + "vm": { + "crosvm":{ + } + }, + "boot": { + } + }, + { + "vm": { + "crosvm":{ + } + }, + "boot": { + "use_vendor_boot_debug": true + } + } + ] +} + )""""; + + Json::Value json_configs; + std::string json_text(test_string); + + EXPECT_TRUE(ParseJsonString(json_text, json_configs)) + << "Invalid Json string"; + auto serialized_data = LaunchCvdParserTester(json_configs); + ASSERT_THAT(serialized_data, IsOk()); + EXPECT_TRUE( + FindConfig(*serialized_data, R"(--use_vendor_boot_debug=false,true)")) + << "use_vendor_boot_debug flag is missing or wrongly formatted"; +} + +TEST(BootFlagsParserTest, ParseTwoInstancesUseVendorBootDebugFlagFullJson) { + const char* test_string = R""""( +{ + "instances" : + [ + { + "vm": { + "crosvm":{ + } + }, + "boot": { + "use_vendor_boot_debug": true + } + }, + { + "vm": { + "crosvm":{ + } + }, + "boot": { + "use_vendor_boot_debug": true + } + } + ] +} + )""""; + + Json::Value json_configs; + std::string json_text(test_string); + + EXPECT_TRUE(ParseJsonString(json_text, json_configs)) + << "Invalid Json string"; + auto serialized_data = LaunchCvdParserTester(json_configs); + ASSERT_THAT(serialized_data, IsOk()); + EXPECT_TRUE( + FindConfig(*serialized_data, R"(--use_vendor_boot_debug=true,true)")) + << "use_vendor_boot_debug flag is missing or wrongly formatted"; +} + TEST(BootFlagsParserTest, ParseTwoInstancesSerialNumberFlagEmptyJson) { const char* test_string = R""""( { diff --git a/base/cvd/cuttlefish/host/commands/cvd/cli/parser/instance/cf_boot_configs.cpp b/base/cvd/cuttlefish/host/commands/cvd/cli/parser/instance/cf_boot_configs.cpp index a5ff41947e5..e14cbae2583 100644 --- a/base/cvd/cuttlefish/host/commands/cvd/cli/parser/instance/cf_boot_configs.cpp +++ b/base/cvd/cuttlefish/host/commands/cvd/cli/parser/instance/cf_boot_configs.cpp @@ -47,12 +47,19 @@ static Result BootCfgArgs(const Instance& instance) { return encoded; } +static bool UseVendorBootDebug(const Instance& instance) { + const auto& boot = instance.boot(); + return boot.has_use_vendor_boot_debug() ? boot.use_vendor_boot_debug() + : CF_DEFAULTS_USE_VENDOR_BOOT_DEBUG; +} + Result> GenerateBootFlags( const EnvironmentSpecification& cfg) { return std::vector{ GenerateInstanceFlag("enable_bootanimation", cfg, EnableBootAnimation), CF_EXPECT( ResultInstanceFlag("extra_bootconfig_args_base64", cfg, BootCfgArgs)), + GenerateInstanceFlag("use_vendor_boot_debug", cfg, UseVendorBootDebug), }; } diff --git a/base/cvd/cuttlefish/host/commands/cvd/cli/parser/load_config.proto b/base/cvd/cuttlefish/host/commands/cvd/cli/parser/load_config.proto index 43fc763d3ea..848d4571bce 100644 --- a/base/cvd/cuttlefish/host/commands/cvd/cli/parser/load_config.proto +++ b/base/cvd/cuttlefish/host/commands/cvd/cli/parser/load_config.proto @@ -107,6 +107,7 @@ message Boot { optional string build = 4; optional Build bootloader = 5; optional Build android_efi_loader = 6; + optional bool use_vendor_boot_debug = 7; } message Build { diff --git a/base/cvd/cuttlefish/host/commands/cvd/fetch/download_flags.cc b/base/cvd/cuttlefish/host/commands/cvd/fetch/download_flags.cc index 41100b29220..ab2d3d4039d 100644 --- a/base/cvd/cuttlefish/host/commands/cvd/fetch/download_flags.cc +++ b/base/cvd/cuttlefish/host/commands/cvd/fetch/download_flags.cc @@ -29,6 +29,10 @@ DownloadFlags DownloadFlags::Create(const VectorFlags& flags, const int index) { .value_or(kDefaultDownloadTargetFilesZip), .dynamic_super_image = GetOptional(flags.dynamic_super_image, index) .value_or(kDefaultDynamicSuperImageFragments), + .download_vendor_boot_debug = + GetOptional(flags.download_vendor_boot_debug, index) + .value_or(kDefaultUseVendorBootDebug), + }; } diff --git a/base/cvd/cuttlefish/host/commands/cvd/fetch/download_flags.h b/base/cvd/cuttlefish/host/commands/cvd/fetch/download_flags.h index 00b29c200c7..96e70f33803 100644 --- a/base/cvd/cuttlefish/host/commands/cvd/fetch/download_flags.h +++ b/base/cvd/cuttlefish/host/commands/cvd/fetch/download_flags.h @@ -25,6 +25,7 @@ struct DownloadFlags { bool download_img_zip; bool download_target_files_zip; bool dynamic_super_image; + bool download_vendor_boot_debug; }; } // namespace cuttlefish diff --git a/base/cvd/cuttlefish/host/commands/cvd/fetch/fetch_cvd.cc b/base/cvd/cuttlefish/host/commands/cvd/fetch/fetch_cvd.cc index 064d20947af..bbcfc6593bd 100644 --- a/base/cvd/cuttlefish/host/commands/cvd/fetch/fetch_cvd.cc +++ b/base/cvd/cuttlefish/host/commands/cvd/fetch/fetch_cvd.cc @@ -192,6 +192,12 @@ Result SaveConfig(FetcherConfig& config, return fetcher_path; } +Result DownloadVendorBootDebug(FetchBuildContext& context) { + FetchArtifact vendor_boot_debug = context.Artifact("vendor_boot-debug.img"); + CF_EXPECT(vendor_boot_debug.Download()); + return {}; +} + Result FetchDefaultTarget(FetchBuildContext& context, bool keep_downloaded_archives, const DownloadFlags& flags, @@ -253,6 +259,10 @@ Result FetchDefaultTarget(FetchBuildContext& context, } } } + + if (flags.download_vendor_boot_debug) { + CF_EXPECT(DownloadVendorBootDebug(context)); + } return {}; } @@ -314,7 +324,8 @@ Result FetchKernelTarget(FetchBuildContext context) { } Result FetchBootTarget(FetchBuildContext& context, - bool keep_downloaded_archives) { + bool keep_downloaded_archives, + bool download_vendor_boot_debug) { const std::optional filepath = context.GetFilepath(); const std::string to_download = filepath.has_value() ? *filepath : context.GetBuildZipName("img"); @@ -323,7 +334,11 @@ Result FetchBootTarget(FetchBuildContext& context, if (!filepath.has_value()) { CF_EXPECT(artifact.ExtractOne("boot.img")); - CF_EXPECT(artifact.ExtractOne("vendor_boot.img")); + if (download_vendor_boot_debug) { + CF_EXPECT(DownloadVendorBootDebug(context)); + } else { + CF_EXPECT(artifact.ExtractOne("vendor_boot.img")); + } if (!keep_downloaded_archives) { CF_EXPECT(artifact.DeleteLocalFile()); } @@ -422,7 +437,8 @@ Result FetchTarget(FetchContext& fetch_context, } if (std::optional context = fetch_context.BootBuild()) { - CF_EXPECT(FetchBootTarget(*context, keep_downloaded_archives)); + CF_EXPECT(FetchBootTarget(*context, keep_downloaded_archives, + flags.download_vendor_boot_debug)); } if (std::optional ctx = fetch_context.BootloaderBuild()) { diff --git a/base/cvd/cuttlefish/host/commands/cvd/fetch/vector_flags.cc b/base/cvd/cuttlefish/host/commands/cvd/fetch/vector_flags.cc index 0a97d894731..bb98bf63d02 100644 --- a/base/cvd/cuttlefish/host/commands/cvd/fetch/vector_flags.cc +++ b/base/cvd/cuttlefish/host/commands/cvd/fetch/vector_flags.cc @@ -76,6 +76,10 @@ std::vector VectorFlags::Flags() { GflagsCompatFlag("dynamic_super_image", this->dynamic_super_image, kDefaultDynamicSuperImageFragments) .Help("Fetch the super image members as independent files.")); + flags.emplace_back(GflagsCompatFlag("download_vendor_boot_debug", + this->download_vendor_boot_debug, + kDefaultUseVendorBootDebug) + .Help("Fetch vendor_boot-debug.img.")); return flags; } diff --git a/base/cvd/cuttlefish/host/commands/cvd/fetch/vector_flags.h b/base/cvd/cuttlefish/host/commands/cvd/fetch/vector_flags.h index 7461298d640..e585a639668 100644 --- a/base/cvd/cuttlefish/host/commands/cvd/fetch/vector_flags.h +++ b/base/cvd/cuttlefish/host/commands/cvd/fetch/vector_flags.h @@ -30,6 +30,7 @@ inline constexpr bool kDefaultDownloadImgZip = true; inline constexpr bool kDefaultDownloadTargetFilesZip = false; // TODO: schuffelen - Enable this by default. inline constexpr bool kDefaultDynamicSuperImageFragments = false; +inline constexpr bool kDefaultUseVendorBootDebug = false; struct VectorFlags { std::vector Flags(); @@ -49,6 +50,7 @@ struct VectorFlags { std::vector download_target_files_zip; std::vector boot_artifact; std::vector dynamic_super_image; + std::vector download_vendor_boot_debug; }; } // namespace cuttlefish