1*333d2b36SAndroid Build Coastguard Worker// Copyright (C) 2024 The Android Open Source Project 2*333d2b36SAndroid Build Coastguard Worker// 3*333d2b36SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License"); 4*333d2b36SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License. 5*333d2b36SAndroid Build Coastguard Worker// You may obtain a copy of the License at 6*333d2b36SAndroid Build Coastguard Worker// 7*333d2b36SAndroid Build Coastguard Worker// http://www.apache.org/licenses/LICENSE-2.0 8*333d2b36SAndroid Build Coastguard Worker// 9*333d2b36SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software 10*333d2b36SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS, 11*333d2b36SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*333d2b36SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and 13*333d2b36SAndroid Build Coastguard Worker// limitations under the License. 14*333d2b36SAndroid Build Coastguard Worker 15*333d2b36SAndroid Build Coastguard Workerpackage filesystem 16*333d2b36SAndroid Build Coastguard Worker 17*333d2b36SAndroid Build Coastguard Workerimport ( 18*333d2b36SAndroid Build Coastguard Worker "fmt" 19*333d2b36SAndroid Build Coastguard Worker "path/filepath" 20*333d2b36SAndroid Build Coastguard Worker "strconv" 21*333d2b36SAndroid Build Coastguard Worker "strings" 22*333d2b36SAndroid Build Coastguard Worker 23*333d2b36SAndroid Build Coastguard Worker "android/soong/android" 24*333d2b36SAndroid Build Coastguard Worker "github.com/google/blueprint" 25*333d2b36SAndroid Build Coastguard Worker "github.com/google/blueprint/proptools" 26*333d2b36SAndroid Build Coastguard Worker) 27*333d2b36SAndroid Build Coastguard Worker 28*333d2b36SAndroid Build Coastguard Workerfunc init() { 29*333d2b36SAndroid Build Coastguard Worker android.RegisterModuleType("super_image", SuperImageFactory) 30*333d2b36SAndroid Build Coastguard Worker} 31*333d2b36SAndroid Build Coastguard Worker 32*333d2b36SAndroid Build Coastguard Workertype superImage struct { 33*333d2b36SAndroid Build Coastguard Worker android.ModuleBase 34*333d2b36SAndroid Build Coastguard Worker 35*333d2b36SAndroid Build Coastguard Worker properties SuperImageProperties 36*333d2b36SAndroid Build Coastguard Worker partitionProps SuperImagePartitionNameProperties 37*333d2b36SAndroid Build Coastguard Worker 38*333d2b36SAndroid Build Coastguard Worker installDir android.InstallPath 39*333d2b36SAndroid Build Coastguard Worker} 40*333d2b36SAndroid Build Coastguard Worker 41*333d2b36SAndroid Build Coastguard Workertype SuperImageProperties struct { 42*333d2b36SAndroid Build Coastguard Worker // the size of the super partition 43*333d2b36SAndroid Build Coastguard Worker Size *int64 44*333d2b36SAndroid Build Coastguard Worker // the block device where metadata for dynamic partitions is stored 45*333d2b36SAndroid Build Coastguard Worker Metadata_device *string 46*333d2b36SAndroid Build Coastguard Worker // the super partition block device list 47*333d2b36SAndroid Build Coastguard Worker Block_devices []string 48*333d2b36SAndroid Build Coastguard Worker // whether A/B updater is used 49*333d2b36SAndroid Build Coastguard Worker Ab_update *bool 50*333d2b36SAndroid Build Coastguard Worker // whether dynamic partitions is enabled on devices that were launched without this support 51*333d2b36SAndroid Build Coastguard Worker Retrofit *bool 52*333d2b36SAndroid Build Coastguard Worker // whether virtual A/B seamless update is enabled 53*333d2b36SAndroid Build Coastguard Worker Virtual_ab *bool 54*333d2b36SAndroid Build Coastguard Worker // whether retrofitting virtual A/B seamless update is enabled 55*333d2b36SAndroid Build Coastguard Worker Virtual_ab_retrofit *bool 56*333d2b36SAndroid Build Coastguard Worker // whether the output is a sparse image 57*333d2b36SAndroid Build Coastguard Worker Sparse *bool 58*333d2b36SAndroid Build Coastguard Worker // information about how partitions within the super partition are grouped together 59*333d2b36SAndroid Build Coastguard Worker Partition_groups []PartitionGroupsInfo 60*333d2b36SAndroid Build Coastguard Worker // whether dynamic partitions is used 61*333d2b36SAndroid Build Coastguard Worker Use_dynamic_partitions *bool 62*333d2b36SAndroid Build Coastguard Worker} 63*333d2b36SAndroid Build Coastguard Worker 64*333d2b36SAndroid Build Coastguard Workertype PartitionGroupsInfo struct { 65*333d2b36SAndroid Build Coastguard Worker Name string 66*333d2b36SAndroid Build Coastguard Worker GroupSize string 67*333d2b36SAndroid Build Coastguard Worker PartitionList []string 68*333d2b36SAndroid Build Coastguard Worker} 69*333d2b36SAndroid Build Coastguard Worker 70*333d2b36SAndroid Build Coastguard Workertype SuperImagePartitionNameProperties struct { 71*333d2b36SAndroid Build Coastguard Worker // Name of the System partition filesystem module 72*333d2b36SAndroid Build Coastguard Worker System_partition *string 73*333d2b36SAndroid Build Coastguard Worker // Name of the System_ext partition filesystem module 74*333d2b36SAndroid Build Coastguard Worker System_ext_partition *string 75*333d2b36SAndroid Build Coastguard Worker // Name of the System_dlkm partition filesystem module 76*333d2b36SAndroid Build Coastguard Worker System_dlkm_partition *string 77*333d2b36SAndroid Build Coastguard Worker // Name of the System_other partition filesystem module 78*333d2b36SAndroid Build Coastguard Worker System_other_partition *string 79*333d2b36SAndroid Build Coastguard Worker // Name of the Product partition filesystem module 80*333d2b36SAndroid Build Coastguard Worker Product_partition *string 81*333d2b36SAndroid Build Coastguard Worker // Name of the Vendor partition filesystem module 82*333d2b36SAndroid Build Coastguard Worker Vendor_partition *string 83*333d2b36SAndroid Build Coastguard Worker // Name of the Vendor_dlkm partition filesystem module 84*333d2b36SAndroid Build Coastguard Worker Vendor_dlkm_partition *string 85*333d2b36SAndroid Build Coastguard Worker // Name of the Odm partition filesystem module 86*333d2b36SAndroid Build Coastguard Worker Odm_partition *string 87*333d2b36SAndroid Build Coastguard Worker // Name of the Odm_dlkm partition filesystem module 88*333d2b36SAndroid Build Coastguard Worker Odm_dlkm_partition *string 89*333d2b36SAndroid Build Coastguard Worker} 90*333d2b36SAndroid Build Coastguard Worker 91*333d2b36SAndroid Build Coastguard Workerfunc SuperImageFactory() android.Module { 92*333d2b36SAndroid Build Coastguard Worker module := &superImage{} 93*333d2b36SAndroid Build Coastguard Worker module.AddProperties(&module.properties, &module.partitionProps) 94*333d2b36SAndroid Build Coastguard Worker android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon) 95*333d2b36SAndroid Build Coastguard Worker return module 96*333d2b36SAndroid Build Coastguard Worker} 97*333d2b36SAndroid Build Coastguard Worker 98*333d2b36SAndroid Build Coastguard Workertype superImageDepTagType struct { 99*333d2b36SAndroid Build Coastguard Worker blueprint.BaseDependencyTag 100*333d2b36SAndroid Build Coastguard Worker} 101*333d2b36SAndroid Build Coastguard Worker 102*333d2b36SAndroid Build Coastguard Workervar superImageDepTag superImageDepTagType 103*333d2b36SAndroid Build Coastguard Worker 104*333d2b36SAndroid Build Coastguard Workerfunc (s *superImage) DepsMutator(ctx android.BottomUpMutatorContext) { 105*333d2b36SAndroid Build Coastguard Worker addDependencyIfDefined := func(dep *string) { 106*333d2b36SAndroid Build Coastguard Worker if dep != nil { 107*333d2b36SAndroid Build Coastguard Worker ctx.AddDependency(ctx.Module(), superImageDepTag, proptools.String(dep)) 108*333d2b36SAndroid Build Coastguard Worker } 109*333d2b36SAndroid Build Coastguard Worker } 110*333d2b36SAndroid Build Coastguard Worker 111*333d2b36SAndroid Build Coastguard Worker addDependencyIfDefined(s.partitionProps.System_partition) 112*333d2b36SAndroid Build Coastguard Worker addDependencyIfDefined(s.partitionProps.System_ext_partition) 113*333d2b36SAndroid Build Coastguard Worker addDependencyIfDefined(s.partitionProps.System_dlkm_partition) 114*333d2b36SAndroid Build Coastguard Worker addDependencyIfDefined(s.partitionProps.System_other_partition) 115*333d2b36SAndroid Build Coastguard Worker addDependencyIfDefined(s.partitionProps.Product_partition) 116*333d2b36SAndroid Build Coastguard Worker addDependencyIfDefined(s.partitionProps.Vendor_partition) 117*333d2b36SAndroid Build Coastguard Worker addDependencyIfDefined(s.partitionProps.Vendor_dlkm_partition) 118*333d2b36SAndroid Build Coastguard Worker addDependencyIfDefined(s.partitionProps.Odm_partition) 119*333d2b36SAndroid Build Coastguard Worker addDependencyIfDefined(s.partitionProps.Odm_dlkm_partition) 120*333d2b36SAndroid Build Coastguard Worker} 121*333d2b36SAndroid Build Coastguard Worker 122*333d2b36SAndroid Build Coastguard Workerfunc (s *superImage) GenerateAndroidBuildActions(ctx android.ModuleContext) { 123*333d2b36SAndroid Build Coastguard Worker miscInfo, deps := s.buildMiscInfo(ctx) 124*333d2b36SAndroid Build Coastguard Worker builder := android.NewRuleBuilder(pctx, ctx) 125*333d2b36SAndroid Build Coastguard Worker output := android.PathForModuleOut(ctx, s.installFileName()) 126*333d2b36SAndroid Build Coastguard Worker lpMake := ctx.Config().HostToolPath(ctx, "lpmake") 127*333d2b36SAndroid Build Coastguard Worker lpMakeDir := filepath.Dir(lpMake.String()) 128*333d2b36SAndroid Build Coastguard Worker deps = append(deps, lpMake) 129*333d2b36SAndroid Build Coastguard Worker builder.Command().Textf("PATH=%s:\\$PATH", lpMakeDir). 130*333d2b36SAndroid Build Coastguard Worker BuiltTool("build_super_image"). 131*333d2b36SAndroid Build Coastguard Worker Text("-v"). 132*333d2b36SAndroid Build Coastguard Worker Input(miscInfo). 133*333d2b36SAndroid Build Coastguard Worker Implicits(deps). 134*333d2b36SAndroid Build Coastguard Worker Output(output) 135*333d2b36SAndroid Build Coastguard Worker builder.Build("build_super_image", fmt.Sprintf("Creating super image %s", s.BaseModuleName())) 136*333d2b36SAndroid Build Coastguard Worker ctx.SetOutputFiles([]android.Path{output}, "") 137*333d2b36SAndroid Build Coastguard Worker} 138*333d2b36SAndroid Build Coastguard Worker 139*333d2b36SAndroid Build Coastguard Workerfunc (s *superImage) installFileName() string { 140*333d2b36SAndroid Build Coastguard Worker return s.BaseModuleName() + ".img" 141*333d2b36SAndroid Build Coastguard Worker} 142*333d2b36SAndroid Build Coastguard Worker 143*333d2b36SAndroid Build Coastguard Workerfunc (s *superImage) buildMiscInfo(ctx android.ModuleContext) (android.Path, android.Paths) { 144*333d2b36SAndroid Build Coastguard Worker var miscInfoString strings.Builder 145*333d2b36SAndroid Build Coastguard Worker addStr := func(name string, value string) { 146*333d2b36SAndroid Build Coastguard Worker miscInfoString.WriteString(name) 147*333d2b36SAndroid Build Coastguard Worker miscInfoString.WriteRune('=') 148*333d2b36SAndroid Build Coastguard Worker miscInfoString.WriteString(value) 149*333d2b36SAndroid Build Coastguard Worker miscInfoString.WriteRune('\n') 150*333d2b36SAndroid Build Coastguard Worker } 151*333d2b36SAndroid Build Coastguard Worker 152*333d2b36SAndroid Build Coastguard Worker addStr("use_dynamic_partitions", strconv.FormatBool(proptools.Bool(s.properties.Use_dynamic_partitions))) 153*333d2b36SAndroid Build Coastguard Worker addStr("dynamic_partition_retrofit", strconv.FormatBool(proptools.Bool(s.properties.Retrofit))) 154*333d2b36SAndroid Build Coastguard Worker addStr("lpmake", "lpmake") 155*333d2b36SAndroid Build Coastguard Worker addStr("super_metadata_device", proptools.String(s.properties.Metadata_device)) 156*333d2b36SAndroid Build Coastguard Worker if len(s.properties.Block_devices) > 0 { 157*333d2b36SAndroid Build Coastguard Worker addStr("super_block_devices", strings.Join(s.properties.Block_devices, " ")) 158*333d2b36SAndroid Build Coastguard Worker } 159*333d2b36SAndroid Build Coastguard Worker addStr("super_super_device_size", strconv.Itoa(proptools.Int(s.properties.Size))) 160*333d2b36SAndroid Build Coastguard Worker var groups, partitionList []string 161*333d2b36SAndroid Build Coastguard Worker for _, groupInfo := range s.properties.Partition_groups { 162*333d2b36SAndroid Build Coastguard Worker groups = append(groups, groupInfo.Name) 163*333d2b36SAndroid Build Coastguard Worker partitionList = append(partitionList, groupInfo.PartitionList...) 164*333d2b36SAndroid Build Coastguard Worker addStr("super_"+groupInfo.Name+"_group_size", groupInfo.GroupSize) 165*333d2b36SAndroid Build Coastguard Worker addStr("super_"+groupInfo.Name+"_partition_list", strings.Join(groupInfo.PartitionList, " ")) 166*333d2b36SAndroid Build Coastguard Worker } 167*333d2b36SAndroid Build Coastguard Worker addStr("super_partition_groups", strings.Join(groups, " ")) 168*333d2b36SAndroid Build Coastguard Worker addStr("dynamic_partition_list", strings.Join(partitionList, " ")) 169*333d2b36SAndroid Build Coastguard Worker 170*333d2b36SAndroid Build Coastguard Worker addStr("virtual_ab", strconv.FormatBool(proptools.Bool(s.properties.Virtual_ab))) 171*333d2b36SAndroid Build Coastguard Worker addStr("virtual_ab_retrofit", strconv.FormatBool(proptools.Bool(s.properties.Virtual_ab_retrofit))) 172*333d2b36SAndroid Build Coastguard Worker addStr("ab_update", strconv.FormatBool(proptools.Bool(s.properties.Ab_update))) 173*333d2b36SAndroid Build Coastguard Worker addStr("build_non_sparse_super_partition", strconv.FormatBool(!proptools.Bool(s.properties.Sparse))) 174*333d2b36SAndroid Build Coastguard Worker 175*333d2b36SAndroid Build Coastguard Worker partitionToImagePath := make(map[string]string) 176*333d2b36SAndroid Build Coastguard Worker nameToPartition := make(map[string]string) 177*333d2b36SAndroid Build Coastguard Worker var systemOtherPartitionNameNeeded string 178*333d2b36SAndroid Build Coastguard Worker addEntryToPartitionToName := func(p string, s *string) { 179*333d2b36SAndroid Build Coastguard Worker if proptools.String(s) != "" { 180*333d2b36SAndroid Build Coastguard Worker nameToPartition[*s] = p 181*333d2b36SAndroid Build Coastguard Worker } 182*333d2b36SAndroid Build Coastguard Worker } 183*333d2b36SAndroid Build Coastguard Worker 184*333d2b36SAndroid Build Coastguard Worker // Build partitionToImagePath, because system partition may need system_other 185*333d2b36SAndroid Build Coastguard Worker // partition image path 186*333d2b36SAndroid Build Coastguard Worker for _, p := range partitionList { 187*333d2b36SAndroid Build Coastguard Worker if _, ok := nameToPartition[p]; ok { 188*333d2b36SAndroid Build Coastguard Worker continue 189*333d2b36SAndroid Build Coastguard Worker } 190*333d2b36SAndroid Build Coastguard Worker switch p { 191*333d2b36SAndroid Build Coastguard Worker case "system": 192*333d2b36SAndroid Build Coastguard Worker addEntryToPartitionToName(p, s.partitionProps.System_partition) 193*333d2b36SAndroid Build Coastguard Worker systemOtherPartitionNameNeeded = proptools.String(s.partitionProps.System_other_partition) 194*333d2b36SAndroid Build Coastguard Worker case "system_dlkm": 195*333d2b36SAndroid Build Coastguard Worker addEntryToPartitionToName(p, s.partitionProps.System_dlkm_partition) 196*333d2b36SAndroid Build Coastguard Worker case "system_ext": 197*333d2b36SAndroid Build Coastguard Worker addEntryToPartitionToName(p, s.partitionProps.System_ext_partition) 198*333d2b36SAndroid Build Coastguard Worker case "product": 199*333d2b36SAndroid Build Coastguard Worker addEntryToPartitionToName(p, s.partitionProps.Product_partition) 200*333d2b36SAndroid Build Coastguard Worker case "vendor": 201*333d2b36SAndroid Build Coastguard Worker addEntryToPartitionToName(p, s.partitionProps.Vendor_partition) 202*333d2b36SAndroid Build Coastguard Worker case "vendor_dlkm": 203*333d2b36SAndroid Build Coastguard Worker addEntryToPartitionToName(p, s.partitionProps.Vendor_dlkm_partition) 204*333d2b36SAndroid Build Coastguard Worker case "odm": 205*333d2b36SAndroid Build Coastguard Worker addEntryToPartitionToName(p, s.partitionProps.Odm_partition) 206*333d2b36SAndroid Build Coastguard Worker case "odm_dlkm": 207*333d2b36SAndroid Build Coastguard Worker addEntryToPartitionToName(p, s.partitionProps.Odm_dlkm_partition) 208*333d2b36SAndroid Build Coastguard Worker default: 209*333d2b36SAndroid Build Coastguard Worker ctx.ModuleErrorf("current partition %s not a super image supported partition", p) 210*333d2b36SAndroid Build Coastguard Worker } 211*333d2b36SAndroid Build Coastguard Worker } 212*333d2b36SAndroid Build Coastguard Worker 213*333d2b36SAndroid Build Coastguard Worker var deps android.Paths 214*333d2b36SAndroid Build Coastguard Worker ctx.VisitDirectDeps(func(m android.Module) { 215*333d2b36SAndroid Build Coastguard Worker if p, ok := nameToPartition[m.Name()]; ok { 216*333d2b36SAndroid Build Coastguard Worker if output, ok := android.OtherModuleProvider(ctx, m, android.OutputFilesProvider); ok { 217*333d2b36SAndroid Build Coastguard Worker partitionToImagePath[p] = output.DefaultOutputFiles[0].String() 218*333d2b36SAndroid Build Coastguard Worker deps = append(deps, output.DefaultOutputFiles[0]) 219*333d2b36SAndroid Build Coastguard Worker } 220*333d2b36SAndroid Build Coastguard Worker } else if systemOtherPartitionNameNeeded != "" && m.Name() == systemOtherPartitionNameNeeded { 221*333d2b36SAndroid Build Coastguard Worker if output, ok := android.OtherModuleProvider(ctx, m, android.OutputFilesProvider); ok { 222*333d2b36SAndroid Build Coastguard Worker partitionToImagePath["system_other"] = output.DefaultOutputFiles[0].String() 223*333d2b36SAndroid Build Coastguard Worker // TODO: add system_other to deps after it can be generated 224*333d2b36SAndroid Build Coastguard Worker // deps = append(deps, output.DefaultOutputFiles[0]) 225*333d2b36SAndroid Build Coastguard Worker } 226*333d2b36SAndroid Build Coastguard Worker } 227*333d2b36SAndroid Build Coastguard Worker }) 228*333d2b36SAndroid Build Coastguard Worker 229*333d2b36SAndroid Build Coastguard Worker for _, p := range android.SortedKeys(partitionToImagePath) { 230*333d2b36SAndroid Build Coastguard Worker addStr(p+"_image", partitionToImagePath[p]) 231*333d2b36SAndroid Build Coastguard Worker } 232*333d2b36SAndroid Build Coastguard Worker 233*333d2b36SAndroid Build Coastguard Worker miscInfo := android.PathForModuleOut(ctx, "misc_info.txt") 234*333d2b36SAndroid Build Coastguard Worker android.WriteFileRule(ctx, miscInfo, miscInfoString.String()) 235*333d2b36SAndroid Build Coastguard Worker return miscInfo, deps 236*333d2b36SAndroid Build Coastguard Worker} 237