Working with Synology hardware – /dev/synobios and /dev/ttyS1

It was interesting to me what is inside DS207 box, how it works and controlled. Because root access is allowed it was not very hard to do my investigation. Hardware itself is based on standard 8245 PPC CPU with 64Mb of memory. It starts booting from internal flash (/dev/mtdX) using PPCBoot 2.0.0. boot loader. After loading kernel from flash its trying to run OS from system partition and if it is not possible – waiting for commands from synology tools. If DSM is already installed then it will boot OS from the hard drive and will start the web interface and other services. Network and sata controllers are standard hardware with corresponding device drivers in kernel.  They are working in a standard way, as on any other hardware. Non-standard parts in the NAS hardware are: Buttons, FAN control/sensors, and temperature sensor. We will talk how to manage them in this article.

About synobios module

To make an abstraction layer for the Synology kernel  module synobios was implemented. It is not under GPL but sources are available inside synology GPL packages. This driver is different for every NAS family but providing same API for the user-land applications. Also has information about device capabilities. Driver using ioctl() to speak with userland application. Internally there is a closed-source library in DSM with all related functions implemented. I decided to re-implement them myself based on module source.

Controlling FAN(s) and getting system temperature.

I decided to start with system temperature. I found that kernel sources are missing synobios.h – header with all ioctl related structures. I found it on another directory with uclib. ioctl providing many commands, i found that only small part of them are implemented by driver.

Below is a full command list with mine short description for some commands

SYNOIO_EXDISPLAY
SYNOIO_NEXTEVENT
SYNOIO_RTC_CONTROL_READ  commands to manage RTC, it is not available as normal linux /dev/rtc
SYNOIO_RTC_CONTROL_WRITE
SYNOIO_RTC_TIME_READ
SYNOIO_RTC_TIME_WRITE
SYNOIO_BUTTON_POWER
SYNOIO_BUTTON_RESET
SYNOIO_BUTTON_USB
SYNOIO_SET_DISK_LED sets LED disks status, actively used by scemd
SYNOIO_GET_FAN_STATUS getting fan(s) speed and status
SYNOIO_SET_FAN_STATUS setting fan(s) speed and status
SYNOIO_GET_DS_MODEL device identification, used by synobios driver
SYNOIO_GET_DS_BRAND
SYNOIO_GET_CPLD_VERSION
SYNOIO_GET_TEMPERATURE system temperature command
SYNOIO_GET_CPLD_REG internal registries of Complex programmable logic device. Different for every model.
SYNOIO_GET_AUTO_POWERON get/set power on after AC failure?
SYNOIO_SET_AUTO_POWERON
SYNOIO_GET_MEM_BYTE direct memory operations, don`t think that is in use
SYNOIO_SET_MEM_BYTE
SYNOIO_SET_ALARM_LED
SYNOIO_GET_HW_CAPABILITY getting device capabilities, actively used by DSM
SYNOIO_GET_FAN_NUM
SYNOIO_GET_POWER_STATUS
SYNOIO_SHUTDOWN_LOG
SYNOIO_UNINITIALIZE
SYNOIO_GET_SYS_STATUS
SYNOIO_SET_SYS_STATUS
SYNOIO_GET_MODULE_TYPE
SYNOIO_GET_BUZZER_CLEARED
SYNOIO_GET_BACKPLANE_STATUS
SYNOIO_SET_UART2
SYNOIO_GET_CPU_TEMPERATURE CPU temp., supported only by few devices
SYNOIO_SET_CPU_FAN_STATUS
SYNOIO_SET_PHY_LED
SYNOIO_SET_HDD_LED actively used by DSM (scemd)
SYNOIO_SET_PWR_LED
SYNOIO_PWM_CTL
SYNOIO_CHECK_MICROP_ID
SYNOIO_MANUTIL_MODE
SYNOIO_RECORD_EVENT
SYNOIO_GPIO_PIN_READ
SYNOIO_GPIO_PIN_WRITE
SYNOIO_RTC_READ
SYNOIO_RTC_READ_3
SYNOIO_SDA_SDL_READ
DISK_BADSECTOR_ON - seems to be not implemented at all.
DISK_BADSECTOR_OFF
DISK_BADSECTOR_SET
DISK_BADSECTOR_GETDISK_BADSECTOR_RESET

Our IOCTL is SYNOIO_GET_TEMPERATURE. It should return correct temperature. To find if it works i created small C code. I will post only part of the source, full source is available in archive.


syno_fd = open("/dev/synobios", O_RDONLY,0);
ret = ioctl(syno_fd, SYNOIO_GET_TEMPERATURE, &i);
printf("SYNOIO_GET_TEMPERATURE= %dF, %dC\n",i, (i - 32) * 5 / 9);

After running this code i got system temperature (in F), so driver works! Good start, lets look what else could be done. I personally tested get capabilities command, RTC and CPLD registers. BTW, only using CPLD registers you will get FAN speed (high/low, no RPM on this device) because this information is not exported in other structures. Also you may set HDD leds mode using it. We will talk about this in the next section.

LEDs and buttons

My device has a lot of controllable LEDs: Status, LAN, HDD1, HDD2, USB Copy, Power and 2 buttons – Power and Reset. Most of the leds are controlled by DSM, only LAN led is controlled directly by Ethernet chip. HDD leds are controlled with IOCTL call to /dev/synobios with SYNOIO_SET_DISK_LED. It is possible to switch this leds between OFF/GREEN/GREEN_BLINK/ORANGE/ORANGE_BLINK modes. In the solid green mode it also blinks on SATA activity. It is possible to change the mode, but scemd from DSM will set it back in a couple of seconds. See demo in the source code if you want to play with this. But what about other leds and buttons? They are controlled by special controller installed on /dev/ttyS1. To change LED mode or beep with speaker you need to send 1 byte to the /dev/ttyS1. It is also possible to read this device, and button events are passed to the serial port as 1 byte commands. DSM scemd is always reading this port to capture key presses. This controller is also used to implement some special functionality, e.g. to control WoL on supported boards. I was able to find full list of the available commands in the source tarball in the libsynosdk/gpl/synosdk/external.h file (it was not easy!). Below i provided list of the commands with my comments:


UART2_CMD_BUTTON_POWER              0x30 Power button event, delayed, handled by scemd
UART2_CMD_SHUTDOWN                  0x31 Hard power off, use with care!!!
UART2_CMD_BUZZER_SHORT              0x32 Short beep
UART2_CMD_BUZZER_LONG               0x33 Long beep
UART2_CMD_LED_POWER_ON              0x34 Power led on
UART2_CMD_LED_POWER_BLINK           0x35 Power led blink
UART2_CMD_LED_POWER_OFF             0x36 Power led off
UART2_CMD_LED_HD_OFF                0x37 Status led off
UART2_CMD_LED_HD_GS                 0x38 Status led green
UART2_CMD_LED_HD_GB                 0x39 Status led green blinking
UART2_CMD_LED_HD_AS                 0x3A Status led orange
UART2_CMD_LED_HD_AB                 0x3B Status led orange blinking
UART2_CMD_LED_HD_BREATH             0x3D
UART2_CMD_LED_USB_ON                0x40 USB led on
UART2_CMD_LED_USB_BLINK             0x41 USB led blinking
UART2_CMD_LED_USB_OFF               0x42 USB led off
UART2_CMD_LED_10G_LAN_ON            0x4A
UART2_CMD_LED_10G_LAN_OFF           0x4B
UART2_CMD_LED_MIRROR_OFF            0x50
UART2_CMD_LED_MIRROR_GS             0x51
UART2_CMD_LED_MIRROR_GB             0x52
UART2_CMD_LED_MIRROR_AS             0x53
UART2_CMD_LED_MIRROR_AB             0x54
UART2_CMD_TOGGLE_FAN_RPS_REPORT     0x55 /* 'U' */
UART2_CMD_SET_PWM_DUTY              0x56 /* 'V' */
UART2_CMD_SET_PWM_FREQ              0x57 /* 'W' */
UART2_CMD_BUTTON_USB                0x60 Fired if USB button pressed, handled by scemd
UART2_CMD_BUTTON_RESET              0x61
UART2_CMD_FAN_FAILURE               0x66 /* 'f' */
UART2_CMD_CPUFAN_FAILURE            0x67 /* 'g' */
UART2_CMD_RCPOWEROFF                0x70
UART2_CMD_RCPOWERON                 0x71
UART2_CMD_DISABLE_SCHEDULE_POWERON  0x72
UART2_CMD_ENABLE_SCHEDULE_POWERON   0x73
UART2_CMD_DISABLE_FANCHECK          0x74
UART2_CMD_ENABLE_FANCHECK           0x75
UART2_CMD_DISABLE_CPUFANCHECK       "EC0"
UART2_CMD_ENABLE_CPUFANCHECK        "EC1"
UART2_CMD_WOL_ENABLE                "l"  Does not working on DS207
UART2_CMD_GET_UNIQUE_CMD             0x52 /* 'R' */ Only for x86/x64 devices

The easiest way to send command to the serial port is to use printf with redirect. Below is an example:

"printf  "\\x35" > /dev/ttyS1" - this should make your power lad blinking, as on normal DSM boot. To read from port you will need to write some code (on C, Perl or anything else) which reading one byte from the port. Before doing this you will need to stop scemd to avoid conflicts. You can find example of this in the source code.

Conclusion

It is relatively easy to work with all hardware on Synology NAS  device. Currently all operations are managed by “scemd” closed-source daemon, so to work directly with hardware we will need to re-implement it functionality (or fake it somehow, e.g. with LD_PRELOAD or virtual ttyS1). I am not yet sure that I am going to do this (it works fine) but it always good to know that it is possible. It also could be very useful for alternative OS, like NetBSD or just normal Debian.  Source code is available as is, without any warranty.

Sample source code: synosrc_0.0.1.tar.gz


Advertisements
Tagged , , , ,

20 thoughts on “Working with Synology hardware – /dev/synobios and /dev/ttyS1

  1. Martin says:

    So it should be possible to run Synology OS on different hardware with a custom synobios as well, right? I mean it is fine hardware with a good price/value.

    • sammczk says:

      Yes. I think it could be illegal, but technically i see no problems. It should be very easy to provide emulation of the synobios using provided source on any hardware. But personally i would not recommend to do this, i think we should respect synology for their “open” politic.

  2. Marten says:

    Thank you for your work!

    I was looking into the fan speed of my DS1812 – it seems to have become louder recently – and it says:
    CAPABILITY_FAN_RPM_RPT: 0
    SYNOIO_GET_TEMPERATURE 256F, 124C
    SYNOIO_GET_FAN_STATUS 1

    The temperature seems off, and the Fan RPM too (the fan is obviously spinning), but I suspect this is your program getting the wrong data. The system info says that it’s running at a healthy 48C.

    Is there some way for me to force fan speed lower?

  3. Source code download seems to be broken. I get a corrupt file (3,7kb).

  4. marz says:

    i would love to see the ds207(+) or other synology devices to run a pure linux like debian or archlinux (see qnap devices). the synology devices like the ds207 are no longer updated since 2011 … (http://www.synology.com/products/status.php)

    Keep going 😉

    • sammczk says:

      I think this should not be hard – i am planning to do this once i will have some time. I want to start with Debian + original kernel, and later to replace kernel as well.

      • marz says:

        great … as soon you have some howto / tutorial i will offer my help as alpha/beta tester. Have a ds207+ here . An usb->serial adapter is on hand, so terminal and bootloader stuff is no problem.

        thanks for your efforts

      • sammczk says:

        Ok, I did some [initial] experiments.
        1) I compiled busybox with pivot_root support. One from synology is not providing it.
        2) I bootstrapped debian/ppc to the USB flash formatted as ext2
        3) Created devices in /dev/, mounted /proc and /sys on usb devoce.
        4) finally did pivot_root, killed old pids (except unkillable init) and do have debian running and working.
        Now i will think how its better to hack original rcS to do this on boot. For know i don`t see any strong reason to update the kernel (2.6.24 is not so old) so i think i will just build bootable-from usb debian with kernel from synology.

  5. doppelhelix says:

    Is it possible to program a little Atmel uC to emulate the Synology front panel?
    I run the DSM4.1 hack perfect on a Supermicro X7SPA-H-D525. But PowerButton and Speaker doesn’t work. A HDD (failure) LED is a nice to have, too.

    • sammczk says:

      I think you can actually write a fake driver which will emulate serial port in Linux, like null modem. Of course some device on atmel will work as well.

  6. doppelhelix says:

    Hmm…
    I think there is a missunderstanding.
    After I read all posts here and in other forums my understanding is, that there is an Microcontroller (Microchip PIC) on Synology Mainboard short to serial port 2 /dev/ttyS1.
    The controller interprete the commads from scemd for the LED’s an send commands triggered by pressing Power/Reset-Button.
    Is that incorrect?
    Some Users write that an “echo 1 >/dev/ttyS1” powers the device down. In my case this have no effect.
    Over again. The hacked Firmware from avsforum runs absolutely perfect on my Supermicro X7SPA Atom Hardware.
    The only thing I miss is the use of Powerbutton and LED’s for failure.
    When my assumption is right, the idea is to program an microcontroller, connected to serial2 (/dev/ttyS1) which emulate the original Synology’s one.

    • sammczk says:

      At least on my device part of the leds and power/usb buttons are controlled via serial port. It is bidirectional interface which is referenced in my article. You can build a hardware or just some kine of software loopback serial which will listen on the fake port and generate/accept commands you need. BTW, one of the hacks can work is a pipe instead of real /dev/ttyS0 device.

  7. Im in intrigued by your findings, however im running dsm 4.2 on ds107 model and some reason can’t get led to work right.Tried replacing synobios.o and scemd from latest ds107 .pat and unit wont work right.You have any off the board solution for this? I tried using cmds to get led working and they work! just seems disk and power led are mixed somehow.Just need way to reprogram what I have now with right codes zzz

  8. Arnout Boer says:

    Hi,

    I’d like to read the system clock (RTC), to troubleshoot the system not resuming from hibernation.

    I’m a linux newbie. How can I complile / use your code to read the clock?

    Thx!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: