blob: ae7755f93159f3fda62aaa79f2483f74639fcd5b [file] [log] [blame]
Jihoon Kangf2c53982024-10-09 17:32:52 +00001// 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 filesystem
16
17import (
Spandan Das258c08f2025-01-08 23:30:45 +000018 "strings"
19
Jihoon Kangf2c53982024-10-09 17:32:52 +000020 "android/soong/android"
21
22 "github.com/google/blueprint"
23 "github.com/google/blueprint/proptools"
24)
25
26type PartitionNameProperties struct {
Cole Faust77243442025-01-09 15:49:15 -080027 // Name of the super partition filesystem module
28 Super_partition_name *string
Jihoon Kange7e3ec82025-01-02 21:29:14 +000029 // Name of the boot partition filesystem module
Jihoon Kangf2c53982024-10-09 17:32:52 +000030 Boot_partition_name *string
Jihoon Kange7e3ec82025-01-02 21:29:14 +000031 // Name of the vendor boot partition filesystem module
32 Vendor_boot_partition_name *string
33 // Name of the init boot partition filesystem module
34 Init_boot_partition_name *string
35 // Name of the system partition filesystem module
Jihoon Kangf2c53982024-10-09 17:32:52 +000036 System_partition_name *string
Jihoon Kange7e3ec82025-01-02 21:29:14 +000037 // Name of the system_ext partition filesystem module
Jihoon Kangf2c53982024-10-09 17:32:52 +000038 System_ext_partition_name *string
Jihoon Kange7e3ec82025-01-02 21:29:14 +000039 // Name of the product partition filesystem module
Jihoon Kangf2c53982024-10-09 17:32:52 +000040 Product_partition_name *string
Jihoon Kange7e3ec82025-01-02 21:29:14 +000041 // Name of the vendor partition filesystem module
Jihoon Kangf2c53982024-10-09 17:32:52 +000042 Vendor_partition_name *string
Jihoon Kange7e3ec82025-01-02 21:29:14 +000043 // Name of the odm partition filesystem module
Spandan Dasc5717162024-11-01 18:33:57 +000044 Odm_partition_name *string
Jihoon Kange7e3ec82025-01-02 21:29:14 +000045 // Name of the recovery partition filesystem module
46 Recovery_partition_name *string
Cole Faust3552eb62024-11-06 18:07:26 -080047 // The vbmeta partition and its "chained" partitions
48 Vbmeta_partitions []string
Jihoon Kange7e3ec82025-01-02 21:29:14 +000049 // Name of the userdata partition filesystem module
mrziwang23ba8762024-11-07 16:21:53 -080050 Userdata_partition_name *string
Spandan Dasa0394002025-01-07 18:38:34 +000051 // Name of the system_dlkm partition filesystem module
52 System_dlkm_partition_name *string
53 // Name of the vendor_dlkm partition filesystem module
54 Vendor_dlkm_partition_name *string
55 // Name of the odm_dlkm partition filesystem module
56 Odm_dlkm_partition_name *string
Jihoon Kangf2c53982024-10-09 17:32:52 +000057}
58
Jihoon Kang3be17162025-01-09 20:51:54 +000059type DeviceProperties struct {
60 // Path to the prebuilt bootloader that would be copied to PRODUCT_OUT
61 Bootloader *string `android:"path"`
62}
63
Jihoon Kangf2c53982024-10-09 17:32:52 +000064type androidDevice struct {
65 android.ModuleBase
66
67 partitionProps PartitionNameProperties
Jihoon Kang3be17162025-01-09 20:51:54 +000068
69 deviceProps DeviceProperties
70
71 // copyToProductOutTimestamp for copying necessary files to PRODUCT_OUT
72 copyToProductOutTimestamp android.WritablePath
Jihoon Kangf2c53982024-10-09 17:32:52 +000073}
74
75func AndroidDeviceFactory() android.Module {
76 module := &androidDevice{}
Jihoon Kang3be17162025-01-09 20:51:54 +000077 module.AddProperties(&module.partitionProps, &module.deviceProps)
Cole Faust341d5f12025-01-07 15:32:38 -080078 android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibFirst)
Jihoon Kangf2c53982024-10-09 17:32:52 +000079 return module
80}
81
82type partitionDepTagType struct {
83 blueprint.BaseDependencyTag
84}
85
Cole Faust77243442025-01-09 15:49:15 -080086type superPartitionDepTagType struct {
87 blueprint.BaseDependencyTag
88}
89
90var superPartitionDepTag superPartitionDepTagType
Jihoon Kangf2c53982024-10-09 17:32:52 +000091var filesystemDepTag partitionDepTagType
92
93func (a *androidDevice) DepsMutator(ctx android.BottomUpMutatorContext) {
94 addDependencyIfDefined := func(dep *string) {
95 if dep != nil {
Cole Faust341d5f12025-01-07 15:32:38 -080096 ctx.AddDependency(ctx.Module(), filesystemDepTag, proptools.String(dep))
Jihoon Kangf2c53982024-10-09 17:32:52 +000097 }
98 }
99
Cole Faust77243442025-01-09 15:49:15 -0800100 if a.partitionProps.Super_partition_name != nil {
101 ctx.AddDependency(ctx.Module(), superPartitionDepTag, *a.partitionProps.Super_partition_name)
102 }
Jihoon Kangf2c53982024-10-09 17:32:52 +0000103 addDependencyIfDefined(a.partitionProps.Boot_partition_name)
Jihoon Kang9e087002025-01-08 19:12:23 +0000104 addDependencyIfDefined(a.partitionProps.Init_boot_partition_name)
Spandan Dasef200ac2025-01-08 01:42:45 +0000105 addDependencyIfDefined(a.partitionProps.Vendor_boot_partition_name)
Jihoon Kangf2c53982024-10-09 17:32:52 +0000106 addDependencyIfDefined(a.partitionProps.System_partition_name)
107 addDependencyIfDefined(a.partitionProps.System_ext_partition_name)
108 addDependencyIfDefined(a.partitionProps.Product_partition_name)
109 addDependencyIfDefined(a.partitionProps.Vendor_partition_name)
Spandan Dasc5717162024-11-01 18:33:57 +0000110 addDependencyIfDefined(a.partitionProps.Odm_partition_name)
mrziwang23ba8762024-11-07 16:21:53 -0800111 addDependencyIfDefined(a.partitionProps.Userdata_partition_name)
Spandan Dasa0394002025-01-07 18:38:34 +0000112 addDependencyIfDefined(a.partitionProps.System_dlkm_partition_name)
113 addDependencyIfDefined(a.partitionProps.Vendor_dlkm_partition_name)
114 addDependencyIfDefined(a.partitionProps.Odm_dlkm_partition_name)
Spandan Dasef200ac2025-01-08 01:42:45 +0000115 addDependencyIfDefined(a.partitionProps.Recovery_partition_name)
Cole Faust3552eb62024-11-06 18:07:26 -0800116 for _, vbmetaPartition := range a.partitionProps.Vbmeta_partitions {
117 ctx.AddDependency(ctx.Module(), filesystemDepTag, vbmetaPartition)
118 }
Jihoon Kangf2c53982024-10-09 17:32:52 +0000119}
120
Jihoon Kang3be17162025-01-09 20:51:54 +0000121func (a *androidDevice) copyToProductOut(ctx android.ModuleContext, builder *android.RuleBuilder, src android.Path, dest string) {
122 destPath := android.PathForModuleInPartitionInstall(ctx, "").Join(ctx, dest)
123 builder.Command().Text("rsync").Flag("-a").Flag("--checksum").Input(src).Text(destPath.String())
124}
125
126func (a *androidDevice) copyFilesToProductOut(ctx android.ModuleContext) {
127 a.copyToProductOutTimestamp = android.PathForModuleOut(ctx, "timestamp")
128 builder := android.NewRuleBuilder(pctx, ctx)
129 builder.Command().Text("touch").Output(a.copyToProductOutTimestamp)
130
131 // List all individual files to be copied to PRODUCT_OUT here
132 if a.deviceProps.Bootloader != nil {
133 a.copyToProductOut(ctx, builder, android.PathForModuleSrc(ctx, proptools.String(a.deviceProps.Bootloader)), "bootloader")
134 }
135
136 builder.Build("copy_to_product_out", "Copy files to PRODUCT_OUT")
137}
138
Jihoon Kangf2c53982024-10-09 17:32:52 +0000139func (a *androidDevice) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Cole Faust44080412024-12-20 14:17:07 -0800140 a.buildTargetFilesZip(ctx)
mrziwang2fd33a72025-01-08 12:22:08 -0800141 var deps []android.Path
Cole Faust77243442025-01-09 15:49:15 -0800142 if proptools.String(a.partitionProps.Super_partition_name) != "" {
143 superImage := ctx.GetDirectDepWithTag(*a.partitionProps.Super_partition_name, superPartitionDepTag)
144 if info, ok := android.OtherModuleProvider(ctx, superImage, SuperImageProvider); ok {
145 assertUnset := func(prop *string, propName string) {
146 if prop != nil && *prop != "" {
147 ctx.PropertyErrorf(propName, "Cannot be set because it's already part of the super image")
148 }
149 }
150 for _, subPartitionType := range android.SortedKeys(info.SubImageInfo) {
151 switch subPartitionType {
152 case "system":
153 assertUnset(a.partitionProps.System_partition_name, "system_partition_name")
154 case "system_ext":
155 assertUnset(a.partitionProps.System_ext_partition_name, "system_ext_partition_name")
156 case "system_dlkm":
157 assertUnset(a.partitionProps.System_dlkm_partition_name, "system_dlkm_partition_name")
158 case "system_other":
159 // TODO
160 case "product":
161 assertUnset(a.partitionProps.Product_partition_name, "product_partition_name")
162 case "vendor":
163 assertUnset(a.partitionProps.Vendor_partition_name, "vendor_partition_name")
164 case "vendor_dlkm":
165 assertUnset(a.partitionProps.Vendor_dlkm_partition_name, "vendor_dlkm_partition_name")
166 case "odm":
167 assertUnset(a.partitionProps.Odm_partition_name, "odm_partition_name")
168 case "odm_dlkm":
169 assertUnset(a.partitionProps.Odm_dlkm_partition_name, "odm_dlkm_partition_name")
170 default:
171 ctx.ModuleErrorf("Unsupported sub-partition of super partition: %q", subPartitionType)
172 }
173 }
174
175 deps = append(deps, info.SuperImage)
176 } else {
177 ctx.ModuleErrorf("Expected super image dep to provide SuperImageProvider")
178 }
179 }
mrziwang2fd33a72025-01-08 12:22:08 -0800180 ctx.VisitDirectDepsWithTag(filesystemDepTag, func(m android.Module) {
181 imageOutput, ok := android.OtherModuleProvider(ctx, m, android.OutputFilesProvider)
182 if !ok {
183 ctx.ModuleErrorf("Partition module %s doesn't set OutputfilesProvider", m.Name())
184 }
185 if len(imageOutput.DefaultOutputFiles) != 1 {
186 ctx.ModuleErrorf("Partition module %s should provide exact 1 output file", m.Name())
187 }
188 deps = append(deps, imageOutput.DefaultOutputFiles[0])
189 })
Jihoon Kang3be17162025-01-09 20:51:54 +0000190
191 a.copyFilesToProductOut(ctx)
192
mrziwang2fd33a72025-01-08 12:22:08 -0800193 out := android.PathForModuleOut(ctx, "out")
194 ctx.Build(pctx, android.BuildParams{
Jihoon Kang3be17162025-01-09 20:51:54 +0000195 Rule: android.Touch,
196 Output: out,
197 Implicits: deps,
198 Validation: a.copyToProductOutTimestamp,
mrziwang2fd33a72025-01-08 12:22:08 -0800199 })
200 ctx.SetOutputFiles(android.Paths{out}, "")
201 ctx.CheckbuildFile(out)
Cole Faust44080412024-12-20 14:17:07 -0800202}
Jihoon Kangf2c53982024-10-09 17:32:52 +0000203
Spandan Dasef200ac2025-01-08 01:42:45 +0000204type targetFilesZipCopy struct {
205 srcModule *string
206 destSubdir string
207}
208
Cole Faust44080412024-12-20 14:17:07 -0800209func (a *androidDevice) buildTargetFilesZip(ctx android.ModuleContext) {
210 targetFilesDir := android.PathForModuleOut(ctx, "target_files_dir")
211 targetFilesZip := android.PathForModuleOut(ctx, "target_files.zip")
212
213 builder := android.NewRuleBuilder(pctx, ctx)
214 builder.Command().Textf("rm -rf %s", targetFilesDir.String())
215 builder.Command().Textf("mkdir -p %s", targetFilesDir.String())
Spandan Dasef200ac2025-01-08 01:42:45 +0000216 toCopy := []targetFilesZipCopy{
217 targetFilesZipCopy{a.partitionProps.System_partition_name, "SYSTEM"},
218 targetFilesZipCopy{a.partitionProps.System_ext_partition_name, "SYSTEM_EXT"},
219 targetFilesZipCopy{a.partitionProps.Product_partition_name, "PRODUCT"},
220 targetFilesZipCopy{a.partitionProps.Vendor_partition_name, "VENDOR"},
221 targetFilesZipCopy{a.partitionProps.Odm_partition_name, "ODM"},
222 targetFilesZipCopy{a.partitionProps.System_dlkm_partition_name, "SYSTEM_DLKM"},
223 targetFilesZipCopy{a.partitionProps.Vendor_dlkm_partition_name, "VENDOR_DLKM"},
224 targetFilesZipCopy{a.partitionProps.Odm_dlkm_partition_name, "ODM_DLKM"},
225 targetFilesZipCopy{a.partitionProps.Init_boot_partition_name, "BOOT/RAMDISK"},
226 targetFilesZipCopy{a.partitionProps.Init_boot_partition_name, "INIT_BOOT/RAMDISK"},
227 targetFilesZipCopy{a.partitionProps.Vendor_boot_partition_name, "VENDOR_BOOT/RAMDISK"},
Spandan Das25649f52025-01-07 18:09:22 +0000228 }
Spandan Dasef200ac2025-01-08 01:42:45 +0000229 // TODO: Handle cases where recovery files are copied to BOOT/ or RECOVERY/
230 // https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/Makefile;l=6211-6219?q=core%2FMakefile&ss=android%2Fplatform%2Fsuperproject%2Fmain
231 if ctx.DeviceConfig().BoardMoveRecoveryResourcesToVendorBoot() {
232 toCopy = append(toCopy, targetFilesZipCopy{a.partitionProps.Recovery_partition_name, "VENDOR_BOOT/RAMDISK"})
233 }
234
235 for _, zipCopy := range toCopy {
236 if zipCopy.srcModule == nil {
Spandan Das25649f52025-01-07 18:09:22 +0000237 continue
238 }
Spandan Dasef200ac2025-01-08 01:42:45 +0000239 fsInfo := a.getFilesystemInfo(ctx, *zipCopy.srcModule)
240 subdir := zipCopy.destSubdir
241 rootDirString := fsInfo.RootDir.String()
242 if subdir == "SYSTEM" {
243 rootDirString = rootDirString + "/system"
244 }
Spandan Das25649f52025-01-07 18:09:22 +0000245 builder.Command().Textf("mkdir -p %s/%s", targetFilesDir.String(), subdir)
Cole Faust44080412024-12-20 14:17:07 -0800246 builder.Command().
247 BuiltTool("acp").
Spandan Dasef200ac2025-01-08 01:42:45 +0000248 Textf("-rd %s/. %s/%s", rootDirString, targetFilesDir, subdir).
Cole Faust44080412024-12-20 14:17:07 -0800249 Implicit(fsInfo.Output) // so that the staging dir is built
Spandan Dasef200ac2025-01-08 01:42:45 +0000250
Cole Faust44080412024-12-20 14:17:07 -0800251 }
Spandan Das9b17df22025-01-08 23:30:45 +0000252 // Copy cmdline, kernel etc. files of boot images
Spandan Das258c08f2025-01-08 23:30:45 +0000253 if a.partitionProps.Vendor_boot_partition_name != nil {
254 bootImg := ctx.GetDirectDepWithTag(proptools.String(a.partitionProps.Vendor_boot_partition_name), filesystemDepTag)
255 bootImgInfo, _ := android.OtherModuleProvider(ctx, bootImg, BootimgInfoProvider)
Spandan Das9b17df22025-01-08 23:30:45 +0000256 builder.Command().Textf("echo %s > %s/VENDOR_BOOT/cmdline", proptools.ShellEscape(strings.Join(bootImgInfo.Cmdline, " ")), targetFilesDir)
257 builder.Command().Textf("echo %s > %s/VENDOR_BOOT/vendor_cmdline", proptools.ShellEscape(strings.Join(bootImgInfo.Cmdline, " ")), targetFilesDir)
258 if bootImgInfo.Dtb != nil {
259 builder.Command().Textf("cp %s %s/VENDOR_BOOT/dtb", bootImgInfo.Dtb, targetFilesDir)
260 }
Spandan Das23511372025-01-08 23:30:45 +0000261 if bootImgInfo.Bootconfig != nil {
262 builder.Command().Textf("cp %s %s/VENDOR_BOOT/vendor_bootconfig", bootImgInfo.Bootconfig, targetFilesDir)
263 }
Spandan Das258c08f2025-01-08 23:30:45 +0000264 }
265 if a.partitionProps.Boot_partition_name != nil {
266 bootImg := ctx.GetDirectDepWithTag(proptools.String(a.partitionProps.Boot_partition_name), filesystemDepTag)
267 bootImgInfo, _ := android.OtherModuleProvider(ctx, bootImg, BootimgInfoProvider)
Spandan Das9b17df22025-01-08 23:30:45 +0000268 builder.Command().Textf("echo %s > %s/BOOT/cmdline", proptools.ShellEscape(strings.Join(bootImgInfo.Cmdline, " ")), targetFilesDir)
269 if bootImgInfo.Dtb != nil {
270 builder.Command().Textf("cp %s %s/BOOT/dtb", bootImgInfo.Dtb, targetFilesDir)
271 }
272 if bootImgInfo.Kernel != nil {
273 builder.Command().Textf("cp %s %s/BOOT/kernel", bootImgInfo.Kernel, targetFilesDir)
274 // Even though kernel is not used to build vendor_boot, copy the kernel to VENDOR_BOOT to match the behavior of make packaging.
275 builder.Command().Textf("cp %s %s/VENDOR_BOOT/kernel", bootImgInfo.Kernel, targetFilesDir)
276 }
Spandan Das23511372025-01-08 23:30:45 +0000277 if bootImgInfo.Bootconfig != nil {
278 builder.Command().Textf("cp %s %s/BOOT/bootconfig", bootImgInfo.Bootconfig, targetFilesDir)
279 }
Spandan Das258c08f2025-01-08 23:30:45 +0000280 }
281
Cole Faust44080412024-12-20 14:17:07 -0800282 builder.Command().
283 BuiltTool("soong_zip").
284 Text("-d").
285 FlagWithOutput("-o ", targetFilesZip).
286 FlagWithArg("-C ", targetFilesDir.String()).
287 FlagWithArg("-D ", targetFilesDir.String()).
288 Text("-sha256")
289 builder.Build("target_files_"+ctx.ModuleName(), "Build target_files.zip")
290}
291
292func (a *androidDevice) getFilesystemInfo(ctx android.ModuleContext, depName string) FilesystemInfo {
293 fsMod := ctx.GetDirectDepWithTag(depName, filesystemDepTag)
294 fsInfo, ok := android.OtherModuleProvider(ctx, fsMod, FilesystemProvider)
295 if !ok {
296 ctx.ModuleErrorf("Expected dependency %s to be a filesystem", depName)
297 }
298 return fsInfo
Jihoon Kangf2c53982024-10-09 17:32:52 +0000299}