Open-source project
msm8916-mainline/lk2nd avatar
msm8916-mainline/lk2nd

lk2nd: a unified bootloader for Qualcomm devices running something other than Android

Custom bootloader for Qualcomm MSM8916/MSM8226/MSM8974/... devices

627 stars504 forksCNOASSERTION

At a glance

What is it?
lk2nd is a custom bootloader for Qualcomm SoCs that provides a single Android Fastboot interface across many phones, tablets, watches and boards, with automatic hardware detection and workarounds for device-specific problems. It can run as a secondary bootloader packed into an Android boot image, or as a primary bootloader on single-board computers.
Who is it for?
lk2nd suits an embedded developer who wants to run a non-Android operating system, such as postmarketOS, on a Qualcomm phone or tablet, and who would rather work with one flashing interface than with each vendor's proprietary one.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 3 days ago.
What is it written in?
Mainly C, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

One fastboot interface across many Qualcomm devices

lk2nd is a custom bootloader for many different devices based on Qualcomm system-on-chips, including smartphones, tablets, smartwatches and a few single board computers. The problem it solves is stated in the README's list of what it provides. First, a unified boot and flashing interface using Android Fastboot, independent of device-specific modifications made to the boot chain, with the proprietary flashing interface on Samsung devices given as the example. Second, automatic device and hardware detection, covering display panels and batteries. Third, additional bootloader features such as file system boot and booting from an SD card. Fourth, additional firmware features, such as booting secondary CPU cores when the firmware lacks PSCI support. Fifth, workarounds for device-specific issues, with USB on some Samsung devices and the modem on Motorola smartphones named. And sixth, various debugging commands that allow better understanding of the hardware for research and development purposes. The point of the unification is that a developer who has learned fastboot once can flash and boot the same way on a device whose vendor would otherwise have provided a different tool.

Two configurations, and what changes between them

There are two different configurations and the distinction decides whether the tool fits your device. The lk2nd configuration is the secondary bootloader, intended for devices where the existing firmware cannot be replaced easily, which is most smartphones and tablets. In that configuration lk2nd does not replace the stock bootloader. Instead it is packed into an Android boot image, which is then loaded by the stock bootloader just like the original Android image. The real operating system can be placed in the boot partition with a 512 KiB offset, or stored in an ext2 file system. The README is explicit that the payload does not have to be Android or even Linux, because any kind of kernel can be packed into an Android boot image. The lk1st configuration is the primary bootloader, intended for single-board computers and expert users, and in that case it is the first bootloader responsible for loading the main operating system. The repository is a fork of the original open-source bootloader from Qualcomm, itself a heavily modified version of the Little Kernel Embedded Operating System.

Installing it, and the partition offset trap

Installation is a download and a flash. You download lk2nd.img from the releases, and flash it with the stock flashing interface, either through fastboot with fastboot flash boot lk2nd.img or through Samsung's tool with heimdall flash --BOOT lk2nd.img. If fastboot reports it could not parse partition size 0x, the README gives two workarounds, flashing as a raw partition or booting lk2nd first and then flashing it to the lk2nd partition, and there is also an EDL route with edl w boot lk2nd.img. The trap is the next paragraph, and it is the single most important line in the documentation. The command fastboot flash boot boot.img will flash the actual boot image with a 512 KiB offset into the boot partition, and this is done to avoid replacing lk2nd, since lk2nd is also booted from the boot partition. So the 512 KiB offset is not a detail of the layout, it is the mechanism that lets the stock bootloader keep working while your own system sits behind it. Press Volume Down while booting to enter fastboot mode and Volume Up to boot into Recovery, with a tip that if your stock bootloader uses the same key combinations you need to wait until the screen turns on or the device vibrates so the stock bootloader ignores the keys.

Updating lk2nd and pulling logs

Two day-to-day operations are documented. For updating, fastboot flash lk2nd lk2nd.img updates lk2nd directly from its own fastboot interface, and other fastboot commands work normally. For diagnostics, if the device shows up via fastboot you can get a log file from lk2nd with fastboot oem log followed by fastboot get_staged pointing at an output file, which can be a text file such as output.txt or /dev/stdout to write the log to standard output. The ability to write to standard output is the useful detail for anyone working over a serial console, because it means the log does not have to be staged to the device's storage and retrieved afterwards. The combination of a unified fastboot interface, a staged log mechanism and the debugging commands in the feature list is what makes this usable for the research and development purpose the README names, rather than only for the flashing.

Building it from source for a specific chipset

The build is a make invocation with a toolchain prefix and a target named after the SoC:

bash
$ make TOOLCHAIN_PREFIX=arm-none-eabi- lk2nd-msmXXXX

