openwrt 1806移植mt7628

最小固件:
3604643
openwrt-ramips-mt76x8-mt7628-squashfs-sysupgrade.bin
带LUCI:

./scripts/feeds update -a
./scripts/feeds install -a
make defconfig
make check
make download
make menuconfig
make V=s

1.修改固件大小限制和flash分区
在target中主要是针对各个平台对应的makefile和编译规则等,
当然也有通用的部分
openwrt-master/target/linux/ramips/image/mt76x8.mk
可以查看到当前平台所对应的各种路由器固件配置
这是当前的目标板
define Device/mt7628
DTS := MT7628
BLOCKSIZE := 64k
IMAGE_SIZE := $(ralink_default_fw_size_4M)
DEVICE_TITLE := MediaTek MT7628 EVB
DEVICE_PACKAGES := kmod-usb2 kmod-usb-ohci kmod-usb-ledtrig-usbport
endef
TARGET_DEVICES += mt7628

由于固件大小被限制为4m,所以当固件超过4M的时候就会出现编译错误

partition@50000 {
		label = "firmware";
		reg = <0x50000 0x7b0000>;
	};
这里默认是7m多一点,根据flash大小设置
partition@50000 {
				label = "firmware";
			//	reg = <0x50000 0x7b0000>; //8MB flash
			//	reg = <0x50000 0xfb0000>; //16MB flash
				reg = <0x50000 0x1fb0000>; //32MB flash
			};

