Skip to content

Latest commit

 

History

41 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

NixOS on the Xiaomi POCO X3 NFC

This repository ports NixOS to the Xiaomi POCO X3 NFC (codename surya).

The device uses a Qualcomm SM7150 SoC (Snapdragon 732G). The port builds on the work of the sm7150-mainline project and the postmarketOS community, who maintain the mainline kernel fork, the U-Boot port, and the firmware and ALSA UCM trees this repository consumes. For the state of the underlying hardware support, see the POCO X3 NFC page in the postmarketOS Wiki.

It is adapted from gian-reto/nixos-fairphone-fp5, which does the same for the Fairphone 5, and keeps that project's boot architecture and module layout.

App launcher, file manager, settings and system information on the POCO X3 NFC running NixOS with Plasma Mobile

Current Status

Supported Hardware

  • Audio: Speaker works (no microphone, earpiece or headset profile yet)
  • Battery: Works (capacity from the downstream OCV tables, status from the charger)
  • Bluetooth: Firmware loads (pairing untested)
  • Camera: Not supported (no sensor drivers)
  • Cellular modem: Works (loading IPA occasionally resets the device; the next boot skips it, see modules/ipa)
  • Charging: Works (USB PD chargers and computers)
  • GPU: Works
  • Haptics: Works
  • Screen: Works
  • Sensors: Disabled by default (hexagonrpcd cannot write the sensors registry, which crashes the ADSP)
  • Touchscreen: Works
  • Wi-Fi: Works

Untested: calls, SMS, mobile data, GPS, NFC, SD card, USB OTG, suspend and the flashlight.

Note: Hardware was tested with Plasma Mobile. The minimal image boots to a console without a desktop.

Getting Started

Caution

Cross-compilation is not supported, so the images have to be built on an aarch64-linux host. Because Nix has excellent support for remote builders, the build can also be delegated to a remote aarch64-linux builder (see below).

Prerequisites:

  • A POCO X3 NFC with an unlocked bootloader (through Xiaomi's Mi Unlock process).
  • Knowledge of which display panel the device has, huaxing or tianma. The device tree has to match, or the screen stays dark. It cannot be detected from Linux; see Know your display panel in the postmarketOS Wiki for how to read it from Android.
  • An aarch64-linux NixOS host to build the images. Other distributions with Nix installed may also work, but have not been tested. Alternatively, use a remote builder from any Nix-enabled system.

Optional: Set up a Remote Builder

nixbuild.net works well as a remote builder. It is easy to set up, provides the necessary aarch64-linux builders, and caches the builds of each derivation, so subsequent builds are usually fast.

Set up an account and add your SSH public key as described in their getting started guide. You don't need to make it a builder for your entire NixOS configuration (the guide's "Quick NixOS Configuration" section): set the programs.ssh.extraConfig and programs.ssh.knownHosts options as described there, and ignore the nix.distributedBuilds and nix.buildMachines options. This way, you can use the remote builder on demand as needed.

Verify that you can connect to their server over SSH:

sudo ssh eu.nixbuild.net shell

If you can connect, you're ready to use the remote builder to build your images.

Add the Module to Your NixOS Configuration

The example configuration in this repository is only a starting point. To run your own configuration, add the POCO X3 NFC module to it and expose the two image artifacts for the initial flash:

{
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
    nixos-xiaomi-surya.url = "github:schphe/nixos-xiaomi-surya";
  };

  outputs = { self, nixpkgs, nixos-xiaomi-surya, ... }: {
    nixosConfigurations.my-poco = nixpkgs.lib.nixosSystem {
      system = "aarch64-linux";
      modules = [
        # Import the POCO X3 NFC NixOS module.
        nixos-xiaomi-surya.nixosModules.default

        # Select the display panel of your device, "huaxing" or "tianma".
        { hardware.xiaomi-surya.panel = "huaxing"; }

        # Import your own custom configuration.
        ./hosts/my-poco/default.nix
      ];
    };

    # Use the `mkUbootImage` and `mkDiskImage` functions provided by this flake to build the boot
    # and disk images from your configuration, so you can flash its first generation with `fastboot`.
    packages.aarch64-linux =
      let
        pkgs = nixpkgs.legacyPackages.aarch64-linux;
      in {
        # U-Boot image for the Android `boot` partition, built for your panel.
        uboot-image = nixos-xiaomi-surya.lib.mkUbootImage pkgs "huaxing";

        # Nested GPT image containing the ESP and your complete NixOS system.
        disk-image = nixos-xiaomi-surya.lib.mkDiskImage
          self.nixosConfigurations.my-poco;
      };
  };
}

Build and Flash Images

Caution

