Skip to content

Instantly share code, notes, and snippets.

@rmuxnet
Created March 20, 2026 06:51
Show Gist options
  • Select an option

  • Save rmuxnet/9bad97b4fa65b3deb580e5c31412c7ba to your computer and use it in GitHub Desktop.

Select an option

Save rmuxnet/9bad97b4fa65b3deb580e5c31412c7ba to your computer and use it in GitHub Desktop.
Complete PS4 Aeolia ICC map

PS4 Aeolia / Belize / Baikal — ICC Command Reference

Ultimate Gist — All Revisions Merged

Probed unit: PS4 Fat (Aeolia CXD90025G)
Kernel: Linux 6.18.18-Strawberry-ThinLTO-LTS+ (CachyOS x86_64)
CPU: AMD Jaguar DG1002FGF84HT (8) @ 1.59 GHz — confirmed via fastfetch
Hostname: PlayStation4
Interface: /dev/icc via ioctl(0xC0284901)


Python Gists

Module Gist Purpose
ps4_icc_core.py https://gist.github.com/rmuxnet/34d828bc9832dd2582dc602c4f27ff20 Low-level ioctl wrapper, constants, call_icc, call_clean
ps4_icc_sysinfo.py https://gist.github.com/rmuxnet/e1d0fee9e06dbe7680effe395ac9ab72 Major 0x02 — HW revision, EMC version, subsystem table, thermal slots
ps4_icc_fan.py https://gist.github.com/rmuxnet/8648c7fa8e3ae0aef4e8114ae7661fbe Major 0x0A / 0x0B — fan RMW threshold, live RPM, APU temp, trip points
ps4_icc_led.py https://gist.github.com/rmuxnet/002a2ae105ffca290ada36a39d645f70 Major 0x09 — full LED color table, payload builder, all effects
ps4_icc_nvs.py https://gist.github.com/rmuxnet/fff41726596d7da0ba7196e099a8e8de Major 0x01 — full 0x00–0xFF NVS directory sweep
ps4_icc_i2c.py https://gist.github.com/rmuxnet/c2783c5a56a9955e08a5d572e466c017 /dev/i2c-0 access — detect, read/write byte, I2CBus context manager
ps4_icc_monitor.py https://gist.github.com/rmuxnet/105481ad0745806be4422a5ab5f3ab9b CLI dispatcher tying all modules together

All files must be in the same directory. ps4_icc_core.py is the only dependency the others import.


Device Setup

cat /proc/devices | grep icc        # note the major number on the left
sudo mknod /dev/icc c <major> 0     # replace <major> with that number
sudo chmod 666 /dev/icc

Permanent (survives reboots):

echo 'KERNEL=="icc", MODE="0666"' | sudo tee /etc/udev/rules.d/99-ps4-icc.rules
sudo udevadm control --reload-rules
sudo udevadm trigger

For /dev/i2c-0 (only needed for ps4_icc_i2c.py):

sudo modprobe i2c-dev
sudo chmod 666 /dev/i2c-0

Table of Contents

  1. Hardware Overview
  2. ICC Interface Specification
  3. Response Format and Status Codes
  4. Stale Buffer Hazard
  5. Temperature Encoding Reference
  6. Major Map Summary
  7. Major 0x01 — NVS Directory
  8. Major 0x02 — System Information
  9. Major 0x03 — Partial / No Extractable Data
  10. Major 0x04 — Power Management (DANGEROUS)
  11. Major 0x05 — Peripheral Power
  12. Major 0x06 — EAP-Gated Placeholder
  13. Major 0x07 / 0x08 — No Data / Power Button
  14. Major 0x09 — LED / Indicator
  15. Major 0x0A — Fan Control
  16. Major 0x0B — Device Power Info
  17. Major 0x10 — I2C Proxy
  18. Unimplemented Majors
  19. EMC UART Quick Reference
  20. EMC Firmware Patch — God Mode
  21. Confirmed Hardware Data
  22. Dead Ends
  23. Open Questions
  24. References

1. Hardware Overview

Southbridge Variants

PS4 Model Southbridge Part Number EMC Core
PS4 Fat Aeolia CXD90025G ARM Cortex-M3 r2p1, ~100 MHz
PS4 Slim Belize CXD90036G ARM Cortex-M3 (protocol identical)
PS4 Pro / Late Slim Baikal CXD90042GG ARM Cortex-M3 (protocol expected identical)

