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