Как мы загружаем образ Linux в соответствующее место в памяти

Мы пытаемся загрузить образ Linux в нашу DRAM в определенном месте, конечный адрес DRAM — 0x80000000, который мы узнали из журнала загрузки, в котором говорится, что «конечный адрес устройства памяти — 0x80000000». Мы загружаем наш образ по адресу «0x5000000». и до того, как этот раздел variuos в образе загружается по некоторому адресу, который больше, чем «0x80000000», например, снова из журналов загрузки

 loading section to address 0xc5000000 from file position 0x1000, size is 0x5ac13e

Что означает «из позиции файла 0x1000» в строке выше.

первый загруженный раздел - это раздел .text, ниже приведен дамп изображения vmlinux заголовка раздела

[Nr]      Name           Type            Addr     Off    Size   ES Flg Lk Inf Al

[ 0]                     NULL            00000000 000000 000000 00      0   0  0

 [ 1]   .text            PROGBITS        c5000000 001000 5ac13e 00  AX  0   0 4096

 [ 2]      .notes           NOTE            c55ac140 5ad140 000168 00  AX  0   0  4

 [ 3]    __ex_table        PROGBITS        c55ac2b0 5ad2b0 000fe0 00   A  0   0  4

 [ 4]   .rodata           PROGBITS        c55ae000 5af000 20a930 00   A  0   0 64

 [ 5]   __bug_table       PROGBITS        c57b8930 7b9930 0075fc 00   A  0   0  1

 [ 6]   .pci_fixup        PROGBITS        c57bff2c 7c0f2c 001a90 00   A  0   0  4

 [ 7]    .builtin_fw       PROGBITS        c57c19bc 7c29bc 0000cc 00   A  0   0  4

Это довольно большой список, поэтому он не публиковал полный. Но здесь мы видим одну вещь: раздел .text больше, чем конечный адрес DRAM, поэтому изображение не должно быть загружено должным образом, хотя мы не получаем никаких ошибок после загрузки первого раздела, который он сохраняет. при загрузке других разделов но после этого сообщения зависает.

    program load complete, entry point: 0x5000000, size: 0x92e7fc

Мой вопрос заключается в том, как я могу выровнять адреса этих разных разделов с нашим адресом DRAM. Здесь можно использовать утилиту objcopy для изменения адреса этих разных разделов.

Есть ли способ установить эти адреса разделов перед компиляцией?? Во-вторых, что может быть причиной завершения загрузки программы после зависания.


person Amit Singh Tomar    schedule 20.03.2013    source источник
comment
Вознаграждение — это хорошо, но оно не обязательно даст вам решение, потому что вопрос недостаточно информативен и потому что мы не можем видеть ваш код. Вы в основном просите людей стрелять в темноте.   -  person Alexey Frunze    schedule 27.03.2013
comment
Да, Алексей, вы уже очень хорошо ответили на мой вопрос, я подумал, что получить больше информации по этому вопросу - хорошая идея. Я не хочу, чтобы люди решали мою проблему, потому что тогда я не научусь сам, просто хотел иметь пару хорошие идеи   -  person Amit Singh Tomar    schedule 28.03.2013
comment
Хороший вопрос, на самом деле.   -  person Alexey Frunze    schedule 28.03.2013
comment
@AmitSinghTomar: взгляните на мой ответ, это совершенно нормально для ядра Linux, имеющего точку входа и разделы (заголовки программ) в разных местах (посмотрите на свой собственный файл Linux vmlinux). Дело в физической и виртуальной адресации.   -  person konrad.kruczynski    schedule 29.03.2013


Ответы (3)


from file position 0x1000 означает то, что он говорит. У вас есть это в дампе:

[Nr]      Name           Type            Addr     Off    Size   ES Flg Lk Inf Al
...
[ 1]   .text            PROGBITS        c5000000 001000 5ac13e 00  AX  0   0 4096

Здесь в файле начинается раздел .text со смещением 0x1000.

Но здесь мы видим одну вещь: раздел .text больше, чем конечный адрес DRAM.

Нет, он не больше (по крайней мере, не в смысле больше), он скомпилирован в расчете на то, что он будет загружен по адресу 0xc5000000 в памяти.

поэтому изображение не должно быть загружено должным образом, хотя мы не получаем никаких ошибок после загрузки первого раздела, он продолжает загружать другие разделы.

Изображение можно загрузить куда угодно, это просто данные для загрузки.

OTOH, если loading section to address 0xc5000000 означает то, что он говорит, файл загружается в никуда, так как ваша оперативная память заканчивается на 0x7fffffff.

но после этого сообщения зависает.

И это ожидаемо. Машинный код редко бывает независимым от позиции, поэтому, если вы загрузите его не в то место, где он должен быть загружен, он не будет работать. Или если он даже не загружается, то что вы собираетесь выполнять? Мусор.

Есть ли способ установить эти адреса разделов перед компиляцией??