All research conducted on PS4 Fat (Aeolia CXD90025G). Protocol confirmed identical on Belize.

Full Hardware Context

CPU:             AMD Jaguar (Liverpool / DG1002FGF84HT), 8-core @ 1.59 GHz, btver2
GPU:             AMD GCN 1.1 (Liverpool integrated), ~800 MHz
Southbridge:     Aeolia CXD90025G  (probed unit)
  EMC:           ARM Cortex-M3 r2p1, ~100 MHz
                 Responsibilities: ICC, power sequencing, fan PID, UART debug,
                 syscon-internal NVS (distinct from sflash NVS areas)
  EAP:           Marvell PJ4C, ~500 MHz, FreeBSD 9
                 Responsibilities: network, HDD/optical in standby
Serial Flash:    256 MB Macronix MX25L25635FMI-10G
Southbridge RAM: 256 MB DDR3 (Fat / Slim), 1 GB DDR3 (Pro)
System RAM:      6.74 GiB

ICC = inter-chip communication between x86 APU and ARM EMC via shared memory, managed by the ps4-apcie-icc.c kernel driver.

Aeolia Chip Revision String (dmesg)

eb9e0130:b4081241:00000300

ICC Devices Registered at Orbis Boot

icc nvs device registered                    major 0x01
icc thermal info device registered           major 0x02
icc fan info device registered               major 0x0A
icc configuration info device registered     major unknown
icc indicator device registered              major 0x09
icc device_power info device registered      major 0x0B

2. ICC Interface Specification

Device Node

/dev/icc

ioctl Number

_IOWR('I', 1, struct icc_cmd) = 0xC0284901
(3 << 30) | (40 << 16) | (0x49 << 8) | 1

Struct Layout (64-bit ABI, 40 bytes)

0x00  u8   major
0x01  1B   padding
0x02  u16  minor
0x04  4B   padding
0x08  u64  data pointer
0x10  u16  data length
0x12  6B   padding
0x18  u64  reply pointer
0x20  u16  reply length
0x22  6B   padding

Python pack format: '<BxH4xQH6xQH6x' — 40 bytes confirmed.


3. Response Format and Status Codes

Every ICC reply begins with a two-byte header:

byte[0]  status code
byte[1]  echo of major sent
byte[2+] payload (command-specific)

Status Codes

Code Name Meaning
0x00 OK Success; payload from byte[2]
0x01 UNK Unknown minor for this major
0x02 OK_DATA Stub; real reply is 2 bytes only
0x03 ALT_OK Alternate success; same as OK on most majors
0x04 NOT_IMPL Not implemented in EMC firmware
0x05 EAP_GATE EAP-gated; major 0x06 only, not usable from Linux
0x06 UNIQUE Major 0x02/0x1B only; meaning TBD
0x23 DEAD Major 0x0A/0x04 only; zero data

4. Stale Buffer Hazard

The ICC kernel driver does NOT zero the reply buffer between consecutive calls on the same file descriptor. Bytes beyond the real reply length retain data from the previous ioctl.

The most consequential example: 0x02/0x00 called on a shared fd after 0x02/0x01 consistently showed 00:d9:d1:58:81:82 (the Ethernet MAC) at bytes[4:10]. The byte sequence reordered as 0x58D1D900 decoded to 2017-03-22 01:53:04 UTC — a plausible timestamp that was documented as a live RTC field for some time. It is not. The field is static and reads all-zeros under Linux.

Rule: Use call_clean() (fresh fd, first ioctl) for any command whose real reply is short and contamination would be ambiguous: 0x02/0x00, 0x02/0x01, 0x02/0x07.


5. Temperature Encoding Reference

Source Format Width Example Raw Decoded Formula
EMC UART tempr get 8.8 fixed-point u16 0x1E40 30.25 C raw / 256.0
EMC UART etempr get 8.8 fixed-point u16 0x6000 96.0 C raw / 256.0
ICC 0x0A/0x08 reply[16:18] 8.8 fixed-point LE u16 0x3080 48.5 C raw / 256.0
ICC 0x0A/0x08 reply[8:12] 16.16 fixed-point LE u32 0x08200000 ~2080 RPM raw / 65536.0
ICC 0x0B/0x01 reply[3] Plain integer u8 0x3E 62 C identity
ICC 0x0A/0x07 reply[5] Plain integer u8 0x50 80 C identity
ICC 0x0B/0x05 reply[5,9] Plain integer u8 0x60 96 C identity

