QNX 7.0.0开发总结

1 QNX编译

1.1 基本概念

QNX可以直接使用Linux Makefile编译库和二进制,在Makefile文件中指定CC=aarch64-unknown-nto-qnx7.0.0-g++,或者CC=x86_64-pc-nto-qnx7.0.0-g++,保存退出后,运行source /qnx_sdk_path/qnxsdp-env.sh,然后再运行make即可。

QNX官方不建议直接使用xxx-g++,而是使用q++ -Vxxx,q++通过选项-Vxxx找到对应的g++编译器,如何获取xxx,可以使用q++ -V查询。并且只能将选项-Vxxx加到C语言的CFLAGS或者C++语言的CXXFLAGS中,不能加到其它地方,否则编译会出现各种奇怪的错误。

在q++编译中宏-D_QNX_SOURCE的作用是包括POSIX的头文件,包括数据类型、宏声明、库函数等。如果CXXFLAGS只加了-std=C++11,但没有-D_QNX_SOURCE,就算是包含了头文件unistd.h等,还是无法使用POSIX相关库函数和声明等。C++11先前被称作C++0x。

需要注意的是QNX下Makefile链接线程库使用-pthread而不是Linux风格的-lpthread,而其它的库仍然和Linux一样,需要添加前缀-l,例如-lcrypto。

source /qnx_sdk_path/qnxsdp-env.sh

x86_64-pc-nto-qnx7.0.0-gcc \

-o tcp_server tcp_server.c -lsocket

1.2 showcase

CC = q++

.PHONY: clean

OBJS = src/main.o

CFLAGS = \

-I./include \

-Vgcc_ntox86_64_cxx

LDFLAGS = -pthread -lcrypto

compile every cpp file to object

%.o: %.cpp

$(CC) $(CFLAGS) -c $^ -o $@

link all of the objects to hello

hello: $(OBJS)

$(CC) $(CFLAGS) $(OBJS) $(LDFLAGS) \

-o $@

clean:

rm -rf $(OBJS)

rm -rf hello

1.3 QNX proprietary Makefile

variant:

g-le: A debugging version of a little-endian executable

o-le: executable

a-le: static library, a means archive

so-le: shared library

mkdir my_project

cd my_project

mkdir inc

mkdir src

touch common.mk

touch Makefile

addvariant aarch64 o-le

le: little endian

PINFO: package info

1.4 build_files

xxx.build.tmpl:一般一个分区一个build文件。Because .build file does not support MACRO, could use Linux filepp command to replace MACRO.

filepp -DMACRO_TEST=${MACRO_TEST} \

my.build > my.build_new

on -R0x7 pipe &

-R:表示CPU掩码,亲和性;0x7 = 0111,CPU0、CPU1、CPU2,不包含CPU3

mkifs xxx.build.tmpl xxx.ifs

dumpifs xxx.ifs

/proc/boot

2 进程和sepol

2.1 进程优先级

QNX的线程优先级,是一个0 - 255的数字,数字越大优先级越高。 所以,优先级0是内核中的idle线程;同时,优先级64是一个分界岭,就是说,优先级1 - 63是非特权优先级,一般用户都可以用,而64 - 255必须是有root权限的线程才可以设。QNX进程或者线程刚创建时的优先级是10。

procnto-smp-instr: Instrumented

2.2 QNX secpol

secpol是QNX 7.0才引入的,类似于Android sepolicy,运行on命令时指定参数-T xxx_service_t即可。

编译时需要将SDK 7.0中的aarch64le/bin/secpol和aarch64le/bin/secpolmonitor(不能与secpolgenerate同时运行,因为这2个命令用到同一个目录,运行有冲突)集成到image中。

allow_attach: resmgr_attach()

allow_link: pathmgr_symlink()

SECURE_BOOT_SECPOL

allow_attach io_pkt_v6_hc_t {

/path/to/socket_name

};

/proc/boot/secpol.bin

secpolmonitor -pasno /tmp/secpol.out &

secpolmonitor -pasno /tmp/secpol.out \

-S subrangedAble &

genpol

2.3 列出所有的进程加载了哪些so库

pidin -F "%O"

3 console

3.1 Android vdev console

x86 vdev ser8250

aarch64 ttyAMA0

fdtdump, qnx Configuring guests

