Build and install modules.blocklist in prebuilt_kernel_modules

This ports `build-image-kernel-modules-blocklist-file` to Soong

fsgen has been updated to set this property on the autogenerated dlkm
filesystem modules.

Test: verified that /vendor_dlkm/lib/modules.blocklist is same between
kati and soong built vendor_dlkm
Bug: 377562851
Bug: 377362016

Change-Id: I99425b8cc48128ac72aaad5a3fa09bf8e3a015eb
diff --git a/fsgen/filesystem_creator.go b/fsgen/filesystem_creator.go
index 9cada0b..d9b2973 100644
--- a/fsgen/filesystem_creator.go
+++ b/fsgen/filesystem_creator.go
@@ -267,6 +267,7 @@
 		Vendor_dlkm_specific *bool
 		Odm_dlkm_specific    *bool
 		Load_by_default      *bool
+		Blocklist_file       *string
 	}{
 		Name: proptools.StringPtr(name),
 	}
@@ -279,15 +280,24 @@
 			// https://source.corp.google.com/h/googleplex-android/platform/build/+/ef55daac9954896161b26db4f3ef1781b5a5694c:core/Makefile;l=695-700;drc=549fe2a5162548bd8b47867d35f907eb22332023;bpv=1;bpt=0
 			props.Load_by_default = proptools.BoolPtr(false)
 		}
+		if blocklistFile := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.SystemKernelBlocklistFile; blocklistFile != "" {
+			props.Blocklist_file = proptools.StringPtr(blocklistFile)
+		}
 	case "vendor_dlkm":
 		props.Srcs = ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.VendorKernelModules
 		if len(ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.SystemKernelModules) > 0 {
 			props.System_deps = []string{":" + generatedModuleName(ctx.Config(), "system_dlkm-kernel-modules") + "{.modules}"}
 		}
 		props.Vendor_dlkm_specific = proptools.BoolPtr(true)
+		if blocklistFile := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.VendorKernelBlocklistFile; blocklistFile != "" {
+			props.Blocklist_file = proptools.StringPtr(blocklistFile)
+		}
 	case "odm_dlkm":
 		props.Srcs = ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.OdmKernelModules
 		props.Odm_dlkm_specific = proptools.BoolPtr(true)
+		if blocklistFile := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.OdmKernelBlocklistFile; blocklistFile != "" {
+			props.Blocklist_file = proptools.StringPtr(blocklistFile)
+		}
 	default:
 		ctx.ModuleErrorf("DLKM is not supported for %s\n", partitionType)
 	}
diff --git a/kernel/prebuilt_kernel_modules.go b/kernel/prebuilt_kernel_modules.go
index 78a463f..13d6482 100644
--- a/kernel/prebuilt_kernel_modules.go
+++ b/kernel/prebuilt_kernel_modules.go
@@ -56,6 +56,8 @@
 	// This feature is used by system_dlkm
 	Load_by_default *bool
 
+	Blocklist_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
@@ -109,10 +111,25 @@
 	ctx.InstallFile(installDir, "modules.dep", depmodOut.modulesDep)
 	ctx.InstallFile(installDir, "modules.softdep", depmodOut.modulesSoftdep)
 	ctx.InstallFile(installDir, "modules.alias", depmodOut.modulesAlias)
+	pkm.installBlocklistFile(ctx, installDir)
 
 	ctx.SetOutputFiles(modules, ".modules")
 }
 
+func (pkm *prebuiltKernelModules) installBlocklistFile(ctx android.ModuleContext, installDir android.InstallPath) {
+	if pkm.properties.Blocklist_file == nil {
+		return
+	}
+	blocklistOut := android.PathForModuleOut(ctx, "modules.blocklist")
+
+	ctx.Build(pctx, android.BuildParams{
+		Rule:   processBlocklistFile,
+		Input:  android.PathForModuleSrc(ctx, proptools.String(pkm.properties.Blocklist_file)),
+		Output: blocklistOut,
+	})
+	ctx.InstallFile(installDir, "modules.blocklist", blocklistOut)
+}
+
 var (
 	pctx = android.NewPackageContext("android/soong/kernel")
 
@@ -159,6 +176,19 @@
 			Command: `sed -e 's|\([^: ]*lib/modules/[^: ]*\)|/\1|g' $in > $out`,
 		},
 	)
+	// Remove empty lines. Raise an exception if line is _not_ formatted as `blocklist $name.ko`
+	processBlocklistFile = pctx.AndroidStaticRule("process_blocklist_file",
+		blueprint.RuleParams{
+			Command: `rm -rf $out && awk <$in > $out` +
+				` '/^#/ { print; next }` +
+				` NF == 0 { next }` +
+				` NF != 2 || $$1 != "blocklist"` +
+				` { print "Invalid blocklist line " FNR ": " $$0 >"/dev/stderr";` +
+				` exit_status = 1; next }` +
+				` { $$1 = $$1; print }` +
+				` END { exit exit_status }'`,
+		},
+	)
 )
 
 // This is the path in soong intermediates where the .ko files will be copied.