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

Memory 将大量二进制数据从u-boot传递到linux内核,memory,linux-kernel,arm,embedded-linux,u-boot,Memory,Linux Kernel,Arm,Embedded Linux,U Boot,在imx50 ARM板上将大量数据(3MB)从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 201

在imx50 ARM板上将大量数据(3MB)从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) {
在驱动程序中,ioremap(0x77c00000,区域大小)用于获取内核内存地址。但当我转储内存内容时,只有零。如果使用
mem=120M
引导内核(总共有128MB的RAM可用),那么我的数据高于内核系统RAM区域,那么我就得到了预期的数据

所以,我的问题是:

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

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

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

在Linux内核中,当虚拟内存尚未启用时,在
arch/arm/kernel/setup.c
中处理ATAG。如果您只是从U-Boot传递地址和长度值,那么指针和长度可以分配给导出的全局变量

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,然后在自定义ATAG中将找到的起始地址和KB数传递给内核。内核驱动程序获取这些值,如果它们不为零且具有正常值,则从SRAM中创建一个块设备。与您的情况主要不同的是,SRAM的物理地址范围与SDRAM完全不同

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

我已经有一段时间没有使用ARM了。。。但是看看boot/compressed/head.S。简言之,Linux启动时会清除RAM。这有点复杂,因为u-boot在Linux内核启动之前准备了实际的内存大小。查找bootm.c do_bootm_linux()在那里有一个调用setup_memory_tags()。这些都是老生常谈,但其要点仍然有效。hth在启动启动序列之前,确保引导加载程序没有执行memtest。这可以解释为什么你会看到零。
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);