Uboot - универсальный загрузчик ядра linux.
Исходный код загрузчика доступен на ftp-сервере
На момент написания последняя стабильная версия - 2010.06.
Проще всего отслеживать серьезные изменения в очередном релизе U-Boot по CHANGELOG, который лежит в корневом каталоге исходников. Очень часто различная функциональность просто переносится в разные места дерева исходного кода, все это обязательно будет отражено в CHANGELOG. Такое отслеживание изменений может потребоваться для примения данного руководства к новым версиям U-Boot (или старым).
В U-Boot применяется немного необычная (особенно для имеющих опыт сборки ядра Linux, Busybox или Buildroot)
система конфигурирования - через заголовочные файлы С, в которых объявляется множество define-ов, связанных с различными аспектами будущего загрузчика. Это плохо тем , что зависимости между опциями не отслеживаются и что-нибудь включить-отключить порой непросто.
Конфиги находятся в include/configs, нам нужен будет конфиг at91sam9260ek.h для настройки.
Но сначала внесем изменения в другие файлы
Необходимо поправить файл board/atmel/at91sam9260ek/config.mk. Здесь задается параметр TEXT_BASE. Здесь описано его предназначение (на английском), фактически это стартовый адрес загрузчика в ОП (Linux требуется грузить с 0 адреса), параметр повлияет на IP загрузчика. Нужно просто согласовать его с тем что задано в заголовочных файлах Bootstrap в переменной JUMP_ADDRESS.
В старых версиях она располагалась в общем для группы плат файле cpu/arm926ejs/at91sam9/ether.c. Теперь - вынесена в настройки каждой конкретной платы. Нам нужно изменить файл board/atmel/at91sam9260ek/at91sam9260ek.c
До:
... #ifdef CONFIG_MACB rc = macb_eth_initialize(0, (void *)AT91SAM9260_BASE_EMAC, 0x00); #endif ...
После:
... #ifdef CONFIG_MACB rc = macb_eth_initialize(0, (void *)AT91SAM9260_BASE_EMAC, 0x01); #endif ...
Правим include/configs/at91sam9260ek.h.
Необходимо выставить рабочую частоту кварца равной 12 МГц (а не 18.432 МГц, как стоит по умолчанию)
...
#define CONFIG_SYS_AT91_MAIN_CLOCK 12000000 /* 12.000 MHz crystal */
...
Согласовать частоту SPI с Bootstrap. Задается опцией AT91_SPI_CLK. Выставлено для оригинального Bootstrap.
...
#define AT91_SPI_CLK 33000000
...
U-Boot можно расположить в NAND-flash, а также в Dataflash по CS0 и CS1. Каждый из этих случаев конфигурируется отдельно в секциях /* bootstrap + u-boot + env + linux in nandflash */, /* bootstrap + u-boot + env + linux in dataflash on CS0 */ и /* bootstrap + u-boot + env + linux in dataflash on CS1 */ соответственно.
Отметим следующие опции здесь: CONFIG_ENV_OFFSET - смещение области отводимой под окружение загрузчика, в котором он хранит скрипты и переменные, CONFIG_ENV_SIZE - размер этого окружения в байтах, CONFIG_BOOTCOMMAND - команда загрузки по умолчанию (будет храниться в переменной bootcmd), CONFIG_BOOTARGS - командная строка, передаваемая ядру Linux (будет храниться в переменной bootargs).
В них, например, можно хранить различные мини-скрипты, вроде tftp_update. Задается в секции CONFIG_EXTRA_ENV_SETTINGS. В следующей форме:
... #define CONFIG_EXTRA_ENV_SETTINGS \ "<имя_переменной1>=<хранимый_текст1>\0" \ "<имя_переменной2>=<хранимый_текст2>\0" \ ...
Например:
... #define CONFIG_EXTRA_ENV_SETTINGS \ "tftp_update=tftpboot 20400000 zlinux; cp.b 20400000 c0038000 170000; tftpboot 20400000 rootfs; \ cp.b 20400000 c01a8000 277fff\0" \ "tftp_boot=tftpboot 20400000 zlinux; tftpboot 21100000 rootfs; bootm 20400000\0" \ "boot_df=cp.b c0038000 20400000 170000; cp.b c01a8000 21100000 277fff; bootm 20400000\0" \ "ipaddr=192.168.0.136\0" \ "netmask=255.255.255.0\0" \ "ethaddr=00:1f:f2:00:00:00\0" \ "serverip=192.168.0.2\0" ...
Сборка производится EABI-кросс-компилятором. Например от CodeSourcery. Команды запускаются в корневой директории исходников. Команда
CROSS_COMPILE=<префикс_eabi_кросс-компилятора> make ARCH=arm <имя_конфига>
применяет нужный конфиг, который мы поправили, доступны (см. Makefile U-Boot)
... at91sam9260ek_nandflash_config \ at91sam9260ek_dataflash_cs0_config \ at91sam9260ek_dataflash_cs1_config \ at91sam9260ek_config \ ...
С помощью названия указывается расположение загрузчика. Команда
CROSS_COMPILE=<префикс_eabi_кросс-компилятора> make ARCH=arm
собирает U-Boot с текущим конфигом. Если не было ошибок, будет создан файл u-boot.bin, для заливки на плату.
Для очистки можно использовать
CROSS_COMPILE=<префикс_eabi_кросс-компилятора> make ARCH=arm distclean
Это очистит дерево исходников от всех предыдущих результатов сборки
Для доступа к сети должны быть настроены следующие переменные окружения U-Boot (с помощью указания их при сборке, или задания их c помощью команды setenv в командной строчке U-Boot):
ipaddr - IP-адрес платыnetmask - маска подсети (в принципе не обязательно)ethaddr - MAC-адрес сетевого интерфейса платы (любое 6-байтное значение)serverip - адрес tftp-сервера, по которому будет производится запрос требуемых файлов (в принципе не обязательно, можно указать в вызове команды)help. Помощь, указывая параметр можно получить помощь по различным командам, например help tftpbootrun. Запустить переменную как скрипт. Например (в случае наличия переменной tftp_update), run tftp_updatetftpboot. Загрузка файла по tftp. Формат:tftpboot [адрес_загрузки(в оперативной памяти)] [[IP-адрес_сервера:]полное_имя_файла]
cp. Копирование блока памяти. Позволяет копировать данные из Dataflash в SDRAM и обратно. Формат:cp [.b, .w, .l] <источник> <цель> <количество_копируемых_слов>
Копирование выполняется словами заданной длины (cp.b -копирование байтов, cp.w - слов (2 байта), cp.l - длинных слов (4 байта))
bootm. Загрузка образа приложения из памяти. Формат:bootm [адрес [аргументы ...]]
Подробней о возможных аргументах расскажет help bootm
Используя последние три команды можно составлять скрипты сетевой загрузки (их можно сохранить в переменных для быстрого доступа), команды разделяются с помощью »;». Пример моей переменной-скрипта для обновления ядра Linux по сети:
tftp_update=tftpboot 20400000 zlinux; cp.b 20400000 c0042000 170000
Как видно, сначала образ грузится в ОП по заданному адресу, потом копируется в энергонезависимую память (Dataflash в данном случае).
Для работы с NANDFlash-памятью предназначена команда nand.
nand read - <адрес> <смещение> <размер> nand write - <адрес> <смещение> <размер>
Адрес задает адрес в ОП откуда/куда пишутся данные. Смещение - задает смещение данных в NANDFlash, размер задается в байтах, bad-блоки пропускаются.
U-Boot поддерживает чтение-запись файлов со сменных носителей (USB, MMC). Поддерживает несколько файловых систем (fat, ext2 см. каталог fs в корне исходников). Поддержка задается в конфигурации, как правило наиболее интересна поддержка fat как стандартной ФС для сменных носителей. Для загрузки нужно использовать команду fatload.
fatload <интерфейс> <устройство> <адрес> <имя_файла> [<количество_считываемых_байт>]
В качестве интерфейса может выступать usb и mmc. Для поддержки mmc нужно правильно сконфигурировать U-Boot и выполнить команду mmc init перед загрузкой. Для загрузки с USB нужно предварительно выполнить команду usb reset. Пример команды для загрузки ядра Linux с usb-флешки:
usb reset; fatload usb 0 20400000 zlinux; usb stop; bootm 20400000
На мой взгляд, это очень удобная возможность для использующих Linux как рабочую станцию. Для Linux старые версии SAM-BA, поддерживающие com-порт не сыщешь, а USB-ные у меня так и не заработали. Соответственно для каждого обновления загрузчика нужно грузится в Windows. Основная необходимость использования SAM-BA - смена загрузчика U-boot, ее вполне можно выполнить самим загрузчиком. Например, для расположения загрузчика в Dataflash, источник - usb-флешка, файл u-boot.bin в ее корне. Загрузчик хранится в Dataflash по адресу 0×8000.
usb reset; fatload usb 0 20400000 u-boot.bin; cp.b 20400000 c0008000 30000
Размер 0×30000, взят с запасом, в принципе он определяется размером бинарного файла u-boot-bin и пишется после загрузки с флешки. В случае расположения U-Boot в NANDFlash в скрипте вместо команды cp.b нужно использовать команду nand read с соответствующими параметрами. Также загрузчик можно обновить по сети, например:
tftpboot 20400000 u-boot.bin; cp.b 20400000 c0008000 30000
Точно также в принципе можно обновлять и Bootstrap, там главное правильно файл подготовить, т.к. получаемый после компиляции файл записывается скриптом SAM-BA «Send boot file», который некоторые байты правит, по крайней мере прямая запись полученного после компиляции файла через «Send file» давала неработоспособный Bootstrap.
До сих пор (версия 2010.06) эта фича не работает до конца корректно в U-Boot, в частности, во время записи в Dataflash не выполняется необходимый периодический сброс таймера, что приводит к перезагрузке. Проблему можно решить, поправив вручную драйвер записи в Dataflash. Он располагается в drivers/mtd/at45.c. Нужно включить watchdog.h и использовать макрос WATCHDOG_RESET() для сброса таймера в циклических участках алгоритма записи в Dataflash.
Здесь можно скачать мой тестовый патч, вносящий эти изменения.

Дискуссия