1 /*
2  * Copyright (C) 2023 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/disk.h"
18 
19 #include <vector>
20 
21 #include <gflags/gflags.h>
22 
23 #include "common/libs/utils/files.h"
24 #include "host/commands/assemble_cvd/disk_builder.h"
25 #include "host/libs/config/cuttlefish_config.h"
26 #include "host/libs/image_aggregator/image_aggregator.h"
27 #include "host/libs/vm_manager/qemu_manager.h"
28 
29 DECLARE_bool(resume);
30 
31 namespace cuttlefish {
32 namespace {
33 
PersistentCompositeDiskConfig(const CuttlefishConfig::InstanceSpecific & instance)34 std::vector<ImagePartition> PersistentCompositeDiskConfig(
35     const CuttlefishConfig::InstanceSpecific& instance) {
36   std::vector<ImagePartition> partitions;
37 
38   // Note that if the position of uboot_env changes, the environment for
39   // u-boot must be updated as well (see boot_config.cc and
40   // cuttlefish.fragment in external/u-boot).
41   partitions.push_back(ImagePartition{
42       .label = "uboot_env",
43       .image_file_path = AbsolutePath(instance.uboot_env_image_path()),
44   });
45   partitions.push_back(ImagePartition{
46       .label = "vbmeta",
47       .image_file_path = AbsolutePath(instance.vbmeta_path()),
48   });
49   if (!instance.protected_vm()) {
50     partitions.push_back(ImagePartition{
51         .label = "frp",
52         .image_file_path =
53             AbsolutePath(instance.factory_reset_protected_path()),
54     });
55   }
56   if (instance.bootconfig_supported()) {
57     partitions.push_back(ImagePartition{
58         .label = "bootconfig",
59         .image_file_path = AbsolutePath(instance.persistent_bootconfig_path()),
60     });
61   }
62   return partitions;
63 }
64 
PersistentAPCompositeDiskConfig(const CuttlefishConfig::InstanceSpecific & instance)65 std::vector<ImagePartition> PersistentAPCompositeDiskConfig(
66     const CuttlefishConfig::InstanceSpecific& instance) {
67   std::vector<ImagePartition> partitions;
68 
69   // Note that if the position of uboot_env changes, the environment for
70   // u-boot must be updated as well (see boot_config.cc and
71   // cuttlefish.fragment in external/u-boot).
72   partitions.push_back(ImagePartition{
73       .label = "uboot_env",
74       .image_file_path = AbsolutePath(instance.ap_uboot_env_image_path()),
75   });
76   partitions.push_back(ImagePartition{
77       .label = "vbmeta",
78       .image_file_path = AbsolutePath(instance.ap_vbmeta_path()),
79   });
80 
81   return partitions;
82 }
83 
84 }  // namespace
85 
IsVmManagerQemu(const CuttlefishConfig & config)86 bool IsVmManagerQemu(const CuttlefishConfig& config) {
87   return config.vm_manager() == VmmMode::kQemu;
88 }
InitializeInstanceCompositeDisk(const CuttlefishConfig & config,const CuttlefishConfig::InstanceSpecific & instance,AutoSetup<InitializeFactoryResetProtected>::Type &,AutoSetup<GeneratePersistentVbmeta>::Type &)89 Result<void> InitializeInstanceCompositeDisk(
90     const CuttlefishConfig& config,
91     const CuttlefishConfig::InstanceSpecific& instance,
92     AutoSetup<InitializeFactoryResetProtected>::Type& /* dependency */,
93     AutoSetup<GeneratePersistentVbmeta>::Type& /* dependency */) {
94   const auto ipath = [&instance](const std::string& path) -> std::string {
95     return instance.PerInstancePath(path.c_str());
96   };
97   auto persistent_disk_builder =
98       DiskBuilder()
99           .Partitions(PersistentCompositeDiskConfig(instance))
100           .VmManager(config.vm_manager())
101           .CrosvmPath(instance.crosvm_binary())
102           .ConfigPath(ipath("persistent_composite_disk_config.txt"))
103           .HeaderPath(ipath("persistent_composite_gpt_header.img"))
104           .FooterPath(ipath("persistent_composite_gpt_footer.img"))
105           .CompositeDiskPath(instance.persistent_composite_disk_path())
106           .ResumeIfPossible(FLAGS_resume);
107   CF_EXPECT(persistent_disk_builder.BuildCompositeDiskIfNecessary());
108   persistent_disk_builder.OverlayPath(
109       instance.PerInstancePath("persistent_composite_overlay.img"));
110   if (IsVmManagerQemu(config)) {
111     CF_EXPECT(persistent_disk_builder.BuildOverlayIfNecessary());
112   }
113 
114   using APBootFlow = CuttlefishConfig::InstanceSpecific::APBootFlow;
115   if (instance.ap_boot_flow() == APBootFlow::Grub) {
116     auto persistent_ap_disk_builder =
117         DiskBuilder()
118             .Partitions(PersistentAPCompositeDiskConfig(instance))
119             .VmManager(config.vm_manager())
120             .CrosvmPath(instance.crosvm_binary())
121             .ConfigPath(ipath("ap_persistent_composite_disk_config.txt"))
122             .HeaderPath(ipath("ap_persistent_composite_gpt_header.img"))
123             .FooterPath(ipath("ap_persistent_composite_gpt_footer.img"))
124             .CompositeDiskPath(instance.persistent_ap_composite_disk_path())
125             .ResumeIfPossible(FLAGS_resume);
126     CF_EXPECT(persistent_ap_disk_builder.BuildCompositeDiskIfNecessary());
127     persistent_ap_disk_builder.OverlayPath(
128         instance.PerInstancePath("ap_persistent_composite_overlay.img"));
129     if (IsVmManagerQemu(config)) {
130       CF_EXPECT(persistent_ap_disk_builder.BuildOverlayIfNecessary());
131     }
132   }
133 
134   return {};
135 }
136 
137 }  // namespace cuttlefish
138