分享

嵌入式Linux启动信息全注释(上)

 leon0821 2014-04-24

 接触嵌入式开发也有两年多了,每天看着同样的启动信息似乎都有些麻木了,但上次寻找网络驱动时pan总就是从启动信息中追溯到了驱动源文件,于是想了解一下这些启动信息,对之前感觉熟悉但又不知甚解的东西做一个简单的跟踪,对以后的工作学习应该也有帮助。

 

Flash映射起始地址 进入0xf00000 uboot image (该地址应该是由0x0000处的硬件配置字决定的)
Uboot是上电后执行的第一段程序,主要用于初始化处理器及外设,启动内核。

U-Boot 1.3.0-rc2 (Oct 19 2007 - 16:58:40)

U-Boot版本信息 

 

U-Boot image的入口点是start.S汇编代码,设置一些寄存器,时钟等操作都是在汇编中完成,然后进入board_init_f顺序执行下面的系列初始化函数,board_init_f位于u-boot-1.3.0- rc3/lib_ppc/board.c中,是uboot所有C代码的第一处入口点,注意到这时候uboot是运行在rom中,只能使用很小的堆栈,并且无法修改全局变量。
 

MPC8272 Reset Status: External Soft, External Hard

代码在 u-boot-1.3.0-rc3/cpu/mpc8260/cpu_init.c函数prt_8260_rsr()中 

 

MPC8272 Clock Configuration
- Bus-to-Core Mult 4x, VCO Div 2, 60x Bus Freq 25-75 , Core Freq 100-300
- dfbrg 1, corecnf 0x1a, busdf 3, cpmdf 1, plldf 0, pllmf 3, pcidf 5
- vco_out 400000000, scc_clk 100000000, brg_clk 25000000
- cpu_clk 400000000, cpm_clk 200000000, bus_clk 100000000
- pci_clk 33333333

打印出了主板,cpu的一些指标信息,代码在u-boot-1.3.0-rc3/cpu/mpc8260/speed.c函数prt_8260_clks()中

board_init_f完成一部分初始化工作后又跳转到汇编中,初始化堆栈,控制器等,再次进入C代码段是在board.c的board_init_r中,这时候已经是加载在内存中执行,可以正常得使用堆栈了。
 

CPU: MPC8272 (HiP7 Rev 14, Mask 1.0 1K50M) at 400 MHz
Board: MSC7119RDK
I2C: ready
DRAM: 128 MB
FLASH: 16 MB
In: serial
Out: serial
Err: serial
Net: FCC1 ETHERNET, FCC2 ETHERNET

以上信息是由board_init_r函数检测,初始化,并打印,初始化看门狗之后进入common\main.c的main_loop函数中。
 

Hit any key to stop autoboot: 0

main_loop会延时一小段时间,按键进入u-boot设置,没有按键则进入正常启动流程,延时时间可以在此处修改。

Uboot设置中有两项主要配置,引导着接下来的启动过程。
1. bootcmd=bootm FF020000 无按键时就是执行该命令,uboot之前将flash的kernel映射在FF020000内存地址上,bootm也指向FF020000就能顺利启动linux内核。
2. bootargs=root=/dev/mtdblock3 rootfstype=jffs2 noinitrd init=/etc/preinit console=ttyCPM0,115200n8 Linux内核启动参数,指定了根文件系统块(mtdblock3),文件系统类型(jffs2),内核执行的初始化进程名(preinit),串口参数。(之前有一次串口出问题,就是因为consolo的值配错了),Linux内核启动参数也有其他挺好玩的应用,都可以在此修改,比如设置panic=N,可以让内核在崩溃N秒后才重启。
 

## Booting image at ff020000 ...
Image Name: Linux-2.6.14
Image Type: PowerPC Linux Kernel Image (gzip compressed)
Data Size: 1170641 Bytes = 1.1 MB
Load Address: 00000000
Entry Point: 00000000
Verifying Checksum ... OK
Uncompressing Kernel Image ... OK

