blob: de88aaa402c839617a8e4830bdbc4c4fed77a540 [file]
// Copyright (C) 2021 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package kernel
import (
"android/soong/android"
"android/soong/cc/config"
"android/soong/kernel/common"
"github.com/google/blueprint/proptools"
)
var (
pctx = android.NewPackageContext("android/soong/kernel")
)
func init() {
pctx.Import("android/soong/android")
pctx.Import("android/soong/cc/config")
registerKernelBuildComponents(android.InitRegistrationContext)
}
func registerKernelBuildComponents(ctx android.RegistrationContext) {
ctx.RegisterModuleType("prebuilt_kernel_modules", PrebuiltKernelModulesFactory)
}
var PrepareForTestWithPrebuiltKernelModules = android.FixtureRegisterWithContext(registerKernelBuildComponents)
type prebuiltKernelModules struct {
android.ModuleBase
properties PrebuiltKernelModulesProperties
}
type PrebuiltKernelModulesProperties struct {
// List or filegroup of prebuilt kernel module files. Should have .ko suffix.
Srcs proptools.Configurable[[]string] `android:"path,arch_variant"`
// List of kernel module filenames that will be loaded via modules.load.
// Should have .ko suffix.
// If empty, this will default to filenames of Srcs.
// If no sources should be loaded, set `Load_by_default` to false instead.
Src_filenames_to_load []string `android:"path,arch_variant"`
// List or filegroup of prebuilt kernel module files for 16k. Should have .ko suffix.
// These files will be installed in lib/modules/16k-mode/
// These files are ONLY loaded during the Second Boot Stage when the device is in 16k mode.
Srcs_16k []string `android:"path,arch_variant"`
// List of system_dlkm prebuilt_kernel_modules that the local kernel modules
// depend on. Use `:module_name{.modules.zip}` here.
// The deps will be assembled into intermediates directory for running depmod
// but will not be added to the current module's installed files.
System_dep *string `android:"path,arch_variant"`
// If false, then srcs will not be included in modules.load.
// This feature is used by system_dlkm
Load_by_default *bool
Blocklist_file *string `android:"path"`
// Path to the kernel module options file
Options_file *string `android:"path"`
// Kernel version that these modules are for. Kernel modules are installed to
// /lib/modules/<kernel_version> directory in the corresponding partition. Default is "".
Kernel_version *string
// Whether this module is directly installable to one of the partitions. Default is true
Installable *bool
// Whether debug symbols should be stripped from the *.ko files.
// Defaults to true.
Strip_debug_symbols *bool
// Properties related to loading the kernel modules from a zip file.
// This is useful if you want the list of kernel modules to be dynamic, and unknown at analysis
// time, for example when supplying the kernel modules via CIPD.
//
// Most of these properties are mutually exclusive with the other, non-zip properties. But
// some such as srcs will be merged with the contents / information from the zip file.
Zip struct {
// The zip file containing the kernel modules and other files like the load/blocklist files.
Src *string `android:"path,arch_variant"`
// The name of the load file inside of the zip file. Only modules listed in it will
// be installed.
Load_file *string
// List of extra kernel modules to add to the load file.
Extra_loads []string
// The name of the blocklist file inside of the zip file.
Blocklist_file *string
// Name of a .cfg file inside of the zip that's loaded by init.insmod.sh. This is just used
// to determine the list of 16k kernel modules, taken from all the modprobe| lines
// in the cfg file.
Srcs_16k_cfg_file *string
}
}
func (p *PrebuiltKernelModulesProperties) resolve(ctx android.ModuleContext, command *android.RuleBuilderCommand) common.PrebuiltKernelModulesPropertiesJSON {
var systemDep *string
if p.System_dep != nil {
systemDep = proptools.StringPtr(command.PathForInputFromFile(android.PathForModuleSrc(ctx, *p.System_dep)))
}
var zip *string
if p.Zip.Src != nil {
zip = proptools.StringPtr(command.PathForInputFromFile(android.PathForModuleSrc(ctx, *p.Zip.Src)))
}
var blocklistFile *string
if p.Blocklist_file != nil {
blocklistFile = proptools.StringPtr(command.PathForInputFromFile(android.PathForModuleSrc(ctx, *p.Blocklist_file)))
}
var optionsFile *string
if p.Options_file != nil {
optionsFile = proptools.StringPtr(command.PathForInputFromFile(android.PathForModuleSrc(ctx, *p.Options_file)))
}
var srcs []string
for _, src := range android.PathsForModuleSrc(ctx, p.Srcs.GetOrDefault(ctx, nil)) {
srcs = append(srcs, command.PathForInputFromFile(src))
}
var srcs_16k []string
for _, src := range android.PathsForModuleSrc(ctx, p.Srcs_16k) {
srcs_16k = append(srcs_16k, command.PathForInputFromFile(src))
}
return common.PrebuiltKernelModulesPropertiesJSON{
Srcs: srcs,
Src_filenames_to_load: p.Src_filenames_to_load,
Srcs_16k: srcs_16k,
System_dep: systemDep,
Load_by_default: p.Load_by_default,
Blocklist_file: blocklistFile,
Options_file: optionsFile,
Kernel_version: p.Kernel_version,
Installable: p.Installable,
Strip_debug_symbols: p.Strip_debug_symbols,
Zip: common.ZipProperties{
Src: zip,
Load_file: p.Zip.Load_file,
Extra_loads: p.Zip.Extra_loads,
Blocklist_file: p.Zip.Blocklist_file,
Srcs_16k_cfg_file: p.Zip.Srcs_16k_cfg_file,
},
}
}
// prebuilt_kernel_modules installs a set of prebuilt kernel module files to the correct directory.
// In addition, this module builds modules.load, modules.dep, modules.softdep and modules.alias
// using depmod and installs them as well.
func PrebuiltKernelModulesFactory() android.Module {
module := &prebuiltKernelModules{}
module.AddProperties(&module.properties)
android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
return module
}
func (pkm *prebuiltKernelModules) installable() bool {
return proptools.BoolDefault(pkm.properties.Installable, true)
}
func (pkm *prebuiltKernelModules) KernelVersion() string {
return proptools.StringDefault(pkm.properties.Kernel_version, "")
}
func (pkm *prebuiltKernelModules) DepsMutator(ctx android.BottomUpMutatorContext) {
ctx.AddHostToolDependencies("kernel_modules_builder", "zipsync", "soong_zip", "merge_zips", "depmod")
}
func (pkm *prebuiltKernelModules) GenerateAndroidBuildActions(ctx android.ModuleContext) {
if !pkm.installable() {
pkm.SkipInstall()
}
var deps []android.Path
deps = append(deps, android.PathsForModuleSrc(ctx, pkm.properties.Srcs.GetOrDefault(ctx, nil))...)
deps = append(deps, android.PathsForModuleSrc(ctx, pkm.properties.Srcs_16k)...)
systemModulesZip := android.OptionalPathForModuleSrc(ctx, pkm.properties.System_dep)
if systemModulesZip.Valid() {
deps = append(deps, systemModulesZip.Path())
}
blocklistFile := android.OptionalPathForModuleSrc(ctx, pkm.properties.Blocklist_file)
if blocklistFile.Valid() {
deps = append(deps, blocklistFile.Path())
}
optionsFile := android.OptionalPathForModuleSrc(ctx, pkm.properties.Options_file)
if optionsFile.Valid() {
deps = append(deps, optionsFile.Path())
}
if proptools.String(pkm.properties.Zip.Src) != "" {
deps = append(deps, android.PathForModuleSrc(ctx, *pkm.properties.Zip.Src))
}
propsFile := android.PathForModuleOut(ctx, "props.json")
sboxDir := android.PathForModuleOut(ctx, "sbox")
sboxManifest := android.PathForModuleOut(ctx, "sbox.manifest")
loadFile := sboxDir.Join(ctx, "modules.load")
installsZip := sboxDir.Join(ctx, "installs.zip")
tempDir := sboxDir.Join(ctx, "temp")
builder := android.NewRuleBuilder(pctx, ctx).
SandboxDisabled().
Sbox(sboxDir, sboxManifest)
llvmStrip := config.ClangPath(ctx, "bin/llvm-strip")
// llvm-strip is a symlink to llvm-objcopy
llvmObjcopy := config.ClangPath(ctx, "bin/llvm-objcopy")
llvmLib := config.ClangPath(ctx, "lib/x86_64-unknown-linux-gnu/libc++.so")
cmd := builder.Command()
props := pkm.properties.resolve(ctx, cmd)
android.WriteFileRule(ctx, propsFile, props.ToJSON())
cmd.BuiltTool("kernel_modules_builder").
Flag("--soong_zip").BuiltTool("soong_zip").
Flag("--zipsync").BuiltTool("zipsync").
Flag("--merge_zips").BuiltTool("merge_zips").
Flag("--depmod").BuiltTool("depmod").
Flag("--llvm-strip").Input(llvmStrip).Implicit(llvmLib).Implicit(llvmObjcopy).
// depmod needs libc++
// TODO: Get this from the depmod dep automatically
ImplicitTool(ctx.Config().HostCcSharedLibPath(ctx, "libc++")).
Input(propsFile).
Text(partition(ctx)).
Text(tempDir.String()).
Output(loadFile).
Output(installsZip).
Implicits(deps)
builder.Build("zip_modules", "zip kernel modules")
installDir := android.PathForModuleInstall(ctx, "lib", "modules")
// Kernel module is installed to vendor_ramdisk/lib/modules regardless of product
// configuration. This matches the behavior in make and prevents the files from being
// installed in `vendor_ramdisk/first_stage_ramdisk`.
if pkm.InstallInVendorRamdisk() {
installDir = android.PathForModuleInPartitionInstall(ctx, "vendor_ramdisk", "lib", "modules")
} else if pkm.InstallInVendorKernelRamdisk() {
installDir = android.PathForModuleInPartitionInstall(ctx, "vendor_kernel_ramdisk", "lib", "modules")
}
if pkm.KernelVersion() != "" {
installDir = installDir.Join(ctx, pkm.KernelVersion())
}
var dests []string
var srcs []string
// Use ANDROID-GEN to identify the source of module.* files which are generated in the build process.
// See the use of ANDROID-GEN in build/make/core/Makefile
androidGen := "ANDROID-GEN"
// Add ANDROID-GEN once to match the modules.load file in dests
srcs = append(srcs, androidGen)
installPath := ctx.InstallFileWithExtraFilesZip(installDir, "modules.load", loadFile, installsZip)
dests = append(dests, installPath.String())
ctx.SetOutputFiles(android.Paths{installsZip}, ".modules.zip")
// TODO(b/466436522): we no longer include the files in the zip file here.
android.SetProvider(ctx, android.PrebuiltKernelModulesComplianceMetadataProvider,
android.PrebuiltKernelModulesComplianceMetadata{
Srcs: srcs,
Dests: dests,
})
}
// Return a string representation of the dlkm partition this module is installed on,
// for the kernel_modules_builder tool.
func partition(ctx android.ModuleContext) string {
if ctx.InstallInSystemDlkm() {
return "system_dlkm"
} else if ctx.InstallInVendorDlkm() {
return "vendor_dlkm"
} else if ctx.InstallInOdmDlkm() {
return "odm_dlkm"
} else if ctx.InstallInVendorRamdisk() {
return "vendor_ramdisk"
} else if ctx.InstallInVendorKernelRamdisk() {
return "vendor_kernel_ramdisk"
} else {
// not an android dlkm module.
return "other"
}
}