RPM Sentinel Values

0xFFFFFFFF and 0x0FFFFFFF in the 16.16 RPM field both mean fan is idle. Report as 0.0.

Cross-Validation: UART etempr vs ICC 0x0B/0x05

UART MainSoc Alert    0x6000 / 256 = 96.0 C  ==  ICC 0x0B/0x05 byte[5] = 96   CONFIRMED
UART MainSoc Critical 0x6100 / 256 = 97.0 C  ==  ICC 0x0B/0x05 byte[9] = 97   CONFIRMED

6. Major Map Summary

Major Status Codes Coverage Notes
0x00 04 None Not implemented
0x01 01, 02 Partial NVS directory — metadata only, values RSA-gated
0x02 00,01,02,03,06 Full System info, HW rev, EMC version, thermal, capabilities
0x03 00,01,03,04 Partial OK replies on some minors; no extractable payload
0x04 not probed DANGER Power/reboot — shuts down in 3 seconds
0x05 00,01,02 Partial Peripheral power (BT/WLAN/USB)
0x06 00,01,04,05 Dead end EAP-gated; payload-invariant from Linux
0x07 00,01,02 None No data bytes on any minor
0x08 00,01 Partial Power button state
0x09 00,01 Full LED/indicator — fully mapped
0x0A 00,01,02,04,35 Full Fan control — fully mapped
0x0B 00,01 Full Device power info — fully mapped
0x0C–0x0F 04 None Not implemented
0x10 00,01 Full (via i2c-dev) I2C proxy — use /dev/i2c-0, not raw ICC
0x11 00,01,02 None Stubs only
0x12–0x14 04 None Not implemented
0x1F 04 None Not implemented

7. Major 0x01 — NVS Directory

Python: https://gist.github.com/rmuxnet/fff41726596d7da0ba7196e099a8e8de

Architecture Note

The NVS accessed here is syscon's internal flash — distinct from the EMC-managed sflash NVS areas (csarea, dsarea, osarea, pdarea). Syscon runs ICC over SPI (SPI + interrupt line) and exposes its index through major 0x01.

Call Syntax

Major: 0x01   Minor: 0x00   Payload: bytes([idx])

Response Layout

byte[0]  0x00 (OK) if populated, 0x02 (stub) if empty
byte[2]  0x01 if entry exists
byte[3]  type code
byte[4]  index echo
byte[5+] always 0x00 — value NOT returned (RSA-gated)

NVS Index Map (full 0x00–0xFF sweep, Aeolia Fat)

Index Type Size Known Content
0x01 0x00 1B unknown scalar
0x02 0x06 6B Wi-Fi MAC address
0x03 0x00 1B unknown scalar
0x04 0x21 33B Serial number (32 ASCII + null)
0x05 0x01 1B boolean flag
0x06–0x08 0x00 1B unknown scalars
0x09 0x01 1B boolean flag
0x0A 0x02 2B unknown u16
0x0B 0x01 1B boolean flag
0x10 0x01 1B boolean flag
0x11 0x00 1B unknown scalar
0x8C 0x00 1B factory calibration
0x8D 0x00 1B factory calibration

Type Codes

Code Meaning
0x00 u8 scalar
0x01 boolean flag
0x02 u16 little-endian
0x06 6-byte blob (MAC / BD address format)
0x21 33-byte null-terminated ASCII string

Auth Gate

Values are gated behind RSA authentication (uareq1 / uareq2 on EMC UART). Exhaustive ICC probing confirmed no bypass: 256×256 payload sweep, all 256 minors, 7 format strategies, pre-auth sequences — zero value bytes returned under any condition.

Alternative Value Recovery (no auth)

Entry Recovery Path
Wi-Fi MAC /sys/class/net/mlan0/address
Ethernet MAC /sys/class/net/enp0s20f1/address
BD address Stale buffer from 0x02/0x01
Serial number EMC UART dsarea after uareq1/uareq2

8. Major 0x02 — System Information

Python: https://gist.github.com/rmuxnet/e1d0fee9e06dbe7680effe395ac9ab72