2.修改内存大小
MT7628.dts文件有
memory@0 {
device_type = “memory”;
reg = <0x0 0x10000000>; //256MB RAM
// reg = <0x0 0x8000000>; //128MB RAM
// reg = <0x0 0x4000000>; //64MB RAM
};
但是据说lede很多在修改dts后不生效的。
//在menuconfig(make kenerl_menuconfig)的时候搜索Machine selection --> DRAM Size
3.修改波特率
target/linux/ramips/dts/mt7628an.dtsi
chosen {
bootargs = “console=ttyS0,115200”;
};
4.修改主机名、时区等,
package/base-files/files/bin/config_generate
generate_static_system() {
224 uci -q batch <<-EOF
225 delete system.@system[0]
226 add system system
227 set system.@system[-1].hostname=‘Jiamu’
228 set system.@system[-1].timezone=‘CTS-8’
229 set system.@system[-1].zonename=‘Asia/Shanghai’
230 set system.@system[-1].ttylogin=‘0’
231 set system.@system[-1].log_size=‘64’
232 set system.@system[-1].urandom_seed=‘0’
233
234 delete system.ntp
235 set system.ntp=‘timeserver’
236 set system.ntp.enabled=‘1’
237 set system.ntp.enable_server=‘0’
238 add_list system.ntp.server=‘0.openwrt.pool.ntp.org
239 add_list system.ntp.server=‘1.openwrt.pool.ntp.org
240 add_list system.ntp.server=‘2.openwrt.pool.ntp.org
241 add_list system.ntp.server=‘3.openwrt.pool.ntp.org
242 EOF

5.默认启动wifi,修改wifi名字
package/kernel/mac80211/files/lib/wifi/mac80211.sh

		uci -q batch <<-EOF
		set wireless.radio${devidx}=wifi-device
		set wireless.radio${devidx}.type=mac80211
		set wireless.radio${devidx}.channel=${channel}
		set wireless.radio${devidx}.hwmode=11${mode_band}
		${dev_id}
		${ht_capab}
		set wireless.radio${devidx}.disabled=0  //使能

		set wireless.default_radio${devidx}=wifi-iface
		set wireless.default_radio${devidx}.device=radio${devidx}
		set wireless.default_radio${devidx}.network=lan
		set wireless.default_radio${devidx}.mode=ap
		set wireless.default_radio${devidx}.ssid=jiamu //ssid名
		set wireless.default_radio${devidx}.encryption=psk //wifi加密方式
		set wireless.default_radio${devidx}.key=12345678

EOF
6.自定义busybox
Base system
打开ftpget/ftpput tftp等功能
7.设置串口登录密码
在inittab中添加
::respawn:/sbin/getty -L ttyS0 115200 vt100
主要配置busybox支持gettty

文件系统挂载:

启动流程:
kernel_init -->内核启动
try_to_run_init_process("/sbin/init") --> 启动init程序,似乎和cc不同的是没有直接从/etc/preinit启动
这个init是procd中的init.c的init编译的
early挂载proc等节点,所以在文件系统中不需要fatab了,初始化环境变量(init: Console is alive)
cmdline();解析传递过来的init_debug参数
watchdog_init();初始化看门狗,怎么用这个看门狗???(init: - watchdog -)
execvp(kmod[0], kmod);开始加载/etc/modules-boot.d/的所有驱动/etc/modules-boot.d/*
preinit();(init: - preinit -)
a):先执行/sbin/procd -h /etc/hotplug-preinit.json
b):sh /etc/preinit 执行preinit
c):最后会调用spawn_procd,Exec to real procd now
uloop_run();这个是libubox的函数
到这里init程序就初始化完成
结果:
1.执行/etc/preinit
2.执行/sbin/procd
/etc/preinit:
1:定义函数链表头,共有下面五种链表
boot_hook_init preinit_essential
boot_hook_init preinit_main
boot_hook_init failsafe
boot_hook_init initramfs
boot_hook_init preinit_mount_root、
boot_hook_init在preinit.sh中定义
2.执行脚本,脚本主要是
for pi_source_file in /lib/preinit/*; do
. $pi_source_file
done
3.执行preinit_essential和preinit_main这个链表中的函数
boot_run_hook preinit_essential
boot_run_hook preinit_main

这里在分析脚本的时候,需要关注package/base-files/Makefile
这里会初始化一份变量,在执行preinit的时候会用到
环境变量会echo到/lib/preinit/00_preinit.conf
这里的参数生成依赖于menuconfig的结果
pi_suppress_stderr=""
fs_failsafe_wait_timeout=2
pi_init_path="/usr/sbin:/usr/bin:/sbin:/bin"
pi_init_env=""
pi_init_cmd="/sbin/init"
pi_init_suppress_stderr="y"
pi_ifname=""
pi_ip="192.168.1.1"
pi_netmask="255.255.255.0"
pi_broadcast="192.168.1.255"
pi_preinit_net_messages="y"
pi_preinit_no_failsafe_netmsg=""
pi_preinit_no_failsafe="y"

/lib/preinit/在源码中的package/base-file/里面
主要分析函数链表:
	preinit_essential
		-->
		好像什么都没有
	preinit_main
		-->
		define_default_set_state
		do_sysinfo_generic
		preinit_ip
		pi_indicate_preinit
		failsafe_wait
		run_failsafe_hook
		indicate_regular_preinit
		initramfs_test
		do_mount_root
		do_urandom_seed
		run_init
	failsafe
		-->
		indicate_failsafe
		failsafe_netlogin
		failsafe_shell
	initramfs
		-->
		好想也是空的
	preinit_mount_root
		-->
		move_config
		
在添加的函数链表里面主要是这两种,在preinit最后执行了preinit_main链表
define_default_set_state:
	target/linux/ramips/base-files/etc/diag.sh
	应该是执行了这个脚本
	这里应该是和led相关
	由于未传递参数,这里应该什么都没有做
	
do_sysinfo_generic:
	主要是创建了/tmp/sysinfo/model和 /tmp/sysinfo/board_name
	根据/proc/device-tree里面的
	后面应该会用到这两个文件
preinit_ip:
	由于CONFIG_TARGET_PREINIT_DISABLE_FAILSAFE禁止了故障模式
	所以pi_preinit_no_failsafe="y"
	这里就不执行啥子了
	 preinit_ip_config:
	 preinit_config_board:
			
pi_indicate_preinit:
	set_state preinit 执行set_state,传递preinit
		status_led_blink_preinit 应该是led的相关信息,暂时不管
failsafe_wait 故障模式等待
	fs_wait_for_key "" "" $fs_failsafe_wait_timeout执行这个
	这里应该就是在处理故障模式
	在启动的时候打印出来的
	Press the [1], [2], [3] or [4] key and hit [enter] to select the debug level
	故障模式暂时不管
run_failsafe_hook
	[ "$pi_preinit_no_failsafe" = "y" ] && return 什么都不做
indicate_regular_preinit
	set_state preinit_regular  还是led
initramfs_test
	if [ -n "$INITRAMFS" ];
		initramfs
		
		preinit_ip_deconfig
	好像由于没有设置INITRAMFS而没有执行
do_mount_root
	执行/sbin/mount_root
	应该是用于执行sysupgrade升级
	输出mount_root: jffs2 not ready yet, using temporary tmpfs overlay
do_urandom_seed
	这里应该是设置随机数的种子一类的东西
	输出了urandom-seed: Seeding with /etc/urandom.seed
到这里preinit就执行完了
根据前面在
init.c
	main
		preinit
中的分析
preinit_proc.cb = spawn_procd;
preinit_proc.pid = fork();
if (!preinit_proc.pid) {
	
	execvp(init[0], init);
	ERROR("Failed to start preinit: %m\n");
	exit(-1);
}
fork自后先执行execvp(init[0], init);,即/etc/preinit脚本
然后在执行完之后执行
spawn_procd
	启动/sbin/procd

/sbin/procd:
prod在终端的输出信息
[ 7.684634] procd: - early -
[ 7.688519] procd: - watchdog -
[ 8.385976] procd: - watchdog -
[ 8.389466] procd: - ubus -

1.procd_state_next
	state_enter
		-->
		STATE_EARLY
			LOG("- early -\n"); 
			watchdog_init(0); //
			hotplug("/etc/hotplug.json"); //很具json文件初始化一些热插拔时间,里面使用了netlink套接字
			procd_coldplug();   //应该是对部分文件系统进行挂载
				里面会执行一个udevtrigger的命令
				并且注册udevtrigger.cb = udevtrigger_complete;
				在执行完毕之后调用udevtrigger_complete
					coldplug_complete
						procd_state_next
							STATE_UBUS  
		STATE_UBUS  //ubus是比较重要的
			watchdog_init(0);
			set_stdio("console");  //设置控制终端
			LOG("- ubus -\n");
			procd_connect_ubus();
			service_start_early("ubus", ubus_cmd);
		STATE_INIT	
			inittab的内容
			::sysinit:/etc/init.d/rcS S boot
			::shutdown:/etc/init.d/rcS K shutdown
			::askconsole:/usr/libexec/login.sh

			procd_inittab_run
				会去匹配static struct init_handler handlers
				然后执行对应的回调函数
				runrc
					rcS
					 _rc(&q, "/etc/rc.d", pattern, "*", param);
						会去执行/etc/rc.d/下的脚本
						但是这些脚本是在哪里生成的呢?
						全是链接文件,执行了/etc/init.d/下面的对应文件
					sysinit:
						会去执行S开头的脚本,传入参数为boot,
						脚本里面都有boot函数,会执行每个脚本的booton
						这是调用顺序
							Now cycle init scripts 0 /etc/rc.d/S00sysfixtime boot 
							Now cycle init scripts 1 /etc/rc.d/S10boot boot 
							Now cycle init scripts 2 /etc/rc.d/S10system boot 
							Now cycle init scripts 3 /etc/rc.d/S11sysctl boot 
							Now cycle init scripts 4 /etc/rc.d/S12log boot 
							Now cycle init scripts 5 /etc/rc.d/S12rpcd boot 
							Now cycle init scripts 6 /etc/rc.d/S19dnsmasq boot 
							Now cycle init scripts 7 /etc/rc.d/S19firewall boot 
							Now cycle init scripts 8 /etc/rc.d/S20network boot 
							Now cycle init scripts 9 /etc/rc.d/S30adblock boot 
							Now cycle init scripts 10 /etc/rc.d/S35odhcpd boot 
							Now cycle init scripts 11 /etc/rc.d/S50cron boot 
							Now cycle init scripts 12 /etc/rc.d/S50dropbear boot 
							Now cycle init scripts 13 /etc/rc.d/S50uhttpd boot 
							Now cycle init scripts 14 /etc/rc.d/S65wifidog boot 
							Now cycle init scripts 15 /etc/rc.d/S80ucitrack boot 
							Now cycle init scripts 16 /etc/rc.d/S94gpio_switch boot 
							Now cycle init scripts 17 /etc/rc.d/S95done boot 
							Now cycle init scripts 18 /etc/rc.d/S96led boot 
							Now cycle init scripts 19 /etc/rc.d/S98sysntpd boot 
							Now cycle init scripts 20 /etc/rc.d/S99bootcount boot 
							Now cycle init scripts 21 /etc/rc.d/S99urandom_seed boot 
						这部分处理过程由ubox部分接管,不像Preinit直接由shell启动
						所以,看不到打印,还是恼火
						不过可以将打印输出到指定文件测试
						
						S00sysfixtime:
							对开机时间进行一定处理
						S10boot:
							1.创建了一大堆系统文件/var/lock啥的
							2.挂载debugfs
							3./sbin/kmodloader装载一大堆驱动模块,上面好像已经装过一次啥子了
							4./bin/config_generate 
								这是个脚本文件,就是源码目录中的同名文件·
								
									CFG=/etc/board.json
									. /usr/share/libubox/jshn.sh

									echo "!!!!!!!!!!!!!!!!!luo:Now need run bord_detect"
									[ -s $CFG ] || /bin/board_detect || exit 1
									[ -s /etc/config/network -a -s /etc/config/system ] && exit 0
								a).首先判断了/etc/board.json存在并且为非空[-s],如果不存在则执行/bin/board_detect生成board.json
									board_detect中依次执行了/etc/board.d/*具有可执行权限的脚本
									01_leds:
										board=$(board_name) 获取板子名称,board_name是一个函数包含在/package/base-files/files/lib/functions.sh
											board_name() {
											[ -e /tmp/sysinfo/board_name ] && cat /tmp/sysinfo/board_name || echo "generic"
											}
											如果/tmp/sysinfo/board_name存在,则执行cat
											这个文件在之前preinit中由do_sysinfo_generic读取/proc/device-tree创建了
											现在打印出来是mt7628
										board_config_update
											如果文件存在则加载到json
											如果model对象不存在,添加name和id
											!!!!!!!!!!!!!!!!!!!!!!luochao:
											{
												"model": {
													"id": "mt7628",
													"name": "Mediatek MT7628AN evaluation board"
												}
											}
										设置wifi,led,switch的一些led参数,默认并没有7628评估板,暂时不处理
										board_config_flush
											先输出到/tmp/.board.json,然后移动到/etc/下面的对应文件
											这里如果刚开始不存在,则就已经存在了,如果本身就是存在的
											也不影响,因为是先load进来的
											如果是首次启动,则现在board.json只有model一个对象
									02_network:
										这个文件应该就是配置了lan,wan,vlan等参数
										board_config_update
										board=$(board_name)
											和上面同样的操作
										ramips_setup_interfaces $board
											根据板子名字设置交换机对象
											区分lan和wan
											找到mt7628对应的设置
											ucidef_add_switch "switch0" \
													"0:lan" "1:lan" "2:lan" "3:lan" "4:wan" "6@eth0"
												;;
											这里就是把交换机的端口4设置为wan,0-3设置为lan,6是cpu口,接到eth0
											那么端口5呢???????????
											如果要在源码中修改lan和wan,则修改这里
												ucidef_add_switch
													lan和wan匹配
														[0-9]*:*)
															num="${port%%:*}"
															role="${port##*:}"
														;;
													 "6@eth0"匹配
															[0-9]*@*)
															num="${port%%@*}"
															device="${port##*@}"
															need_tag=0
															want_untag=0
															[ "${num%t}" != "$num" ] && {
																num="${num%t}"
																need_tag=1
															}
															[ "${num%u}" != "$num" ] && {
																num="${num%u}"
																want_untag=1
															}
														;;
														成功解析后调用_ucidef_add_switch_port,添加到switch对象中
													最后执行_ucidef_finish_switch_roles根据添加的switch对象生成roles对象
													
											ramips_setup_macs $board
											根据板子获取mac地址并设置
										     又没有7628,使用default
											 lan_mac=$(cat /sys/class/net/eth0/address)
											 wan_mac=$(macaddr_add "$lan_mac" 1)
											 
											 如果lan_mac和wan_mac存在则执行
											 [ -n "$lan_mac" ] && ucidef_set_interface_macaddr "lan" $lan_mac
											 [ -n "$wan_mac" ] && ucidef_set_interface_macaddr "wan" $wan_mac
											 但是这里有个问题,再启动,mac会变,会设置lan_mac为eth0的地址????
											 
										board_config_flush
											同理更新一次,这次更新的是model+switch对象,因为是已经存在Load进来的
										这就生成了完整的board.json文件	
											这里默认配置eth0.1是lan包含0-3口,eth0.2是wan包含4口,cpu口是6,且wan和lan都要包含cpu口

								b).如果/etc/config/network文件存在,并且/etc/config/system也存在则退出
									如果不存在/etc/config/network:
										generate_static_network 先生成默认的配置
												1.先生成会还设备loopback
												2.json_is_a dsl object不清楚是什么
											1.从board.json的network对象中获取信息,只生成了lan和wan两个接口
											这里就把lan和wan在/etc/network中的信息设置好
											lan设置为桥接,静态ip模式,ip和掩码都在这里,然后对应的接口是eth0.1
											wan设置为dhcp,对应设备是eth0.2
											这里有个问题lan口设置Ip为192.168.1.1,但是eth0.1上并没有Ip
											而是在br-lan,lan桥上有ip,为什么?????
											lan-->eth0.1-->0 1 2 3
											wan-->eth0.2-->4
											这是什么时候生成的
											config interface 'wan6'
											option ifname 'eth0.2'
											option proto 'dhcpv6'
											2.从board.json的switch对象中获取信息
												只有一个交换机生成一个switch配置
													config switch
														option name 'switch0'
														option reset '1'
														option enable_vlan '1'
												generate_switch_vlans_ports "$1"生成当前交换机的vlan信息
													1.生成switch_vlan条目
													2.生成switch_port条目,为什么没有生成这个???
									generate_static_system:
										生成了主机名和ntp参数
										修改主机名就在这里
										暂时没有设置rssimon,gpioswitch,led
									基本网络参数就已经配置好了
							5.uci_apply_defaults
								执行etc/uci-defaults下的配置
								这里的文件只是在首次上电执行一次
								然后删除,里面包含有一些在menuconfig后根据选项生成的
								
							6./sbin/reload_config
								装载配置文件
							基本配置就在这里配置完毕
							
						S10system
							脚本的解释器注意一下
							#!/bin/sh /etc/rc.common
							是执行了/etc/rc.common
							里面将参数进行转化的
							这里会调用
							start_service
								装载系统配置
						S11sysctl:
							通过配置文件中定义的值
							使用sysctl调整内核参数,如tcp超时等
						
						这些都是通过脚本启动配置应用
						使用的方式是procd
					shutdown
						Now cycle init scripts 0 /etc/rc.d/K10gpio_switch shutdown 
						Now cycle init scripts 1 /etc/rc.d/K50dropbear shutdown 
						Now cycle init scripts 2 /etc/rc.d/K85odhcpd shutdown 
						Now cycle init scripts 3 /etc/rc.d/K89log shutdown 
						Now cycle init scripts 4 /etc/rc.d/K90network shutdown 
						Now cycle init scripts 5 /etc/rc.d/K90sysfixtime shutdown 
						Now cycle init scripts 6 /etc/rc.d/K98boot shutdown 
						Now cycle init scripts 7 /etc/rc.d/K99umount shutdown 

启动流程和分析基本如上了

						应用篇

网桥:
1.brctl
通过ioctl命令操作内核,对网桥进行设置
S20network负责了这块的初始化
默认情况下开启eth0.1 eth0.2 wlan0,建立br-lan
将eth0.1和wlan桥接在一起,即无线和LAN桥接
交换机的0-3设置为lan,vid为1,绑定到eth0.1
接口设置参考:
https://wiki.openwrt.org/doc/networking/network.interfaces
默认启动有:
Dev des
br-lan 192.168.1.1
eth0 真实网卡
eth0.1 虚拟网卡,vlan 1 --> lan
eth0.2 虚拟网卡,vlan 2 --> wan
wlan0 无线网卡,桥接到lan上
AP:
配置为普通路由器:
1.设置0为wan,其余为wan
按照上面分析的,在ramips_setup_interfaces设置wan和lan对应的端口即可
2.将wan口接到可上网的路由器上的lan口上,pc接到设备的lan口即可上网
3.设置dhcp参数
在dhcp.conf里面,设置Ip分配范围,租约时间
在dnsmasq_start中,-k参数后添加 --dhcp-sequential-ip
procd_set_param command $PROG -C C O N F I G F I L E k x / v a r / r u n / d n s m a s q / d n s m a s q . &quot; CONFIGFILE -k -x /var/run/dnsmasq/dnsmasq.&quot; {cfg}".pid
配置为无线交换机:
将所有口设置为lan,任意口连接到可上网设备lan口

STA:

SSID:
wifi相关配置参数
https://wiki.openwrt.org/doc/uci/wireless
原创,转载请声明来源

猜你喜欢

转载自blog.csdn.net/huahuang1508/article/details/83065176