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 15package kernel 16 17import ( 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 29func init() { 30 pctx.Import("android/soong/cc/config") 31 registerKernelBuildComponents(android.InitRegistrationContext) 32} 33 34func registerKernelBuildComponents(ctx android.RegistrationContext) { 35 ctx.RegisterModuleType("prebuilt_kernel_modules", prebuiltKernelModulesFactory) 36} 37 38type prebuiltKernelModules struct { 39 android.ModuleBase 40 41 properties prebuiltKernelModulesProperties 42 43 installDir android.InstallPath 44} 45 46type prebuiltKernelModulesProperties struct { 47 // List or filegroup of prebuilt kernel module files. Should have .ko suffix. 48 Srcs []string `android:"path,arch_variant"` 49 50 // Kernel version that these modules are for. Kernel modules are installed to 51 // /lib/modules/<kernel_version> directory in the corresponding partition. Default is "". 52 Kernel_version *string 53} 54 55// prebuilt_kernel_modules installs a set of prebuilt kernel module files to the correct directory. 56// In addition, this module builds modules.load, modules.dep, modules.softdep and modules.alias 57// using depmod and installs them as well. 58func prebuiltKernelModulesFactory() android.Module { 59 module := &prebuiltKernelModules{} 60 module.AddProperties(&module.properties) 61 android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst) 62 return module 63} 64 65func (pkm *prebuiltKernelModules) KernelVersion() string { 66 return proptools.StringDefault(pkm.properties.Kernel_version, "") 67} 68 69func (pkm *prebuiltKernelModules) DepsMutator(ctx android.BottomUpMutatorContext) { 70 // do nothing 71} 72 73func (pkm *prebuiltKernelModules) GenerateAndroidBuildActions(ctx android.ModuleContext) { 74 modules := android.PathsForModuleSrc(ctx, pkm.properties.Srcs) 75 76 depmodOut := runDepmod(ctx, modules) 77 strippedModules := stripDebugSymbols(ctx, modules) 78 79 installDir := android.PathForModuleInstall(ctx, "lib", "modules") 80 if pkm.KernelVersion() != "" { 81 installDir = installDir.Join(ctx, pkm.KernelVersion()) 82 } 83 84 for _, m := range strippedModules { 85 ctx.InstallFile(installDir, filepath.Base(m.String()), m) 86 } 87 ctx.InstallFile(installDir, "modules.load", depmodOut.modulesLoad) 88 ctx.InstallFile(installDir, "modules.dep", depmodOut.modulesDep) 89 ctx.InstallFile(installDir, "modules.softdep", depmodOut.modulesSoftdep) 90 ctx.InstallFile(installDir, "modules.alias", depmodOut.modulesAlias) 91} 92 93var ( 94 pctx = android.NewPackageContext("android/soong/kernel") 95 96 stripRule = pctx.AndroidStaticRule("strip", 97 blueprint.RuleParams{ 98 Command: "$stripCmd -o $out --strip-debug $in", 99 CommandDeps: []string{"$stripCmd"}, 100 }, "stripCmd") 101) 102 103func stripDebugSymbols(ctx android.ModuleContext, modules android.Paths) android.OutputPaths { 104 dir := android.PathForModuleOut(ctx, "stripped").OutputPath 105 var outputs android.OutputPaths 106 107 for _, m := range modules { 108 stripped := dir.Join(ctx, filepath.Base(m.String())) 109 ctx.Build(pctx, android.BuildParams{ 110 Rule: stripRule, 111 Input: m, 112 Output: stripped, 113 Args: map[string]string{ 114 "stripCmd": "${config.ClangBin}/llvm-strip", 115 }, 116 }) 117 outputs = append(outputs, stripped) 118 } 119 120 return outputs 121} 122 123type depmodOutputs struct { 124 modulesLoad android.OutputPath 125 modulesDep android.OutputPath 126 modulesSoftdep android.OutputPath 127 modulesAlias android.OutputPath 128} 129 130func runDepmod(ctx android.ModuleContext, modules android.Paths) depmodOutputs { 131 baseDir := android.PathForModuleOut(ctx, "depmod").OutputPath 132 fakeVer := "0.0" // depmod demands this anyway 133 modulesDir := baseDir.Join(ctx, "lib", "modules", fakeVer) 134 135 builder := android.NewRuleBuilder(pctx, ctx) 136 137 // Copy the module files to a temporary dir 138 builder.Command().Text("rm").Flag("-rf").Text(modulesDir.String()) 139 builder.Command().Text("mkdir").Flag("-p").Text(modulesDir.String()) 140 for _, m := range modules { 141 builder.Command().Text("cp").Input(m).Text(modulesDir.String()) 142 } 143 144 // Enumerate modules to load 145 modulesLoad := modulesDir.Join(ctx, "modules.load") 146 var basenames []string 147 for _, m := range modules { 148 basenames = append(basenames, filepath.Base(m.String())) 149 } 150 builder.Command(). 151 Text("echo").Flag("\"" + strings.Join(basenames, " ") + "\""). 152 Text("|").Text("tr").Flag("\" \"").Flag("\"\\n\""). 153 Text(">").Output(modulesLoad) 154 155 // Run depmod to build modules.dep/softdep/alias files 156 modulesDep := modulesDir.Join(ctx, "modules.dep") 157 modulesSoftdep := modulesDir.Join(ctx, "modules.softdep") 158 modulesAlias := modulesDir.Join(ctx, "modules.alias") 159 builder.Command(). 160 BuiltTool("depmod"). 161 FlagWithArg("-b ", baseDir.String()). 162 Text(fakeVer). 163 ImplicitOutput(modulesDep). 164 ImplicitOutput(modulesSoftdep). 165 ImplicitOutput(modulesAlias) 166 167 builder.Build("depmod", fmt.Sprintf("depmod %s", ctx.ModuleName())) 168 169 return depmodOutputs{modulesLoad, modulesDep, modulesSoftdep, modulesAlias} 170} 171