Передача большого количества двоичных данных из u-boot в ядро ​​Linux

Возникли проблемы с передачей большого объема данных (3 МБ) из uboot в ядро ​​linux 2.6.35.3 на плате imx50 ARM. Эти данные требуются в функции проверки драйвера устройства ядра, а затем должны быть освобождены. Сначала загрузите данные из флэш-памяти в ОЗУ, а затем передайте физический адрес для ядра Linux с помощью загрузочных утилит. В ядре я пытаюсь зарезервировать определенный объем памяти с помощью reserve_resource() в файле arch/arm/kernel/setup.c:

--- 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 (всего доступно 128 МБ ОЗУ), затем мои данные находятся выше области оперативной памяти ядра, затем я получаю ожидаемые данные.

Итак, мои вопросы:

Почему я получаю нули и как передать большой объем двоичных данных из Uboot в ядро ​​Linux?

1 ответ

Решение

Вы можете использовать пользовательский ATAG для передачи блока данных или для адреса и длины данных. Обратите внимание, что "A" в ATAG обозначает ARM, поэтому это решение не переносимо на другие архитектуры. ATAG предпочтительнее командной строки IMO, так как вы не хотите, чтобы пользователь хранил адреса физической памяти. Также ядро ​​Linux будет обрабатывать список ATAG до того, как MMU (то есть виртуальная память) будет включен.

В U-Boot посмотрите на lib_arm/armlinux.c или же arch/arm/lib/bootm.c для подпрограмм, которые создают список тегов ARM. Напишите свою собственную подпрограмму для вашего нового тега (ов), а затем вызовите ее в do_bootm_linux ().

В ядре Linux ATAG обрабатываются в arch/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);

Я использовал подобный код для поиска SRAM в U-Boot, а затем передал начальный адрес и количество найденных килобайт ядру в пользовательском ATAG. Драйвер ядра получает эти значения и, если они ненулевые и имеют нормальные значения, создает блочное устройство из SRAM. Основное отличие от вашей ситуации заключается в том, что SRAM находится в совершенно другом диапазоне физических адресов, чем SDRAM.

ПРИМЕЧАНИЕ. U-Boot создает ATAG для физической памяти, которую может использовать ядро, так что именно здесь вам нужно определить и исключить зарезервированную оперативную память. Вероятно, уже слишком поздно делать это в ядре.

Другие вопросы по тегам