Как найти точку входа в ARM Linux, если он не распаковывается?

Я пытаюсь загрузить Linux через U-boot на пользовательской плате с i.MX6 (ядро процессора - ARM Cortex A9)

Кажется, мы успешно перенесли Das U-Boot (2009.08). Но загрузка Linux завершается ошибкой при последнем сообщении U-Boot: «Запуск ядра ...»

Вот моя соответствующая среда:

bootargs=console=ttymxc1,115200 vmalloc=400M root=/dev/mmcblk0p1 rootwait consoleblank=0 earlyprintk video=mxcfb0:dev=lcd,LCD-ORTUS,if=RGB24 video=mxcfb1:dev=hdmi,1280x720M@60,if=RGB24 calibration tsdev=tsc2004 fbmem=10M,28M
bootcmd=ext2load mmc 0:1 10800000 /boot/uImage ; bootm 10800000

Вывод загрузки:

Loading file "/boot/uImage" from mmc device 0:1 (xxa1)  
4043552 bytes read  
## Booting kernel from Legacy Image at 10800000 ...  
   Image Name:   Linux-3.0.35  
   Image Type:   ARM Linux Kernel Image (uncompressed)  
   Data Size:    4043488 Bytes =  3.9 MB  
   Load Address: 10008000  
   Entry Point:  10008000  
   Verifying Checksum ... OK  
   Loading Kernel Image ... OK  
OK  

Starting kernel ...  

Когда я objdump ядра по адресу 80008000, я вижу точку входа в arch / arm / kernel / head.S, а не в arch / arm / boot / compressed / head.S

Я вижу, что ядро ​​даже не распаковывается. Я попытался добавить код манипуляции регистром, чтобы сигнализировать GPIO в сжатом / head.S без ответа.

У меня вопрос: как я могу убедиться, что U-Boot вызывает правильную точку входа?

Тот же самый двоичный файл ядра успешно загружается на эталонной плате Freescale с использованием тех же команд U-Boot.

РЕДАКТИРОВАТЬ: Я добавил несколько следов в U-Boot. Непосредственно перед вызовом ядра указатель ядра - это 10008000, а не 10800000. Означает ли это, что U-boot прыгает в неправильном месте?


person Atilla Filiz    schedule 22.08.2013    source источник
comment
У вас есть JTAG? Если да, просто отлаживайте его.   -  person Igor Skochinsky    schedule 22.08.2013
comment
Я думаю, что ядро ​​запустится только после распаковки, после запуска печати ядра ядро ​​перейдет к функции входа ядра, которую u-boot получает из заголовка образа ядра. Вы скопировали сжатое ядро ​​с загрузочного носителя на 10800000, команда bootm распакует и поместит ядро ​​на правильный адрес загрузки, который составляет 10008000, граница 32 КБ от начального адреса ОЗУ. Если он не загружается, то, скорее всего, причина в идентификаторе машины. Я хотел бы знать, в чем была правильная причина?   -  person GeekyJ    schedule 26.10.2015


Ответы (3)


Кажется, мы успешно перенесли Das U-Boot.

Есть свидетельства того, что это ошибочное предположение.

Непосредственно перед вызовом ядра указатель theKernel равен 10008000, а не 10800000.

Какую версию U-Boot вы используете?
В версиях U-Boot 2012.10 и 2013.04 переменная theKernel объявляется и используется только кодом для арок, таких как AVR32 и MIPS.
Нет кода ARM, который следует использовать theKernel.

u-boot-2012.10$ find . -print | xargs grep theKernel
./arch/avr32/lib/bootm.c:   void    (*theKernel)(int magic, void *tagtable);
./arch/avr32/lib/bootm.c:   theKernel = (void *)images->ep;
./arch/avr32/lib/bootm.c:          theKernel, params_start);
./arch/avr32/lib/bootm.c:   theKernel(ATAG_MAGIC, params_start);
./arch/microblaze/lib/bootm.c:  void    (*theKernel) (char *, ulong, ulong);
./arch/microblaze/lib/bootm.c:  theKernel = (void (*)(char *, ulong,    ulong))images->ep;
./arch/microblaze/lib/bootm.c:      (ulong) theKernel, rd_data_start, (ulong) of_flat_tree);
./arch/microblaze/lib/bootm.c:  theKernel (commandline, rd_data_start, (ulong) of_flat_tree);
./arch/mips/lib/bootm.c:    void (*theKernel) (int, char **, char **, int *);
./arch/mips/lib/bootm.c:    theKernel = (void (*)(int, char **, char **, int *))images->ep;
./arch/mips/lib/bootm.c:        (ulong) theKernel);
./arch/mips/lib/bootm.c:    theKernel(linux_argc, linux_argv, linux_env, 0);
./arch/mips/lib/bootm_qemu_mips.c:  void (*theKernel) (int, char **, char **, int *);
./arch/mips/lib/bootm_qemu_mips.c:  theKernel = (void (*)(int, char **, char **, int *))images->ep;
./arch/mips/lib/bootm_qemu_mips.c:      (ulong) theKernel);
./arch/mips/lib/bootm_qemu_mips.c:  theKernel(0, NULL, NULL, 0);
./arch/nds32/lib/bootm.c:   void    (*theKernel)(int zero, int arch, uint params);
./arch/nds32/lib/bootm.c:   theKernel = (void (*)(int, int, uint))images->ep;
./arch/nds32/lib/bootm.c:          (ulong)theKernel);
./arch/nds32/lib/bootm.c:   theKernel(0, machid, bd->bi_boot_params);
u-boot-2012.10$


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

