PMON initmips()源码分析
假initmips()
源码分析
PMON的启动代码start.S
执行完成之后,跳转到了zloader/initmips.c
中的initmips()
函数继续执行。
zloader/initmips.c
并不是手工编写的源代码文件,而是由一个叫做genrom
的perl
脚本生成的。
这个脚本的主要任务是打开目标代码文件pmon
,在其中搜索以下几个符号的地址:
_edata
: 数据段的结尾地址,也是bss
开始地址_end_
:bss
段的结尾地址initmips
: 真正的initmips()
函数的入口地址,这个函数是在Targets/LS2K/ls2k/tgt_machdep.c
中定义的。_start_
: 入口地址,但是因为start.o
已经执行过一遍了,所以得到这个地址并不是为了再次执行start.o
,而是 为了确定要将biosdata[]
解压到何处,以及确定堆栈的起始地址,因为stack=_start - 0x4000
。
现在分析initmips()
的执行流程:
- 打印
Uncompressing Bios
; run_unzip(biosdata, _start)
: 解压缩biosdata[]
到地址_start
;- 打印”OK, Booting Bios”;
bss
清零,也就是从_edata
到_end
这一段内存;_start-0x1000
到_start
这一段内存清零;- 跳到
realinitmips()
执行; - 在
realinitmips()
中,设置堆栈起点为_start - 0x4000
, 跳转到真正的initmips()
执行。
真initmips()
源码分析
真正的initmips()
函数是在Targets/LS2K/ls2k/tgt_machdep.c
中定义的。
现在分析真正的initmips()
的执行流程:
- 启动CPU1?Undocumented Loongson!
- 设置
sata gpio
??? - 使能FPU;
- 清TLB;
- 设置内存边界;
- 探测CPU工作频率,打印
cpu freq %u\n
; CPU_ConfigCache()
: 在pmon/arch/mips/cache.S
中定义;- spi, nand, gpio, pwm 相关设置;
- main()