Minor Status Real Reply Description
0x00 00 4 bytes Last Orbis boot timestamp (static under Linux)
0x01 00 4 bytes Hardware revision
0x04 02 2 bytes Stub
0x05 00 10 bytes Subsystem capability table
0x06 00 16 bytes EMC firmware version
0x07 00 4 bytes Thermal sensor slots
0x09 00 6 bytes Capability flag byte[5]=0x10
0x0B, 0x0C 02 2 bytes Stubs
0x0F, 0x10 03 2 bytes ALT_OK, no data
0x1B 06 2 bytes Unique status, TBD

0x02/0x00 — Last Orbis Boot Timestamp

Real reply: 4 bytes, all zeros under Linux. This field is written by the Orbis kernel at boot and is never updated by Linux. Not a live RTC counter.

WRONG. ITS FIRST BOOT MAYBE?

The "Unix timestamp" 0x58D1D900 (2017-03-22) seen in early research was stale buffer contamination: the Ethernet MAC 00:d9:d1:58:81:82 from a preceding 0x02/0x01 call on the same fd. Always call on a fresh fd as the first ioctl.

0x02/0x01 — Hardware Revision

Real reply: 4 bytes. byte[3] = 0x02 on probed unit. Bytes[4:10] on a shared fd contain the BD address 8c:9c:39:9f:93:f4 as stale buffer from EMC shared memory.

0x02/0x05 — Subsystem Capability Table

bytes[2:10] — version per subsystem in Orbis boot registration order:
  [0] nvs           v3   major 0x01
  [1] thermal_info  v2   major 0x02
  [2] fan_info      v2   major 0x0A
  [3] config_info   v1   major unknown
  [4] indicator     v1   major 0x09
  [5] device_power  v1   major 0x0B
  [6] unknown_6     v5   unidentified — highest version of any subsystem
  [7] unknown_7     v1   unidentified

0x02/0x06 — EMC Firmware Version

byte[14] = 0x17 = 23  (major)
byte[15] = 0x12 = 18  (minor)  ->  v23.18

UART version returns 1.19.0 E r4336 — different numbering, same firmware.

0x02/0x07 — Thermal Sensor Slots

Real reply: 4 bytes. byte[3] = 4 (slot count). All slots 0xFF (unpopulated). APU temperature is read via 0x0B/0x01, not external sensor ICs. Extremely stale-buffer sensitive — call on fresh fd as first ioctl.


9. Major 0x03 — Partial / No Extractable Data

Status codes seen: 0x00, 0x01, 0x03, 0x04. Some minors return OK but all confirmed payload bytes are either 2-byte stubs or stale buffer artifacts. No structured payload has been reliably extracted. Possibly corresponds to the configuration info ICC device in the Orbis boot log.


10. Major 0x04 — Power Management (DANGEROUS)

DO NOT PROBE. Sending any valid command initiates shutdown or reboot in ~3 seconds. The kernel driver calls WARN_ON(1). No cancel path once accepted by EMC.

Minor Payload Function
0x01 00 00 02 00 01 00 SHUTDOWN
0x01 00 01 02 00 01 00 REBOOT

11. Major 0x05 — Peripheral Power

Minor Function Payload
0x00 BT/WLAN power 0x02=OFF, 0x03=ON
0x01 BT/WLAN status
0x10 USB power 0x00=OFF, 0x01=ON

BT/WLAN are on a single power rail (Marvell 88W8897). Toggling while a network interface is active will drop the interface.


12. Major 0x06 — EAP-Gated Placeholder

All minors 0x00–0x2F probed with all payload variants. Completely payload-invariant. Functional only during EAP (FreeBSD standby) sessions. Dead end from Linux.


13. Major 0x07 / 0x08

0x07: Returns 0x00, 0x01, or 0x02 on various minors. No payload bytes beyond the 2-byte header. Meaning unknown.

0x08 (Power Button): Returns 0x00 or 0x01. Short payload may encode power button state but stale buffer contamination prevents reliable decoding.


14. Major 0x09 — LED / Indicator

Python: https://gist.github.com/rmuxnet/002a2ae105ffca290ada36a39d645f70

Major: 0x09   Minor: 0x20   Payload: 35 bytes   Reply length: 0x30 bytes
Success: reply[0] == 0x00

Hardware Channels

0x10  Blue
0x11  White
0x02  Orange  (3-operation timed sequence)

Red is not achievable. No red LED element exists on any PS4 hardware revision.

