U-Boot SPL 加载后续程序过程中的内存泄漏问题

问题

项目里是这样设计的 U-Boot SPL 加载过程:SPL 会从多种启动设备尝试加载 uImage。加载的顺序是由板卡支持代码里指定的:

文件:board//xxx/yyy.c

u32 spl_boot_device(void)
{
        return BOOT_DEVICE_MMC1;
}

void board_boot_order(u32 *spl_boot_list)
{
        spl_boot_list[0] = spl_boot_device();
        spl_boot_list[1] = BOOT_DEVICE_MMC2;
        spl_boot_list[2] = BOOT_DEVICE_SPI;
        spl_boot_list[3] = BOOT_DEVICE_NOR;
        spl_boot_list[4] = BOOT_DEVICE_SATA;
}

这里的 spl_boot_list 指定了先后顺序。如果出现某个启动设备加载失败、或者加载内容不合格等等各种问题,那么就会尝试下一个启动设备,直到加载成功、并跳转到 U-Boot,或者启动失败。

开发过程中,进行了多个组合的验证,比如写坏某些启动设备里的 uImage 内容,验证是否能从后续启动设备加载并运行,等等。

现在碰到的问题是,遍历了若干个启动设备后,U-Boot SPL 出现内存不足,导致程序本身无法继续运行。

定位及解决

走读并跟踪了 SPL 代码,定位到内存泄漏出现之前的调用关系,如下:

// FILE: common/spl/spl_fit.c
spl_load_simple_fit()
    struct spl_fit_info ctx;
    ...
    spl_simple_fit_read(&ctx, ...)
        void * buf = spl_get_fit_load_buffer()
            buf = malloc()
        ...
        info->read(..., buf)
        ...
        ctx->fit = buf;
    ...

spl_load_simple_fit() 通过调用 spl_simple_fit_read() 分配内存并往里面写入被加载的程序,所分配的内存记录在 ctx.fit 变量里。如果 spl_load_simple_fit() 后续的代码里遇到什么问题,加载过程就会被中断、并提前返回,但这里并没有正确地释放内存,所以产生了内存泄漏。

定位到了问题,解决就容易了。查找 spl_load_simple_fit() 提前返回的地方,补上恰当的内存释放、调用 free((void *)ctx.fit); 即可。

结论

这个内存泄漏,只在板子内存特别有限、且有多种启动设备的情况下,才会出现实质性的影响。

对于大多数的情况,不会出现什么影响;并且等后续的程序接管内存后,就不再是问题。所以从U-Boot 源代码来看,这个代码一直是这样。

Read More: