Load shared libraries with preferred base address

For performance, sometimes we need to adjust the address space layout. The following way allows the shared or executable object to be loaded with preferred base address.

When the dynamic link maps the shared object, the virtual address of segment(that in ELF program header) will be used as the mapping address hints.

Type 1
Link with text-segment starting address.

# Adjust base address to 0x10000 */
gcc -shared ... -Wl,-Ttext-segment=0x10000

Type 2
We can adjust the virtual address of loaded segment by linker scripts.

0x1 Get link script template

gcc -shared -Wl,--verbose > ld.script

Clear the contents before and after the ‘equal sign’.

0x2 Adjust the base address

....
SECTIONS
{
    /* Adjust base address to 0x10000 */
    . = SEGMENT_START("text-segment", 0x10000) + SIZEOF_HEADERS;
    ...
}
....

0x3 Link with script

gcc -shared ... -Wl,-T ld.script

Over!

硬盘盒来电自动启动改造

市面上常见的硬盘盒或硬盘柜几乎都设计了电源按钮开关,并不是外部供电就自动开机的,这也是一种保护措施。但如果我们用这类产品连接家庭服务器或NAS的话,在意外停电恢复后,外置硬盘盒设备就不能访问了,需要手工按一下电源开关。那么,有没有方法可以使这类产品能自动开机呢?方法不仅有,还不止一种哦。

下面,我们以ORICO 9528系列硬盘柜为例,介绍几种方案,其中短接和电容两种方法为来电自动开机方式,而继电器和伺服电机两种方法则可由单片机或各种派来远程控制。


短接
顾名思义,就是将微动电源开关一直按压住,可以使用强力胶带或其它任意有效方法实现。
优势:1. 简单有效且无需拆机。
缺陷:1. 仅部分产品有效。 2. 长期短接是否有风险。 3. 来电不稳定期损坏硬盘。

电容
相对直接短接,还可以串接电容来替换微动开关,在来电时,电容充电此时相当于开关按下,当电容充满时,相当于开关释放。
优势:1. 适用于所有微动开关。2. 无长期短接的不确定风险。
缺陷:1. 需要拆机,影响保修。2. 来电不稳定期损坏硬盘。

继电器
使用程控继电器替换电源开关,在来电后主机启动完成的情况下,由程序控制硬盘柜启动。
优势:1. 适用于所有开关情况。2. 无长期短接的不确定风险。3. 无来电不稳定损坏硬盘。
缺陷:1. 需要拆机,影响保修。

伺服电机
在硬盘柜电源按钮外安装伺服电机,由程序控制电机转动,再由连接在电机转轴上的机械臂按压微动开关。
优势:1. 适用于所有开关情况。2. 无长期短接的不确定风险。3. 无来电不稳定损坏硬盘。4. 无需拆机,不影响保修。
缺陷:暂无。

综合来看,采用伺服电机方法即有安全保障,又无拆机风险,同时成本并不高,大概20元左右。

清单
1. MG90S型舵机 x 1。

2. 母对公杜邦线 x 3。

3. 3M VHB强力双面胶带 x 1 (搜索ETC专用类,这种双面胶有一定的厚度和弹性,在舵机旋臂按压时有缓冲空间)。

安装
1. 剪取与舵机机身等长的两段3M双面胶粘与机身一面。
2. 再将舵机粘贴在硬盘盒微动开关处的合适位置之上。


3. 将舵机GND线连接树莓派GPIO的任意GND引脚,舵机的5V线连接树莓派GPIO的其中一个5V引脚,最后将舵机的信号线连接树莓派的任意具有GPIO功能的引脚。

4. 先不需要着急安装舵机的旋臂,在连接好线路并确认控制程序可工作后,再根据实际的旋转角度一点点调节旋臂,使之在转至最大角度时正好轻触微动开关,防止角度过大损坏设备。

使用
因为NanoPi M4的GPIO信号是3V电平,驱动不了MG90S舵机,正好手上有一块闲置的Rpi2,拿到当舵机控制模块(有点大材小用了,反面都是吃灰的命)。

NanoPi M4使用USB3.0连接硬盘盒,真千兆网口传输数据,再通过GPIO发送开关信号给Rpi2。Rpi2就比较简单了,在GPIO上监听信号事件,事件触发就产生PWM脉冲信号控制舵机旋转,按压开关按钮。

Rpi2自然也不需要跑完整的发行版啦,只要一个内核和initramfs中包含一个静态链接的控制程序作为init进程。

如果仅用树莓派来控制,控制舵机的关键程序如下:

    const double duty_up = 2.0;
    const double duty_down = 4.0;
    int i;
 
    for (i = 0; i < 10; i++) {
        gpio_write (fd, 1);
        usleep (duty_down * 200);
        gpio_write (fd, 0);
        usleep ((100.0 - duty_down) * 200);
    }
 
    for (i = 0; i < 10; i++) {
        gpio_write (fd, 1);
        usleep (duty_up * 200);
        gpio_write (fd, 0);
        usleep ((100.0 - duty_up) * 200);
    }

NanoPi+Rpi组合完整版控制程序:
https://gist.github.com/heiher/1d48924da7f134315e7128aad74ca6e1

Over!

NanoPi M4 GPIO

 +------+-----+----------+------+ Model  NanoPi-M4 +------+----------+-----+------+
 | GPIO | wPi |   Name   | Mode | V | Physical | V | Mode |   Name   | wPi | GPIO |
 +------+-----+----------+------+---+----++----+---+------+----------+-----+------+
 |      |     |     3.3V |      |   |  1 || 2  |   |      | 5V       |     |      |
 |      |     | I2C2_SDA |      |   |  3 || 4  |   |      | 5V       |     |      |
 |      |     | I2C2_SCL |      |   |  5 || 6  |   |      | GND(0V)  |     |      |
 |   32 |   7 | GPIO1_A0 |  OUT | 0 |  7 || 8  |   | ALT  | GPIO4_C1 | 15  |  145 |
 |      |     |  GND(0V) |      |   |  9 || 10 |   | ALT  | GPIO4_C0 | 16  |  144 |
 |   33 |   0 | GPIO1_A1 |   IN | 0 | 11 || 12 | 1 | IN   | GPIO1_C2 | 1   |  50  |
 |   35 |   2 | GPIO1_A3 |   IN | 0 | 13 || 14 |   |      | GND(0V)  |     |      |
 |   36 |   3 | GPIO1_A4 |   IN | 0 | 15 || 16 | 0 | IN   | GPIO1_C6 | 4   |  54  |
 |      |     |     3.3V |      |   | 17 || 18 | 0 | IN   | GPIO1_C7 | 5   |  55  |
 |      |     | UART4_TX |      |   | 19 || 20 |   |      | GND(0V)  |     |      |
 |      |     | UART4_RX |      |   | 21 || 22 | 0 | IN   | GPIO1_D0 | 6   |  56  |
 |      |     | SPI1_CLK |      |   | 23 || 24 |   |      | SPI1_CSn |     |      |
 |      |     |  GND(0V) |      |   | 25 || 26 |   | ALT  | GPIO4_C5 | 11  |  149 |
 |      |     | I2C2_SDA |      |   | 27 || 28 |   |      | I2C2_SCL |     |      |
 |      |     | I2S0_LRX |      |   | 29 || 30 |   |      | GND(0V)  |     |      |
 |      |     | I2S0_LTX |      |   | 31 || 32 |   |      | I2S_CLK  |     |      |
 |      |     | I2S0_SCL |      |   | 33 || 34 |   |      | GND(0V)  |     |      |
 |      |     | I2S0SDI0 |      |   | 35 || 36 |   |      | I2S0SDO0 |     |      |
 |      |     | I2S0I1O3 |      |   | 37 || 38 |   |      | I2S0I2O2 |     |      |
 |      |     |  GND(0V) |      |   | 39 || 40 |   |      | I2S0I3O1 |     |      |
 +------+-----+----------+------+---+----++----+---+------+----------+-----+------+

Over!

Nginx WebDAV Service

0x01 Installation

git clone --depth 1 https://github.com/heiher/nginx
cd nginx
git clone --depth 1 https://github.com/heiher/nginx-dav-ext-module
 
./auto/configure --prefix=/opt/nginx \
    --with-compat \
    --with-file-aio \
    --with-http_addition_module \
    --with-http_auth_request_module \
    --with-http_dav_module \
    --with-http_degradation_module \
    --with-http_flv_module \
    --with-http_geoip_module \
    --with-http_gunzip_module \
    --with-http_gzip_static_module \
    --with-http_mp4_module \
    --with-http_realip_module \
    --with-http_secure_link_module \
    --with-http_slice_module \
    --with-http_ssl_module \
    --with-http_stub_status_module \
    --with-http_sub_module \
    --with-http_v2_module \
    --with-pcre-jit \
    --with-threads \
    --add-module=nginx-dav-ext-module
 
make
sudo make install

0x02 Configuration
Main: /opt/nginx/conf/nginx.conf:

#user  nobody;
worker_processes  1;
 
#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;
 
