Extract the elf image from a compressed kernel image.
If the --decompress_kernel flag is given to the launcher, the kernel
image will be decompressed and stored in ${runtime_dir}/vmlinux. This
is the default (and required) behavior for crosvm.
Bug: 122978436
Test: build & run locally
Change-Id: I47e70d4cae20a398bc46772c3f5cb0dd9e3b5dcc
diff --git a/host/commands/launch/flags.cc b/host/commands/launch/flags.cc
index 5b67f2b..76cb1c8 100644
--- a/host/commands/launch/flags.cc
+++ b/host/commands/launch/flags.cc
@@ -43,6 +43,11 @@
DEFINE_int32(num_screen_buffers, 3, "The number of screen buffers");
DEFINE_string(kernel_path, "",
"Path to the kernel. Overrides the one from the boot image");
+DEFINE_bool(decompress_kernel, false,
+ "Whether to decompress the kernel image. Required for crosvm.");
+DEFINE_string(kernel_decompresser_executable,
+ vsoc::DefaultHostArtifactsPath("bin/extract-vmlinux"),
+ "Path to the extract-vmlinux executable.");
DEFINE_string(extra_kernel_cmdline, "",
"Additional flags to put on the kernel command line");
DEFINE_int32(loop_max_part, 7, "Maximum number of loop partitions");
@@ -245,6 +250,11 @@
tmp_config_obj.PerInstancePath("kernel"));
tmp_config_obj.set_use_unpacked_kernel(true);
}
+ tmp_config_obj.set_decompress_kernel(FLAGS_decompress_kernel);
+ if (FLAGS_decompress_kernel) {
+ tmp_config_obj.set_decompressed_kernel_image_path(
+ tmp_config_obj.PerInstancePath("vmlinux"));
+ }
auto ramdisk_path = tmp_config_obj.PerInstancePath("ramdisk.img");
bool use_ramdisk = boot_image_unpacker.HasRamdiskImage();
@@ -430,6 +440,8 @@
google::FlagSettingMode::SET_FLAGS_DEFAULT);
SetCommandLineOptionWithMode("adb_mode", "tunnel",
google::FlagSettingMode::SET_FLAGS_DEFAULT);
+ SetCommandLineOptionWithMode("decompress_kernel", "false",
+ google::FlagSettingMode::SET_FLAGS_DEFAULT);
}
void SetDefaultFlagsForCrosvm() {
@@ -459,6 +471,8 @@
google::FlagSettingMode::SET_FLAGS_DEFAULT);
SetCommandLineOptionWithMode("adb_mode", "vsock_tunnel",
google::FlagSettingMode::SET_FLAGS_DEFAULT);
+ SetCommandLineOptionWithMode("decompress_kernel", "true",
+ google::FlagSettingMode::SET_FLAGS_DEFAULT);
}
bool ParseCommandLineFlags(int* argc, char*** argv) {
@@ -513,6 +527,20 @@
}
return true;
}
+
+bool DecompressKernel(const std::string& src, const std::string& dst) {
+ cvd::Command decomp_cmd(FLAGS_kernel_decompresser_executable);
+ decomp_cmd.AddParameter(src);
+ auto output_file = cvd::SharedFD::Creat(dst.c_str(), 0666);
+ if (!output_file->IsOpen()) {
+ LOG(ERROR) << "Unable to create decompressed image file: "
+ << output_file->StrError();
+ return false;
+ }
+ decomp_cmd.RedirectStdIO(cvd::Subprocess::StdIOChannel::kStdOut, output_file);
+ auto decomp_proc = decomp_cmd.Start(false);
+ return decomp_proc.Started() && decomp_proc.Wait() == 0;
+}
} // namespace
vsoc::CuttlefishConfig* InitFilesystemAndCreateConfig(int* argc, char*** argv) {
@@ -563,6 +591,14 @@
exit(LauncherExitCodes::kBootImageUnpackError);
}
+ if (config->decompress_kernel()) {
+ if (!DecompressKernel(config->kernel_image_path(),
+ config->decompressed_kernel_image_path())) {
+ LOG(ERROR) << "Failed to decompress kernel";
+ exit(LauncherExitCodes::kKernelDecompressError);
+ }
+ }
+
ValidateAdbModeFlag(*config);
// Create data if necessary