- PVSM.RU - https://www.pvsm.ru -

Linux для ARM в эмуляторе qemu

Вывести что-нибудь на экран эмулируемого устройства VersatilePB не так-то просто. Все примеры простых ядер для ARM, которые удалось найти на момент написания статьи, ограничиваются работой с последовательным портом.

Этот пост — начало серии, рассказывающей о том, как собиралось простое ядро для вывода на экран эмулируемого устройства.

На примере 2-х с небольшим тысяч строк кода будет подробно рассказано об инициализации памяти, зонах памяти, slab-аллокаторе применяемых в Linux.

Сборка ядра для архитектуры ARM (на примере linux-2.6.32.3)

Команды, приводимые далее взяты из файлов *.cmd. Эти файлы формируются автоматически системой сборки ядра, но никто не запрещает использовать команды непосредственно.

Ядро запускаемое в qemu ./arch/arm/boot/zImage получается отсечением ненужных секций от скомпилированного кода распаковки:

 arm-unknown-linux-gnueabi-objcopy -O binary -R .note -R .note.gnu.build-id -R .comment -S  arch/arm/boot/compressed/vmlinux arch/arm/boot/zImage 

Этот код собирается из библиотеки(libgcc.a), файла содержащего точку входа (head.o), файла в который включены двоичные данные упакованного ядра (piggy.o) и кода на Си выполняющего распаковку (misc.o):

/opt/arm/bin/arm-unknown-linux-gnueabi-ld -EL    --defsym zreladdr=0x00008000 --defsym initrd_phys=0x00800000 --defsym params_phys=0x00000100 -p --no-undefined -X /opt/arm/bin/../lib/gcc/arm-unknown-linux-gnueabi/4.4.1/libgcc.a -T arch/arm/boot/compressed/vmlinux.lds arch/arm/boot/compressed/head.o arch/arm/boot/compressed/piggy.o arch/arm/boot/compressed/misc.o -o arch/arm/boot/compressed/vmlinux

Упакованное ядро добавляется в piggy.S строкой:

.incbin "arch/arm/boot/compressed/piggy.gz"

piggy.o компилируется командой:

/opt/arm/bin/arm-unknown-linux-gnueabi-gcc -Wp,-MD,arch/arm/boot/compressed/.piggy.o.d  -nostdinc -isystem /opt/arm/bin/../lib/gcc/arm-unknown-linux-gnueabi/4.4.1/include -Iinclude  -I/home/tlx/linux-2.6.32.3_e/arch/arm/include -include include/linux/autoconf.h -D__KERNEL__ -mlittle-endian -Iarch/arm/mach-versatile/include -D__ASSEMBLY__ -mabi=apcs-gnu -mno-thumb-interwork  -D__LINUX_ARM_ARCH__=5 -march=armv5te -mtune=arm9tdmi -include asm/unified.h -msoft-float     -Wa,-march=all   -c -o arch/arm/boot/compressed/piggy.o arch/arm/boot/compressed/piggy.S

Файл piggy.gz получается командой:

cat arch/arm/boot/compressed/../Image | gzip -f -9 > arch/arm/boot/compressed/piggy.gz

Обратите внимание на две точки между директориями compressed и Image. Они означают переход на один уровень вверх в дереве файловой системы, т.е. Image расположен в arch/arm/boot/.
Такие сложности обусловлены автоматической генерацией команд сборки.

Image получается отсечением ненужных секций от скомпилированного ядра.:

/opt/arm/bin/arm-unknown-linux-gnueabi-objcopy -O binary -R .note -R .note.gnu.build-id -R .comment -S  vmlinux arch/arm/boot/Image

Не упакованое ядро (vmlinux) получается так:

/opt/arm/bin/arm-unknown-linux-gnueabi-ld -EL  -p --no-undefined -X --build-id -o vmlinux -T arch/arm/kernel/vmlinux.lds arch/arm/kernel/head.o arch/arm/kernel/init_task.o  init/built-in.o --start-group  usr/built-in.o  arch/arm/kernel/built-in.o  arch/arm/mm/built-in.o  arch/arm/common/built-in.o  arch/arm/mach-versatile/built-in.o  arch/arm/nwfpe/built-in.o  arch/arm/vfp/built-in.o  kernel/built-in.o  mm/built-in.o  fs/built-in.o  ipc/built-in.o  security/built-in.o  crypto/built-in.o  block/built-in.o  arch/arm/lib/lib.a  lib/lib.a  arch/arm/lib/built-in.o  lib/built-in.o  drivers/built-in.o  sound/built-in.o  firmware/built-in.o  net/built-in.o --end-group .tmp_kallsyms2.o

И наконец файл main.c, который мы будем рассматривать входит в состав init/built-in.o:

arm-unknown-linux-gnueabi-ld -EL    -r -o init/built-in.o init/main.o init/version.o init/mounts.o init/initramfs.o init/calibrate.o

После окончания работы по отделению необходимого кода от дерева исходников ядра получилась следующая последовательность команд, позволяющая собрать минимальное ядро, способное выводить информацию на дисплей эмулятора архитектуры ARM:

