Вывести что-нибудь на экран эмулируемого устройства 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.
Текст остальных статей написан. Остается только опубликовать.
Автор: tlx