/**
* @file MTD.h @class MTD @internal Header
* @brief Memory Technology Device (MTD) Support
* @addtogroup MTD @date 02.06.2022 6:26:00
* @{ @author Copyright (C) 2021, msct.ru
*/
#ifndef MTD_H
#define MTD_H
/// ====================================================================================
/// @include
/// ====================================================================================

#if NONE /// @pre
Для встроенных систем решающее значение имеет оптимальное распределение памяти прошивки.
Стандартом доступа к памяти прошивки де-факто стала Linux-технология Memory Technology
Device (MTD). Смысл внедрения подсистемы MTD в наши проекты:
- обеспечить эффективное управление флэш-памятью NOR;
- побудить ПО наших ПНС отвечать Linux-стандартам;
- приблизиться к возможностям FITC/UEFI при управлении генерацией прошивок.

Наша цель — создать быстрое удобное ПО. Несоответствие стандартам затруднит ПОРТИРОВАНИЕ
нужной нам функциональности MTD-FS и затянет сроки реализации проектов. В итоге лишние
затраты, дублирование данных и проблемы с безопасностью.

Чтобы разработка выполнялась без напряжения, считаем принципиальным — отклонения от
Linux-стандартов недопустимы, какими бы доводами это не подкреплялось.

/// ####################################################################################
/// @internal Содержание
/// ####################################################################################
/// §1 @~ Обзор FLASH MEMORY 2
/// §1.1 @~ Устройства на основе флэш-памяти 2
/// §1.2 @~ Типы флэш-памяти 2
/// §1.3 @~ Флэш-память vs HDD 3
/// §2 @~ MTD — Memory Technology Device и устройства с этой технологией 3
/// §2.1 @~ Разделы MTD в Linux и параметр командной строки ядра mtdparts 3
/// §2.2 @~ ЧТО ОСОБЕННОГО В РАЗДЕЛАХ MTD 4
/// §2.3 @~ Задание MTD-разделов через командная строку Linux и DevTree 4
/// §2.4 @~ Пример создания таблицы разделов с помощью mtdparts 5
/// §2.5 @~ Создание пустой файловой системы (чистого раздела) с jFFS2 5
/// §2.6 @~ Создание/Подключение образа с jFFS2 5
/// §3 @~ Комбинатор vs MTD-FS 5
/// §4 @~ Комбинатор или умный программатор? 6
/// §4.1 @~ Комбинатор или развитие ПНС? 6
/// §4.2 @~ Заголовок Комбинатора и сложность реализации ПО ПНС 8
/// §5 @~ Суммируем 8
/// §6 @~ Комбинатор + Partition Table + Full MTD-FS. Перспективы/риски/недостатки 11
/// @~ §6.1 ВВОД METADATA 11
/// @~ §6.2 Создание разделов 12
/// @~ §6.3 Обновление компонентов 12
/// @~ §6.4 Рассмотрим узловые моменты 13
/// §7 @~ ПНС + Комбинатор. Flash Image Tool и Boot в одном флаконе 13
/// §8 @~ Комбинатор без Partition Table (Linux стандарт) + Light MTD-FS 14
/// @~ §8.1 ВВОД METADATA 14
/// @~ §8.2 Создание разделов с оптимизацией кода ПНС на этапе компиляции 14
/// @~ §8.3 Обновление компонентов 15
/// @~ §8.4 В чем фундаментальное различие между сценариями «§6″ и «§8″? 15
/// §9 @~ Комбинатор без поддержки MTD-FS, но имеющий Partition Table 16
/// §10 @~ Работа ПНС, созданных по сценарию «§6″ 16
/// §11 @~ Работа ПНС, созданных по сценарию «§8″ 17
/// §12 @~ Преимущества ПНС при внедрении сценария «§8″ 17
/// @example Приложение#1. Унификация настройки «mtdparts.conf» в .ini файле 18
/// @example Приложение#2. Пример определения MTD-разделов в коде ядра Linux 18
/// @example Приложение#3. Пример создания пустой файловой системы 19
/// @example Приложение#4. Пример создания образа файловой системы 19
/// @example Приложение#5. Реальные примеры устройств с MTD-FS 20
/// @example Приложение#6. Сравнение ТТХ жестких дисков и флэш-памяти 20
/// @link Приложение#7. Ссылки 20
/// @section Приложение#8. Q&A (Вопрос-Ответ) 21
/// @interface as U-BOOT…
/// @page 1
/// ===================================================================================
/// §1 @~ Обзор FLASH MEMORY
/// ===================================================================================
Флэш-память (и/или просто флэш) — вид полупроводниковой технологии энергонезависимой
электрически перепрограммируемой памяти EEPROM.

Существует два основных способа применения памяти флэш:
— как носитель информации для компьютеров и электронных гаджетов;
— как хранилище программного обеспечения (прошивка) цифровых устройств.

Часто два этих способа совмещаются в одном устройстве.

/// ———————————————————————————
/// @~ §1.1 Устройства на основе флэш-памяти
/// ———————————————————————————
Если ЦП сопряжен напрямую с флэш и может непосредственно обращаться к её адресам,
то флэш называется raw. Пример raw-флэш — это чип BIOS в PC-совместимых машинах.
Если ли между ЦП и флэш стоит контроллер, то флэш называются FTL.

Устройства на основе флэш-памяти делятся на MTD-ВУ на базе raw-флэш и FTL-ВУ на
основе флэш-контроллера. FTL-ВУ включают USB-накопители, CompactFlash, MMC/eMMC,
SD, SSD и пр. Хотя в FTL-ВУ есть флэш-память, она скрыта за блочным интерфейсом
и уровнем флэш-трансляции (Flash Translation Layer — FTL).

Встроенные системы — это почти всегда raw-флэш. В то время, как любые накопители
это, как правило, FTL! Иначе говоря, при raw доступе ЦП оперирует адресами флэш,
а при FTL адресами контроллера. Исключение — так называемая трансляция SPI в ОЗУ.
Тут контроллер SPI перехватывает все обращения к флэш и транслирует их в протокол
SPI. ЦП не замечает подмены. Но это довольно редкое аппаратное решение.

Флэш может подключаться к материнской плате разными способами. Например, NOR флэш
может быть подключена непосредственно на шину ЦП, или же может быть подключена к
внешней шине PCI. Доступ к флэш также может быть разным, в зависимости от типа ЦП.
Разработчик материнки должен предоставить «FlashMapDriver datasheet», как к плате
подключена флэш-память. Это описание необходимо для настройки драйвера флэш-памяти
для работы с любой платой и ЦП.

/// ——————————————————————————-
/// @~ §1.2 Типы флэш-памяти
/// ——————————————————————————-
Основные типы флэш-памяти NOR и NAND имеют разную разметку данных. NOR от Not-OR
- логическое Не/ИЛИ. NAND от Not-AND — логическое Не/И. NAND создана позже NOR.

NOR. Была первой изобретенной флэш-памятью. Она позволяет читать байты в случайном
порядке. Таким образом, ЦП может выполнять код непосредственно из NOR. Это удобно
для загрузчиков, которым не нужно копировать код в ОЗУ перед его выполнением. Чаще
на основе NOR-памяти строятся raw-флэш для MTD-ВУ.

Микросхемы NOR флэш бывают двух видов: старые не-CFI и новые, CFI совместимые. CFI
расшифровывается как Common Flash Interface (Стандартный Интерфейс Флэш-памяти) и
является отраслевым стандартом для обеспечения совместимости чипов флэш-памяти
одного и того же поставщика.

NAND. Самая популярная флэш-память, ибо дает большую емкость по более низкой цене.
Недостатки: 1. Нужно использовать контроллер для доступа к данным, и ЦП не может
выполнять код из NAND без копирования кода в ОЗУ. 2. NAND флэш могут поставляться
со сбойными блоками, что требует аппаратно-программных решений для выявления и
удаления неисправных блоков.

Сегодня доступны два типа NAND. Первый тип эмулирует стандартный блочный интерфейс
и имеет аппаратный FTL, который обеспечивает стирание блоков, выравнивание износа
и управления сбойными блоками. Это соответствует USB-накопителям, картам памяти,
eMMC и SSD. Тут ОС не может контролировать способ управления секторами, ибо видит
лишь эмулируемое блочное ВУ. Такой подход полезен для снижения сложности ПО на
стороне ОС. Но производители железа часто держат в секрете алгоритмы FTL, что не
позволяет ОС настраивать и проверять эти алгоритмы. Ходят слухи, что за секретами
скрывается плохая реализация железа. Например, ряд флэш реализуют выравнивание
износа на 16 МБ секторах вместо использования пространства всего хранилища.
Что может легко повредить ВУ.

/// @page 2
Второй тип — NAND raw-флэш. Тут ОС имеет доступ к контроллеру и может напрямую
управлять блоками ВУ + возможен подсчет стираний блока (счетчик стираний).

/// ——————————————————————————
/// @~ §1.3 Флэш-память vs HDD
/// ——————————————————————————
HDD — дешевая и проверенная технология. Основное преимущество по сравнению с флэш
заключается в том, что жесткий диск не подвергается естественному износу из-за
перезаписи данных. Тем не менее флэш-память набирает популярность и, по утверждению
некоторых экспертов, в скором времени может вытеснить жесткие диски с рынка.

Детальное сравнение возможностей (сильных и слабых сторон технологий) HDD и флэш-
памяти можно увидеть в «Приложение#6″.

/// ==============================================================================
/// @~ §2 MTD — Memory Technology Device и устройства с этой технологией
/// ==============================================================================
MTD — подсистема ядра Linux для работы с флэш-памятью. MTD обеспечивает интерфейс
между низкоуровневыми драйверами чипов (NOR, NAND и пр.) и модулями пользователей.
Другими словами, MTD абстрагирует драйвера от приложений.

Чтобы избежать использования различных средств для разных технологий и поддержать
общие возможности для всех, MTD унифицирует API и плавно сочетает драйвера чипов
с приложениями более высокого уровня.

Разумеется, общие возможности подразумевают и единые стандарты, нарушение которых
недопустимо, какими бы вескими мотивами это не подкреплялось.

В терминологии Linux, MTD-ВУ включают в себя все устройства памяти, такие как ROM,
RAM, флэш-память и DiskOnChip (DOC) и пр. Разнообразные ВУ имеют свои собственные
возможности, особенности и ограничения. Для программирования и использования MTD-
ВУ в своих системах разработчики встроенного ПО традиционно применяют инструменты
и методы, специфичные для этого типа устройств.

Хотя для блочных и символьных ВУ давно существуют свои подсистемы, их семантика
плохо согласуется с работой с MTD-ВУ. Поэтому MTD реализует для них режим блочного
и символьного устройства.

Приложениями MTD могут быть как СУБМОДУЛИ ядра, такие как jFFS2 или NFTL, так и
приложения в пространстве пользователя, такие как «dd» или менеджер обновлений.

MTD позволяет получать доступ ко всем типам флэш (NOR, NAND и пр.) и управлять
ими с помощью общего интерфейса. Это обеспечивает свободу реализации аппаратно-
независимого ПО для управления флэш-памятью, в частности, файловыми системами.

Для работы с FTL-ВУ применяются обычные FS: FAT, EXT3/4, XFS и т.д., которые
поддерживают HDD. При работе с MTD-ВУ применяются FS с поддержкой MTD: jFFS2,
YAFFS2, UBIFS, LogFS и пр. MTD может экспортировать блочные ВУ и работать с общей
FS, такой как EXT4. Но использовать MTD-ВУ таким образом не рекомендуется, ибо не
происходит ни поиска сбойных блоков, ни выравнивания износа.

Сегодня применение MTD — обычная практика. Реализаций множество. MTD используется
в Android-системах на смартфонах, в роутерах, ресиверах, серверах, настольных ПК,
IP-камерах, NAS и в иных завсегдатаях интернет-вещей и прочего.

