Support for XikeStor SKS8300-8T (RTL9300)

I recently acquired an SKS8300-8T switch, which uses the Realtek RTL9303 SoC with 8x rj45 REALTEK 8261BE 10GbE ports. After a bit of research and based on the work done with the SKS8300-8X switch, I was able to fairly easily boot into OpenWRT. The only problem is that there's a bug with the LAN ports, when a cable is plugged into ports 1-4, the corresponding ports 5-8 are incorrectly activated (port pairing) and ports 5-8 cannot function independently.

So after I found a remote code execution vulnerability in the device, I gained root access to the stock firmware and started gathering information about the device.

/www_wayos # cat /proc/mtd
dev:    size   erasesize  name
mtd0: 001c0000 00010000 "LOADER"
mtd1: 00010000 00010000 "BDINFO"
mtd2: 00010000 00010000 "SYSINFO"
mtd3: 00010000 00010000 "JFFS2 FACTORYDATA"
mtd4: 00010000 00010000 "JFFS2 SYSDATA"
mtd5: 00a00000 00010000 "JFFS2 FILESYSTEM"
mtd6: 01400000 00010000 "RUNTIME"
mtd7: 02000000 00010000 "RUNTIME2"
/www_wayos # cat /proc/cpuinfo
system type             : RTL9300
machine                 : RTL9300
processor               : 0
cpu model               : MIPS 34Kc V5.5
BogoMIPS                : 530.41
wait instruction        : yes
microsecond timers      : yes
tlb_entries             : 32
extra interrupt vector  : yes
hardware watchpoint     : no
isa                     : mips1 mips32r2
ASEs implemented        : mips16
shadow register sets    : 1
kscratch registers      : 0
package                 : 0
core                    : 0

And here is my current DTS file:

// SPDX-License-Identifier: GPL-2.0-or-later
#include "rtl930x.dtsi"

#include <dt-bindings/input/input.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/leds/common.h>
#include <dt-bindings/thermal/thermal.h>

/ {
  compatible = "xikestor,sks8300-8t", "realtek,rtl930x-soc";
  model = "XikeStor SKS8300-8T";

  memory@0 {
    device_type = "memory";
    reg = <0x00000000 0x10000000>,
          <0x20000000 0x10000000>; 
  };

  aliases {
    led-boot = &led_sys;
    led-failsafe = &led_sys;
    led-running = &led_sys;
    led-upgrade = &led_sys;
  };

  chosen {
    stdout-path = "serial0:115200n8";
  };

  i2c_master: i2c@1b00036c {
    compatible = "realtek,rtl9300-i2c";
    reg = <0x1b00036c 0x3c>;
    #address-cells = <1>;
    #size-cells = <0>;
    scl-pin = <8>;
    sda-pin = <9>;
    clock-frequency = <100000>;

    fan_controller: fan-controller@6a {
      compatible = "realtek,fan-controller";
      reg = <0x6a>;
      status = "okay";
    };
  };

  keys {
    compatible = "gpio-keys";

    button-reset {
      label = "reset";
      gpios = <&gpio0 22 GPIO_ACTIVE_LOW>;
      linux,code = <KEY_RESTART>;
    };
  };

  leds {
    compatible = "gpio-leds";

    led_sys: led-0 {
      gpios = <&gpio0 23 GPIO_ACTIVE_HIGH>;
      color = <LED_COLOR_ID_GREEN>;
      function = LED_FUNCTION_STATUS;
    };
  };

  led_set {
    compatible = "realtek,rtl9300-leds";
    active-low;

    /*
     * LED set 0
     *
     * - LED[0](Green): 10G/LINK/ACT
     * - LED[1](Amber): 10M/100M/1G/2.5G/5G/LINK/ACT
     */
    led_set0 = <0x0baa 0x0a01>;
  };

  temp_sensor: temp-sensor@48 {
    compatible = "national,lm75";
    reg = <0x48>;
  };

  thermal-zones {
      main_thermal: main-thermal {
          polling-delay = <5000>;

          thermal-sensors = <&temp_sensor 0>;

          trips {
              fan_on: fan-on {
                  temperature = <50000>;
                  hysteresis = <2000>;
                  type = "active";
              };
          };

          cooling-maps {
              map0 {
                  trip = <&fan_on>;
                  cooling-device = <&fan_controller 0 1>;
              };
          };
      };
  };
};

&mdio_aux {
  status = "okay";

  gpio1: gpio@0 {
    compatible = "realtek,rtl8231";
    reg = <0>;

    gpio-controller;
    #gpio-cells = <2>;
    gpio-ranges = <&gpio1 0 0 37>;
    status = "okay";

    led-controller {
      compatible = "realtek,rtl8231-leds";
      status = "disabled";
    };
  };
};

&spi0 {
  status = "okay";

  flash@0 {
    compatible = "jedec,spi-nor";
    reg = <0>;
    spi-max-frequency = <10000000>;

    partitions {
      compatible = "fixed-partitions";
      #address-cells = <1>;
      #size-cells = <1>;

      partition@0 {
        label = "u-boot";
        reg = <0x0 0x100000>;
        read-only;
      };

      /* "flash_raw" on stock */
      partition@100000 {
        label = "board-info";
        reg = <0x100000 0x30000>;
        read-only;
      };

      partition@130000 {
        label = "syslog";
        reg = <0x130000 0xd0000>;
        read-only;
      };

      /* "flash_user" on stock */
      partition@200000 {
        compatible = "fixed-partitions";
        label = "firmware";
        reg = <0x200000 0x1e00000>;
        #address-cells = <1>;
        #size-cells = <1>;

        partition@0 {
          label = "kernel";
          reg = <0x0 0x800000>;
        };

        partition@800000 {
          label = "rootfs";
          reg = <0x800000 0x1600000>;
        };
      };
    };
  };
};

&ethernet0 {
    mdio: mdio-bus {
        compatible = "realtek,rtl838x-mdio";
        regmap = <&ethernet0>;
        #address-cells = <1>;
        #size-cells = <0>;

        phy0: ethernet-phy@0 {
            compatible = "ethernet-phy-ieee802.3-c45";
            phy-is-integrated;
            reg = <0>;
            sds = <2>;
        };

        phy8: ethernet-phy@8 {
            compatible = "ethernet-phy-ieee802.3-c45";
            phy-is-integrated;
            reg = <8>;
            sds = <3>;
        };

        phy16: ethernet-phy@16 {
            compatible = "ethernet-phy-ieee802.3-c45";
            phy-is-integrated;
            reg = <16>;
            sds = <4>;
        };

        phy20: ethernet-phy@20 {
            compatible = "ethernet-phy-ieee802.3-c45";
            phy-is-integrated;
            reg = <20>;
            sds = <5>;
        };

        phy24: ethernet-phy@18 {
            compatible = "ethernet-phy-ieee802.3-c45";
            phy-is-integrated;
            reg = <24>;
            sds = <6>;
        };

        phy25: ethernet-phy@19 {
            compatible = "ethernet-phy-ieee802.3-c45";
            phy-is-integrated;
            reg = <25>;
            sds = <7>;
        };

        phy26: ethernet-phy@1a {
            compatible = "ethernet-phy-ieee802.3-c45";
            phy-is-integrated;
            reg = <26>;
            sds = <8>;
        };

        phy27: ethernet-phy@1b {
            compatible = "ethernet-phy-ieee802.3-c45";
            phy-is-integrated;
            reg = <27>;
            sds = <9>;
        };
    };
};

&switch0 {
    ports {
        #address-cells = <1>;
        #size-cells = <0>;

        port@0 {
            reg = <0>;
            label = "lan1";
            phy-handle = <&phy0>;
            phy-mode = "usxgmii";
            led-set = <0>;
        };

        port@8 {
            reg = <8>;
            label = "lan2";
            phy-handle = <&phy8>;
            phy-mode = "usxgmii";
            led-set = <0>;
        };

        port@16 {
            reg = <16>;
            label = "lan3";
            phy-handle = <&phy16>;
            phy-mode = "usxgmii";
            led-set = <0>;
        };

        port@20 {
            reg = <20>;
            label = "lan4";
            phy-handle = <&phy20>;
            phy-mode = "usxgmii";
            led-set = <0>;
        };

        port@24 {
            reg = <24>;
            label = "lan5";
            phy-handle = <&phy24>;
            phy-mode = "usxgmii";
            led-set = <0>;
        };

        port@25 {
            reg = <25>;
            label = "lan6";
            phy-handle = <&phy25>;
            phy-mode = "usxgmii";
            led-set = <0>;
        };

        port@26 {
            reg = <26>;
            label = "lan7";
            phy-handle = <&phy26>;
            phy-mode = "usxgmii";
            led-set = <0>;
        };

        port@27 {
            reg = <27>;
            label = "lan8";
            phy-handle = <&phy27>;
            phy-mode = "usxgmii";
            led-set = <0>;
        };

        port@28 {
            ethernet = <&ethernet0>;
            reg = <28>;
            phy-mode = "internal";
            fixed-link {
                speed = <10000>;
                full-duplex;
            };
        };
    };
};