Payload Format (35 bytes)

bytes [0-3]   header:  03 01 00 00
bytes [4-10]  Blue:    10 01 02 [BLUE_VAL]  02 01 00
bytes [11-17] White:   11 01 02 [WHITE_VAL] 02 01 00
bytes [18-19] Orange header: 02 03
bytes [20-34] Orange: 3 operations x 5 bytes each

Operation Block (5 bytes)

byte[0]  opcode:  0x01=FADE-FROM, 0x02=HOLD/FADE-TO
                  0x03, 0x04 accepted, visual TBD
byte[1]  value:   0x00=off, 0xFF=full
byte[2]  timing_hi
byte[3]  timing_lo
byte[4]  flags:   0xFF=loop forever, 0x00=one-shot, 0xBF=loop with hold

Orange Channel Programs (bytes 20–34)

Program Bytes Used For
OFF 01 00 04 01 bf 02 00 05 01 ff 02 00 05 01 ff off, blue, white, white_blue
ON 02 ff 02 01 00 02 ff 05 01 ff 02 ff 05 01 00 orange, violet_blue, pink, pink_blue
COMBINED 01 00 04 01 bf 02 ff 05 01 ff 02 00 05 01 ff orange_blue, orange_white, orange_white_blue
PULSATE 01 ff 04 01 00 02 ff 05 01 ff 02 ff 05 01 00 pulsate_orange

Color Table

Effect BLUE_VAL WHITE_VAL Orange
off 0x00 0x00 OFF
blue 0xFF 0x00 OFF
white 0x00 0xFF OFF
white_blue 0xFF 0xFF OFF
orange 0x00 0x00 ON
orange_blue 0xFF 0x00 COMBINED
orange_white 0x00 0xFF COMBINED
orange_white_blue 0xFF 0xFF COMBINED
violet_blue 0x57 0x00 ON
pink 0x00 0x30 ON
pink_blue 0x20 0x00 ON
pulsate_orange 0x00 0x00 PULSATE

HDMI Warning

Orange channel at timing (0x00, 0x01) causes monitor dropout via voltage noise on a shared power rail. Hardware electrical issue — not bus congestion (200 safe ioctls/sec with no dropout confirmed). Minimum safe timing: (0x01, 0x01).


15. Major 0x0A — Fan Control

Python: https://gist.github.com/rmuxnet/8648c7fa8e3ae0aef4e8114ae7661fbe

Minor Function
0x06 Write fan threshold (RMW required)
0x07 Read fan config (52 bytes)
0x08 Live RPM + APU temp
0x04 Status 0x23 dead end

READ-MODIFY-WRITE REQUIREMENT (CRITICAL)

Writing fewer than all 52 bytes, or zero-filling any byte, corrupts the EMC PID configuration. The fan permanently reports 0 RPM until a hard power cycle (not reboot). This was the root bug in the legacy ps4fancontrol tool: 6-byte allocation with 52-byte length, zeroing 46 bytes including the PID flags.

Always use write_fan_threshold() from ps4_icc_fan.py. Never write raw config.

Fan Config Block Layout (52 bytes)

byte[5]   temperature threshold in degrees C (plain u8)
byte[9]   0x08  PID integral gain flag   -- MUST preserve
byte[12]  0x80  PID prop. gain flag      -- MUST preserve

Stock config at 80 C (probed unit):

0x00:  00 00 00 00 00 50 00 00  00 08 00 00 80 00 00 00
0x10:  ff ff ff 0f ff ff ff 0f  ff ff ff 0f 00 00 00 00
0x20:  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
0x30:  00 00 00 00

Fan Status Reply Layout (0x0A/0x08)

byte[5]      tachometer ADC raw (~232 at idle) — NOT a duty cycle %
bytes[8:12]  RPM, u32 LE, 16.16 fixed-point (/ 65536.0)
             0xFFFFFFFF or 0x0FFFFFFF = idle sentinel -> report 0.0
bytes[16:18] APU temp, u16 LE, 8.8 fixed-point (/ 256.0)

Tachometer updates ~1 Hz. RPM climbs slowly under load (PID integral windup — intentional). ~10 seconds to spin back down after threshold is raised.

UART fservo get Cross-Reference (MainSoc PID loop)

SetVal=0x00005000  PGain=0x00000800  IGain=0x00000080  ILimit=0x0FFFFFFF

