9

imx50 ARMボード上のubootからLinuxカーネル2.6.35.3に大量のデータ(3 MB)を渡す際にいくつかの問題があります。このデータはカーネルデバイスドライバのプローブ機能に必要であり、その後解放する必要があります。最初に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

Inドライバーioremap(0x77c00000, AREA_SIZE)はカーネルメモリアドレスを取得するために使用されます。しかし、メモリの内容をダンプすると、ゼロしかありません。mem=120M(合計128MBのRAMが利用可能)でカーネルを起動する場合、私のデータはカーネルシステムのRAM領域より上にあり、期待するデータを取得します。

だから、私の質問:

ゼロを取得する理由と、ubootからLinuxカーネルに大量のバイナリデータを渡すにはどうすればよいですか?

4

1 に答える 1

8

カスタムATAGを使用して、データブロックを渡すか、データのアドレスと長さを渡すことができます。ATAGの「A」はARMを表すため、このソリューションは他のアーキテクチャに移植できないことに注意してください。ATAGは、ユーザーが物理メモリアドレスをいじくり回したくないため、コマンドラインのbootargIMOよりも適しています。また、Linuxカーネルは、MMU(つまり仮想メモリ)が有効になる前にATAGリストを処理します。

U-Bootで、ARMタグリストを作成するルーチンを確認しlib_arm/armlinux.cます。arch/arm/lib/bootm.c新しいタグ用の独自のルーチンを作成し、それをdo_bootm_linux()で呼び出します。

Linuxカーネルでは、仮想メモリがまだ有効になっていない場合、ATAGはで処理されます。arch/arm/kernel/setup.cU-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を定義および除外する必要があるのはここです。カーネルでそれを行うにはおそらく遅すぎます。

于 2012-08-27T07:01:08.653 に答える