/// ———————————————————————————
/// @~ §2.1 Разделы MTD в Linux и параметр командной строки ядра mtdparts
/// ———————————————————————————
Первое, что можно сделать, это получить доступ к флэш-хранилищу и его разделам.
Это похоже на доступ к блочным raw ВУ через файлы устройств, такие как /dev/sda
(все устройство) и /dev/sda1, /dev/sda2 и т.д. MTD ВУ обычно делят на разделы.

Это полезно при задании областей для различных программных целей. «Raw» означает,
что FS не используется. И в этом нет необходимости, если у вас есть только один
двоичный файл для хранения, а не несколько файлов. Объявление разделов доступными
только для чтения — это также способ запретить ОС вносить изменения в такие разделы.
В результате, разделы загрузчика и «RootFS» могут быть защищены от ошибок и попыток
несанкционированного изменения. Вы также можете заметить, что разделы нельзя обойти,
обратившись ко всему ВУ по заданному смещению, поскольку Linux не предлагает файла
для доступа ко всему хранилищу.
/// @page 3

Обычно вам потребуется разделить флэш-память на несколько областей, например, чтобы
выделить место для ПНС, образа ОС или корневой FS. Linux предоставляет 3 стандартных
способа указать размеры/адреса разделов: 1. Командная строка ядра ОС 2. Определение
MTD-разделов в исходном коде ядра; 3. Конфигурирование ядра через DevTree. А именно:
— CONFIG_MTD_CMDLINE_PARTS; /// @note через командную строку Linux
— CONFIG_MTD_PARTITIONS; /// @note через драйвер отображения платформы в коде ОС
— CONFIG_MTD_OF_PARTS. /// @note через DevTree (дерево устройств)
/// @~ Вопрос. Зачем нужен заголовок Комбинатора (см. Ниже) если метаданные можно
/// по стандарту передать ядру ОС через DevTree или командную строку Linux?!
В случае первого варианта используется параметр командной строки ядра — «mtdparts»,
который задается следующим образом в исходном коде Linux в drivers/mtd/cmdlinepart.c:
mtdparts=[; := : [, ]
:= уникальное имя чипа

:= [G][g][M][m][K][k][@][ ][ro]
:= размер раздела ИЛИ ‘-’, обозначающий все оставшееся место
:= смещение начала раздела внутри устройства;
оставить пустым, если раздел начинается сразу после предыдущего

:= (‘имя раздела назначенное разработчиком ПО’)

mtd-id определяется расположением флэш на плате. Принятый формат mtd-id:
spi%d.%d-%s.
Значения соответствуют spi.-ChipID
ChipID — название Flash-чипа, например AT45DB642x.

Командная строка может принимать несколько mtddef, разделенных ‘;’. Любой mtddef может
определять несколько «partdef», разделенных ‘,’. Разделам может быть присвоен размер и
необязательные токены: смещение, имя и флаг «read-only». Смещения нужны, при наличии
несмежных partdef (есть нераспределенное пространство между partdef). Смещения/размеры
разделов должны быть кратны длине блока стирания. Его длину ищите в /sys/class/mtd/mtdx
/erasesize путем запуска cat /proc/mtd или в командной строке целевой ОС. Далее будем
рассматривать передачу мета в Linux через строку «mtdparts».

/// ———————————————————————————-
/// @~ §2.2 ЧТО ОСОБЕННОГО В РАЗДЕЛАХ MTD
/// ———————————————————————————-
ЭТО ТО, ЧТО В НИХ НЕТ ТАБЛИЦЫ РАЗДЕЛОВ, как в блочных ВУ. Тому есть несколько причин, и
одна из них — флэш устройства являются небезопасным местом для хранения такой ключевой
информации, как «Partition Table», поскольку блоки флэш-памяти могут стать негодными во
время эксплуатации системы.

Вместо «Partition Table» разделы на флэш определяются в структуре «mtd_partition» в
коде ядра Linux. Пример, как это делается в коде ядра, приведён в «Приложение#2″.

/// ———————————————————————————-
/// @~ §2.3 Задание MTD-разделов через командная строку Linux и DevTree
/// ———————————————————————————-
К счастью, можно переопределить «struct mtd_partition» по дефолту, не меняя код ядра.

Посмотрите на журнал ядра во время загрузки. В примере платы «Beagle» имя устройства
MTD было «omap2-nand.0″ и на нем было создано пять разделов:

omap2-nand driver initializing. ONFI flash detected
NAND device: Manufacturer ID: 0x2c, Chip ID: 0xba (Micron NAND 256MiB 1,8V 16-bit)
Creating 5 MTD partitions on «omap2-nand.0″:
0×000000000000-0×000000080000 : «X-Loader»
0×000000080000-0×000000260000 : «U-Boot»
0×000000260000-0×000000280000 : «U-Boot Env»
0×000000280000-0×000000680000 : «Kernel»
0×000000680000-0×000010000000 : «File System»

Теперь можно задать свои собственные MTD-разделы, не изменяя исходные коды ядра.
Для этого Linux предлагает параметр «mtdparts» для определения ваших собственных
границ раздела. Вы можете добавить определение «mtdparts» в командную строку ядра
и изменить его поведение при запуске загрузчика (см. «§2.4″).
Также вы можете задать MTD-разделы, специфицировав «MTD Partitions» в «Device Tree»
(в дереве устройств): /// @see lists.debian.org/debian-arm/2015/05/msg00036.html

/// @page 4
/// ———————————————————————————-
/// @~ §2.4 Пример создания таблицы разделов с помощью mtdparts
/// ———————————————————————————-
mtdparts=omap2-nand.0:128k(X-Loader)ro,256k(U-Boot)ro,128k(Environment),4m(Kernel)ro,
32m(RootFS)ro,-(Data)
Мы только что определили 6 разделов в устройстве «omap2-nand.0″:
X-Loader — загрузчик первого этапа ( 128 КБ, только для чтения )
U-Boot ( 256 КБ, только для чтения )
Environment — среда U-Boot ( 128 КБ)
Kernel — ядро ( 4 МБ, только для чтения )
RootFS — корневая файловая система ( 16 МБ, только для чтения )
Data — раздел данных ( занимает все оставшееся место )

Теперь, когда разделы определены, можно отобразить соответствующие устройства MTD,
просмотрев /proc/mtd (размеры указаны в шестнадцатеричном формате):
dev: size erasesize name
mtd0: 00020000 00020000 «X-Loader»
mtd1: 00040000 00020000 «U-Boot»
mtd2: 00020000 00020000 «Environment»
mtd3: 00400000 00020000 «Kernel»
mtd4: 02000000 00020000 «File System»
mtd5: 0dbc0000 00020000 «Data»

Также можно заметить еще одно отличие от блочных ВУ: имена разделов блочных ВУ по-
прежнему относятся к полному имени ВУ. Например, /dev/sda1 для 1-го раздела ВУ
относится к /dev/sda. А разделы MTD отображаются, как независимые ВУ, и, например,
mtd1 может быть либо вторым разделом 1-го флэш, либо первым разделом 2-го флэш-ВУ.

/// ———————————————————————————-
/// @~ §2.5 Создание пустой файловой системы (чистого раздела) с jFFS2
/// ———————————————————————————-
Пример создания пустой файловой системы «jFFS2″ можно увидеть в «Приложение#3″.

/// ———————————————————————————-
/// @~ §2.6 Создание/Подключение образа с jFFS2
/// ———————————————————————————-
Пример создания/подключения файловой системы «jFFS2″ можно увидеть в «Приложение#4″.

/// @~ ЗАМЕЧАНИЕ. Созданные в Linux по директивам Приложения#4 разделы FS, файловые
/// системы и файлы внутри них, как и сама MTD-разметка, будут работоспособны лишь
/// в данном месте (в контексте заданного диапазона адресов текущего флэш-чипа).
/// Простой сдвиг разделов и/или перенос разметки в микросхему иного типа приведут,
/// как правило, к исключению «failed hardware».

/// ===============================================================================
/// @~ §3 Комбинатор vs MTD-FS
/// ===============================================================================
Для флэш-памяти всегда остаются актуальными внешние методы балансировки нагрузки,
прежде всего, с помощью специальных файловых систем. Первой попыткой создания FS,
которая бы учитывала организацию флэш-памяти, была «Journaling Flash File System»
и её развитие jFFS2 с поддержкой NOR и NAND.

ЖУРНАЛИРУЕМАЯ файловая система jFFS2, является приложением MTD. На ВУ её файлы
представлены, как индексы. Индексы хранятся в статическом виде на ВУ и содержат
сведения, нужные для доступа к файлам, а также физические смещения и указатели
на фактические адреса блоков файлов на ВУ. /// @see sourceware.org/jffs2/jffs2.pdf

Для создания прошивок для наших ПНС была создана программа «Комбинатор», которая в
классическом понимании, есть инструмент генерации прошивок — Flash Image Tool (FIT).
В текущей редакции Комбинатор создает в конце флэш свою таблицу разделов устройства
- «Partition Table» (далее «раздел» Комбинатора или «заголовок» Комбинатора).

Заметим, что при использовании «Комбинатора» (в его нынешнем виде), работа любой FS,
такой как jFFS2, может стать невозможной! Комбинатор создает образы «firmware» путем
конкатенации всех разделов, то есть переносит последующие разделы в новое место при
изменении размера у предыдущих. Причем делает это без поддержки MTD->jFFS2, т.е. без
учёта зависимостей. В итоге, после переноса раздела FS, фактические адреса блоков
файлов в индексах на флэш становятся неактуальными, т.к. уже указывают не на блоки
файлов, а на чужое или неиспользуемое пространство на ВУ.

/// @page 5
Другой пример, применение на флэш простейшей файловой системы «RomFS».
/// @see https://www.kernel.org/doc/html/latest/filesystems/romfs.html

Эта FS включает поле «offset» — физическое смещение 1-го компонента от начала ПЗУ.
Отсюда, при использовании Комбинатора и перемещении разделов работа даже этой простой
FS станет невозможна! Более того, совместно с Комбинатором опасно применять и саму MTD
платформу, т.к. MTD разметка, её метаданные и метод передачи строки «mtdparts» есть
наглядный пример связанных и физически зависимых сущностей. С другой стороны, даже если
мы откажемся от размещения MTD-FS на флэш, то это вовсе не значит, что от использования
файловых системы на флэш должны отказаться и сторонние разработчики.

/// ====================================================================================
/// @~ §4 Комбинатор или умный программатор?
/// ====================================================================================
Разнотипные ПНС практически всегда относятся к разным семействам машин. У семейств
обычно отличаются аппаратные платформы: архитектуры ЦП, южные мосты, виды ОЗУ, типы
флэш-чипов, размеры MTD-ВУ, аппаратные интерфейсы и т.д. Они имеют свои уникальные
файлы настроек и, как правило, используют собственные разноименные разно-целевые
сущности загрузки. В частности, они загружают разные по наполнению/размерам DevTree,
ОС, Микро-ОС, параметры загрузки и пр.

Создать общее ПО, подходящее сразу ко всем семействам или ряду семейств, практически
невозможно. Разработка такого ПО бессмысленна, неразумна и нерентабельна.

Каждое семейство машин обычно имеет свою структуру (конфигурацию) разделов прошивки.
Де-факто образ прошивки — это стек компонентов загрузки, где в голове с 0-го адреса
располагается ПНС, а за ней остальные разделы в продуманном разработчиком порядке.
«Порядки» здесь устанавливает разработчик ПНС. Тем самым структура прошивки заранее
предопределена. Это при общепринятой технике применения MTD-FS фиксируется в коде
ПНС, где еще на этапе компиляции у всех элементов мета разработчик заблаговременно
детерминирует каждое основополагающее поле: тип, имя, размер и прочее. Т/о, именно
разработчик определяет текущую структуру прошивки. Постфактум ПНС передаёт свои мета
ядру ОС. Причём делает это согласно стандарту Linux через параметр командной строки
«mtdparts» и/или с помощью файла «DevTree». Задание структуры прошивки стандартным
способом позволяет определить метаданные о разбиении флэш-памяти в одном месте (DRY)
и затем видеть, передать и использовать общую информацию о разделах MTD одновременно
в ОС, ПНС и FIT.

При таком способе формирования и передачи метаданных заголовок Комбинатора не только
не отвечает стандарту, но и просто избыточен. Ведь «любой» может запустить Комбинатор,
а Комбинатор и, тем более «любой», не могут решать за ПНС, каким сущностям входить в
прошивку, как они будут называться и как ими следует манипулировать.

КОМБИНАТОР ДОЛЖЕН СТАТЬ ПРОСТО УМНЫМ ПРОГРАММАТОРОМ, т.е. работать по Linux-правилам
разбора строки метаданных «mtdparts», а не навязывать ПНС тип, имена, адреса, размеры,
порядок следования и число разделов в «firmware».

Метаданные о составе компонентов (их наличие, типы, адреса, размер и пр.) ПРОГРАММНО
СВЯЗАНЫ, контекстно зависимы и функционально важны для работы и ПНС и ОС.
А отсюда следует:

НЕ FIT ЗАДАЮТ СТРУКТУРУ И ОРГАНИЗАЦИЮ FIRMWARE, А FIRMWARE ОПРЕДЕЛЯЮТ И ГОВОРЯТ FIT,
КАК ИХ СЛЕДУЕТ СОБРАТЬ И ПОСТРОИТЬ.

Задача Комбинатора проверить совпадают ли метаданные у зашиваемой ПНС с «mtdparts»
на ВУ и, если Да, то записать на ВУ указанный компонент (или компоненты) по адресу
из MTD-метаданных. А если метаданные не совпадают, то предупредить о расхождении.

Иначе говоря, Комбинатор не должен каждый раз обновлять всю прошивку, как он это
делает сейчас, и не должен перемещать разделы и/или изменять структуру прошивок, а
должен следовать указаниям ПНС, которая точно знает, как нужно построить «firmware»
и что и куда или откуда нужно записать или прочитать.

/// ———————————————————————————
/// @~ §4.1 Комбинатор или развитие ПНС?
/// ———————————————————————————
Кроме того, ПНС естественным образом развиваются. Так для быстрого старта E2K.V6
ПНС реализует параллельную настройку DDR4, режим BroadCast. Далее, для ускорения
загрузки в ПНС планируется внедрить многопоточный запуск («multitask»).

/// @page 6
В «multitask» среде могут запускаться приложения, драйвера, тесты, утилиты, средства
отладки и др. сущности загрузки.

Задачи приложений, назначение др. сущностей, их имена и размеры будут отличаться
у разных ПНС. Число сущностей будет определяться типом ПНС и ограничиваться лишь
размерами флэш. При этом сущностью загрузки может быть не только сырая информация,
но и контейнеры с файлами. Так, например, в большинстве «embedded» проектов ОС и
ПНС предпочитают хранить свои приложения и данные не столько в RAW-областях,
сколько в разделах файловых систем: «RomFS», «EXT4″, «jFFS2″, «UbiFS» и пр.
В большинстве случаев этим же путем пойдут и пользователи наших ПНС.

MTD разметка + контейнеры данных в виде FS стали обычной общепринятой практикой.
Такой подход сейчас — это фактически стандарт (классика) при создании прошивок
для современных цифровых устройств. Реальные примеры устройств с MTD-FS можно
увидеть в «Приложение#5″.

Как видно по примерам из «Приложения#5″, число разделов и используемых файловых
систем самое разнообразное и зависит только от типа устройства и решаемых целевых
задач.

Конечно, Комбинатор позволяет в интерактивном режиме изменить число и/или порядок
разделов. В то же время, запрос на появление новой сущности (или нескольких сразу)
может возникнуть у разработчиков ПНС или ОС в любой момент. Тогда потребуется
вмешательство оператора (что не всегда удобно) или придется править Комбинатор,
а от его доработок лучше вообще не зависеть.

Например, сейчас возникла потребность во внедрении файла «S3″ для поддержки режима
энергосбережения на E2C3. Далее подобные потребности могут возникать неоднократно.
Файл «S3″, по понятным причинам, будет отсутствовать у серверов E16C и E12C. Т.е.
ПНС E2C3, E16C и E12C — это разные семейства машин. У них отличается наполнение
прошивок, хотя и общая система команд.

На совещании с «ядерщиками» было принято решение размещать компоненты прошивки
«BootCode», «uOS», «S3″ и «DevTree» в «raw»-разделах, + будут добавлены FS-разделы:
— «dflt.RomFS» c файлом «dflt.json» с параметрами загрузки по умолчанию;
— «work.RomFS» c файлом «work.json» с настройками загрузки, установленными
пользователем.

В «uOS» к файлам «dflt.json» и «work.json» будет обеспечиваться доступ, как к
текстовым файлам, а в ПНС их интерактивная настройка через консоль бута.

Что мы получим после размещения всех компонентов ПНС в «raw», «RomFS» и «jFFS2″
разделах MTD:
- Каждая сущность загрузки будет размещаться в своём целевом разделе:
«BootCode»(Raw) «dflt/work»(RomFS), «S3/DevTree/uOS»(Raw) «RootFS»(jFFS2)
/** @note 1. У каждой ПНС может быть свой собственный размер раздела BootCode.
По системным соображениям размер раздела BootCode.Raw следует
зафиксировать (сделать условно-постоянным) для семейства машин.
2. На этапе монтирования RomFS должны создаваться (если отсутствуют)
обязательные конфигурационные файлы: DevTree, work.json, dflt.json,
S3 (для E2C3) и пр. По умолчанию, обязательные файлы настроек
создаются пустыми (и возможно) с ID-сигнатурами.
3. Для того, чтобы адрес разделов RomFS менялся, как можно реже, их
следует располагать сразу за BootCode.Raw.*/ ;
- Упростится работа с «S3″ в ядре;
- Появится возможность передачи «DevTree», «S3″ из ПНС в ОС, минуя «boot_info»/ОЗУ;
- К сущностям загрузки в Linux будет обеспечен стандартный механизм доступа;
- «uOS» сможет перенести все свои файлы (такие, как «initrd» и пр.) в раздел с FS;
- У «uOS» с FS будут развязаны руки, ибо она получит свободу реализации в привычной
Linux-среде и пр.;
- «json» файлы можно будет читать (в перспективе править) в Linux редакторах/
ПРОСМОТРЩИКАХ и/или в специально созданной утилите;
- Балансировка нагрузки защитит все файлы в jFFS2 и увеличит время жизни флэш;
- Будет возможен доступ из «uOS» к флэш-памяти старше 16 МБ как к FS-разделу;
- «Lintel» и СДЗ также могут стать частью «firmware» и запускаться из разделов FS;
- Прошивка «Lintel» и СДЗ может выглядеть для оператора в «uOS», как обычная операция
записи в файл;
- Упростятся исходники ПНС;
- Сократится размер ПНС;
- Увеличится скорость загрузки.
/// @page 7

В общем, как говорится, «это вам не у Пронькиных», и все будет «не хуже, чем у людей».

И что важно, при использовании FS число файлов (сущностей загрузки) не лимитировано.

Понятно, что при неограниченном разнообразии и числе файлов, возникнет классическая
задача реализации динамического распределения пространства памяти хранилища.
С этим, в общем случае, отлично бы справились файловые системы, такие как: «RomFS»,
«jFFS2″ и пр.

Однако применение FS невозможно в рамках Комбинатора с его концепцией по перемещению
разделов. Причем, Комбинатор не только не учитывает FS-зависимости, но и создает на
флэш ДОПРАЗДЕЛ под свои метаданные, чем фрагментирует адресное пространство ВУ.

А ПАРАДИГМА MTD ВООБЩЕ НЕ ПОДРАЗУМЕВАЕТ ХРАНЕНИЕ МЕТАДАННЫХ НА САМОМ ВУ.

Этому, вкупе и с другими аспектами, есть вполне простое и логичное объяснение (+ ещё
одна причина отсутствия «Partition Table» на флэш):
ПО прошивки с неопределённой произвольно-переменной структурой трудно реализуемо и
ненадежно, что может приводить к малообъяснимым сложно обнаруживаемым ошибкам и
непредсказуемым результатам при загрузке.

/// ———————————————————————————
/// @~ §4.2 Заголовок Комбинатора и сложность реализации ПО ПНС
/// ———————————————————————————
О возможных проблемах и сложностях, которые могут быть (или обязательно возникнут)
в ходе реализации ПО Комбинатора детально говорится в параграфах ниже, начиная с
номера «§5″. Здесь лишь небольшой пример, как иллюстрация возможных трудноcтей при
реализации ПО ПНС, в случае наличия и отработки в ПНС заголовка Комбинатора.

Сейчас во всех наших ПНС есть такая сущность, как SPI Chip-Select — простая числовая
константа, пока «ЗАХАРДКОЖЕНАЯ» в коде бута и используемая базовой подсистемой SPI,
подсистемой работы с NOR-флэш и т.д.

При получении переменного значения Chip-Select из метаданных, хранящихся в заголовке
Комбинатора, нам потребуется массовая доработка SPI-подсистем во всех бутах. Конечно,
это преодолимо, но трудоёмко, что уже неприятно.

Отметим, что «ЗАХАРДКОЖЕНОСТЬ» данных — это не просто «магические константы» в коде.
Напротив — это ключевая информация, «база данных» по умолчанию, без которой немыслима
штатная работа ПНС. Например, без знания нужных размеров и смысловых имён у конкретных
разделов и файлов не получишь доступ к ним. Без номера шины/CS по умолчанию, без «инфы»
о других ТТХ, присущих целевому «железу», ПНС просто не сможет функционировать. Да и
мало ли что там снаружи мог задать «user» в заголовке. А если даже семантика заголовка
и понимание ПНС совпадают, то при наличии «Partition Table» получаем не DRY, а WET код,
т.е. избыточное бессмысленное дублирование данных в ПНС и в заголовке Комбинатора.
И таких похожих или иных проблем, связанных с наличием/отработкой метаданных, уже не
«ЗАХАРДКОЖЕНЫХ» в коде, а полученных из заголовка Комбинатора будет достаточно.

Весьма вероятно, что для отработки части таких проблем, потребуется подключить CAR,
а для облегченной поддержки MTD-FS в буте помощь «CacheAsRam» понадобится точно.
К сожалению, механизм CAR есть у нас не во всех архитектурах.

Даже общий разбор строки «mtdparts» из заголовка Комбинатора удобней (желательней)
делать в CAR. Мучиться с её разбором через регистровый файл совершенно не хочется,
т.к. это будет еще один «плюс» в копилку досадных проблем.

При этом в ПНС, созданной по схеме «§11″ (см. ниже), строка «mtdparts» формируется
заранее на этапе компиляции. Она складывается прямо из метаданных по умолчанию, т.е.
из известных имен/размеров у разделов и файлов и пр. То есть, де-факто, обеспечивается
оптимизация кода ПНС ещё на этапе компиляции. В итоге ПНС, при загрузке, разбор строки
«mtdparts» и подключение для подобных целей CAR не требуется, исключается ручной ввод
данных (и ошибки ввода).

/// ==================================================================================
/// @~ §5 Суммируем
/// ==================================================================================
Первое. ПНС могут использовать FS, а образы «firmware» размещаться сразу на нескольких
ВУ. К такой организации данных Комбинатор совершенно не готов и с подобной структурой
прошивок работать не умеет.
/// @page 8
ГЛАВНОЕ. Для операций с MTD-FS: создание MTD разделов, чтение и запись файлов и пр.
нужен Linux. И желательно не просто Linux, а Linux, запущенный на этой же машине,
для штатного взаимодействия с любой поддерживаемой MTD-FS. В Windows работа с MTD-FS
практически невозможна. Т.е. Комбинатор под Windows не сможет работать с FS Linux.

В этих условиях Комбинатор может только разобрать прошивку, но собрать её безошибочно
вновь и с иной адресацией он уже не сможет по техническим причинам. Единственное, что
Комбинатор может сделать при сборке с FS-разделами Linux для сохранения их целостности
- это записать их обратно по старым адресам без изменения содержимого.

Второе. Комбинатор определяет метаданные прошивки вне ПНС и затем хранит их в своём
заголовке. Метаданные в Комбинаторе задаются в интерактивном диалоге с оператором.

Поскольку структура прошивки «с заголовком» Комбинатора предполагается произвольно-
переменной, то все действия по описанию образа «firmware» пользователи и разработчики
ПНС будут выполнять врукопашную, т.е. ручным способом формировать/указывать топологию
MTD-разделов и детальные характеристики используемых файловых систем.

К этому добавляются действия по непосредственному созданию разделов и, собственно,
самих FS. В параграфе «Создание/Подключение образа с jFFS2″ описан примерный и очень
неполный сценарий выполнения такой работы.

Данную процедуру придётся делать каждый раз при создании новой структуры прошивки,
или если флэш-память пуста и/или при смене адресов MTD-FS разделов.

Кроме того, разработчику собрать строку мета в исходном коде ПНС гораздо удобнее и
быстрее, чем выполнить запуск Комбинатора и провести последующий интерактивный
диалог с ним и прочее. ДЛЯ СПРАВКИ: только сам запуск Комбинатора на машине «i5″
занимает целых 15 секунд. Это много и субъективно очень заметно.

Отметим также, что чаще всего пользователи и наладчики имеют на руках (и им нужны)
только обрезанный код бута и данные «DevTree» (иногда еще нужен код «uOS»). Но если
флэш сотрут (а это обычное дело), то и им придется изучить синтаксис «mtdparts» и
затем каждый раз набивать вручную мета-строку. Это касается и разработчиков ПНС,
если создается новое семейство или меняется старое. Даже в самой простой строке
«mtdparts=spi0:5M(E2C3),64k(d.j),64k(w.j),9k(D3),20k(S3),10M(uOS),-(root)»
уже 10 токенов. При их написании человек может в сумме сделать более 10 ошибок.

От всякой ручной работы, да и от самого Комбинатора не хочется зависеть. Ясно, что
заставлять разработчиков/пользователей все время «писать письма» непрофессионально,
а также чревато возможностью возникновения человеческих ошибок.

При этом отказ от ручной работы означает возврат к идее использования параметра
командной строки «mtdparts». Как реализовать эту идею?

Ответ: /// @see §11 Работа ПНС, созданных по сценарию «§8″

Третье. Сейчас некоторые вещи в Комбинаторе «ЗАХАРДКОЖЕНЫ» (адреса, имена и др.), а
некоторым сущностям присваиваются не отвечающие смыслу и наполнению проектов имена,
типа: «userspace1″, «userspace2″ и пр.

Однако, другие и/или новые ПНС-проекты обычно будут создаваться иной персональной (и
возможно, сторонней) командой программистов-разработчиков. Такие проекты обязательно
станут отличаться от старых. И хотя основная цель у всех ПНС одна, отличия между ними
будут весьма значительны.

Но так как ПНС не похожи, Комбинатор не в состоянии учесть их изменчивый состав и
особенности. Да он и не знает и не может знать, какие задачи решают разработчики ПНС,
какие файловые системы они предпочитают, как будут называться файлы, сколько и каких
именно файлов нужно сейчас или сколько и каких именно понадобится в будущем.

Четвёртое. Мы собираемся активно применять MTD-FS. Но реальные ФИЗАДРЕСА у файлов в
контейнерах MTD-FS изменчивы и не постоянны.

ФИЗАДРЕСА — позиционно-зависимые, сложно-образуемые и сложно-идентифицируемые объекты.
Комбинатор без поддержки всех FS не сможет узнать, какие реальные ФИЗАДРЕСА на ВУ
(в рамках «некой указанной оператором FS») имеют используемые файлы в данный момент,
а значит и не сможет указать ПНС смещения для доступа к файлам.

/// @page 9
Кроме того, любая ПНС имеет право выбрать и опираться на свою FS и не одну. ПНС, зная
выбор разработчика, может (хотя бы облегченно) поддержать «любимую» файловую систему.

/// @note Облегченная (light) поддержка MTD-FS в ПНС означает отсутствие большей части
/// операций с файлами + внедрение некоего нового функционала присущего только
/// конкретной ПНС, например, размещение файла на ВУ непрерывно по ФИЗАДРЕСАМ,
/// или запись данных в read-only файл и пр. Задача light-поддержки MTD-FS в
/// ПНС — не повторить или продублировать работу MTD-FS в целом, а лишь добавить
/// немного красок в палитру возможностей при условии сохранения целостности
/// MTD-FS и с полным учетом текущих программно-функциональных зависимостей.

Лишь паре ПНС + ОС по сути предопределено и всегда точно известно:
- место хранения ( bus, chip-select, раздел, смещение, порядок );
- способ хранения ( raw, FS );
- и поименно, какие именно компоненты ( приложения, драйвера, утилиты, файлы, тесты,
«payload», «initrd» и пр. сущности ) требуется разместить на флэш.

А значит, де-факто раздел Комбинатора на флэш избыточен. Ибо ПНС сама знает/передает
метаданные Linux через ОЗУ, а ядро затем только симулирует таблицу разделов. В этих
условиях заголовок Комбинатора бесполезен и даже вреден.

ОН ЛИШЬ ЗАНИМАЕТ МЕСТО НА ВУ И БЕССМЫСЛЕННО ФРАГМЕНТИРУЕТ АДРЕСНОЕ ПРОСТРАНСТВО.

Пятое. Есть мнение, что наличие заголовка Комбинатора облегчает сертификацию ПНС.
Такой довод несостоятелен. Число разделов на ВУ меняется крайне редко. Например,
у всех семейств ПНС V6 число разделов на флэш не меняется уже 4 года. И это в
условиях интенсивной разработки загрузчика. И как в принципе константа, общая для
всех машин семейства (или даже ряда семейств), может влиять на сертификацию ?
А в конце разработки ПНС их метаданные, как правило, вообще не меняются, т.к. смена
мета по окончании работ теряет всякий смысл. Напротив, по ходу разработки ПНС V6 из-
за разных ошибок «железа» число правок кода этих ПНС стало трудно подсчитать.
Значит, отсутствие заголовка Комбинатора в ПНС V6 на возможную сертификацию никак не
влияет, зато обход багов «железа» в буте сорвал бы её совсем или превратил в ужас.

Шестое. Как мы видим из всего выше сказанного, что от заголовка Комбинатора, кроме
вреда пользы никакой. Но если заголовок Комбинатора бесполезен или вреден, а его
создание для клиентов всегда связано с кропотливой ручной работой и риском внести
ошибки, то здравый смысл подсказывает очевидный вывод:

ХРАНИТЬ МЕТАДАННЫЕ ПРОШИВКИ В СПЕЦ.РАЗДЕЛЕ НА ФЛЭШ НЕЦЕЛЕСООБРАЗНО.

Можно предположить (а это подтверждает общая практика и стандарты), что сама миссия
флэш — ХРАНЕНИЕ ОБРАЗА ЗАГРУЗКИ (в сумме с разнообразием и уникальностью кодов ПНС),
и ЯВЛЯЕТСЯ ГЛАВНОЙ ПРИЧИНОЙ ОТСУТСТВИЯ У ПРОШИВОК НА MTD-ВУ ТАБЛИЦЫ РАЗДЕЛОВ.

Седьмое. Переход на технологию MTD позволит всем ПНС-проектам опираться на Linux-
стандарты и в перспективе использовать всю мощь известных файловых систем вместо
доморощенных возможностей Комбинатора. Альтернатива здесь явно контрпродуктивна -
это невозможность использования в наших ПНС файловых систем. А значит, компромисс
может быть найден лишь при условии отказа от неподконтрольного перемещения разделов
на ВУ самим Комбинатором. В итоге нам придётся либо доработать Комбинатор до уровня
умного программатора или совсем отказаться от него.

/// @~ ЗАМЕЧАНИЯ ОТ РАЗРАБОТЧИКОВ ПНС V6:
1. Если Комбинатор не может ничего «комбинировать», то может стоит задуматься,
а нужен ли нам вообще Комбинатор в старом виде?
2. Если FS-разделы перемещать нельзя, а мета информация о них и используемых в ПНС
файлах «ЗАХАРДКОЖЕНА» в самом коде бута, то зачем её (мета-инфу) нужно повторно
дублировать в заголовке Комбинатора? Совершенно непонятно. Получается, что цель
дублирования в самом дублировании, с риском внесения при этом человеческих ошибок
+ бессмысленном усложнении кода ПНС.
3. Больше того, возникает явная ПРОБЛЕМА С БЕЗОПАСНОСТЬЮ, связанная с наличием самой
возможности изменять заголовок. А именно, нельзя «кому-попало» позволять влиять на
работоспособность изделий. А значит, не может «кто-попало» предписывать(навязывать)
структуру прошивок. Разработчик ПНС учитывает наличие зависимостей в коде.
«Кто-попало» даже не знает о зависимостях и не отвечает за последствия.
А если последствия наступят?

ВЫХОДИТ, МЫ САМИ ДАЛИ КОМУ-ПОПАЛО ВОЗМОЖНОСТЬ ВНОСИТЬ БАГИ В НАШИ ПНС?!

/// @page 10
В итоге, отвечать разработчику, ответственность на МЦСТ, а «кто-попало» ни при чём.

Ниже дан краткий анализ возможных сценариев развития событий и обзоры реализаций
предполагаемых алгоритмов.

/// ==================================================================================
/// @~ §6 Комбинатор + Partition Table + Full MTD-FS. Перспективы/риски/недостатки
/// ==================================================================================
Данный вариант Комбинатора не считается основным. Он самый ТРУДОЗАТРАТНЫЙ из всех
возможных сценариев и не отвечает стандартам Linux.

Этот вариант Комбинатора, как и алгоритм обработки в загрузчике заголовка Комбинатора,
может быть реализован на более поздних стадиях развития проектов ПНС V6. Однако шанс
на появление у нас потребности в таком Комбинаторе, IMHO, минимален.

Итак, у Комбинатор໧6″ две задачи: а) каждый раз при создании/генерации любой новой
прошивки получать от оператора полное описание метаданных и б) поддерживать для
управления флэш-памятью полную MTD-среду + все файловые системы Linux. Для этого:
1) Комбинатор должен работать под Linux (такой код еще нужно апробировать/создать)
или 2) Комбинатор должен работать, как Linux, т.е. прямо в него должны быть встроены
все нужные, как у Linux, возможности MTD.
При этом каждый оператор должен знать/изучить синтаксис описания мета «mtdparts».

