|
|
  |
initfamfs - busybox - kernel, порочный круг при сборке |
|
|
|
Dec 6 2013, 17:37
|
Профессионал
    
Группа: Свой
Сообщений: 1 700
Регистрация: 2-07-12
Из: дефолт-сити
Пользователь №: 72 596

|
почитайте http://www.linuxfromscratch.org/lfs/view/stable/и потом http://cross-lfs.org/files/BOOK/2.1.0/view/все зависимости, которые требуются для *nix и ядра - там описаны. если вы видите что-то, что серьезно отличается по идеологии - то это с вероятностью 99% костыль для специфичной платформы. зы. на автоматическую сборку не надейтесь. У разработчиков популярных дистрибутивов для кросс-компиляции тонны самописных полукостыльных дистрибутивозависимых скриптов в закромах, которыми это делается.
--------------------
провоцируем неудовлетворенных провокаторов с удовольствием.
|
|
|
|
|
Dec 12 2013, 20:26
|
Профессионал
    
Группа: Свой
Сообщений: 1 351
Регистрация: 21-05-10
Пользователь №: 57 439

|
Цитата(Hoodwin @ Dec 12 2013, 18:37)  Есть у меня такая книжка. Правда издания 2006 года.
Стал было читать linux from scratch, что krux советовал. Но там совсем занудно, и не наш случай. Мы не можем собирать с нуля binutils и другие вещи для архитектуры c6x. Зато они уж есть собранные. То есть, очевидно, книжку надо читать выборочно, а конкретно про initramfs в оглавлении ничего нет. В книжке, что я дал вот что написано: Код 6.5. Using initramfs initramfs is a relatively new (Linux 2.6) mechanism for executing early user space programs. It is conceptually similar to initrd, as described in the previous section. Its purpose is also similar: to enable loading of drivers that might be required before mounting the real root file system. However, it differs in significant ways from the initrd mechanism. The technical implementation details differ significantly between initrd and initramfs. For example, initramfs is loaded before the call to do_basic_setup(), [9] which provides a mechanism for loading firmware for devices before its driver has been loaded. For more details, the Linux kernel documentation for this subsystem is relatively up-to-date. See [9] do_basic_setup is called from .../init/main.c and calls do_initcalls(). This causes driver module initialization routines to be called. This was described in detail in Chapter 5 and shown in Listing 5-10. .../Documentation/filesystems/ramfs-rootfs-initramfs.txt. From a practical perspective, initramfs is much easier to use. initramfs is a cpio archive, whereas initrd is a gzipped file system image. This simple difference contributes to the easy of use of initramfs. It is integrated into the Linux kernel source tree and is built automatically when you build the kernel image. Making changes to it is far easier than building and loading a new initrd image. Listing 6-13 shows the contents of the Linux kernel .../usr directory, where the initramfs image is built. The contents of Listing 6-13 are shown after a kernel has been built. Listing 6-13. Kernel initramfs Build Directory $ ls -l total 56 -rw-rw-r-- 1 chris chris 834 Mar 25 11:13 built-in.o -rwxrwxr-x 1 chris chris 11512 Mar 25 11:13 gen_init_cpio -rw-rw-r-- 1 chris chris 10587 Oct 27 2005 gen_init_cpio.c -rw-rw-r-- 1 chris chris 512 Mar 25 11:13 initramfs_data.cpio -rw-rw-r-- 1 chris chris 133 Mar 25 11:13 initramfs_data.cpio.gz -rw-rw-r-- 1 chris chris 786 Mar 25 11:13 initramfs_data.o -rw-rw-r-- 1 chris chris 1024 Oct 27 2005 initramfs_data.S -rw-rw-r-- 1 chris chris 113 Mar 25 11:13 initramfs_list -rw-rw-r-- 1 chris chris 1619 Oct 27 2005 Kconfig -rw-rw-r-- 1 chris chris 2048 Oct 27 2005 Makefile The file initramfs_list contains a list of files that will be included in the initramfs archive. The default for recent Linux kernels looks like this: dir /dev 0755 0 0 nod /dev/console 0600 0 0 c 5 1 dir /root 0700 0 0 This produces a small default directory structure containing the /root and /dev top-level directories, as well as a single device node representing the console. Add to this file to build your own initramfs. You can also specify a source for your initramfs files via the kernel-configuration facility. Enable INITRAMFS_SOURCE in your kernel configuration and point it to a location on your development workstation; the kernel build system will use those files as the source for your initramfs image. The final output of this build directory is the initramfs_data_cpio.gz file. This is a compressed archive containing the files you specified (either through the initramfs_list or via the INITRAMFS_SOURCE kernel-configuration option). This archive is linked into the final kernel image. This is another advantage of initramfs over initrd: There is no need to load a separate initrd image at boot time, as is the case with initrd. http://www.cs.rit.edu/~mjh/books/EmbeddedLinuxPrimer.pdf
|
|
|
|
|
Dec 12 2013, 21:22
|
Знающий
   