Следующий вывод после того, как U-Boot напечатает «Запуск ядра ...», должен быть «Распаковка Linux ...».
Для архитектуры Freescale этот текстовый вывод зависит от правильной передачи machine type number (также известного как arch_id) пользователем. -Загрузить ядро.
Вам необходимо убедиться, что этот machine type number правильно определен в U-Boot.

Как выглядит ваш файл конфигурации для U-Boot?

Я попытался добавить код манипуляции регистром, чтобы сигнализировать GPIO в сжатом / head.S без ответа.

Проверяли ли вы этот код, чтобы убедиться, что он работает так, как вы ожидаете?
Вы пробовали операции GPIO из командной строки U-Boot?

У меня вопрос: как я могу убедиться, что U-Boot вызывает правильную точку входа?

Для архитектуры ARM это переход к адресу, указанному в команде bootm.
Поскольку адрес загрузки uImage и bootm указывают один и тот же адрес 0x10800000, это должно быть хорошо (при условии, что U-Boot правильно настроен и построен для ARM).

Непосредственно перед вызовом ядра указатель ядра - это 10008000, а не 10800000. Означает ли это, что U-boot прыгает в неправильном месте?

ДА.
Если вы проверите исходный код (для AVR32 или MIPS), вы обнаружите, что theKernel назначается из заголовка изображения, в частности, значение точки входа. Затем U-Boot перейдет в это место.
Но настоящая проблема в том, что ваш ARM Cortex A9 не должен использовать этот код или эту переменную.

Кажется, что U-Boot не является сконфигурирован для правильной арки и / или тип машины может быть неправильно определен.

ИСПРАВЛЕНИЯ:

Как указал OP, более старые версии U-Boot действительно использовали переменную theKernel даже для архитектуры ARM.

Строка вывода U-Boot:

   Loading Kernel Image ... OK  

указывает, что U-Boot (успешно) скопировал образ ядра (без заголовка информации об образе) с адреса bootm 0x10800000 (плюс смещение 0x40 для длины заголовка) на адрес загрузки 0x10008000. Эта операция перемещения памяти выполняется процедурой bootm_load_os() в common / cmd_bootm.c.

Таким образом, указанное вами значение 0x10008000 является правильным для theKernel.
Нет никаких указаний на то, что U-Boot переходит в неправильное место.

Как уже упоминалось, вы должны убедиться, что тип машины определен правильно. Значение будет использоваться в __arch_decomp_setup() в arch / arm / plat-mxc / include / mach / uncompress.h, чтобы текст мог выводиться во время распаковки перед загрузкой ядра.

person sawdust    schedule 22.08.2013
comment
Спасибо за подробное объяснение. Я также отредактирую свой вопрос, потому что мы используем U-Boot 2009.08, официально поддерживаемую Freescale версией. Здесь ядро ​​ используется в поддереве lib_arm. Кроме того, мы используем арку Cortex A8 для загрузки A9, которая кажется идеальной для других плат на базе mx6. - person Atilla Filiz; 23.08.2013
comment
Ваша поправка решила проблему! Я не знал, что мне нужно добавить свои собственные определения плат в mach / uncompress.h - person Atilla Filiz; 29.08.2013
comment
@Atilla Filiz Было бы неплохо, если бы вы добавили arch_id и тип машины, которые вы использовали для работы. - person CaptainBli; 05.09.2013
comment
@CaptainBli - Фактическое значение типа машины, переданное из U-Boot в ядро, не так важно, как обеспечение его распознавания. ОП явно создал новый тип машины для своей пользовательской платы, но пропустил один исходный файл, который требовал редактирования. ПОДСКАЗКА: grep все ваше дерево исходных текстов (ядро и загрузчики) для типа компьютера исходной платы, чтобы найти код, который нуждается в обновлении. - person sawdust; 05.09.2013
comment
@sawdust, не могли бы вы также взглянуть на это - person user0193; 05.01.2021

Кажется, вы не загружаете файл ядра vmlinux, поэтому вам не нужно беспокоиться о точках входа. Код декомпрессии в начале изображения переместит ядро ​​по мере необходимости и перейдет к правильной точке входа, когда это будет сделано. Вам просто нужно перейти к началу изображения, которое uBoot, похоже, делает правильно.

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

Изменить: как уже указывалось, мой ответ применяется только в том случае, если uBoot делает это правильно в первую очередь. В этом случае есть вероятность, что это не так. Возможно, вы могли бы создать и попытаться загрузить фиктивное «ядро», которое просто включает некоторые светодиоды или выводит некоторые значения регистров на последовательный порт (в частности, r0, r1 и r2). Тогда вы можете хотя бы проверить и / или исключить uBoot как виновника.

person tangrs    schedule 22.08.2013
comment
Кажется, что uBoot работает правильно. - Нет никаких доказательств, подтверждающих этот вывод. Я бы включил отладку ядра - в OP четко указано, что нет никаких указаний на то, что ядро ​​не сжато. Поскольку ядро ​​не начало загружаться, вы не можете ожидать чего-либо от функций отладки ядра. Вы предлагаете только общие советы, которые не помогают в данной конкретной ситуации. - person sawdust; 23.08.2013

Может быть, файл, который загружает U-Boot, на самом деле является двоичным образом vmlinux файла, а не самораспаковывающимся _2 _ / _ 3_? Это всего лишь предположение, я не эксперт в этом.

Этот вопрос, который я недавно задал на Unix Stack Exchange, может вас заинтересовать: https://unix.stackexchange.com/questions/197225/is-vmlinuz-and-bzimage-really-the-same

person Multisync    schedule 20.04.2015