将大量二进制数据从 u-boot 传递到 linux 内核 [英] Pass large amount of binary data from u-boot to linux kernel

查看:21
本文介绍了将大量二进制数据从 u-boot 传递到 linux 内核的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Have some issues with passing large amount of data (3 MB) from uboot to linux kernel 2.6.35.3 on imx50 ARM board. This data is required in kernel device driver probe function and then it should be released. First uboot load data from flash to RAM, then pass physical address for linux kernel using bootargs. In kernel I try to reserve certain amount of memory using reserve_resource() in arch/arm/kernel/setup.c file:

--- 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) {

通过这个,我试图告诉内核它保留了这个内存区域,这个数据不应该被内核修改.

By this I'm trying to tell kernel that this memory area it reserved and this data should not be modified by kernel.

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 区域,然后我得到我期望的数据.

In driver ioremap(0x77c00000, AREA_SIZE) is used to get kernel memory address. But when I dump content of memory, there is only zeros. If boot kernel with mem=120M (total 128MB RAM is avaliable), then my data is above kernel system ram region, then I get data I expect.

那么,我的问题:

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

Why I get zeros and how do I pass large amount of binary data from uboot to linux kernel?

推荐答案

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

You could use a custom ATAG to either pass the data block or to pass the address & length of the data. Note that the "A" in ATAG stands for ARM, so this solution is not portable to other architectures. An ATAG is preferable to a command-line bootarg IMO because you do not want the user to muck with physical memory addresses. Also the Linux kernel will process the ATAG list before the MMU (i.e. virtual memory) is enabled.

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

In U-Boot, look at lib_arm/armlinux.c or arch/arm/lib/bootm.c for routines that build the ARM tag list. Write your own routine for your new tag(s), and then invoke it in do_bootm_linux().

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

In the Linux kernel ATAGs are processed in arch/arm/kernel/setup.c, when virtual memory has not yet been enabled. If you just pass an address & length values from U-Boot, then the pointer & length can be assigned to global variables that are exported,

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

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

and then the driver can retrieve it.

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 中内核找到的千字节数.内核驱动程序获取这些值,如果它们非零且具有合理的值,则从 SRAM 中创建块设备.与您的情况的主要区别在于 SRAM 与 SDRAM 处于完全不同的物理地址范围.

I've used similar code to probe for SRAM in U-Boot, then pass the starting address & number of KBytes found to the kernel in a custom ATAG. A kernel driver obtains these values, and if they are nonzero and have sane values, creates a block device out of the SRAM. The major difference from your situation is that the SRAM is in a completely different physical address range from the SDRAM.

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

NOTE An ATAG is built by U-Boot for the physical memory that the kernel can use, so this is really where you need to define and exclude your reserved RAM. It's probably too late to do that in the kernel.

这篇关于将大量二进制数据从 u-boot 传递到 linux 内核的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