blob: be738ea8606b37e58205e9c669853911d95e7bb1 [file] [log] [blame]
Cole Faust3552eb62024-11-06 18:07:26 -08001// Copyright (C) 2024 The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package fsgen
16
17import (
18 "android/soong/android"
19 "android/soong/filesystem"
20 "slices"
21 "strconv"
22
23 "github.com/google/blueprint/proptools"
24)
25
26type vbmetaModuleInfo struct {
27 // The name of the generated vbmeta module
28 moduleName string
29 // The name of the module that avb understands. This is the name passed to --chain_partition,
30 // and also the basename of the output file. (the output file is called partitionName + ".img")
31 partitionName string
32}
33
Jihoon Kang2f0d1932025-01-17 19:22:44 +000034// https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/Makefile;l=4849;drc=62e20f0d218f60bae563b4ee742d88cca1fc1901
35var avbPartitions = []string{
36 "boot",
37 "init_boot",
38 "vendor_boot",
39 "vendor_kernel_boot",
40 "system",
41 "vendor",
42 "product",
43 "system_ext",
44 "odm",
45 "vendor_dlkm",
46 "odm_dlkm",
47 "system_dlkm",
48 "dtbo",
49 "pvmfw",
50 "recovery",
51 "vbmeta_system",
52 "vbmeta_vendor",
53}
54
Cole Faust3552eb62024-11-06 18:07:26 -080055// Creates the vbmeta partition and the chained vbmeta partitions. Returns the list of module names
56// that the function created. May return nil if the product isn't using avb.
57//
58// AVB is Android Verified Boot: https://source.android.com/docs/security/features/verifiedboot
59// It works by signing all the partitions, but then also including an extra metadata paritition
60// called vbmeta that depends on all the other signed partitions. This creates a requirement
61// that you update all those partitions and the vbmeta partition together, so in order to relax
62// that requirement products can set up "chained" vbmeta partitions, where a chained partition
63// like vbmeta_system might contain the avb metadata for just a few products. In cuttlefish
64// vbmeta_system contains metadata about product, system, and system_ext. Using chained partitions,
65// that group of partitions can be updated independently from the other signed partitions.
Jihoon Kang2f0d1932025-01-17 19:22:44 +000066func (f *filesystemCreator) createVbmetaPartitions(ctx android.LoadHookContext, generatedPartitionTypes []string) []vbmetaModuleInfo {
Cole Faust3552eb62024-11-06 18:07:26 -080067 partitionVars := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse
68 // Some products seem to have BuildingVbmetaImage as true even when BoardAvbEnable is false
69 if !partitionVars.BuildingVbmetaImage || !partitionVars.BoardAvbEnable {
70 return nil
71 }
72
73 var result []vbmetaModuleInfo
74
Jihoon Kang2f0d1932025-01-17 19:22:44 +000075 // https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/Makefile;l=4593;drc=62e20f0d218f60bae563b4ee742d88cca1fc1901
76 var internalAvbPartitionsInChainedVbmetaImages []string
77 var chainedPartitionTypes []string
Cole Faust481a7252024-11-13 11:46:22 -080078 for _, chainedName := range android.SortedKeys(partitionVars.ChainedVbmetaPartitions) {
79 props := partitionVars.ChainedVbmetaPartitions[chainedName]
Cole Faust3552eb62024-11-06 18:07:26 -080080 chainedName = "vbmeta_" + chainedName
81 if len(props.Partitions) == 0 {
82 continue
83 }
Jihoon Kang2f0d1932025-01-17 19:22:44 +000084 internalAvbPartitionsInChainedVbmetaImages = append(internalAvbPartitionsInChainedVbmetaImages, props.Partitions...)
Cole Faust3552eb62024-11-06 18:07:26 -080085 if len(props.Key) == 0 {
86 ctx.ModuleErrorf("No key found for chained avb partition %q", chainedName)
87 continue
88 }
89 if len(props.Algorithm) == 0 {
90 ctx.ModuleErrorf("No algorithm found for chained avb partition %q", chainedName)
91 continue
92 }
93 if len(props.RollbackIndex) == 0 {
94 ctx.ModuleErrorf("No rollback index found for chained avb partition %q", chainedName)
95 continue
96 }
97 ril, err := strconv.ParseInt(props.RollbackIndexLocation, 10, 32)
98 if err != nil {
99 ctx.ModuleErrorf("Rollback index location must be an int, got %q", props.RollbackIndexLocation)
100 continue
101 }
102 // The default is to use the PlatformSecurityPatch, and a lot of product config files
103 // just set it to the platform security patch, so detect that and don't set the property
104 // in soong.
105 var rollbackIndex *int64
106 if props.RollbackIndex != ctx.Config().PlatformSecurityPatch() {
107 i, err := strconv.ParseInt(props.RollbackIndex, 10, 32)
108 if err != nil {
109 ctx.ModuleErrorf("Rollback index must be an int, got %q", props.RollbackIndex)
110 continue
111 }
112 rollbackIndex = &i
113 }
114
115 var partitionModules []string
116 for _, partition := range props.Partitions {
Cole Faust3552eb62024-11-06 18:07:26 -0800117 if !slices.Contains(generatedPartitionTypes, partition) {
118 // The partition is probably unsupported.
119 continue
120 }
121 partitionModules = append(partitionModules, generatedModuleNameForPartition(ctx.Config(), partition))
122 }
123
Jihoon Kang2f0d1932025-01-17 19:22:44 +0000124 name := generatedModuleNameForPartition(ctx.Config(), chainedName)
Cole Faust3552eb62024-11-06 18:07:26 -0800125 ctx.CreateModuleInDirectory(
126 filesystem.VbmetaFactory,
127 ".", // Create in the root directory for now so its easy to get the key
128 &filesystem.VbmetaProperties{
129 Partition_name: proptools.StringPtr(chainedName),
130 Stem: proptools.StringPtr(chainedName + ".img"),
131 Private_key: proptools.StringPtr(props.Key),
132 Algorithm: &props.Algorithm,
133 Rollback_index: rollbackIndex,
134 Rollback_index_location: &ril,
135 Partitions: proptools.NewSimpleConfigurable(partitionModules),
136 }, &struct {
137 Name *string
138 }{
139 Name: &name,
140 },
141 ).HideFromMake()
142
Cole Faust3552eb62024-11-06 18:07:26 -0800143 result = append(result, vbmetaModuleInfo{
144 moduleName: name,
145 partitionName: chainedName,
146 })
Jihoon Kang2f0d1932025-01-17 19:22:44 +0000147
148 chainedPartitionTypes = append(chainedPartitionTypes, chainedName)
Cole Faust3552eb62024-11-06 18:07:26 -0800149 }
150
Jihoon Kang2f0d1932025-01-17 19:22:44 +0000151 vbmetaModuleName := generatedModuleNameForPartition(ctx.Config(), "vbmeta")
Cole Faust3552eb62024-11-06 18:07:26 -0800152
153 var algorithm *string
154 var ri *int64
155 var key *string
156 if len(partitionVars.BoardAvbKeyPath) == 0 {
157 // Match make's defaults: https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/Makefile;l=4568;drc=5b55f926830963c02ab1d2d91e46442f04ba3af0
158 key = proptools.StringPtr("external/avb/test/data/testkey_rsa4096.pem")
159 algorithm = proptools.StringPtr("SHA256_RSA4096")
160 } else {
161 key = proptools.StringPtr(partitionVars.BoardAvbKeyPath)
162 algorithm = proptools.StringPtr(partitionVars.BoardAvbAlgorithm)
163 }
164 if len(partitionVars.BoardAvbRollbackIndex) > 0 {
165 parsedRi, err := strconv.ParseInt(partitionVars.BoardAvbRollbackIndex, 10, 32)
166 if err != nil {
167 ctx.ModuleErrorf("Rollback index location must be an int, got %q", partitionVars.BoardAvbRollbackIndex)
168 }
169 ri = &parsedRi
170 }
171
Jihoon Kang2f0d1932025-01-17 19:22:44 +0000172 // --chain_partition argument is only set for partitions that set
173 // `BOARD_AVB_<partition name>_KEY_PATH` value and is not "recovery"
174 // https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/Makefile;l=4823;drc=62e20f0d218f60bae563b4ee742d88cca1fc1901
175 includeAsChainedPartitionInVbmeta := func(partition string) bool {
176 val, ok := partitionVars.PartitionQualifiedVariables[partition]
177 return ok && len(val.BoardAvbKeyPath) > 0 && partition != "recovery"
178 }
179
180 // --include_descriptors_from_image is passed if both conditions are met:
181 // - `BOARD_AVB_<partition name>_KEY_PATH` value is not set
182 // - not included in INTERNAL_AVB_PARTITIONS_IN_CHAINED_VBMETA_IMAGES
183 // for partitions that set INSTALLED_<partition name>IMAGE_TARGET
184 // https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/Makefile;l=4827;drc=62e20f0d218f60bae563b4ee742d88cca1fc1901
185 includeAsIncludedPartitionInVbmeta := func(partition string) bool {
186 if android.InList(partition, internalAvbPartitionsInChainedVbmetaImages) {
187 // Already handled by chained vbmeta partitions
188 return false
189 }
190 partitionQualifiedVars := partitionVars.PartitionQualifiedVariables[partition]
191
192 // The return logic in the switch cases below are identical to
193 // ifdef INSTALLED_<partition name>IMAGE_TARGET
194 switch partition {
195 case "boot":
196 return partitionQualifiedVars.BuildingImage || partitionQualifiedVars.PrebuiltImage || partitionVars.BoardUsesRecoveryAsBoot
197 case "vendor_kernel_boot", "dtbo":
198 return partitionQualifiedVars.PrebuiltImage
199 case "system":
200 return partitionQualifiedVars.BuildingImage
201 case "init_boot", "vendor_boot", "vendor", "product", "system_ext", "odm", "vendor_dlkm", "odm_dlkm", "system_dlkm":
202 return partitionQualifiedVars.BuildingImage || partitionQualifiedVars.PrebuiltImage
203 // TODO: Import BOARD_USES_PVMFWIMAGE
204 // ifeq ($(BOARD_USES_PVMFWIMAGE),true)
205 // case "pvmfw":
206 case "recovery":
207 // ifdef INSTALLED_RECOVERYIMAGE_TARGET
208 return !ctx.DeviceConfig().BoardUsesRecoveryAsBoot() && !ctx.DeviceConfig().BoardMoveRecoveryResourcesToVendorBoot()
209 // Technically these partitions are determined based on len(BOARD_AVB_VBMETA_SYSTEM) and
210 // len(BOARD_AVB_VBMETA_VENDOR) but if these are non empty these partitions are
211 // already included in the chained partitions.
212 case "vbmeta_system", "vbmeta_vendor":
213 return false
214 default:
215 return false
216 }
217 }
218
219 var chainedPartitionModules []string
220 var includePartitionModules []string
221 allGeneratedPartitionTypes := append(generatedPartitionTypes,
222 chainedPartitionTypes...,
223 )
224 if len(f.properties.Boot_image) > 0 {
225 allGeneratedPartitionTypes = append(allGeneratedPartitionTypes, "boot")
226 }
227 if len(f.properties.Init_boot_image) > 0 {
228 allGeneratedPartitionTypes = append(allGeneratedPartitionTypes, "init_boot")
229 }
230 if len(f.properties.Vendor_boot_image) > 0 {
231 allGeneratedPartitionTypes = append(allGeneratedPartitionTypes, "vendor_boot")
232 }
233
234 // https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/Makefile;l=4919;drc=62e20f0d218f60bae563b4ee742d88cca1fc1901
235 for _, partitionType := range android.SortedUniqueStrings(append(avbPartitions, chainedPartitionTypes...)) {
236 if !android.InList(partitionType, allGeneratedPartitionTypes) {
237 // Skip if the partition is not auto generated
Cole Faust3552eb62024-11-06 18:07:26 -0800238 continue
239 }
Jihoon Kang2f0d1932025-01-17 19:22:44 +0000240 if includeAsChainedPartitionInVbmeta(partitionType) {
241 chainedPartitionModules = append(chainedPartitionModules, generatedModuleNameForPartition(ctx.Config(), partitionType))
242 } else if includeAsIncludedPartitionInVbmeta(partitionType) {
243 includePartitionModules = append(includePartitionModules, generatedModuleNameForPartition(ctx.Config(), partitionType))
Cole Faust76a6e952024-11-07 16:56:45 -0800244 }
Cole Faust3552eb62024-11-06 18:07:26 -0800245 }
246
247 ctx.CreateModuleInDirectory(
248 filesystem.VbmetaFactory,
249 ".", // Create in the root directory for now so its easy to get the key
250 &filesystem.VbmetaProperties{
251 Stem: proptools.StringPtr("vbmeta.img"),
252 Algorithm: algorithm,
253 Private_key: key,
254 Rollback_index: ri,
Jihoon Kang2f0d1932025-01-17 19:22:44 +0000255 Chained_partitions: chainedPartitionModules,
256 Partitions: proptools.NewSimpleConfigurable(includePartitionModules),
Cole Faust11fda332025-01-14 16:47:19 -0800257 Partition_name: proptools.StringPtr("vbmeta"),
Cole Faust3552eb62024-11-06 18:07:26 -0800258 }, &struct {
259 Name *string
260 }{
261 Name: &vbmetaModuleName,
262 },
263 ).HideFromMake()
264
265 result = append(result, vbmetaModuleInfo{
266 moduleName: vbmetaModuleName,
267 partitionName: "vbmeta",
268 })
269 return result
270}