Понятно, что вариант 1) тяжело эксплуатировать + еще нужно создать, а вариант 2)
практически не реализуем. Тем не менее, проанализируем 1-ый вариант работы Комбинатора
с полной поддержкой MTD-FS («Full MTD-FS») под Linux.

/// ———————————————————————————
/// @~ §6.1 ВВОД METADATA
/// ———————————————————————————
Окно Комбинатора содержит обязательное поле EditBox для отображения/редактирования
строки мета ( вкупе с кнопкой «Take» и списком всех поддерживаемых в Linux MTD-FS ).
Оператор указывает/выбирает в списке любую MTD-FS, как опорную/нужную для работы ПНС.
При запуске Комбинатор очищает поле ввода в EditBox и читает метаданные, если они
есть, из своего заголовка на флэш ВУ (если он есть) и отображает метаданные в поле
ввода EditBox.

Оператор может задать в поле ввода EditBox:
— совершенно новые произвольные метаданные, необходимые для работы опорной MTD-FS;
— или отредактировать метаданные, считаные из заголовка Комбинатора (если он есть).

Метаданные в поле ввода EditBox должны включать мета-строку «mtdparts». Каждый раздел в
«mtdparts» (кроме «root») будет содержать один файл в опорной MTD-FS или одну сущность
загрузки в «raw»-разделе, которая нужна для работы ПНС и включена разработчиком ПНС в
раздел. Для старых машин «mtdparts» ядру не передаётся.

