Build hlk-rm04 OpenWRT image

Howto Build hlk-rm04 OpenWRT image, in this tutorial we will show u howto succesfully build an OpenWRT image for the hlk-rm04 module. On this page we are going to show u howto make your own OpenWRT image for the Hi-link hlk-rm04 module. We use Ubuntu as our build machine so all the commands are for Ubuntu but might work on other distro’s as well. This guide does not go about configuring Ubuntu and if you get errors on building the final OpenWRT image then u probably miss some Ubuntu dependencies/packages.

Basic buildsystem

Never build an OpenWRT image as a root user!

Create a new directory for the build files and run the code below to clone the OpenWRT build files in it.

git clone

git clone

cd openwrt
./scripts/feeds update -a

Update OpenWRT feed

./scripts/feeds install -a

Install OpenWRT feed

Needed changes to Build hlk-rm04 OpenWRT image

Now we can change some source files to fully benefit the bigger flash and RAM memory. Lets start with the .dts file first, in this file the sizes of the flash memory and the RAM memory are configured. The default OpenWRT configuration uses the 4MB flash with 16MB RAM memory and we will want to upgrade that to the 8MB flash with 32MB RAM memory.

U can find the .dts file in the folder

So open this file with your text editor and look for the following lines;

compatible = "hilink,hlk-rm04", "ralink,rt5350-soc";
model = "HILINK HLK-RM04";