Группа: Участник
Сообщений: 881
Регистрация: 21-03-10
Из: _// \\_
Пользователь №: 56 107

|
TarbalНу и как этот текст помогает решить исходную проблему, описанную вначале темы? Напомню, с помощью CONFIG_INITRAMFS_SOURCE уже готовый архив cpio линкуется к ядру, и становится встроенным массивом данных, начиная с __initramfs_start и до __initramfs_end. Вот кусок из init/initramfs.c: Код static int __init populate_rootfs(void) { char *err = unpack_to_rootfs(__initramfs_start, __initramfs_end - __initramfs_start); Так вот, мне для тестовой системы нужен rootfs с busybox И еще кучей драйверов и софта, а make их собирается делать после сборки ядра, и возникает порочный круг. Порочный круг дает два эффекта: 1) При сборке системы с нуля оно не может собрать ядро. 2) При внесении изменений в состав rootfs они попадают в загрузочный образ ядра только со второго раза. И вот никто в двух словах не может объяснить, как это победить на уровне makefile, а не придумывать разные ручные хаки. Например, если бы можно было rootfs пришивать в конец ядра, а не влинковывать, то можно было бы делать ядро отдельно, а ядро с образом rootfs - отдельно, и проблема бы ушла, но такого, похоже, нет. Нынешние Makrefile-ы писаны людьми, которые вообще портировали линукс на платформу c6x. Я их кое где поправил, чтобы собиралось мое ядро, а не только для TI-ных EVM, но в целом они работоспособные. И я не склонен считать их "криворукими китайцами", которые не знают как должен выглядеть правильный порядок сборки ядра.
|
|
|
|
|
Dec 12 2013, 22:26
|
Знающий
   
Группа: Участник
Сообщений: 783
Регистрация: 22-11-08
Пользователь №: 41 858

|
Цитата(Hoodwin @ Dec 13 2013, 01:22)  И вот никто в двух словах не может объяснить, как это победить на уровне makefile, а не придумывать разные ручные хаки. То что вы описывали Цитата А было бы удобнее так: 1) Собрать ядро 2) Собрать BB 3) собрать прочие файлы для наполнения initramfs 4) сделать образ rootfs 5) Прилинковать образ initramfs к ядру. в нормальных системах сборки именно так и работает - что тут еще объяснять ? http://git.buildroot.net/buildroot/tree/linux/linux.mk#n172http://git.buildroot.net/buildroot/tree/fs...nitramfs.mk#n10http://git.buildroot.net/buildroot/tree/linux/linux.mk#n312"rebuild" в данном случае означает простую линковку с образом настоящей корневой вместо фейковой - полной пересборки ядра не происходит на последнем этапе. Цитата Например, если бы можно было rootfs пришивать в конец ядра, а не влинковывать и это тоже далется по щелчку пальца - вы же не читаете что вам пишут Dron_Gus: Цитата Если что-то не очень кастрированнное, то ему можно отдельно подпихнуть два образа - ядра и initramfs. А еще можно склеить их вместе с помошью mkimage. стоит погуглить mkimage multi image - куча ссылок как их создавать http://www.isysop.com/unpacking-and-repack...t-uimage-files/осталось посмотреть на параметр ядра http://lxr.free-electrons.com/source/Docum...eters.txt#L1206и что произойдет если вместо рамдиска ядро обнаружит там initramfs http://lxr.free-electrons.com/source/Docum...tramfs.txt#L217Цитата И я не склонен считать их "криворукими китайцами", которые не знают как должен выглядеть правильный порядок сборки ядра. Чтобы правильно сделать - это же думать надо, а они делают "лишь бы что-то работало". Видел я техасовские SDK для их давинчей, ерунда полная - набор кривых make-файлов, такое ощущение что их писали школьники - настолько примитивно сделано.
Сообщение отредактировал sasamy - Dec 12 2013, 23:29
|
|
|
|
|
Dec 13 2013, 06:02
|
Знающий
   
Группа: Участник
Сообщений: 881
Регистрация: 21-03-10
Из: _// \\_
Пользователь №: 56 107