Valid threshold range: 45–85 C. Hardware default: 79 C (0x4F).


16. Major 0x0B — Device Power Info

Python: https://gist.github.com/rmuxnet/8648c7fa8e3ae0aef4e8114ae7661fbe

Real reply: 20 bytes. Bytes beyond byte 19 are stale (LED payload from recent 0x09/0x20 commonly appears there).

0x0B/0x01 — APU Temperature

reply[3] = APU temperature in degrees C, plain u8, no conversion.
           Cross-validated against k10temp hwmon under stress-ng load.

0x0B/0x05 — Thermal Trip Points

payload [0x00]  APU domain:
  byte[5] = 96 C   alert threshold
  byte[7] = 0x02   domain count
  byte[9] = 97 C   EMC shutdown threshold

payload [0x01]  domain 1 — untested (expected LPDDR4)

payload [0x02]  GPU domain:
  byte[9] = 72 C   GPU shutdown threshold

READ-ONLY from ICC. EMC ignores write attempts. Values written by Orbis kernel at boot from NVRAM; fixed for the session.


17. Major 0x10 — I2C Proxy

Python: https://gist.github.com/rmuxnet/c2783c5a56a9955e08a5d572e466c017

The ICC driver implements I2C framing internally and registers a standard Linux adapter:

i2c i2c-0: adapter [icc] registered
i2c_dev: adapter [icc] registered as minor 0

Do not use raw ICC ioctls for I2C. All raw format attempts return zeros. Use /dev/i2c-0 via i2c-dev instead:

i2cdetect -y 0
i2cget   -y 0 0x60 0x9E
i2cset   -y 0 0x60 0x9E 0x00

Known I2C peripherals on the Aeolia bus (not yet enumerated via i2cdetect):

  • Voltage Regulator Module (VRM) — likely near 0x60
  • Power management IC
  • Possibly HDMI repeater chip

i2cdetect -y 0 is the highest-priority remaining open investigation.


18. Unimplemented Majors

Return 0x04 (NOT_IMPL) on every minor — full 0–255 sweep confirmed:

0x00, 0x0C–0x0F, 0x12–0x14, 0x1F


19. EMC UART Quick Reference

115200 8N1
MMIO 0xd0340000 — DO NOT read via /dev/mem (machine check + instant poweroff)
Physical serial pads on motherboard

Auth: uareq1 (challenge) / uareq2 (RSA response) — required for all NVS reads.

Command Function Auth
tempr get SoC + exhaust temps, 8.8 fixed-point No
etempr get Trip point thresholds, 8.8 fixed-point No
fduty get Fan duty 0–1024 (÷1024×100=%) No
fservo get Full PID parameters No
fsstate get Live fan servo state (both loops) No
flimit get Fan duty limits (max/min per loop) No
devpm Device power states (wlan/hdd/usb/bd/hdmi/gbe) No
rtc RTC counter No
state System state No
powupcause Last power-up cause No
version EMC firmware version (1.19.0 E r4336) No
scversion Syscon version (1.0.0 ET r1808) No
getmacadr Wi-Fi MAC (direct NVS read) Yes
socuid SoC UID Yes
csarea Serial Flash NVS CS Area dump Yes
dsarea Serial Flash NVS DS Area (serial / socuid) Yes
osarea Serial Flash NVS OS Area Yes
pdarea Serial Flash NVS PD Area Yes
nvscsum NVS checksum Yes
stinfo Statistics from NVS Yes
uareq1 / uareq2 RSA auth handshake

20. EMC Firmware Patch — God Mode

The EMC firmware enforces privilege levels via a permission byte in the command dispatch table. Patching grants unconditional access regardless of auth state.

Change all: 03 00 FD 00  ->  0F 00 FD 00
Change all: 07 00 FD 00  ->  0F 00 FD 00

Back up Serial Flash before patching. The EMC has no known external recovery mode if its firmware is corrupted. Wrong commands after unlocking can brick permanently.


21. Confirmed Hardware Data

Unit:               PS4 Fat (CUH-1xxx)
Southbridge:        Aeolia CXD90025G
Chip revision:      eb9e0130:b4081241:00000300
EMC firmware (ICC): v23.18  (byte[14]=0x17, byte[15]=0x12)
EMC firmware (UART):1.19.0 E r4336
Syscon version:     1.0.0 ET r1808
HW revision:        0x02  (0x0B/0x01 reply byte[3])
Active flash bank:  Second  (UART: sb)
Kernel:             Linux 6.18.18-Strawberry-ThinLTO-LTS+ (CachyOS x86_64)
Memory:             5.71 GiB / 6.74 GiB
Network:            enp0s20f1 @ 192.168.1.116/24