For the port mapping I used this https://svanheule.net/switches/rtl93xx#section9303

  - Port 1 (PHY 0) β†’ SerDes 2
  - Port 2 (PHY 8) β†’ SerDes 3
  - Port 3 (PHY 16) β†’ SerDes 4
  - Port 4 (PHY 20) β†’ SerDes 5
  - Port 5 (PHY 24) β†’ SerDes 6
  - Port 6 (PHY 25) β†’ SerDes 7
  - Port 7 (PHY 26) β†’ SerDes 8
  - Port 8 (PHY 27) β†’ SerDes 9

And after a bit of work, I finally found the binary that sets up the SerDes, fan functionalities, LEDs, etc..., located at /bin/smdrm, which I then decompiled with Ghidra. I then managed get all the functions to rewrite the driver and add support for USXGMII with auto-negotiation in /target/linux/realtek/files-6.6/drivers/net but all my attempts ended in failure...

If a Realtek driver expert happens to read this, I would really appreciate some help or guidance.

EDIT: bootloader with some debug added https://pastebin.com/5yiVT67c
EDIT 2: I have also uploaded all the reversed functions from the stock firmware related to SerDes and USXGMII initialization https://pastebin.com/2vKG9Buu

2 Likes

Someone like @svanheule ?

Check out this PR. Similar hardware. Might give you some ideas.

I already tried with CONFIG_RTL8261N_PHY=y enabled, and the behavior is the same (port pairing issue), except that it sets the 10Gbps mode by default even when I plug in a 1Gbps cable. I also tried modifying the driver for the RTL8261N in target/linux/generic/files/drivers/net/phy/rtl8261n and tweaking some functions to match the ones extracted from the stock firmware but I got the same behavior...

EDIT: bootloader using RTL8261N driver https://pastebin.com/MkvbbtDz

1 Like

Also see https://github.com/openwrt/openwrt/pull/19081

Some tips for you:

2 Likes

Thanks for the tips! It worked!

I was heading in the wrong direction from the beginning. The key was finding the correct rtl9300,smi-address values and removing phy-is-integrated.

Appreciate the pointer to the Realtek docs too!

1 Like

I have one more question. The device has a fan on the board and after some time I was able to figure out how it works and wrote a Bash script to control it. But since that's obviously not the best solution, I'd like the fan to start automatically on boot. I tried adding it to the DTS file but that didn't work. Do you have any tips for that part as well?

Here's the Bash script implementation:

#!/bin/ash

# FAN Control Script for XikeStor - SKS8300 series
# Temperature sensor: LM75 at address 0x48

# I2C Configuration
I2C_BUS=0
I2C_ADDR=0x6a        # FAN controller
TEMP_ADDR=0x48       # LM75 temperature sensor

# Initialize FAN controller
fan_init() {
    echo "Initializing FAN controller..."
    
    # Check if chip exists
    if ! i2cget -y $I2C_BUS $I2C_ADDR 0xfe &>/dev/null; then
        echo "Error: FAN controller not detected"
        return 1
    fi
    
    # Initialization sequence
    i2cset -y $I2C_BUS $I2C_ADDR 0x4e 0x32
    i2cset -y $I2C_BUS $I2C_ADDR 0x48 0x1e
    i2cset -y $I2C_BUS $I2C_ADDR 0x40 0x6e
    i2cset -y $I2C_BUS $I2C_ADDR 0x11 0x55
    i2cset -y $I2C_BUS $I2C_ADDR 0x10 0x00
    
    echo "FAN controller initialized"
}

