| 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) { | 
|  | 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 |  | 
|  | 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. | 
|  | 58 | func prebuiltKernelModulesFactory() android.Module { | 
|  | 59 | module := &prebuiltKernelModules{} | 
|  | 60 | module.AddProperties(&module.properties) | 
|  | 61 | android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst) | 
|  | 62 | return module | 
|  | 63 | } | 
|  | 64 |  | 
|  | 65 | func (pkm *prebuiltKernelModules) KernelVersion() string { | 
|  | 66 | return proptools.StringDefault(pkm.properties.Kernel_version, "") | 
|  | 67 | } | 
|  | 68 |  | 
|  | 69 | func (pkm *prebuiltKernelModules) DepsMutator(ctx android.BottomUpMutatorContext) { | 
|  | 70 | // do nothing | 
|  | 71 | } | 
|  | 72 |  | 
|  | 73 | func (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 |  | 
| Jiyong Park | 599992b | 2021-02-04 19:40:56 +0900 | [diff] [blame] | 79 | installDir := android.PathForModuleInstall(ctx, "lib", "modules") | 
| Jiyong Park | 6446b62 | 2021-02-01 20:08:28 +0900 | [diff] [blame] | 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 |  | 
|  | 93 | var ( | 
|  | 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 |  | 
|  | 103 | func 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 |  | 
|  | 123 | type depmodOutputs struct { | 
|  | 124 | modulesLoad    android.OutputPath | 
|  | 125 | modulesDep     android.OutputPath | 
|  | 126 | modulesSoftdep android.OutputPath | 
|  | 127 | modulesAlias   android.OutputPath | 
|  | 128 | } | 
|  | 129 |  | 
|  | 130 | func 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 | } |