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 15package fsgen 16 17import ( 18 "crypto/sha256" 19 "fmt" 20 "path/filepath" 21 "slices" 22 "strconv" 23 "strings" 24 25 "android/soong/android" 26 "android/soong/filesystem" 27 "android/soong/kernel" 28 29 "github.com/google/blueprint" 30 "github.com/google/blueprint/parser" 31 "github.com/google/blueprint/proptools" 32) 33 34var pctx = android.NewPackageContext("android/soong/fsgen") 35 36func init() { 37 registerBuildComponents(android.InitRegistrationContext) 38} 39 40func registerBuildComponents(ctx android.RegistrationContext) { 41 ctx.RegisterModuleType("soong_filesystem_creator", filesystemCreatorFactory) 42 ctx.PreDepsMutators(RegisterCollectFileSystemDepsMutators) 43} 44 45type filesystemCreatorProps struct { 46 Generated_partition_types []string `blueprint:"mutated"` 47 Unsupported_partition_types []string `blueprint:"mutated"` 48 49 Vbmeta_module_names []string `blueprint:"mutated"` 50 Vbmeta_partition_names []string `blueprint:"mutated"` 51 52 Boot_image string `blueprint:"mutated" android:"path_device_first"` 53 Vendor_boot_image string `blueprint:"mutated" android:"path_device_first"` 54 Init_boot_image string `blueprint:"mutated" android:"path_device_first"` 55 Super_image string `blueprint:"mutated" android:"path_device_first"` 56} 57 58type filesystemCreator struct { 59 android.ModuleBase 60 61 properties filesystemCreatorProps 62} 63 64func filesystemCreatorFactory() android.Module { 65 module := &filesystemCreator{} 66 67 android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon) 68 module.AddProperties(&module.properties) 69 android.AddLoadHook(module, func(ctx android.LoadHookContext) { 70 generatedPrebuiltEtcModuleNames := createPrebuiltEtcModules(ctx) 71 avbpubkeyGenerated := createAvbpubkeyModule(ctx) 72 createFsGenState(ctx, generatedPrebuiltEtcModuleNames, avbpubkeyGenerated) 73 module.createAvbKeyFilegroups(ctx) 74 module.createMiscFilegroups(ctx) 75 module.createInternalModules(ctx) 76 }) 77 78 return module 79} 80 81func generatedPartitions(ctx android.LoadHookContext) []string { 82 partitionVars := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse 83 generatedPartitions := []string{"system"} 84 if ctx.DeviceConfig().SystemExtPath() == "system_ext" { 85 generatedPartitions = append(generatedPartitions, "system_ext") 86 } 87 if ctx.DeviceConfig().BuildingVendorImage() && ctx.DeviceConfig().VendorPath() == "vendor" { 88 generatedPartitions = append(generatedPartitions, "vendor") 89 } 90 if ctx.DeviceConfig().BuildingProductImage() && ctx.DeviceConfig().ProductPath() == "product" { 91 generatedPartitions = append(generatedPartitions, "product") 92 } 93 if ctx.DeviceConfig().BuildingOdmImage() && ctx.DeviceConfig().OdmPath() == "odm" { 94 generatedPartitions = append(generatedPartitions, "odm") 95 } 96 if ctx.DeviceConfig().BuildingUserdataImage() && ctx.DeviceConfig().UserdataPath() == "data" { 97 generatedPartitions = append(generatedPartitions, "userdata") 98 } 99 if partitionVars.BuildingSystemDlkmImage { 100 generatedPartitions = append(generatedPartitions, "system_dlkm") 101 } 102 if partitionVars.BuildingVendorDlkmImage { 103 generatedPartitions = append(generatedPartitions, "vendor_dlkm") 104 } 105 if partitionVars.BuildingOdmDlkmImage { 106 generatedPartitions = append(generatedPartitions, "odm_dlkm") 107 } 108 if partitionVars.BuildingRamdiskImage { 109 generatedPartitions = append(generatedPartitions, "ramdisk") 110 } 111 if buildingVendorBootImage(partitionVars) { 112 generatedPartitions = append(generatedPartitions, "vendor_ramdisk") 113 } 114 if ctx.DeviceConfig().BuildingRecoveryImage() && ctx.DeviceConfig().RecoveryPath() == "recovery" { 115 generatedPartitions = append(generatedPartitions, "recovery") 116 } 117 return generatedPartitions 118} 119 120func (f *filesystemCreator) createInternalModules(ctx android.LoadHookContext) { 121 soongGeneratedPartitions := generatedPartitions(ctx) 122 finalSoongGeneratedPartitions := make([]string, 0, len(soongGeneratedPartitions)) 123 for _, partitionType := range soongGeneratedPartitions { 124 if f.createPartition(ctx, partitionType) { 125 f.properties.Generated_partition_types = append(f.properties.Generated_partition_types, partitionType) 126 finalSoongGeneratedPartitions = append(finalSoongGeneratedPartitions, partitionType) 127 } else { 128 f.properties.Unsupported_partition_types = append(f.properties.Unsupported_partition_types, partitionType) 129 } 130 } 131 132 partitionVars := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse 133 dtbImg := createDtbImgFilegroup(ctx) 134 135 if buildingBootImage(partitionVars) { 136 if createBootImage(ctx, dtbImg) { 137 f.properties.Boot_image = ":" + generatedModuleNameForPartition(ctx.Config(), "boot") 138 } else { 139 f.properties.Unsupported_partition_types = append(f.properties.Unsupported_partition_types, "boot") 140 } 141 } 142 if buildingVendorBootImage(partitionVars) { 143 if createVendorBootImage(ctx, dtbImg) { 144 f.properties.Vendor_boot_image = ":" + generatedModuleNameForPartition(ctx.Config(), "vendor_boot") 145 } else { 146 f.properties.Unsupported_partition_types = append(f.properties.Unsupported_partition_types, "vendor_boot") 147 } 148 } 149 if buildingInitBootImage(partitionVars) { 150 if createInitBootImage(ctx) { 151 f.properties.Init_boot_image = ":" + generatedModuleNameForPartition(ctx.Config(), "init_boot") 152 } else { 153 f.properties.Unsupported_partition_types = append(f.properties.Unsupported_partition_types, "init_boot") 154 } 155 } 156 157 for _, x := range createVbmetaPartitions(ctx, finalSoongGeneratedPartitions) { 158 f.properties.Vbmeta_module_names = append(f.properties.Vbmeta_module_names, x.moduleName) 159 f.properties.Vbmeta_partition_names = append(f.properties.Vbmeta_partition_names, x.partitionName) 160 } 161 162 if buildingSuperImage(partitionVars) { 163 createSuperImage(ctx, finalSoongGeneratedPartitions, partitionVars) 164 f.properties.Super_image = ":" + generatedModuleName(ctx.Config(), "super") 165 } 166 167 ctx.Config().Get(fsGenStateOnceKey).(*FsGenState).soongGeneratedPartitions = finalSoongGeneratedPartitions 168 f.createDeviceModule(ctx, finalSoongGeneratedPartitions, f.properties.Vbmeta_module_names) 169} 170 171func generatedModuleName(cfg android.Config, suffix string) string { 172 prefix := "soong" 173 if cfg.HasDeviceProduct() { 174 prefix = cfg.DeviceProduct() 175 } 176 return fmt.Sprintf("%s_generated_%s", prefix, suffix) 177} 178 179func generatedModuleNameForPartition(cfg android.Config, partitionType string) string { 180 return generatedModuleName(cfg, fmt.Sprintf("%s_image", partitionType)) 181} 182 183func (f *filesystemCreator) createDeviceModule( 184 ctx android.LoadHookContext, 185 generatedPartitionTypes []string, 186 vbmetaPartitions []string, 187) { 188 baseProps := &struct { 189 Name *string 190 }{ 191 Name: proptools.StringPtr(generatedModuleName(ctx.Config(), "device")), 192 } 193 194 // Currently, only the system and system_ext partition module is created. 195 partitionProps := &filesystem.PartitionNameProperties{} 196 if android.InList("system", generatedPartitionTypes) { 197 partitionProps.System_partition_name = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "system")) 198 } 199 if android.InList("system_ext", generatedPartitionTypes) { 200 partitionProps.System_ext_partition_name = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "system_ext")) 201 } 202 if android.InList("vendor", generatedPartitionTypes) { 203 partitionProps.Vendor_partition_name = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "vendor")) 204 } 205 if android.InList("product", generatedPartitionTypes) { 206 partitionProps.Product_partition_name = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "product")) 207 } 208 if android.InList("odm", generatedPartitionTypes) { 209 partitionProps.Odm_partition_name = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "odm")) 210 } 211 if android.InList("userdata", f.properties.Generated_partition_types) { 212 partitionProps.Userdata_partition_name = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "userdata")) 213 } 214 partitionProps.Vbmeta_partitions = vbmetaPartitions 215 216 ctx.CreateModule(filesystem.AndroidDeviceFactory, baseProps, partitionProps) 217} 218 219func partitionSpecificFsProps(ctx android.EarlyModuleContext, fsProps *filesystem.FilesystemProperties, partitionVars android.PartitionVariables, partitionType string) { 220 switch partitionType { 221 case "system": 222 fsProps.Build_logtags = proptools.BoolPtr(true) 223 // https://source.corp.google.com/h/googleplex-android/platform/build//639d79f5012a6542ab1f733b0697db45761ab0f3:core/packaging/flags.mk;l=21;drc=5ba8a8b77507f93aa48cc61c5ba3f31a4d0cbf37;bpv=1;bpt=0 224 fsProps.Gen_aconfig_flags_pb = proptools.BoolPtr(true) 225 // Identical to that of the aosp_shared_system_image 226 if partitionVars.ProductFsverityGenerateMetadata { 227 fsProps.Fsverity.Inputs = []string{ 228 "etc/boot-image.prof", 229 "etc/dirty-image-objects", 230 "etc/preloaded-classes", 231 "etc/classpaths/*.pb", 232 "framework/*", 233 "framework/*/*", // framework/{arch} 234 "framework/oat/*/*", // framework/oat/{arch} 235 } 236 fsProps.Fsverity.Libs = []string{":framework-res{.export-package.apk}"} 237 } 238 // Most of the symlinks and directories listed here originate from create_root_structure.mk, 239 // but the handwritten generic system image also recreates them: 240 // https://cs.android.com/android/platform/superproject/main/+/main:build/make/target/product/generic/Android.bp;l=33;drc=db08311f1b6ef6cb0a4fbcc6263b89849360ce04 241 // TODO(b/377734331): only generate the symlinks if the relevant partitions exist 242 fsProps.Symlinks = []filesystem.SymlinkDefinition{ 243 filesystem.SymlinkDefinition{ 244 Target: proptools.StringPtr("/system/bin/init"), 245 Name: proptools.StringPtr("init"), 246 }, 247 filesystem.SymlinkDefinition{ 248 Target: proptools.StringPtr("/system/etc"), 249 Name: proptools.StringPtr("etc"), 250 }, 251 filesystem.SymlinkDefinition{ 252 Target: proptools.StringPtr("/system/bin"), 253 Name: proptools.StringPtr("bin"), 254 }, 255 filesystem.SymlinkDefinition{ 256 Target: proptools.StringPtr("/data/user_de/0/com.android.shell/files/bugreports"), 257 Name: proptools.StringPtr("bugreports"), 258 }, 259 filesystem.SymlinkDefinition{ 260 Target: proptools.StringPtr("/sys/kernel/debug"), 261 Name: proptools.StringPtr("d"), 262 }, 263 filesystem.SymlinkDefinition{ 264 Target: proptools.StringPtr("/storage/self/primary"), 265 Name: proptools.StringPtr("sdcard"), 266 }, 267 filesystem.SymlinkDefinition{ 268 Target: proptools.StringPtr("/product/etc/security/adb_keys"), 269 Name: proptools.StringPtr("adb_keys"), 270 }, 271 filesystem.SymlinkDefinition{ 272 Target: proptools.StringPtr("/vendor/odm/app"), 273 Name: proptools.StringPtr("odm/app"), 274 }, 275 filesystem.SymlinkDefinition{ 276 Target: proptools.StringPtr("/vendor/odm/bin"), 277 Name: proptools.StringPtr("odm/bin"), 278 }, 279 filesystem.SymlinkDefinition{ 280 Target: proptools.StringPtr("/vendor/odm/etc"), 281 Name: proptools.StringPtr("odm/etc"), 282 }, 283 filesystem.SymlinkDefinition{ 284 Target: proptools.StringPtr("/vendor/odm/firmware"), 285 Name: proptools.StringPtr("odm/firmware"), 286 }, 287 filesystem.SymlinkDefinition{ 288 Target: proptools.StringPtr("/vendor/odm/framework"), 289 Name: proptools.StringPtr("odm/framework"), 290 }, 291 filesystem.SymlinkDefinition{ 292 Target: proptools.StringPtr("/vendor/odm/lib"), 293 Name: proptools.StringPtr("odm/lib"), 294 }, 295 filesystem.SymlinkDefinition{ 296 Target: proptools.StringPtr("/vendor/odm/lib64"), 297 Name: proptools.StringPtr("odm/lib64"), 298 }, 299 filesystem.SymlinkDefinition{ 300 Target: proptools.StringPtr("/vendor/odm/overlay"), 301 Name: proptools.StringPtr("odm/overlay"), 302 }, 303 filesystem.SymlinkDefinition{ 304 Target: proptools.StringPtr("/vendor/odm/priv-app"), 305 Name: proptools.StringPtr("odm/priv-app"), 306 }, 307 filesystem.SymlinkDefinition{ 308 Target: proptools.StringPtr("/vendor/odm/usr"), 309 Name: proptools.StringPtr("odm/usr"), 310 }, 311 filesystem.SymlinkDefinition{ 312 Target: proptools.StringPtr("/product"), 313 Name: proptools.StringPtr("system/product"), 314 }, 315 filesystem.SymlinkDefinition{ 316 Target: proptools.StringPtr("/system_ext"), 317 Name: proptools.StringPtr("system/system_ext"), 318 }, 319 filesystem.SymlinkDefinition{ 320 Target: proptools.StringPtr("/vendor"), 321 Name: proptools.StringPtr("system/vendor"), 322 }, 323 filesystem.SymlinkDefinition{ 324 Target: proptools.StringPtr("/system_dlkm/lib/modules"), 325 Name: proptools.StringPtr("system/lib/modules"), 326 }, 327 filesystem.SymlinkDefinition{ 328 Target: proptools.StringPtr("/data/cache"), 329 Name: proptools.StringPtr("cache"), 330 }, 331 // For Treble Generic System Image (GSI), system-as-root GSI needs to work on 332 // both devices with and without /odm_dlkm partition. Those symlinks are for 333 // devices without /odm_dlkm partition. For devices with /odm_dlkm 334 // partition, mount odm_dlkm.img under /odm_dlkm will hide those symlinks. 335 // Note that /odm_dlkm/lib is omitted because odm DLKMs should be accessed 336 // via /odm/lib/modules directly. All of this also applies to the vendor_dlkm symlink 337 filesystem.SymlinkDefinition{ 338 Target: proptools.StringPtr("/odm/odm_dlkm/etc"), 339 Name: proptools.StringPtr("odm_dlkm/etc"), 340 }, 341 filesystem.SymlinkDefinition{ 342 Target: proptools.StringPtr("/vendor/vendor_dlkm/etc"), 343 Name: proptools.StringPtr("vendor_dlkm/etc"), 344 }, 345 } 346 fsProps.Base_dir = proptools.StringPtr("system") 347 fsProps.Dirs = proptools.NewSimpleConfigurable([]string{ 348 // From generic_rootdirs in build/make/target/product/generic/Android.bp 349 "acct", 350 "apex", 351 "bootstrap-apex", 352 "config", 353 "data", 354 "data_mirror", 355 "debug_ramdisk", 356 "dev", 357 "linkerconfig", 358 "metadata", 359 "mnt", 360 "odm", 361 "odm_dlkm", 362 "oem", 363 "postinstall", 364 "proc", 365 "second_stage_resources", 366 "storage", 367 "sys", 368 "system", 369 "system_dlkm", 370 "tmp", 371 "vendor", 372 "vendor_dlkm", 373 374 // from android_rootdirs in build/make/target/product/generic/Android.bp 375 "system_ext", 376 "product", 377 }) 378 case "system_ext": 379 if partitionVars.ProductFsverityGenerateMetadata { 380 fsProps.Fsverity.Inputs = []string{ 381 "framework/*", 382 "framework/*/*", // framework/{arch} 383 "framework/oat/*/*", // framework/oat/{arch} 384 } 385 fsProps.Fsverity.Libs = []string{":framework-res{.export-package.apk}"} 386 } 387 case "product": 388 fsProps.Gen_aconfig_flags_pb = proptools.BoolPtr(true) 389 fsProps.Android_filesystem_deps.System = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "system")) 390 if ctx.DeviceConfig().SystemExtPath() == "system_ext" { 391 fsProps.Android_filesystem_deps.System_ext = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "system_ext")) 392 } 393 case "vendor": 394 fsProps.Gen_aconfig_flags_pb = proptools.BoolPtr(true) 395 fsProps.Symlinks = []filesystem.SymlinkDefinition{ 396 filesystem.SymlinkDefinition{ 397 Target: proptools.StringPtr("/odm"), 398 Name: proptools.StringPtr("odm"), 399 }, 400 filesystem.SymlinkDefinition{ 401 Target: proptools.StringPtr("/vendor_dlkm/lib/modules"), 402 Name: proptools.StringPtr("lib/modules"), 403 }, 404 } 405 fsProps.Android_filesystem_deps.System = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "system")) 406 if ctx.DeviceConfig().SystemExtPath() == "system_ext" { 407 fsProps.Android_filesystem_deps.System_ext = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "system_ext")) 408 } 409 case "odm": 410 fsProps.Symlinks = []filesystem.SymlinkDefinition{ 411 filesystem.SymlinkDefinition{ 412 Target: proptools.StringPtr("/odm_dlkm/lib/modules"), 413 Name: proptools.StringPtr("lib/modules"), 414 }, 415 } 416 case "userdata": 417 fsProps.Base_dir = proptools.StringPtr("data") 418 case "ramdisk": 419 // Following the logic in https://cs.android.com/android/platform/superproject/main/+/c3c5063df32748a8806ce5da5dd0db158eab9ad9:build/make/core/Makefile;l=1307 420 fsProps.Dirs = android.NewSimpleConfigurable([]string{ 421 "debug_ramdisk", 422 "dev", 423 "metadata", 424 "mnt", 425 "proc", 426 "second_stage_resources", 427 "sys", 428 }) 429 if partitionVars.BoardUsesGenericKernelImage { 430 fsProps.Dirs.AppendSimpleValue([]string{ 431 "first_stage_ramdisk/debug_ramdisk", 432 "first_stage_ramdisk/dev", 433 "first_stage_ramdisk/metadata", 434 "first_stage_ramdisk/mnt", 435 "first_stage_ramdisk/proc", 436 "first_stage_ramdisk/second_stage_resources", 437 "first_stage_ramdisk/sys", 438 }) 439 } 440 case "recovery": 441 // Following https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/Makefile;l=2826;drc=ad7cfb56010cb22c3aa0e70cf71c804352553526 442 fsProps.Dirs = android.NewSimpleConfigurable([]string{ 443 "sdcard", 444 "tmp", 445 }) 446 fsProps.Symlinks = []filesystem.SymlinkDefinition{ 447 { 448 Target: proptools.StringPtr("/system/bin/init"), 449 Name: proptools.StringPtr("init"), 450 }, 451 { 452 Target: proptools.StringPtr("prop.default"), 453 Name: proptools.StringPtr("default.prop"), 454 }, 455 } 456 fsProps.Base_dir = proptools.StringPtr("recovery") 457 } 458} 459 460var ( 461 dlkmPartitions = []string{ 462 "system_dlkm", 463 "vendor_dlkm", 464 "odm_dlkm", 465 } 466) 467 468// Creates a soong module to build the given partition. Returns false if we can't support building 469// it. 470func (f *filesystemCreator) createPartition(ctx android.LoadHookContext, partitionType string) bool { 471 baseProps := generateBaseProps(proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), partitionType))) 472 473 fsProps, supported := generateFsProps(ctx, partitionType) 474 if !supported { 475 return false 476 } 477 478 if partitionType == "vendor" || partitionType == "product" || partitionType == "system" { 479 fsProps.Linker_config.Gen_linker_config = proptools.BoolPtr(true) 480 if partitionType != "system" { 481 fsProps.Linker_config.Linker_config_srcs = f.createLinkerConfigSourceFilegroups(ctx, partitionType) 482 } 483 } 484 485 if android.InList(partitionType, append(dlkmPartitions, "vendor_ramdisk")) { 486 f.createPrebuiltKernelModules(ctx, partitionType) 487 } 488 489 var module android.Module 490 if partitionType == "system" { 491 module = ctx.CreateModule(filesystem.SystemImageFactory, baseProps, fsProps) 492 } else { 493 // Explicitly set the partition. 494 fsProps.Partition_type = proptools.StringPtr(partitionType) 495 module = ctx.CreateModule(filesystem.FilesystemFactory, baseProps, fsProps) 496 } 497 module.HideFromMake() 498 if partitionType == "vendor" { 499 f.createVendorBuildProp(ctx) 500 } 501 return true 502} 503 504// Creates filegroups for the files specified in BOARD_(partition_)AVB_KEY_PATH 505func (f *filesystemCreator) createAvbKeyFilegroups(ctx android.LoadHookContext) { 506 partitionVars := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse 507 var files []string 508 509 if len(partitionVars.BoardAvbKeyPath) > 0 { 510 files = append(files, partitionVars.BoardAvbKeyPath) 511 } 512 for _, partition := range android.SortedKeys(partitionVars.PartitionQualifiedVariables) { 513 specificPartitionVars := partitionVars.PartitionQualifiedVariables[partition] 514 if len(specificPartitionVars.BoardAvbKeyPath) > 0 { 515 files = append(files, specificPartitionVars.BoardAvbKeyPath) 516 } 517 } 518 519 fsGenState := ctx.Config().Get(fsGenStateOnceKey).(*FsGenState) 520 for _, file := range files { 521 if _, ok := fsGenState.avbKeyFilegroups[file]; ok { 522 continue 523 } 524 if file == "external/avb/test/data/testkey_rsa4096.pem" { 525 // There already exists a checked-in filegroup for this commonly-used key, just use that 526 fsGenState.avbKeyFilegroups[file] = "avb_testkey_rsa4096" 527 continue 528 } 529 dir := filepath.Dir(file) 530 base := filepath.Base(file) 531 name := fmt.Sprintf("avb_key_%x", strings.ReplaceAll(file, "/", "_")) 532 ctx.CreateModuleInDirectory( 533 android.FileGroupFactory, 534 dir, 535 &struct { 536 Name *string 537 Srcs []string 538 Visibility []string 539 }{ 540 Name: proptools.StringPtr(name), 541 Srcs: []string{base}, 542 Visibility: []string{"//visibility:public"}, 543 }, 544 ) 545 fsGenState.avbKeyFilegroups[file] = name 546 } 547} 548 549// Creates filegroups for miscellaneous other files 550func (f *filesystemCreator) createMiscFilegroups(ctx android.LoadHookContext) { 551 partitionVars := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse 552 553 if partitionVars.BoardErofsCompressorHints != "" { 554 dir := filepath.Dir(partitionVars.BoardErofsCompressorHints) 555 base := filepath.Base(partitionVars.BoardErofsCompressorHints) 556 ctx.CreateModuleInDirectory( 557 android.FileGroupFactory, 558 dir, 559 &struct { 560 Name *string 561 Srcs []string 562 Visibility []string 563 }{ 564 Name: proptools.StringPtr("soong_generated_board_erofs_compress_hints_filegroup"), 565 Srcs: []string{base}, 566 Visibility: []string{"//visibility:public"}, 567 }, 568 ) 569 } 570} 571 572// createPrebuiltKernelModules creates `prebuilt_kernel_modules`. These modules will be added to deps of the 573// autogenerated *_dlkm filsystem modules. Each _dlkm partition should have a single prebuilt_kernel_modules dependency. 574// This ensures that the depmod artifacts (modules.* installed in /lib/modules/) are generated with a complete view. 575func (f *filesystemCreator) createPrebuiltKernelModules(ctx android.LoadHookContext, partitionType string) { 576 fsGenState := ctx.Config().Get(fsGenStateOnceKey).(*FsGenState) 577 name := generatedModuleName(ctx.Config(), fmt.Sprintf("%s-kernel-modules", partitionType)) 578 props := &struct { 579 Name *string 580 Srcs []string 581 System_deps []string 582 System_dlkm_specific *bool 583 Vendor_dlkm_specific *bool 584 Odm_dlkm_specific *bool 585 Vendor_ramdisk *bool 586 Load_by_default *bool 587 Blocklist_file *string 588 Options_file *string 589 }{ 590 Name: proptools.StringPtr(name), 591 } 592 switch partitionType { 593 case "system_dlkm": 594 props.Srcs = android.ExistentPathsForSources(ctx, ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.SystemKernelModules).Strings() 595 props.System_dlkm_specific = proptools.BoolPtr(true) 596 if len(ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.SystemKernelLoadModules) == 0 { 597 // Create empty modules.load file for system 598 // https://source.corp.google.com/h/googleplex-android/platform/build/+/ef55daac9954896161b26db4f3ef1781b5a5694c:core/Makefile;l=695-700;drc=549fe2a5162548bd8b47867d35f907eb22332023;bpv=1;bpt=0 599 props.Load_by_default = proptools.BoolPtr(false) 600 } 601 if blocklistFile := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.SystemKernelBlocklistFile; blocklistFile != "" { 602 props.Blocklist_file = proptools.StringPtr(blocklistFile) 603 } 604 case "vendor_dlkm": 605 props.Srcs = android.ExistentPathsForSources(ctx, ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.VendorKernelModules).Strings() 606 if len(ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.SystemKernelModules) > 0 { 607 props.System_deps = []string{":" + generatedModuleName(ctx.Config(), "system_dlkm-kernel-modules") + "{.modules}"} 608 } 609 props.Vendor_dlkm_specific = proptools.BoolPtr(true) 610 if blocklistFile := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.VendorKernelBlocklistFile; blocklistFile != "" { 611 props.Blocklist_file = proptools.StringPtr(blocklistFile) 612 } 613 case "odm_dlkm": 614 props.Srcs = android.ExistentPathsForSources(ctx, ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.OdmKernelModules).Strings() 615 props.Odm_dlkm_specific = proptools.BoolPtr(true) 616 if blocklistFile := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.OdmKernelBlocklistFile; blocklistFile != "" { 617 props.Blocklist_file = proptools.StringPtr(blocklistFile) 618 } 619 case "vendor_ramdisk": 620 props.Srcs = android.ExistentPathsForSources(ctx, ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.VendorRamdiskKernelModules).Strings() 621 props.Vendor_ramdisk = proptools.BoolPtr(true) 622 if blocklistFile := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.VendorRamdiskKernelBlocklistFile; blocklistFile != "" { 623 props.Blocklist_file = proptools.StringPtr(blocklistFile) 624 } 625 if optionsFile := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.VendorRamdiskKernelOptionsFile; optionsFile != "" { 626 props.Options_file = proptools.StringPtr(optionsFile) 627 } 628 629 default: 630 ctx.ModuleErrorf("DLKM is not supported for %s\n", partitionType) 631 } 632 633 if len(props.Srcs) == 0 { 634 return // do not generate `prebuilt_kernel_modules` if there are no sources 635 } 636 637 kernelModule := ctx.CreateModuleInDirectory( 638 kernel.PrebuiltKernelModulesFactory, 639 ".", // create in root directory for now 640 props, 641 ) 642 kernelModule.HideFromMake() 643 // Add to deps 644 (*fsGenState.fsDeps[partitionType])[name] = defaultDepCandidateProps(ctx.Config()) 645} 646 647// Create a build_prop and android_info module. This will be used to create /vendor/build.prop 648func (f *filesystemCreator) createVendorBuildProp(ctx android.LoadHookContext) { 649 // Create a android_info for vendor 650 // The board info files might be in a directory outside the root soong namespace, so create 651 // the module in "." 652 partitionVars := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse 653 androidInfoProps := &struct { 654 Name *string 655 Board_info_files []string 656 Bootloader_board_name *string 657 }{ 658 Name: proptools.StringPtr(generatedModuleName(ctx.Config(), "android-info.prop")), 659 Board_info_files: partitionVars.BoardInfoFiles, 660 } 661 if len(androidInfoProps.Board_info_files) == 0 { 662 androidInfoProps.Bootloader_board_name = proptools.StringPtr(partitionVars.BootLoaderBoardName) 663 } 664 androidInfoProp := ctx.CreateModuleInDirectory( 665 android.AndroidInfoFactory, 666 ".", 667 androidInfoProps, 668 ) 669 androidInfoProp.HideFromMake() 670 // Create a build prop for vendor 671 vendorBuildProps := &struct { 672 Name *string 673 Vendor *bool 674 Stem *string 675 Product_config *string 676 Android_info *string 677 }{ 678 Name: proptools.StringPtr(generatedModuleName(ctx.Config(), "vendor-build.prop")), 679 Vendor: proptools.BoolPtr(true), 680 Stem: proptools.StringPtr("build.prop"), 681 Product_config: proptools.StringPtr(":product_config"), 682 Android_info: proptools.StringPtr(":" + androidInfoProp.Name()), 683 } 684 vendorBuildProp := ctx.CreateModule( 685 android.BuildPropFactory, 686 vendorBuildProps, 687 ) 688 vendorBuildProp.HideFromMake() 689} 690 691// createLinkerConfigSourceFilegroups creates filegroup modules to generate linker.config.pb for the following partitions 692// 1. vendor: Using PRODUCT_VENDOR_LINKER_CONFIG_FRAGMENTS (space separated file list) 693// 1. product: Using PRODUCT_PRODUCT_LINKER_CONFIG_FRAGMENTS (space separated file list) 694// It creates a filegroup for each file in the fragment list 695// The filegroup modules are then added to `linker_config_srcs` of the autogenerated vendor `android_filesystem`. 696func (f *filesystemCreator) createLinkerConfigSourceFilegroups(ctx android.LoadHookContext, partitionType string) []string { 697 ret := []string{} 698 partitionVars := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse 699 var linkerConfigSrcs []string 700 if partitionType == "vendor" { 701 linkerConfigSrcs = android.FirstUniqueStrings(partitionVars.VendorLinkerConfigSrcs) 702 } else if partitionType == "product" { 703 linkerConfigSrcs = android.FirstUniqueStrings(partitionVars.ProductLinkerConfigSrcs) 704 } else { 705 ctx.ModuleErrorf("linker.config.pb is only supported for vendor and product partitions. For system partition, use `android_system_image`") 706 } 707 708 if len(linkerConfigSrcs) > 0 { 709 // Create a filegroup, and add `:<filegroup_name>` to ret. 710 for index, linkerConfigSrc := range linkerConfigSrcs { 711 dir := filepath.Dir(linkerConfigSrc) 712 base := filepath.Base(linkerConfigSrc) 713 fgName := generatedModuleName(ctx.Config(), fmt.Sprintf("%s-linker-config-src%s", partitionType, strconv.Itoa(index))) 714 srcs := []string{base} 715 fgProps := &struct { 716 Name *string 717 Srcs proptools.Configurable[[]string] 718 }{ 719 Name: proptools.StringPtr(fgName), 720 Srcs: proptools.NewSimpleConfigurable(srcs), 721 } 722 ctx.CreateModuleInDirectory( 723 android.FileGroupFactory, 724 dir, 725 fgProps, 726 ) 727 ret = append(ret, ":"+fgName) 728 } 729 } 730 return ret 731} 732 733type filesystemBaseProperty struct { 734 Name *string 735 Compile_multilib *string 736 Visibility []string 737} 738 739func generateBaseProps(namePtr *string) *filesystemBaseProperty { 740 return &filesystemBaseProperty{ 741 Name: namePtr, 742 Compile_multilib: proptools.StringPtr("both"), 743 // The vbmeta modules are currently in the root directory and depend on the partitions 744 Visibility: []string{"//.", "//build/soong:__subpackages__"}, 745 } 746} 747 748func generateFsProps(ctx android.EarlyModuleContext, partitionType string) (*filesystem.FilesystemProperties, bool) { 749 fsProps := &filesystem.FilesystemProperties{} 750 751 partitionVars := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse 752 var avbInfo avbInfo 753 var fsType string 754 if strings.Contains(partitionType, "ramdisk") { 755 fsType = "compressed_cpio" 756 } else { 757 specificPartitionVars := partitionVars.PartitionQualifiedVariables[partitionType] 758 fsType = specificPartitionVars.BoardFileSystemType 759 avbInfo = getAvbInfo(ctx.Config(), partitionType) 760 if fsType == "" { 761 fsType = "ext4" //default 762 } 763 } 764 765 fsProps.Type = proptools.StringPtr(fsType) 766 if filesystem.GetFsTypeFromString(ctx, *fsProps.Type).IsUnknown() { 767 // Currently the android_filesystem module type only supports a handful of FS types like ext4, erofs 768 return nil, false 769 } 770 771 if *fsProps.Type == "erofs" { 772 if partitionVars.BoardErofsCompressor != "" { 773 fsProps.Erofs.Compressor = proptools.StringPtr(partitionVars.BoardErofsCompressor) 774 } 775 if partitionVars.BoardErofsCompressorHints != "" { 776 fsProps.Erofs.Compress_hints = proptools.StringPtr(":soong_generated_board_erofs_compress_hints_filegroup") 777 } 778 } 779 780 // Don't build this module on checkbuilds, the soong-built partitions are still in-progress 781 // and sometimes don't build. 782 fsProps.Unchecked_module = proptools.BoolPtr(true) 783 784 // BOARD_AVB_ENABLE 785 fsProps.Use_avb = avbInfo.avbEnable 786 // BOARD_AVB_KEY_PATH 787 fsProps.Avb_private_key = avbInfo.avbkeyFilegroup 788 // BOARD_AVB_ALGORITHM 789 fsProps.Avb_algorithm = avbInfo.avbAlgorithm 790 // BOARD_AVB_SYSTEM_ROLLBACK_INDEX 791 fsProps.Rollback_index = avbInfo.avbRollbackIndex 792 fsProps.Avb_hash_algorithm = avbInfo.avbHashAlgorithm 793 794 fsProps.Partition_name = proptools.StringPtr(partitionType) 795 796 switch partitionType { 797 // The partitions that support file_contexts came from here: 798 // https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/Makefile;l=2270;drc=ad7cfb56010cb22c3aa0e70cf71c804352553526 799 case "system", "userdata", "cache", "vendor", "product", "system_ext", "odm", "vendor_dlkm", "odm_dlkm", "system_dlkm", "oem": 800 fsProps.Precompiled_file_contexts = proptools.StringPtr(":file_contexts_bin_gen") 801 } 802 803 fsProps.Is_auto_generated = proptools.BoolPtr(true) 804 805 partitionSpecificFsProps(ctx, fsProps, partitionVars, partitionType) 806 807 return fsProps, true 808} 809 810type avbInfo struct { 811 avbEnable *bool 812 avbKeyPath *string 813 avbkeyFilegroup *string 814 avbAlgorithm *string 815 avbRollbackIndex *int64 816 avbMode *string 817 avbHashAlgorithm *string 818} 819 820func getAvbInfo(config android.Config, partitionType string) avbInfo { 821 partitionVars := config.ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse 822 specificPartitionVars := partitionVars.PartitionQualifiedVariables[partitionType] 823 var result avbInfo 824 boardAvbEnable := partitionVars.BoardAvbEnable 825 if boardAvbEnable { 826 result.avbEnable = proptools.BoolPtr(true) 827 // There are "global" and "specific" copies of a lot of these variables. Sometimes they 828 // choose the specific and then fall back to the global one if it's not set, other times 829 // the global one actually only applies to the vbmeta partition. 830 if partitionType == "vbmeta" { 831 if partitionVars.BoardAvbKeyPath != "" { 832 result.avbKeyPath = proptools.StringPtr(partitionVars.BoardAvbKeyPath) 833 } 834 if partitionVars.BoardAvbRollbackIndex != "" { 835 parsed, err := strconv.ParseInt(partitionVars.BoardAvbRollbackIndex, 10, 64) 836 if err != nil { 837 panic(fmt.Sprintf("Rollback index must be an int, got %s", partitionVars.BoardAvbRollbackIndex)) 838 } 839 result.avbRollbackIndex = &parsed 840 } 841 } 842 if specificPartitionVars.BoardAvbKeyPath != "" { 843 result.avbKeyPath = proptools.StringPtr(specificPartitionVars.BoardAvbKeyPath) 844 } 845 if specificPartitionVars.BoardAvbAlgorithm != "" { 846 result.avbAlgorithm = proptools.StringPtr(specificPartitionVars.BoardAvbAlgorithm) 847 } else if partitionVars.BoardAvbAlgorithm != "" { 848 result.avbAlgorithm = proptools.StringPtr(partitionVars.BoardAvbAlgorithm) 849 } 850 if specificPartitionVars.BoardAvbRollbackIndex != "" { 851 parsed, err := strconv.ParseInt(specificPartitionVars.BoardAvbRollbackIndex, 10, 64) 852 if err != nil { 853 panic(fmt.Sprintf("Rollback index must be an int, got %s", specificPartitionVars.BoardAvbRollbackIndex)) 854 } 855 result.avbRollbackIndex = &parsed 856 } 857 if specificPartitionVars.BoardAvbRollbackIndex != "" { 858 parsed, err := strconv.ParseInt(specificPartitionVars.BoardAvbRollbackIndex, 10, 64) 859 if err != nil { 860 panic(fmt.Sprintf("Rollback index must be an int, got %s", specificPartitionVars.BoardAvbRollbackIndex)) 861 } 862 result.avbRollbackIndex = &parsed 863 } 864 865 // Make allows you to pass arbitrary arguments to avbtool via this variable, but in practice 866 // it's only used for --hash_algorithm. The soong module has a dedicated property for the 867 // hashtree algorithm, and doesn't allow custom arguments, so just extract the hashtree 868 // algorithm out of the arbitrary arguments. 869 addHashtreeFooterArgs := strings.Split(specificPartitionVars.BoardAvbAddHashtreeFooterArgs, " ") 870 if i := slices.Index(addHashtreeFooterArgs, "--hash_algorithm"); i >= 0 { 871 result.avbHashAlgorithm = &addHashtreeFooterArgs[i+1] 872 } 873 874 result.avbMode = proptools.StringPtr("make_legacy") 875 } 876 if result.avbKeyPath != nil { 877 fsGenState := config.Get(fsGenStateOnceKey).(*FsGenState) 878 filegroup := fsGenState.avbKeyFilegroups[*result.avbKeyPath] 879 result.avbkeyFilegroup = proptools.StringPtr(":" + filegroup) 880 } 881 return result 882} 883 884func (f *filesystemCreator) createFileListDiffTest(ctx android.ModuleContext, partitionType string) android.Path { 885 partitionModuleName := generatedModuleNameForPartition(ctx.Config(), partitionType) 886 systemImage := ctx.GetDirectDepWithTag(partitionModuleName, generatedFilesystemDepTag) 887 filesystemInfo, ok := android.OtherModuleProvider(ctx, systemImage, filesystem.FilesystemProvider) 888 if !ok { 889 ctx.ModuleErrorf("Expected module %s to provide FileysystemInfo", partitionModuleName) 890 } 891 makeFileList := android.PathForArbitraryOutput(ctx, fmt.Sprintf("target/product/%s/obj/PACKAGING/%s_intermediates/file_list.txt", ctx.Config().DeviceName(), partitionType)) 892 diffTestResultFile := android.PathForModuleOut(ctx, fmt.Sprintf("diff_test_%s.txt", partitionModuleName)) 893 894 builder := android.NewRuleBuilder(pctx, ctx) 895 builder.Command().BuiltTool("file_list_diff"). 896 Input(makeFileList). 897 Input(filesystemInfo.FileListFile). 898 Text(partitionModuleName) 899 builder.Command().Text("touch").Output(diffTestResultFile) 900 builder.Build(partitionModuleName+" diff test", partitionModuleName+" diff test") 901 return diffTestResultFile 902} 903 904func createFailingCommand(ctx android.ModuleContext, message string) android.Path { 905 hasher := sha256.New() 906 hasher.Write([]byte(message)) 907 filename := fmt.Sprintf("failing_command_%x.txt", hasher.Sum(nil)) 908 file := android.PathForModuleOut(ctx, filename) 909 builder := android.NewRuleBuilder(pctx, ctx) 910 builder.Command().Textf("echo %s", proptools.NinjaAndShellEscape(message)) 911 builder.Command().Text("exit 1 #").Output(file) 912 builder.Build("failing command "+filename, "failing command "+filename) 913 return file 914} 915 916func createVbmetaDiff(ctx android.ModuleContext, vbmetaModuleName string, vbmetaPartitionName string) android.Path { 917 vbmetaModule := ctx.GetDirectDepWithTag(vbmetaModuleName, generatedVbmetaPartitionDepTag) 918 outputFilesProvider, ok := android.OtherModuleProvider(ctx, vbmetaModule, android.OutputFilesProvider) 919 if !ok { 920 ctx.ModuleErrorf("Expected module %s to provide OutputFiles", vbmetaModule) 921 } 922 if len(outputFilesProvider.DefaultOutputFiles) != 1 { 923 ctx.ModuleErrorf("Expected 1 output file from module %s", vbmetaModule) 924 } 925 soongVbMetaFile := outputFilesProvider.DefaultOutputFiles[0] 926 makeVbmetaFile := android.PathForArbitraryOutput(ctx, fmt.Sprintf("target/product/%s/%s.img", ctx.Config().DeviceName(), vbmetaPartitionName)) 927 928 diffTestResultFile := android.PathForModuleOut(ctx, fmt.Sprintf("diff_test_%s.txt", vbmetaModuleName)) 929 createDiffTest(ctx, diffTestResultFile, soongVbMetaFile, makeVbmetaFile) 930 return diffTestResultFile 931} 932 933func createDiffTest(ctx android.ModuleContext, diffTestResultFile android.WritablePath, file1 android.Path, file2 android.Path) { 934 builder := android.NewRuleBuilder(pctx, ctx) 935 builder.Command().Text("diff"). 936 Input(file1). 937 Input(file2) 938 builder.Command().Text("touch").Output(diffTestResultFile) 939 builder.Build("diff test "+diffTestResultFile.String(), "diff test") 940} 941 942type systemImageDepTagType struct { 943 blueprint.BaseDependencyTag 944} 945 946var generatedFilesystemDepTag systemImageDepTagType 947var generatedVbmetaPartitionDepTag systemImageDepTagType 948 949func (f *filesystemCreator) DepsMutator(ctx android.BottomUpMutatorContext) { 950 for _, partitionType := range f.properties.Generated_partition_types { 951 ctx.AddDependency(ctx.Module(), generatedFilesystemDepTag, generatedModuleNameForPartition(ctx.Config(), partitionType)) 952 } 953 for _, vbmetaModule := range f.properties.Vbmeta_module_names { 954 ctx.AddDependency(ctx.Module(), generatedVbmetaPartitionDepTag, vbmetaModule) 955 } 956} 957 958func (f *filesystemCreator) GenerateAndroidBuildActions(ctx android.ModuleContext) { 959 if ctx.ModuleDir() != "build/soong/fsgen" { 960 ctx.ModuleErrorf("There can only be one soong_filesystem_creator in build/soong/fsgen") 961 } 962 f.HideFromMake() 963 964 var content strings.Builder 965 generatedBp := android.PathForModuleOut(ctx, "soong_generated_product_config.bp") 966 for _, partition := range ctx.Config().Get(fsGenStateOnceKey).(*FsGenState).soongGeneratedPartitions { 967 content.WriteString(generateBpContent(ctx, partition)) 968 content.WriteString("\n") 969 } 970 android.WriteFileRule(ctx, generatedBp, content.String()) 971 972 ctx.Phony("product_config_to_bp", generatedBp) 973 974 var diffTestFiles []android.Path 975 for _, partitionType := range f.properties.Generated_partition_types { 976 diffTestFile := f.createFileListDiffTest(ctx, partitionType) 977 diffTestFiles = append(diffTestFiles, diffTestFile) 978 ctx.Phony(fmt.Sprintf("soong_generated_%s_filesystem_test", partitionType), diffTestFile) 979 } 980 for _, partitionType := range f.properties.Unsupported_partition_types { 981 diffTestFile := createFailingCommand(ctx, fmt.Sprintf("Couldn't build %s partition", partitionType)) 982 diffTestFiles = append(diffTestFiles, diffTestFile) 983 ctx.Phony(fmt.Sprintf("soong_generated_%s_filesystem_test", partitionType), diffTestFile) 984 } 985 for i, vbmetaModule := range f.properties.Vbmeta_module_names { 986 diffTestFile := createVbmetaDiff(ctx, vbmetaModule, f.properties.Vbmeta_partition_names[i]) 987 diffTestFiles = append(diffTestFiles, diffTestFile) 988 ctx.Phony(fmt.Sprintf("soong_generated_%s_filesystem_test", f.properties.Vbmeta_partition_names[i]), diffTestFile) 989 } 990 if f.properties.Boot_image != "" { 991 diffTestFile := android.PathForModuleOut(ctx, "boot_diff_test.txt") 992 soongBootImg := android.PathForModuleSrc(ctx, f.properties.Boot_image) 993 makeBootImage := android.PathForArbitraryOutput(ctx, fmt.Sprintf("target/product/%s/boot.img", ctx.Config().DeviceName())) 994 createDiffTest(ctx, diffTestFile, soongBootImg, makeBootImage) 995 diffTestFiles = append(diffTestFiles, diffTestFile) 996 ctx.Phony("soong_generated_boot_filesystem_test", diffTestFile) 997 } 998 if f.properties.Vendor_boot_image != "" { 999 diffTestFile := android.PathForModuleOut(ctx, "vendor_boot_diff_test.txt") 1000 soongBootImg := android.PathForModuleSrc(ctx, f.properties.Vendor_boot_image) 1001 makeBootImage := android.PathForArbitraryOutput(ctx, fmt.Sprintf("target/product/%s/vendor_boot.img", ctx.Config().DeviceName())) 1002 createDiffTest(ctx, diffTestFile, soongBootImg, makeBootImage) 1003 diffTestFiles = append(diffTestFiles, diffTestFile) 1004 ctx.Phony("soong_generated_vendor_boot_filesystem_test", diffTestFile) 1005 } 1006 if f.properties.Init_boot_image != "" { 1007 diffTestFile := android.PathForModuleOut(ctx, "init_boot_diff_test.txt") 1008 soongBootImg := android.PathForModuleSrc(ctx, f.properties.Init_boot_image) 1009 makeBootImage := android.PathForArbitraryOutput(ctx, fmt.Sprintf("target/product/%s/init_boot.img", ctx.Config().DeviceName())) 1010 createDiffTest(ctx, diffTestFile, soongBootImg, makeBootImage) 1011 diffTestFiles = append(diffTestFiles, diffTestFile) 1012 ctx.Phony("soong_generated_init_boot_filesystem_test", diffTestFile) 1013 } 1014 if f.properties.Super_image != "" { 1015 diffTestFile := android.PathForModuleOut(ctx, "super_diff_test.txt") 1016 soongSuperImg := android.PathForModuleSrc(ctx, f.properties.Super_image) 1017 makeSuperImage := android.PathForArbitraryOutput(ctx, fmt.Sprintf("target/product/%s/super.img", ctx.Config().DeviceName())) 1018 createDiffTest(ctx, diffTestFile, soongSuperImg, makeSuperImage) 1019 diffTestFiles = append(diffTestFiles, diffTestFile) 1020 ctx.Phony("soong_generated_super_filesystem_test", diffTestFile) 1021 } 1022 ctx.Phony("soong_generated_filesystem_tests", diffTestFiles...) 1023} 1024 1025func generateBpContent(ctx android.EarlyModuleContext, partitionType string) string { 1026 fsProps, fsTypeSupported := generateFsProps(ctx, partitionType) 1027 if !fsTypeSupported { 1028 return "" 1029 } 1030 1031 baseProps := generateBaseProps(proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), partitionType))) 1032 fsGenState := ctx.Config().Get(fsGenStateOnceKey).(*FsGenState) 1033 deps := fsGenState.fsDeps[partitionType] 1034 highPriorityDeps := fsGenState.generatedPrebuiltEtcModuleNames 1035 depProps := generateDepStruct(*deps, highPriorityDeps) 1036 1037 result, err := proptools.RepackProperties([]interface{}{baseProps, fsProps, depProps}) 1038 if err != nil { 1039 ctx.ModuleErrorf("%s", err.Error()) 1040 return "" 1041 } 1042 1043 moduleType := "android_filesystem" 1044 if partitionType == "system" { 1045 moduleType = "android_system_image" 1046 } 1047 1048 file := &parser.File{ 1049 Defs: []parser.Definition{ 1050 &parser.Module{ 1051 Type: moduleType, 1052 Map: *result, 1053 }, 1054 }, 1055 } 1056 bytes, err := parser.Print(file) 1057 if err != nil { 1058 ctx.ModuleErrorf(err.Error()) 1059 } 1060 return strings.TrimSpace(string(bytes)) 1061} 1062