以上信息是bootm的执行函数do_bootm打印的(common\cmd_bootm.c),实际上就是二进制内核文件的开头几个字节,而且注意到我们的内核是压缩内核,需要一次解压过程,解压后执行do_bootm_linux函数启动Linux内核。


-----------------------------------------Linux内核启动分割线---------------------------------


Linux内核的入口在init/main.cstart_kernel()函数中,初始化调度,中断,定时器等系列初始化操作都在该函数中。它主要完成剩余的与硬件平台相关的初始化工作,在进行一系列与内核相关的初始化后,调用第一个用户进程-init 进程并等待用户进程的执行,这样整个 Linux 内核便启动完毕。
 

Linux version 2.6.14 (huangzc@compiling-server) (gcc version 4.1.2) #3 PREEMPT Mon Dec7 13:58:26 CST 2009
以上信息保存在linux_banner常量中(init/version.c) 

 

Freescale StarCore PowerPC port

setup_arch()函数打印(arch/ppc/kernel/setup.c),ppc_md.setup_arch()回调原型在arch/ppc/syslib/m8260_setup.c的m8260_setup_arch(void)函数中,上述常量信息在arch/ppc/platforms/Msc7119rdk.h中,该文件是设备相关的,平台移植时的一大工作量应该就是修改这类文件。
setup_arch()函数是与体系结构相关的第一个初始化工作,对不同的体系结构来说该函数有不同的定义。它首先通过检测出来的处理器类型进行处理器内核的初始化,然后通过 bootmem_init()函数根据系统定义的 meminfo 结构进行内存结构的初始化,最后调用paging_init()开启 MMU,创建内核页表,映射所有的物理内存和 IO空间。
 

Staring set led to default state

led初始化,set_default_led()函数中(arch/ppc/kernel/setup.c) 

 

arch/ppc/syslib/m82xx_pci.c: The PCI bus is 33333333 Mhz.
Waiting 1 second after deasserting RST...

pq2_find_bridges()函数调用pq2ads_setup_pci()完成pci初始化(arch/ppc/syslib/m82xx_pci.c)。

 

Built 1 zonelists

build_all_zonelists函数打印(mm/page_alloc.c) 

 

Kernel command line: root=/dev/mtdblock3 rootfstype=jffs2 noinitrd init=/etc/preinit console=ttyCPM0,115200n8

start_kernel()重新打印出了Linux内核启动参数,内核启动异常时可以先核对该参数是否正确。

 

PID hash table entries: 1024 (order: 10, 16384 bytes)

pidhash_init()函数打印(kernel/pid.c),由函数也可以看出,进程id的分配查找用的是哈希算法 

 

Warning: real time clock seems stuck!

time_init()函数打印(kernel/time.c),初始化系统时钟。

 

Console: colour dummy device 80x25

console_init打印(drivers/char/tty_io.c),也是调用了系列回调。 

 

Dentry cache hash table entries: 32768 (order: 5, 131072 bytes)
Inode-cache hash table entries: 16384 (order: 4, 65536 bytes)

alloc_large_system_hash()函数打印(mm/page_alloc.c),分别在fs/dcache.c和fs/inode.c中调用。

 

Memory: 127232k available (1900k kernel code, 584k data, 96k init, 0k highmem)

mem_init()函数打印(mm/init.c) 

 

Mount-cache hash table entries: 512

mnt_init()函数打印(fs/namespace.c) 

 

NET: Registered protocol family 16

net/netlink/af_netlink.c模块初始化,调用sock_register注册函数注册netlink系列回调 

 

PCI: Probing PCI hardware

arch/ppc/kernel/pci.c模块初始化,调用pcibios_init()函数打印 

 

PCI: Cannot allocate resource region 0 of device 0000:00:00.0
PCI: Cannot allocate resource region 1 of device 0000:00:00.0

