mrziwang | 79730d4 | 2024-12-02 22:13:59 -0800 | [diff] [blame] | 1 | // 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 | |
| 15 | package filesystem |
| 16 | |
| 17 | import ( |
| 18 | "fmt" |
| 19 | "path/filepath" |
Cole Faust | 498ffc1 | 2025-01-15 14:19:32 -0800 | [diff] [blame] | 20 | "regexp" |
Cole Faust | 74ee4e0 | 2025-01-16 14:55:35 -0800 | [diff] [blame] | 21 | "slices" |
mrziwang | 79730d4 | 2024-12-02 22:13:59 -0800 | [diff] [blame] | 22 | "strconv" |
| 23 | "strings" |
| 24 | |
| 25 | "android/soong/android" |
Cole Faust | 2bdc5e5 | 2025-01-10 10:29:36 -0800 | [diff] [blame] | 26 | |
mrziwang | 79730d4 | 2024-12-02 22:13:59 -0800 | [diff] [blame] | 27 | "github.com/google/blueprint" |
| 28 | "github.com/google/blueprint/proptools" |
| 29 | ) |
| 30 | |
| 31 | func init() { |
| 32 | android.RegisterModuleType("super_image", SuperImageFactory) |
| 33 | } |
| 34 | |
| 35 | type superImage struct { |
| 36 | android.ModuleBase |
| 37 | |
| 38 | properties SuperImageProperties |
| 39 | partitionProps SuperImagePartitionNameProperties |
| 40 | |
| 41 | installDir android.InstallPath |
| 42 | } |
| 43 | |
| 44 | type SuperImageProperties struct { |
| 45 | // the size of the super partition |
| 46 | Size *int64 |
| 47 | // the block device where metadata for dynamic partitions is stored |
| 48 | Metadata_device *string |
| 49 | // the super partition block device list |
mrziwang | f3c8ddf | 2024-12-05 17:15:11 -0800 | [diff] [blame] | 50 | Block_devices []string |
mrziwang | 79730d4 | 2024-12-02 22:13:59 -0800 | [diff] [blame] | 51 | // whether A/B updater is used |
| 52 | Ab_update *bool |
| 53 | // whether dynamic partitions is enabled on devices that were launched without this support |
| 54 | Retrofit *bool |
mrziwang | 79730d4 | 2024-12-02 22:13:59 -0800 | [diff] [blame] | 55 | // whether the output is a sparse image |
| 56 | Sparse *bool |
| 57 | // information about how partitions within the super partition are grouped together |
| 58 | Partition_groups []PartitionGroupsInfo |
Cole Faust | 74ee4e0 | 2025-01-16 14:55:35 -0800 | [diff] [blame] | 59 | // Name of the system_other partition filesystem module. This module will be installed to |
| 60 | // the "b" slot of the system partition in a/b partition builds. |
| 61 | System_other_partition *string |
mrziwang | 79730d4 | 2024-12-02 22:13:59 -0800 | [diff] [blame] | 62 | // whether dynamic partitions is used |
| 63 | Use_dynamic_partitions *bool |
Cole Faust | 498ffc1 | 2025-01-15 14:19:32 -0800 | [diff] [blame] | 64 | Virtual_ab struct { |
| 65 | // whether virtual A/B seamless update is enabled |
| 66 | Enable *bool |
| 67 | // whether retrofitting virtual A/B seamless update is enabled |
| 68 | Retrofit *bool |
| 69 | // If set, device uses virtual A/B Compression |
| 70 | Compression *bool |
| 71 | // This value controls the compression algorithm used for VABC. |
| 72 | // Valid options are defined in system/core/fs_mgr/libsnapshot/cow_writer.cpp |
| 73 | // e.g. "none", "gz", "brotli" |
| 74 | Compression_method *string |
| 75 | // Specifies maximum bytes to be compressed at once during ota. Options: 4096, 8192, 16384, 32768, 65536, 131072, 262144. |
| 76 | Compression_factor *int64 |
| 77 | // Specifies COW version to be used by update_engine and libsnapshot. If this value is not |
| 78 | // specified we default to COW version 2 in update_engine for backwards compatibility |
| 79 | Cow_version *int64 |
| 80 | } |
Spandan Das | 9da8a2d | 2025-02-28 07:45:30 +0000 | [diff] [blame] | 81 | // Whether the super image will be disted in the update package |
| 82 | Super_image_in_update_package *bool |
Spandan Das | d73441e | 2025-03-10 22:34:25 +0000 | [diff] [blame] | 83 | // Whether a super_empty.img should be created |
| 84 | Create_super_empty *bool |
mrziwang | 79730d4 | 2024-12-02 22:13:59 -0800 | [diff] [blame] | 85 | } |
| 86 | |
| 87 | type PartitionGroupsInfo struct { |
| 88 | Name string |
| 89 | GroupSize string |
| 90 | PartitionList []string |
| 91 | } |
| 92 | |
| 93 | type SuperImagePartitionNameProperties struct { |
| 94 | // Name of the System partition filesystem module |
| 95 | System_partition *string |
| 96 | // Name of the System_ext partition filesystem module |
| 97 | System_ext_partition *string |
| 98 | // Name of the System_dlkm partition filesystem module |
| 99 | System_dlkm_partition *string |
| 100 | // Name of the System_other partition filesystem module |
| 101 | System_other_partition *string |
| 102 | // Name of the Product partition filesystem module |
| 103 | Product_partition *string |
| 104 | // Name of the Vendor partition filesystem module |
| 105 | Vendor_partition *string |
| 106 | // Name of the Vendor_dlkm partition filesystem module |
| 107 | Vendor_dlkm_partition *string |
| 108 | // Name of the Odm partition filesystem module |
| 109 | Odm_partition *string |
| 110 | // Name of the Odm_dlkm partition filesystem module |
| 111 | Odm_dlkm_partition *string |
| 112 | } |
| 113 | |
Cole Faust | 2bdc5e5 | 2025-01-10 10:29:36 -0800 | [diff] [blame] | 114 | type SuperImageInfo struct { |
| 115 | // The built super.img file, which contains the sub-partitions |
| 116 | SuperImage android.Path |
| 117 | |
| 118 | // Mapping from the sub-partition type to its re-exported FileSystemInfo providers from the |
| 119 | // sub-partitions. |
| 120 | SubImageInfo map[string]FilesystemInfo |
Spandan Das | f079f0d | 2025-02-27 13:13:50 +0000 | [diff] [blame] | 121 | |
| 122 | DynamicPartitionsInfo android.Path |
Spandan Das | d73441e | 2025-03-10 22:34:25 +0000 | [diff] [blame] | 123 | |
| 124 | SuperEmptyImage android.Path |
Spandan Das | 8d1d4e0 | 2025-03-18 20:07:51 +0000 | [diff] [blame] | 125 | |
| 126 | AbUpdate bool |
Cole Faust | 2bdc5e5 | 2025-01-10 10:29:36 -0800 | [diff] [blame] | 127 | } |
| 128 | |
| 129 | var SuperImageProvider = blueprint.NewProvider[SuperImageInfo]() |
| 130 | |
mrziwang | 79730d4 | 2024-12-02 22:13:59 -0800 | [diff] [blame] | 131 | func SuperImageFactory() android.Module { |
| 132 | module := &superImage{} |
| 133 | module.AddProperties(&module.properties, &module.partitionProps) |
| 134 | android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon) |
| 135 | return module |
| 136 | } |
| 137 | |
| 138 | type superImageDepTagType struct { |
| 139 | blueprint.BaseDependencyTag |
| 140 | } |
| 141 | |
Cole Faust | 2bdc5e5 | 2025-01-10 10:29:36 -0800 | [diff] [blame] | 142 | var subImageDepTag superImageDepTagType |
mrziwang | 79730d4 | 2024-12-02 22:13:59 -0800 | [diff] [blame] | 143 | |
Cole Faust | 74ee4e0 | 2025-01-16 14:55:35 -0800 | [diff] [blame] | 144 | type systemOtherDepTagType struct { |
| 145 | blueprint.BaseDependencyTag |
| 146 | } |
| 147 | |
| 148 | var systemOtherDepTag systemOtherDepTagType |
| 149 | |
mrziwang | 79730d4 | 2024-12-02 22:13:59 -0800 | [diff] [blame] | 150 | func (s *superImage) DepsMutator(ctx android.BottomUpMutatorContext) { |
| 151 | addDependencyIfDefined := func(dep *string) { |
| 152 | if dep != nil { |
Cole Faust | 2bdc5e5 | 2025-01-10 10:29:36 -0800 | [diff] [blame] | 153 | ctx.AddDependency(ctx.Module(), subImageDepTag, proptools.String(dep)) |
mrziwang | 79730d4 | 2024-12-02 22:13:59 -0800 | [diff] [blame] | 154 | } |
| 155 | } |
| 156 | |
| 157 | addDependencyIfDefined(s.partitionProps.System_partition) |
| 158 | addDependencyIfDefined(s.partitionProps.System_ext_partition) |
| 159 | addDependencyIfDefined(s.partitionProps.System_dlkm_partition) |
| 160 | addDependencyIfDefined(s.partitionProps.System_other_partition) |
| 161 | addDependencyIfDefined(s.partitionProps.Product_partition) |
| 162 | addDependencyIfDefined(s.partitionProps.Vendor_partition) |
| 163 | addDependencyIfDefined(s.partitionProps.Vendor_dlkm_partition) |
| 164 | addDependencyIfDefined(s.partitionProps.Odm_partition) |
| 165 | addDependencyIfDefined(s.partitionProps.Odm_dlkm_partition) |
Cole Faust | 74ee4e0 | 2025-01-16 14:55:35 -0800 | [diff] [blame] | 166 | if s.properties.System_other_partition != nil { |
| 167 | ctx.AddDependency(ctx.Module(), systemOtherDepTag, *s.properties.System_other_partition) |
| 168 | } |
mrziwang | 79730d4 | 2024-12-02 22:13:59 -0800 | [diff] [blame] | 169 | } |
| 170 | |
| 171 | func (s *superImage) GenerateAndroidBuildActions(ctx android.ModuleContext) { |
Spandan Das | d73441e | 2025-03-10 22:34:25 +0000 | [diff] [blame] | 172 | miscInfo, deps, subImageInfos := s.buildMiscInfo(ctx, false) |
mrziwang | 79730d4 | 2024-12-02 22:13:59 -0800 | [diff] [blame] | 173 | builder := android.NewRuleBuilder(pctx, ctx) |
| 174 | output := android.PathForModuleOut(ctx, s.installFileName()) |
| 175 | lpMake := ctx.Config().HostToolPath(ctx, "lpmake") |
| 176 | lpMakeDir := filepath.Dir(lpMake.String()) |
| 177 | deps = append(deps, lpMake) |
| 178 | builder.Command().Textf("PATH=%s:\\$PATH", lpMakeDir). |
| 179 | BuiltTool("build_super_image"). |
| 180 | Text("-v"). |
| 181 | Input(miscInfo). |
| 182 | Implicits(deps). |
| 183 | Output(output) |
| 184 | builder.Build("build_super_image", fmt.Sprintf("Creating super image %s", s.BaseModuleName())) |
Spandan Das | d73441e | 2025-03-10 22:34:25 +0000 | [diff] [blame] | 185 | var superEmptyImage android.WritablePath |
| 186 | if proptools.Bool(s.properties.Create_super_empty) { |
| 187 | superEmptyImageBuilder := android.NewRuleBuilder(pctx, ctx) |
| 188 | superEmptyImage = android.PathForModuleOut(ctx, "super_empty.img") |
| 189 | superEmptyMiscInfo, superEmptyDeps, _ := s.buildMiscInfo(ctx, true) |
| 190 | if superEmptyDeps != nil { |
| 191 | ctx.ModuleErrorf("TODO: Handle additional deps when building super_empty.img") |
| 192 | } |
| 193 | superEmptyImageBuilder.Command().Textf("PATH=%s:\\$PATH", lpMakeDir). |
| 194 | BuiltTool("build_super_image"). |
| 195 | Text("-v"). |
| 196 | Input(superEmptyMiscInfo). |
| 197 | Implicit(lpMake). |
| 198 | Output(superEmptyImage) |
| 199 | superEmptyImageBuilder.Build("build_super_empty_image", fmt.Sprintf("Creating super empty image %s", s.BaseModuleName())) |
| 200 | } |
Cole Faust | 2bdc5e5 | 2025-01-10 10:29:36 -0800 | [diff] [blame] | 201 | android.SetProvider(ctx, SuperImageProvider, SuperImageInfo{ |
Spandan Das | f079f0d | 2025-02-27 13:13:50 +0000 | [diff] [blame] | 202 | SuperImage: output, |
| 203 | SubImageInfo: subImageInfos, |
| 204 | DynamicPartitionsInfo: s.generateDynamicPartitionsInfo(ctx), |
Spandan Das | d73441e | 2025-03-10 22:34:25 +0000 | [diff] [blame] | 205 | SuperEmptyImage: superEmptyImage, |
Spandan Das | 8d1d4e0 | 2025-03-18 20:07:51 +0000 | [diff] [blame] | 206 | AbUpdate: proptools.Bool(s.properties.Ab_update), |
Cole Faust | 2bdc5e5 | 2025-01-10 10:29:36 -0800 | [diff] [blame] | 207 | }) |
mrziwang | 79730d4 | 2024-12-02 22:13:59 -0800 | [diff] [blame] | 208 | ctx.SetOutputFiles([]android.Path{output}, "") |
Cole Faust | 2bdc5e5 | 2025-01-10 10:29:36 -0800 | [diff] [blame] | 209 | ctx.CheckbuildFile(output) |
Wei Li | 7b8455f | 2025-03-05 16:05:51 -0800 | [diff] [blame] | 210 | |
| 211 | buildComplianceMetadata(ctx, subImageDepTag) |
mrziwang | 79730d4 | 2024-12-02 22:13:59 -0800 | [diff] [blame] | 212 | } |
| 213 | |
| 214 | func (s *superImage) installFileName() string { |
Cole Faust | a472a6f | 2025-02-10 16:10:04 -0800 | [diff] [blame] | 215 | return "super.img" |
mrziwang | 79730d4 | 2024-12-02 22:13:59 -0800 | [diff] [blame] | 216 | } |
| 217 | |
Spandan Das | d73441e | 2025-03-10 22:34:25 +0000 | [diff] [blame] | 218 | func (s *superImage) buildMiscInfo(ctx android.ModuleContext, superEmpty bool) (android.Path, android.Paths, map[string]FilesystemInfo) { |
mrziwang | 79730d4 | 2024-12-02 22:13:59 -0800 | [diff] [blame] | 219 | var miscInfoString strings.Builder |
Spandan Das | f079f0d | 2025-02-27 13:13:50 +0000 | [diff] [blame] | 220 | partitionList := s.dumpDynamicPartitionInfo(ctx, &miscInfoString) |
mrziwang | 79730d4 | 2024-12-02 22:13:59 -0800 | [diff] [blame] | 221 | addStr := func(name string, value string) { |
| 222 | miscInfoString.WriteString(name) |
| 223 | miscInfoString.WriteRune('=') |
| 224 | miscInfoString.WriteString(value) |
| 225 | miscInfoString.WriteRune('\n') |
| 226 | } |
Spandan Das | 9284f67 | 2025-03-10 17:29:53 +0000 | [diff] [blame] | 227 | addStr("ab_update", strconv.FormatBool(proptools.Bool(s.properties.Ab_update))) |
Spandan Das | d73441e | 2025-03-10 22:34:25 +0000 | [diff] [blame] | 228 | if superEmpty { |
| 229 | miscInfo := android.PathForModuleOut(ctx, "misc_info_super_empty.txt") |
| 230 | android.WriteFileRule(ctx, miscInfo, miscInfoString.String()) |
| 231 | return miscInfo, nil, nil |
| 232 | } |
mrziwang | 79730d4 | 2024-12-02 22:13:59 -0800 | [diff] [blame] | 233 | |
Cole Faust | 2bdc5e5 | 2025-01-10 10:29:36 -0800 | [diff] [blame] | 234 | subImageInfo := make(map[string]FilesystemInfo) |
| 235 | var deps android.Paths |
| 236 | |
| 237 | missingPartitionErrorMessage := "" |
| 238 | handleSubPartition := func(partitionType string, name *string) { |
| 239 | if proptools.String(name) == "" { |
| 240 | missingPartitionErrorMessage += fmt.Sprintf("%s image listed in partition groups, but its module was not specified. ", partitionType) |
| 241 | return |
mrziwang | 79730d4 | 2024-12-02 22:13:59 -0800 | [diff] [blame] | 242 | } |
Cole Faust | 2bdc5e5 | 2025-01-10 10:29:36 -0800 | [diff] [blame] | 243 | mod := ctx.GetDirectDepWithTag(*name, subImageDepTag) |
| 244 | if mod == nil { |
| 245 | ctx.ModuleErrorf("Could not get dep %q", *name) |
| 246 | return |
| 247 | } |
| 248 | info, ok := android.OtherModuleProvider(ctx, mod, FilesystemProvider) |
| 249 | if !ok { |
| 250 | ctx.ModuleErrorf("Expected dep %q to provide FilesystemInfo", *name) |
| 251 | return |
| 252 | } |
| 253 | addStr(partitionType+"_image", info.Output.String()) |
| 254 | deps = append(deps, info.Output) |
| 255 | if _, ok := subImageInfo[partitionType]; ok { |
| 256 | ctx.ModuleErrorf("Already set subimageInfo for %q", partitionType) |
| 257 | } |
| 258 | subImageInfo[partitionType] = info |
mrziwang | 79730d4 | 2024-12-02 22:13:59 -0800 | [diff] [blame] | 259 | } |
| 260 | |
| 261 | // Build partitionToImagePath, because system partition may need system_other |
| 262 | // partition image path |
| 263 | for _, p := range partitionList { |
mrziwang | 79730d4 | 2024-12-02 22:13:59 -0800 | [diff] [blame] | 264 | switch p { |
| 265 | case "system": |
Cole Faust | 2bdc5e5 | 2025-01-10 10:29:36 -0800 | [diff] [blame] | 266 | handleSubPartition("system", s.partitionProps.System_partition) |
mrziwang | 79730d4 | 2024-12-02 22:13:59 -0800 | [diff] [blame] | 267 | case "system_dlkm": |
Cole Faust | 2bdc5e5 | 2025-01-10 10:29:36 -0800 | [diff] [blame] | 268 | handleSubPartition("system_dlkm", s.partitionProps.System_dlkm_partition) |
mrziwang | 79730d4 | 2024-12-02 22:13:59 -0800 | [diff] [blame] | 269 | case "system_ext": |
Cole Faust | 2bdc5e5 | 2025-01-10 10:29:36 -0800 | [diff] [blame] | 270 | handleSubPartition("system_ext", s.partitionProps.System_ext_partition) |
mrziwang | 79730d4 | 2024-12-02 22:13:59 -0800 | [diff] [blame] | 271 | case "product": |
Cole Faust | 2bdc5e5 | 2025-01-10 10:29:36 -0800 | [diff] [blame] | 272 | handleSubPartition("product", s.partitionProps.Product_partition) |
mrziwang | 79730d4 | 2024-12-02 22:13:59 -0800 | [diff] [blame] | 273 | case "vendor": |
Cole Faust | 2bdc5e5 | 2025-01-10 10:29:36 -0800 | [diff] [blame] | 274 | handleSubPartition("vendor", s.partitionProps.Vendor_partition) |
mrziwang | 79730d4 | 2024-12-02 22:13:59 -0800 | [diff] [blame] | 275 | case "vendor_dlkm": |
Cole Faust | 2bdc5e5 | 2025-01-10 10:29:36 -0800 | [diff] [blame] | 276 | handleSubPartition("vendor_dlkm", s.partitionProps.Vendor_dlkm_partition) |
mrziwang | 79730d4 | 2024-12-02 22:13:59 -0800 | [diff] [blame] | 277 | case "odm": |
Cole Faust | 2bdc5e5 | 2025-01-10 10:29:36 -0800 | [diff] [blame] | 278 | handleSubPartition("odm", s.partitionProps.Odm_partition) |
mrziwang | 79730d4 | 2024-12-02 22:13:59 -0800 | [diff] [blame] | 279 | case "odm_dlkm": |
Cole Faust | 2bdc5e5 | 2025-01-10 10:29:36 -0800 | [diff] [blame] | 280 | handleSubPartition("odm_dlkm", s.partitionProps.Odm_dlkm_partition) |
mrziwang | 79730d4 | 2024-12-02 22:13:59 -0800 | [diff] [blame] | 281 | default: |
Cole Faust | 2bdc5e5 | 2025-01-10 10:29:36 -0800 | [diff] [blame] | 282 | ctx.ModuleErrorf("partition %q is not a super image supported partition", p) |
mrziwang | 79730d4 | 2024-12-02 22:13:59 -0800 | [diff] [blame] | 283 | } |
| 284 | } |
| 285 | |
Cole Faust | 74ee4e0 | 2025-01-16 14:55:35 -0800 | [diff] [blame] | 286 | if s.properties.System_other_partition != nil { |
| 287 | if !slices.Contains(partitionList, "system") { |
| 288 | ctx.PropertyErrorf("system_other_partition", "Must have a system partition to use a system_other partition") |
| 289 | } |
| 290 | systemOther := ctx.GetDirectDepProxyWithTag(*s.properties.System_other_partition, systemOtherDepTag) |
| 291 | systemOtherFiles := android.OutputFilesForModule(ctx, systemOther, "") |
| 292 | if len(systemOtherFiles) != 1 { |
| 293 | ctx.PropertyErrorf("system_other_partition", "Expected 1 output file from module %q", *&s.properties.System_other_partition) |
| 294 | } else { |
Spandan Das | 7a42d1c | 2025-02-12 01:32:21 +0000 | [diff] [blame] | 295 | handleSubPartition("system_other", s.partitionProps.System_other_partition) |
Cole Faust | 74ee4e0 | 2025-01-16 14:55:35 -0800 | [diff] [blame] | 296 | } |
| 297 | } |
| 298 | |
Cole Faust | 2bdc5e5 | 2025-01-10 10:29:36 -0800 | [diff] [blame] | 299 | // Delay the error message until execution time because on aosp-main-future-without-vendor, |
| 300 | // BUILDING_VENDOR_IMAGE is false so we don't get the vendor image, but it's still listed in |
| 301 | // BOARD_GOOGLE_DYNAMIC_PARTITIONS_PARTITION_LIST. |
| 302 | missingPartitionErrorMessageFile := android.PathForModuleOut(ctx, "missing_partition_error.txt") |
| 303 | if missingPartitionErrorMessage != "" { |
| 304 | ctx.Build(pctx, android.BuildParams{ |
| 305 | Rule: android.ErrorRule, |
| 306 | Output: missingPartitionErrorMessageFile, |
| 307 | Args: map[string]string{ |
| 308 | "error": missingPartitionErrorMessage, |
| 309 | }, |
| 310 | }) |
| 311 | } else { |
| 312 | ctx.Build(pctx, android.BuildParams{ |
| 313 | Rule: android.Touch, |
| 314 | Output: missingPartitionErrorMessageFile, |
| 315 | }) |
Naresh Kumar Podishetty (xWF) | 4173c5b | 2025-01-09 20:20:32 -0800 | [diff] [blame] | 316 | } |
| 317 | |
mrziwang | 79730d4 | 2024-12-02 22:13:59 -0800 | [diff] [blame] | 318 | miscInfo := android.PathForModuleOut(ctx, "misc_info.txt") |
Cole Faust | 2bdc5e5 | 2025-01-10 10:29:36 -0800 | [diff] [blame] | 319 | android.WriteFileRule(ctx, miscInfo, miscInfoString.String(), missingPartitionErrorMessageFile) |
| 320 | return miscInfo, deps, subImageInfo |
mrziwang | 79730d4 | 2024-12-02 22:13:59 -0800 | [diff] [blame] | 321 | } |
Spandan Das | f079f0d | 2025-02-27 13:13:50 +0000 | [diff] [blame] | 322 | |
| 323 | func (s *superImage) dumpDynamicPartitionInfo(ctx android.ModuleContext, sb *strings.Builder) []string { |
| 324 | addStr := func(name string, value string) { |
| 325 | sb.WriteString(name) |
| 326 | sb.WriteRune('=') |
| 327 | sb.WriteString(value) |
| 328 | sb.WriteRune('\n') |
| 329 | } |
| 330 | |
Spandan Das | f079f0d | 2025-02-27 13:13:50 +0000 | [diff] [blame] | 331 | addStr("use_dynamic_partitions", strconv.FormatBool(proptools.Bool(s.properties.Use_dynamic_partitions))) |
| 332 | if proptools.Bool(s.properties.Retrofit) { |
| 333 | addStr("dynamic_partition_retrofit", "true") |
| 334 | } |
| 335 | addStr("lpmake", "lpmake") |
Spandan Das | 0ff1dcd | 2025-03-11 18:21:40 +0000 | [diff] [blame] | 336 | addStr("build_super_partition", "true") |
| 337 | if proptools.Bool(s.properties.Create_super_empty) { |
| 338 | addStr("build_super_empty_partition", "true") |
| 339 | } |
Spandan Das | f079f0d | 2025-02-27 13:13:50 +0000 | [diff] [blame] | 340 | addStr("super_metadata_device", proptools.String(s.properties.Metadata_device)) |
| 341 | if len(s.properties.Block_devices) > 0 { |
| 342 | addStr("super_block_devices", strings.Join(s.properties.Block_devices, " ")) |
| 343 | } |
Spandan Das | f079f0d | 2025-02-27 13:13:50 +0000 | [diff] [blame] | 344 | // TODO: In make, there's more complicated logic than just this surrounding super_*_device_size |
| 345 | addStr("super_super_device_size", strconv.Itoa(proptools.Int(s.properties.Size))) |
| 346 | var groups, partitionList []string |
| 347 | for _, groupInfo := range s.properties.Partition_groups { |
| 348 | groups = append(groups, groupInfo.Name) |
| 349 | partitionList = append(partitionList, groupInfo.PartitionList...) |
Spandan Das | f079f0d | 2025-02-27 13:13:50 +0000 | [diff] [blame] | 350 | } |
Spandan Das | 0ff1dcd | 2025-03-11 18:21:40 +0000 | [diff] [blame] | 351 | addStr("dynamic_partition_list", strings.Join(android.SortedUniqueStrings(partitionList), " ")) |
| 352 | addStr("super_partition_groups", strings.Join(groups, " ")) |
Spandan Das | f079f0d | 2025-02-27 13:13:50 +0000 | [diff] [blame] | 353 | initialPartitionListLen := len(partitionList) |
| 354 | partitionList = android.SortedUniqueStrings(partitionList) |
| 355 | if len(partitionList) != initialPartitionListLen { |
| 356 | ctx.ModuleErrorf("Duplicate partitions found in the partition_groups property") |
| 357 | } |
Spandan Das | 0ff1dcd | 2025-03-11 18:21:40 +0000 | [diff] [blame] | 358 | // Add Partition group info after adding `super_partition_groups` and `dynamic_partition_list` |
| 359 | for _, groupInfo := range s.properties.Partition_groups { |
| 360 | addStr("super_"+groupInfo.Name+"_group_size", groupInfo.GroupSize) |
| 361 | addStr("super_"+groupInfo.Name+"_partition_list", strings.Join(groupInfo.PartitionList, " ")) |
| 362 | } |
| 363 | |
| 364 | if proptools.Bool(s.properties.Super_image_in_update_package) { |
| 365 | addStr("super_image_in_update_package", "true") |
| 366 | } |
| 367 | addStr("super_partition_size", strconv.Itoa(proptools.Int(s.properties.Size))) |
Spandan Das | f079f0d | 2025-02-27 13:13:50 +0000 | [diff] [blame] | 368 | |
Spandan Das | f079f0d | 2025-02-27 13:13:50 +0000 | [diff] [blame] | 369 | if proptools.Bool(s.properties.Virtual_ab.Enable) { |
| 370 | addStr("virtual_ab", "true") |
| 371 | if proptools.Bool(s.properties.Virtual_ab.Retrofit) { |
| 372 | addStr("virtual_ab_retrofit", "true") |
| 373 | } |
| 374 | addStr("virtual_ab_compression", strconv.FormatBool(proptools.Bool(s.properties.Virtual_ab.Compression))) |
| 375 | if s.properties.Virtual_ab.Compression_method != nil { |
| 376 | matched, _ := regexp.MatchString("^[a-zA-Z0-9_-]+$", *s.properties.Virtual_ab.Compression_method) |
| 377 | if !matched { |
| 378 | ctx.PropertyErrorf("virtual_ab.compression_method", "compression_method cannot have special characters") |
| 379 | } |
| 380 | addStr("virtual_ab_compression_method", *s.properties.Virtual_ab.Compression_method) |
| 381 | } |
Spandan Das | f079f0d | 2025-02-27 13:13:50 +0000 | [diff] [blame] | 382 | if s.properties.Virtual_ab.Cow_version != nil { |
| 383 | addStr("virtual_ab_cow_version", strconv.FormatInt(*s.properties.Virtual_ab.Cow_version, 10)) |
| 384 | } |
Spandan Das | 0ff1dcd | 2025-03-11 18:21:40 +0000 | [diff] [blame] | 385 | if s.properties.Virtual_ab.Compression_factor != nil { |
| 386 | addStr("virtual_ab_compression_factor", strconv.FormatInt(*s.properties.Virtual_ab.Compression_factor, 10)) |
| 387 | } |
Spandan Das | f079f0d | 2025-02-27 13:13:50 +0000 | [diff] [blame] | 388 | |
| 389 | } else { |
| 390 | if s.properties.Virtual_ab.Retrofit != nil { |
| 391 | ctx.PropertyErrorf("virtual_ab.retrofit", "This property cannot be set when virtual_ab is disabled") |
| 392 | } |
| 393 | if s.properties.Virtual_ab.Compression != nil { |
| 394 | ctx.PropertyErrorf("virtual_ab.compression", "This property cannot be set when virtual_ab is disabled") |
| 395 | } |
| 396 | if s.properties.Virtual_ab.Compression_method != nil { |
| 397 | ctx.PropertyErrorf("virtual_ab.compression_method", "This property cannot be set when virtual_ab is disabled") |
| 398 | } |
| 399 | if s.properties.Virtual_ab.Compression_factor != nil { |
| 400 | ctx.PropertyErrorf("virtual_ab.compression_factor", "This property cannot be set when virtual_ab is disabled") |
| 401 | } |
| 402 | } |
| 403 | |
| 404 | return partitionList |
| 405 | } |
| 406 | |
| 407 | func (s *superImage) generateDynamicPartitionsInfo(ctx android.ModuleContext) android.Path { |
| 408 | var contents strings.Builder |
| 409 | s.dumpDynamicPartitionInfo(ctx, &contents) |
| 410 | dynamicPartitionsInfo := android.PathForModuleOut(ctx, "dynamic_partitions_info.txt") |
Spandan Das | 0ff1dcd | 2025-03-11 18:21:40 +0000 | [diff] [blame] | 411 | android.WriteFileRuleVerbatim(ctx, dynamicPartitionsInfo, contents.String()) |
Spandan Das | f079f0d | 2025-02-27 13:13:50 +0000 | [diff] [blame] | 412 | return dynamicPartitionsInfo |
| 413 | } |