When enabling new drivers in GKI kernels, the kernel build system forces us to build them as "Loadable Kernel Modules" (LKMs) instead of inline drivers.
On some devices (particularly certain OnePlus models), even after placing custom LKMs in the vendor_dlkm partition and properly configuring the module files (modules.load, modules.dep, modules.alias, etc.), the phone still refuses to load them.
In such cases, manually using insmod through the terminal doesn't work correctly due to dependency issues.
This Magisk module mimics the default kernel module loading behavior, allowing developers to ship their custom .ko modules as a Magisk module.

Loading all the modules by pressing the "Action" button.

Listing loaded kernel modules via lsmod
This module offers two loading modes:
- Auto-load during boot: Select "yes" during installation to automatically load all LKMs at boot time
- Manual load: Select "no" during installation to manually load LKMs using the "Action" button in KernelSU/Magisk/AP Managers after Android finishes booting
-
Packaging
- ✅ Works: Custom kernel + matching custom .ko modules (built together)
- ❌ Won't work: Stock kernel + custom .ko modules
- ❌ Won't work: Different custom kernel + .ko modules from another kernel
Install the required dependencies:
sudo apt install kmod binutils-aarch64-linux-gnu -yImportant: Fully compile your kernel before proceeding.
Navigate to your kernel root directory and create a staging folder:
mkdir -p stagingCopy all .ko modules to the staging folder:
for i in $(find . -name "*.ko"); do cp -ar $i staging/ ; doneCopy these files from your kernel root or out directory to the staging folder:
System.mapModule.symversmodules.builtinmodules.order
If you only want specific modules:
- Open the
stagingfolder - Identify the modules that were compiled after enabling
CONFIG_XXXX=m - Copy those specific modules to a separate new folder
Note: Skip this step if you want to package all modules.
- Create a new folder to store your packaged modules (e.g.,
my_packaged_modules) - Clone the LKM_Tools repository:
git clone https://github.com/ravindu644/LKM_Tools.gitNavigate to the LKM_Tools directory and run:
./04.prepare_only_nethunter_modules.shThe script will prompt you for:
- NetHunter modules directory:
- If you completed Step 3: Path to your manually copied modules folder
- If you skipped Step 3: Path to your
stagingfolder
- Kernel build staging directory: Path to your
stagingfolder - vendor_boot.img's modules_list.txt: Press Enter to skip (not needed for non-GKI kernels)
- System.map file: Path to
System.mapin your staging folder - Output directory: Where to save the organized modules (e.g.,
my_packaged_modules) - Strip tool path: Get this with
which aarch64-linux-gnu-strip
Copy all contents from your output directory to:
LKM_Loader/system/vendor/lib/modules/custom/
GKI kernels are more complex because modules are distributed across two partitions with specific dependencies.
vendor_boot Partition:
- Contains essential modules needed for device boot and recovery
- Not accessible from Android userspace
- Usually contains vendor-independent, generic modules
- Examples: Basic drivers needed for the device to start
vendor_dlkm Partition:
- Contains the majority of kernel modules
- Includes vendor-specific and SoC-dependent modules
- Accessible from Android userspace
- This is where your custom modules should go
Some modules in vendor_dlkm depend on modules located in vendor_boot.
Example: ath.ko (in vendor_dlkm) may depend on mac80211.ko (in vendor_boot)
To handle these cross-partition dependencies correctly, we need to extract the module information from vendor_boot and generate a module list.
In GKI build environments, the staging folder is typically located at:
${KERNEL_ROOT}/out/target/product/<your_product_name>/obj/KERNEL_OBJ/staging
You need to obtain the modules.dep file from your device's vendor_boot partition:
Option A: Extract from stock ROM
- Download your device's stock ROM package
- Extract the
vendor_boot.imgfile
Option B: Dump from device (requires root)
dd if=/dev/block/by-name/vendor_boot of=/sdcard/vendor_boot.imgUnpack the image:
- Use Android_boot_image_editor to unpack
vendor_boot.img - Locate and extract the
modules.depfile - Save it to your PC for the next step
- Create a new folder to store your packaged modules (e.g.,
my_packaged_modules) - Clone the LKM_Tools repository:
git clone https://github.com/ravindu644/LKM_Tools.git- Navigate to the
LKM_Toolsdirectory - Run the first script to generate
modules_list.txtfrom yourvendor_bootmodules.depfile
- Open your GKI staging directory
- Identify the modules that were compiled after enabling
CONFIG_XXXX=m - Copy those specific modules to a separate folder
- Important: Only copy the modules you actually need, not all modules
Navigate to the LKM_Tools directory and run:
./04.prepare_only_nethunter_modules.shThe script will prompt you for:
- NetHunter modules directory: Path to your custom modules folder from Step 4
- Kernel build staging directory: Path to your GKI staging folder
- vendor_boot.img's modules_list.txt: Path to the
modules_list.txtgenerated in Step 3 - System.map file: Path to
System.mapin your staging folder - Output directory: Where to save the organized modules (e.g.,
my_packaged_modules) - Strip tool path: Get this with
which aarch64-linux-gnu-strip
The script creates two separate folders in your output directory:
vendor_boot- Contains modules that belong in the vendor_boot partitionvendor_dlkm- Contains modules for the vendor_dlkm partition
For the Magisk Module:
Copy the files from vendor_dlkm/lib/modules/<kernel_version> folder to:
LKM_Loader/system/vendor/lib/modules/custom/
For vendor_boot modules (if any exist):
- Navigate to the
vendor_bootfolder in your output directory - Copy any
.komodules found there - Replace the corresponding modules in your unpacked
vendor_boot.img(from Step 2) - Use Android_boot_image_editor to repack the
vendor_boot.img - Keep this modified
vendor_boot.imgready for flashing
Your final structure should look like this:
LKM_Loader/system/
├── bin/
│ └── keycheck
└── vendor/
└── lib/
└── modules/
└── custom/
├── your_module1.ko
├── your_module2.ko
├── modules.alias
├── modules.dep
├── modules.devname
├── modules.load
├── modules.order
├── modules.softdep
├── modules.symbols
└── modules.weakdep
-
Place your
.kofiles and module configuration files located insideoutput_folder/vendor_dlkm/lib/modules/<kernel_version> folder totheLKM_Loader/system/vendor/lib/modules/custom/folder -
Zip the entire
LKM_Loaderdirectory -
This creates an installable Magisk module
- Copy the zip file to your phone
- Install it through Magisk Manager
- During installation, use the volume keys to choose your preferred loading mode:
- Volume Up (Yes): Auto-load modules at boot
- Volume Down (No): Manual load using Action button
- Do not reboot yet after installation
Only for GKI kernels with vendor_boot modules:
-
Immediately after installing the Magisk module, boot into fastboot mode:
adb reboot bootloader
Or use hardware buttons to enter fastboot/download mode
-
Flash your modified
vendor_boot.img:fastboot flash vendor_boot vendor_boot.img
-
Reboot your device:
fastboot reboot
- Auto-load mode: Your modules should load automatically at boot
- Manual load mode: Use the Action button in Magisk Manager when you need the modules
- Modules fail to load: Ensure kernel and modules were built together
- GKI-specific issues:
- Ensure you flashed the modified
vendor_boot.imgafter installing the Magisk module
- Ensure you flashed the modified
vendor_boot.img immediately after installing the Magisk module, before the first reboot. This ensures both partition modifications are applied together.
💡 Backup: Always keep a backup of your original vendor_boot.img before flashing the modified version.