При таком подходе все сущности загрузки, находящиеся в сырых или опорных FS-разделах,
будут иметь одинаковые фиксированные смещения и у данных и у «patrdef»-метаданных
(если они есть), относительно начала текущего раздела-контейнера. В общем случае «§6″
эти смещения будут отличаться у разных FS и это нужно запомнить в «Partition Table».
В случае «§8″ (см. ниже) этого делать не нужно. При любых ошибках оператору выдаются
предупреждения. Оператор может указать правильный с его точки зрения вариант.

По клику на кнопку «Take» выводится «рабочий-список» всех компонентов, найденных у
текущей ПНС в виде пар: «имя компонента» и «путь к данным».

Оператору требуется в ручном режиме выбрать и указать каждый нужный «путь к данным».
Если данные находятся на USB-носителе, то потребуется вставить ВУ, mount и т.д.

Данные могут быть в «паутине», как это организовано в большинстве общепринятых случаев.
Например, тут /** @see https://downloads.cpp.canon/ProductDownloads/Index/595) */

Если нам придется взаимодействовать со сторонними пользователями аналогичным или
похожим образом, то оператору придется выполнить действия, связанные с доступом к
WEB-ресурсу и загрузкой данных по сети «Internet».

Далее Комбинатор проверяет наличие и корректность данных по указанным путям и на флэш
(в соответствии EditBox). При ошибках оператору может быть предложено стереть данные
во флэш-памяти.

