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