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