/// @page 11

Если данные на флэш не корректны и/или их расположение не отвечает EditBox,
то на флэш «§6.2″ нужно создать разделы,
иначе на флэш «§6.3″ можно обновлять компоненты.

При любых коллизиях Комбинатор вступает в диалог с оператором и/или выдаёт на экран
предупреждения, отвечающие ситуации. Оператор указывает правильный вариант работы.
Вся ответственность за выбор верного сценария действий возлагается на оператора.

/// ———————————————————————————
/// @~ §6.2 Создание разделов
/// ———————————————————————————
Режим создания разделов на флэш ВУ (по концепции работы сценария «§6″) доступен
любому пользователю и разработчику ПНС.

Запускается ПНС с «default» параметрами, которая передаёт в Linux мета «mtdparts»
из EditBox. После запуска Linux вызывается Комбинатор, в среде которого выполняются
действия по созданию разделов опорной MTD-FS и/или «RootFS» для микро ОС, аналогичные
описанным пунктах «§2.5″ и «§2.6″. Создание разделов выполняется по схем廧6″ обычно
в ручном режиме диалога с оператором.

/// @~ ЗАМЕЧАНИЕ. Для выполнения действий по созданию опорных разделов и RootFS в
/// сценарии «§6″ можно поддержать некий ограниченный размерами разделов и типами
/// FS пакетный режим. Hо тогда сценарий «§6″ тихо мигрирует в сценарий «§8″, что
/// говорит об изначальной предпочтительности последнего.

При любых коллизиях оператору выдаются предупреждения. Оператор указывает правильный
сценарий работы. Вся ответственность за выбор верного сценария работы возлагается на
оператора.

ЗАМЕЧАНИЕ. По условиям сценария «§6″ число разделов и FS, типы FS, размеры файлов, их
имена и иные данные заранее неизвестны. Метаданные задаются вручную и читаются из поля
EditBox. Поскольку метаданные произвольны, то и реализация обработки такой произвольной
информации, как общего случая, представляется крайне сложной.

При этом могут возникнуть разные обременения, типа: отсутствие поддержки нашим ядром
указанных FS, ошибки их поддержки в текущей MTD, отсутствие документации, отсутствие
примеров аналогичных реализаций или плохая ПОРТИРУЕМОСТЬ кода аналогов и пр.

В результате реализация общего случая обработки может занять достаточно много времени.
И что совсем печально, даже если запрограммировать некий урезанный общей случай, ручной
ввод данных все равно будет каждый раз необходим при эксплуатации сценария «§6″.
/// @~ По завершению создания разделов содержимое EditBox сохраняется в заголовке.

После этого оператору при помощи Комбинатора нужно разобрать вновь созданную прошивку
на составляющие в виде бинарных файлов для последующих сборок. Оператору надо в ручном
режиме указать пути для сохранения и затем сохранить нужные части прошивки: RAW и FS
разделы + все файлы (блоки прошивки) в указанных местах.

Действия по созданию разделов оператор будет вынужден повторять каждый при создании
прошивки или если на флэш нет «firmware». То есть всегда при генерации новой версии
прошивки и оператору и разработчику потребуется выполнять большой объём ручной работы.

/// ———————————————————————————-
/// @~ §6.3 Обновление компонентов
/// ———————————————————————————-
Комбинатор под Windows для поддержки MTD-FS требует доработки, а Комбинатор под Linux
еще нужно создать и отладить. В этом контексте рассмотрим схему обновления компонентов
только для Комбинатора под Windows, а функционал обновления компонентов под Linux пока
вынесем за скобки (его детальный обзор дан в «§8.3″, см. ниже). Итак:

Комбинатор рассчитан на общий случай и состав компонентов ему заранее неизвестен.
Комбинатор не знает, что найдет у источника, какой длины будет список, какие в нём
будут сущности, как они называются, какие у них ТТХ: bus, раздел, размер, тип/вид,
смещение и пр. ТТХ метаданных зависит от кода текущей ПНС и сложившейся конъюнктуры.

У выбранных компонентов в «рабочем-списке» оператор задает пути к данным и нажимает
на кнопку «Прошить», а Комбинатор записывает на флэш-память все выбранные оператором
компоненты по адресам, отвечающим мета-параметрам в «mtdparts».

/// @page 12
/// ———————————————————————————
/// @~ §6.4 Рассмотрим узловые моменты
/// ———————————————————————————
1. Мы внедряем MTD-FS. Сегодня это мейнстрим при разработке ПНС. Но заметим, что за
разумный срок Комбинатор с поддержкой MTD-FS запросто не создашь. В среде Windows
работа Комбинатора с MTD-FS скорее всего просто невозможна.

При этом Комбинатор под Windows — у нас штатный вариант работы, а гипотетический
Комбинатор с MTD-FS еще не создан.

2. Отсюда риторический вопрос «Ждать ли нашим ПНС доработки Комбинатора до уровня
MTD-FS с поддержкой всей номенклатуры файловых систем, ну или хотя бы поддержки
текущих выбранных файловых систем (как опорной «RomFS» и «JFFS2″ как RootFS)?»

ПРАВИЛЬНО — НЕТ. IMHO, ОТ ЛЮБЫХ ДОРАБОТОК КОМБИНАТОРА (ТЕМ БОЛЕЕ СЛОЖНЫХ) СОЗДАНИЕ
ПНС МЦСТ ВООБЩЕ НЕ ДОЛЖНО ЗАВИСЕТЬ!

3. Но давайте предположим, что мы дождались и получили в руки Комбинатор с MTD-FS.
Однако и у этого, казалось бы, образцового варианта есть свои проблемы и недостатки.

В частности, для работы такого Комбинатора, несомненно, нужен Linux. А если Linux не
запускается? Конечно, мы можем создать новую прошивку и на другой аналогичной машине!
Но тогда нужно иметь две машины. А что делать пользователю, если второй машины нет?

Вспомним, что «User» может иметь Комбинатор под Windows. Это ‘+’ или ‘-’? Конечно ‘+’.
Зато теперь у него сразу 2 Комбинатора (под Windows и Linux) и оба надо устанавливать
«это всегда удобно и приятно», да еще ставить на разные ОС и, как водится, на разные
машины. В итоге у нашего клиента уже есть (или надо) три машины, два Комбинатора и
куча знаний и инструкций про них. Не много ли нужно Комбинаторов, машин и знаний?

Итак, что мы имеем: сложность создания Комбинатора, большой объём ручной работы (при
создании разделов, FS, файлов) + зависимость разработки ПНС от самого Комбинатора и
его капризов + придётся устанавливать сразу два Комбинатора, требуется несколько ОС
и машин. А если стерли флэш? А это нужно и нередко бывает для устранения эффектов в
работе программатора «DediProg». И если нет под рукой файла с полной прошивкой, то
клиенту потребуются знания синтаксиса + семантики строки «mtdparts», а затем долгий
ручной процесс создания и/или восстановления «firmware» и её мета.

Все это нетехнологично, долго, неудобно. Кроме того, при большом объёме ручной работы
человеческий фактор никуда не уйдет и обязательно скажется, и ошибки будут сделаны 100
%. А наша цель, чтобы все было технологично, удобно, быстро и желательно без ошибок.
А получилось наоборот — проблемы остались, а цель не достигнута!

/// ==================================================================================
/// @~ §7 ПНС + Комбинатор. Flash Image Tool и Boot в одном флаконе
/// ==================================================================================
Но есть решения, позволяющие добиться поставленной цели (они внедряются). А именно:
№1. Мы отказываемся от индивидуальности при организации отдельных прошивок семейства.
Отказ от индивидуальности позволяет избежать массы проблем и добиться успеха там где
это реально нужно. «№1″ относится к тому типу решений, какие нужно принять 1 раз, и
если кто-то другой сделал это за вас, тем лучше. Кроме повышения скорости разработки,
подобные решения снижают порог вхождения для пользователей. Им даже не нужно знать,
почему все сделано именно так. В то же время, когда сторонний разработчик хорошо
понимает, как все устроено, ему проще оценить стоит ли менять структуру прошивок.
№2. ПНС переходят на MTD-стандарт и отказываются от заголовка Комбинатора, а может и
от самого Комбинатора. В итоге, упрощается и формализуется код ПНС. Одновременно в
ПНС внедряется облегчённая поддержка MTD-FS и нужные файловые системы.
№3. ПНС V6 умеют прошивать флэш и читать файлы с блочных ВУ. Эта линия развивается и
создаются функции чтения файлов из папок на HDD/USB-носителях и записи файлов (*.json,
«uOS», «DevTree» и пр.) во флэш-память прямо в среде ПНС в «Raw»/»RomFS» в разделы.
По трудозатратам (все перечисленные и им подобные) доработки в ПНС сделать в 100-крат
легче, чем любые правки Комбинатора или двух Комбинаторов.
№4. В случае идетичности структур у всех прошивок семейства ПНС V6 будет автоматически
создавать/восстанавливать разделы «RomFS» и «json» файлы при их отсутствии на ВУ.
В итоге получаем ПНС + FIT «в 1-ом флаконе» и все их возможности в буте: и инструмент
формирования образа прошивки; и интерфейс настройки параметров ПНС; и функции начальной
загрузки системы. При этом клиенту уже не нужны ни Linux, ни Windows, и не требуется
«сакральных» знаний о метаданных «firmware», плюс трех машин и/или двух Комбинаторов.
Фактически нужен только программатор «DediProg» (если на флэш нет бута) и нужный файл
(или файлы компонентов) для прошивки.
/// @page 13
Но если услуги Комбинатора не востребованы, зачем нам тогда вообще Комбинатор?
Как тамагочи для его обслуживания и пожирания им ресурсов? Ну ладно. Предлагается
компромисс: давайте оставим на откуп Комбинатору лишь доступ к контроллеру BMC.
Но тогда это уже не «Комбинатор», а скорее сервис-менеджер BMC.

/// =================================================================================
/// @~ §8 Комбинатор без Partition Table (Linux стандарт) + Light MTD-FS
/// =================================================================================
Этот вариант работы Комбинатора основной и должен быть реализован в первую очередь.
Данный вариант Комбинатора работает по схеме решения «§7″ и полностью отвечает всем
существующим на данный момент стандартам Linux. У Комбинатор໧8″ две задачи:
1. Облегчённая поддержка MTD-FS + опорной файловой системы «RomFS» под Windows при
обновлении компонентов у текущей ПНС.
2. Управление флэш-памятью под Linux при создании прошивки для нового (или смене
пространственно-адресной структуры «firmware» у существующего) семейства машин.