~user/arm-2011.09/bin/arm-none-linux-gnueabi-gcc -nostdinc -mlittle-endian -mabi=apcs-gnu -mno-thumb-interwork  -D__LINUX_ARM_ARCH__=5 -march=armv5te -mtune=arm9tdmi -msoft-float     -DTEXT_OFFSET=0x00008000  -c -o arch/arm/kernel/head.o arch/arm/kernel/head.S


~user/arm-2011.09/bin/arm-none-linux-gnueabi-gcc -nostdinc -mlittle-endian -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -Werror-implicit-function-declaration -Wno-format-security -fno-delete-null-pointer-checks -Os -marm -fno-omit-frame-pointer -mapcs -mno-sched-prolog -mabi=apcs-gnu -mno-thumb-interwork -D__LINUX_ARM_ARCH__=5 -march=armv5te -mtune=arm9tdmi -msoft-float -Uarm -Wframe-larger-than=1024 -fno-stack-protector -fno-omit-frame-pointer -fno-optimize-sibling-calls -Wdeclaration-after-statement -Wno-pointer-sign -fno-strict-overflow -fno-dwarf2-cfi-asm -fconserve-stack -c -o init/main.o init/main.c


~user/arm-2011.09/bin/arm-none-linux-gnueabi-ld -EL  -p --no-undefined -X --build-id -o vmlinux -T arch/arm/kernel/vmlinux.lds arch/arm/kernel/head.o init/main.o --start-group --end-group


~user/arm-2011.09/bin/arm-none-linux-gnueabi-objcopy -O binary -R .note -R .note.gnu.build-id -R .comment -S  vmlinux arch/arm/boot/Image

cat arch/arm/boot/compressed/../Image | gzip -f -9 > arch/arm/boot/compressed/piggy.gz

~user/arm-2011.09/bin/arm-none-linux-gnueabi-gcc -nostdinc -mlittle-endian -mabi=apcs-gnu -mno-thumb-interwork -march=armv5te -mtune=arm9tdmi -msoft-float  -march=armv5te   -c -o arch/arm/boot/compressed/piggy.o arch/arm/boot/compressed/piggy.S


~user/arm-2011.09/bin/arm-none-linux-gnueabi-gcc -nostdinc -D__KERNEL__ -mlittle-endian -D__ASSEMBLY__ -mabi=apcs-gnu -mno-thumb-interwork  -D__LINUX_ARM_ARCH__=5 -march=armv5te -mtune=arm9tdmi -msoft-float   -c -o arch/arm/boot/compressed/head.o arch/arm/boot/compressed/head.S


~user/arm-2011.09/bin/arm-none-linux-gnueabi-gcc -nostdinc -D__KERNEL__ -mlittle-endian -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -Werror-implicit-function-declaration -Wno-format-security -fno-delete-null-pointer-checks -Os -marm -fno-omit-frame-pointer -mapcs -mno-sched-prolog -mabi=apcs-gnu -mno-thumb-interwork -D__LINUX_ARM_ARCH__=5 -march=armv5te -mtune=arm9tdmi -msoft-float -Uarm -Wframe-larger-than=1024 -fno-stack-protector -fno-omit-frame-pointer -fno-optimize-sibling-calls -Wdeclaration-after-statement -Wno-pointer-sign -fno-strict-overflow -fno-dwarf2-cfi-asm -fconserve-stack -fpic -fno-builtin -Dstatic=   -c -o arch/arm/boot/compressed/misc.o arch/arm/boot/compressed/misc.c


~user/arm-2011.09/bin/arm-none-linux-gnueabi-ld -EL    --defsym zreladdr=0x00008000 --defsym initrd_phys=0x00800000 --defsym params_phys=0x00000100 -p --no-undefined -X -T arch/arm/boot/compressed/vmlinux.lds arch/arm/boot/compressed/head.o arch/arm/boot/compressed/piggy.o arch/arm/boot/compressed/misc.o -o arch/arm/boot/compressed/vmlinux


~user/arm-2011.09/bin/arm-none-linux-gnueabi-objcopy -O binary -R .note -R .note.gnu.build-id -R .comment -S  arch/arm/boot/compressed/vmlinux zImage

~user/arm-2011.09/bin/ — путь начинающийся от домашнего каталога автора до директории, содержащий тулчейн. Если вы скопируете тулчейн для ARM в свой домашний каталог и измените «user», на имя пользователя, то у Вас всё должно получиться.

Команды объединены в исполняемый файл make (не путайте с одноименной утилитой).

Код непосредственно после отделения от дерева исходников ядра, включая всё, о чем пойдет речь в следующих постах arm_qemu_max [1].

Сокращенный вариант, без инициализации памяти и slab-аллокатора (только вывод на экран) arm_qemu_min [2].

Текст остальных статей написан. Остается только опубликовать.

Автор: tlx


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/linux/8245

Ссылки в тексте:

[1] arm_qemu_max: http://kliga.ru/files/arm_qemu_max.zip

[2] arm_qemu_min: http://kliga.ru/files/arm_qemu_min.zip