# Start FAN at normal speed (controlled mode)
fan_start() {
    echo "Starting FAN at normal speed..."
    
    i2cset -y $I2C_BUS $I2C_ADDR 0x11 0x55    # Enable
    i2cset -y $I2C_BUS $I2C_ADDR 0x40 0x6e    # Controlled mode
    i2cset -y $I2C_BUS $I2C_ADDR 0x48 0x1e    # Default speed
    
    echo "FAN started at normal speed"
}

# Start FAN at full speed
fan_start_full() {
    echo "Starting FAN at full speed..."
    
    i2cset -y $I2C_BUS $I2C_ADDR 0x40 0x00    # Full speed mode
    
    echo "FAN started at full speed"
}

# Stop FAN
fan_stop() {
    echo "Stopping FAN..."
    
    i2cset -y $I2C_BUS $I2C_ADDR 0x40 0xff    # Turn OFF
    
    echo "FAN stopped"
}

# Get current RPM
fan_get_rpm() {
    local rpm_reg=$(i2cget -y $I2C_BUS $I2C_ADDR 0x09 2>/dev/null)
    
    if [ -z "$rpm_reg" ]; then
        echo "Error: Failed to read RPM"
        return 1
    fi
    
    # Check FAN mode
    local mode=$(i2cget -y $I2C_BUS $I2C_ADDR 0x40 2>/dev/null)
    
    if [ "$mode" = "0xff" ]; then
        echo "FAN RPM: 0 (FAN is OFF)"
        return 0
    fi
    
    if [ "$rpm_reg" = "0xff" ]; then
        if [ "$mode" = "0x00" ]; then
            echo "FAN RPM: Maximum (full speed mode)"
        else
            echo "FAN RPM: Normal speed"
        fi
        return 0
    fi
    
    # Calculate actual RPM if we get a valid reading
    local dec_value=$((rpm_reg))
    local shifted=$(( (dec_value >> 4) & 0x0F ))
    
    if [ $shifted -eq 0 ]; then
        echo "FAN RPM: 0"
        return 0
    fi
    
    # RPM = 0x1e0000 / ((value >> 4) << 1)
    local rpm=$(( 1966080 / (shifted << 1) ))
    echo "FAN RPM: $rpm"
}

# Get temperature from LM75 sensor
fan_get_temp() {
    # LM75 temperature sensor at address 0x48
    # Register 0x00 contains temperature data (2 bytes)
    
    # Check if LM75 exists
    if ! i2cget -y $I2C_BUS $TEMP_ADDR 0x00 w &>/dev/null; then
        echo "Temperature: Sensor not detected"
        return 1
    fi
    
    # Read temperature (word read for 2 bytes)
    local temp_raw=$(i2cget -y $I2C_BUS $TEMP_ADDR 0x00 w 2>/dev/null)
    
    if [ -z "$temp_raw" ]; then
        echo "Temperature: Read error"
        return 1
    fi
    
    # Convert from hex to decimal
    local temp_dec=$((temp_raw))
    
    # LM75 format: 
    # - Bytes are swapped in word read (LSB MSB)
    # - Need to swap bytes back: ((temp & 0xFF) << 8) | ((temp >> 8) & 0xFF)
    local temp_swapped=$(( ((temp_dec & 0xFF) << 8) | ((temp_dec >> 8) & 0xFF) ))
    
    # Temperature is in upper 9 bits, in 0.5Β°C increments
    # Shift right by 7 to get temperature in 0.5Β°C units
    local temp_half=$(( temp_swapped >> 7 ))
    
    # Check if negative (bit 8 set)
    if [ $(( temp_half & 0x100 )) -ne 0 ]; then
        # Negative temperature (two's complement)
        temp_half=$(( temp_half - 512 ))
    fi
    
    # Convert to degrees Celsius
    local temp_int=$(( temp_half / 2 ))
    local temp_frac=$(( (temp_half % 2) * 5 ))
    
    echo "Temperature: ${temp_int}.${temp_frac}Β°C"
}