|
sasamy1) У меня проблема в том, что образ ядра грузится по TFTP, а параметр initrd, который Вы упоминаете, описан как filename, который содержит образ рамдиска. То, что с 2.6 можно туда тоже подпихнуть initramfs, я прочитал, но непонятно, как ядро найдет по этому имени что-то, если образ загружен по tftp. Обычный initrd в дескотоповой системе ссылается на /boot/inird-..., и ядро, видимо как-то монтирует сам boot раздел. В моем случае такого раздела нет, и поэтому это вариант я пока не смотрел. 2) Образ uImage с двумя файлами внутри уже интереснее. Из примера следует, что образ рамдиска встроен в uImage в виде второго файла. Однако пока непонятен механизм, как ядро узнает о наличии этого образа? Насколько я понимаю, ядро само по себе не обучено взаимодействовать с u-boot. Наоборот, U-boot скармливает ядру необходимые опции. А тут речь идет о том, как научить ядро находить по имени, подставленному в initrd=, собственно файл с образом initramfs. 3) Вот этот вот комментарий (http://git.buildroot.net/buildroot/tree/linux/linux.mk#n172) Цитата # As the kernel gets compiled before root filesystems are # built, we create a fake cpio file. It'll be # replaced later by the real cpio archive, and the kernel will be # rebuilt using the linux26-rebuild-with-initramfs target. доказывает, что проблема существует, и что ядро действительно надо собирать дважды через его собственные Makefile-ы, чтобы получить результат. То есть эта "ерунда" из ядра произрастает, а все кто вокруг как-то под это подстраиваются. c6x еще на предыдущей ступени развития в этой части. 4) Любой большой проект включает в себя этапы, в соответствии с которыми что-то делается фундаментально и сразу, а что-то упрощенно, как временная мера, просто потому, что сразу на все ресурсов не хватает. Наша задача - разобраться в том, что есть, и развить то, что нам необходимо. Все в детстве писают в штаны, но потом все налаживается.
|
|
|
|
|
Dec 13 2013, 07:01
|
Знающий
   
Группа: Участник
Сообщений: 783
Регистрация: 22-11-08
Пользователь №: 41 858

|
Цитата(Hoodwin @ Dec 13 2013, 10:02)  1) У меня проблема в том, что образ ядра грузится по TFTP, а параметр initrd, который Вы упоминаете, описан как filename У вас проблема со чтением Цитата initrd= [BOOT] Specify the location of the initial ramdisk где вы тут filename увидели ? к тому же с u-boot этот параметр будет не нужен (зря я про него упомянул), он автоматически передаст адрес рамдиска ядру через загрузочный тег при загрузке имиджа командой bootm http://www.simtec.co.uk/products/SWLINUX/f...cle.html#d0e383по какому адресу расположить этот образ в памяти можно задать в параметрах mkimage при создании образа рамдиска, но скорей всего даже этого не надо будет - u-boot сам вычислит расположение рамдиска так как информация где расположены файлы в multi-file имидже у него есть. там как раз описан еще метод про который я предполагал что он есть: Цитата make ARCH=arm help ... Architecture specific targets (arm): * zImage - Compressed kernel image (arch/arm/boot/zImage) Image - Uncompressed kernel image (arch/arm/boot/Image) * xipImage - XIP kernel image, if configured (arch/arm/boot/xipImage) uImage - U-Boot wrapped zImage bootpImage - Combined zImage and initial RAM disk (supply initrd image via make variable INITRD=<path>) ... Цитата ядро действительно надо собирать дважды дважды запускать сборку нужно если нужны динамические модули ядра - чтобы они оказались в корневой ФС нужно их сначала собрать, а потом слинковать ядро с этой ФС - какой "фатальный недостаток" вы в этом увидели ?
Сообщение отредактировал sasamy - Dec 13 2013, 07:59
|
|
|
|
|
Dec 13 2013, 09:45
|
Знающий
   
Группа: Участник
Сообщений: 881
Регистрация: 21-03-10
Из: _// \\_
Пользователь №: 56 107

|
sasamyЦитата У вас проблема со чтением Цитата initrd= [BOOT] Specify the location of the initial ramdisk
где вы тут filename увидели ? У Вас проблема с культурой общения. Что-то мешает вести себя менее заносчиво? Конкретно про filename прочитал тут: https://wiki.debian.org/InitrdЦитата initrd kernel parameter
The initrd=filename kernel parameter Specify the location of the initial ramdisk (which can be either a plain 2.4's initrd or a 2.6's initramfs). проблема не в том, как трактовать описание initrd, а в том, как по этому параметру ядро найдет образ initramfs, если оно само загружено по tftp. Я не уверен, что нынешняя сборка linux для c6x и текущая сборка u-boot поддерживает передачу образа initrd через указатель. Не видел этого в исходниках.
Сообщение отредактировал Hoodwin - Dec 13 2013, 10:05
|
|
|
|
|
Dec 13 2013, 10:23
|
Знающий
   
Группа: Участник
Сообщений: 783
Регистрация: 22-11-08
Пользователь №: 41 858

