25 May 2012

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

Configuring Linux
Sandbox
Вывести что-нибудь на экран эмулируемого устройства 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.

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

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

Tags:linuxarmqemu
Hubs: Configuring Linux
+19
22k 68
Comments 5
Popular right now
Администратор Linux
January 18, 202180,000 ₽OTUS
Безопасность Linux
February 12, 202130,000 ₽OTUS
Профессия iOS-разработчик
November 30, 202075,000 ₽SkillFactory
Основы HTML и CSS
November 30, 2020FreeНетология
Frontend-разработчик с нуля
November 30, 202077,940 ₽Нетология