Подход Комбинатор໧8″: взять из кода ПНС строку «mtdparts» и, на основании полученных
мета, разместить указанные в «mtdparts» сущности по их ФИЗАДРЕСАМ, сформированным из
мета. При этом, в соответствии с Linux-стандартом, никаких «Partition Table» во флэш-
памяти не создаётся. ТО ЕСТЬ, ЭТОТ КОМБИНАТОР — ПРОСТО УМНЫЙ ПРОГРАММАТОР.

Доработка Комбинатора до уровня умного программатора не потребует долгих и сложных
правок его исходного кода. Следовательно, обновление Комбинатора до состояния работы
без заголовка плюс решение задач 1. и 2. может быть успешно выполнено силами одного
подразделения: «Разработка программы начального старта (загрузчик)».

Проанализируем работу Комбинатор໧8″ с Light-поддержкой MTD-FS и без раздела.

/// ———————————————————————————
/// @~ §8.1 ВВОД METADATA
/// ———————————————————————————
Окно Комбинатора содержит два обязательных поля:
— TextBox для отображения строки метаданных (вкупе с кнопкой «Take»);
— «BootCodePath» для задания пути к .bin прошиваемого кода ПНС.

При запуске Комбинатор очищает поле TextBox и читает метаданные (если они есть) из
сигнатуры «BootCode» на флэш (если найдена) и отображает метаданные в поле TextBox.
Сигнатура у любой ПНС находится по константному смещению для всех семейств.

Оператор может указать путь к .bin кода ПНС посредством «BootCodePath». В этом случае
Комбинатор ищет в нём мета и проверяет их на согласованность с TextBox. При конфликте
оператор должен выбрать правильный вариант метаданных, который и будет отображён в
TextBox. Если был конфликт и был выбран вариант «BootCode», то код ПНС заданный
в «BootCodePath» игнорируется, а «BootCodePath» становится невидимым.

При любых конфликтах оператору выдаются предупреждения. Оператор указывает правильный
вариант. При клике по «Take» выводится «рабочий-список» всех компонентов, найденных у
текущей ПНС в виде пар: «имя компонента» и «путь к данным» и проверяется наличие и
корректность данных на флэш (в соответствии TextBox) и по указанным путям. При ошибках
оператору может быть предложено стереть данные на флэш.

Если данные на флэш некорректны и/или их расположение не отвечает TextBox,
то на флэш «§8.2″ нужно создать разделы,
иначе на флэш «§8.3″ можно обновлять компоненты.

Вся ответственность за выбор того или иного варианта действий возлагается на
оператора.

/// ———————————————————————————-
/// @~ §8.2 Создание разделов с оптимизацией кода ПНС на этапе компиляции
/// ———————————————————————————-
Режим создания FS-разделов на флэш ВУ пользователю недоступен и является инструментом
разработчика ПНС. Запускается скрипт «./config_{имя семейства} mtdparts.conf», который
собирает мета-строку «mtdparts». Нужная организация прошивки заранее предопределяется
разработчиком в файле «mtdparts.conf» в «json»|»ini» формате. Пример «mtdparts.conf» в
«ini» формате в «Приложение#1″. На базе «mtdparts.conf» для «Makefile.{имя семейства}»
создаются файлы с переменными среды. Скрипт «config_{имя семейства} …» демонстрирует
разработчику созданную строку «mtdparts». Если ошибок и проблем нет, то запускается
«Makefile.{имя семейства}» и «КОМПИЛИТСЯ» код ПНС. Код новой ПНС с помощью «DediProg»
записывается во флэш.
/// @page 14
Затем запускается ПНС с параметрами по умолчанию, которая передаёт в Linux новые мета
«mtdparts». После запуска ОС она запускает Комбинатор. Последний в пакетном режиме
выполняет действия, аналогичные уже описанным в параграфах «§2.5″+»§2.6″ для создания
разделов: «RomFS» (она выбрана, как опорная для ПНС) и «JFFS2″, как RootFS для Linux.

/// @note Действия по созданию разделов могут по приказу оператора выполняться и
/// в диалоговом режиме.
Затем оператор с помощью Комбинатора может разобрать вновь созданную прошивку на части
/составляющие в виде бинарных конфигураций разделов для последующих сборок. Полученные
конфигурации могут быть сохранены в независимых файлах, что исключает необходимость
всякий раз повторять одни и те же действия.

Для семейства ПНС, устроенных по схеме «§7″, задание структуры «firmware» разработчик
может выполнить единственный раз. Делать это повторно придётся только, если он принял
решение кардинально изменить пространственно-адресную структуры «firmware» семейства,
т.е. лишь тогда, когда ему нужно поменять/изменить адреса у разделов MTD-FS. В рабочем
режиме меняется только содержимое файлов (настройки загрузки) и/или добавляются файлы
(сущности загрузки) через консоль бута или с помощью утилиты Linux «genromfs».
/// @see https://www.opennet.ru/man.shtml?topic=genromfs&category=8&russian=2

При этом адреса разделов (контейнеров) в обычном режиме неизменны.
/// @note
/// 1. Де-факто концепция работы схемы «§8″ опирается на то обстоятельство, что смена
/// пространственно-адресной структуры прошивок семейства выполняется в крайнем
/// случае. За 4 года разработки ПНС V6 этого не случалось еще ни разу.
/// 2. Семантику строки «mtdparts» определяет разработчик ПНС. Точнее и надёжней чем он,
/// никто это сделать не может. При этом нужно избавить разработчика от необходимости
/// каждый раз задавать строку «mtdparts» в Комбинаторе вручную. Мета по схеме «§8″
/// уже и так есть в коде. Через файл «mtdparts.conf.ini» их задал сам разработчик.
/// 3. Пользователей тоже нужно избавить от необходимости каждый раз задавать/создавать
/// конфигурацию прошивок. Конфигурирование семейства — это задача разработчика ПНС.
/// 4. Т.к. пространственно-адресная структура прошивок у семейства не меняется, то при
/// включении новой ПНС в состав семейства не нужно выполнять действия по ручному
/// созданию разделов, ибо заготовки разделов уже давно созданы и есть под рукой.
Оператор не должен строить прошивку за разработчика. Задача оператора — уточнять и
обновлять настройки. При любых коллизиях оператору выдаются предупреждения. Оператор
задаёт нужный вариант работы. Вся ответственность за выбор возлагается на оператора.

/// ————————————————————————————
/// @~ §8.3 Обновление компонентов
/// ————————————————————————————
Обновление компонентов под Windows выполняется аналогично схеме «§6.3″ (см. выше), но
с той лишь разницей, что заголовок Комбинатора отсутствует.
В рамках концепци軧8″ Комбинатор под Linux вообще не нужен. Все действия по обновлению
компонентов могут быть просто выполнены прямо в среде Linux. Приведём в качестве примера
варианты обновления компонента «dflt.json» (настройки загрузки по умолчанию) для ПНС V6:
1. genromfs -d ./dflt.json -f /dev/mtd1
2. genromfs -d ./dflt.json -f /tmp/image.dflt.json
dd if=image.dflt.json of=/dev/mtd1

/// ————————————————————————————
/// @~ §8.4 В чем фундаментальное различие между сценариями «§6″ и «§8″?
/// ————————————————————————————
ПНС по концепции «§6″ может опираться на любую опорную FS и имеет произвольно-переменную
структуру прошивки. ПНС по сценарию «§8″ опирается на «RomFS» и имеет фиксированную
структуру прошивки. Опишем это на псевдокоде: if (ПНС на флэш нет), то switch (сценарий)
{ case «§6″: Из формируемых блоков-данных создаётся новая прошивка с ручным обременением
case «§8″: Нужные файлы раскладываются по готовым полкам конфигурации семейства
} По сценарию «§8″:
1. Упрощается код ПНС.
2. Объем ручной работы минимален (конфигурирование семейства выполняется один раз).
3. Разделы пользователям создавать не надо.
4. Размер полной работоспособной минимально-достаточной прошивки ПНС V6 = 5 МБ.
5. Комбинатор для обновления компонентов прошивки не нужен.
6. Сломать прошивку путем модификации её структуры пользователь не может.
По сценарию «§6″:
1. Усложняется ПО и увеличивается объем кода ПНС.
2. Большой объем ручной работы (конфигурирование выполняется для каждой новой ПНС).
3. Для новых ПНС конфигурацию прошивок нужно задавать/создавать заново.

/// @page 15
4. Размер полной работоспособной минимально-достаточной прошивки = 16 МБ.
5. Создание прошивок привязано к Комбинатору и невозможно без него.
6. «Кто-попало» может сломать прошивку за счет некорректной правки заголовка.

Конечно, можно зафиксировать некий полный образ прошивки в 16 МБ, как эталон.
Но тогда адресная семантика у заголовка не меняется. И схема «§6″ превращается
в схему «§8″, где принципиально не используется заголовок Комбинатора.

Отсюда, извечный вопрос — зачем нужен «заголовок и его Комбинатор»? Выбирайте:
Ответ 1: чтобы клиенты упражнялись в эпистолярном жанре при создании прошивок.
Ответ 2: чтобы пользователи могли сломать прошивку.
Ответ 3: чтобы бессмысленно занять место на ВУ и увеличить размер полной ПНС до 16 МБ.
Ответ 4: чтобы бесполезно увеличить объём ПО за счет кода Комбинатора.
Ответ 5: чтобы бесцельно усложнить бут за счет функций, отвечающих за заголовок.

/// =================================================================================
/// @~ §9 Комбинатор без поддержки MTD-FS, но имеющий Partition Table
/// =================================================================================
Данный вариант Комбинатора не считается основным, т.к. не отвечает стандарту Linux.

Этот тип Комбинатора не работает с файлами в MTD-FS контейнерах. Его первая задача:
принять от оператора строку метаданных и сохранить её в своём заголовке.

Его задача номер два: разместить по сформированным на основании метаданных ФИЗАДРЕСАМ
указанные оператором сущности. Размещение безусловное, даже если потом при запуске ПНС
будут найдены ошибки такого размещения.

ПНС при запуске ищет заголовок Комбинатора на флэш и, если его находит, то сверяет
полученные метаданные со своим пониманием. И если были обнаружены противоречия, то
процесс загрузки приостанавливается и дальнейшие решения о продолжении работы или
остановке процесса загрузки принимает оператор.

При этом в отличие от решения «§7″, если ПНС детектировала НЕВАЛИДНОСТЬ метаданных, то
создание/восстановление мета и разделов опорной FS в буте невозможно по концептуальным
причинам, т.к. указанная в заголовке структура ПНС считается правильной, а у самой ПНС
- нет. Максимум, что может сделать оператор, это попытаться вернуться к «default»
параметрам работы загрузчика. Однако полнота функционала ПНС в этом случае отсутствует.

Создание Комбинатора лишь с разделом под метаданные и без поддержки MTD-FS особого
смысла не имеет. Поэтому этот сценарий работы Комбинатора мы вынесем за скобки и
рассматривать, как основу для разработки, не будем.

/// =================================================================================
/// @~ §10 Работа ПНС, созданных по сценарию «§6″
/// =================================================================================
Задача ПНС — обеспечить поддержку MTD-FS (с учётом всех зависимостей) для дальнейшей
корректной работы MTD, файловых систем Linux и самой Linux после запуска.

Текущие метаданные передаются из ПНС в Linux через параметр «mtdparts», как это и
предусмотрено стандартом MTD. При этом «mtdparts» берётся из заголовка Комбинатора.
А наличие заголовка Комбинатора на ВУ — это нарушение стандарта MTD.
ПНС, построенные по сценарию «§6″, концептуально хранят свои метаданные в разделе
Комбинатора. Они рассчитаны на заранее неизвестную произвольно-переменную структуру
прошивки. А значит, должны при 1-ом пуске новой ПНС сначала создать разделы опорной
FS с данными по умолчанию (какие задал разработчик ПНС или назначил оператор).

Т.е. эта процедура ОБЯЗАТЕЛЬНА для 1-го пуска. Таков принцип работы ПНС по сценарию
«§6″. При 1-ом запуске ПНС, построенная по сценарию «§6″, выполняет сценарий «§6.2″,
и создаются разделы опорной FS. Лишь затем становится возможной штатная работа ПНС и
загрузка ОС. Для доступа ПНС и FIT к содержимому FS-разделов, в том числе к файлам в
опорной FS, заголовок Комбинатора включает данные мета-строки «mtdparts» (см.»§6.1″).
MTD-мета должны быть получены/сформированы еще на этапе выполнения сценария «§6.2″.