vdev vdev-pl011.so

loc 0x1c090000

intr gic:37

3.2 命令

To attach to an existing session:

dtach -a <socket> <options>

Detach from a session

In an attached session, type Ctrl+\

QVM <-> dtach server <-> dtach client <-> QNX shell

ptsname slave (QNX QVM) <-> /dev/ptmx master (QNX dtach, other node by QNX) <-> /tmp/console (QNX dtach, unix-domain socket server) <-> dtach client (dtach -a /tmp/console) <-> QNX shell

3.3 dtach showcase

server:

on -T xxx_t -u 0:0 \

-d /usr/bin/dtach \

-n /path/to/socket_name \

-r winch qvm @/vm/images/linux-la.config

-T apply secpol type to dtach

-u uid:gid

-d daemon

-n new session

-r redraw, winch means windows change

client:

dtach -a /path/to/socket_name

-a attach

3.4 slogger

https://github.com/christianzeroc/openqnx

slog2info是slogger2的客户端。

4 Block

4.1 Block设备

/dev/hd0t12 - t表示type,12表示FAT32分区

/dev/hd1t6 - t表示type,6表示文件系统类型FAT

/fs/usb0

fdisk /dev/hd1 show

dinit:disk initialization

[25-Jan-2022]

mount block device as read write, find command from .build file.

mount -tqnx6 -u -w /dev/xxx /xxx

4.2 Android和QNX共享数据

QNX ->

ls /dev/hd0.*

mkdosfs /dev/hd0.xxx

mount -t dos /dev/hd0.xxx /mnt

Android ->

ls -al /dev/block/by-name/

mount -t vfat -o sync,rw /dev/block/vda17 /mnt/share

5 Display

5.1 keyboard

vdev vdev-virtio-input.so

/usr/share/keyboard/US_101.kbd

slog2info | grep screen

slog2info | grep qvm

5.2 screen

#include <screen/screen.h>

screen_set_event_property_iv()

iv: integer value

cv: char value

6 Network

6.1 FreeBSD

QNX network commands all come from BSD family.

ral0: devnp-ral.so, Ralink

wm0: devnp-e1000.so, wiseman, name comes from FreeBSD

nw_dll_syms

https://github.com/ownmac/qnx_drv/tree/master/hardware/devnp/e1000

6.2 Basic Commands

io-pkt-v6-hc: hardware crypto, crypto is OpenSSL library.

TUNnel: peer=/dev/qvm/la/la_to_host,\

bind=/dev/vdevpeer/vp0,

on io-pkt-v6-hc -d vdevpeer-net \

peer=/dev/qvm/la/la_to_host,\

bind=/dev/vdevpeer/vp0,\

mac=bbbbbbbbbbbb

mount -T io-pkt -o <options>

options for network driver

unload eth0 driver

call driver xxx_detach()

ifconfig eth0 destroy

ifconfig bridge0 create

ifconfig bridge0 destroy

brconfig bridge0 delete eth0

6.3 iptables NAT for hypervisor

PREROUTING:DNAT专用。

POSTROUTING:SNAT专用。

MASQUERADE:SNAT转换时,如果--to-source的地址经常变化,那么就无法在iptables命令中固定,譬如路由器WAN口上的IP地址,内网设备通过WAN口访问外网时,只要指定使用MASQUERADE参数,iptables就会统一将内网设备的IP地址替换为路由器WAN口的IP地址。

Figure 6-1 NAT chain

vp0: 192.168.0.98 (QNX veth)

eth0: 192.168.0.99 (Android veth)

eth1: 192.168.5.99 (Android USB Ethernet)

Because PC could not get QNX vp0 MAC, so use the following commands for NAT, PC client should connect eth1 IP.

client -> eth1 -> eth0 -> vp0 -> server

iptables -I FORWARD 1 -i eth1 -o eth0 -j ACCEPT

iptables -I FORWARD 1 -i eth0 -o eth1 -j ACCEPT

iptables -t nat -A PREROUTING -i eth1 -j DNAT --to-destination 192.168.0.98

iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

echo 1 > /proc/sys/net/ipv4/ip_forward

6.4 QNX sshd

