diff options
author | 2024-12-02 22:13:59 -0800 | |
---|---|---|
committer | 2024-12-04 16:48:32 -0800 | |
commit | 79730d4d9c00d72ee47163e49c931d21aa532967 (patch) | |
tree | 591f83f53257297f9043c74586d1c3fd5a7d51b0 | |
parent | 18bad5f5c7d2a0e7da8553234aa5a281578131d8 (diff) |
Add super_image module type and create super image module in fsgen
fsgen processes the variables exported from make and create
the super image module. This module generates the misc-info.txt,
which is used by build_super_image.py to build the super image.
Test: CI
Bug: 376726109
Change-Id: I74a3e68d697704f36a770b3c83e5f8821b3ac128
-rw-r--r-- | android/variable.go | 17 | ||||
-rw-r--r-- | filesystem/Android.bp | 1 | ||||
-rw-r--r-- | filesystem/super_image.go | 234 | ||||
-rw-r--r-- | fsgen/Android.bp | 1 | ||||
-rw-r--r-- | fsgen/filesystem_creator.go | 14 | ||||
-rw-r--r-- | fsgen/super_img.go | 91 |
6 files changed, 358 insertions, 0 deletions
diff --git a/android/variable.go b/android/variable.go index baa26460f..19f63e33f 100644 --- a/android/variable.go +++ b/android/variable.go @@ -581,6 +581,11 @@ type PartitionQualifiedVariablesType struct { BoardAvbRollbackIndexLocation string `json:",omitempty"` } +type BoardSuperPartitionGroupProps struct { + GroupSize string `json:",omitempty"` + PartitionList []string `json:",omitempty"` +} + type ChainedAvbPartitionProps struct { Partitions []string `json:",omitempty"` Key string `json:",omitempty"` @@ -634,6 +639,18 @@ type PartitionVariables struct { InternalBootconfig []string `json:",omitempty"` InternalBootconfigFile string `json:",omitempty"` + // Super image stuff + ProductUseDynamicPartitions bool `json:",omitempty"` + ProductRetrofitDynamicPartitions bool `json:",omitempty"` + ProductBuildSuperPartition bool `json:",omitempty"` + BoardSuperPartitionSize string `json:",omitempty"` + BoardSuperPartitionMetadataDevice string `json:",omitempty"` + BoardSuperPartitionBlockDevices []string `json:",omitempty"` + BoardSuperPartitionGroups map[string]BoardSuperPartitionGroupProps `json:",omitempty"` + ProductVirtualAbOta bool `json:",omitempty"` + ProductVirtualAbOtaRetrofit bool `json:",omitempty"` + AbOtaUpdater bool `json:",omitempty"` + // Avb (android verified boot) stuff BoardAvbEnable bool `json:",omitempty"` BoardAvbAlgorithm string `json:",omitempty"` diff --git a/filesystem/Android.bp b/filesystem/Android.bp index bbb3ea7d8..127faa75f 100644 --- a/filesystem/Android.bp +++ b/filesystem/Android.bp @@ -25,6 +25,7 @@ bootstrap_go_package { "fsverity_metadata.go", "logical_partition.go", "raw_binary.go", + "super_image.go", "system_image.go", "vbmeta.go", "testing.go", diff --git a/filesystem/super_image.go b/filesystem/super_image.go new file mode 100644 index 000000000..1583c0b4f --- /dev/null +++ b/filesystem/super_image.go @@ -0,0 +1,234 @@ +// Copyright (C) 2024 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package filesystem + +import ( + "fmt" + "path/filepath" + "strconv" + "strings" + + "android/soong/android" + "github.com/google/blueprint" + "github.com/google/blueprint/proptools" +) + +func init() { + android.RegisterModuleType("super_image", SuperImageFactory) +} + +type superImage struct { + android.ModuleBase + + properties SuperImageProperties + partitionProps SuperImagePartitionNameProperties + + installDir android.InstallPath +} + +type SuperImageProperties struct { + // the size of the super partition + Size *int64 + // the block device where metadata for dynamic partitions is stored + Metadata_device *string + // the super partition block device list + Block_devices *string + // whether A/B updater is used + Ab_update *bool + // whether dynamic partitions is enabled on devices that were launched without this support + Retrofit *bool + // whether virtual A/B seamless update is enabled + Virtual_ab *bool + // whether retrofitting virtual A/B seamless update is enabled + Virtual_ab_retrofit *bool + // whether the output is a sparse image + Sparse *bool + // information about how partitions within the super partition are grouped together + Partition_groups []PartitionGroupsInfo + // whether dynamic partitions is used + Use_dynamic_partitions *bool +} + +type PartitionGroupsInfo struct { + Name string + GroupSize string + PartitionList []string +} + +type SuperImagePartitionNameProperties struct { + // Name of the System partition filesystem module + System_partition *string + // Name of the System_ext partition filesystem module + System_ext_partition *string + // Name of the System_dlkm partition filesystem module + System_dlkm_partition *string + // Name of the System_other partition filesystem module + System_other_partition *string + // Name of the Product partition filesystem module + Product_partition *string + // Name of the Vendor partition filesystem module + Vendor_partition *string + // Name of the Vendor_dlkm partition filesystem module + Vendor_dlkm_partition *string + // Name of the Odm partition filesystem module + Odm_partition *string + // Name of the Odm_dlkm partition filesystem module + Odm_dlkm_partition *string +} + +func SuperImageFactory() android.Module { + module := &superImage{} + module.AddProperties(&module.properties, &module.partitionProps) + android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon) + return module +} + +type superImageDepTagType struct { + blueprint.BaseDependencyTag +} + +var superImageDepTag superImageDepTagType + +func (s *superImage) DepsMutator(ctx android.BottomUpMutatorContext) { + addDependencyIfDefined := func(dep *string) { + if dep != nil { + ctx.AddDependency(ctx.Module(), superImageDepTag, proptools.String(dep)) + } + } + + addDependencyIfDefined(s.partitionProps.System_partition) + addDependencyIfDefined(s.partitionProps.System_ext_partition) + addDependencyIfDefined(s.partitionProps.System_dlkm_partition) + addDependencyIfDefined(s.partitionProps.System_other_partition) + addDependencyIfDefined(s.partitionProps.Product_partition) + addDependencyIfDefined(s.partitionProps.Vendor_partition) + addDependencyIfDefined(s.partitionProps.Vendor_dlkm_partition) + addDependencyIfDefined(s.partitionProps.Odm_partition) + addDependencyIfDefined(s.partitionProps.Odm_dlkm_partition) +} + +func (s *superImage) GenerateAndroidBuildActions(ctx android.ModuleContext) { + miscInfo, deps := s.buildMiscInfo(ctx) + builder := android.NewRuleBuilder(pctx, ctx) + output := android.PathForModuleOut(ctx, s.installFileName()) + lpMake := ctx.Config().HostToolPath(ctx, "lpmake") + lpMakeDir := filepath.Dir(lpMake.String()) + deps = append(deps, lpMake) + builder.Command().Textf("PATH=%s:\\$PATH", lpMakeDir). + BuiltTool("build_super_image"). + Text("-v"). + Input(miscInfo). + Implicits(deps). + Output(output) + builder.Build("build_super_image", fmt.Sprintf("Creating super image %s", s.BaseModuleName())) + ctx.SetOutputFiles([]android.Path{output}, "") +} + +func (s *superImage) installFileName() string { + return s.BaseModuleName() + ".img" +} + +func (s *superImage) buildMiscInfo(ctx android.ModuleContext) (android.Path, android.Paths) { + var miscInfoString strings.Builder + addStr := func(name string, value string) { + miscInfoString.WriteString(name) + miscInfoString.WriteRune('=') + miscInfoString.WriteString(value) + miscInfoString.WriteRune('\n') + } + + addStr("use_dynamic_partitions", strconv.FormatBool(proptools.Bool(s.properties.Use_dynamic_partitions))) + addStr("dynamic_partition_retrofit", strconv.FormatBool(proptools.Bool(s.properties.Retrofit))) + addStr("lpmake", "lpmake") + addStr("super_metadata_device", proptools.String(s.properties.Metadata_device)) + addStr("super_block_devices", proptools.String(s.properties.Block_devices)) + addStr("super_super_device_size", strconv.Itoa(proptools.Int(s.properties.Size))) + var groups, partitionList []string + for _, groupInfo := range s.properties.Partition_groups { + groups = append(groups, groupInfo.Name) + partitionList = append(partitionList, groupInfo.PartitionList...) + addStr("super_"+groupInfo.Name+"_group_size", groupInfo.GroupSize) + addStr("super_"+groupInfo.Name+"_partition_list", strings.Join(groupInfo.PartitionList, " ")) + } + addStr("super_partition_groups", strings.Join(groups, " ")) + addStr("dynamic_partition_list", strings.Join(partitionList, " ")) + + addStr("virtual_ab", strconv.FormatBool(proptools.Bool(s.properties.Virtual_ab))) + addStr("virtual_ab_retrofit", strconv.FormatBool(proptools.Bool(s.properties.Virtual_ab_retrofit))) + addStr("ab_update", strconv.FormatBool(proptools.Bool(s.properties.Ab_update))) + addStr("build_non_sparse_super_partition", strconv.FormatBool(!proptools.Bool(s.properties.Sparse))) + + partitionToImagePath := make(map[string]string) + nameToPartition := make(map[string]string) + var systemOtherPartitionNameNeeded string + addEntryToPartitionToName := func(p string, s *string) { + if proptools.String(s) != "" { + nameToPartition[*s] = p + } + } + + // Build partitionToImagePath, because system partition may need system_other + // partition image path + for _, p := range partitionList { + if _, ok := nameToPartition[p]; ok { + continue + } + switch p { + case "system": + addEntryToPartitionToName(p, s.partitionProps.System_partition) + systemOtherPartitionNameNeeded = proptools.String(s.partitionProps.System_other_partition) + case "system_dlkm": + addEntryToPartitionToName(p, s.partitionProps.System_dlkm_partition) + case "system_ext": + addEntryToPartitionToName(p, s.partitionProps.System_ext_partition) + case "product": + addEntryToPartitionToName(p, s.partitionProps.Product_partition) + case "vendor": + addEntryToPartitionToName(p, s.partitionProps.Vendor_partition) + case "vendor_dlkm": + addEntryToPartitionToName(p, s.partitionProps.Vendor_dlkm_partition) + case "odm": + addEntryToPartitionToName(p, s.partitionProps.Odm_partition) + case "odm_dlkm": + addEntryToPartitionToName(p, s.partitionProps.Odm_dlkm_partition) + default: + ctx.ModuleErrorf("current partition %s not a super image supported partition", p) + } + } + + var deps android.Paths + ctx.VisitDirectDeps(func(m android.Module) { + if p, ok := nameToPartition[m.Name()]; ok { + if output, ok := android.OtherModuleProvider(ctx, m, android.OutputFilesProvider); ok { + partitionToImagePath[p] = output.DefaultOutputFiles[0].String() + deps = append(deps, output.DefaultOutputFiles[0]) + } + } else if systemOtherPartitionNameNeeded != "" && m.Name() == systemOtherPartitionNameNeeded { + if output, ok := android.OtherModuleProvider(ctx, m, android.OutputFilesProvider); ok { + partitionToImagePath["system_other"] = output.DefaultOutputFiles[0].String() + // TODO: add system_other to deps after it can be generated + // deps = append(deps, output.DefaultOutputFiles[0]) + } + } + }) + + for _, p := range android.SortedKeys(partitionToImagePath) { + addStr(p+"_image", partitionToImagePath[p]) + } + + miscInfo := android.PathForModuleOut(ctx, "misc_info.txt") + android.WriteFileRule(ctx, miscInfo, miscInfoString.String()) + return miscInfo, deps +} diff --git a/fsgen/Android.bp b/fsgen/Android.bp index e8065f351..365d9540f 100644 --- a/fsgen/Android.bp +++ b/fsgen/Android.bp @@ -17,6 +17,7 @@ bootstrap_go_package { "filesystem_creator.go", "fsgen_mutators.go", "prebuilt_etc_modules_gen.go", + "super_img.go", "util.go", "vbmeta_partitions.go", ], diff --git a/fsgen/filesystem_creator.go b/fsgen/filesystem_creator.go index 745aeaaa7..2acfb9c4e 100644 --- a/fsgen/filesystem_creator.go +++ b/fsgen/filesystem_creator.go @@ -51,6 +51,7 @@ type filesystemCreatorProps struct { Boot_image string `blueprint:"mutated" android:"path_device_first"` Vendor_boot_image string `blueprint:"mutated" android:"path_device_first"` Init_boot_image string `blueprint:"mutated" android:"path_device_first"` + Super_image string `blueprint:"mutated" android:"path_device_first"` } type filesystemCreator struct { @@ -157,6 +158,11 @@ func (f *filesystemCreator) createInternalModules(ctx android.LoadHookContext) { f.properties.Vbmeta_partition_names = append(f.properties.Vbmeta_partition_names, x.partitionName) } + if buildingSuperImage(partitionVars) { + createSuperImage(ctx, finalSoongGeneratedPartitions, partitionVars) + f.properties.Super_image = ":" + generatedModuleName(ctx.Config(), "super") + } + ctx.Config().Get(fsGenStateOnceKey).(*FsGenState).soongGeneratedPartitions = finalSoongGeneratedPartitions f.createDeviceModule(ctx, finalSoongGeneratedPartitions, f.properties.Vbmeta_module_names) } @@ -971,6 +977,14 @@ func (f *filesystemCreator) GenerateAndroidBuildActions(ctx android.ModuleContex diffTestFiles = append(diffTestFiles, diffTestFile) ctx.Phony("soong_generated_init_boot_filesystem_test", diffTestFile) } + if f.properties.Super_image != "" { + diffTestFile := android.PathForModuleOut(ctx, "super_diff_test.txt") + soongSuperImg := android.PathForModuleSrc(ctx, f.properties.Super_image) + makeSuperImage := android.PathForArbitraryOutput(ctx, fmt.Sprintf("target/product/%s/super.img", ctx.Config().DeviceName())) + createDiffTest(ctx, diffTestFile, soongSuperImg, makeSuperImage) + diffTestFiles = append(diffTestFiles, diffTestFile) + ctx.Phony("soong_generated_super_filesystem_test", diffTestFile) + } ctx.Phony("soong_generated_filesystem_tests", diffTestFiles...) } diff --git a/fsgen/super_img.go b/fsgen/super_img.go new file mode 100644 index 000000000..45698969f --- /dev/null +++ b/fsgen/super_img.go @@ -0,0 +1,91 @@ +// Copyright (C) 2024 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package fsgen + +import ( + "strconv" + + "android/soong/android" + "android/soong/filesystem" + "github.com/google/blueprint/proptools" +) + +func buildingSuperImage(partitionVars android.PartitionVariables) bool { + return partitionVars.ProductBuildSuperPartition +} + +func createSuperImage(ctx android.LoadHookContext, partitions []string, partitionVars android.PartitionVariables) { + baseProps := &struct { + Name *string + }{ + Name: proptools.StringPtr(generatedModuleName(ctx.Config(), "super")), + } + + superImageProps := &filesystem.SuperImageProperties{ + Metadata_device: proptools.StringPtr(partitionVars.BoardSuperPartitionMetadataDevice), + Block_devices: proptools.StringPtr(partitionVars.BoardSuperPartitionBlockDevices[0]), + Ab_update: proptools.BoolPtr(partitionVars.AbOtaUpdater), + Retrofit: proptools.BoolPtr(partitionVars.ProductRetrofitDynamicPartitions), + Virtual_ab: proptools.BoolPtr(partitionVars.ProductVirtualAbOta), + Virtual_ab_retrofit: proptools.BoolPtr(partitionVars.ProductVirtualAbOtaRetrofit), + Use_dynamic_partitions: proptools.BoolPtr(partitionVars.ProductUseDynamicPartitions), + } + size, _ := strconv.ParseInt(partitionVars.BoardSuperPartitionSize, 10, 64) + superImageProps.Size = proptools.Int64Ptr(size) + sparse := !partitionVars.TargetUserimagesSparseExtDisabled && !partitionVars.TargetUserimagesSparseF2fsDisabled + superImageProps.Sparse = proptools.BoolPtr(sparse) + + var partitionGroupsInfo []filesystem.PartitionGroupsInfo + for _, groupName := range android.SortedKeys(partitionVars.BoardSuperPartitionGroups) { + info := filesystem.PartitionGroupsInfo{ + Name: groupName, + GroupSize: partitionVars.BoardSuperPartitionGroups[groupName].GroupSize, + PartitionList: partitionVars.BoardSuperPartitionGroups[groupName].PartitionList, + } + partitionGroupsInfo = append(partitionGroupsInfo, info) + } + superImageProps.Partition_groups = partitionGroupsInfo + + partitionNameProps := &filesystem.SuperImagePartitionNameProperties{} + if android.InList("system", partitions) { + partitionNameProps.System_partition = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "system")) + } + if android.InList("system_ext", partitions) { + partitionNameProps.System_ext_partition = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "system_ext")) + } + if android.InList("system_dlkm", partitions) { + partitionNameProps.System_dlkm_partition = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "system_dlkm")) + } + if android.InList("system_other", partitions) { + partitionNameProps.System_other_partition = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "system_other")) + } + if android.InList("product", partitions) { + partitionNameProps.Product_partition = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "product")) + } + if android.InList("vendor", partitions) { + partitionNameProps.Vendor_partition = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "vendor")) + } + if android.InList("vendor_dlkm", partitions) { + partitionNameProps.Vendor_dlkm_partition = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "vendor_dlkm")) + } + if android.InList("odm", partitions) { + partitionNameProps.Odm_partition = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "odm")) + } + if android.InList("odm_dlkm", partitions) { + partitionNameProps.Odm_dlkm_partition = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "odm_dlkm")) + } + + ctx.CreateModule(filesystem.SuperImageFactory, baseProps, superImageProps, partitionNameProps) +} |