3.6.3. MMC 加载
SPL 从 MMC 加载 U-Boot 的处理过程。
程序编码的时候,针对 MMC 设备添加了对应的加载程序支持,如 spl_mmc.c 中,通过使用宏:
SPL_LOAD_IMAGE_METHOD(“MMC1”, 0, BOOT_DEVICE_MMC1, spl_mmc_load_image);
将 spl_mmc_load_image
函数添加到 .u_boot_list_2_spl_image_loader_* 段。
在 SPL 初始化过程中,通过 boot_from_devices(spl_boot_list)
函数调用,检查当前项目
所支持的 SPL 读取的存储介质类型,然后依次检查是否存在对应的程序加载器。
board_init_r() // common/spl/spl.c
|-> boot_from_devices(spl_boot_list)
|-> spl_ll_find_loader() // 根据boot device找到spl_load_image指针
// 这里可能是各种介质的 load image 函数
// SPL_LOAD_IMAGE_METHOD() 定义的 Loader
// 可能是 MMC/SPI/BROM/...
找到 SPL MMC Loader 之后,从项目配置的指定 Sector 读取数据。
CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR
boot_from_devices(spl_boot_list); // common/spl/spl.c
|-> spl_ll_find_loader() // 根据boot device找到spl_load_image指针
| // 此处通过遍历固件的 .u_boot_list_2_spl_image_loader_* 段
| // 找到当前支持的存储介质,然后逐个尝试
|
|-> spl_load_image(loader);
|-> loader->load_image(spl_image, &bootdev);
spl_mmc_load_image(); // common/spl/spl_mmc.c
|-> spl_mmc_load();
|
+-------------+
|
spl_mmc_load();
|-> spl_mmc_find_device(&mmc, bootdev->boot_device);
| |-> mmc_initialize
| |-> mmc_probe
| |-> uclass_get(UCLASS_MMC, &uc)
| |-> device_probe(dev)
| |-> uclass_resolve_seq(dev)
| |-> pinctrl_select_state(dev, "default")
| | |-> pinctrl_select_state_full(dev, "default")
| | | |-> state = dev_read_stringlist_search(dev,
| | | | "pinctrl-names", "default");
| | | |-> dev_read_prop(dev, propname, &size)
| | | | // snprintf(propname, sizeof(propname),
| | | | // "pinctrl-%d", state)
| | | |
| | | |-> pinctrl_config_one(config)
| | | |-> ops = pinctrl_get_ops(pctldev)
| | | |-> ops->set_state(pctldev, config)
| | |
| | |-> pinctrl_select_state_simple(dev)
| | |-> uclass_get_device_by_seq(UCLASS_PINCTRL, 0, &pctldev)
| | |-> ops=pinctrl_get_ops(pctldev)
| | | // #define pinctrl_get_ops(dev)
| | | // ((struct pinctrl_ops *)(dev)->driver->ops)
| | |
| | |-> ops->set_state_simple(pctldev, dev)
| |
| |-> power_domain_on(&powerdomain)
| |-> uclass_pre_probe_device(dev)
| |-> clk_set_defaults(dev)
| | |-> clk_set_default_parents(dev)
| | |-> clk_set_default_rates(dev)
| |
| |-> drv->probe(dev)
| |-> uclass_post_probe_device(dev)
|
|-> mmc_init
|-> boot_mode=spl_boot_mode(bootdev->boot_device)
|-> mmc_load_image_raw_sector
|-> header=spl_get_load_buffer(-sizeof(*header), bd->blksz)
| // header位于load_addr偏移-head_size处
|
|-> blk_dread(bd, sector, 1, header)
| // 读取一个sector的u-boot image header
|
|-> mmc_load_legacy(spl_image, mmc, sector, header)
| |-> spl_parse_image_header(spl_image, header)
| // 解析u-boot image header信息,得到u-boot的addr和size信息
|
|-> blk_dread(bd, sector, cnt, load_addr)
// 读取完整的u-boot image,包括header,注意load_addr是向前偏移过的地址