# Get FAN status
fan_status() {
    echo "=== FAN Status ==="
    
    # Read control registers
    local reg_40=$(i2cget -y $I2C_BUS $I2C_ADDR 0x40 2>/dev/null)
    local reg_11=$(i2cget -y $I2C_BUS $I2C_ADDR 0x11 2>/dev/null)
    
    echo -n "FAN State: "
    case "$reg_40" in
        "0x00") 
            echo "ON (Full speed mode)"
            ;;
        "0x6e") 
            echo "ON (Normal speed mode)"
            ;;
        "0xff") 
            echo "OFF"
            ;;
        *) 
            echo "Unknown (0x40=$reg_40)"
            ;;
    esac
    
    # Show RPM
    fan_get_rpm
    
    # Show temperature
    fan_get_temp
    
    echo "=================="
}

# Main script
case "$1" in
    init)
        fan_init
        ;;
    start)
        fan_start
        ;;
    start-full)
        fan_start_full
        ;;
    stop)
        fan_stop
        ;;
    rpm)
        fan_get_rpm
        ;;
    temp)
        fan_get_temp
        ;;
    status)
        fan_status
        ;;
    *)
        echo "FAN Control Script for OpenWRT"
        echo "Usage: $0 {init|start|start-full|stop|rpm|temp|status}"
        echo ""
        echo "Commands:"
        echo "  init       - Initialize FAN controller"
        echo "  start      - Start FAN at normal speed"
        echo "  start-full - Start FAN at full speed"
        echo "  stop       - Stop the FAN"
        echo "  rpm        - Get current RPM"
        echo "  temp       - Get temperature from LM75 sensor"
        echo "  status     - Show FAN status"
        echo ""
        echo "Examples:"
        echo "  $0 init       # Initialize on first use"
        echo "  $0 start      # Start at normal speed"
        echo "  $0 start-full # Start at maximum speed"
        echo "  $0 stop       # Stop FAN"
        echo "  $0 status     # Check current status"
        exit 1
        ;;
esac

exit 0

Here is my current DTS file

// SPDX-License-Identifier: GPL-2.0-or-later

#include "rtl930x.dtsi"

#include <dt-bindings/input/input.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/leds/common.h>
#include <dt-bindings/thermal/thermal.h>

/ {
  compatible = "xikestor,sks8300-8t", "realtek,rtl930x-soc";
  model = "XikeStor SKS8300-8T";

  memory@0 {
    device_type = "memory";
    reg = <0x00000000 0x10000000>, /* first 256 MiB */
          <0x20000000 0x10000000>; /* remaining 256 MiB */
  };

  aliases {
    led-boot = &led_sys;
    led-failsafe = &led_sys;
    led-running = &led_sys;
    led-upgrade = &led_sys;
  };

  chosen {
    stdout-path = "serial0:115200n8";
  };

  i2c_master: i2c@1b00036c {
    compatible = "realtek,rtl9300-i2c";
    reg = <0x1b00036c 0x3c>;
    #address-cells = <1>;
    #size-cells = <0>;
    scl-pin = <8>;
    sda-pin = <9>;
    clock-frequency = <100000>;

    fan_controller: fan-controller@6a {
      compatible = "realtek,fan-controller";
      reg = <0x6a>;
      status = "okay";
    };
  };

  keys {
    compatible = "gpio-keys";

    button-reset {
      label = "reset";
      gpios = <&gpio0 22 GPIO_ACTIVE_LOW>;
      linux,code = <KEY_RESTART>;
    };
  };

  leds {
    compatible = "gpio-leds";

    led_sys: led-0 {
      gpios = <&gpio0 23 GPIO_ACTIVE_HIGH>;
      color = <LED_COLOR_ID_GREEN>;
      function = LED_FUNCTION_STATUS;
    };
  };

  led_set {
    compatible = "realtek,rtl9300-leds";
    active-low;

    /*
     * LED set 0
     *
     * - LED[0](Green): 10G/LINK/ACT
     * - LED[1](Amber): 10M/100M/1G/2.5G/5G/LINK/ACT
     */
    led_set0 = <0x0baa 0x0a01>;
  };

  temp_sensor: temp-sensor@48 {
    compatible = "national,lm75";
    reg = <0x48>;
  };

  thermal-zones {
      main_thermal: main-thermal {
          polling-delay = <5000>;

          thermal-sensors = <&temp_sensor 0>;

          trips {
              fan_on: fan-on {
                  temperature = <50000>;
                  hysteresis = <2000>;
                  type = "active";
              };
          };

          cooling-maps {
              map0 {
                  trip = <&fan_on>;
                  cooling-device = <&fan_controller 0 1>;
              };
          };
      };
  };
};