#pid        logs/nginx.pid;
 
 
events {
    worker_connections  1024;
}
 
 
http {
    include       mime.types;
    default_type  application/octet-stream;
 
    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';
 
    #access_log  logs/access.log  main;
 
    sendfile        on;
    #tcp_nopush     on;
 
    #keepalive_timeout  0;
    keepalive_timeout  65;
 
    #gzip  on;
 
    dav_ext_lock_zone zone=foo:10m;
 
    server {
        listen       80;
        server_name  localhost;
 
        #charset koi8-r;
 
        #access_log  logs/host.access.log  main;
 
        location / {
            root   html;
 
            auth_basic Restricted;
            auth_basic_user_file htpasswd;
 
            dav_methods PUT DELETE MKCOL COPY MOVE;
            dav_ext_methods PROPFIND PROPPATCH OPTIONS LOCK UNLOCK;
            dav_ext_lock zone=foo;
            dav_access user:rw group:rw all:r;
 
            client_max_body_size 0;
            create_full_put_path on;
        }
 
        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #    deny  all;
        #}
    }
 
}

Auth: /opt/nginx/conf/htpasswd:

htpasswd -b -c /opt/nginx/conf/htpasswd YOUR_USERNAME YOUR_PASSWORD

Start, Stop and Reload:

# Start
sudo /opt/nginx/sbin/nginx
 
# Stop
sudo /opt/nginx/sbin/nginx -s stop
 
# Reload
sudo /opt/nginx/sbin/nginx -s reload

0x03 Clients
Nautils

Windows 10
Fix authentication and file size limits, open regedit and modify:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\WebClient\Parameters\
BasicAuthLevel = 2
FileSizeLimitInBytes = 0xffffffff



Over!

Install Linux 5.x to NanoPi M4

Source code
https://github.com/heiher/linux/tree/nanopi-m4

git clone -b nanopi-m4 https://github.com/heiher/linux

Install prebuilt

git clone --depth 1 https://github.com/heiher/kernel-nanopi-m4
cd kernel-nanopi-m4
 
./generate.sh /dev/mmcblk0
 
sudo dd if=output/boot/param.img of=/dev/mmcblk0 bs=1M seek=4
sudo dd if=output/boot/kernel.img of=/dev/mmcblk0 bs=1M seek=32
sudo dd if=output/boot/resource.img of=/dev/mmcblk0 bs=1M seek=20
sudo cp -a output/modules/* /lib/modules/
sudo chown -R root:root /lib/modules

Additional patches
* arm64: rk3399: increase CPU frequency during early boot

This is a workaround to fix the following issues. The right way should
be to increase frequency of CPU before boot linux kernel in bootloader.

[   92.165850] watchdog: BUG: soft lockup - CPU#4 stuck for 22s! [swapper/0:1]
[   92.166643] Modules linked in:
[   92.167463] CPU: 4 PID: 1 Comm: swapper/0 Not tainted 5.5.10-ARCH #1
[   92.168025] Hardware name: FriendlyElec NanoPi M4 (DT)
[   92.168672] pstate: 20000005 (nzCv daif -PAN -UAO)
[   92.169504] pc : trace_event_eval_update+0xfc/0x348
[   92.170164] lr : trace_event_eval_update+0x144/0x348
[   92.170652] sp : ffff80001004bcf0
[   92.171112] x29: ffff80001004bcf0 x28: 0000000000000001
[   92.171834] x27: ffff8000118d2228 x26: ffff8000111710b0
[   92.172502] x25: ffff80001180db98 x24: 000000000000000e
[   92.173134] x23: ffff800011746428 x22: 00000000000000ec
[   92.173749] x21: 0000000000000264 x20: 0000000000000158
[   92.174352] x19: ffff8000118bc778 x18: 0000000000000001
[   92.174951] x17: 00000000ed34b782 x16: 00000000d54c3662
[   92.175549] x15: 2d20377b1910031c x14: ff00000000000000
[   92.176140] x13: 0000000000000000 x12: 0000000000000007
[   92.176731] x11: 0101010101010101 x10: 0000000000000005
[   92.177322] x9 : 0000000000000003 x8 : 0000000000000008
[   92.177922] x7 : 1c0310197b37202d x6 : 2d20377b1910031c
[   92.178506] x5 : 0000000000000000 x4 : 000000000000000e
[   92.179085] x3 : ffff8000118bbbee x2 : 0000000000000045
[   92.179671] x1 : 000000000000002c x0 : 0000000000000000
[   92.180263] Call trace:
[   92.180921]  trace_event_eval_update+0xfc/0x348
[   92.181652]  tracer_init_tracefs+0x160/0x1e8
[   92.182304]  do_one_initcall+0x4c/0x218
[   92.182949]  kernel_init_freeable+0x1d0/0x240
[   92.183652]  kernel_init+0x18/0x104
[   92.184245]  ret_from_fork+0x10/0x18

[  133.872912] cpufreq: cpufreq_online: CPU4: Running at unlisted freq: 12000 KHz
[  133.891606] cpufreq: cpufreq_online: CPU4: Unlisted initial frequency changed to: 408000 KHz

Over!