Fan threshold:      80 C  (byte[5]=0x50)
Hardware default:   79 C  (0x4F)
PID flag [9]:       0x08  (intact)
PID flag [12]:      0x80  (intact)
APU alert:          96 C  (0x0B/0x05 domain 0 byte[5])
APU shutdown:       97 C  (0x0B/0x05 domain 0 byte[9])
GPU shutdown:       72 C  (0x0B/0x05 domain 2 byte[9])

Wi-Fi MAC:          e8:61:7e:f8:ea:b7  (/sys/class/net/mlan0/address)
Ethernet MAC:       00:d9:d1:58:81:82  (/sys/class/net/enp0s20f1/address)
BD address:         8c:9c:39:9f:93:f4  (stale buffer from 0x02/0x01)
Serial:             not ICC-accessible  (syscon NVS RSA-gated)
Last Orbis boot:    2017-03-22 01:53:04 UTC  (frozen in EMC NVRAM)
Thermal slots:      4 configured, 0 populated (all 0xFF)

22. Dead Ends

Target Reason Consequence
Major 0x04 Power/reboot management System shuts down in 3 seconds
Major 0x06 all minors EAP-gated, payload-invariant No data
Major 0x07 all minors No data bytes returned No data
0x0A/0x04 Status 0x23, zero data Dead end
NVS values via ICC RSA auth gate — no bypass exists Zero value bytes
/dev/mem at 0xd0340000+ EMC MMIO Machine check + instant poweroff
Raw ICC ioctls for I2C Kernel handles framing Returns zeros — use /dev/i2c-0

23. Open Questions

  1. /dev/i2c-0 bus enumerationi2cdetect -y 0 not yet run. VRM and other Aeolia-attached I2C devices may be fully accessible. Highest-priority remaining item.

  2. NVS serial number — not ICC-accessible without RSA auth. Recoverable via EMC UART dsarea or hardware flash programmer.

  3. 0x02/0x05 unknown subsystems (v5 and v1) — two unidentified subsystems in the capability table. unknown_6 at version 5 is notable. Hypotheses: majors in the 0x0C–0x1F NOT_IMPL range that are functional from Orbis but not Linux, or EAP-side only.

  4. LED opcodes 0x03 and 0x04 — accepted by EMC (returns OK_DATA) but visual behavior not yet observed.

  5. 0x0B/0x05 domain 1 (payload [0x01]) — trip points for power domain 1 not yet queried. Likely LPDDR4 memory domain.

  6. Major 0x03 fresh-fd sweep — some minors return status 0x00 but real reply may be a 2-byte stub indistinguishable from stale buffer. Fresh-fd probing of all 0x03 minors not completed.


24. References

Kernel drivers:
  drivers/ps4/ps4-apcie-icc.c     ICC character device + ioctl
  drivers/ps4/ps4-fan.c           hwmon: temp1_input, temp1_crit (RMW), fan1_input
  drivers/ps4/ps4-led.c           LED class, 11 sysfs nodes, thermal trigger

Community:
  psdevwiki.com/ps4/Southbridge   EMC UART command reference
  psdevwiki.com/ps4/Bootprocess   Orbis boot log with ICC device names
  psdevwiki.com/ps4/Serial_Flash  NVS area layout

Projects:
  ps4fancontrol (Ps3itaTeam)       original fan tool — RMW bug documented here
  ps4-kexec linux_boot.c           Aeolia MMIO map
  Belize ps4-linux led_config (Saya) LED payload format confirmed

Hardware:
  Macronix MX25L25635FMI-10G      Serial Flash datasheet
  ARM Cortex-M3 r2p1 TRM          EMC core reference
  AMD btver2 (Jaguar) BKDG        APU temp sensor details

Probed on PS4 Fat (Aeolia CXD90025G), Linux 6.18.18-Strawberry-ThinLTO-LTS+, CachyOS x86_64.
Protocol confirmed compatible with Belize (CXD90036G). Expected compatible with Baikal (CXD90042GG).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment