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

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

问题描述

将大量数据(3 MB)从uboot传递到imx50 ARM板上的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,因此该解决方案无法移植到其他体系结构.与命令行 bootarg IMO相比, ATAG 更可取,因为您不希望用户使用物理内存地址进行处理.另外,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内核中, ATAG 在尚未启用虚拟内存的情况下在arch/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 中找到到内核的KB数.内核驱动程序获取这些值,如果它们不为零且具有合理的值,则从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.

注意 U-Boot为内核可以使用的物理内存构建了一个 ATAG ,因此实际上是需要定义和排除保留的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天全站免登陆