passwordless登陆,QNX Neutrino 6.6.0用户密码加密默认算法是SHA-512,1000轮计算,并附带16字节的盐值。

  1. Windows puttygen产生公匙和私匙.ppk

  2. Windows WinSCP导入私匙.ppk

  3. 将Windows puttygen产生的公匙转换为QNX的格式

QNX shell:

ssh-keygen -i -f win_rsa.pub > /path/to/authorized_keys

  1. /path/to/sshd_config

StrictModes no

PasswordAuthentication yes

PubkeyAuthentication yes

AuthorizedKeysFile /path/to/authorized_keys

6.5 Windows as ssh server

  1. Install ssh server for Win10: BvSshServer (original name is WinSSHD)

https://www.bitvise.com/ssh-server-download

Bitvise SSH Server installer

a) Personal Edition

b) Open easy settings

c) Server settings

d) Virtual accounts

  • Virtual account password

  • test/888888

  • Save changes

e) Start Server

  1. 在QNX环境下,将Windows下的文件复制到QNX系统中:

scp -S /path/to/ssh virtual_account_name@192.168.3.181:/d:/test/config.ips /tmp

如果ssh不在/usr/bin/ssh下,需要给scp指定-S参数,否则scp执行失败。

6.6 QNX Momentics Debug

  1. QNX shell

Run qconn, default qconn port: 8000

Enable bridge or NAT

  1. Windows Momentics IDE

[Windows][Perspective][Open Perspective][QNX System Information]

[Target Navigator][New QNX Target]

Configure IP and 8000, then Momentics will connect to QNX automatically.

6.7 eAVB

ptpd-avb: gPTP

ptpd: IEEE1588 v2

6.8 QNX adb test

  1. Android
    ip route get <X.Y.Z.5>
    ip rule add to X.Y.Z.0/24 lookup main pref 9999

setprop service.adb.tcp.port 5555

stop adbd

start adbd

iptables-save | grep 5555

iptables -A INPUT -i eth0 -p tcp -m tcp --dport 5555 -j ACCEPT

iptables -A OUTPUT -o eth0 -p tcp -m tcp --dport 5555 -j ACCEPT

  1. QNX

mount block device as read write, find command from .build file.

mount -tqnx6 -u -w /dev/xxx /xxx

Copy libnbutil.so.1 to /path/to/lib as LD_LIBRARY_PATH shown.
route get <ANDROID_IP>

adb connect <ANDROID_IP>

adb shell

7 x86 USB

7.1 FreeBSD

QNX USB API and umass (src/sys/dev/usb/umass.c) all come from BSD family.

FreeBSD SCSI software architecture is called CAM (Common Access Method), it developed by Future Domain and other SCSI vendors. Linux has little support for a SCSI CAM system yet (mainly for booting from hard disk). CAM even supports target mode, so one could disguise ones computer as a peripheral hardware device (e.g. for a small SCSI net).

7.2 usblauncher_otg

client communicates with io-usb through /dev/io-usb/io-usb

pps: Persistent Publish/Subscribe

/pps/qnx/device/usb_ctrl

usbd_alloc(): /memory/below4G, pidin syspage=asinfo (Address Space Information)

pidin -p qvm irqs

while true; do /bin/slay qvm; \

if [ $? -ne 1 ]; then break; fi; \

done

io-usb-otg -d xhci

devb-umass cam pnp

usb -vvvv

slay devb-umass

7.3 USB PHY Tunning

  1. QNX设备地址映射函数

#include <sys/mman.h>

#include <sys/neutrino.h>

ThreadCtl(_NTO_TCTL_IO, 0);

void *ptr = mmap_device_memory(0,

len,

PROT_READ|PROT_WRITE| \

PROT_NOCACHE,

0,

0xb8000);

if (ptr == MAP_FAILED) {}

  1. in32_x86 and out32

get xHCI BAR0 in QNX, skip bit0-bit3 of BAR0

pci-tool -d 0:21:0 --read=CFG:0x10

APL (Gen9, A39X0) 8-port MPH xHCI PORTSC1

in32_x86 <addr from the last step + 0x480>

7.4 x86 xHCI透传

APL (Gen9, A39X0) 8-port MPH xHCI透传给Android后,尽管在QNX下可以使用in32_x86命令和函数mmap_device_memory()读写xHCI寄存器,但是由于IOMMU中仍然有xHCI的DMAR和INTR配置,所以即使卸载Android端xHCI驱动,加载QNX端xHCI驱动,也不会工作;要想让xHCI在QNX下可以工作,需要删除xHCI在IOMMU中的DMAR和INTR配置。

