2012-07-20 59 views
9

在从imb50 ARM板上的uboot到linux kernel 2.6.35.3传递大量数据(3 MB)时遇到一些问题。这些数据在内核设备驱动程序探测功能中是必需的,然后它应该被释放。首先从闪存加载数据到RAM,然后使用bootargs传递Linux内核的物理地址。在内核中我尝试使用在arch/ARM /内核/ setup.c中文件reserve_resource()保留的内存一定量:将大量的二进制数据从u-boot传递到linux内核

--- 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内核?

+0

自从我与ARM合作以来已经有一段时间了......但看看boot/compressed/head.S。简而言之,当Linux启动时清除RAM。这有点复杂,因为u-boot在Linux内核启动之前准备好实际的内存大小。查找bootm.c do_bootm_linux(),在那里有一个调用setup_memory_tags()。这些虽然陈旧,但依然有效[1](http://www.simtec.co.uk/products/SWLINUX/files/booting_article.html)和[2](http://amitshah.bizhat.com/臂/ arm_linux_boot-1.HTML)。 HTH – 2012-08-03 04:18:45

+0

确保引导加载程序在启动引导序列之前未进行memtest。这可以解释为什么你看到零。 – 2012-09-21 09:48:56

回答

7

你可以使用一个自定义ATAG要么通过数据块或传递数据的地址&长度。请注意,ATAG中的“A”代表ARM,因此该解决方案不适用于其他架构。一个ATAG比命令行bootarg IMO更可取,因为您不希望用户使用物理内存地址。此外,Linux内核将在启用MMU(即虚拟存储器)之前处理该列表。

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

在Linux内核中ATAGsarch/arm/kernel/setup.c中处理时,虚拟内存尚未启用。如果你只是通过从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。内核驱动程序获取这些值,如果它们非零并且具有合理的值,则从SRAM中创建块设备。与您的情况的主要区别在于,SRAM与SDRAM的物理地址范围完全不同。

注意ATAG是由U-Boot的建成为物理内存的内核可以使用,所以这是真的,你需要定义和排除您预留的RAM。在内核中这样做可能已经太迟了。

相关问题