&mdio_aux {
  status = "okay";

  gpio1: gpio@0 {
    compatible = "realtek,rtl8231";
    reg = <0>;

    gpio-controller;
    #gpio-cells = <2>;
    gpio-ranges = <&gpio1 0 0 37>;
    status = "okay";

    led-controller {
      compatible = "realtek,rtl8231-leds";
      status = "disabled";
    };
  };
};

&spi0 {
  status = "okay";

  flash@0 {
    compatible = "jedec,spi-nor";
    reg = <0>;
    spi-max-frequency = <10000000>;

    partitions {
      compatible = "fixed-partitions";
      #address-cells = <1>;
      #size-cells = <1>;

      partition@0 {
        label = "u-boot";
        reg = <0x0 0x100000>;
        read-only;
      };

      /* "flash_raw" on stock */
      partition@100000 {
        label = "board-info";
        reg = <0x100000 0x30000>;
        read-only;
      };

      partition@130000 {
        label = "syslog";
        reg = <0x130000 0xd0000>;
        read-only;
      };

      /* "flash_user" on stock */
      partition@200000 {
        compatible = "fixed-partitions";
        label = "firmware";
        reg = <0x200000 0x1e00000>;
        #address-cells = <1>;
        #size-cells = <1>;

        partition@0 {
          label = "kernel";
          reg = <0x0 0x800000>;
        };

        partition@800000 {
          label = "rootfs";
          reg = <0x800000 0x1600000>;
        };
      };
    };
  };
};

&ethernet0 {
    mdio: mdio-bus {
        compatible = "realtek,rtl838x-mdio";
        regmap = <&ethernet0>;
        #address-cells = <1>;
        #size-cells = <0>;

        phy0: ethernet-phy@0 {
            compatible = "ethernet-phy-ieee802.3-c45";
            reg = <0>;
            sds = <2>;
            rtl9300,smi-address = <0 0>;
        };

        phy8: ethernet-phy@8 {
            compatible = "ethernet-phy-ieee802.3-c45";
            reg = <8>;
            sds = <3>;
            rtl9300,smi-address = <0 1>;
        };

        phy16: ethernet-phy@16 {
            compatible = "ethernet-phy-ieee802.3-c45";
            reg = <16>;
            sds = <4>;
            rtl9300,smi-address = <0 2>;
        };

        phy20: ethernet-phy@20 {
            compatible = "ethernet-phy-ieee802.3-c45";
            reg = <20>;
            sds = <5>;
            rtl9300,smi-address = <0 3>;
        };

        phy24: ethernet-phy@24 {
            compatible = "ethernet-phy-ieee802.3-c45";
            reg = <24>;
            sds = <6>;
            rtl9300,smi-address = <1 0>;
        };

        phy25: ethernet-phy@25 {
            compatible = "ethernet-phy-ieee802.3-c45";
            reg = <25>;
            sds = <7>;
            rtl9300,smi-address = <1 1>;
        };

        phy26: ethernet-phy@26 {
            compatible = "ethernet-phy-ieee802.3-c45";
            reg = <26>;
            sds = <8>;
            rtl9300,smi-address = <1 2>;
        };

        phy27: ethernet-phy@27 {
            compatible = "ethernet-phy-ieee802.3-c45";
            reg = <27>;
            sds = <9>;
            rtl9300,smi-address = <1 3>;
        };
    };
};

