美文网首页
orangpione利用usb共享网络(RNDIS)实现tftp

orangpione利用usb共享网络(RNDIS)实现tftp

作者: vencol | 来源:发表于2020-07-25 19:34 被阅读0次

    https://www.mobileread.com/forums/showthread.php?p=3283986

    目录结构说明

    一、环境说明

    1、环境介绍

    2、RNDIS介绍

    3、网络环境配置

    4、编译脚本说明

    二、uboot的RNDIS测试

    1、配置编译uboot的RNDIS功能

    2、测试uboot的RNDIS网络是否正常

    三、kernel的RNDIS测试

    1、配置编译kernel的RNDIS功能

    2、测试kernel的RNDIS网络是否正常

    3、测试kernel的RNDIS网络的nfs功能是否正常

    四、综合测试RNDIS网络

    1、通过uboot手动测试tftp加载kernel启动

    2、通过uboot手动测试tftp加载kernel挂载nfs启动

    3、把测试启动的nfs命令转换成boot.scr启动脚本

    一、环境说明

    1、环境介绍

       首先这里我们需要安装一些基础的编译环境,安装tftp服务器,安装nfs服务器等,这里我们可以参考文章《用buildroot编译整个系统,用qemu仿真vexpressa9》中的环境准备章节,自行安装相关服务,在这里不展开。

    2、RNDIS介绍

       RNDIS是指Remote NDIS,基于USB实现RNDIS实际上就是TCP/IP over USB,就是在USB设备上跑TCP/IP,让USB设备看上去像一块网卡。简单的来说,就是通过USB模拟了一个网卡,这样我们可以通过这个网卡实现和虚拟机的联机,以及正常的网络访问。相关内容可以参考网站https://zhidao.baidu.com/question/1930394656632188907.html

    3、网络环境配置

       1、这里我们实现的网络环境配置如下图所示。在win10主机上虚拟一个网桥,win10主机和Ubuntu虚拟机通过这个网桥连接到无线网络,访问外网。同时orangepione开发板则通过USB实现与win10主机的RNDIS网络共享。通过主机访问外网。

    网络环境配置
       2、通过win10的hyperv创建虚拟网桥,把虚拟机的网络和主机的网络通过网桥桥接起来。在hyperv管理器上面找的虚拟交换机管理器,并点击新建虚拟交换机网络,这里名字随意就好,我这里的名字叫做hyper-net,相关配置如下图所示,这里要选择一个可以上外网的网卡进行桥接
    hyperv交换机
       3、在编译好后,在开发板上电并进行网络通信的时候会在设备管理器出现RNDIS相管的提示信息,如果没有驱动,则按照https://www.mobileread.com/forums/showthread.php?p=3283986网址上的驱动方式对RNDIS进行驱动,先下载kindle_rndis.inf_amd64-v1.0.0.1.zip并解压,再执行第5个cmd脚本注册驱动签名,然后再设备管理器更新驱动管理程序,选择下载的驱动目录进行驱动,如果驱动成功,则在设备管理器会显示下面的驱动
    RNDIS驱动
      4、设置和主机的网络共享,在驱动成功后,需要在更改适配器选项界面,设置共享配置,这里选择共享的是之前hyperv桥接的网卡,这里建议把hyperv桥接网卡的ip设置为静态ip,后面共享的网卡需要通过该网卡的ip进行dns解析,配置如下图所示
    这里如果配置不成功,后面会不能正常通讯
    共享网络配置

    4、编译脚本说明

    这里我们和还是使用文章《用buildroot编译整个系统,用qemu仿真vexpressa9》提到的buildroot环境进行开发。但是我们这里稍微改变了一下在orangepione目录下的脚本build.sh,脚本的主要功能是编译,和拷贝文件到tftp目录,以及修改生成boot.scr文件,可能需要根据实际的情况进行相关的调整

    #! /bin/bash
    NPWD=`realpath .`
    echo $NPWD
    if [ $1_x == cp_x ];then
            cp $NPWD/rootfs/build/linux-custom/arch/arm/boot/zImage ~/tftp
            cp $NPWD/rootfs/build/linux-custom/arch/arm/boot/dts/sun8i-h3-orangepi-one.dtb ~/tftp
    elif [ $1_x == env_x ];then
            /home/vencol/code/buildroot/host/bin/mkimage -C none -A arm -T script -d $NPWD/boot.cmd $NPWD/boot.scr
            cp $NPWD/boot.scr $NPWD/rootfs/images/boot.scr
    else
            cd $NPWD/../buildroot
            mkdir -p $NPWD/rootfs
            make O=$NPWD/rootfs ARCH=arm $1
    fi
    

    二、uboot的RNDIS测试

    1、配置编译uboot的RNDIS功能

    1. 在orangepi目录执行./build.sh uboot-menuconfig会弹出uboot的menuconfig的配置界面,我们的配置选项如下 Device Drivers --->USB support --->

    EHCI HCD (USB 2.0) support --->CONFIG_USB_EHCI_HCD
    Support for generic EHCI USB controller--->CONFIG_USB_EHCI_GENERIC
    MUSB gadget mode support--->CONFIG_USB_MUSB_GADGET
    Enable sunxi OTG / DRC USB controller--->CONFIG_USB_MUSB_SUNXI
    Disable MUSB bulk split/combine--->CONFIG_USB_MUSB_DISABLE_BULK_COMBINE_SPLIT
    Disable DMA (always use PIO)--->CONFIG_USB_MUSB_PIO_ONLY
    USB Gadget Support--->CONFIG_USB_GADGET

    (0x0525) Vendor ID of the USB device--->CONFIG_USB_GADGET_VENDOR_NUM
    (0xA4A2) Product ID of the USB device--->CONFIG_USB_GADGET_PRODUCT_NUM
    USB Ethernet Gadget--->CONFIG_USB_ETHER
    USB Ethernet Gadget Model (RNDIS Protocol)--->CONFIG_USB_ETH_RNDIS
    (de:ad:be:ef:00:01) USB Gadget Ethernet device mac address--->CONFIG_USBNET_DEVADDR
    (de:ad:be:ef:00:00) USB Gadget Ethernet host mac address--->CONFIG_USBNET_HOST_ADDR

    1. 配置完成后,使用脚本命令./build.sh -j4进行uboot编译,如无意外,则可以正常编译通过,通过orangpi相关烧录指引,把sdcard.img烧录到sd卡中
    2. 烧录完成后,插入sd卡。连接调试串口,并启动orangepi,在uboot3s后输入空格停下启动信息,如下图所示


      stop uboot

    2、测试uboot的RNDIS网络是否正常

    1. 在uboot停止的页面输入下面的内容
    usb start
    setenv ethact usb_ether
    setenv ipaddr 192.168.137.2
    setenv netmask 255.255.255.0
    setenv gatewayip 192.168.137.1
    saveenv
    ping 192.168.1.111
    
    1. 这里ping的ip是虚拟机的ip地址,需要查看uboot是否可以和虚拟机通讯,如果出现下图类似情况ip is alive则通讯成功


      ping

    三、kernel的RNDIS测试

    1、配置编译kernel的RNDIS功能

    1. 在orangepi目录执行./build.sh linux-menuconfig会弹出kernel的menuconfig的配置界面,我们的配置选项如下
      RNDIS选项的配置 (这里一开始我们先配置为模块,调用g_ether.ko,调试通过后再编译进内核)Device Drivers --->USB support --->
    Support for Host-side USB--->CONFIG_USB
    Enable USB persist by default--->CONFIG_USB_DEFAULT_PERSIST
    EHCI HCD (USB 2.0) support--->CONFIG_USB_EHCI_HCD
    Improved Transaction Translator scheduling--->CONFIG_USB_EHCI_TT_NEWSCHED
    Generic EHCI driver for a platform device--->CONFIG_USB_EHCI_HCD_PLATFORM
    OHCI HCD (USB 1.1) support--->CONFIG_USB_OHCI_HCD
    Generic OHCI driver for a platform device--->CONFIG_USB_OHCI_HCD_PLATFORM
    Inventra Highspeed Dual Role Controller--->CONFIG_USB_MUSB_HDRC
    MUSB Mode Selection (Gadget only mode)--->CONFIG_USB_MUSB_GADGET
    Allwinner (sunxi)--->USB_MUSB_SUNXI
    USB Gadget Support--->CONFIG_USB_GADGET
    USB Gadget precomposed configurations--->
    Ethernet Gadget (with CDC Ethernet support)--->CONFIG_USB_ETH
    RNDIS support--->CONFIG_USB_ETH_RNDIS
    

    NFS网络选项的配置 Networking support --->Networking options --->

    TCP/IP networking--->CONFIG_INET
    IP: kernel level autoconfiguration--->CONFIG_IP_PNP
    IP: DHCP support--->CONFIG_IP_PNP_DHCP
    IP: BOOTP support--->CONFIG_IP_PNP_BOOTP
    

    NFS文件系统选项的配置 File systems --->Network File Systems --->

    NFS client support--->CONFIG_NFS_FS
    NFS client support for NFS version 2--->CONFIG_NFS_V2
    NFS client support for NFS version 3--->CONFIG_NFS_V3
    NFS client support for the NFSv3 ACL protocol extension--->CONFIG_NFS_V3_ACL
    NFS client support for NFS version 4--->CONFIG_NFS_V4
    Root file system on NFS--->CONFIG_ROOT_NFS
    
    1. 通过源码修改kernel的ubs0网卡地址,因为如果不修改地址,每次重启都会产生一个随机的网卡地址,那么win10这边识别的就不是前面设置的共享网卡了,这里我们需要把网卡设置成和uboot的网卡地址一样,这里我么需要修改的文件是,kernel源码下面的u_ether.c文件的gether_setup_name_default函数添加usb网卡的判断,当识别到usb网卡的时候,设置其默认的host地址为de:ad:be:ef:00:00,dev地址为de:ad:be:ef:00:01
     837     snprintf(net->name, sizeof(net->name), "%s%%d", netname);
     838
     839     if(memcmp(netname, "usb", 3) == 0)
     840     {
     841         eth_random_addr(dev->dev_mac);
     842         pr_warn("using usb my random %s ethernet address\n", "self");
     843         eth_random_addr(dev->host_mac);
     844         pr_warn("using usb my %s ethernet address\n", "host");
     845         dev->host_mac[0] = 222;
     846         dev->host_mac[1] = 173;
     847         dev->host_mac[2] = 190;
     848         dev->host_mac[3] = 239;
     849         dev->host_mac[4] = 0;
     850         dev->host_mac[5] = 0;
     851
     852         dev->dev_mac[0] = 222;
     853         dev->dev_mac[1] = 173;
     854         dev->dev_mac[2] = 190;
     855         dev->dev_mac[3] = 239;
     856         dev->dev_mac[4] = 0;
     857         dev->dev_mac[5] = 1;
     858     }
     859     else
     860     {
     861         eth_random_addr(dev->dev_mac);
     862         pr_warn("using random %s ethernet address\n", "self");
     863         eth_random_addr(dev->host_mac);
     864         pr_warn("using random %s ethernet address\n", "host");
     865     }
    
    1. 配置修改完成后,使用脚本命令./build.sh -j4进行uboot编译,如无意外,则可以正常编译通过,通过orangpi相关烧录指引,把sdcard.img烧录到sd卡中

    2、测试kernel的RNDIS网络是否正常

    1. 重新上电后,等等其加载mmc的根文件系统,加载成功后登陆系统,通过命令modprobe g_ether加载模块驱动,如果加载成功,会出现类似的信息
    [    1.526195] usb0: HOST MAC de:ad:be:ef:00:00
    [    1.530505] usb0: MAC de:ad:be:ef:00:01
    [    1.534355] using usb my random self ethernet address
    [    1.539399] using usb my host ethernet address
    [    1.543905] g_ether gadget: Ethernet Gadget, version: Memorial Day 2008
    [    1.550519] g_ether gadget: g_ether ready
    
    1. 通过ifconfig -a查看是否存在usb0网卡,如果存在usb0网卡,说明网卡正常驱动
    2. 启动usb0网卡且对其进行配置ifconfig usb0 up && ifconfig usb0 192.168.137.2 netmask 255.255.255.0
    3. 配置默认网关route add default gw 192.168.137.1
    4. 测试是否可以ping通虚拟机ping 192.168.1.111,如果正常ping通说明网络成功通讯
    5. 通过命令/etc/network/nfs_check创建网卡启动时对nfs的检查文件
    #!/bin/sh
    
    # This allows NFS booting to work while also being able to configure
    # the network interface via DHCP when not NFS booting.  Otherwise, a
    # NFS booted system will likely hang during DHCP configuration.
    
    # Attempting to configure the network interface used for NFS will
    # initially bring that network down.  Since the root filesystem is
    # accessed over this network, the system hangs.
    
    # This script is run by ifup and will attempt to detect if a NFS root
    # mount uses the interface to be configured (IFACE), and if so does
    # not configure it.  This should allow the same build to be disk/flash
    # booted or NFS booted.
    
    nfsip=`sed -n '/^[^ ]*:.* \/ nfs.*[ ,]addr=\([0-9.]\+\).*/s//\1/p' /proc/mounts`
    if [ -n "$nfsip" ] && ip route get to "$nfsip" | grep -q "dev $IFACE"; then
            echo Skipping $IFACE, used for NFS from $nfsip
            exit 1
    fi
    
    1. 通过命令vi /etc/network/interfaces添加usb0网卡开机自动挂载
    auto usb0
    iface usb0 inet static
    pre-up /etc/network/nfs_check
    address 192.168.137.2
    netmask 255.255.255.0
    gateway 192.168.137.1
    #dns-nameservers 8.8.8.8 192.168.137.1 211.136.20.203
    
    1. 通过命令vi /etc/resolv.conf配置dns服务器,注意resolv.conf文件不能是链接文件
    nameserver 127.0.0.1
    nameserver 8.8.8.8
    nameserver 192.168.137.1
    

    3、测试kernel的RNDIS网络的nfs功能是否正常

    1. 在虚拟机服务器端开启nfs服务
    2. 在虚拟机通过命令ln -s nfsroot nfs创建nfs文件的的软连接,nfsroot是实际的根文件系统目录,而后面的nfs是创建的软连接目录
    3. 在虚拟机通过命令sudo vi /etc/exports修改文件内容,添加类似的内容/home/vencol/code/nfs *(insecure,rw,sync,no_root_squash,no_subtree_check)
    4. 在虚拟机通过命令sudo /etc/init.d/nfs-kernel-server restart重启nfs服务
    5. 在开发创建nfsdir目录,并且通过命令mount -t nfs -o nolock 192.168.1.111:/home/vencol/code/nfs nfsdir,如果挂载成功通过ls nfsdir则可以看到nfs根文件系统的内容。

    四、综合测试RNDIS网络

    1、通过uboot手动测试tftp加载kernel启动

    1. 由于前面我们使用了saveenv命令来保存uboot的环境参数,所以这里我们只要没有重新烧录,都可以不用再次设置,如果需要设置,请参考【测试uboot的RNDIS网络是否正常】章节内容
    2. 我们在虚拟机上通过执行./build.sh cp命令把zImage和sun8i-h3-orangepi-one.dtb设备树文件拷贝到我们的tftp服务器目录下。
    3. 我们在开发板上设置bootargs参数为setenv bootargs "console=ttyS0,115200 earlyprintk root=/dev/mmcblk0p2 rootwait"并且通过saveenv保存该参数
    4. 在开发板上,使用tftp 0x42000000 zImage加载zimage到内存,通过tftp 0x43000000 sun8i-h3-orangepi-one.dtb加载设备树到内存
    5. 在开发板上,通过bootz 0x42000000 - 0x43000000启动内核,如无意外,可以成功进入登录界面,但是这时加载的是mmc根文件系统,下面我们开始加载nfs文件系统

    2、通过uboot手动测试tftp加载kernel挂载nfs启动

    1. 在前面已经可以正常加载mmc根文件系统的前提下,进行nfs文件系统的加载
    2. 在uboot界面停下,由于前面保存了相关的环境变量,这里我们直接进行bootargs参数的修改,通过命令修改bootargs参数为,setenv bootargs root=/dev/nfs rw rootpath=/home/vencol/code/nfs nfsroot=192.168.1.111:/home/vencol/code/nfs,nolock ip=192.168.137.2:192.168.1.111:192.168.137.1:255.255.255.0 console=ttyS0,115200 nfsvers=2这里的rootpath是虚拟机上nfs根文件的地址,而ip则是根据我们的实际情况设置,由于这里虚拟机和开发板不在同一网段,所以需要填写网关和掩码信息
    3. 在开发板上,使用tftp 0x42000000 zImage加载zimage到内存,通过tftp 0x43000000 sun8i-h3-orangepi-one.dtb加载设备树到内存
    4. 在开发板上,通过bootz 0x42000000 - 0x43000000启动内核,如无意外,可以成功进入登录界面,但是这时加载的是mmc根文件系统,下面我们开始加载nfs文件系统
    5. 出现问题排查

    1.nfs服务器端的传输协议是否和开发版客户端的协议一致,如果不一致,在bootargs添加nfsserver=2,这里2是nfs2的意思,对应版本即可

    1. 查看nfs根文件系统中的/dev目录是否存在,/dev/console和/dev/null,如果不存在通过下面命令创建
      sudo mknod console c 5 1 //创建console字符设备,
      sudo mknod null c 1 3 //创建null 字符设备,
      sudo chown 1000:1000 console null```
    2. 在源码文件init/do_mounts.c的do_mount_root函数中调用的do_mount函数返回的错误打印出来,查看错误码是什么,如果错误码为-93,那么就是服务器版本不对,这里有可能是下面4这点的问题。在服务器端用nfsstat -s查看版本,如果是其他错误可以参考/var/log/syslog中nfs的输出日志。
    3. 低版本uboot和高版本ubuntu搭配进行开发时,发现nfs不能使用.uboot默认启动协议为2.而高版本的ubuntu17之后nfs就默认支持3和4,因此需要ubuntu支持协议2。在文件/etc/default/nfs-kernel-server末尾添加RPCNFSDOPTS="--nfs-version 2,3,4 --debug --syslog",然后重启nfs服务。

    3、把测试启动的nfs命令转换成boot.scr启动脚本

    1. boot.scr是通过mkimage工具生成的,这里我们需要先拷贝buildroot中orangepione的boot.cmd文件到脚本目录,在这个文件的基础上进行修改,其目录在buildroot/board/orangepi/orangepi-one/boot.cmd
    2. 修改boot.cmd文件如下,其中rootdelay=3看具体情况使用
    setenv fdt_high ffffffff
    usb start
    setenv ethact usb_ether
    setenv ipaddr 192.168.137.2
    setenv gatewayip 192.168.137.1
    setenv netmask 255.255.255.0
    setenv serverip 192.168.1.111
    #setenv bootargs console=ttyS0,115200 earlyprintk root=/dev/mmcblk0p2 rootwait
    setenv bootargs root=/dev/nfs rw rootpath=/home/vencol/code/nfs nfsroot=192.168.1.111:/home/vencol/code/nfs,nolock ip=192.168.137.2:192.168.1.111:192.168.137.1:255.255.255.0 console=ttyS0,115200 nfsvers=2 rootdelay=3
    
    tftp $kernel_addr_r zImage
    tftp $fdt_addr_r sun8i-h3-orangepi-one.dtb
    bootz $kernel_addr_r - $fdt_addr_r
    
    #fatload mmc 0 $kernel_addr_r zImage
    #fatload mmc 0 $fdt_addr_r sun8i-h3-orangepi-one.dtb
    #bootz $kernel_addr_r - $fdt_addr_r
    
    1. 通过脚本命令./build.sh env生成boot.scr文件在当前目录中
    2. 把boot.scr文件拷贝到nfs目录的root目录下
    3. 在开发板已经正常进入mmc根文件系统的情况下,挂载nfs目录到nfsdir目录中
    4. 通过命令mount /dev/mmcblk0p1 /mnt/fat/挂载boot分区到/mnt/fat/
    5. 把nfs目录的boot.scf拷贝到boot分区cp nfsdir/root/boot.scr /mnt/fat
    6. 确认boot分区的boot.scr文件更新后,卸载boot分区,并重启umount /mnt/fat && reboot
      如无意外,则可以看到类似的挂nfs信息出现
      nfs

    :

    相关文章

      网友评论

          本文标题:orangpione利用usb共享网络(RNDIS)实现tftp

          本文链接:https://www.haomeiwen.com/subject/jpoplktx.html