在pcibios_init()函数中pcibios_allocate_resources打印。因为我们板没有提供PCI支持,所以alloc失败? 

 

Generic PHY: Registered new driver
PHY模块初始化,注册了Generic PHY这个通用PHY设备(drivers/net/phy/phy_device.c) 

 

SCSI subsystem initialized
SCSI模块初始化,注册了scsi的系列函数方法(drivers/scsi/scsi.c) 

 

JFFS2 version 2.2. (NAND) (C) 2001-2003 Red Hat, Inc.

jffs2文件系统初始化,通过register_filesystem等函数注册文件系统(fs/jffs2/super.c) 

 

yaffs Dec 7 2009 13:57:00 Installing.

yaffs(yaffs2)文件系统初始化,打印的时间即为编译时间(fs/yaffs2/yaffs_fs.c) 

 

Initializing Cryptographic API

crypto模块初始化,完成crypto的系列内核函数(crypto/api.c)

 

Generic RTC Driver v1.07

rtc模块初始化,注册基于misc的字符设备(drivers/char/genrtc.c) 

 

Serial: CPM driver $Revision: 1.1.1.1 $
ttyCPM0 at MMIO 0xf0011a80 (irq = 4) is a CPM UART
serial模块初始化,通过tty_register_driver注册(driver/serial/cpm_uart/cpu_uart_core.c),并通过uart_configure_port()完成配置。 

 

io scheduler noop registered

io调度模块初始化,通过elv_register函数注册(drivers/block/noop-iosched.c) 

 

Uniform Multi-Platform E-IDE driver Revision: 7.00alpha2
ide: Assuming 33MHz system bus speed for PIO modes; override with idebus=xx
IDE phys mem : fe000000...fe000200 (size 00000200)

ide模块初始化(drivers/ide/ide.c),先通过ide_system_bus_speed获取总线速率,然后调用init_ide_data初始化ide相关数据 

 

hda: SanDisk SDCFJ-1024, CFA DISK drive
ide0 at 0xfe001000-0xfe001007,0xfe00200c on irq 52

ideprobe模块初始化(drivers/ide/ide-probe.c),do_identify()函数打印hda相关信息,init_irq()注册相关中断 

 

hda: max request size: 128KiB
hda: 2001888 sectors (1024 MB) w/1KiB Cache, CHS=1986/16/63
hda: cache flushes not supported
hda: hda1

idedisk模块初始化(drivers/ide/ide-disk.c),调用idedisk_setup()检测相关数据 

 

SVX8016 flash device: 1000000 at ff000000

drivers/mtd/maps/msc7119rdk.c模块初始化,flash大小等信息都定义在msc7119rdk.h中 

 

SVX8016: Found 1 x16 devices at 0x0 in 16-bit bank

drivers/mtd/chips/cfi_probe.c函数cfi_probe_chip()打印 

 

Amd/Fujitsu Extended Query Table at 0x0040

driver/mtd/chips/cfi_util.c函数cfi_read_pri()打印 

 

SVX8016: CFI does not contain boot bank location. Assuming top.
number of CFI chips: 1
cfi_cmdset_0002: Disabling erase-suspend-program due to code brokenness.

drivers/mtd/chips/cfi_cmdset_0002.c函数cfi_cmdset_0002()和cfi_amdstd_setup()打印。

 

Creating 7 MTD partitions on "SVX8016":
0x00f00000-0x00f40000 : "uboot image"
0x00f40000-0x00f80000 : "uboot env"
0x00020000-0x00160000 : "kernel"
0x00160000-0x00f00000 : "file system"
0x00020000-0x00f00000 : "kernel+fs"
0x00f80000-0x01000000 : "config"
0x00000000-0x01000000 : "binary"

msc7119rdk模块调用函数add_mtd_partitions()完成mtd分区(drivers/mtd/mtdpart.c),从这里就可以看出8032 flash上的分区分布。整理如下图: 

嵌入式Linux启动信息全注释(上)

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多