Jiyong Park | 6446b62 | 2021-02-01 20:08:28 +0900 | [diff] [blame] | 1 | // Copyright (C) 2021 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 | |
| 15 | package kernel |
| 16 | |
| 17 | import ( |
| 18 | "fmt" |
| 19 | "path/filepath" |
| 20 | "strings" |
| 21 | |
| 22 | "android/soong/android" |
| 23 | _ "android/soong/cc/config" |
| 24 | |
| 25 | "github.com/google/blueprint" |
| 26 | "github.com/google/blueprint/proptools" |
| 27 | ) |
| 28 | |
| 29 | func init() { |
Jiyong Park | 6446b62 | 2021-02-01 20:08:28 +0900 | [diff] [blame] | 30 | pctx.Import("android/soong/cc/config") |
Paul Duffin | e5ac250 | 2021-03-29 01:24:49 +0100 | [diff] [blame] | 31 | registerKernelBuildComponents(android.InitRegistrationContext) |
| 32 | } |
| 33 | |
| 34 | func registerKernelBuildComponents(ctx android.RegistrationContext) { |
Spandan Das | 5e33642 | 2024-11-01 22:31:20 +0000 | [diff] [blame] | 35 | ctx.RegisterModuleType("prebuilt_kernel_modules", PrebuiltKernelModulesFactory) |
Jiyong Park | 6446b62 | 2021-02-01 20:08:28 +0900 | [diff] [blame] | 36 | } |
| 37 | |
| 38 | type prebuiltKernelModules struct { |
| 39 | android.ModuleBase |
| 40 | |
| 41 | properties prebuiltKernelModulesProperties |
| 42 | |
| 43 | installDir android.InstallPath |
| 44 | } |
| 45 | |
| 46 | type prebuiltKernelModulesProperties struct { |
| 47 | // List or filegroup of prebuilt kernel module files. Should have .ko suffix. |
| 48 | Srcs []string `android:"path,arch_variant"` |
| 49 | |
Spandan Das | eb426b7 | 2024-11-08 03:26:45 +0000 | [diff] [blame] | 50 | // List of system_dlkm kernel modules that the local kernel modules depend on. |
| 51 | // The deps will be assembled into intermediates directory for running depmod |
| 52 | // but will not be added to the current module's installed files. |
| 53 | System_deps []string `android:"path,arch_variant"` |
| 54 | |
Spandan Das | ad40292 | 2024-11-08 03:26:45 +0000 | [diff] [blame] | 55 | // If false, then srcs will not be included in modules.load. |
| 56 | // This feature is used by system_dlkm |
| 57 | Load_by_default *bool |
| 58 | |
Spandan Das | 6dfcbdf | 2024-11-11 18:43:07 +0000 | [diff] [blame] | 59 | Blocklist_file *string `android:"path"` |
| 60 | |
Jihoon Kang | c16c919 | 2024-11-27 00:59:23 +0000 | [diff] [blame] | 61 | // Path to the kernel module options file |
| 62 | Options_file *string `android:"path"` |
| 63 | |
Jiyong Park | 6446b62 | 2021-02-01 20:08:28 +0900 | [diff] [blame] | 64 | // Kernel version that these modules are for. Kernel modules are installed to |
| 65 | // /lib/modules/<kernel_version> directory in the corresponding partition. Default is "". |
| 66 | Kernel_version *string |
Inseob Kim | 6a463f8 | 2023-11-06 18:07:13 +0900 | [diff] [blame] | 67 | |
| 68 | // Whether this module is directly installable to one of the partitions. Default is true |
| 69 | Installable *bool |
Jiyong Park | 6446b62 | 2021-02-01 20:08:28 +0900 | [diff] [blame] | 70 | } |
| 71 | |
| 72 | // prebuilt_kernel_modules installs a set of prebuilt kernel module files to the correct directory. |
| 73 | // In addition, this module builds modules.load, modules.dep, modules.softdep and modules.alias |
| 74 | // using depmod and installs them as well. |
Spandan Das | 5e33642 | 2024-11-01 22:31:20 +0000 | [diff] [blame] | 75 | func PrebuiltKernelModulesFactory() android.Module { |
Jiyong Park | 6446b62 | 2021-02-01 20:08:28 +0900 | [diff] [blame] | 76 | module := &prebuiltKernelModules{} |
| 77 | module.AddProperties(&module.properties) |
| 78 | android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst) |
| 79 | return module |
| 80 | } |
| 81 | |
Inseob Kim | 6a463f8 | 2023-11-06 18:07:13 +0900 | [diff] [blame] | 82 | func (pkm *prebuiltKernelModules) installable() bool { |
| 83 | return proptools.BoolDefault(pkm.properties.Installable, true) |
| 84 | } |
| 85 | |
Jiyong Park | 6446b62 | 2021-02-01 20:08:28 +0900 | [diff] [blame] | 86 | func (pkm *prebuiltKernelModules) KernelVersion() string { |
| 87 | return proptools.StringDefault(pkm.properties.Kernel_version, "") |
| 88 | } |
| 89 | |
| 90 | func (pkm *prebuiltKernelModules) DepsMutator(ctx android.BottomUpMutatorContext) { |
| 91 | // do nothing |
| 92 | } |
| 93 | |
| 94 | func (pkm *prebuiltKernelModules) GenerateAndroidBuildActions(ctx android.ModuleContext) { |
Inseob Kim | 6a463f8 | 2023-11-06 18:07:13 +0900 | [diff] [blame] | 95 | if !pkm.installable() { |
| 96 | pkm.SkipInstall() |
| 97 | } |
Spandan Das | eb426b7 | 2024-11-08 03:26:45 +0000 | [diff] [blame] | 98 | |
Jiyong Park | 6446b62 | 2021-02-01 20:08:28 +0900 | [diff] [blame] | 99 | modules := android.PathsForModuleSrc(ctx, pkm.properties.Srcs) |
Spandan Das | eb426b7 | 2024-11-08 03:26:45 +0000 | [diff] [blame] | 100 | systemModules := android.PathsForModuleSrc(ctx, pkm.properties.System_deps) |
Jiyong Park | 6446b62 | 2021-02-01 20:08:28 +0900 | [diff] [blame] | 101 | |
Spandan Das | ad40292 | 2024-11-08 03:26:45 +0000 | [diff] [blame] | 102 | depmodOut := pkm.runDepmod(ctx, modules, systemModules) |
Jiyong Park | 6446b62 | 2021-02-01 20:08:28 +0900 | [diff] [blame] | 103 | strippedModules := stripDebugSymbols(ctx, modules) |
| 104 | |
Jiyong Park | 599992b | 2021-02-04 19:40:56 +0900 | [diff] [blame] | 105 | installDir := android.PathForModuleInstall(ctx, "lib", "modules") |
Jihoon Kang | f6b5e8f | 2024-11-27 00:33:30 +0000 | [diff] [blame] | 106 | // Kernel module is installed to vendor_ramdisk/lib/modules regardless of product |
| 107 | // configuration. This matches the behavior in make and prevents the files from being |
| 108 | // installed in `vendor_ramdisk/first_stage_ramdisk`. |
| 109 | if pkm.InstallInVendorRamdisk() { |
| 110 | installDir = android.PathForModuleInPartitionInstall(ctx, "vendor_ramdisk", "lib", "modules") |
| 111 | } |
| 112 | |
Jiyong Park | 6446b62 | 2021-02-01 20:08:28 +0900 | [diff] [blame] | 113 | if pkm.KernelVersion() != "" { |
| 114 | installDir = installDir.Join(ctx, pkm.KernelVersion()) |
| 115 | } |
| 116 | |
| 117 | for _, m := range strippedModules { |
| 118 | ctx.InstallFile(installDir, filepath.Base(m.String()), m) |
| 119 | } |
| 120 | ctx.InstallFile(installDir, "modules.load", depmodOut.modulesLoad) |
| 121 | ctx.InstallFile(installDir, "modules.dep", depmodOut.modulesDep) |
| 122 | ctx.InstallFile(installDir, "modules.softdep", depmodOut.modulesSoftdep) |
| 123 | ctx.InstallFile(installDir, "modules.alias", depmodOut.modulesAlias) |
Spandan Das | 6dfcbdf | 2024-11-11 18:43:07 +0000 | [diff] [blame] | 124 | pkm.installBlocklistFile(ctx, installDir) |
Jihoon Kang | c16c919 | 2024-11-27 00:59:23 +0000 | [diff] [blame] | 125 | pkm.installOptionsFile(ctx, installDir) |
Spandan Das | eb426b7 | 2024-11-08 03:26:45 +0000 | [diff] [blame] | 126 | |
| 127 | ctx.SetOutputFiles(modules, ".modules") |
Jiyong Park | 6446b62 | 2021-02-01 20:08:28 +0900 | [diff] [blame] | 128 | } |
| 129 | |
Spandan Das | 6dfcbdf | 2024-11-11 18:43:07 +0000 | [diff] [blame] | 130 | func (pkm *prebuiltKernelModules) installBlocklistFile(ctx android.ModuleContext, installDir android.InstallPath) { |
| 131 | if pkm.properties.Blocklist_file == nil { |
| 132 | return |
| 133 | } |
| 134 | blocklistOut := android.PathForModuleOut(ctx, "modules.blocklist") |
| 135 | |
| 136 | ctx.Build(pctx, android.BuildParams{ |
| 137 | Rule: processBlocklistFile, |
| 138 | Input: android.PathForModuleSrc(ctx, proptools.String(pkm.properties.Blocklist_file)), |
| 139 | Output: blocklistOut, |
| 140 | }) |
| 141 | ctx.InstallFile(installDir, "modules.blocklist", blocklistOut) |
| 142 | } |
| 143 | |
Jihoon Kang | c16c919 | 2024-11-27 00:59:23 +0000 | [diff] [blame] | 144 | func (pkm *prebuiltKernelModules) installOptionsFile(ctx android.ModuleContext, installDir android.InstallPath) { |
| 145 | if pkm.properties.Options_file == nil { |
| 146 | return |
| 147 | } |
| 148 | optionsOut := android.PathForModuleOut(ctx, "modules.options") |
| 149 | |
| 150 | ctx.Build(pctx, android.BuildParams{ |
| 151 | Rule: processOptionsFile, |
| 152 | Input: android.PathForModuleSrc(ctx, proptools.String(pkm.properties.Options_file)), |
| 153 | Output: optionsOut, |
| 154 | }) |
| 155 | ctx.InstallFile(installDir, "modules.options", optionsOut) |
| 156 | } |
| 157 | |
Jiyong Park | 6446b62 | 2021-02-01 20:08:28 +0900 | [diff] [blame] | 158 | var ( |
| 159 | pctx = android.NewPackageContext("android/soong/kernel") |
| 160 | |
| 161 | stripRule = pctx.AndroidStaticRule("strip", |
| 162 | blueprint.RuleParams{ |
| 163 | Command: "$stripCmd -o $out --strip-debug $in", |
| 164 | CommandDeps: []string{"$stripCmd"}, |
| 165 | }, "stripCmd") |
| 166 | ) |
| 167 | |
| 168 | func stripDebugSymbols(ctx android.ModuleContext, modules android.Paths) android.OutputPaths { |
| 169 | dir := android.PathForModuleOut(ctx, "stripped").OutputPath |
| 170 | var outputs android.OutputPaths |
| 171 | |
| 172 | for _, m := range modules { |
| 173 | stripped := dir.Join(ctx, filepath.Base(m.String())) |
| 174 | ctx.Build(pctx, android.BuildParams{ |
| 175 | Rule: stripRule, |
| 176 | Input: m, |
| 177 | Output: stripped, |
| 178 | Args: map[string]string{ |
| 179 | "stripCmd": "${config.ClangBin}/llvm-strip", |
| 180 | }, |
| 181 | }) |
| 182 | outputs = append(outputs, stripped) |
| 183 | } |
| 184 | |
| 185 | return outputs |
| 186 | } |
| 187 | |
| 188 | type depmodOutputs struct { |
| 189 | modulesLoad android.OutputPath |
| 190 | modulesDep android.OutputPath |
| 191 | modulesSoftdep android.OutputPath |
| 192 | modulesAlias android.OutputPath |
| 193 | } |
| 194 | |
Spandan Das | eb426b7 | 2024-11-08 03:26:45 +0000 | [diff] [blame] | 195 | var ( |
| 196 | // system/lib/modules/foo.ko: system/lib/modules/bar.ko |
| 197 | // will be converted to |
| 198 | // /system/lib/modules/foo.ko: /system/lib/modules/bar.ko |
| 199 | addLeadingSlashToPaths = pctx.AndroidStaticRule("add_leading_slash", |
| 200 | blueprint.RuleParams{ |
| 201 | Command: `sed -e 's|\([^: ]*lib/modules/[^: ]*\)|/\1|g' $in > $out`, |
| 202 | }, |
| 203 | ) |
Spandan Das | 6dfcbdf | 2024-11-11 18:43:07 +0000 | [diff] [blame] | 204 | // Remove empty lines. Raise an exception if line is _not_ formatted as `blocklist $name.ko` |
| 205 | processBlocklistFile = pctx.AndroidStaticRule("process_blocklist_file", |
| 206 | blueprint.RuleParams{ |
| 207 | Command: `rm -rf $out && awk <$in > $out` + |
| 208 | ` '/^#/ { print; next }` + |
| 209 | ` NF == 0 { next }` + |
| 210 | ` NF != 2 || $$1 != "blocklist"` + |
| 211 | ` { print "Invalid blocklist line " FNR ": " $$0 >"/dev/stderr";` + |
| 212 | ` exit_status = 1; next }` + |
| 213 | ` { $$1 = $$1; print }` + |
| 214 | ` END { exit exit_status }'`, |
| 215 | }, |
| 216 | ) |
Jihoon Kang | c16c919 | 2024-11-27 00:59:23 +0000 | [diff] [blame] | 217 | // Remove empty lines. Raise an exception if line is _not_ formatted as `options $name.ko` |
| 218 | processOptionsFile = pctx.AndroidStaticRule("process_options_file", |
| 219 | blueprint.RuleParams{ |
| 220 | Command: `rm -rf $out && awk <$in > $out` + |
| 221 | ` '/^#/ { print; next }` + |
| 222 | ` NF == 0 { next }` + |
| 223 | ` NF < 2 || $$1 != "options"` + |
| 224 | ` { print "Invalid options line " FNR ": " $$0 >"/dev/stderr";` + |
| 225 | ` exit_status = 1; next }` + |
| 226 | ` { $$1 = $$1; print }` + |
| 227 | ` END { exit exit_status }'`, |
| 228 | }, |
| 229 | ) |
Spandan Das | eb426b7 | 2024-11-08 03:26:45 +0000 | [diff] [blame] | 230 | ) |
| 231 | |
| 232 | // This is the path in soong intermediates where the .ko files will be copied. |
| 233 | // The layout should match the layout on device so that depmod can create meaningful modules.* files. |
| 234 | func modulesDirForAndroidDlkm(ctx android.ModuleContext, modulesDir android.OutputPath, system bool) android.OutputPath { |
| 235 | if ctx.InstallInSystemDlkm() || system { |
| 236 | // The first component can be either system or system_dlkm |
| 237 | // system works because /system/lib/modules is a symlink to /system_dlkm/lib/modules. |
| 238 | // system was chosen to match the contents of the kati built modules.dep |
| 239 | return modulesDir.Join(ctx, "system", "lib", "modules") |
| 240 | } else if ctx.InstallInVendorDlkm() { |
| 241 | return modulesDir.Join(ctx, "vendor", "lib", "modules") |
| 242 | } else if ctx.InstallInOdmDlkm() { |
| 243 | return modulesDir.Join(ctx, "odm", "lib", "modules") |
| 244 | } else { |
| 245 | // not an android dlkm module. |
| 246 | return modulesDir |
| 247 | } |
| 248 | } |
| 249 | |
Spandan Das | ad40292 | 2024-11-08 03:26:45 +0000 | [diff] [blame] | 250 | func (pkm *prebuiltKernelModules) runDepmod(ctx android.ModuleContext, modules android.Paths, systemModules android.Paths) depmodOutputs { |
Jiyong Park | 6446b62 | 2021-02-01 20:08:28 +0900 | [diff] [blame] | 251 | baseDir := android.PathForModuleOut(ctx, "depmod").OutputPath |
| 252 | fakeVer := "0.0" // depmod demands this anyway |
| 253 | modulesDir := baseDir.Join(ctx, "lib", "modules", fakeVer) |
Spandan Das | eb426b7 | 2024-11-08 03:26:45 +0000 | [diff] [blame] | 254 | modulesCpDir := modulesDirForAndroidDlkm(ctx, modulesDir, false) |
Jiyong Park | 6446b62 | 2021-02-01 20:08:28 +0900 | [diff] [blame] | 255 | |
| 256 | builder := android.NewRuleBuilder(pctx, ctx) |
| 257 | |
| 258 | // Copy the module files to a temporary dir |
Spandan Das | eb426b7 | 2024-11-08 03:26:45 +0000 | [diff] [blame] | 259 | builder.Command().Text("rm").Flag("-rf").Text(modulesCpDir.String()) |
| 260 | builder.Command().Text("mkdir").Flag("-p").Text(modulesCpDir.String()) |
Jiyong Park | 6446b62 | 2021-02-01 20:08:28 +0900 | [diff] [blame] | 261 | for _, m := range modules { |
Spandan Das | eb426b7 | 2024-11-08 03:26:45 +0000 | [diff] [blame] | 262 | builder.Command().Text("cp").Input(m).Text(modulesCpDir.String()) |
| 263 | } |
| 264 | |
| 265 | modulesDirForSystemDlkm := modulesDirForAndroidDlkm(ctx, modulesDir, true) |
| 266 | if len(systemModules) > 0 { |
| 267 | builder.Command().Text("mkdir").Flag("-p").Text(modulesDirForSystemDlkm.String()) |
| 268 | } |
| 269 | for _, m := range systemModules { |
| 270 | builder.Command().Text("cp").Input(m).Text(modulesDirForSystemDlkm.String()) |
Jiyong Park | 6446b62 | 2021-02-01 20:08:28 +0900 | [diff] [blame] | 271 | } |
| 272 | |
| 273 | // Enumerate modules to load |
| 274 | modulesLoad := modulesDir.Join(ctx, "modules.load") |
Spandan Das | ad40292 | 2024-11-08 03:26:45 +0000 | [diff] [blame] | 275 | // If Load_by_default is set to false explicitly, create an empty modules.load |
| 276 | if pkm.properties.Load_by_default != nil && !*pkm.properties.Load_by_default { |
| 277 | builder.Command().Text("rm").Flag("-rf").Text(modulesLoad.String()) |
| 278 | builder.Command().Text("touch").Output(modulesLoad) |
| 279 | } else { |
| 280 | var basenames []string |
| 281 | for _, m := range modules { |
| 282 | basenames = append(basenames, filepath.Base(m.String())) |
| 283 | } |
| 284 | builder.Command(). |
| 285 | Text("echo").Flag("\"" + strings.Join(basenames, " ") + "\""). |
| 286 | Text("|").Text("tr").Flag("\" \"").Flag("\"\\n\""). |
| 287 | Text(">").Output(modulesLoad) |
Jiyong Park | 6446b62 | 2021-02-01 20:08:28 +0900 | [diff] [blame] | 288 | } |
Jiyong Park | 6446b62 | 2021-02-01 20:08:28 +0900 | [diff] [blame] | 289 | |
| 290 | // Run depmod to build modules.dep/softdep/alias files |
| 291 | modulesDep := modulesDir.Join(ctx, "modules.dep") |
| 292 | modulesSoftdep := modulesDir.Join(ctx, "modules.softdep") |
| 293 | modulesAlias := modulesDir.Join(ctx, "modules.alias") |
Spandan Das | eb426b7 | 2024-11-08 03:26:45 +0000 | [diff] [blame] | 294 | builder.Command().Text("mkdir").Flag("-p").Text(modulesDir.String()) |
Jiyong Park | 6446b62 | 2021-02-01 20:08:28 +0900 | [diff] [blame] | 295 | builder.Command(). |
| 296 | BuiltTool("depmod"). |
| 297 | FlagWithArg("-b ", baseDir.String()). |
| 298 | Text(fakeVer). |
| 299 | ImplicitOutput(modulesDep). |
| 300 | ImplicitOutput(modulesSoftdep). |
| 301 | ImplicitOutput(modulesAlias) |
| 302 | |
| 303 | builder.Build("depmod", fmt.Sprintf("depmod %s", ctx.ModuleName())) |
| 304 | |
Spandan Das | eb426b7 | 2024-11-08 03:26:45 +0000 | [diff] [blame] | 305 | finalModulesDep := modulesDep |
| 306 | // Add a leading slash to paths in modules.dep of android dlkm |
| 307 | if ctx.InstallInSystemDlkm() || ctx.InstallInVendorDlkm() || ctx.InstallInOdmDlkm() { |
| 308 | finalModulesDep := modulesDep.ReplaceExtension(ctx, "intermediates") |
| 309 | ctx.Build(pctx, android.BuildParams{ |
| 310 | Rule: addLeadingSlashToPaths, |
| 311 | Input: modulesDep, |
| 312 | Output: finalModulesDep, |
| 313 | }) |
| 314 | } |
| 315 | |
| 316 | return depmodOutputs{modulesLoad, finalModulesDep, modulesSoftdep, modulesAlias} |
Jiyong Park | 6446b62 | 2021-02-01 20:08:28 +0900 | [diff] [blame] | 317 | } |