1 /*
2  * Copyright (C) 2019 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/commands/assemble_cvd/disk_flags.h"
18 
19 #include <sys/statvfs.h>
20 
21 #include <fstream>
22 #include <string>
23 #include <vector>
24 
25 #include <android-base/logging.h>
26 #include <android-base/parsebool.h>
27 #include <android-base/parseint.h>
28 #include <android-base/strings.h>
29 #include <fruit/fruit.h>
30 #include <gflags/gflags.h>
31 
32 #include "common/libs/fs/shared_buf.h"
33 #include "common/libs/utils/files.h"
34 #include "common/libs/utils/flag_parser.h"
35 #include "common/libs/utils/result.h"
36 #include "common/libs/utils/size_utils.h"
37 #include "common/libs/utils/subprocess.h"
38 #include "host/commands/assemble_cvd/boot_config.h"
39 #include "host/commands/assemble_cvd/boot_image_utils.h"
40 #include "host/commands/assemble_cvd/bootconfig_args.h"
41 #include "host/commands/assemble_cvd/disk/disk.h"
42 #include "host/commands/assemble_cvd/disk_builder.h"
43 #include "host/commands/assemble_cvd/flags_defaults.h"
44 #include "host/commands/assemble_cvd/super_image_mixer.h"
45 #include "host/commands/assemble_cvd/vendor_dlkm_utils.h"
46 #include "host/libs/avb/avb.h"
47 #include "host/libs/config/cuttlefish_config.h"
48 #include "host/libs/config/data_image.h"
49 #include "host/libs/config/inject.h"
50 #include "host/libs/config/instance_nums.h"
51 #include "host/libs/vm_manager/gem5_manager.h"
52 
53 DECLARE_string(system_image_dir);
54 
55 DEFINE_string(boot_image, CF_DEFAULTS_BOOT_IMAGE,
56               "Location of cuttlefish boot image. If empty it is assumed to be "
57               "boot.img in the directory specified by -system_image_dir.");
58 DEFINE_string(
59     init_boot_image, CF_DEFAULTS_INIT_BOOT_IMAGE,
60     "Location of cuttlefish init boot image. If empty it is assumed to "
61     "be init_boot.img in the directory specified by -system_image_dir.");
62 DEFINE_string(data_image, CF_DEFAULTS_DATA_IMAGE,
63               "Location of the data partition image.");
64 DEFINE_string(super_image, CF_DEFAULTS_SUPER_IMAGE,
65               "Location of the super partition image.");
66 DEFINE_string(misc_info_txt, "", "Location of the misc_info.txt file.");
67 DEFINE_string(
68     vendor_boot_image, CF_DEFAULTS_VENDOR_BOOT_IMAGE,
69     "Location of cuttlefish vendor boot image. If empty it is assumed to "
70     "be vendor_boot.img in the directory specified by -system_image_dir.");
71 DEFINE_string(vbmeta_image, CF_DEFAULTS_VBMETA_IMAGE,
72               "Location of cuttlefish vbmeta image. If empty it is assumed to "
73               "be vbmeta.img in the directory specified by -system_image_dir.");
74 DEFINE_string(
75     vbmeta_system_image, CF_DEFAULTS_VBMETA_SYSTEM_IMAGE,
76     "Location of cuttlefish vbmeta_system image. If empty it is assumed to "
77     "be vbmeta_system.img in the directory specified by -system_image_dir.");
78 DEFINE_string(
79     vbmeta_vendor_dlkm_image, CF_DEFAULTS_VBMETA_VENDOR_DLKM_IMAGE,
80     "Location of cuttlefish vbmeta_vendor_dlkm image. If empty it is assumed "
81     "to "
82     "be vbmeta_vendor_dlkm.img in the directory specified by "
83     "-system_image_dir.");
84 DEFINE_string(
85     vbmeta_system_dlkm_image, CF_DEFAULTS_VBMETA_SYSTEM_DLKM_IMAGE,
86     "Location of cuttlefish vbmeta_system_dlkm image. If empty it is assumed "
87     "to "
88     "be vbmeta_system_dlkm.img in the directory specified by "
89     "-system_image_dir.");
90 
91 DEFINE_string(
92     default_target_zip, CF_DEFAULTS_DEFAULT_TARGET_ZIP,
93     "Location of default target zip file.");
94 DEFINE_string(
95     system_target_zip, CF_DEFAULTS_SYSTEM_TARGET_ZIP,
96     "Location of system target zip file.");
97 
98 DEFINE_string(android_efi_loader, CF_DEFAULTS_ANDROID_EFI_LOADER,
99               "Location of android EFI loader for android efi load flow.");
100 
101 DEFINE_string(linux_kernel_path, CF_DEFAULTS_LINUX_KERNEL_PATH,
102               "Location of linux kernel for cuttlefish otheros flow.");
103 DEFINE_string(linux_initramfs_path, CF_DEFAULTS_LINUX_INITRAMFS_PATH,
104               "Location of linux initramfs.img for cuttlefish otheros flow.");
105 DEFINE_string(linux_root_image, CF_DEFAULTS_LINUX_ROOT_IMAGE,
106               "Location of linux root filesystem image for cuttlefish otheros flow.");
107 
108 DEFINE_string(chromeos_disk, CF_DEFAULTS_CHROMEOS_DISK,
109               "Location of a complete ChromeOS GPT disk");
110 DEFINE_string(chromeos_kernel_path, CF_DEFAULTS_CHROMEOS_KERNEL_PATH,
111               "Location of the chromeos kernel for the chromeos flow.");
112 DEFINE_string(chromeos_root_image, CF_DEFAULTS_CHROMEOS_ROOT_IMAGE,
113               "Location of chromeos root filesystem image for chromeos flow.");
114 
115 DEFINE_string(fuchsia_zedboot_path, CF_DEFAULTS_FUCHSIA_ZEDBOOT_PATH,
116               "Location of fuchsia zedboot path for cuttlefish otheros flow.");
117 DEFINE_string(fuchsia_multiboot_bin_path, CF_DEFAULTS_FUCHSIA_MULTIBOOT_BIN_PATH,
118               "Location of fuchsia multiboot bin path for cuttlefish otheros flow.");
119 DEFINE_string(fuchsia_root_image, CF_DEFAULTS_FUCHSIA_ROOT_IMAGE,
120               "Location of fuchsia root filesystem image for cuttlefish otheros flow.");
121 
122 DEFINE_string(custom_partition_path, CF_DEFAULTS_CUSTOM_PARTITION_PATH,
123               "Location of custom image that will be passed as a \"custom\" partition"
124               "to rootfs and can be used by /dev/block/by-name/custom");
125 
126 DEFINE_string(blank_metadata_image_mb, CF_DEFAULTS_BLANK_METADATA_IMAGE_MB,
127               "The size of the blank metadata image to generate, MB.");
128 DEFINE_string(
129     blank_sdcard_image_mb, CF_DEFAULTS_BLANK_SDCARD_IMAGE_MB,
130     "If enabled, the size of the blank sdcard image to generate, MB.");
131 
132 DECLARE_string(ap_rootfs_image);
133 DECLARE_string(bootloader);
134 DECLARE_string(initramfs_path);
135 DECLARE_string(kernel_path);
136 DECLARE_bool(resume);
137 DECLARE_bool(use_overlay);
138 DECLARE_bool(use_16k);
139 
140 namespace cuttlefish {
141 
142 using APBootFlow = CuttlefishConfig::InstanceSpecific::APBootFlow;
143 using vm_manager::Gem5Manager;
144 
ResolveInstanceFiles()145 Result<void> ResolveInstanceFiles() {
146   CF_EXPECT(!FLAGS_system_image_dir.empty(),
147             "--system_image_dir must be specified.");
148   if (FLAGS_use_16k) {
149     CF_EXPECT(FLAGS_kernel_path.empty(),
150               "--use_16k is not compatible with --kernel_path");
151     CF_EXPECT(FLAGS_initramfs_path.empty(),
152               "--use_16k is not compatible with --initramfs_path");
153   }
154 
155   // It is conflict (invalid) to pass both kernel_path/initramfs_path
156   // and image file paths.
157   bool flags_kernel_initramfs_has_input = (FLAGS_kernel_path != "")
158                                           || (FLAGS_initramfs_path != "");
159   bool flags_image_has_input =
160       (FLAGS_super_image != "") || (FLAGS_vendor_boot_image != "") ||
161       (FLAGS_vbmeta_vendor_dlkm_image != "") ||
162       (FLAGS_vbmeta_system_dlkm_image != "") || (FLAGS_boot_image != "");
163   CF_EXPECT(!(flags_kernel_initramfs_has_input && flags_image_has_input),
164              "Cannot pass both kernel_path/initramfs_path and image file paths");
165 
166   std::vector<std::string> system_image_dir =
167       android::base::Split(FLAGS_system_image_dir, ",");
168   std::string default_boot_image = "";
169   std::string default_init_boot_image = "";
170   std::string default_data_image = "";
171   std::string default_super_image = "";
172   std::string default_misc_info_txt = "";
173   std::string default_vendor_boot_image = "";
174   std::string default_vbmeta_image = "";
175   std::string default_vbmeta_system_image = "";
176   std::string default_vbmeta_vendor_dlkm_image = "";
177   std::string default_vbmeta_system_dlkm_image = "";
178   std::string default_16k_kernel_image = "";
179   std::string default_16k_ramdisk_image = "";
180 
181   std::string cur_system_image_dir;
182   std::string comma_str = "";
183   auto instance_nums =
184       CF_EXPECT(InstanceNumsCalculator().FromGlobalGflags().Calculate());
185   for (int instance_index = 0; instance_index < instance_nums.size(); instance_index++) {
186     if (instance_index < system_image_dir.size()) {
187       cur_system_image_dir = system_image_dir[instance_index];
188     } else {
189       // legacy variable or out of boundary. Vectorize by copy [0] to all instances
190       cur_system_image_dir = system_image_dir[0];
191     }
192     if (instance_index > 0) {
193       comma_str = ",";
194     }
195 
196     // If user did not specify location of either of these files, expect them to
197     // be placed in --system_image_dir location.
198     default_boot_image += comma_str + cur_system_image_dir + "/boot.img";
199     default_init_boot_image += comma_str + cur_system_image_dir + "/init_boot.img";
200     default_data_image += comma_str + cur_system_image_dir + "/userdata.img";
201     default_super_image += comma_str + cur_system_image_dir + "/super.img";
202     default_misc_info_txt +=
203         comma_str + cur_system_image_dir + "/misc_info.txt";
204     default_vendor_boot_image += comma_str + cur_system_image_dir + "/vendor_boot.img";
205     default_vbmeta_image += comma_str + cur_system_image_dir + "/vbmeta.img";
206     default_vbmeta_system_image += comma_str + cur_system_image_dir + "/vbmeta_system.img";
207     default_vbmeta_vendor_dlkm_image +=
208         comma_str + cur_system_image_dir + "/vbmeta_vendor_dlkm.img";
209     default_vbmeta_system_dlkm_image +=
210         comma_str + cur_system_image_dir + "/vbmeta_system_dlkm.img";
211     if (FLAGS_use_16k) {
212       const auto kernel_16k = cur_system_image_dir + "/kernel_16k";
213       const auto ramdisk_16k = cur_system_image_dir + "/ramdisk_16k.img";
214       default_16k_kernel_image += comma_str + kernel_16k;
215       default_16k_ramdisk_image += comma_str + ramdisk_16k;
216       CF_EXPECT(FileExists(kernel_16k),
217                 kernel_16k + " missing for launching 16k cuttlefish");
218       CF_EXPECT(FileExists(ramdisk_16k),
219                 ramdisk_16k + " missing for launching 16k cuttlefish");
220     }
221   }
222   if (FLAGS_use_16k) {
223     LOG(INFO) << "Using 16k kernel: " << default_16k_kernel_image;
224     LOG(INFO) << "Using 16k ramdisk: " << default_16k_ramdisk_image;
225 
226     SetCommandLineOptionWithMode("kernel_path",
227                                  default_16k_kernel_image.c_str(),
228                                  google::FlagSettingMode::SET_FLAGS_DEFAULT);
229     SetCommandLineOptionWithMode("initramfs_path",
230                                  default_16k_ramdisk_image.c_str(),
231                                  google::FlagSettingMode::SET_FLAGS_DEFAULT);
232   }
233   SetCommandLineOptionWithMode("boot_image", default_boot_image.c_str(),
234                                google::FlagSettingMode::SET_FLAGS_DEFAULT);
235   SetCommandLineOptionWithMode("init_boot_image",
236                                default_init_boot_image.c_str(),
237                                google::FlagSettingMode::SET_FLAGS_DEFAULT);
238   SetCommandLineOptionWithMode("data_image", default_data_image.c_str(),
239                                google::FlagSettingMode::SET_FLAGS_DEFAULT);
240   SetCommandLineOptionWithMode("super_image", default_super_image.c_str(),
241                                google::FlagSettingMode::SET_FLAGS_DEFAULT);
242   SetCommandLineOptionWithMode("misc_info_txt", default_misc_info_txt.c_str(),
243                                google::FlagSettingMode::SET_FLAGS_DEFAULT);
244   SetCommandLineOptionWithMode("vendor_boot_image",
245                                default_vendor_boot_image.c_str(),
246                                google::FlagSettingMode::SET_FLAGS_DEFAULT);
247   SetCommandLineOptionWithMode("vbmeta_image", default_vbmeta_image.c_str(),
248                                google::FlagSettingMode::SET_FLAGS_DEFAULT);
249   SetCommandLineOptionWithMode("vbmeta_system_image",
250                                default_vbmeta_system_image.c_str(),
251                                google::FlagSettingMode::SET_FLAGS_DEFAULT);
252   SetCommandLineOptionWithMode("vbmeta_vendor_dlkm_image",
253                                default_vbmeta_vendor_dlkm_image.c_str(),
254                                google::FlagSettingMode::SET_FLAGS_DEFAULT);
255   SetCommandLineOptionWithMode("vbmeta_system_dlkm_image",
256                                default_vbmeta_system_dlkm_image.c_str(),
257                                google::FlagSettingMode::SET_FLAGS_DEFAULT);
258 
259   return {};
260 }
261 
chromeos_composite_disk_config(const CuttlefishConfig::InstanceSpecific & instance)262 std::vector<ImagePartition> chromeos_composite_disk_config(
263     const CuttlefishConfig::InstanceSpecific& instance) {
264   std::vector<ImagePartition> partitions;
265 
266   partitions.emplace_back(ImagePartition{
267       .label = "STATE",
268       .image_file_path = AbsolutePath(instance.chromeos_state_image()),
269       .type = kLinuxFilesystem,
270       .read_only = FLAGS_use_overlay,
271   });
272   partitions.emplace_back(ImagePartition{
273       .label = "linux_esp",
274       .image_file_path = AbsolutePath(instance.esp_image_path()),
275       .type = kEfiSystemPartition,
276       .read_only = FLAGS_use_overlay,
277   });
278   partitions.emplace_back(ImagePartition{
279       .label = "linux_root",
280       .image_file_path = AbsolutePath(instance.chromeos_root_image()),
281       .type = kLinuxFilesystem,
282       .read_only = FLAGS_use_overlay,
283   });
284 
285   return partitions;
286 }
287 
linux_composite_disk_config(const CuttlefishConfig::InstanceSpecific & instance)288 std::vector<ImagePartition> linux_composite_disk_config(
289     const CuttlefishConfig::InstanceSpecific& instance) {
290   std::vector<ImagePartition> partitions;
291 
292   partitions.push_back(ImagePartition{
293       .label = "linux_esp",
294       .image_file_path = AbsolutePath(instance.esp_image_path()),
295       .type = kEfiSystemPartition,
296       .read_only = FLAGS_use_overlay,
297   });
298   partitions.push_back(ImagePartition{
299       .label = "linux_root",
300       .image_file_path = AbsolutePath(instance.linux_root_image()),
301       .read_only = FLAGS_use_overlay,
302   });
303 
304   return partitions;
305 }
306 
fuchsia_composite_disk_config(const CuttlefishConfig::InstanceSpecific & instance)307 std::vector<ImagePartition> fuchsia_composite_disk_config(
308     const CuttlefishConfig::InstanceSpecific& instance) {
309   std::vector<ImagePartition> partitions;
310 
311   partitions.push_back(ImagePartition{
312       .label = "fuchsia_esp",
313       .image_file_path = AbsolutePath(instance.esp_image_path()),
314       .type = kEfiSystemPartition,
315       .read_only = FLAGS_use_overlay,
316   });
317 
318   return partitions;
319 }
320 
android_composite_disk_config(const CuttlefishConfig::InstanceSpecific & instance)321 std::vector<ImagePartition> android_composite_disk_config(
322     const CuttlefishConfig::InstanceSpecific& instance) {
323   std::vector<ImagePartition> partitions;
324 
325   partitions.push_back(ImagePartition{
326       .label = "misc",
327       .image_file_path = AbsolutePath(instance.misc_image()),
328       .read_only = FLAGS_use_overlay,
329   });
330   partitions.push_back(ImagePartition{
331       .label = "boot_a",
332       .image_file_path = AbsolutePath(instance.new_boot_image()),
333       .read_only = FLAGS_use_overlay,
334   });
335   partitions.push_back(ImagePartition{
336       .label = "boot_b",
337       .image_file_path = AbsolutePath(instance.new_boot_image()),
338       .read_only = FLAGS_use_overlay,
339   });
340   const auto init_boot_path = instance.init_boot_image();
341   if (FileExists(init_boot_path)) {
342     partitions.push_back(ImagePartition{
343         .label = "init_boot_a",
344         .image_file_path = AbsolutePath(init_boot_path),
345         .read_only = FLAGS_use_overlay,
346     });
347     partitions.push_back(ImagePartition{
348         .label = "init_boot_b",
349         .image_file_path = AbsolutePath(init_boot_path),
350         .read_only = FLAGS_use_overlay,
351     });
352   }
353   partitions.push_back(ImagePartition{
354       .label = "vendor_boot_a",
355       .image_file_path = AbsolutePath(instance.new_vendor_boot_image()),
356       .read_only = FLAGS_use_overlay,
357   });
358   partitions.push_back(ImagePartition{
359       .label = "vendor_boot_b",
360       .image_file_path = AbsolutePath(instance.new_vendor_boot_image()),
361       .read_only = FLAGS_use_overlay,
362   });
363   auto vbmeta_image = instance.new_vbmeta_image();
364   if (!FileExists(vbmeta_image)) {
365     vbmeta_image = instance.vbmeta_image();
366   }
367   partitions.push_back(ImagePartition{
368       .label = "vbmeta_a",
369       .image_file_path = AbsolutePath(vbmeta_image),
370       .read_only = FLAGS_use_overlay,
371   });
372   partitions.push_back(ImagePartition{
373       .label = "vbmeta_b",
374       .image_file_path = AbsolutePath(vbmeta_image),
375       .read_only = FLAGS_use_overlay,
376   });
377   partitions.push_back(ImagePartition{
378       .label = "vbmeta_system_a",
379       .image_file_path = AbsolutePath(instance.vbmeta_system_image()),
380       .read_only = FLAGS_use_overlay,
381   });
382   partitions.push_back(ImagePartition{
383       .label = "vbmeta_system_b",
384       .image_file_path = AbsolutePath(instance.vbmeta_system_image()),
385       .read_only = FLAGS_use_overlay,
386   });
387   auto vbmeta_vendor_dlkm_img = instance.new_vbmeta_vendor_dlkm_image();
388   if (!FileExists(vbmeta_vendor_dlkm_img)) {
389     vbmeta_vendor_dlkm_img = instance.vbmeta_vendor_dlkm_image();
390   }
391   if (FileExists(vbmeta_vendor_dlkm_img)) {
392     partitions.push_back(ImagePartition{
393         .label = "vbmeta_vendor_dlkm_a",
394         .image_file_path = AbsolutePath(vbmeta_vendor_dlkm_img),
395         .read_only = FLAGS_use_overlay,
396     });
397     partitions.push_back(ImagePartition{
398         .label = "vbmeta_vendor_dlkm_b",
399         .image_file_path = AbsolutePath(vbmeta_vendor_dlkm_img),
400         .read_only = FLAGS_use_overlay,
401     });
402   }
403   auto vbmeta_system_dlkm_img = instance.new_vbmeta_system_dlkm_image();
404   if (!FileExists(vbmeta_system_dlkm_img)) {
405     vbmeta_system_dlkm_img = instance.vbmeta_system_dlkm_image();
406   }
407   if (FileExists(vbmeta_system_dlkm_img)) {
408     partitions.push_back(ImagePartition{
409         .label = "vbmeta_system_dlkm_a",
410         .image_file_path = AbsolutePath(vbmeta_system_dlkm_img),
411         .read_only = FLAGS_use_overlay,
412     });
413     partitions.push_back(ImagePartition{
414         .label = "vbmeta_system_dlkm_b",
415         .image_file_path = AbsolutePath(vbmeta_system_dlkm_img),
416         .read_only = FLAGS_use_overlay,
417     });
418   }
419   auto super_image = instance.new_super_image();
420   if (!FileExists(super_image)) {
421     super_image = instance.super_image();
422   }
423   partitions.push_back(ImagePartition{
424       .label = "super",
425       .image_file_path = AbsolutePath(super_image),
426       .read_only = FLAGS_use_overlay,
427   });
428   auto data_image = instance.new_data_image();
429   if (!FileExists(data_image)) {
430     data_image = instance.data_image();
431   }
432   partitions.push_back(ImagePartition{
433       .label = "userdata",
434       .image_file_path = AbsolutePath(data_image),
435       .read_only = FLAGS_use_overlay,
436   });
437   partitions.push_back(ImagePartition{
438       .label = "metadata",
439       .image_file_path = AbsolutePath(instance.metadata_image()),
440       .read_only = FLAGS_use_overlay,
441   });
442   const auto custom_partition_path = instance.custom_partition_path();
443   if (!custom_partition_path.empty()) {
444     partitions.push_back(ImagePartition{
445         .label = "custom",
446         .image_file_path = AbsolutePath(custom_partition_path),
447         .read_only = FLAGS_use_overlay,
448     });
449   }
450 
451   return partitions;
452 }
453 
AndroidEfiLoaderCompositeDiskConfig(const CuttlefishConfig::InstanceSpecific & instance)454 std::vector<ImagePartition> AndroidEfiLoaderCompositeDiskConfig(
455     const CuttlefishConfig::InstanceSpecific& instance) {
456   std::vector<ImagePartition> partitions =
457       android_composite_disk_config(instance);
458   // Cuttlefish uboot EFI bootflow by default looks at the first partition
459   // for EFI application. Thus we put "android_esp" at the beginning.
460   partitions.insert(
461       partitions.begin(),
462       ImagePartition{
463           .label = "android_esp",
464           .image_file_path = AbsolutePath(instance.esp_image_path()),
465           .type = kEfiSystemPartition,
466           .read_only = FLAGS_use_overlay,
467       });
468 
469   return partitions;
470 }
471 
GetApCompositeDiskConfig(const CuttlefishConfig & config,const CuttlefishConfig::InstanceSpecific & instance)472 std::vector<ImagePartition> GetApCompositeDiskConfig(const CuttlefishConfig& config,
473     const CuttlefishConfig::InstanceSpecific& instance) {
474   std::vector<ImagePartition> partitions;
475 
476   if (instance.ap_boot_flow() == APBootFlow::Grub) {
477     partitions.push_back(ImagePartition{
478         .label = "ap_esp",
479         .image_file_path = AbsolutePath(instance.ap_esp_image_path()),
480         .read_only = FLAGS_use_overlay,
481     });
482   }
483 
484   partitions.push_back(ImagePartition{
485       .label = "ap_rootfs",
486       .image_file_path = AbsolutePath(config.ap_rootfs_image()),
487       .read_only = FLAGS_use_overlay,
488   });
489 
490   return partitions;
491 }
492 
GetOsCompositeDiskConfig(const CuttlefishConfig::InstanceSpecific & instance)493 std::vector<ImagePartition> GetOsCompositeDiskConfig(
494     const CuttlefishConfig::InstanceSpecific& instance) {
495   switch (instance.boot_flow()) {
496     case CuttlefishConfig::InstanceSpecific::BootFlow::Android:
497       return android_composite_disk_config(instance);
498     case CuttlefishConfig::InstanceSpecific::BootFlow::AndroidEfiLoader:
499       return AndroidEfiLoaderCompositeDiskConfig(instance);
500     case CuttlefishConfig::InstanceSpecific::BootFlow::ChromeOs:
501       return chromeos_composite_disk_config(instance);
502     case CuttlefishConfig::InstanceSpecific::BootFlow::ChromeOsDisk:
503       return {};
504     case CuttlefishConfig::InstanceSpecific::BootFlow::Linux:
505       return linux_composite_disk_config(instance);
506     case CuttlefishConfig::InstanceSpecific::BootFlow::Fuchsia:
507       return fuchsia_composite_disk_config(instance);
508   }
509 }
510 
OsCompositeDiskBuilder(const CuttlefishConfig & config,const CuttlefishConfig::InstanceSpecific & instance)511 DiskBuilder OsCompositeDiskBuilder(const CuttlefishConfig& config,
512     const CuttlefishConfig::InstanceSpecific& instance) {
513   auto builder =
514       DiskBuilder()
515           .VmManager(config.vm_manager())
516           .CrosvmPath(instance.crosvm_binary())
517           .ConfigPath(instance.PerInstancePath("os_composite_disk_config.txt"))
518           .ResumeIfPossible(FLAGS_resume);
519   if (instance.boot_flow() ==
520       CuttlefishConfig::InstanceSpecific::BootFlow::ChromeOsDisk) {
521     return builder.EntireDisk(instance.chromeos_disk())
522         .CompositeDiskPath(instance.chromeos_disk());
523   }
524   return builder.Partitions(GetOsCompositeDiskConfig(instance))
525       .HeaderPath(instance.PerInstancePath("os_composite_gpt_header.img"))
526       .FooterPath(instance.PerInstancePath("os_composite_gpt_footer.img"))
527       .CompositeDiskPath(instance.os_composite_disk_path());
528 }
529 
ApCompositeDiskBuilder(const CuttlefishConfig & config,const CuttlefishConfig::InstanceSpecific & instance)530 DiskBuilder ApCompositeDiskBuilder(const CuttlefishConfig& config,
531     const CuttlefishConfig::InstanceSpecific& instance) {
532   return DiskBuilder()
533       .Partitions(GetApCompositeDiskConfig(config, instance))
534       .VmManager(config.vm_manager())
535       .CrosvmPath(instance.crosvm_binary())
536       .ConfigPath(instance.PerInstancePath("ap_composite_disk_config.txt"))
537       .HeaderPath(instance.PerInstancePath("ap_composite_gpt_header.img"))
538       .FooterPath(instance.PerInstancePath("ap_composite_gpt_footer.img"))
539       .CompositeDiskPath(instance.ap_composite_disk_path())
540       .ResumeIfPossible(FLAGS_resume);
541 }
542 
AvailableSpaceAtPath(const std::string & path)543 static uint64_t AvailableSpaceAtPath(const std::string& path) {
544   struct statvfs vfs {};
545   if (statvfs(path.c_str(), &vfs) != 0) {
546     int error_num = errno;
547     LOG(ERROR) << "Could not find space available at " << path << ", error was "
548                << strerror(error_num);
549     return 0;
550   }
551   // f_frsize (block size) * f_bavail (free blocks) for unprivileged users.
552   return static_cast<uint64_t>(vfs.f_frsize) * vfs.f_bavail;
553 }
554 
InitializeChromeOsState(const CuttlefishConfig::InstanceSpecific & instance)555 Result<void> InitializeChromeOsState(
556     const CuttlefishConfig::InstanceSpecific& instance) {
557   using BootFlow = CuttlefishConfig::InstanceSpecific::BootFlow;
558   if (instance.boot_flow() != BootFlow::ChromeOs) {
559     return {};
560   } else if (FileExists(instance.chromeos_state_image())) {
561     return {};
562   }
563   CF_EXPECT(CreateBlankImage(instance.chromeos_state_image(), 8096, "ext4"));
564   return {};
565 }
566 
InitializeMetadataImage(const CuttlefishConfig::InstanceSpecific & instance)567 Result<void> InitializeMetadataImage(
568     const CuttlefishConfig::InstanceSpecific& instance) {
569   if (FileExists(instance.metadata_image()) &&
570       FileSize(instance.metadata_image()) == instance.blank_metadata_image_mb()
571                                                  << 20) {
572     return {};
573   }
574 
575   CF_EXPECT(CreateBlankImage(instance.metadata_image(),
576                              instance.blank_metadata_image_mb(), "none"),
577             "Failed to create \"" << instance.metadata_image()
578                                   << "\" with size "
579                                   << instance.blank_metadata_image_mb());
580   return {};
581 }
582 
InitializeAccessKregistryImage(const CuttlefishConfig::InstanceSpecific & instance)583 Result<void> InitializeAccessKregistryImage(
584     const CuttlefishConfig::InstanceSpecific& instance) {
585   auto access_kregistry = instance.access_kregistry_path();
586   if (FileExists(access_kregistry)) {
587     return {};
588   }
589   CF_EXPECT(CreateBlankImage(access_kregistry, 2 /* mb */, "none"),
590             "Failed to create \"" << access_kregistry << "\"");
591   return {};
592 }
593 
InitializeHwcomposerPmemImage(const CuttlefishConfig::InstanceSpecific & instance)594 Result<void> InitializeHwcomposerPmemImage(
595     const CuttlefishConfig::InstanceSpecific& instance) {
596   if (FileExists(instance.hwcomposer_pmem_path())) {
597     return {};
598   }
599   CF_EXPECT(
600       CreateBlankImage(instance.hwcomposer_pmem_path(), 2 /* mb */, "none"),
601       "Failed creating \"" << instance.hwcomposer_pmem_path() << "\"");
602   return {};
603 }
604 
InitializePstore(const CuttlefishConfig::InstanceSpecific & instance)605 Result<void> InitializePstore(
606     const CuttlefishConfig::InstanceSpecific& instance) {
607   if (FileExists(instance.pstore_path())) {
608     return {};
609   }
610 
611   CF_EXPECT(CreateBlankImage(instance.pstore_path(), 2 /* mb */, "none"),
612             "Failed to create \"" << instance.pstore_path() << "\"");
613   return {};
614 }
615 
InitializePflash(const CuttlefishConfig::InstanceSpecific & instance)616 Result<void> InitializePflash(
617     const CuttlefishConfig::InstanceSpecific& instance) {
618   if (FileExists(instance.pflash_path())) {
619     return {};
620   }
621 
622   auto boot_size_mb = FileSize(instance.bootloader()) / (1 << 20);
623 
624   // Pad out bootloader space to 4MB
625   CF_EXPECTF(CreateBlankImage(instance.pflash_path(), 4 - boot_size_mb, "none"),
626              "Failed to create '{}'", instance.pflash_path());
627   return {};
628 }
629 
InitializeSdCard(const CuttlefishConfig & config,const CuttlefishConfig::InstanceSpecific & instance)630 Result<void> InitializeSdCard(
631     const CuttlefishConfig& config,
632     const CuttlefishConfig::InstanceSpecific& instance) {
633   if (!(instance.use_sdcard() && !instance.protected_vm())) {
634     return {};
635   }
636   if (FileExists(instance.sdcard_path())) {
637     return {};
638   }
639   CF_EXPECT(CreateBlankImage(instance.sdcard_path(),
640                              instance.blank_sdcard_image_mb(), "sdcard"),
641             "Failed to create \"" << instance.sdcard_path() << "\"");
642   if (config.vm_manager() == VmmMode::kQemu) {
643     const std::string crosvm_path = instance.crosvm_binary();
644     CreateQcowOverlay(crosvm_path, instance.sdcard_path(),
645                       instance.sdcard_overlay_path());
646   }
647   return {};
648 }
649 
VbmetaEnforceMinimumSize(const CuttlefishConfig::InstanceSpecific & instance)650 Result<void> VbmetaEnforceMinimumSize(
651     const CuttlefishConfig::InstanceSpecific& instance) {
652   // libavb expects to be able to read the maximum vbmeta size, so we must
653   // provide a partition which matches this or the read will fail
654   for (const auto& vbmeta_image :
655        {instance.vbmeta_image(), instance.new_vbmeta_image(),
656         instance.vbmeta_system_image(), instance.vbmeta_vendor_dlkm_image(),
657         instance.vbmeta_system_dlkm_image()}) {
658     // In some configurations of cuttlefish, the vendor dlkm vbmeta image does
659     // not exist
660     if (FileExists(vbmeta_image)) {
661       CF_EXPECT(EnforceVbMetaSize(vbmeta_image));
662     }
663   }
664   return {};
665 }
666 
BootloaderPresentCheck(const CuttlefishConfig::InstanceSpecific & instance)667 Result<void> BootloaderPresentCheck(
668     const CuttlefishConfig::InstanceSpecific& instance) {
669   CF_EXPECT(FileHasContent(instance.bootloader()),
670             "File not found: " << instance.bootloader());
671   return {};
672 }
673 
DiskChangesComponent(const FetcherConfig * fetcher,const CuttlefishConfig * config,const CuttlefishConfig::InstanceSpecific * instance)674 static fruit::Component<> DiskChangesComponent(
675     const FetcherConfig* fetcher, const CuttlefishConfig* config,
676     const CuttlefishConfig::InstanceSpecific* instance) {
677   return fruit::createComponent()
678       .bindInstance(*fetcher)
679       .bindInstance(*config)
680       .bindInstance(*instance)
681       .install(CuttlefishKeyAvbComponent)
682       .install(AutoSetup<InitializeMetadataImage>::Component)
683       .install(AutoSetup<InitializeChromeOsState>::Component)
684       .install(KernelRamdiskRepackerComponent)
685       .install(AutoSetup<VbmetaEnforceMinimumSize>::Component)
686       .install(AutoSetup<BootloaderPresentCheck>::Component)
687       .install(AutoSetup<Gem5ImageUnpacker>::Component)
688       .install(AutoSetup<InitializeMiscImage>::Component)
689       // Create esp if necessary
690       .install(InitializeEspImageComponent)
691       .install(SuperImageRebuilderComponent);
692 }
693 
DiskChangesPerInstanceComponent(const FetcherConfig * fetcher,const CuttlefishConfig * config,const CuttlefishConfig::InstanceSpecific * instance)694 static fruit::Component<> DiskChangesPerInstanceComponent(
695     const FetcherConfig* fetcher, const CuttlefishConfig* config,
696     const CuttlefishConfig::InstanceSpecific* instance) {
697   return fruit::createComponent()
698       .bindInstance(*fetcher)
699       .bindInstance(*config)
700       .bindInstance(*instance)
701       .install(AutoSetup<InitializeAccessKregistryImage>::Component)
702       .install(AutoSetup<InitBootloaderEnvPartition>::Component)
703       .install(AutoSetup<InitializeFactoryResetProtected>::Component)
704       .install(AutoSetup<InitializeHwcomposerPmemImage>::Component)
705       .install(AutoSetup<InitializePstore>::Component)
706       .install(AutoSetup<InitializeSdCard>::Component)
707       .install(AutoSetup<GeneratePersistentBootconfig>::Component)
708       .install(AutoSetup<GeneratePersistentVbmeta>::Component)
709       .install(AutoSetup<InitializeInstanceCompositeDisk>::Component)
710       .install(AutoSetup<InitializeDataImage>::Component)
711       .install(AutoSetup<InitializePflash>::Component);
712 }
713 
DiskImageFlagsVectorization(CuttlefishConfig & config,const FetcherConfig & fetcher_config)714 Result<void> DiskImageFlagsVectorization(CuttlefishConfig& config, const FetcherConfig& fetcher_config) {
715   std::vector<std::string> boot_image =
716       android::base::Split(FLAGS_boot_image, ",");
717   std::vector<std::string> init_boot_image =
718       android::base::Split(FLAGS_init_boot_image, ",");
719   std::vector<std::string> data_image =
720       android::base::Split(FLAGS_data_image, ",");
721   std::vector<std::string> super_image =
722       android::base::Split(FLAGS_super_image, ",");
723   std::vector<std::string> misc_info =
724       android::base::Split(FLAGS_misc_info_txt, ",");
725   std::vector<std::string> vendor_boot_image =
726       android::base::Split(FLAGS_vendor_boot_image, ",");
727   std::vector<std::string> vbmeta_image =
728       android::base::Split(FLAGS_vbmeta_image, ",");
729   std::vector<std::string> vbmeta_system_image =
730       android::base::Split(FLAGS_vbmeta_system_image, ",");
731   auto vbmeta_vendor_dlkm_image =
732       android::base::Split(FLAGS_vbmeta_vendor_dlkm_image, ",");
733   auto vbmeta_system_dlkm_image =
734       android::base::Split(FLAGS_vbmeta_system_dlkm_image, ",");
735 
736   std::vector<std::string> default_target_zip_vec =
737       android::base::Split(FLAGS_default_target_zip, ",");
738   std::vector<std::string> system_target_zip_vec =
739       android::base::Split(FLAGS_system_target_zip, ",");
740 
741   std::vector<std::string> android_efi_loader =
742       android::base::Split(FLAGS_android_efi_loader, ",");
743 
744   std::vector<std::string> chromeos_disk =
745       android::base::Split(FLAGS_chromeos_disk, ",");
746   std::vector<std::string> chromeos_kernel_path =
747       android::base::Split(FLAGS_chromeos_kernel_path, ",");
748   std::vector<std::string> chromeos_root_image =
749       android::base::Split(FLAGS_chromeos_root_image, ",");
750 
751   std::vector<std::string> linux_kernel_path =
752       android::base::Split(FLAGS_linux_kernel_path, ",");
753   std::vector<std::string> linux_initramfs_path =
754       android::base::Split(FLAGS_linux_initramfs_path, ",");
755   std::vector<std::string> linux_root_image =
756       android::base::Split(FLAGS_linux_root_image, ",");
757 
758   std::vector<std::string> fuchsia_zedboot_path =
759       android::base::Split(FLAGS_fuchsia_zedboot_path, ",");
760   std::vector<std::string> fuchsia_multiboot_bin_path =
761       android::base::Split(FLAGS_fuchsia_multiboot_bin_path, ",");
762   std::vector<std::string> fuchsia_root_image =
763       android::base::Split(FLAGS_fuchsia_root_image, ",");
764 
765   std::vector<std::string> custom_partition_path =
766       android::base::Split(FLAGS_custom_partition_path, ",");
767 
768   std::vector<std::string> bootloader =
769       android::base::Split(FLAGS_bootloader, ",");
770   std::vector<std::string> initramfs_path =
771       android::base::Split(FLAGS_initramfs_path, ",");
772   std::vector<std::string> kernel_path =
773       android::base::Split(FLAGS_kernel_path, ",");
774 
775   std::vector<std::string> blank_metadata_image_mb =
776       android::base::Split(FLAGS_blank_metadata_image_mb, ",");
777   std::vector<std::string> blank_sdcard_image_mb =
778       android::base::Split(FLAGS_blank_sdcard_image_mb, ",");
779 
780   std::string cur_kernel_path;
781   std::string cur_initramfs_path;
782   std::string cur_boot_image;
783   std::string cur_vendor_boot_image;
784   std::string cur_super_image;
785   int value{};
786   int instance_index = 0;
787   auto instance_nums =
788       CF_EXPECT(InstanceNumsCalculator().FromGlobalGflags().Calculate());
789   for (const auto& num : instance_nums) {
790     auto instance = config.ForInstance(num);
791     if (instance_index >= misc_info.size()) {
792       instance.set_misc_info_txt(misc_info[0]);
793     } else {
794       instance.set_misc_info_txt(misc_info[instance_index]);
795     }
796     if (instance_index >= boot_image.size()) {
797       cur_boot_image = boot_image[0];
798     } else {
799       cur_boot_image = boot_image[instance_index];
800     }
801     instance.set_boot_image(cur_boot_image);
802     instance.set_new_boot_image(cur_boot_image);
803 
804     if (instance_index >= init_boot_image.size()) {
805       instance.set_init_boot_image(init_boot_image[0]);
806     } else {
807       instance.set_init_boot_image(init_boot_image[instance_index]);
808     }
809     if (instance_index >= vendor_boot_image.size()) {
810       cur_vendor_boot_image = vendor_boot_image[0];
811     } else {
812       cur_vendor_boot_image = vendor_boot_image[instance_index];
813     }
814     instance.set_vendor_boot_image(cur_vendor_boot_image);
815     instance.set_new_vendor_boot_image(cur_vendor_boot_image);
816 
817     if (instance_index >= vbmeta_image.size()) {
818       instance.set_vbmeta_image(vbmeta_image[0]);
819     } else {
820       instance.set_vbmeta_image(vbmeta_image[instance_index]);
821     }
822     if (instance_index >= vbmeta_system_image.size()) {
823       instance.set_vbmeta_system_image(vbmeta_system_image[0]);
824     } else {
825       instance.set_vbmeta_system_image(vbmeta_system_image[instance_index]);
826     }
827     if (instance_index >= vbmeta_vendor_dlkm_image.size()) {
828       instance.set_vbmeta_vendor_dlkm_image(vbmeta_vendor_dlkm_image[0]);
829     } else {
830       instance.set_vbmeta_vendor_dlkm_image(
831           vbmeta_vendor_dlkm_image[instance_index]);
832     }
833     if (instance_index >= vbmeta_system_dlkm_image.size()) {
834       instance.set_vbmeta_system_dlkm_image(vbmeta_system_dlkm_image[0]);
835     } else {
836       instance.set_vbmeta_system_dlkm_image(
837           vbmeta_system_dlkm_image[instance_index]);
838     }
839     if (instance_index >= super_image.size()) {
840       cur_super_image = super_image[0];
841     } else {
842       cur_super_image = super_image[instance_index];
843     }
844     instance.set_super_image(cur_super_image);
845     if (instance_index >= data_image.size()) {
846       instance.set_data_image(data_image[0]);
847     } else {
848       instance.set_data_image(data_image[instance_index]);
849     }
850     if (instance_index >= android_efi_loader.size()) {
851       instance.set_android_efi_loader(android_efi_loader[0]);
852     } else {
853       instance.set_android_efi_loader(android_efi_loader[instance_index]);
854     }
855     if (instance_index >= chromeos_disk.size()) {
856       instance.set_chromeos_disk(chromeos_disk[0]);
857     } else {
858       instance.set_chromeos_disk(chromeos_disk[instance_index]);
859     }
860     if (instance_index >= chromeos_kernel_path.size()) {
861       instance.set_chromeos_kernel_path(chromeos_kernel_path[0]);
862     } else {
863       instance.set_chromeos_kernel_path(chromeos_kernel_path[instance_index]);
864     }
865     if (instance_index >= chromeos_root_image.size()) {
866       instance.set_chromeos_root_image(chromeos_root_image[0]);
867     } else {
868       instance.set_chromeos_root_image(chromeos_root_image[instance_index]);
869     }
870     if (instance_index >= linux_kernel_path.size()) {
871       instance.set_linux_kernel_path(linux_kernel_path[0]);
872     } else {
873       instance.set_linux_kernel_path(linux_kernel_path[instance_index]);
874     }
875     if (instance_index >= linux_initramfs_path.size()) {
876       instance.set_linux_initramfs_path(linux_initramfs_path[0]);
877     } else {
878       instance.set_linux_initramfs_path(linux_initramfs_path[instance_index]);
879     }
880     if (instance_index >= linux_root_image.size()) {
881       instance.set_linux_root_image(linux_root_image[0]);
882     } else {
883       instance.set_linux_root_image(linux_root_image[instance_index]);
884     }
885     if (instance_index >= fuchsia_zedboot_path.size()) {
886       instance.set_fuchsia_zedboot_path(fuchsia_zedboot_path[0]);
887     } else {
888       instance.set_fuchsia_zedboot_path(fuchsia_zedboot_path[instance_index]);
889     }
890     if (instance_index >= fuchsia_multiboot_bin_path.size()) {
891       instance.set_fuchsia_multiboot_bin_path(fuchsia_multiboot_bin_path[0]);
892     } else {
893       instance.set_fuchsia_multiboot_bin_path(fuchsia_multiboot_bin_path[instance_index]);
894     }
895     if (instance_index >= fuchsia_root_image.size()) {
896       instance.set_fuchsia_root_image(fuchsia_root_image[0]);
897     } else {
898       instance.set_fuchsia_root_image(fuchsia_root_image[instance_index]);
899     }
900     if (instance_index >= custom_partition_path.size()) {
901       instance.set_custom_partition_path(custom_partition_path[0]);
902     } else {
903       instance.set_custom_partition_path(custom_partition_path[instance_index]);
904     }
905     if (instance_index >= bootloader.size()) {
906       instance.set_bootloader(bootloader[0]);
907     } else {
908       instance.set_bootloader(bootloader[instance_index]);
909     }
910     if (instance_index >= kernel_path.size()) {
911       cur_kernel_path = kernel_path[0];
912     } else {
913       cur_kernel_path = kernel_path[instance_index];
914     }
915     instance.set_kernel_path(cur_kernel_path);
916     if (instance_index >= initramfs_path.size()) {
917       cur_initramfs_path = initramfs_path[0];
918     } else {
919       cur_initramfs_path = initramfs_path[instance_index];
920     }
921     instance.set_initramfs_path(cur_initramfs_path);
922 
923     using android::base::ParseInt;
924     if (instance_index >= blank_metadata_image_mb.size()) {
925       CF_EXPECTF(ParseInt(blank_metadata_image_mb[0], &value), "'{}'",
926                  blank_metadata_image_mb[0]);
927     } else {
928       CF_EXPECTF(ParseInt(blank_metadata_image_mb[instance_index], &value),
929                  "'{}'", blank_metadata_image_mb[value]);
930     }
931     instance.set_blank_metadata_image_mb(value);
932 
933     if (instance_index >= blank_sdcard_image_mb.size()) {
934       CF_EXPECTF(ParseInt(blank_sdcard_image_mb[0], &value), "'{}'",
935                  blank_sdcard_image_mb[0]);
936     } else {
937       CF_EXPECTF(ParseInt(blank_sdcard_image_mb[instance_index], &value),
938                  "'{}'", blank_sdcard_image_mb[instance_index]);
939     }
940     instance.set_blank_sdcard_image_mb(value);
941 
942     // Repacking a boot.img changes boot_image and vendor_boot_image paths
943     const CuttlefishConfig& const_config = const_cast<const CuttlefishConfig&>(config);
944     const CuttlefishConfig::InstanceSpecific const_instance = const_config.ForInstance(num);
945     if (cur_kernel_path.size() && config.vm_manager() != VmmMode::kGem5) {
946       const std::string new_boot_image_path =
947           const_instance.PerInstancePath("boot_repacked.img");
948       // change the new flag value to corresponding instance
949       instance.set_new_boot_image(new_boot_image_path.c_str());
950     }
951 
952     instance.set_new_data_image(const_instance.PerInstancePath("userdata.img"));
953     if (instance_index >= data_image.size()) {
954       instance.set_data_image(data_image[0]);
955     } else {
956       instance.set_data_image(data_image[instance_index]);
957     }
958 
959     if (cur_kernel_path.size() || cur_initramfs_path.size()) {
960       const std::string new_vendor_boot_image_path =
961           const_instance.PerInstancePath("vendor_boot_repacked.img");
962       // Repack the vendor boot images if kernels and/or ramdisks are passed in.
963       if (cur_initramfs_path.size()) {
964         // change the new flag value to corresponding instance
965         instance.set_new_vendor_boot_image(new_vendor_boot_image_path.c_str());
966       }
967     }
968 
969     if (instance_index >= default_target_zip_vec.size()) {
970       instance.set_default_target_zip(default_target_zip_vec[0]);
971     } else {
972       instance.set_default_target_zip(default_target_zip_vec[instance_index]);
973     }
974     if (instance_index >= system_target_zip_vec.size()) {
975       instance.set_system_target_zip(system_target_zip_vec[0]);
976     } else {
977       instance.set_system_target_zip(system_target_zip_vec[instance_index]);
978     }
979 
980     // We will need to rebuild vendor_dlkm if custom ramdisk is specified, as a
981     // result super image would need to be rebuilt as well.
982     if (CF_EXPECT(SuperImageNeedsRebuilding(fetcher_config,
983                   const_instance.default_target_zip(),
984                   const_instance.system_target_zip())) ||
985         cur_initramfs_path.size()) {
986       const std::string new_super_image_path =
987           const_instance.PerInstancePath("super.img");
988       instance.set_new_super_image(new_super_image_path);
989       const std::string new_vbmeta_image_path =
990           const_instance.PerInstancePath("os_vbmeta.img");
991       instance.set_new_vbmeta_image(new_vbmeta_image_path);
992     }
993 
994     instance.set_new_vbmeta_vendor_dlkm_image(
995         const_instance.PerInstancePath("vbmeta_vendor_dlkm_repacked.img"));
996     instance.set_new_vbmeta_system_dlkm_image(
997         const_instance.PerInstancePath("vbmeta_system_dlkm_repacked.img"));
998 
999     instance_index++;
1000   }
1001   return {};
1002 }
1003 
CreateDynamicDiskFiles(const FetcherConfig & fetcher_config,const CuttlefishConfig & config)1004 Result<void> CreateDynamicDiskFiles(const FetcherConfig& fetcher_config,
1005                                     const CuttlefishConfig& config) {
1006   for (const auto& instance : config.Instances()) {
1007     // TODO(schuffelen): Unify this with the other injector created in
1008     // assemble_cvd.cpp
1009     fruit::Injector<> injector(DiskChangesComponent, &fetcher_config, &config,
1010                                &instance);
1011     for (auto& late_injected : injector.getMultibindings<LateInjected>()) {
1012       CF_EXPECT(late_injected->LateInject(injector));
1013     }
1014 
1015     const auto& features = injector.getMultibindings<SetupFeature>();
1016     CF_EXPECT(SetupFeature::RunSetup(features));
1017     fruit::Injector<> instance_injector(DiskChangesPerInstanceComponent,
1018                                         &fetcher_config, &config, &instance);
1019     for (auto& late_injected :
1020          instance_injector.getMultibindings<LateInjected>()) {
1021       CF_EXPECT(late_injected->LateInject(instance_injector));
1022     }
1023 
1024     const auto& instance_features =
1025         instance_injector.getMultibindings<SetupFeature>();
1026     CF_EXPECT(SetupFeature::RunSetup(instance_features),
1027               "instance = \"" << instance.instance_name() << "\"");
1028 
1029     // Check if filling in the sparse image would run out of disk space.
1030     auto existing_sizes = SparseFileSizes(instance.data_image());
1031     CF_EXPECT(existing_sizes.sparse_size > 0 || existing_sizes.disk_size > 0,
1032               "Unable to determine size of \"" << instance.data_image()
1033                                                << "\". Does this file exist?");
1034     auto available_space = AvailableSpaceAtPath(instance.data_image());
1035     if (available_space <
1036         existing_sizes.sparse_size - existing_sizes.disk_size) {
1037       // TODO(schuffelen): Duplicate this check in run_cvd when it can run on a
1038       // separate machine
1039       return CF_ERR("Not enough space remaining in fs containing \""
1040                     << instance.data_image() << "\", wanted "
1041                     << (existing_sizes.sparse_size - existing_sizes.disk_size)
1042                     << ", got " << available_space);
1043     } else {
1044       LOG(DEBUG) << "Available space: " << available_space;
1045       LOG(DEBUG) << "Sparse size of \"" << instance.data_image()
1046                  << "\": " << existing_sizes.sparse_size;
1047       LOG(DEBUG) << "Disk size of \"" << instance.data_image()
1048                  << "\": " << existing_sizes.disk_size;
1049     }
1050 
1051     auto os_disk_builder = OsCompositeDiskBuilder(config, instance);
1052     const auto os_built_composite = CF_EXPECT(os_disk_builder.BuildCompositeDiskIfNecessary());
1053 
1054     auto ap_disk_builder = ApCompositeDiskBuilder(config, instance);
1055     if (instance.ap_boot_flow() != APBootFlow::None) {
1056       CF_EXPECT(ap_disk_builder.BuildCompositeDiskIfNecessary());
1057     }
1058 
1059     if (os_built_composite) {
1060       if (FileExists(instance.access_kregistry_path())) {
1061         CF_EXPECT(CreateBlankImage(instance.access_kregistry_path(), 2 /* mb */,
1062                                    "none"),
1063                   "Failed for \"" << instance.access_kregistry_path() << "\"");
1064       }
1065       if (FileExists(instance.hwcomposer_pmem_path())) {
1066         CF_EXPECT(CreateBlankImage(instance.hwcomposer_pmem_path(), 2 /* mb */,
1067                                    "none"),
1068                   "Failed for \"" << instance.hwcomposer_pmem_path() << "\"");
1069       }
1070       if (FileExists(instance.pstore_path())) {
1071         CF_EXPECT(CreateBlankImage(instance.pstore_path(), 2 /* mb */, "none"),
1072                   "Failed for\"" << instance.pstore_path() << "\"");
1073       }
1074     }
1075 
1076     if (!instance.protected_vm()) {
1077       os_disk_builder.OverlayPath(instance.PerInstancePath("overlay.img"));
1078       CF_EXPECT(os_disk_builder.BuildOverlayIfNecessary());
1079       if (instance.ap_boot_flow() != APBootFlow::None) {
1080         ap_disk_builder.OverlayPath(instance.PerInstancePath("ap_overlay.img"));
1081         CF_EXPECT(ap_disk_builder.BuildOverlayIfNecessary());
1082       }
1083     }
1084   }
1085 
1086   for (auto instance : config.Instances()) {
1087     // Check that the files exist
1088     for (const auto& file : instance.virtual_disk_paths()) {
1089       if (!file.empty()) {
1090         CF_EXPECT(FileHasContent(file), "File not found: \"" << file << "\"");
1091       }
1092     }
1093     // Gem5 Simulate per-instance what the bootloader would usually do
1094     // Since on other devices this runs every time, just do it here every time
1095     if (config.vm_manager() == VmmMode::kGem5) {
1096       RepackGem5BootImage(instance.PerInstancePath("initrd.img"),
1097                           instance.persistent_bootconfig_path(),
1098                           config.assembly_dir(), instance.initramfs_path());
1099     }
1100   }
1101 
1102   return {};
1103 }
1104 
1105 } // namespace cuttlefish
1106