pmon构建过程分析

    科技2024-07-31  29

    以编译ls2k pai 为例,编译步骤如下

    $ cd zloader.ls2k $ make cfg // $ make tgt=rom // 生成gzrom.bin $ make dtb // 生成gzrom-dtb.bin ,即包含设备树

    构建过程如下:

    通过脚本getname获取当前的目录名,以确定具体的板卡,设置相应的变量处理libc, libm, libz 的Makefile创建文件夹Targets/LS2K/compile进入Targets/LS2K/conf 目录,执行pmoncfg ls2k, ls2k 是配置文件指定选用哪些驱动模块和命令, files.LS2K 和 conf/files指定了每个模块或命令对应的实现文件和宏定义。执行pmoncfg ls2k 之后会生成Targets/LS2K/compile/ls2k目录,目录里面有相应的文件。跳转到 Targets/LS2K/compile/ls2k 执行命令make depend clean根据编译时指定的参数tgt=rom 或 tgt=rom以ld.script.S生成Targets/LS2K/conf/ld.script文件。 主要区别是start的地址不同。到Target/LS2K/compile/ls2k/生成pmon, pmon.bin, start.o,拷贝Target/LS2K/compile/ls2k/start.o 到当前位置(zloader.ls2k)。其中pmon.bin是通过objcopy -o binary pmon而来, 如果编译时参入DEBUG=-g 参数则会生成pmon.gdb 文件,用于调试。将pmon.bin通过gzip 压缩成pmon.bin.gz将pmon.bin.gz 通过bin2c 转换成为C数组文件pmon.bin.c,数组名为biosdata通过 ./genrom ../Targets/LS2K/compile/ls2k/pmon > initmips.c 生成initmips.cgenrom 的功能是通过执行objdump -x pmon获取pmon的符号表和重定位信息,通过匹配正则表达式从中获取 start和initmips的地址,initmips.c的功能用于将biosdata解压到start处,之后再跳转到initmips处执行。 所以pmon的执行过程是从start.S 开始跳转到zloader.ls2k/initmips.c中的initmips,之后再跳转到Targets/LS2K/ls2k/tgt_machdep.c中的initmips函数将zloader.c inflate.c malloc.c memop.c pmon.bin.c initmips.c 编译成zloader.o链接start.o和zloader.o 生成gzrom通过objcopy 将gzrom转成raw binary gzrom.bin即去除符号表和重定位信息。进入Targets/LS2K/compile/ls2k,以Targets/LS2K/conf/ls2k.dts为输入文件,LS2K.dtb.i为输出文件,执行make dtb通过dtc 将LS2K.dtb.i转换成LS2K.dtb通过../tools/pmonenv.py 将dtb和内核启动参数追加到gzrom.bin形成gzrom-dtb.bin

    简化后的Makefile.inc

    ifndef PMONCC CC=$(CROSS_COMPILE)gcc -mabi=32 CROSS_COMPILE ?= mipsel-linux- else CC=${PMONCC} endif ifeq "$(shell echo ${CC}|grep 'mips-elf-')" "" ifeq "$(shell echo ${CC}|grep '\-mabi=64')" "" LD = $(CROSS_COMPILE)ld -m elf32ltsmip -G 0 -static -n -nostdlib OUT_FORMAT="elf32-tradlittlemips" else LD = $(CROSS_COMPILE)ld -m elf64ltsmip -G 0 -static -n -nostdlib OUT_FORMAT="elf64-tradlittlemips" endif else ENDIAN_FLAG= -EL LD = $(CROSS_COMPILE)ld -m elf32ebmip -G 0 -static -n -nostdlib -EL CC :=${CC} -EL OUT_FORMAT="elf32-littlemips" endif RAMSTARTADDR?=0xffffffff88000000 GZROMSTARTADDR?=0xffffffff8f900000 ROMSTARTADDR?=0xffffffff8f010000 export CROSS_COMPILE export CC += ${MYCC} -mno-abicalls -fno-pic export LD export MKDEP=makedepend ifeq ("${tgt}","rom") gencode=./genrom endif ifndef tgt help: @echo use make tgt=sim for sim in linux @echo use make tgt=rom for generate romfile gzrom.bin @echo use make tgt=ram for generate ramfile gzram @echo use make cfg for config @echo use make recfg for change config @echo use make tgt=rom DEBUG=-g MYCC="'"-g3 -DMYDBG='"printf(\"debug:%s,%d\\n\",__FILE__,__LINE__);"'"'" to support MYDBG macro. else all: ${tgt} ejtag_rom ejtag_rom1 ejtag_ram rom: clean ${START} zloader.o gcc -DSTARTADDR=${GZROMSTARTADDR} -DOUT_FORMAT=\"${OUT_FORMAT}\" -DOUT_ARCH=mips -Umips -E -P ld.script.S > ld.script ${LD} -T ld.script -e start -o gzrom ${START} zloader.o ${CROSS_COMPILE}objcopy -O binary gzrom gzrom.bin ${START}: rm -f ../Targets/${TARGET}/compile/${TARGETEL}/${START} gcc -DSTARTADDR=${ROMSTARTADDR} -DOUT_FORMAT=\"${OUT_FORMAT}\" -DOUT_ARCH=mips -Umips -E -P ld.script.S > ../Targets/${TARGET}/conf/ld.script make -C ../Targets/${TARGET}/compile/${TARGETEL}/ cp ../Targets/${TARGET}/compile/${TARGETEL}/${START} . zloader.o: zloader.c inflate.c malloc.c memop.c pmon.bin.c initmips.c $(CC) -c zloader.c ${ZLOADER_OPTIONS} -DMEMSIZE=${MEMSIZE} initmips.c: ../Targets/${TARGET}/compile/${TARGETEL}/pmon ${gencode} $< > initmips.c pmon.bin.c: ../Targets/${TARGET}/compile/${TARGETEL}/pmon.bin gzip $< -c > pmon.bin.gz ./bin2c pmon.bin.gz pmon.bin.c biosdata endif dtb: make -C ../Targets/${TARGET}/compile/${TARGETEL}/ DTB_O=`pwd`/${TARGET}.dtb.i DTB_I=`pwd`/../Targets/${TARGET}/conf/${TARGET}.dts dtb ./dtc -I dts -O dtb -o ${TARGET}.dtb ${TARGET}.dtb.i ( echo "#include <include/load_dtb.h>";echo NVRAM_OFFS; echo DTB_OFFS; )| make -C ../Targets/${TARGET}/compile/${TARGETEL}/ DTB_O=`pwd`/dtbinfo.txt DTB_I=- dtb [ -f gzrom.bin ] && cp gzrom.bin gzrom-dtb.bin && python ../tools/pmonenv.py -O $$((`tail -n 1 dtbinfo.txt`)) -o $$((`tail -n 2 dtbinfo.txt|head -n 1`)) -f gzrom-dtb.bin -d ${TARGET}.dtb -w al=\(usb0,0\)/boot/vmlinuz al1=\(wd0,0\)/boot/vmlinuz append="'console=ttyS0,115200 console=tty initcall_debug=1 loglevel=20'" FR=1 cleanall: clean make -C ../Targets/${TARGET}/compile/${TARGETEL}/ clean clean: rm -rf *.o zlib_gzip zloader pmon.bin.c gzrom gzrom.bin gzram initmips.c pmon.bin.gz zlib_deflate/*.o zlib_inflate/*.o zlib_gzrom zlib_gzrom.bin cfg: # DO NOT DELETE perl -i -ne 'print;exit if(/^# DO NOT DELETE/);' ../lib/libc/Makefile perl -i -ne 'print;exit if(/^# DO NOT DELETE/);' ../lib/libm/Makefile perl -i -ne 'print;exit if(/^# DO NOT DELETE/);' ../lib/libz/Makefile mkdir -p ../Targets/${TARGET}/compile cd ../Targets/${TARGET}/conf/;pmoncfg ${TARGETEL} make -C ../Targets/${TARGET}/compile/${TARGETEL}/ depend clean

    详细分析

    make 命令是通过对Makefile 文件进行解释编译的,故我们来看Makefile 文件。

    $ cat Makefile include $(shell ./getname) # DO NOT DELETE

    通过上面可知是要执行的Makefile文件名为执行getname后得到的结果

    $ cat getname #echo $(pwd0=$(pwd);pwd1=$(dirname $pwd0)/zloader.;echo Makefile.${pwd0#$pwd1}) pwd=$(pwd); if [ "${pwd#*/zloader.}" = "$pwd" ];then echo Makefile.cpci else echo Makefile.${pwd#*/zloader.} fi

    通过上面可知是得到的是Makefile.ls2k

    $ cat Makefile.ls2k TARGET=LS2K TARGETEL=ls2k export START=start.o MEMSIZE=128 ZLOADER_OPTIONS=-mips3 include Makefile.inc

    通过查看Makefile.ls2k可知其他主要是定义了一些变量和调用Makefile.inc

    $ cat Makefile.inc ifndef PMONCC CC=$(CROSS_COMPILE)gcc -mabi=32 CROSS_COMPILE ?= mipsel-linux- else CC=${PMONCC} endif ifeq "$(shell echo ${CC}|grep 'mips-elf-')" "" ifeq "$(shell echo ${CC}|grep '\-mabi=64')" "" LD = $(CROSS_COMPILE)ld -m elf32ltsmip -G 0 -static -n -nostdlib OUT_FORMAT="elf32-tradlittlemips" else LD = $(CROSS_COMPILE)ld -m elf64ltsmip -G 0 -static -n -nostdlib OUT_FORMAT="elf64-tradlittlemips" endif else ENDIAN_FLAG= -EL LD = $(CROSS_COMPILE)ld -m elf32ebmip -G 0 -static -n -nostdlib -EL CC :=${CC} -EL OUT_FORMAT="elf32-littlemips" endif RAMSTARTADDR?=0xffffffff88000000 GZROMSTARTADDR?=0xffffffff8f900000 ROMSTARTADDR?=0xffffffff8f010000 export CROSS_COMPILE export CC += ${MYCC} -mno-abicalls -fno-pic export LD export MKDEP=makedepend ifeq ("${tgt}","rom") gencode=./genrom endif ifeq ("${tgt}","ejtag_rom") gencode=./genrom_ejtag endif ifeq ("${tgt}","ejtag_rom1") gencode=./genrom CC += -DBOOT_FROM_EJTAG endif ifeq ("${tgt}","ejtag_ram") gencode=./genrom ROMSTARTADDR=0xffffffffff200200 endif ifeq ("${tgt}","rom1") gencode=./genrom endif ifdef obj export CC += -g3 pwd=$(shell pwd) gcc_E: cd ../Targets/${TARGET}/compile/${TARGETEL};${pwd}/mymake ${obj} > /tmp/tmp.c endif ifndef tgt help: @echo use make tgt=sim for sim in linux @echo use make tgt=rom for generate romfile gzrom.bin @echo use make tgt=ram for generate ramfile gzram @echo use make cfg for config @echo use make recfg for change config @echo use make tgt=rom DEBUG=-g MYCC="'"-g3 -DMYDBG='"printf(\"debug:%s,%d\\n\",__FILE__,__LINE__);"'"'" to support MYDBG macro. else all: ${tgt} sim: clean pmon.bin.c gcc -o zloader -DSIM zloader.c ejtag_rom ejtag_rom1 ejtag_ram rom: clean ${START} zloader.o gcc -DSTARTADDR=${GZROMSTARTADDR} -DOUT_FORMAT=\"${OUT_FORMAT}\" -DOUT_ARCH=mips -Umips -E -P ld.script.S > ld.script ${LD} -T ld.script -e start -o gzrom ${START} zloader.o ${CROSS_COMPILE}objcopy -O binary gzrom gzrom.bin ram: clean startram.o zloader.o ${CC} -DSTARTADDR=${RAMSTARTADDR} -DOUT_FORMAT=\"${OUT_FORMAT}\" -DOUT_ARCH=mips -Umips -E -P ld.script.S > ld.script ${LD} -T ld.script -e start -o gzram startram.o zloader.o ${START}: rm -f ../Targets/${TARGET}/compile/${TARGETEL}/${START} gcc -DSTARTADDR=${ROMSTARTADDR} -DOUT_FORMAT=\"${OUT_FORMAT}\" -DOUT_ARCH=mips -Umips -E -P ld.script.S > ../Targets/${TARGET}/conf/ld.script make -C ../Targets/${TARGET}/compile/${TARGETEL}/ cp ../Targets/${TARGET}/compile/${TARGETEL}/${START} . startram.o: gcc -DSTARTADDR=${RAMSTARTADDR} -DOUT_FORMAT=\"${OUT_FORMAT}\" -DOUT_ARCH=mips -Umips -E -P ld.script.S > ../Targets/${TARGET}/conf/ld.script make -C ../Targets/${TARGET}/compile/${TARGETEL}/ DEBUG='-g -DMYDBG="printf(\"debug:%s,%d\\n\",__FILE__,__LINE__);"' $(CC) -D_LOCORE -G 0 -nostdinc -DMIPS -DCONS_BAUD="B115200" -DCONFIG_CACHE_64K_4WAY -D_KERNEL -D__OpenBSD__ -DPMON -D__PMON__ -mno-abicalls -c startram.S ${ZLOADER_OPTIONS} -D MEMSIZE=${MEMSIZE} # $(CC) -D_LOCORE -G 0 -nostdinc -DMIPS -DCONS_BAUD="B115200" -DCONFIG_CACHE_64K_4WAY -D_KERNEL -D__OpenBSD__ -DPMON -D__PMON__ -EL -mno-abicalls -mcpu=r4000 -c startram.S -D MEMSIZE=${MEMSIZE} zloader.o: zloader.c inflate.c malloc.c memop.c pmon.bin.c initmips.c $(CC) -c zloader.c ${ZLOADER_OPTIONS} -DMEMSIZE=${MEMSIZE} rom1: clean ${START} zloader1.o gcc -DSTARTADDR=0xffffffff9fc00000 -D_ROM1 -DOUT_FORMAT=\"${OUT_FORMAT}\" -DOUT_ARCH=mips -Umips -E -P ld.script.S > ld.script ${LD} -T ld.script -e start -o gzrom ${START} zloader.o ${CROSS_COMPILE}objcopy -O binary gzrom gzrom.bin zloader1.o: zloader.c inflate.c malloc.c memop.c pmon.bin.c initmips.c program.o xmodem.o sed -i 's/initmips/initmips1/' initmips.c sed -i 's/flush_cache2();//;s/flush_cache();//' initmips.c $(CC) -g -c -o zloader.tmp.o zloader.c ${ZLOADER_OPTIONS} -DMEMSIZE=${MEMSIZE} ${LD} -r -o zloader.o zloader.tmp.o program.o xmodem.o program.o: program.S make -C ../Targets/${TARGET}/compile/${TARGETEL}/ `pwd`/$@ xmodem.o: xmodem.c make -C ../Targets/${TARGET}/compile/${TARGETEL}/ `pwd`/$@ zlib_loader.o: zlib_loader.c ./zlib_gzip zlib_pmon.bin.c initmips.c cd zlib_inflate;$(CC) -I ../../include -c *.c #cd zlib_inflate;$(CC) -I ../../include -EL -mcpu=r4000 -c *.c #$(CC) -I ../include -EL -mcpu=r4000 -c zlib_loader.c $(CC) -I ../include -c zlib_loader.c initmips.c: ../Targets/${TARGET}/compile/${TARGETEL}/pmon ${gencode} $< > initmips.c zlib_pmon.bin.c: ../Targets/${TARGET}/compile/${TARGETEL}/pmon.bin ./zlib_gzip $< zlib_pmon.bin.gz ./bin2c zlib_pmon.bin.gz zlib_pmon.bin.c biosdata pmon.bin.c: ../Targets/${TARGET}/compile/${TARGETEL}/pmon.bin gzip $< -c > pmon.bin.gz ./bin2c pmon.bin.gz pmon.bin.c biosdata endif ifeq ("${tgt}","rom") gencode=./genrom endif ifeq ("${tgt}","zlib_rom") gencode=./genrom endif ifndef gencode gencode=./genram endif dtb: make -C ../Targets/${TARGET}/compile/${TARGETEL}/ DTB_O=`pwd`/${TARGET}.dtb.i DTB_I=`pwd`/../Targets/${TARGET}/conf/${TARGET}.dts dtb ./dtc -I dts -O dtb -o ${TARGET}.dtb ${TARGET}.dtb.i ( echo "#include <include/load_dtb.h>";echo NVRAM_OFFS; echo DTB_OFFS; )| make -C ../Targets/${TARGET}/compile/${TARGETEL}/ DTB_O=`pwd`/dtbinfo.txt DTB_I=- dtb [ -f gzrom.bin ] && cp gzrom.bin gzrom-dtb.bin && python ../tools/pmonenv.py -O $$((`tail -n 1 dtbinfo.txt`)) -o $$((`tail -n 2 dtbinfo.txt|head -n 1`)) -f gzrom-dtb.bin -d ${TARGET}.dtb -w al=\(usb0,0\)/boot/vmlinuz al1=\(wd0,0\)/boot/vmlinuz append="'console=ttyS0,115200 console=tty initcall_debug=1 loglevel=20'" FR=1 cleanall: clean make -C ../Targets/${TARGET}/compile/${TARGETEL}/ clean clean: rm -rf *.o zlib_gzip zloader pmon.bin.c gzrom gzrom.bin gzram initmips.c pmon.bin.gz zlib_deflate/*.o zlib_inflate/*.o zlib_gzrom zlib_gzrom.bin cfg: # DO NOT DELETE perl -i -ne 'print;exit if(/^# DO NOT DELETE/);' ../lib/libc/Makefile perl -i -ne 'print;exit if(/^# DO NOT DELETE/);' ../lib/libm/Makefile perl -i -ne 'print;exit if(/^# DO NOT DELETE/);' ../lib/libz/Makefile mkdir -p ../Targets/${TARGET}/compile cd ../Targets/${TARGET}/conf/;pmoncfg ${TARGETEL} make -C ../Targets/${TARGET}/compile/${TARGETEL}/ depend clean recfg: vi ../Targets/${TARGET}/conf/$(TARGETEL) make cfg zlib_gzip: zlib_gzip.c cd zlib_deflate/;gcc -I ../../include -c *.c cd zlib_inflate/;gcc -I ../../include -c *.c gcc -o zlib_gzip zlib_gzip.c zlib_deflate/*.o zlib_inflate/*.o

    从上可知Makefile.inc 是真正执行编译的控制文件。我们从编译步骤一步一步来分析。

    make cfg,对应的过程

    cfg: # DO NOT DELETE perl -i -ne 'print;exit if(/^# DO NOT DELETE/);' ../lib/libc/Makefile perl -i -ne 'print;exit if(/^# DO NOT DELETE/);' ../lib/libm/Makefile perl -i -ne 'print;exit if(/^# DO NOT DELETE/);' ../lib/libz/Makefile mkdir -p ../Targets/${TARGET}/compile cd ../Targets/${TARGET}/conf/;pmoncfg ${TARGETEL} make -C ../Targets/${TARGET}/compile/${TARGETEL}/ depend clean

    其中TARGET和 TARGETEL 在Makefile.ls2k 中定义了,分别是LS2K 和 ls2k make tgt=cfg 对四件事:

    处理libc, libm, libz 的Makefile创建文件夹Targets/LS2K/compile进入Targets/LS2K/conf 目录,进行pmoncfg ls2k, ls2k 是配置文件指定选用哪些驱动模块和命令, files.LS2K 和 conf/files指定了每个模块或命令对应的实现文件和宏定义。执行pmoncfg ls2k 之后会生成Targets/LS2K/compile/ls2k目录,目录里面有相应的文件。 $ ls ahci_cdrom.h cd.h cmd_shell.h flash.h logfile.h mod_debugger.h mod_sisfb.h mod_usb_kbd.h mod_vesa.h options raw_ether.h usbnet.h ahci_sd.h cmd_env.h cs5536.h gzip.h loopdev.h mod_display.h mod_smi502.h mod_usb_ohci.h mod_vgacon.h pcibr.h sdcard.h wd.h atp.h cmd_hist.h elf32only.h ide_cd.h machine mod_framebuffer.h mod_smi712.h mod_usb_storage.h mod_x86emu.h pci.h sd.h bpfilter.h cmd_lwdhcp.h ether.h ioconf.c mainbus.h mod_load.h mod_symbols.h mod_usb_uhci.h mod_x86emu_int10.h pcinvme.h target bridge.h cmd_more.h fd.h iso9660.h Makefile mod_s3load.h mod_tod.h mod_usb_xhci.h nand.h ramfiles.h tcp.h 跳转到 Targets/LS2K/compile/ls2k 执行命令make depend clean

    Targets/LS2K/compile/ls2k下的Makefile节选

    IDENT=-DVGAROM_IN_BIOS -DLOONGSON_2K -DBOOT_PARAM -DVRAM_SIZE="0x10" -DSYSTYPE="\"FCR\"" -DTARGETNAME="\"FCR\"" -DLS2K_STR -DBONITOEL -DDEVBD2E -DMIPS -DINET -DLS3_HT -Dloongson3A3 -D LSMC_2 -DDDR3_DIMM -DAUTO_DDR_CONFIG -DLOONGSON_GMAC -DDTB -DINTERFACE_3A780E -DCONS_BAUD="B115200" -DMY40IO -DMY61IO -DVGA_BASE="0xb0000000" -DVGA_NO_ROM -DNOPCINAMES -DCONFIG_VIDEO_ 16BPP -DNOSNOOP -DHAVE_TOD -DINTERNAL_RTC -DHAVE_NVENV -DHAVE_LOGO -DUSE_SUPERIO_UART -DAUTOLOAD -DCONFIG_CACHE_64K_4WAY -DNVRAM_IN_FLASH -DSET_DDR_FREQ -DIDE_DMA -DIDECD -DFOR_GXEMUL -DFLOATINGPT -DCOM3_BASE_ADDR="0xbfe001e0" -DINPUT_FROM_BOTH -DOUTPUT_TO_BOTH -DKBD_CHECK_FAST -DTEST_USB_HOST -DCONFIG_SLOW_PCI_FOR_BROKENDEV -DCONFIG_VIDEO_SW_CURSOR -DHPET_RTC S!= echo `/bin/pwd`/../../../.. ENDIAN=EL ifndef S S:=$(shell cd ../../../..; pwd) endif TARGET= ${S}/Targets/LS2K SUBTARGET?=ls2k CPPFLAGS=-mips3 OBJS= wdc.o mainbus.o pcibr.o if.o if_ethersubr.o if_loop.o if_media.o \ radix.o raw_cb.o raw_usrreq.o route.o rtsock.o if_ether.o in.o \ ... ... ... CFILES= $S/sys/dev/ic/wdc.c $S/pmon/dev/mainbus.c $S/pmon/dev/pcibr.c \ $S/sys/net/if.c $S/sys/net/if_ethersubr.c $S/sys/net/if_loop.c \ ... ... ... SFILES= all: pmon pmon: ${SYSTEM_DEP} newvers ${SYSTEM_LD_HEAD} ${SYSTEM_LD} ${SYSTEM_LD_TAIL} export CFILES OBJS SFILES include ${S}/Makefile.inc

    根目录下的Makefile.inc,这里面主要是包含了libc,libz, libm等的编译规则

    $ cat Makefile.inc # $Id: Makefile.Bonito2fdev,v 1.1.1.1 2006/09/14 01:59:09 root Exp $ # # Makefile for PMON2000 EV64240 # # This makefile is constructed from a machine description: # config machineid # Most changes should be made in the machine description # /sys/arch/pmonppc/conf/``machineid'' # after which you should do # config machineid # Machine generic makefile changes should be made in # /sys/arch/pmonppc/conf/Makefile.pmonppc # after which config should be rerun for all machines of that type. # # N.B.: NO DEPENDENCIES ON FOLLOWING FLAGS ARE VISIBLE TO MAKEFILE # IF YOU CHANGE THE DEFINITION OF ANY OF THESE RECOMPILE EVERYTHING # .SUFFIXES: .S .c .o CROSS_COMPILE ?=mipsel-linux- # # Include the make variables (CC, etc...) # AS = $(CROSS_COMPILE)as LD = $(CROSS_COMPILE)ld -m elf32ltsmip -G 0 -static -n -nostdlib CC ?= $(CROSS_COMPILE)gcc CPP = $(CC) -E AR = $(CROSS_COMPILE)ar NM = $(CROSS_COMPILE)nm STRIP = $(CROSS_COMPILE)strip OBJCOPY = $(CROSS_COMPILE)objcopy OBJDUMP = $(CROSS_COMPILE)objdump RANLIB = $(CROSS_COMPILE)ranlib SIZE = $(CROSS_COMPILE)size ifeq "$(shell echo ${CC}|grep 'mips-elf-')" "" ifeq "$(shell echo ${CC}|grep '\-mabi=64')" "" LD = $(CROSS_COMPILE)ld -m elf32ltsmip -G 0 -static -n -nostdlib else LD = $(CROSS_COMPILE)ld -m elf64ltsmip -G 0 -static -n -nostdlib endif else ENDIAN_FLAG= -EL LD = $(CROSS_COMPILE)ld -m elf32ebmip -G 0 -static -n -nostdlib -EL endif OPT?= -O2 IDENT:=${IDENT} $(shell echo ${IDENT}|sed -n 's/.*-DX\([0-9]\+\)x\([0-9]\+\).*/ -DFB_XSIZE=\1 -DFB_YSIZE=\2 /p') IDENT:=${IDENT} $(shell echo ${IDENT}|sed -n 's/.*-DCONFIG_VIDEO_\([0-9]\+\)BPP.*/ -DFB_COLOR_BITS=\1 /p') all: pmon # source tree is located via $S relative to the compilation directory ifndef S S:=$(shell cd ../../../..; pwd) endif # Defines START?=start.o MACHINE=mips MACHINE_ARCH=mips COMPILEDIR=${shell pwd} OBJDIR=${COMPILEDIR} PMONDIR=${S} INCLUDES= -I. -I${S}/include -I./machine -I${S} \ -I${S}/sys/arch/${MACHINE}/include -I${S}/sys \ -I${TARGET} -I${COMPILEDIR} -I${PATH1} -nostdinc -fno-strict-aliasing -fno-pic ifneq "$(findstring $S/x86emu/src,$(CFILES))" "" INCLUDES += -I${S}/x86emu/src/x86emu/ -I${S}/x86emu/src/x86emu/include else INCLUDES += -I${S}/x86emu/int10/x86emu/include -I${S}/x86emu/int10/x86emu/src/x86emu/x86emu endif CPPFLAGS := ${CPPFLAGS} ${ENDIAN_FLAG} ${INCLUDES} ${IDENT} -D_KERNEL -D__OpenBSD__ -DPMON -D__PMON__\ -mmemcpy -mno-abicalls -fno-builtin#-march=r4600 #CWARNFLAGS= -Werror -Wall -Wmissing-prototypes -Wstrict-prototypes \ -Wno-uninitialized -Wno-format -Wno-main CWARNFLAGS= -Wall -Wstrict-prototypes \ -Wno-uninitialized -Wno-format -Wno-main CFLAGS= ${DEBUG} ${CWARNFLAGS} ${OPT} -G 0 AFLAGS= -D_LOCORE -G 0 LFLAGS= ${ENDIAN_FLAG} -N -G 0 -T../../conf/ld.script -e start STRIPFLAGS= -g -S --strip-debug HOSTCC?= ${CC} HOSTED_CPPFLAGS=${CPPFLAGS:S/^-nostdinc$//} HOSTED_CFLAGS= ${CFLAGS} include ${S}/lib/libc/Makefile.inc LIBC=${CLIB} include ${S}/lib/libm/Makefile.inc LIBM=${MLIB} include ${S}/lib/libz/Makefile.inc LIBZ=${ZLIB} # compile rules: rules are named ${TYPE}_${SUFFIX}${CONFIG_DEP} # where TYPE is NORMAL, DRIVER, or PROFILE}; SUFFIX is the file suffix, # capitalized (e.g. C for a .c file), and CONFIG_DEP is _C if the file # is marked as config-dependent. USRLAND_C= ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} -c $< USRLAND_C_C= ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} ${PARAM} -c $< NORMAL_C= ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} -c $< NORMAL_C_C= ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} ${PARAM} -c $< DRIVER_C= ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} -c $< DRIVER_C_C= ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} ${PARAM} -c $< NORMAL_S= ${CC} ${AFLAGS} ${CPPFLAGS} -c $< NORMAL_S_C= ${AS} ${COPTS} ${PARAM} $< -o $@ # load lines for config "xxx" will be emitted as: # xxx: ${SYSTEM_DEP} # ${SYSTEM_LD_HEAD} # ${SYSTEM_LD} # ${SYSTEM_LD_TAIL} #SYSTEM_OBJ= ${START} crtbegin.o param.o ioconf.o ri.o ${OBJS} ${LIBC} ${LIBM} ${LIBZ} \ SYSTEM_OBJ= ${START} crtbegin.o param.o ioconf.o ri.o ${OBJS} ${LIBC} ${LIBM} ${LIBZ} \ crtend.o SYSTEM_DEP= Makefile ${SYSTEM_OBJ} SYSTEM_LD_HEAD= rm -f $@ SYSTEM_LD= @echo ${LD} ${LFLAGS} -o $@ ${LIBDIR} '${SYSTEM_OBJ}' vers.o; \ ${LD} ${LFLAGS} -o $@ ${LIBDIR} ${SYSTEM_OBJ} vers.o -L../../../../examples/math/ -lgcc SYSTEM_LD_TAIL= @${SIZE} $@; chmod 755 $@ ; \ ${OBJCOPY} -O binary $@ $@.bin DEBUG?= ifneq ("${DEBUG}", "") LFLAGS+= -X SYSTEM_LD_TAIL+=; \ echo cp $@ $@.gdb; rm -f $@.gdb; cp $@ $@.gdb; \ echo ${STRIP} ${STRIPFLAGS} $@; ${STRIP} ${STRIPFLAGS} $@ else LFLAGS+= -S endif param.c: $S/sys/kern/param.c rm -f param.c cp $S/sys/kern/param.c . param.o: param.c Makefile ${NORMAL_C_C} ioconf.o: ioconf.c ${NORMAL_C} ri.o:ri.c Makefile ${NORMAL_C_C} ri.c: $S/pmon/arch/mips/ri.c rm -f ri.c cp $S/pmon/arch/mips/ri.c . crtbegin.c: $S/pmon/arch/mips/crtbegin.c rm -f crtbegin.c cp $S/pmon/arch/mips/crtbegin.c . crtbegin.o: crtbegin.c Makefile ${NORMAL_C_C} crtend.c: $S/pmon/arch/mips/crtend.c rm -f crtend.c cp $S/pmon/arch/mips/crtend.c . crtend.o: crtend.c Makefile ${NORMAL_C_C} newvers: ${SYSTEM_DEP} ${SYSTEM_SWAP_DEP} sh $S/conf/newvers.sh ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} -c vers.c clean:: rm -f eddep *netbsd netbsd.gdb tags *.[io] [a-z]*.s \ [Ee]rrs linterrs makelinks genassym genassym.o lint: @lint -hbxncez -DGENERIC -Dvolatile= ${CPPFLAGS} -UKGDB \ ${CFILES} \ ioconf.c param.c | \ grep -v 'static function .* unused' tags: @echo "see $S/kern/Makefile for tags" links: egrep '#if' ${CFILES} | sed -f $S/conf/defines | \ sed -e 's/:.*//' -e 's/\.c/.o/' | sort -u > dontlink echo ${CFILES} | tr -s ' ' '\12' | sed 's/\.c/.o/' | \ sort -u | comm -23 - dontlink | \ sed 's,../.*/\(.*.o\),rm -f \1; ln -s ../GENERIC/\1 \1,' > makelinks sh makelinks && rm -f dontlink SRCS= ${TARGET}/${SUBTARGET}/start.S \ param.c ioconf.c ri.c ${CFILES} ${SFILES} depend:: .depend .depend: ${SRCS} param.c ${MKDEP} ${AFLAGS} ${shell echo ${CPPFLAGS}|sed -e 's/ -f[^ ]*//g' } ${TARGET}/${SUBTARGET}/start.S ${MKDEP} -a ${CFLAGS} ${shell echo ${CPPFLAGS}|sed -e 's/ -f[^ ]*//g' } param.c ioconf.c ${CFILES} ifneq (${SFILES}, "") ${MKDEP} -a ${AFLAGS} ${shell echo ${CPPFLAGS}|sed -e 's/ -f[^ ]*//g' } ${SFILES} endif # depend on root or device configuration autoconf.o conf.o: Makefile # depend on network or filesystem configuration uipc_proto.o vfs_conf.o: Makefile ${START}: ${TARGET}/${SUBTARGET}/${START:.o=.S} Makefile ${NORMAL_S} dtb: ${CC} ${AFLAGS} ${CPPFLAGS} -E -D__ASSEMBLY__ -D__DTS__ -x assembler-with-cpp -o $(DTB_O) $(DTB_I) zpmon: startz.o rm start.o && cp -f startz.o start.o make pmon make -C ../zboot zpmon startz.o: ${TARGET}/${SUBTARGET}/startz.S Makefile ${NORMAL_S}

    make tgt=rom 对应的过程

    Makefile.inc部分节选

    ${START}: rm -f ../Targets/${TARGET}/compile/${TARGETEL}/${START} gcc -DSTARTADDR=${ROMSTARTADDR} -DOUT_FORMAT=\"${OUT_FORMAT}\" -DOUT_ARCH=mips -Umips -E -P ld.script.S > ../Targets/${TARGET}/conf/ld.script make -C ../Targets/${TARGET}/compile/${TARGETEL}/ cp ../Targets/${TARGET}/compile/${TARGETEL}/${START} .

    根据编译时指定的参数tgt=rom 或 tgt=rom以ld.script.S生成Targets/LS2K/conf/ld.script文件。 主要区别是start的地址不同。 编译生成pmon, pmon.bin, start.o,拷贝Target/LS2K/compile/ls2k/start.o 到当前位置(zloader.ls2k) 其中pmon.bin是通过objcopy -o binary pmon而来。根目录下Makefile.inc的编译规则:

    SYSTEM_LD_TAIL= @${SIZE} $@; chmod 755 $@ ; \ ${OBJCOPY} -O binary $@ $@.bin

    如果编译时参入DEBUG=-g 参数则会生成pmon.gdb 文件,用于调试。根目录下Makefile.inc的编译规则:

    DEBUG?= ifneq ("${DEBUG}", "") LFLAGS+= -X SYSTEM_LD_TAIL+=; \ echo cp $@ $@.gdb; rm -f $@.gdb; cp $@ $@.gdb; \ echo ${STRIP} ${STRIPFLAGS} $@; ${STRIP} ${STRIPFLAGS} $@ else LFLAGS+= -S endif

    Makefile.inc的部分节选,rom, zloader.o 目标

    ejtag_rom ejtag_rom1 ejtag_ram rom: clean ${START} zloader.o gcc -DSTARTADDR=${GZROMSTARTADDR} -DOUT_FORMAT=\"${OUT_FORMAT}\" -DOUT_ARCH=mips -Umips -E -P ld.script.S > ld.script ${LD} -T ld.script -e start -o gzrom ${START} zloader.o ${CROSS_COMPILE}objcopy -O binary gzrom gzrom.bin zloader.o: zloader.c inflate.c malloc.c memop.c pmon.bin.c initmips.c $(CC) -c zloader.c ${ZLOADER_OPTIONS} -DMEMSIZE=${MEMSIZE}

    链接start.o和zloader.o 生成gzrom, 通过objcopy 将gzrom转成raw binary gzrom.bin即去除符号表和重定位信息。

    生成initmips.c

    initmips.c: ../Targets/${TARGET}/compile/${TARGETEL}/pmon ${gencode} $< > initmips.c pmon.bin.c: ../Targets/${TARGET}/compile/${TARGETEL}/pmon.bin gzip $< -c > pmon.bin.gz ./bin2c pmon.bin.gz pmon.bin.c biosdata ifeq ("${tgt}","rom") gencode=./genrom endif

    将pmon.bin通过gzip 压缩成pmon.bin.gz 将pmon.bin.gz 通过bin2c 转换成为C数组文件pmon.bin.c,数组名为biosdata genrom 的功能是通过执行objdump -x pmon获取pmon的符号表和重定位信息,通过匹配正则表达式从中获取 start和initmips的地址,initmips.c的功能用于将biosdata解压到start处,之后再跳转到initmips处执行。 所以pmon的执行过程是从start.S 开始跳转到zloader.ls2k/initmips.c中的initmips,之后再跳转到Targets/LS2K/ls2k/tgt_machdep.c中的initmips函数

    通过上面可知 initmips.c 是通过 ./genrom ../Targets/LS2K/compile/ls2k/pmon > initmips.c 生成的

    genrom 的内容:

    $ cat genrom #!/usr/bin/perl my ($myedata,$myend,$initmips,$mystart); open(F,qq(objdump -x $ARGV[0]|)); while(<F>) { chomp; if(/([0-9a-f]+).+_edata/){ $myedata=qq(0x$1); } if(/([0-9a-f]+).+_end$/){ $myend=qq(0x$1); } if(/([0-9a-f]+).+initmips$/){ $myinitmips=qq(0x$1); } if(/([0-9a-f]+).+\s_start$/){ $mystart=qq(0x$1); } } printf(<< "END" void stringserial(char *msg); void realinitmips(unsigned long long msize); void enable_cache() { __asm__ volatile( ".set mips2;\\n" \\ " mfc0 \$4,\$16;\\n" \\ " and \$4,\$4,0xfffffff8;\\n" \\ " or \$4,\$4,0x3;\\n" \\ " mtc0 \$4,\$16;\\n" \\ " .set mips0;\\n" :: :"\$4" ); } #ifndef NOCACHE2 void flush_cache2() { asm volatile(\ ".set mips3;\\n" \\ " mfc0 \$3, \$15; # read processor ID register;\\n" \\ " li \$2, 0x6303; #godson2f prid;\\n" \\ " beq \$2, \$3, godson_2f;\\n" \\ " nop;\\n" \\ " li \$2, 0x6302; #godson2e prid;\\n" \\ " bne \$2, \$3,11f; #godson3a/2g need not flush\\n" \\ " nop;\\n" \\ "# godson2e;\\n" \\ " godson_2f: " \\ " li \$2, 0x80000000;\\n" \\ " addu \$3,\$2,512*1024;\\n" \\ "10:\\n" \\ " cache 3, 0(\$2);\\n" \\ " cache 3, 1(\$2);\\n" \\ " cache 3, 2(\$2);\\n" \\ " cache 3, 3(\$2);\\n" \\ " addu \$2, 32;\\n" \\ " bne \$2,\$3, 10b;\\n" \\ " nop;\\n" \\ "11:\\n" \\ :::"\$2","\$3" ); } #else void flush_cache() { #ifndef WAYBIT #define WAYBIT 0 #endif #define WAY__(x) #x #define WAY_(x,y) WAY__((x<<y)) #define WAY(x) WAY_(x,WAYBIT) asm volatile(\ " .set mips3;\\n" " li \$5,0x80000000;\\n" " addu \$6,\$5,16384;\\n" "1:\\n" " cache 1," WAY(0) "(\$5);\\n" " cache 1," WAY(1) "(\$5);\\n" " cache 1," WAY(2) "(\$5);\\n" " cache 1," WAY(3) "(\$5);\\n" " cache 0," WAY(0) "(\$5);\\n" " cache 0," WAY(1) "(\$5);\\n" " cache 0," WAY(2) "(\$5);\\n" " cache 0," WAY(3) "(\$5);\\n" " add \$5,\$5,32;\\n" " bne \$5,\$6,1b;\\n" " nop;\\n" " .set mips0;\\n" ::: "\$5","\$6"); } #endif void initmips(unsigned long long msize,unsigned long long dmsize, unsigned long long dctrl) { long *edata=(void *)$myedata; long *end=(void *)$myend; int *p; int debug=(msize==0); #ifdef LS3A2H_STR long long str_ra,str_flag,str_sp; str_ra = *((long long*)0xafaaa040); str_sp = *((long long*)0xafaaa048); str_flag = *((long long*)0xafaaa050); #endif // CPU_TLBClear(); stringserial("Uncompressing Bios"); if(!debug||dctrl&1)enable_cache(); #ifdef LS3A2H_STR if ((str_sp < 0x9800000000000000) || (str_ra < 0xffffffff80000000) || (str_flag != 0x5a5a5a5a5a5a5a5a)) { #endif while(1) { if(run_unzip(biosdata,$mystart)>=0)break; } #ifdef LS3A2H_STR } #endif stringserial("OK,Booting Bios\\r\\n"); for(p=edata;p<=end;p++) { *p=0; } memset($mystart-0x1000,0,0x1000);//$mystart-0x1000 for frame(registers),memset for pretty #ifdef NOCACHE2 flush_cache(); #else flush_cache2(); #endif realinitmips(debug?dmsize:msize); } void realinitmips(unsigned long long msize) { stringserial("zloader/initmips.c realinitmips ...\\r\\n"); asm ("li \$29,$mystart-0x4000;\\n" \\ " li \$2,$myinitmips;\\n" \\ " move \$4,\%0;\\n" \\ " jalr \$2;\\n" \\ " nop;\\n" \\ " 1: b 1b;nop;" \\ : : "r" (msize) : "\$29", "\$2","\$4"); } END );

    make dtb 对应的过程

    dtb: make -C ../Targets/${TARGET}/compile/${TARGETEL}/ DTB_O=`pwd`/${TARGET}.dtb.i DTB_I=`pwd`/../Targets/${TARGET}/conf/${TARGET}.dts dtb ./dtc -I dts -O dtb -o ${TARGET}.dtb ${TARGET}.dtb.i ( echo "#include <include/load_dtb.h>";echo NVRAM_OFFS; echo DTB_OFFS; )| make -C ../Targets/${TARGET}/compile/${TARGETEL}/ DTB_O=`pwd`/dtbinfo.txt DTB_I=- dtb [ -f gzrom.bin ] && cp gzrom.bin gzrom-dtb.bin && python ../tools/pmonenv.py -O $$((`tail -n 1 dtbinfo.txt`)) -o $$((`tail -n 2 dtbinfo.txt|head -n 1`)) -f gzrom-dtb.bin -d ${TARGET}.dtb -w al=\(usb0,0\)/boot/vmlinuz al1=\(wd0,0\)/boot/vmlinuz append="'console=ttyS0,115200 console=tty initcall_debug=1 loglevel=20'" FR=1

    进入Targets/LS2K/compile/ls2k,以Targets/LS2K/conf/ls2k.dts为输入文件,LS2K.dtb.i为输出文件,执行make dtb 通过dtc 将LS2K.dtb.i转换成LS2K.dtb 通过../tools/pmonenv.py 将dtb和内核启动参数追加到gzrom.bin生成gzrom-dtb.bin

    make dtb 的编译规则(根目录下的Makefile.inc):

    dtb: ${CC} ${AFLAGS} ${CPPFLAGS} -E -D__ASSEMBLY__ -D__DTS__ -x assembler-with-cpp -o $(DTB_O) $(DTB_I)

    tools/pmonenv.py

    $ cat ../tools/pmonenv.py """ python pmonenv.py -f gzrom.bin -o 0x70000 -s 512 al=/dev/mtd0 append="'root=/dev/mtdblock0'" python ../tools/pmonenv.py -f gzrom-dtb.bin -d ls2k.dtb -w al=/dev/ram@p0x110000000 al1=/dev/ram@p0x110000000 append="'console=ttyS0,115200 initcall_debug=1 loglevel=20 nosmp'" FR=1 """ import struct import sys import getopt def readenv(fname,foff,fsz,argv): f=open(fname,'rb+') f.seek(foff,0) a=f.read(fsz); a=a.ljust(fsz,b'\x00') f.close() d={} b = struct.unpack('!'+str(len(a)//2)+'H',a) if(sum(b)&0xffff): print('checksum error, rebuild env') t = argv else: e = a[2:].find(b'\x00\x00') t = a[2:2+e].split(b'\x00')+list(map(lambda x:x.encode('utf8'),argv)) for i in t: a=i.split(b'=',1) if len(a) > 1: d[a[0]] = a[1] elif a[0] in d: del d[a[0]] return d def writeenv(fname,foff,fsz,d): a=b'\x00\x00' for i in d.keys(): a += i+b'='+d[i]+b'\x00' a=a.ljust(fsz,b'\x00') b = struct.pack('!H',(-sum(struct.unpack('!'+str(len(a)//2)+'H',a)))&0xffff) a=b+a[2:] f=open(fname,'rb+') f.seek(foff,0) f.write(a) f.close() def writehexenv(fname,hexbin): f=open(fname,'rb+') f.seek(foff+fsz, 0) f.write('\xff'*256) for b in hexbin.split(','): i,v = b.split(':') f.seek(foff+int(i,0),0) f.write(v.decode('hex')) f.close() def writedtb(fname,dtb,foff): f=open(dtb,'rb') a=f.read(); f.close() a=a.ljust(0x4000-8,'\x00') b = struct.pack('I',(-sum(struct.unpack(''+str(len(a)//4)+'I',a)))&0xffffffff) a=b+a+b f=open(fname,'rb+') f.seek(foff-0x4000,0) f.write(a) f.close() if __name__ == '__main__': opt,argv=getopt.getopt(sys.argv[1:],'b:o:s:f:wd:') opt=dict(opt) foff = int(opt['-o'],0) if '-o' in opt else 0x000ff000 fsz = int(opt['-s'],0) if '-s' in opt else 500 fname = opt['-f'] if '-f' in opt else 'gzrom.bin' d=readenv(fname,foff,fsz,argv) print(d) if '-w' in opt: writeenv(fname,foff,fsz,d) if '-b' in opt: writehexenv(fname, opt['-b']) if '-d' in opt: writedtb(fname, opt['-d'], foff)
    Processed: 0.009, SQL: 8