&switch0 {
    ports {
        #address-cells = <1>;
        #size-cells = <0>;

        port@0 {
            reg = <0>;
            label = "lan1";
            phy-handle = <&phy0>;
            phy-mode = "usxgmii";
            led-set = <0>;
        };

        port@8 {
            reg = <8>;
            label = "lan2";
            phy-handle = <&phy8>;
            phy-mode = "usxgmii";
            led-set = <0>;
        };

        port@16 {
            reg = <16>;
            label = "lan3";
            phy-handle = <&phy16>;
            phy-mode = "usxgmii";
            led-set = <0>;
        };

        port@20 {
            reg = <20>;
            label = "lan4";
            phy-handle = <&phy20>;
            phy-mode = "usxgmii";
            led-set = <0>;
        };

        port@24 {
            reg = <24>;
            label = "lan5";
            phy-handle = <&phy24>;
            phy-mode = "usxgmii";
            led-set = <0>;
        };

        port@25 {
            reg = <25>;
            label = "lan6";
            phy-handle = <&phy25>;
            phy-mode = "usxgmii";
            led-set = <0>;
        };

        port@26 {
            reg = <26>;
            label = "lan7";
            phy-handle = <&phy26>;
            phy-mode = "usxgmii";
            led-set = <0>;
        };

        port@27 {
            reg = <27>;
            label = "lan8";
            phy-handle = <&phy27>;
            phy-mode = "usxgmii";
            led-set = <0>;
        };

        port@28 {
            ethernet = <&ethernet0>;
            reg = <28>;
            phy-mode = "internal";
            fixed-link {
                speed = <10000>;
                full-duplex;
            };
        };
    };
};
1 Like

Sorry no idea about this area. Have a look at the master rtl838x thread.

Request from my side: Please add the device via pull request.

Yes, I plan to submit a proper pull request to add support for the device. I'm currently in the final testing phase before doing so.

The initramfs image boots fine over TFTP via U-Boot (bootm after tftpboot), but I'm running into an issue with persistent installation. After flashing the sysupgrade image using sysupgrade -n, the device fails to boot, and U-Boot throws:

## Invalid image header
## Boot from partition 0 failed.
## Boot from both partitions are all failed.

I'm not entirely sure what's causing the issue but I suspect it might be related to the partitioning defined in my DTS file.

&spi0 {
  status = "okay";
  flash@0 {
    compatible = "jedec,spi-nor";
    reg = <0>;
    spi-max-frequency = <10000000>;
    partitions {
      compatible = "fixed-partitions";
      #address-cells = <1>;
      #size-cells = <1>;
      partition@0 {
        label = "u-boot";
        reg = <0x0 0x1c0000>;  // Match stock LOADER size
        read-only;
      };
      /* "flash_raw" on stock */
      partition@1c0000 {
        label = "board-info";
        reg = <0x1c0000 0x10000>;  // Match stock BDINFO size
        read-only;
      };
      partition@1d0000 {
        label = "sysinfo";
        reg = <0x1d0000 0x10000>;  // Match stock SYSINFO size
        read-only;
      };
      partition@1e0000 {
        label = "factory-data";
        reg = <0x1e0000 0x10000>;  // Match stock JFFS2_FACTORYDATA size
      };
      partition@1f0000 {
        label = "jffs";
        reg = <0x1f0000 0x10000>;  // Match stock JFFS2_SYSDATA size
      };
      partition@200000 {
        label = "jffs2";
        reg = <0x200000 0xa00000>;  // Match stock JFFS2_FILESYSTEM
      };
      partition@c00000 {
        compatible = "fixed-partitions";
        label = "firmware";
        reg = <0xc00000 0x1400000>;  // Match stock RUNTIME1 size
        #address-cells = <1>;
        #size-cells = <1>;
        partition@0 {
          label = "kernel";
          reg = <0x0 0x800000>;
        };
        partition@800000 {
          label = "rootfs";
          reg = <0x800000 0xc00000>; 
        };
      };
    };
  };
};

It could also be something in the rtl930x.mk definition for the device:

define Device/xikestor_sks8300-8t
  SOC := rtl9303
  DEVICE_VENDOR := XikeStor
  DEVICE_MODEL := SKS8300-8T
  BLOCKSIZE := 64k
  KERNEL_SIZE := 8192k
  IMAGE_SIZE := 20480k
  IMAGE/sysupgrade.bin := pad-extra 256 | append-kernel | xikestor-nosimg | \
  jffs2 nos.img -e 4KiB -x lzma | pad-to $$$$(KERNEL_SIZE) | \
  append-rootfs | pad-rootfs | append-metadata | check-size
endef
TARGET_DEVICES += xikestor_sks8300-8t