В зависимости от системы у вас может быть один из двух следующих вариантов или оба:

  • настроить трансляцию страниц таким образом, чтобы виртуальные адреса от 0xc5000000 и выше отображались на физические адреса от 0x5000000 и выше для всей программы
  • найдите сценарий компоновщика, который использует ваш компилятор, и измените адрес начального раздела с 0xc5000000 на 0x5000000, погуглите, см. документацию по компилятору/компоновщику

Кроме того, немного странно, что точка входа находится на 0x5000000. Не то, чтобы это обязательно неправильно, просто это бывает редко. Я бы убедился, что метка start (или _start, или что-то еще) действительно получает тот же адрес, что и начало раздела .text. Если по какой-то причине это не так, то что-то не так либо со сценарием компоновщика, либо с параметрами командной строки компилятора/линковщика, либо с загрузчиком.

person Alexey Frunze    schedule 20.03.2013
comment
Спасибо @Alexey за ваш добрый ответ. Хотел бы поделиться с вами несколькими вещами, которые я пропустил в своем вопросе, точка входа 0x5000000 изменена нами путем изменения файла .config ядра, потому что не удалось загрузить изображение на адрес по умолчанию 0x1000000 Во-вторых, мы ранее загрузили и выполнили образ ядра на основе QNX в ту же DRAM, теперь мы можем использовать те же адреса для разделов и адрес точки входа, которые использовались для образа QNX здесь, для образа ядра Linux, и еще один момент, который Вы подняли точку входа, которая является частью раздела .text. - person Amit Singh Tomar; 20.03.2013
comment
Это now can we use same addresses for sections and entry point address which have been used for QNX image here in for Linux kernel image вопрос? Я не совсем понимаю вашу точку зрения. - person Alexey Frunze; 23.03.2013
comment
Привет, Алексей, как вы предложили, после изменения значения смещения страницы, адрес раздела был в пределах диапазона 2 ГБ, и после завершения загрузки программы появилось сообщение, что наше изображение не зависает, но мы столкнулись с другой проблемой, вскоре он говорит, что загрузка программы завершена, ЦП сбрасывается вместо того, чтобы передать управление образу ядра Linux, хотелось бы услышать пару слов с вашей стороны по этому вопросу. - person Amit Singh Tomar; 24.03.2013
comment
Я понятия не имею. Но я бы посоветовал вам сначала заставить работать небольшую программу, а затем вернуться ко всей ОС, возможно, делая дополнительные контрольные точки (например, печатать что-то на экране или в последовательный порт до и после каждого основного шага в код инициализации ядра). Если есть возможность, попробуйте еще и в симуляторе с отладчиком. - person Alexey Frunze; 24.03.2013

Какой загрузчик используете? Какова форма «образа»? Образ U-boot, необработанный, файл vmlinux ELF? Думаю последнее, судя по наличию разделов и т.д. Из файла ELF нужно загружать не разделы, а так называемые заголовки программ. Например, это список заголовков программ ядра Linux OpenRISC (полученный с использованием readelf -l):

Elf file type is EXEC (Executable file)
Entry point 0xc0000000
There are 2 program headers, starting at offset 52

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x002000 0xc0000000 0x00000000 0x231728 0x232000 RWE 0x2000
  LOAD           0x234000 0xc0232000 0x00232000 0x17c78c 0x18bfcc RWE 0x2000

 Section to Segment mapping:
  Segment Sections...
   00     .text .rodata __ksymtab __ksymtab_gpl __ksymtab_strings __param __modver 
   01     .data __ex_table .head.text .init.text .init.data .bss 

Посмотрите разницу между VirtAddr и PhysAddr (отброшено c из-за обычного сопоставления ядра Linux). Естественно, для загрузки должен использоваться физический адрес.

Причина, по которой ядро ​​использует виртуальные адреса для символов, разделов и т. д., заключается в том, что во время загрузки вы быстро попадаете в момент, когда инициализируется MMU, тогда единственными действительными являются виртуальные адреса.

И, наконец, о смене этих адресов. Действительно, как указал Алексей, ключевым моментом является скрипт компоновщика. Вы можете найти их в arch/(your arch)/kernel/vmlinux.lds.S. Но дело в том, что это ИМО не ваша проблема, проблема скорее всего в загрузчике или его опциях.

person konrad.kruczynski    schedule 26.03.2013

Проверьте файл arch/arm/mach-xxx/Makefile.boot (вы правильно используете армборд?)

  zreladdr-y        += 0x80008000
params_phys-y       := 0x80000100
initrd_phys-y       := 0x80800000

Это от чипа Ti omap3.

Как я думаю, вам понадобится то же самое

person liyaoshi    schedule 30.03.2013
comment
Спасибо за ответ, @liyaoshi, но мы на плате x86. - person Amit Singh Tomar; 30.03.2013
comment
Извините за этот ответ, я делаю ошибку. Я думал 0x80000000 это начальный адрес вашей платы. - person liyaoshi; 31.03.2013