以编译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.c
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
函数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)