MMC 加载
Read time: 3 minute(s)
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() // 根据 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() // 根据 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 位于 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) | // 解析 header 信息,得到 boot 的 addr 和 size 信息 | |-> blk_dread(bd, sector, cnt, load_addr) // 读取完整的 image,包括 header,注意 addr 是向前偏移过的地址