Второй файловый раздел «RootFS» — это уже епархия микро ОС. Данные «RootFS» на работу
загрузчика не влияют. При первом пуске «RootFS по умолчанию» автоматически создает
сама «uOS» (или ПНС в зависимости от текущей прошивки).

По ходу загрузки ПНС проверяет правильность и согласованность всех используемых данных.
При возникновении любых проблем в работе ПНС на экран выдаются аварийные сообщения.

/// @page 16
/// =================================================================================
/// @~ §11 Работа ПНС, созданных по сценарию «§8″
/// =================================================================================
Задача ПНС не дублировать возможности Linux, а обеспечить light-поддержку для MTD-FS
(с учётом всех зависимостей) для дальнейшей корректной работы MTD, файловых систем
«RomFS» (как опорной), «jFFS2″ (как RootFS) и самой Linux после запуска.

Текущие метаданные передаются из ПНС в Linux через параметр «mtdparts», как это и
предусмотрено стандартом MTD. При этом сам «mtdparts» берётся из сигнатуры бута.
Также может быть создан некий гибридный вариант ПНС»§8+6″. Такая ПНС будет искать,
а затем сканировать заголовок Комбинатора, если он есть на ВУ. В случае расхождения
в семантиках заголовка и ПНС дальнейшая загрузка становиться невозможной.

При первом пуске ПНС, построенная по сценарию «§8″ (без заголовка Комбинатора), уже
автоматом «из коробки» имеет разделы «RomFS» (как опорной) с настройками загрузки по
умолчанию. Разделы «RomFS» созданы заранее разработчиком ПНС еще на этапе генерации
«firmware» семейства с соблюдением всех MTD-FS зависимостей, присущих этому типу ПНС.

/** @note Два замечания относительно использования заголовка и организацию прошивок.
Посмотрим на применение/наличие/отсутствие заголовка Комбинатора с другой стороны:
1. Каждое семейство машин имеет собственную структуру/организацию разделов firmware.
Зашивать код ПНС из одного семейства во флэш-память машины, принадлежащей к другому
семейству нелепо, ибо все равно работать не будет. Поэтому, как только мы позволяем
работу FS (запрещаем конкатенацию и перемещение разделов в Комбинаторе), структура
прошивок машин одного семейства может быть условно зафиксирована, а мета переведены
в разряд условно-постоянных констант и стать известны и доступны в коде ПНС.

2. Когда условно-постоянные мета уже зашиты в код ПНС, исчезает смысл использования
заголовка Комбинатора. Отказ от заголовка упрощает код ПНС и чуть ускоряет загрузку.
Но ещё важнее — позволяет единожды создать MTD-FS разделы для всех машин семейства,
что фактически избавляет и пользователей и разработчиков от необходимости выполнять
большой объем ручной работы по конфигурированию прошивок. */

Для доступа FIT к файлам в разделах «RomFS» сигнатура ПНС включает строку «mtdparts»
(см. «§6.1″).

Строка «mtdparts» должна быть создана/сформирована заранее перед самым 1-ым пуском ПНС,
ещё при компиляции её кода. При этом (и поэтому), строка «mtdparts» собирается «LCC»
автоматически при ПРЕПРОЦЕССИРОВАНИИ из отдельных метаданных. В дальнейшем никакого
разбора строки «mtdparts» в ПНС уже не требуется.

Второй файловый раздел «RootFS» — это уже епархия микро ОС. Данные «RootFS» на работу
загрузчика не влияют. При первом пуске «RootFS по умолчанию» автоматически создает сама
«uOS» (или инициализирует ПНС в зависимости от кода текущей прошивки). По ходу загрузки
ПНС проверяет правильность и согласованность всех используемых данных.
При возникновении любых проблем в работе ПНС на экран выдаются аварийные сообщения.

/// ==================================================================================
/// @~ §12 Преимущества ПНС при внедрении сценария «§8″
/// ==================================================================================
- в проекты ПНС МЦСТ внедряется облегчённая поддержка MTD-FS;
- в проекты ПНС МЦСТ внедряется облегчённая поддержка файловой системы «RomFS»;
- разделы «RomFS» по умолчанию будет создаваться ПНС автоматически;
- раздел «RootFS по умолчанию» будет создаваться автоматически;
- Комбинатор дорабатывается до уровня умного программатора и больше не меняется;
- потребуется минимум доработок ПНС и Комбинатора, которые мы сможем сделать сами;
- не нужно ждать окончания доработок Комбинатора. Создание ПНС идет своим ходом;
- получим все функции ПНС + Комбинатор «в одном флаконе» — в буте;
- Комбинатор не нужен. Нужен менеджер BMC;
- Утилита обновления FRUID не нужна. FRUID будет обновляться прямо в буте;
- уменьшается фрагментация адресного пространства и число разделов на ВУ;
- повышается скорость загрузки;
- упрощается процедура генерации и тиражирование образов «firmware»;
- повышается живучесть/устраняется человеческий фактор и возможность внесения ошибок;
- упрощается процесс эксплуатации ПНС;
- понижается порог вхождения в наши проекты для пользователей;
- формализуется процесс разработки загрузчиков;
- сокращаются трудозатраты и время разработки.

/// @page 17
Таким образом, в ПНС МЦСТ внедряется общий случай + свобода при реализации проектов
ПНС для нас и сторонних разработчиков, причем в полном соответствии с FS и MTD-FS
стандартами Linux, что обеспечит апробированную функциональную гибкость при описании,
разработке, внедрении и тиражировании различных программ начального старта.

/// ====================================================================================
/// @example Приложение#1. Унификация настройки «mtdparts.conf» в .ini файле
/// ====================================================================================
# ФОРМАЛИЗАЦИЯ НАСТРОЙКИ СТРОКИ «MTDPARTS». Задание структуры прошивки в формате ini для
# любого семейства машин с сохранением всех преимуществ предопределения разделов. Пример
[SPI]
# mtd-id описание SPI-чипа флэш-памяти
chip = «MT25QU512″
bus = 0
cs = 0

[boot.raw]
# Сырой раздел с кодом бута
ro = 0
max_size = 0x4A0000

[dev3.raw]
# Сырой раздел DevTree
source = «devtree/$(ARCH)/$(IMAGE).devtree»
#offset = 0x4A0000
max_size = 0×010000

[dflt.RomFS/dflt.json]
# Раздел RomFS с файлом настроек параметров бута по умолчанию
max_size = 0×020000

#[dflt.json] — файл с параметрами бута по умолчанию
source = «micro_os/boot_dflts.json»
offset = 0x4B0020
#max_size = 0x01FFE0

[work.RomFS/work.json]
# Раздел RomFS с файлом настроек рабочих параметров загрузки
max_size = 0×010000

#[work.json] — файл с текущими параметрами бута, установленными оператором ПНС
source = «micro_os/boot_params.json»
offset = 0x4D0020
#max_size = 0x00FFE0

[s3s4.raw]
# Сырой раздел с данными настройки PHY-DDR4 при выходе из гибернации
source = «micro_os/os_params.dat»
#offset = 0x4E0000
max_size = 0×020000

[u_os.raw]
# Сырой раздел с кодом Микро-ОС
#offset = 0×500000
source = «micro_os/zImage.dat»
max_size = 0xA00000

[root.jFFS2]
# Раздел jFFS2 с RootFS с файлами Микро-ОС
#offset = 0xF00000
source = «micro_os/root_fs.dat»
max_size = «-»

/// =================================================================================
/// @example Приложение#2. Пример определения MTD-разделов в коде ядра Linux
/// =================================================================================
Пример исходника некого ядра в файле «arch/arm/mach-omap2/board-omap3beagle.c»,
определяющем флэш-разделы в ядре для платы Beagle:
/// @see https://stackoverflow.com/questions/8585864/nand-partitioning-in-u-boot

/// @page 18
static struct mtd_partition omap3beagle_nand_partitions[] =
{ /// CONFIG_MTD_PARTITIONS: All sizes are listed in terms of NAND block size
{ .name = «X-Loader»,
.offset = 0,
.size = 4 * NAND_BLOCK_SIZE,
.mask_flags = MTD_WRITEABLE, /* force read-only */
},

{ .name = «U-Boot»,
.offset = MTDPART_OFS_APPEND, /* Offset = 0×80000 */
.size = 15 * NAND_BLOCK_SIZE,
.mask_flags = MTD_WRITEABLE, /* force read-only */
},

{ .name = «U-Boot Env»,
.offset = MTDPART_OFS_APPEND, /* Offset = 0×260000 */
.size = 1 * NAND_BLOCK_SIZE,
},

{ .name = «Kernel»,
.offset = MTDPART_OFS_APPEND, /* Offset = 0×280000 */
.size = 32 * NAND_BLOCK_SIZE,
},

{ .name = «File System»,
.offset = MTDPART_OFS_APPEND, /* Offset = 0×680000 */
.size = MTDPART_SIZ_FULL,
},
}; /// @~ For CONFIG_MTD_PARTITIONS — драйвер отображения платформы.

/// =================================================================================
/// @example Приложение#3. Пример создания пустой файловой системы
/// =================================================================================
Создание пустой файловой системы (чистого раздела) с jFFS2.

Для работы с jFFS2 потребуется установить mtd-tools:
$ sudo apt-get install mad-tools
flash_erase -j /dev/mtd6 0 0
mount -t jffs2 mtd6 /mnt

/// =================================================================================
/// @example Приложение#4. Пример создания образа файловой системы
/// =================================================================================
Создание образа jFFS2, если есть уже готовая FS, делается следующей командой:
$ mkfs.jffs2 -p -d /директорий/с/файлами/ -e 128KiB -n -o rootfs_jffs2.bin
$ sumtool -n -e 0×20000 -p -i -/rootfs_jffs2.bin -о -/rootfs_jffs2_sum.jffs2

Монтирование созданного образа jFFS2:
$ sudo modprobe -v mtd
$ sudo modprobe -v jffs2
$ sudo modprobe -v mtdram total_size=256000 erase_size=256
$ sudo modprobe -v mtdchar
$ sudo modprobe -v mtdblock
$ sudo dd if=//rootfs_jffs2.bin of=/dev/mtdblock0
$ sudo mkdir /mnt/jffs/
$ sudo mount -t jffs2 /dev/mtdblock0 /mnt/jffs/

Упаковать данные в новую папку:
$ tar -C «FolderSrc» -cf — . | tar -C «FolderDst» -xvf –

Отключение:
$ sudo umount /mnt/jffs
$ sudo modprobe -r jffs2
$ sudo modprobe -r mtdram
$ sudo modprobe -r mtdblock
$ sudo rmdir /mnt/jffs
$ sudo rm /dev/mtdblock0
/** @see https://ru.bmstu.wiki/index.php?title=jFFS2_(Journaling_Flash_File_Syste
m_version_2)&mobileaction=toggle_view_mobile */

/// @page 19
/// ==================================================================================
/// @example Приложение#5. Реальные примеры устройств с MTD-FS.
/// ==================================================================================
Формат примеров [ изделие ]( файловая система )[ https/http ссылка ][комментарий]:

