将大量二进制数据从u-boot传递到linux内核

时间:2012-07-20 13:24:39

标签: memory linux-kernel arm embedded-linux u-boot

在imx50 ARM板上将大量数据(3 MB)从uboot传递到linux内核2.6.35.3时遇到一些问题。内核设备驱动程序探测功能需要此数据,然后才能释放。首先uboot将数据从闪存加载到RAM,然后使用bootargs传递linux内核的物理地址。在内核中我尝试使用arch / arm / kernel / setup.c文件中的reserve_resource()来保留一定量的内存:

--- a/arch/arm/kernel/setup.c   Tue Jul 17 11:22:39 2012 +0300
+++ b/arch/arm/kernel/setup.c   Fri Jul 20 14:17:16 2012 +0300

struct resource my_mem_res = {
    .name = "My_Region",
    .start = 0x77c00000,
    .end = 0x77ffffff,
    .flags = IORESOURCE_MEM | IORESOURCE_BUSY,
};

@@ -477,6 +479,10 @@
    kernel_code.end     = virt_to_phys(_etext - 1);
    kernel_data.start   = virt_to_phys(_data);
    kernel_data.end     = virt_to_phys(_end - 1);
+   my_mem_res.start    = mi->bank[i].start + mi->bank[i].size - 0x400000;
+   my_mem_res.end      = mi->bank[i].start + mi->bank[i].size - 1;

    for (i = 0; i < mi->nr_banks; i++) {
        if (mi->bank[i].size == 0)
@@ -496,6 +502,8 @@
        if (kernel_data.start >= res->start &&
            kernel_data.end <= res->end)
            request_resource(res, &kernel_data);
+
+       request_resource(res, &my_mem_res);
    }

    if (mdesc->video_start) {

由此我试图告诉内核它保留的内存区域以及内核不应该修改这些数据。

70000000-77ffffff : System RAM
  70027000-7056ffff : Kernel text
  70588000-7062094f : Kernel data
  77c00000-77ffffff : My_Region

在驱动程序ioremap(0x77c00000, AREA_SIZE)中用于获取内核内存地址。但是当我转储内存的内容时,只有零。如果启动内核mem=120M(总共128MB RAM可用),那么我的数据高于内核系统ram区域,然后我得到我期望的数据。

所以,我的问题:

为什么我得到零,如何将大量二进制数据从uboot传递到linux内核?

1 个答案:

答案 0 :(得分:8)

您可以使用自定义 ATAG 来传递数据块或传递地址&amp;数据长度。请注意, ATAG 中的“A”代表ARM,因此该解决方案无法移植到其他体系结构。 ATAG 优于命令行 bootarg IMO,因为您不希望用户使用物理内存地址进行清理。此外,Linux内核将在启用MMU(即虚拟内存)之前处理 ATAG 列表。

在U-Boot中,查看构建ARM标记列表的例程的lib_arm/armlinux.carch/arm/lib/bootm.c。为新标记编写自己的例程,然后在 do_bootm_linux()中调用它。

在Linux内核中 ATAG arch/arm/kernel/setup.c中处理,当时尚未启用虚拟内存。如果你只是传递一个地址&amp;来自U-Boot的长度值,然后是指针&amp; length可以分配给导出的全局变量

void          *my_data;
unsigned int  my_dlen;
EXPORT_SYMBOL(my_data);
EXPORT_SYMBOL(my_dlen);

然后驱动程序可以检索它。

extern void          *my_data;
extern unsigned int  my_dlen;

request_mem_region(my_data, my_dlen, DRV_NAME);
md_map = ioremap(my_data, my_dlen);

我使用类似的代码在U-Boot中探测SRAM,然后传递起始地址&amp;在自定义 ATAG 中找到内核的KB数。内核驱动程序获取这些值,如果它们非零且具有合理的值,则从SRAM中创建块设备。与您的情况的主要区别在于SRAM与SDRAM的物理地址范围完全不同。

注意 ATAG 由U-Boot构建,用于内核可以使用的物理内存,因此您需要定义和排除保留的RAM。在内核中这样做可能为时已晚。