SMCCC - a tool to directly communicate SOC firmware with userspace

Hello

I have started to work o a new project which allows to communicate with SOC’s internal firmware directly.

Normally SOCs have internal microprocessors that manage frequency, voltage, wake up, sleep, and other facilities. Sometimes the software for the MCU is loaded during in early boot stage (BL2/3…), and sometimes they dont need any firmware at all, simply it is part of the boot rom.

And when your OS/kernel wants to change frequencies of gpu/cpu for instance, it commincates with this MCU over an interface called SMCCC. The contents of the communication is Vendor specific, but the way to communicate is standardized.

So this tool is seperated in 2 parts. There is a kernel module that allows communication with firmware from userspace. And 2nd tool that does the communication for rockchip devices.

So you just need the build the module, insert the module, and run the pysmcc user space tool.

Currently it can read and write and there is no useful application that i built on top of it except reading DDR settings.

My first goal is to create a tool to overclock several parts of the device as much as the firmware allows.

3 Likes

what can we do with this ?

currently you can only change the dram frequency (which is already available by other means like devfreq), i am exploring more ways to exploit this interface, so this is kinda learning by doing type of project.

1 Like

Becareful with probing SMCs blind… Some will let you brick the device by writing garbage values into the OTPs if you’re not careful :slight_smile:

1 Like

i kinda liked the way it sounds :brick: would be even greater if i could find a way to manipulate the ddr timings

Several of the DDR SMCs in BL31 are non functional, see screenshots. SMC 0x82000008 deals with DDR stuff with a “function ID” in X3. X3 goes from 0 to 0x12 (inclusive).


image

Functions that do stuff: X3 = 0, 1, 3, 5, 8, 9, 0xC, 0xE, 0x10, 0x11
The rest will error out one way or another.

image
image

great info thanks, i think INIT = 0x00 and SET_RATE = 0x01 should also do things, dmc driver in kernel actively uses them.

I also think that those print functions are activated by setting up a functional UART may be with “UARTDBG_CFG = 0x82000005”

definitions are also here

command ids: https://github.com/hbiyik/smccc/blob/dae744c881157ed91ca251abaf386aa31b3a1e82/pysmccc/smccc/implementations/rockchip/ids.py#L20-L67

dram calls: https://github.com/hbiyik/smccc/blob/dae744c881157ed91ca251abaf386aa31b3a1e82/pysmccc/smccc/implementations/rockchip/dmc.py#L18-L36

82000005 is a “NOP”.

weird so it prints out to thin air.

It can print for real, it uses the standard BL31 console_* functions, but I didn’t look at how to activate them. You can lookup “console_putchar” in TF-A source code to get a general idea.

1 Like

What if we remove the power supply from the OTP, as a default setting. This should prevent any subsystem to access the OTP, accidentally or not. This needs to be confirmed though.