xref: /aosp_15_r20/build/soong/filesystem/super_image.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
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