chosen {
bootargs = "console=ttyS1,57600";

and change it into;

compatible = "hilink,hlk-rm04", "ralink,rt5350-soc";
model = "HILINK HLK-RM04";

memory@0 {
device_type = "memory";
reg = <0x0 0x2000000>;

chosen {
bootargs = "console=ttyS1,57600";

look for the lines;

partition@50000 {
compatible = "denx,uimage";
label = "firmware";
reg = <0x50000 0x3b0000>;

change it into;

partition@50000 {
compatible = "denx,uimage";
label = "firmware";
reg = <0x50000 0x7b0000>;

After these changes your module should use all the memory space available.

Add Ser2net with Luci integration for RM04

Preventing OpenWRT to interfere with ser2net

Since these devices are mostly used for there uart connections you probably want to add ser2net to luci, for this to work you will need to change some more files….
By default Openwrt will ask for login details when u start talking to the configured ser2net port. If your application doesn’t use login u will have to disable that by changing the following file.


The original looks like;

::sysinit:/etc/init.d/rcS S boot
::shutdown:/etc/init.d/rcS K shutdown

just comment out the last line so it looks like this;

::sysinit:/etc/init.d/rcS S boot
::shutdown:/etc/init.d/rcS K shutdown

Then save the file

The next file to change is sysctl.conf so OpenWRT won’t push messages to the uart console. You can find the file in
Open it and add this line;
kernel.printk = 0 4 1 7
and save the file.

The Ser2net files for the hi-link hlk-rm04 module

Now we need to add/change the files needed for the ser2net package which we slightly modified to suit our needs and also the files to integrate ser2net into Luci.

By default the ser2net package is allready added into packages we just need to modify 1 file a little to make sure any configuration changes are applied after save and applied using Luci. The file we want to change can be found below.


Scroll down to the bottom of the file and add the following lines to it;

service_triggers () {
procd_add_reload_trigger "ser2net"
procd_add_config_trigger "config.change" "ser2net" /etc/init.d/ser2net restart
procd_add_config_trigger "config.change" "/etc/config/ser2net" /etc/init.d/ser2net restart

After that save the file.
The next changes will add support for ser2net inside Luci goto the next directory;


and create a new directory called “luci-app-ser2net”
Inside this directory create a file called “Makefile” and copy the lines below into it;

include $(TOPDIR)/
LUCI_TITLE:=Serial to network module
include ../../
# call BuildPackage - OpenWrt buildroot signature

and save this file, next we create a new directory in the current working directory called “luasrc”. When u created this directory go inside it. Inside the “luasrc” directory we create 2 new directories called “controller” and “model” after creating them let’s go inside controller first. We create a new file called “ser2net.lua” in this directory and copy the below content in it;

module("luci.controller.ser2net", package.seeall)
function index()
entry({"admin", "services", "ser2net"}, alias("admin", "services", "ser2net", "config"), "ser2net").i18n = "ser2net"
entry({"admin", "services", "ser2net", "config"}, cbi("ser2net"))

and save the file, after this go back up 1 directory and enter the directory called “model” inside this directory create a new directory called “cbi” and create a new file inside that directory called “ser2net.lua” and copy the lines below to it.

m = Map("ser2net", translate("ser2net"),
translate("The ser2net allows telnet and tcp sessions to be established with a unit's serial ports.<br/>"))

function m.on_after_save(self)
luci.sys.init.enable("ser2net")"/etc/init.d/ser2net restart >/dev/null 2>&1")

s = m:section(TypedSection, "proxy", translate("Description"),
translate("The program comes up normally as a service, opens the TCP ports specified in the configuration file, and waits for connections.<br/>Once a connection occurs, the program attempts to set up the connection and opens the serial port.<br/>If another user is already using the connection or serial port, the connection is refused with an error message.<br/><br/>Manual changes can be made in /tmp/ser2net"))

s.anonymous = true
s.addremove = true

enabled = s:option(Value, "enabled", translate("enable or disable"),
translate("Enable or disable this config."))

enabled.rmempty = false
enabled:value("1", translate("ON"))
enabled:value("0", translate("Off"))
enabled.default = "1"

port = s:option(Value, "port", translate("Address and/or TCP Port"),
translate("A port number may be of the form [host,]port, such as,2000 or localhost,2000.<br/>If this is specified, it will only bind to the IP address specified for the port.<br/>Otherwise, it will bind to all the ports on the machine."))

port.rmempty = false
port.default = "10000"

protocol = s:option(Value, "protocol", translate("Protocol"),
translate("Either raw, rawlp, telnet or off. off disables the port from accepting connections.<br/>It can be turned on later from the control port.<br/>raw enables the port and transfers all data as-is between the port and the long.<br/>rawlp enables the port and transfers all input data to device, device is open without any termios setting.<br/>It allow to use /dev/lpX devices and printers connected to them.<br/>telnet enables the port and runs the telnet protocol on the port to set up telnet parameters."))
protocol.rmempty = false
protocol:value("raw", translate("Raw"))
protocol:value("rawlp", translate("Rawlp"))
protocol:value("telnet", translate("Telnet"))
protocol:value("off", translate("OFF"))
protocol.default = "raw"

baudrate = s:option(Value, "baudrate", translate("Baudrate"),
translate("Options 300, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200 set the various baud rates."))
baudrate.rmempty = false
baudrate:value("300", translate("300"))
baudrate:value("1200", translate("1200"))
baudrate:value("2400", translate("2400"))
baudrate:value("4800", translate("4800"))
baudrate:value("9600", translate("9600"))
baudrate:value("19200", translate("19200"))
baudrate:value("38400", translate("38400"))
baudrate:value("57600", translate("57600"))
baudrate:value("115200", translate("115200"))
baudrate.default = "115200"

databits = s:option(Value, "databits", translate("Databits"),
translate("Set the number of data bits."))
databits.rmempty = false
databits:value("7", translate("7"))
databits:value("8", translate("8"))
databits.default = "8"

parity = s:option(Value, "parity", translate("Parity"),
translate("Set the parity EVEN, ODD or NONE."))
parity.rmempty = false
parity:value("even", translate("EVEN"))
parity:value("odd", translate("ODD"))
parity:value("none", translate("NONE"))
parity.default = "none"

stopbits = s:option(Value, "stopbits", translate("Stopbits"),
translate("Set the number of stop bits."))
stopbits.rmempty = false
stopbits:value("1", translate("1"))
stopbits:value("2", translate("2"))
stopbits.default = "1"

rtscts = s:option(Value, "rtscts", translate("RTSCTS"),
translate("Turns hardware flow control ON or OFF."))
rtscts.rmempty = false
rtscts:value("false", translate("OFF"))
rtscts:value("true", translate("ON"))
rtscts.default = "false"

xonxoff = s:option(Value, "xonxoff", translate("XONXOFF"),
translate("Changes XON/XOFF values."))
xonxoff.rmempty = false
xonxoff:value("false", translate("OFF"))
xonxoff:value("true", translate("ON"))
xonxoff.default = "false"

timeout = s:option(Value, "timeout", translate("Timeout"),
translate("The time (in seconds) before the port will be disconnected if there is no activity on it.<br/>A zero value disables this function."))
timeout.rmempty = false
timeout.default = "30"

device = s:option(Value, "device", translate("Device"),
translate("The name of the device to connect to."))
device.rmempty = false
device:value("/dev/ttyS0", translate("ttySo"))
device:value("/dev/ttyS1", translate("ttyS1"))
device.default = "/dev/ttyS1"

return m

Now save that file. These changes give in our opinion the basics u will need to make the hlk-rm04 work smoothly with OpenWRT. So now all the needed files are in place we can continue the build.
Go back to {your_build_dir}/openwrt/ and run the following commands;

./scripts/feeds install -a
./scripts/feeds update -a

All the changes we made are now integrated and will show up in the build config, now run;

Build the hlk-rm04 OpenWRT image

make menuconfig

change the top 3 lines to match the image

make menuconfig OpenWRT

select ser2net package as it shows in the picture;

select ser2net package

select luci webserver as it shows in the picture;

select Luci webserver

At last select luci_app_ser2net and exit the config menu and save your config.

Now run

make -j9 download

OpenWRT make download

where -j9 means to use 8 processor cores u can adjust the numer of cores u want to use
This will download all the needed files before making the image. When it’s done it will look like the picture below. Now run the final command to build the image where 9 still means number of cores -1.

make -j9

Succesfull OpenWRT build

OpenWRT build done?

If the build fails use

make -j1 V=sc

This will show what errors you get so they can be solved. If the build succeeds it will look like the screenshot below.

You will then find your image at the path below.

If you need any extra packages etc you can run make_menuconfig again and select the needed packages and run “make -j9” again.

Flash hlk-rm04 with OpenWRT

To install your new image you will need the below list of materials.

If you don’t wan’t the hassle of building your own image we also sell flashed units with OpenWRT.

For any comments or suggestions you can use the comment section below.