blob: f5b5f1cf04845fe33a18c3600c916a145911ea69 [file] [log] [blame]
Cole Faust1fa1c6d2024-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
34// Creates the vbmeta partition and the chained vbmeta partitions. Returns the list of module names
35// that the function created. May return nil if the product isn't using avb.
36//
37// AVB is Android Verified Boot: https://source.android.com/docs/security/features/verifiedboot
38// It works by signing all the partitions, but then also including an extra metadata paritition
39// called vbmeta that depends on all the other signed partitions. This creates a requirement
40// that you update all those partitions and the vbmeta partition together, so in order to relax
41// that requirement products can set up "chained" vbmeta partitions, where a chained partition
42// like vbmeta_system might contain the avb metadata for just a few products. In cuttlefish
43// vbmeta_system contains metadata about product, system, and system_ext. Using chained partitions,
44// that group of partitions can be updated independently from the other signed partitions.
45func createVbmetaPartitions(ctx android.LoadHookContext, generatedPartitionTypes []string) []vbmetaModuleInfo {
46 partitionVars := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse
47 // Some products seem to have BuildingVbmetaImage as true even when BoardAvbEnable is false
48 if !partitionVars.BuildingVbmetaImage || !partitionVars.BoardAvbEnable {
49 return nil
50 }
51
52 var result []vbmetaModuleInfo
53
54 var chainedPartitions []filesystem.ChainedPartitionProperties
55 var partitionTypesHandledByChainedPartitions []string
56 for chainedName, props := range partitionVars.ChainedVbmetaPartitions {
57 chainedName = "vbmeta_" + chainedName
58 if len(props.Partitions) == 0 {
59 continue
60 }
61 if len(props.Key) == 0 {
62 ctx.ModuleErrorf("No key found for chained avb partition %s", chainedName)
63 continue
64 }
65 if len(props.Algorithm) == 0 {
66 ctx.ModuleErrorf("No algorithm found for chained avb partition %s", chainedName)
67 continue
68 }
69 if len(props.RollbackIndex) == 0 {
70 ctx.ModuleErrorf("No rollback index found for chained avb partition %s", chainedName)
71 continue
72 }
73 ril, err := strconv.ParseInt(props.RollbackIndexLocation, 10, 32)
74 if err != nil {
75 ctx.ModuleErrorf("Rollback index location must be an int, got %s", props.RollbackIndexLocation)
76 continue
77 }
78 // The default is to use the PlatformSecurityPatch, and a lot of product config files
79 // just set it to the platform security patch, so detect that and don't set the property
80 // in soong.
81 var rollbackIndex *int64
82 if props.RollbackIndex != ctx.Config().PlatformSecurityPatch() {
83 i, err := strconv.ParseInt(props.RollbackIndex, 10, 32)
84 if err != nil {
85 ctx.ModuleErrorf("Rollback index must be an int, got %s", props.RollbackIndex)
86 continue
87 }
88 rollbackIndex = &i
89 }
90
91 var partitionModules []string
92 for _, partition := range props.Partitions {
93 partitionTypesHandledByChainedPartitions = append(partitionTypesHandledByChainedPartitions, partition)
94 if !slices.Contains(generatedPartitionTypes, partition) {
95 // The partition is probably unsupported.
96 continue
97 }
98 partitionModules = append(partitionModules, generatedModuleNameForPartition(ctx.Config(), partition))
99 }
100
101 name := generatedModuleName(ctx.Config(), chainedName)
102 ctx.CreateModuleInDirectory(
103 filesystem.VbmetaFactory,
104 ".", // Create in the root directory for now so its easy to get the key
105 &filesystem.VbmetaProperties{
106 Partition_name: proptools.StringPtr(chainedName),
107 Stem: proptools.StringPtr(chainedName + ".img"),
108 Private_key: proptools.StringPtr(props.Key),
109 Algorithm: &props.Algorithm,
110 Rollback_index: rollbackIndex,
111 Rollback_index_location: &ril,
112 Partitions: proptools.NewSimpleConfigurable(partitionModules),
113 }, &struct {
114 Name *string
115 }{
116 Name: &name,
117 },
118 ).HideFromMake()
119
120 chainedPartitions = append(chainedPartitions, filesystem.ChainedPartitionProperties{
121 Name: &chainedName,
122 Rollback_index_location: &ril,
123 Private_key: &props.Key,
124 })
125
126 result = append(result, vbmetaModuleInfo{
127 moduleName: name,
128 partitionName: chainedName,
129 })
130 }
131
132 vbmetaModuleName := generatedModuleName(ctx.Config(), "vbmeta")
133
134 var algorithm *string
135 if len(partitionVars.BoardAvbAlgorithm) > 0 {
136 algorithm = proptools.StringPtr(partitionVars.BoardAvbAlgorithm)
137 }
138 ril, err := strconv.ParseInt(partitionVars.BoardAvbRollbackIndex, 10, 32)
139 if err != nil {
140 ctx.ModuleErrorf("Rollback index location must be an int, got %s", partitionVars.BoardAvbRollbackIndex)
141 }
142
143 var partitionModules []string
144 for _, partitionType := range generatedPartitionTypes {
145 if slices.Contains(partitionTypesHandledByChainedPartitions, partitionType) {
146 // Already handled by a chained vbmeta partition
147 continue
148 }
149 partitionModules = append(partitionModules, generatedModuleNameForPartition(ctx.Config(), partitionType))
150 }
151
152 ctx.CreateModuleInDirectory(
153 filesystem.VbmetaFactory,
154 ".", // Create in the root directory for now so its easy to get the key
155 &filesystem.VbmetaProperties{
156 Stem: proptools.StringPtr("vbmeta.img"),
157 Algorithm: algorithm,
158 Private_key: proptools.StringPtr(partitionVars.BoardAvbKeyPath),
159 Rollback_index_location: &ril,
160 Chained_partitions: chainedPartitions,
161 Partitions: proptools.NewSimpleConfigurable(partitionModules),
162 }, &struct {
163 Name *string
164 }{
165 Name: &vbmetaModuleName,
166 },
167 ).HideFromMake()
168
169 result = append(result, vbmetaModuleInfo{
170 moduleName: vbmetaModuleName,
171 partitionName: "vbmeta",
172 })
173 return result
174}