|
Цитата Конкретно про filename прочитал тут: с наскоку не могу найти в доках но через этот параметр можно передать физической адрес в памяти и размер рамдиска initrd=phys_addr_offset,size по крайней мере на архитектуре arm Цитата Я не уверен, что нынешняя сборка linux для c6x и текущая сборка u-boot поддерживает передачу образа initrd через указатель. Не видел этого в исходниках. задайте этот вопрос лучше сотрудникам TI
Сообщение отредактировал sasamy - Dec 13 2013, 10:42
|
|
|
|
|
Dec 16 2013, 07:01
|

Профессионал
    
Группа: Свой
Сообщений: 1 202
Регистрация: 9-01-05
Из: Санкт-Петербург
Пользователь №: 1 861

|
Цитата(Hoodwin @ Dec 13 2013, 13:45)  Я не уверен, что нынешняя сборка linux для c6x и текущая сборка u-boot поддерживает передачу образа initrd через указатель. Не видел этого в исходниках. В чем проблема проверить? Еще раз приведу формат команды bootm: Код bootm <Linux uImage address> <mkimage wrapped ramdisk address> <device tree (dtb) address>
--------------------
Если сверху смотреть, то сбоку кажется, что снизу ничего не видно.
|
|
|
|
|
Dec 16 2013, 12:08
|
Знающий
   
Группа: Участник
Сообщений: 881
Регистрация: 21-03-10
Из: _// \\_
Пользователь №: 56 107

|
Да проверю, конечно. Просто сейчас текучки много, не хватает времени глубоко копать. Дело в том, что bootm передает управление в кастомную функцию (arch/c6x/lib/bootm.c): Код int do_bootm_linux(int flag, int argc, char * const argv[], bootm_headers_t *images) { void (*kernel)() = (void *)images->ep; char *commandline = getenv("bootargs"); if (commandline) { char *dst = (char *)images->ep + 0x1000; strncpy(dst, commandline, 1023); dst[1023] = 0; } { unsigned int *ptr = (unsigned int *)0xc1f00000; ptr[0] = 0x64000001; /*TAG_SOL*/ ptr[1] = 0; /*size SOL*/ ptr[2] = 0x64000002; /*TAG_EOL*/ ptr[3] = 0; } asm("MVKL .S1 0x54694265,A4"); asm("MVKH .S1 0x54694265,A4"); asm("MVKL .S2 0xc1f00000,B4"); // это бред asm("MVKH .S2 0xc1f00000,B4"); // это тоже бред kernel(); printf("after kernel\n"); return 1; } То есть, как видно, ничего оно никуда не передает, только комстроку копирует. А вот как сказать ядру, что есть еще какие-то данные я пока не знаю. Это через тэги над сделать, или указателем в регистре?
|
|
|
|
|
Dec 18 2013, 06:53
|

Профессионал
    
Группа: Свой
Сообщений: 1 202
Регистрация: 9-01-05
Из: Санкт-Петербург
Пользователь №: 1 861

|
Цитата(Hoodwin @ Dec 16 2013, 16:08)  Да проверю, конечно. Просто сейчас текучки много, не хватает времени глубоко копать. Дело в том, что bootm передает управление в кастомную функцию (arch/c6x/lib/bootm.c): Код int do_bootm_linux(int flag, int argc, char * const argv[], bootm_headers_t *images) { void (*kernel)() = (void *)images->ep; char *commandline = getenv("bootargs"); if (commandline) { char *dst = (char *)images->ep + 0x1000; strncpy(dst, commandline, 1023); dst[1023] = 0; } { unsigned int *ptr = (unsigned int *)0xc1f00000; ptr[0] = 0x64000001; /*TAG_SOL*/ ptr[1] = 0; /*size SOL*/ ptr[2] = 0x64000002; /*TAG_EOL*/ ptr[3] = 0; } asm("MVKL .S1 0x54694265,A4"); asm("MVKH .S1 0x54694265,A4"); asm("MVKL .S2 0xc1f00000,B4"); // это бред asm("MVKH .S2 0xc1f00000,B4"); // это тоже бред kernel(); printf("after kernel\n"); return 1; } То есть, как видно, ничего оно никуда не передает, только комстроку копирует. А вот как сказать ядру, что есть еще какие-то данные я пока не знаю. Это через тэги над сделать, или указателем в регистре? Почитайте про ATAG'и. Там, где у вам написано "бред" как раз и идет передача указателя на атаги. А чуть выше они заполняются. Где-то там вам надо добавить еще один ATAG, указывающий на initrd. И посмотрите как это сделано на других архитектурах. ARM хороший пример.
--------------------
Если сверху смотреть, то сбоку кажется, что снизу ничего не видно.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|