[Роутер TP-Link](SquashFS)[openwrt.org/ru/docs/techref/flash.layout]
[Linux ресивер](UbiFS)[sat.com.ru/stati/obzor-sputnikovogo-linux-resivera-sezam-marvel]
[ARM-планшет ](EXT4 )[4pda.to/forum/index.php?showtopic=544998&st=300]
[Android ](EXT4 )[hotmcu.com/wiki/RK3066_partitions]
[Одноплатный ПК](UbiFS)[habr.com/ru/post/470519]
[WiFi IP камеры](SquashFS)[4pda.to/forum/index.php?showtopic=807259&st=200]
[IP камера](RomFS/CramFS/jFFS2)[itunedvr.ru/forum/phpBB3/viewtopic.php?t=876]
[Регистратор](RomFS)[forum.videon.spb.ru/viewtopic.php?f=24&t=11280&start=48]
[FPGA](RomFS/CramFS/jFFS2)[lists.denx.de/pipermail/u-boot/2010-June/073182.html]
[MTD Manual](CramFS/jFFS2)[dmilvdv.narod.ru/Translate/ELSDD/elsdd_registering_mtd_info.html]
[NAS Server](jFFS2)[rtsoft.ru/upload/pdfcat/AM4530_T5518_Manual_v1_2.pdf]
[Net Attached Storage]
[Risc CPUs Renesas](jFFS2)[git.progress-linux.org/packages/fuchur/linux/commit/arch/
sh?h=upstream/5.10.46&id=a8d1db2141e7a2b05a0ef6e582bf6bdb13ec7344]
[Theadorable X86 MB](NFS) [github.com/ARM-software/u-boot/blob/master/include/configs/
theadorable-x86-common.h ]
[x86/x86_64/ARM/Mips/PPC..](UbiFS/jFFS2/RomFS/EXT4..)[barebox.org/doc/latest/user/booting-linux.html]
[x86/x86_64/ARMv7/ARM64/Mips32/S390/ppc32/ppc64/Android/Darwin/Illumos/SOLARIS...]
(UbiFS и пр.)[bootlin.com/doc/training/boot-time/boot-time-slides.pdf ]
[x86/x86_64/Arc/ARM/m68k/Microblaze/Mips/Nios2/ppc/Risc-v/Sandbox/Sh/Xtensa ]
( UbiFS/jFFS2/FFS2/RomFS/EXT4..)[ u-boot.readthedocs.io/en/latest/index.html ] и др.

/// ==================================================================================
/// @example Приложение#6. Сравнение ТТХ жестких дисков и флэш-памяти
/// ==================================================================================
Жесткие диски — это блочные ВУ. При этом флэш ВУ имеют ряд преимуществ перед HDD:
1. Нет механических и движущихся частей
2. Нет шума + высокая устойчивость к ударам и вибрациям
3. Низкое тепловыделение и энергопотребление.
4. Флэш обеспечивает произвольное быстрое чтение, так как больше не надо
перемещать головку диска в нужное место на ВУ.

Конечно, у флэш-памяти есть и недостатки:
1. По той же цене у вас будет в 10 раз меньший объем хранения, чем у HDD. Это
может быть проблемой для ОС, где требуются гигабайты дискового пространства.
К счастью, Linux нужно лишь несколько МБ.
2. Запись во флэш имеет особые ограничения. Нельзя писать в блок не стирая весь
блок. Это ограничение приводит к тому, что скорость записи будет значительно
ниже скорости чтения.
3. Также блоки флэш могут выдержать лишь ограниченное число стираний, до 1000000
в лучшем случае. Нужны аппаратно-программные решения, называемые ВЫРАВНИВАНИЕМ
ИЗНОСА, чтобы гарантировать, что ни один блок не будет записываться слишком
часто по сравнению с другими.

/// ==================================================================================
/// @link Приложение#7. Ссылки
/// ==================================================================================
/** @link bootlin.com/blog/managing-flash-storage-with-linux @~ Linux Managing Flash
* @link linuxlink.timesys.com/docs/wiki/engineering/HOWTO_Partition_MTD_on
* _the_Command_Line
* @link openwrt.org/ru/docs/techref/flash.layout
* @link books.google.ru/books?id=YsJSEAAAQBAJ&pg=PA172&lpg=PA172&dq=mtd+mtdparts+
* смещение+без+размера&source=bl&ots=gkoW-UJfNq&si
* g=ACfU3U33WA9c0mqslDBT6XzKo52Rd5rJYw&hl=
* ru&sa=X&ved=2ahUKEwip7oW364v4AhWGs4sKHQd1AbwQ6AF6BAgqEAM#v=onepage&q&f=false
* @link rus-linux.net/MyLDP/BOOKS/Embedded_Linux_system_design_and_development_ru.pdf
* @link gitlab.psi.ch/schmid_e/dcb_uboot/-/blob/master/cmd/mtdparts.c
* @link sourceware.org/jffs2/jffs2.pdf
* @example Реальный-Е16С-пример:работа¨MTD¨c¨МЦСТ-Linux.~»image-5.4.0-4.3-e16c»
* console=ttyS0,115200 mtdparts=spi0.0:4736K(boot),64K(dev3),192K(BootArgs),
* 128K(mOS.Args),
* 11M(mOS),-(jFFS2)
* @example mtdids=nor0=spi0.0-MT25QU @~ Declare MTD-variables
/// @page 20
/** @todo Ideal MTD parts in future @example:
* mtdparts=nor0:0x4A0000(ПНС),10M(uOS),-(jFFS2)
* mtdparts=nor0:0x4A0000(E16C),0×10000(D3),0×30000(w.j),0×20000(S3),10M(uOS),-(root)
* mtdparts=spi0.0-MT25QU512:5M(ПНС),64k(D3),192k(json),128k(S3),10M(uOS),-(FFS2)
* mtdparts=nor0:5M(Boot),64k@0x4A0000(D3),192k(w.j),128k(S3),10M(mOS),-(jFFS2) */
«mtdparts=spi0:5M(E2C3),64k(d.j),64k(w.j),9k(D3),20k(S3),10M(uOS),-(root)»

/// ==================================================================================
/// @section Приложение#8. Q&A (Вопрос-Ответ)
/// ==================================================================================
On 28.07.2022 13:39, Степан Рыбаков wrote: > И еще у меня остались вопросы касательно
> предлагаемой разбивки на разделы. В тексте часто видел, что «RomFS опорная для ПНС»,
> плюс в «RomFS» предлагается поместить «DevTree» и «S3″. В то же время пользователь
> должен уметь обновлять «DevTree» тем же «flashboot/flashrom», а ядро перезаписывать
> настройки «S3″. На мой взгляд, чаще всего и пользователю/ядру и ПНС было бы удобнее
> работать с raw-разделами, а не с ФС. ОТСЮДА ВОПРОСЫ: Откуда это стремление уменьшить
> число разделов и по максимуму применять ФС? Это уменьшает общий объем прошивки?

Число файлов в «jFFS2″ не оговаривается. ФС может хранить части разных файлов в одном
физ. блоке + удобнее писать в «jFFS2″-файлы, как в файлы. Но более важно применять ФС
для удобства чтения пользователем неких файлов, как текстовых. В первую очередь json
файлов с настройками ПНС. Например, это нужно в Микро ОС.

> — Какие ФС бут будет поддерживать (уметь создавать, читать, изменять и т.д.)?
> Только «RomFS» или «jFFS2/UBIFS» и т.д.?

Изначально прошивку формирует утилита FIT под Linux. Она будет поддерживать любые ФС,
какие нам нужны (в том числе «RomFS»). Сам бут полноценно не поддерживает ни одну ФС.
Но благодаря тому, что «RomFS» устроена очень просто, оказывается возможна запись в
её области по физ. адресам, с перевычислением и перезаписью контрольных сумм. В буте
есть/будет именно такая, облегченная поддержка «RomFS». Бут ею пользуется когда надо
перезаписать файлы внутри «RomFS», такие как: настройки в «*.json» файлах, «DevTree»
и т.д. (например, если пользователь принес обновления этих файлов на USB-носителе).

> — «RomFS» не подходит для хранения перезаписываемых файлов. «RomFS» нужно поменять
> на «raw, jFFS2″ и пр.

Облегчённой поддержкой записи в «RomFS» могут воспользоваться и ядро (для гибернации),
и FIT (из под Windows/Linux), и утилита пространства пользователя «flashboot» ( при
обновлении «DevTree»). Для этого могут быть использованы функции «light» поддержки,
возвращающие физ. адреса/смещения данных файлов и контрольных сумм файлов в «RomFS».

Второй способ вычисления физических адресов/смещений данных файлов и контрольных сумм
у файлов в «RomFS» — это прибавить к адресу начала раздела фиксированные значения,
указанные в «§6.1″. 3-й способ — это получить нужную «инфу» из ядра. /// @see «§2.1″

Но возникает вопрос о передаче любой из FIT или утилитам «flashboot»/»dd» мета-строки
«mtdparts» для определения адресов у разделов «RomFS» и «raw»-разделов. Вопрос решается
путем размещения мета-строки «mtdparts» по константному смещению в сигнатуре ПНС.

On 28.07.2022 14:01, Ломако Григорий wrote: По большому счёту, мета «mtdparts» в
сигнатуре ПНС Linux-ядру не нужны. Они нужны утилитам FIT: под Linux для создания/
инициализации нужных файлов, под Windows для обновления файлов. Дима правда хочет
передавать мета через «boot_info». А ты предлагаешь вообще зафиксировать в коде ядра
конфигурацию MTD-FS для всех наших МЦСТ-архитектур. Так как ПНС все равно как отдать
мета Linux, то тут как вы решите, так и будет. Но ИМХО передавать метаданные ядру
через «CmdLine» правильнее, ибо это полностью соответствует стандарту Linux. В ПНС
для отладки Linux и обхода неясных ситуаций будет «ручка» отключения передачи в ОС
мета-строки «mtdparts» через «CmdLine». На всякий случай, ниже даны «https» ресурсы
по кодированию MTD-метаданных в «DevTree»:
— support.xilinx.com/s/question/0D52E00006hpZYXSA2/jffs2-file-system-and-flash-
partitions?language=en_US
— elinux.org/Device_Tree_Usage
— android.googlesource.com/kernel/msm/+/android-msm-bullhead-3.10-marshmallow-dr/
Documentation/devicetree/bindings/mtd/partition.txt
— chromium.googlesource.com/chromiumos/third_party/u-boot/+/stabilize-5062.B/doc/device-
tree-bindings/spi/spi-bus.txt
— unix.stackexchange.com/questions/559593/override-mtdparts-configured-in-kernel-device
tree
#endif /// @pre
/// @page 21

/// ==================================================================================
/// @interface as UBOOT: gitlab.psi.ch/schmid_e/dcb_uboot/-/blob/master/cmd/mtdparts.c
/// ==================================================================================
u64 no_stk memsize_parse ( const char * const ptr, const char ** retptr );
int no_stk parse_mtdparts( const char * const mtdparts );

/// ==================================================================================
/// @enum
/// ==================================================================================
typedef enum
{ rBOOT , /// @~ Раздел cырой (RAW) с кодом бута
rDEV3 , /// @~ Раздел cырой (RAW) c данными DevTree
rDFLT , /// @~ Раздел/Файл RomFS с файлом с параметрами бута по умолчанию
rWORK , /// @~ Раздел/Файл RomFS с рабочими параметрами загрузки USER
rS3S4 , /// @~ Раздел cырой (RAW) с данными настройки PHY-DDR4 гибернации
rU_OS , /// @~ Сырой (RAW) раздел с кодом Микро-ОС
rROOT , /// @~ Раздел root jFFS2 с с файлами Микро-ОС
PARTS /// @~ Число разделов/файлов ПНС V6 на FLASH
} MTD_e ;

/// ====================================================================================
/// @struct
/// ====================================================================================
struct mtd_spi_s
{ char * chip ;
u8 bus ;
u8 cs ;
} ;
typedef struct mtd_spi_s MTDSPI_t ;

struct mtd_partition
{
char * name ; /// @~ Identifier string
char * fs ; /// @~ Опорная файловая система
long size ; /// @~ Partition size
long offset ; /// @~ Offset within the master MTD space
bool ro ; /// @~ Read-Only
char * source ; /// @~ Путь к источнику данных по умолчанию
};
typedef struct mtd_partition mtd_partition_t ;

/// ==================================================================================
/// @} @file EOF
/// ==================================================================================
#endif /// @~ MTD_H

 ▤  Двигатель танка Оплот
 ▤  Расход топлива танка Леопард 2 на 100 км
 ▤  Звезда R136a2
 ▤  Армата vs Меркава