The target name carries the chipset identifier, so the example lk2nd-msmXXXX is a placeholder for whichever SoC you are building for, and the toolchain prefix points at an arm-none-eabi cross compiler. The README says that generally this should be enough to build lk2nd and points to the building documentation for more, and the repository layout is consistent with a multi-target build. There is a target/ directory for the per-chipset build definitions, a project/ directory, platform/ and arch/ directories for the hardware layers, a kernel/ directory and the lk2nd/ application directory itself, an app/ directory, a make/ directory of makefile fragments, and a top-level makefile with an AndroidBoot.mk for the Android build path. The presence of both a GNU make build and an AndroidBoot.mk is the clearest signal of the two audiences the project serves, the Linux embedded developer and the Android builder.

Where the custom bootloader stops being the right answer

The limits are structural and they are worth being blunt about. lk2nd starts from a device whose bootloader you can already flash, so a device with a locked or unflashable bootloader is out of scope, and no amount of lk2nd changes that because the whole chain begins with the vendor's own fastboot accepting an image. Second, the support surface is device-specific even though the interface is unified, since the automatic detection of panels and batteries and the workarounds for USB and modem issues are all per-model work, and the README points to a comprehensive device list in Documentation/devices.md rather than claiming coverage. A chipset that is not on that list means writing the hardware support yourself, which is a substantial task rather than a configuration step. Third, the lk1st configuration, the primary bootloader, is explicitly for single-board computers and expert users, so it is not the tool for a phone where the stock bootloader must stay in place. The practical alternative for most people is a device that already has a mainline-supported bootloader, or an SBC with an open boot chain, and the difference in approach is that lk2nd is a compatibility shim that keeps the vendor's chain intact rather than a replacement for it.

Maintenance, licence and how to reach the people who know

The releases show steady work rather than a one-off port. The tagged versions are 23.1 on 2026-07-14, 23.0 on 2026-07-12 and 22.0 on 2026-02-14, and the last push to the repository was on 2026-10-19, so the tree moves more often than the tags do. The README points at a Matrix room and an IRC channel for questions, #lk2nd on irc.oftc.net and #lk2nd:postmarketos.org on Matrix, which is the right place for a project whose users are working across dozens of chipsets, because the knowledge is in the people rather than in a wiki page. The licence is the one to check before you build on it. GitHub classifies the repository as Other, a custom licence the platform cannot map to a known identifier, and the LICENSE file at the root is the authoritative text, which matters here because the project is a fork of Qualcomm's own bootloader and of Little Kernel, so the terms of the upstream code flow into the fork.

Editorial conclusion

lk2nd suits an embedded developer who wants to run a non-Android operating system, such as postmarketOS, on a Qualcomm phone or tablet, and who would rather work with one flashing interface than with each vendor's proprietary one. It is the wrong tool for a device whose bootloader cannot be unlocked in the first place, since the whole design starts from a stock bootloader you can flash into, and it is the wrong tool for a modern chipset outside the supported SoC list, where the device-specific work has not been done. Verify first which SoC your device uses and whether it appears in the devices list in the Documentation directory, and read the 512 KiB offset rule in the README before flashing anything, because flashing the boot partition directly will overwrite lk2nd itself.

Frequently asked questions

What is the difference between the lk2nd and lk1st configurations?

The lk2nd configuration is a secondary bootloader for devices whose existing firmware cannot be replaced easily, so it is packed into an Android boot image and loaded by the stock bootloader. The lk1st configuration is a primary bootloader for single-board computers and expert users, responsible for loading the main operating system.

How do I install lk2nd on a device?

Download lk2nd.img from the releases and flash it with the stock flashing interface, using fastboot flash boot lk2nd.img, or heimdall flash --BOOT lk2nd.img on Samsung devices, or edl w boot lk2nd.img over EDL. If fastboot reports it could not parse partition size 0x, use fastboot flash:raw boot lk2nd.img instead.

Why does the README warn against flashing the boot partition directly?

The command fastboot flash boot boot.img will flash the actual boot image with a 512 KiB offset into the boot partition, and this is done to avoid replacing lk2nd, since lk2nd is itself booted from the boot partition.

How do I get a log file from lk2nd?

If the device appears via fastboot, run fastboot oem log and then fastboot get_staged with an output file, which can be a text file such as output.txt or /dev/stdout to write the log to standard output.

How do I build lk2nd for my chipset?

With make, passing a toolchain prefix and a target named after the SoC, for example make TOOLCHAIN_PREFIX=arm-none-eabi- lk2nd-msmXXXX. The README says that generally this should be enough and points to the building documentation for more.

Official sources

  1. Issues
  2. msm8916-mainline/lk2nd on GitHub
  3. README
  4. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/msm8916-mainline-lk2nd.svg)](https://hysenlabs.com/projects/msm8916-mainline-lk2nd)

Was this useful?