Any insight or suggestions would be greatly appreciated!

 QRTL9300# # flshow
=============== FLASH Partition Layout ===============
Index  Name       Size       Address
------------------------------------------------------
 0     LOADER     0x1c0000   0xb4000000-0xb41bffff
 1     BDINFO     0x10000    0xb41c0000-0xb41cffff
 2     SYSINFO    0x10000    0xb41d0000-0xb41dffff
 3     JFFS2_FACTORYDATA 0x10000    0xb41e0000-0xb41effff
 4     JFFS2_SYSDATA 0x10000    0xb41f0000-0xb41fffff
 5     JFFS2_FILESYSTEM 0xa00000   0xb4200000-0xb4bfffff
 6     RUNTIME1   0x1400000  0xb4c00000-0xb5ffffff
 7     RUNTIME2   0x0        0xb4000000-0xb3ffffff
======================================================

From the stock firmware

/www_wayos # cat /proc/mtd
dev:    size   erasesize  name
mtd0: 001c0000 00010000 "LOADER"
mtd1: 00010000 00010000 "BDINFO"
mtd2: 00010000 00010000 "SYSINFO"
mtd3: 00010000 00010000 "JFFS2 FACTORYDATA"
mtd4: 00010000 00010000 "JFFS2 SYSDATA"
mtd5: 00a00000 00010000 "JFFS2 FILESYSTEM"
mtd6: 01400000 00010000 "RUNTIME"
mtd7: 02000000 00010000 "RUNTIME2"

@musashino -san γŠι‘˜γ„γ—γΎγ™

You cannot use the U-Boot environment to figure out flash layout. It's just some arbitrary RTK default. This is what it looks like on the Onti ONT-S508CL-8S (identical to. XikeStor SKS8300-8X):

RTL9300# flshow
=============== FLASH Partition Layout ===============
Index  Name       Size       Address
------------------------------------------------------
 0     LOADER     0xe0000    0xb4000000-0xb40dffff
 1     BDINFO     0x10000    0xb40e0000-0xb40effff
 2     SYSINFO    0x10000    0xb40f0000-0xb40fffff
 3     JFFS2_CFG  0x100000   0xb4100000-0xb41fffff
 4     JFFS2_LOG  0x100000   0xb4200000-0xb42fffff
 5     RUNTIME1   0xe80000   0xb4300000-0xb517ffff
 6     RUNTIME2   0xe80000   0xb5180000-0xb5ffffff
======================================================

Notice that it doesn't match the DTS at all.

You need the layout from the stock firmware. A bold guess would be that it is similar to the SKS8300-8X, but checking is probably easier than guessing....

EDIT: The real layout is found in the mtdparts variable:

RTL9300# printenv mtdparts
mtdparts=mtdparts=spi_nor:30M@2M(flash_user),832K@1216K(sys_log),192K@1M(raw),1M@0(bootrom);

I think the hardware isn't exactly the same. I did try to compile my image based on the SKS8300-8X DTS config but it didn't work.

mtdparts is not defined in the U-Boot environment variables.

QRTL9300# # printenv mtdparts
## Error: "mtdparts" not defined
RTL9300# # printenv         
baudrate=115200
boardmodel=RTL9303_8X8261BE_V1
bootcmd=boota
bootdelay=3
ethact=rtl9300#0
ethaddr=00:E0:4C:00:00:00
fileaddr=81000000
filesize=B30621
ipaddr=10.42.0.2
ledModeInitSkip=0
serverip=10.42.0.1
stderr=serial
stdin=serial
stdout=serial

Environment size: 274/65532 bytes

In the stock firmware I am getting:

/www_wayos # cat /proc/mtd
dev:    size   erasesize  name
mtd0: 001c0000 00010000 "LOADER"
mtd1: 00010000 00010000 "BDINFO"
mtd2: 00010000 00010000 "SYSINFO"
mtd3: 00010000 00010000 "JFFS2 FACTORYDATA"
mtd4: 00010000 00010000 "JFFS2 SYSDATA"
mtd5: 00a00000 00010000 "JFFS2 FILESYSTEM"
mtd6: 01400000 00010000 "RUNTIME"
mtd7: 02000000 00010000 "RUNTIME2"