Flashing the disk image permanently erases everything in userdata, including Android apps, files, and settings. Back up anything you need before continuing.

Tip

If you use a remote builder, configure Nix on the phone to use it by default. Otherwise nixos-rebuild boot and nixos-rebuild switch build locally on the phone, which can take a very long time or fail due to insufficient resources.

  1. Build both images from the configuration shown above:

    nix build .#packages.aarch64-linux.uboot-image --out-link result-uboot
    nix build .#packages.aarch64-linux.disk-image --out-link result-disk

    To delegate the builds to nixbuild.net, run:

    nix build .#packages.aarch64-linux.uboot-image --out-link result-uboot --max-jobs 0 --builders "ssh://eu.nixbuild.net aarch64-linux - 100 1 big-parallel,benchmark" --option builders-use-substitutes true
    nix build .#packages.aarch64-linux.disk-image --out-link result-disk --max-jobs 0 --builders "ssh://eu.nixbuild.net aarch64-linux - 100 1 big-parallel,benchmark" --option builders-use-substitutes true

    To try the example configuration from this repository instead, build .#uboot-image-huaxing and .#disk-image-huaxing (or the -tianma variants) in a checkout of it.

  2. Turn off the phone, then hold Volume Down and Power until the fastboot screen appears.

  3. Connect the phone to the build host over USB.

  4. From the directory containing result-uboot and result-disk, start a shell containing the fastboot tools:

    nix shell nixpkgs#android-tools
  5. Flash the images and reboot:

    fastboot flash boot result-uboot
    fastboot erase dtbo
    fastboot flash userdata result-disk/image.raw
    fastboot reboot

    fastboot erase dtbo is required. This device sets BOARD_KERNEL_SEPARATED_DTBO, so its bootloader overlays whatever is in the dtbo partition onto the device tree it boots. A stale Android dtbo corrupts a mainline tree, and the device drops straight back to fastboot.

The first boot may take a while while the root filesystem expands to the available space.

Important

The screen may flicker or go black for a moment while the display driver takes over from the boot framebuffer. This is expected; wait until the login prompt or desktop appears.

Restore Android

Caution

Reinstalling Android erases NixOS and everything in userdata. It cannot recover previous Android user data.

Flash a stock MIUI or LineageOS image for surya with fastboot, following that image's own instructions.

Advanced Usage

In some advanced use cases, you might want to change the process of building the images, or do other customizations. In that case, you can use the xiaomi-surya overlay provided by this flake directly, which allows you to use the included packages in the way you want.

{
  inputs.nixos-xiaomi-surya.url = "github:schphe/nixos-xiaomi-surya";

  outputs = { nixpkgs, nixos-xiaomi-surya, ... }: {
    nixosConfigurations.my-poco = nixpkgs.lib.nixosSystem {
      system = "aarch64-linux";
      modules = [
        {
          nixpkgs.overlays = [ nixos-xiaomi-surya.overlays.default ];

          # Now you have access to all POCO X3 NFC packages:
          # pkgs.kernel-xiaomi-surya
          # pkgs.firmware-xiaomi-surya
          # pkgs.uboot-xiaomi-surya
          # pkgs.tqftpserv (1.2), pkgs.swclock-offset
        }
        # Your custom configuration...
      ];
    };
  };
}

Development & Contribution

This flake outputs the uboot-image-<panel> and disk-image-<panel> packages for both panels, built from the example host configuration in ./hosts/minimal. These can be built and flashed as described above. The example user is called "schphe", and the password is "1234".

Once the device boots and is reachable over SSH, userspace changes do not need reflashing:

nixos-rebuild switch --flake .#huaxing --target-host schphe@<address> --sudo

The kernel, its command line, the initrd, and the device tree are part of each generation's systemd-boot entry, so nixos-rebuild boot and a reboot apply them too. Only U-Boot changes require flashing the boot partition again.

AI

The development in this repository is partially assisted by AI tools. Contributions made with the help of AI are welcome, provided that they are reviewed and tested by human contributors to ensure quality and correctness.

Coding agents must adhere to the instructions and guidelines outlined in agents.md when working in this repository.

Thanks

  • The sm7150-mainline project, for the kernel fork, the U-Boot port, the firmware tree, and the ALSA UCM profiles that make this device usable at all.
  • The postmarketOS community, whose kernel configuration, device packaging, and wiki documentation this port follows closely.
  • gian-reto/nixos-fairphone-fp5, which this repository is adapted from, and which worked out the U-Boot and nested-GPT boot architecture used here.
  • ungeskriptet/nixos-qcom, an independent NixOS port to this exact device, which was a valuable reference for the U-Boot build and the Qualcomm userspace services.