8 x86 GPIO
8.1 P2SB
PCH(Platform Controller Hub)上大部分设备可以通过PCIe或IO方式访问,但PCH上部分设备需要访问PCH的私有空间,这部分空间通过P2SB(Primary to SideBand)的SBREG_BAR寄存器映射到内存空间,这段空间被称为PCR(PCH Private Configuration Space Register)。每个设备对应一个PortID,PortID表示设备在PCR空间的偏移量,再加上寄存器偏移就可以获取寄存器的地址。

8.2 P2SB GPIO
x86下GPIO寄存器位于PCH的私有空间。GPIO被分组,每组对应一个PCR的PortID。GPIO community和PortID的对应关系如下所示。
SouthWest: 0xC0
NorthWest: 0xC4
North: 0xC5
West: 0xC7

每个community的每个GPIO有2个寄存器,分别是PADCFG0(偏移0)和PADCFG1(偏移4),2个寄存器占用8个字节的地址,所以计算某个GPIO 2个寄存器的绝对地址方法如下,其中PortID是每个GPIO community在PCR空间的偏移量。
基地址pad_regs = 0xf8000000(P2SB bar0) + (PortID << 16) + 0x500(read from PADBAR);
某个GPIO padcfg0的绝对地址 = pad_regs + PADCFG0 + 在bank内的GPIO编号 x 8;
某个GPIO padcfg1的绝对地址 = pad_regs + PADCFG1 + 在bank内的GPIO编号 x 8;

每个community的32个GPIO公用2个寄存器,分别是GPI_IS(GPI Interrupt Status)和GPI_IE(GPI Interrupt Enable),2个中断相关寄存器的绝对地址计算方法如下,其中PortID是每个GPIO community在PCR空间的偏移量。
基地址regs = 0xf8000000(P2SB bar0) + (PortID << 16);
某个GPIO GPI_IS的绝对地址 = regs + 0x100(GPI_IS)+ 在bank内的GPIO编号 / 32;
某个GPIO GPI_IE的绝对地址 = regs + 0x110(GPI_IE)+ 在bank内的GPIO编号 / 32;

/sys/class/gpio/gpiochip434/label

跟dts或者ACPI dsl文件对应上,是哪一组

gpiochip434 - North

gpiochip357 - Northwest

gpiochip310 - West

gpiochip267 - Southwest

9 Abbreviations

APIC:读作ei pic

APS:adaptive partitioning

CAM:UNIX/QNX SCSI Common Access Methods

dtach:detach

hogs:List the processes that are hogging the CPU

IFS:Image File System,QNX系统镜像

IPL:Image Program Loader,bootloader程序

mbuf: Unix TCP/IP message buffer

OCP:Open Core Protocol

OpenUSBDI: Open USB Driver Interface

P2SB:Primary to SideBand

pbuf: lwip packet buffer

pidin:类似于Linux ps,也可以执行pidin arg

PPS: QNX Persistent Pusblish/SubScribe

QNX: Quick UNIX

slay <pid>:kill进程

slm: System Launch and Monitor

smmuman:IOMMU/SMMU Manager

ttyAMA: ARM AMBA PL011

vp0: vdevpeer

相关推荐
初级代码游戏18 天前
国密起步5:GmSSL3交叉编译arm64
arm·国密·交叉编译·gmssl·aarch64
DogDaoDao3 个月前
ARM架构 AArch64 基础知识介绍
汇编·arm开发·arm·指令集·寄存器·aarch64
千码君20165 个月前
MySQL:飞腾2000+Centos7.6 aarch64 部署MySQL8.0.36
数据库·navicat·aarch64·飞腾2000+·mysql8.0.36
CinzWS8 个月前
Arm Generic Interrupt Controller v3 and v4(GICv3v4)学习(一)
arm·gic·aarch64·architecture
hkNaruto8 个月前
debian 11 arm64 aarch64 D2000 平台编译 box86 box64 笔记
debian·aarch64·box86
CinzWS8 个月前
AArch64 memory management学习(二)
mmu·aarch64