initmips()源码分析

PMON的启动代码start.S执行完成之后,跳转到了zloader/initmips.c中的initmips()函数继续执行。

zloader/initmips.c并不是手工编写的源代码文件,而是由一个叫做genromperl脚本生成的。 这个脚本的主要任务是打开目标代码文件pmon,在其中搜索以下几个符号的地址:

  1. _edata: 数据段的结尾地址,也是bss开始地址
  2. _end_: bss段的结尾地址
  3. initmips: 真正的initmips()函数的入口地址,这个函数是在Targets/LS2K/ls2k/tgt_machdep.c中定义的。
  4. _start_: 入口地址,但是因为start.o已经执行过一遍了,所以得到这个地址并不是为了再次执行start.o,而是 为了确定要将biosdata[]解压到何处,以及确定堆栈的起始地址,因为stack=_start - 0x4000

现在分析initmips()的执行流程:

  1. 打印Uncompressing Bios;
  2. run_unzip(biosdata, _start): 解压缩biosdata[]到地址_start;
  3. 打印”OK, Booting Bios”;
  4. bss清零,也就是从_edata_end这一段内存;
  5. _start-0x1000_start这一段内存清零;
  6. 跳到realinitmips()执行;
  7. realinitmips()中,设置堆栈起点为 _start - 0x4000, 跳转到真正的initmips()执行。

initmips()源码分析

真正的initmips()函数是在Targets/LS2K/ls2k/tgt_machdep.c中定义的。

现在分析真正的initmips()的执行流程:

  1. 启动CPU1?Undocumented Loongson!
  2. 设置sata gpio???
  3. 使能FPU;
  4. 清TLB;
  5. 设置内存边界;
  6. 探测CPU工作频率,打印cpu freq %u\n;
  7. CPU_ConfigCache(): 在pmon/arch/mips/cache.S中定义;
  8. spi, nand, gpio, pwm 相关设置;
  9. main()