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