A PlayStation 4 is an x86-64 PC in disguise: an 8-core AMD Jaguar CPU, an AMD GPU and a hard drive. So in theory, Kali Linux should run on it. In practice, nothing about it is a normal PC, and stock Linux will not even get you a picture on the TV.

I built Kali Linux for PS4: Kali rolling with the XFCE desktop, installed from a graphical installer that runs on the TV. You copy five files to a jailbroken PS4 over FTP, run a payload and press X on the controller. As far as I could find, it is the first public Kali Linux release for the PS4.

Source code: github.com/blue0x1/kali-ps4

The installer on the TV

Here are the problems I had to solve along the way.

Problem 1: Kali's userland is easy, the kernel is not

Kali's normal amd64 packages run on the Jaguar CPU without any emulation. The hard part is the kernel: mainline Linux cannot drive the PS4's southbridge (Aeolia, Belize or Baikal, depending on the model) or its GPU setup.

The community ps4-linux kernel tree solves that. My build system clones it, applies my own patches, builds it in Docker together with a Kali root filesystem, and packs everything into three files: the kernel (bzImage), my initramfs, and a 900 MB compressed Kali archive.

Linux is started by a community payload, the PS4 Linux Loader, which you run from GoldHEN. One detail cost me a lot of time: the loader extracts the console's own GPU firmware and the TV's EDID into an initramfs archive that is loaded before mine. When I shipped my own copy of the GPU firmware, it silently overwrote the correct one and the GPU failed its ring tests. The fix was to ship no GPU firmware at all and let the loader's files win.

Problem 2: the PS4 Pro would not show a picture

The PS4 Slim and Pro do not output HDMI directly. The GPU sends DisplayPort to a Panasonic MN864729 bridge chip, which converts it to HDMI. With the stock kernel, the link trained, the kernel logs looked perfect, and the TV said "No signal".

To find out why, I wrote a small Python tool that talks to the bridge through the PS4's ICC interface (/dev/icc) and reads or writes its registers live, while Linux runs. That showed the actual problem: right after setup, and again after every EDID read, the bridge switched its HDMI output enables off and turned the video mute on.

The fix is a kernel patch that turns them back on after setup and after each EDID read:

/* HDMI output on, video unmuted */ mask(0x1e02, 0x70, 0x70); /* output enables, bits 4-6 */ mask(0x1e00, 0x01, 0x01); /* output enable, bit 0 */ write(0x705f, 0x10); /* VMUTECNT: unmute */ 

The bridge still turns the output off now and then, for example when the TV renegotiates. So a small keep-alive helper checks the registers every few seconds and repairs them: a C version runs during boot, and a systemd service takes over inside Kali.

Problem 3: installing onto an encrypted drive Linux should not write to

I wanted people to be able to install without a USB drive, on the PS4's internal hard drive. Two problems:

  1. The PS4's user partition is encrypted with a key that is unique to each console. The loader hands that key to Linux, so the partition can be opened with cryptsetup (AES-XTS).
  2. The partition uses the UFS2 file system, and Linux's UFS write support is experimental. Writing to it is a good way to corrupt the PS4's data.

My solution: Kali lives inside one big file on the PS4 drive, /user/home/kali-ps4.img, and Linux never writes the PS4's file system after creating it. At boot, the initramfs mounts UFS read-only, asks the file system where the file's blocks physically are (the FIBMAP ioctl), and turns that into a device-mapper table:

for (i = 0; i < nblocks; i++) { int blk = (int)i; ioctl(fd, FIBMAP, &blk); /* file block -> disk block */ /* merge contiguous runs, then print one line per extent: */ /* "start length linear /dev/mapper/ps4hdd offset" */ } 

Then it unmounts UFS and creates a dm-linear device from that table. The result is a normal block device that contains an ext4 file system, which Kali boots from. Reads and writes go straight to the file's blocks on disk, and the PS4's own file system metadata is never touched.

The only write to UFS happens once, during the first install: creating the file, filled with zeros so that every block is allocated. After that, the partition is only ever mounted read-only.

Problem 4: an installer with no graphics stack

The installer runs inside the initramfs, before Kali exists: no X11, no Wayland, no GTK. So it is a small C program, fbui, that draws directly to the Linux framebuffer:

  • Fonts are pre-rendered: a Python script renders Noto Sans glyphs into a C header, so no font library is needed at boot.
  • It draws everything itself: anti-aliased rounded buttons with gradients and a glow, text, the Kali logo with a breathing aura, and a progress ring around the logo.
  • The controller is read straight from /dev/input/event* with evdev. The D-pad, the left stick and X work, and so does a keyboard.

Two lessons from the real hardware:

Small screen updates did not show up. Updating only the countdown digits through the amdgpu framebuffer emulation often had no visible effect until a large redraw happened later. My working theory is a write cache in the PS4's memory path. The reliable fix was to send a full frame on every update. Because the screen's pixel format matches the program's own buffer, a full 1920x1080 frame is a single write() and costs only a few milliseconds.

The animation must never slow the install. The progress screen is drawn from a separate thread. The main thread only copies the Kali archive from the drive to xz and counts bytes, which also gives an accurate progress percentage, and the drawing thread reads that counter 30 times a second.

Installing

The result

  • Install to the PS4's internal drive or to a USB drive, chosen in the installer.
  • No PC tools, partitioning or USB stick needed.
  • After installing, every boot goes straight to the Kali desktop.
  • The whole project is GPL-2.0 and builds with make in Docker.

Choose where to install

What I learned

Most of the work was not Kali itself. It was the boot chain: payloads, initramfs, device-mapper, a misbehaving HDMI bridge, and a framebuffer that does not behave like a normal one. Reading kernel logs, poking registers live and testing on real hardware taught me more about how Linux boots than any desktop install ever has.

If you have a jailbroken PS4, try it and tell me how it works on your model:

github.com/blue0x1/kali-ps4

Built for learning and security research, on consoles you own.