Дата и время публикации:
Проблемы и решение
1. Суть проблемы
Заключается в том, что нужно имитировать физические блочные устройства /dev/mmcblk*, которые показаны в дампе 1.1
Дамп 1.1
root@home:~# lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT mmcblk0 179:0 0 7,5G 0 disk └─mmcblk0p1 179:1 0 7,5G 0 part /media/user/78CA-E57D
Из которого видно, что носитель с меткой 78CA-E57D имеет файлы блочных устройств /dev/mmcblk0 и /dev/mmcblk0p1
Файл /dev/mmcblk0p1 является специальным блочным файлом устройства, который указывает на одну единственную созданную партицию или логический диск, как показано в дампе 1.2. В тоже время, из которого видно, что файл /dev/mmcblk0 указывает на весь носитель информации карты памяти SD, который включает в себя 8192 блоков по 512 байт .
Дамп 1.2
$ sudo fdisk -l /dev/mmcblk0 Disk /dev/mmcblk0: 7,5 GiB, 8053063680 bytes, 15728640 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disklabel type: dos Disk identifier: 0x00000000 Device Boot Start End Sectors Size Id Type /dev/mmcblk0p1 8192 15728639 15720448 7,5G b W95 FAT32
Поэтому изначально проблема лежит в плоскости имитации структуры карты памяти SD, без которой образ не может быть востребован эмулятором Qemu.
Так же, далее по тексту,после решения проблем, связанных с имитацией структуры карты памяти SD, будет рассказываться как выполнять симуляцию устройства карты SD (команда в CLI -drive sd-card,drive=sd1 ...) и подключать дополнительным накопителем (команда в CLI -drive id=sd1,if=none,...) c помощью эмулятора Qemu на базе встроенного гипервизора KVM, встроенного в ядро Linux, которое, в свою очередь также надо настраивать для подключения им драйвера sdhci_pci при выполнении команды -device sdhci-pci . А также почему в данном примере три устройства MMC, а не одно.
2. Решение
2.1 Создание имитирующий струтуру файл образа c использованием карты памяти SD
Самым простым и востребованным способом является создание файла дубликата диска с использованием команды DD(1), которая создает файл образа "точь-в-точь" согласно реальной физической структуры носителя информации, как показано в дампе 2.1
Дамп 2.1
sudo dd if=/dev/mmcblk0 of=sdcard.img bs=512 count=15720449 status=progres
Указываем,
- в первом аргументе if= — абсолютный путь к специальному блочному файлу /dev/mmcblk0,
- во втором аргументе of= — имя образа файла sdcard.img,
- в третьем аргументе bs= — количество байт в блоке, которых равняется 512,
- в четвертом аргументе count= — количество блоков, при этом берем не результирующее, а общее число блоков доступное на носителе информации, которое равно 15728640, как показано в дампе 1.2, а по номеру последнего блока плюс один единственной и крайней партиции /dev/mmcblk0p1, равным значению 15720449 блоков; хотя, будет правильным указать общее число блоков, равное, в этом случае, значению 15728640,
- Пятый аргумент status=progress — опционально для отображения статуса в процентах выполненной текущей работы .
В результате будем иметь файл работоспособного образа sdcard.img, как показано в дампе 2.2
Дамп 2.2
$ sudo fdisk -l sdcard.img Disk sdcard.img: 7,5 GiB, 8048869888 bytes, 15720449 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disklabel type: dos Disk identifier: 0x00000000 Device Boot Start End Sectors Size Id Type sdcard.img1 8192 15728639 15720448 7,5G b W95 FAT32
Соответственно, как показано в дампе 2.2, файл образа соответствует ранее указанной структуре, где партиция sdcard.img байт в байт повторяет /dev/mmcblk0p1, данные по который приводятся в дампе 1.2
2.2 Создание файла образа карты памяти SD программными средствами
Создание файла образа карты памяти SD показано в дампе 2.3
Дамп 2.3
$ qemu-img create ~/qemu-sdcard.img 7.5G Formatting '/home/user/qemu-sdcard.img', fmt=raw size=8053063680
Затем создаем сетевое блочное устройство. Процесс можно запустить в фоновом режиме и с ожиданием присоединения клиента nbd-client к qemu-nmbd путем добавления через проблем символа амперсанда (&), как показано 2.4
Дамп 2.4
$ qemu-nbd ~/qemu-sdcard.img &
Теперь нам необходим сам клиент nbd-client, который устанавливается в Debian, как показано в дампе 2.5
Дамп 2.5
$ sudo apt update && sudo apt install nbd-client
Подгружаем необходимый драйвер ядра, как показано в дампе 2.6
Дамп 2.6
$ sudo modprobe nbd
Цепляемся к диску, как показано в дампе 2.7
Дамп 2.7
$ sudo nbd-client localhost /dev/nbd0 Warning: the oldstyle protocol is no longer supported. This method now uses the newstyle protocol with a default export Negotiation: ..size = 7680MB Connected /dev/nbd0
Размечаем nbd-диск с использованием fdisk, как показано в дампе 2.8
Дамп 2.8
$ sudo fdisk /dev/nbd0
При этом, как показано в дампе 2.9, должны получить результаты, такие же показанные ранее в дампе 2.2
Дамп 2.9
... Command (m for help): p Disk /dev/nbd0: 7,5 GiB, 8053063680 bytes, 15728640 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disklabel type: dos Disk identifier: 0x6b766460 Device Boot Start End Sectors Size Id Type /dev/nbd0p1 8192 15728639 15720448 7,5G b W95 FAT32 ...
Последовательно выполняем команды по форматированию устройства, монитирования и размонтирования блочного устройства, как показано в дампе 2.10
Дамп 2.10
$ sudo mkfs.vfat /dev/nbd0p1 mkfs.fat 4.1 (2017-01-24) $ sudo mount /dev/nbd0p1 /mnt $ sudo umount /mnt
Отцепляем диск и освобождаем файл блочного устройства /dev/nbd0, как показано в дампе 2.11
Дамп 2.11
$ sudo nbd-client -d /deb/nbd0
Иначе, при последующем подключении диска клиент nbd-client может завершится с ошибкой, как показано в дампе 2.12
Дамп 2.12
... Warning: the oldstyle protocol is no longer supported. This method now uses the newstyle protocol with a default export Negotiation: ..size = 7680MB Error: Failed to setup device, check dmesg Exiting. ...
А также в случае преждевременного закрытия qemu-nbd , как показано в дампе 2.13
Дамп 2.13
... Warning: the oldstyle protocol is no longer supported. This method now uses the newstyle protocol with a default export Error: Socket failed: Connection refused ...
2.3 Подключение файла образа
Для добавления носителей информации, подобных карте памяти SD, производится по правилу, приведенному в дампе 2.14, с использованием команд, передаваемых в командной строке -drive и -device во время запуска эмулятору Qemu
Дамп 2.14
$ qemu-system-arm … -device sdhci-pci -device sd-card,drive=sd1 -drive id=sd1,if=none,format=raw,file=sdcard.img ...
В котором показано, что команды -drive и -device связываются через опции drive= и id=, соответсвенно. Плюс некоторые интересные опции регулирующие тип устройства, источник нахождения файла образа симуляции карты памяти и т.д.
Опция file= указывает откуда на хозяйской машине эмулятор Qemu буедет брать файл образа sdcard.img, симулирующий структуру карты памяти SD.
Опция if= устанавливает тип интерфейса, используемого устройством при запуске эмулятор Qemu и выбором одного из значений ide, scsi, sd, mtd, floppy, pflash, virtio . В данном случае, опция if=none, потому что указано автоматически подключаемое устройство в виде карты памяти SD, которая требует игнорировать эту опцию. Иначе, можно получить ошибку и рекомендацию попробовать использовать if=none, как показано в дамп 2.15
Дамп 2.15
... ERROR qemu-system-arm: -device sd-card,drive=sd0: Drive 'sd0' is already in use because it has been automatically connected to another device (did you need 'if=none' in the drive options?) ...
Опция format= устанавливает формат структуры диска. Так, в данном случае, нужно указывать format=raw во избежании неправильного определения структуры носителя информации.
Также, иногда, указывают опцию index=, которая указывает на числовое значение номера позиции устройства в списке подключаемых устройств к одному и тому же из ранее перечисленных типов интерфейсов . Обычно, это не требуется и можно игнорировать.
В результате загрузки гостевой ОС в её журнале dmesg или systemd-journal должны быть зарегистрированны сообщения, подобно тем, что показаны в дампе 2.16
Дамп 2.16
... [ 6.414277] mmci-pl18x fpga:05: mmc0: PL181 manf 41 rev0 at 0x10005000 irq 59,60 (pio) [ 6.464211] mmci-pl18x fpga:0b: mmc1: PL181 manf 41 rev0 at 0x1000b000 irq 49,50 (pio) ... [ 6.420364] sdhci: Secure Digital Host Controller Interface driver [ 6.423949] sdhci: Copyright(c) Pierre Ossman [ 6.427320] sdhci-pci 0000:00:11.0: SDHCI controller found [1b36:0007] (rev 0) [ 6.438809] sdhci-pci 0000:00:11.0: enabling device (0100 -> 0102) [ 6.445422] mmc2: SDHCI controller on PCI [0000:00:11.0] using ADMA ... [ 6.813491] mmc2: Problem switching card into high-speed mode! [ 6.818252] mmc2: new SDHC card at address 4567 [ 6.834510] mmcblk2: mmc2:4567 QEMU! 7.50 GiB [ 6.855938] mmcblk2: p1 [ 6.858153] mmcblk2: p1 size 15720448 extends beyond EOD, truncated ...
При этом, были инициализированы два устройства mmc0 и mmc1, так как в выбранной симулируемой технической платформе versatile-pb уже имелось устройство карты памяти SD совместимое c ARM PrimeCell MMCI PL180/1 под управлением драйвера mmci-pl18x. Но, которые не удалось подключить в в используемом эмуляторе qemu-system-arm, потому что им поддерживается симуляция устройств карт памяти SD только "sd-card" и "sdhci-pci", которые оказалось работают в месте и одной связке, на что указывает инициализация третьего устройства mmc2, о подключении которого поговорим ниже.
2.4 Поддержка симмуляции контроллера SDHCI на PCI
Для этого необходимо, чтобы ядро linuх и эмулируемая техническая платформа на базе процессора ARM или RISC-V включали дрaйвер sdhci_pci и симмуляцию контроллера SDHCI на PCI, путем включения поддержки:
- симуляции контроллера SDHCI на PCI производится передачей в командной строке -device sdhci_pci эмулятору qemu-system-arm или qemu-system-riscv, как показано в дампе 2.14;
- дрaйвера (модуля) sdhci_pci поддержка которого задается макросом CONFIG_MMC_SDHCI_PCI конфигурации ядра, который в свою очередь зависит от CONFIG_MMC_SDHCI и CONFIG_PCI
Настройка ядра для включения в него модуля производится с использованием сборочной машины yocto/poky, из под которой обычно запускаются встроенный в неё эмулятор qemu-system-arm или qemu-system-riscv. В виду возможности добавления в них некоторых функциональных возможностей на этапе сборки.
Для установки CONFIG_PCI=y в меню конфигурации ядра в разделе "Device Driver" должен быть выбран пункт "PCI support" и напротив него, в квадратных скобках, установлен символ звездочка (*), как показано на рисунке 2.17
Рисунок 2.17
Далее, возвращаемся в раздел "Device Driver" и выбираем "MMC/SD/SDIO card support" , как показано на рисунке 2.18
Рисунок 2.18
В нем включаем в ядро, используя символ звоздочка (*), последовательно "Secure Digital Host Controller Interface support" — CONFIG_MMC_SDHCI и "SDHCI support on PCI bus" — CONFIG_MMC_SDHCI_PCI, как показано рисунок 2.19
Рисунок 2.19
После чего, необходимо сохранить сделанные изменения и пересобрать ядро, выполняя действия необходимые по сборке ядра Linux для архитектуры ARM или RISC-V для сборочной машины Yocto/poky или согласно руководству для 5-й версии Debian
3. Библиография
3.1 Heiko's Blog. qemu-system-x86_64 -drive options
3.2 lists.nongnu.org. [Qemu-devel] sd: add SDHCI and eMMC support
3.3 lists.nongnu.org. [Qemu-devel]. [Qemu-devel] how to ues qemu -sd option?
3.4 www.raspberrypi.org. Generating an SD card image for QEMU emulation
3.5 Kele's Blog. Create SD Image for Xilinx Qemu
3.6 Kele's Blog. Create SD Image for Xilinx Qemu
3.8 nixCraft. Linux dd Command Show Progress Copy Bar With Status
3.9 xboot-clone. How To Create SD Card Image For Qemu Emulator
3.10 HAIKU. [GSoC 2018: SDHCI MMC Driver]: Week #1 and #2