Merge "Add super_image module type and create super image module in fsgen" into main

This commit is contained in:
Zi Wang 2024-12-05 17:44:43 +00:00 committed by Gerrit Code Review
commit a242492bb7
6 changed files with 358 additions and 0 deletions

View file

@ -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"`

View file

@ -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",

234
filesystem/super_image.go Normal file
View file

@ -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
}

View file

@ -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",
],

View file

@ -52,6 +52,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 {
@ -158,6 +159,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)
}
@ -998,6 +1004,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...)
}

91
fsgen/super_img.go Normal file
View file

@ -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)
}