Problems mounting a ubi image using QEMU - arm

I'm trying to emulate a nand flash with qemu and use that to mount an existent ubifs image on the virtual machine.
I added a nand device and a drive of the type mtd, resulting on the following command:
$ qemu-system-arm -nographic -M virt -m 64 -device nand,chip_id=0x59 -drive if=mtd,format=raw,file=data.ubi -kernel openwrt-armvirt-32-zImage-initramfs
Warning: Orphaned drive without device: id=mtd0,file=data.ubi,if=mtd,bus=0,unit=0
[ 0.000000] Booting Linux on physical CPU 0x0
[ 0.000000] Linux version 4.19.56 (buildbot#builds) (gcc version 7.4.0 (OpenWrt GCC 7.4.0 r10348-577174cf60)) #0 SMP Tue Jun 25 14:46:01 2019
[ 0.000000] CPU: ARMv7 Processor [412fc0f1] revision 1 (ARMv7), cr=30c5387d
[ 0.000000] CPU: div instructions available: patching division code
[ 0.000000] CPU: PIPT / VIPT nonaliasing data cache, PIPT instruction cache
[ 0.000000] OF: fdt: Machine model: linux,dummy-virt
[ 0.000000] Memory policy: Data cache writealloc
[ 0.000000] psci: probing for conduit method from DT.
[ 0.000000] psci: PSCIv0.2 detected in firmware.
...
I can't access to the data.ubi probably because of the following warning:
"Warning: Orphaned drive without device"
How can I add the ubi image to the nand device correctly?

You have to link the -drive and -device via an id parameter:
qemu-system-arm \
`: [...]` \
-device nand,chip_id=0x59,id=myubiflash \
-drive if=mtd,format=raw,file=data.ubi,id=myubiflash \
`: [...]`
If you really read the message carefully, you'll notice that the drive id defaults to mtd0:
Warning: Orphaned drive without device: id=mtd0,file=data.ubi,if=mtd,bus=0,unit=0
And of course qemu can't magically guess that you meant to define the -device nand for the drive.
The error message is exactly on the spot here.
Edit
I'll admit, no perfect understanding of the layers of syntax in QEMU commandline on my side either.
Also, the QEMU doc isn't the easiest to read; however it has this passage:
A block driver node created with -blockdev can be used for a guest device by specifying its node name for the drive property in a -device argument that defines a block device.
-blockdev is synonym to -drive in this context.
If I can interpret it right, the meaning of this is that instead of
-device […],id=foo, -drive […],id=foo
you're supposed to use
-device […],drive=foo, -drive […],id=foo
Can't test this ATM, but either of those should make it work for you.

Related

Bootloading QEMU emulating Freescale i.MX6 Quad SABRE Lite Board

I am trying to start a QEMU sabrelite machine with U-Boot. I am managed to build it according to guide.
I run it as
./qemu-6.1.0/build/qemu-system-arm \
-M sabrelite \
-m 1G \
-kernel u-boot \
-drive file=disk.img,format=raw,id=mycard \
-device sd-card,drive=mycard,bus=sd-bus \
-serial null \
-serial stdio \
-nic user \
-no-reboot
Disk.img is a raw formatted file with the first vfat partition. I tried partition types 0xc 'EFI (FAT-12/16/32)' and 0xef 'W95 FAT32 (LBA)'. It starts with a bundle of errors.
U-Boot 2021.07 (Aug 24 2021 - 19:43:55 +0300)
CPU: Freescale i.MX6Q rev1.0 at 792 MHz
Reset cause: POR
Model: Freescale i.MX6 Quad SABRE Lite Board
Board: SABRE Lite
I2C: ready
DRAM: 1 GiB
force_idle_bus: sda=0 scl=0 sda.gp=0x5c scl.gp=0x55
force_idle_bus: failed to clear bus, sda=0 scl=0
force_idle_bus: sda=0 scl=0 sda.gp=0x6d scl.gp=0x6c
force_idle_bus: failed to clear bus, sda=0 scl=0
force_idle_bus: sda=0 scl=0 sda.gp=0xcb scl.gp=0x5
force_idle_bus: failed to clear bus, sda=0 scl=0
MMC: FSL_SDHC: 0, FSL_SDHC: 1
Loading Environment from MMC... *** Warning - No block device, using default environment
In: serial
Out: serial
Err: serial
Net: using phy at 6
FEC [PRIME]
Error: FEC address not set.
, usb_ether
Error: usb_ether address not set.
starting USB...
Bus usb#2184000: usb dr_mode not found
probe failed, error -22
Bus usb#2184200: probe failed, error -22
No working controllers found
Hit any key to stop autoboot: 0
SATA Device Info:
S/N:
Product model number:
Firmware version:
Capacity: 0 sectors
Device 0: starting USB...
Bus usb#2184000: usb dr_mode not found
probe failed, error -22
Bus usb#2184200: probe failed, error -22
No working controllers found
USB is stopped. Please issue 'usb start' first.
starting USB...
Bus usb#2184000: usb dr_mode not found
probe failed, error -22
Bus usb#2184200: probe failed, error -22
No working controllers found
*** ERROR: `ethaddr' not set
missing environment variable: pxeuuid
missing environment variable: bootfile
Retrieving file: pxelinux.cfg/00000000
*** ERROR: `serverip' not set
…
=> mmcinfo
=> mmc list
FSL_SDHC: 0
FSL_SDHC: 1
The issue is that SD/MMC and USB Storage fails. So, I am not able to load an OS.
I came across a discussion. It mentions that this board have some SD controller specific and that there were SD related bug. But the fix was applied a couple years ago.
I guess there is a mismatch between QEMU and U-Boot SD controller definitions.
But I have no idea how to fix it. I would be relly happy if anyone could give me a hint.
Real i.MX6Q SABRE Lite board boots from SPI-NOR flash that is preloaded with U-Boot. QEMU emulates it as sst25vf016b device. I tried to load it with a proprietary bootloader as
-device sst25vf016b,drive=spi \
-drive if=none,file=flash.bin,format=raw,id=spi \
But it doesn’t work. Is it possible to bootload a QEMU sabrelite machine this way?
Some time later...
I built a linux kernel and started it with rootfs from an SD card. QEMU 5.1.0, 5.2.0, 6.0.0 and 6.1.0 plus linux handles SD/MMC well.
[ 10.400092] sdhci: Secure Digital Host Controller Interface driver
[ 10.401012] sdhci: Copyright(c) Pierre Ossman
[ 10.401982] sdhci-pltfm: SDHCI platform and OF driver helper
[ 10.425404] caam 2100000.crypto: device ID = 0x0000000000000000 (Era -524)
[ 10.427688] sdhci-esdhc-imx 2198000.mmc: Got CD GPIO
[ 10.427954] caam 2100000.crypto: job rings = 2, qi = 0
[ 10.429650] sdhci-esdhc-imx 2198000.mmc: Got WP GPIO
[ 10.435224] sdhci-esdhc-imx 219c000.mmc: Got CD GPIO
[ 10.459144] caam_jr 2101000.jr: failed to flush job ring 0
[ 10.472458] caam_jr: probe of 2101000.jr failed with error -5
[ 10.481084] caam_jr 2102000.jr: failed to flush job ring 1
[ 10.488221] caam_jr: probe of 2102000.jr failed with error -5
[ 10.507965] usbcore: registered new interface driver usbhid
[ 10.515781] usbhid: USB HID core driver
[ 10.571593] mmc2: SDHCI controller on 2198000.mmc [2198000.mmc] using ADMA
[ 10.583693] mmc3: SDHCI controller on 219c000.mmc [219c000.mmc] using ADMA
[ 10.590880] ipu1_csi0: Registered ipu1_csi0 capture as /dev/video0
[ 10.611980] ipu1_ic_prpenc: Registered ipu1_ic_prpenc capture as /dev/video1
[ 10.622227] ipu1_ic_prpvf: Registered ipu1_ic_prpvf capture as /dev/video2
[ 10.643235] ipu1_csi1: Registered ipu1_csi1 capture as /dev/video3
[ 10.655850] ipu2_csi0: Registered ipu2_csi0 capture as /dev/video4
[ 10.660920] ipu2_ic_prpenc: Registered ipu2_ic_prpenc capture as /dev/video5
[ 10.670717] ipu2_ic_prpvf: Registered ipu2_ic_prpvf capture as /dev/video6
[ 10.690556] ipu2_csi1: Registered ipu2_csi1 capture as /dev/video7
[ 10.702178] mmc3: host does not support reading read-only switch, assuming write-enable
[ 10.710571] mmc3: new high speed SD card at address 4567
[ 10.729816] mmcblk3: mmc3:4567 QEMU! 32.0 MiB
I bet that it is a U-Boot issue. On the other hand I believe that U-Boot works with real hardware. Probably it is worth it to use U-Boot from Boundary? Can anyone with a real board confirm what U-Boot version does it support?

QEMU No 'PCI' bus found for device 'nvme'

I'm debuging NVME code with QEMU , QEMU return an err message:No 'PCI' bus found for device 'nvme'.
However,I checked device info,it shows PCI is surportted.
root#linux:/home/#qemu-system-arm -machine vexpress-a9 -device help
Storage devices:
name "am53c974", bus PCI, desc "AMD Am53c974 PCscsi-PCI SCSI adapter"
name "nvme", bus PCI, desc "Non-Volatile Memory Express"
name "nvme-ns", bus nvme-bus, desc "Virtual NVMe namespace"
name "nvme-subsys", desc "Virtual NVMe subsystem"
Could anybody give me some tips?
QEMU command:
root#linux:~/run-kernel/$ qemu-system-arm -nographic -M vexpress-a9 -m 1024M -kernel arch/arm/boot/zImage -append "rdinit=/linuxrc console=ttyAMA0 loglevel=8" -dtb arch/arm/boot/dts/vexpress-v2p-ca9.dtb -device nvme,drive=nvme0,serial=deadbeaf1,num_queues=8 -drive file=disk.qcow2,if=none,id=nvme0
output:
WARNING: Image format was not specified for 'disk.qcow2' and probing guessed raw.
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
Specify the 'raw' format explicitly to remove the restrictions.
qemu-system-arm: -device nvme,drive=nvme0,serial=deadbeaf1,num_queues=8: No 'PCI' bus found for device 'nvme'
QEMU version:
root#linux:/home/# qemu-system-arm -version
QEMU emulator version 6.0.94
Copyright (c) 2003-2021 Fabrice Bellard and the QEMU Project developers
You're trying to use a PCI device (nvme) on a machine type with no PCI bus (vexpress-a9). This doesn't work, in the same way that trying to plug a real hardware PCI card into a machine with no PCI slots is impossible.
You may be being confused by the '-device help' output: that output lists all devices compiled into that QEMU binary, and does not filter it based on any additional '-machine' option you pass at the same time. So it will always show you everything.

Access ECAM on QEMU AArch64 virt device

I am trying to implement bare metal PCIE device discovery on QEMU AArch64 virt device. I know, that ECAM area is mapped to 0x3f000000 memory address, and I expect to see there this table.
But when I perform a reading of 4 bytes (MCFG signature) from 0x3f000000 address, I get a synchronous exception.
What am I doing wrong? Is there something I have to perform before accessing PCIE memory mapped area?
QEMU_CMD = qemu-system-aarch64 \
-machine virt \
-m 1024M \
-cpu cortex-a53 \
-serial stdio \
-device virtio-gpu-pci \
-vnc :0 \
-netdev user,id=n1 -device virtio-net-pci,netdev=n1
You're looking at the wrong address. The virt board only puts the ECAM at the 0x3f00_0000 address if it is not using the physical address space above-4GB (which is not the default; QEMU only avoids highmem usage if the user passed -machine highmem=off).
You can check this by asking QEMU to dump the dtb instead of running the guest, by adding "-machine dumpdtb=/tmp/dump.dtb" to your commandline, then disassembling the dtb with "dtc -I dtb -O dts /tmp/dump.dtb | less", and looking at the dtb for the pci controller.
More generally, a guest running in the QEMU "virt" board should not hardcode any addresses of devices, but should always read the dtb that QEMU generates and passes to the guest to determine where in the address space devices are placed. If your code did this it wouldn't have run into this error.

How can I check integrity of a extracted zImage?

$ binwalk -e linux_image.img
DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
0 0x0 Android bootimg, kernel size: 6897653 bytes, kernel addr: 0x81C08000, ramdisk size: 5959520 bytes, ramdisk addr: 0x81C08000, product name: ""
2048 0x800 Linux kernel ARM boot executable zImage (little-endian)
18479 0x482F gzip compressed data, maximum compression, from Unix, last modified: 1970-01-01 00:00:00 (null date)
6761720 0x672CF8 device tree image (dtb)
6883304 0x6907E8 Unix path: /dev/block/platform/soc/7824900.sdhci/by-name/vendor
6899712 0x694800 gzip compressed data, maximum compression, has original file name: "rootfs.cpio", from Unix, last modified: 2019-04-06 00:42:26
9706949 0x941DC5 MySQL ISAM compressed data file Version 11
$ dd if=linux_image.img of=vmlinuz bs=1 skip=2048 count=6897653
$ file vmlinuz
vmlinuz: Linux kernel ARM boot executable zImage (little-endian)
$ dd if=vmlinuz bs=1 skip=$(LC_ALL=C grep -a -b -o $'\x1f\x8b\x08\x00\x00\x00\x00\x00' vmlinuz-3.18.66-perf | head -n 1 | cut -d ':' -f 1) | zcat | grep -a 'Linux version'
Linux version 3.18.66 (build#test) (gcc version 4.9.3 (GCC) ) #1 SMP PREEMPT Fri Apr 1 13:16:33 PDT 2018
Running 'qemu-system-arm.exe -machine vexpress-a9 -cpu cortex-a7 -smp 4 -kernel vmlinuz' blank screen
If you pull a random Arm Linux kernel (including Android) from somewhere and try to run it on anything other than the hardware that it is intended to boot on, the expected result is that it crashes very early in bootup without being able to output anything to screen or serial port, ie you get a black screen and nothing happens. The most likely situation here is that your image is fine and not corrupt, it's just not built to run on the vexpress-a9 board you're running it on.
In the unlikely event that this really is a kernel built for the vexpress-a9, the next problem you have is that you haven't passed QEMU a device tree blob via the -dtb option. Modern Linux kernels don't hardcode all the information about the boards they can run on, but instead expect the bootloader (which is QEMU in this case) to pass them a data file which provides information about where all the devices are for the board. If you don't do that, then the result is the same as above: kernel crashes very early in bootup without being able to output any information, so black screen.

emulating the reMarkable tablet (i.MX6 ARMv7) with Qemu

I'm trying to emulate the reMarkable tablet with Qemu in order to create a proper development environment for it, instead of cross-compiling and sending to the hardware device.
The firmware flasher repo contains the rootfs, kernel, DTB and u-boot files. I've created an .img file from the rootfs in order to boot it in Qemu with the following command:
qemu-system-arm \
-M sabrelite \
-bios "files/u-boot.imx" \
-kernel "zImage" \
-append "console=ttymxc0 rootfstype=ext4 root=/dev/mmcblk1p2 rw rootwait init=/bin/bash loglevel=8 bootmem-debug earlyprintk" \
-dtb "zero-gravitas.dtb" \
-drive file="floppy.img",format=raw,id=mmcblk1p2 \
-device sd-card,drive=mmcblk1p2
but the kernel does not seem to be starting as I have the same log whether the floppy.img file (drive+device) is given or not. The startup loops on this error:
[ 0.713093] 2020000.serial: ttymxc0 at MMIO 0x2020000 (irq = 19, base_baud = 5000000) is a IMX
[ 0.732268] console [ttymxc0] enabled
[ 0.736333] phy index low: 1, phy index high: 2
[ 240.289647] INFO: task swapper:1 blocked for more than 120 seconds.
[ 240.290160] Not tainted 4.1.28-zero-gravitas-01866-ge0b823726ea4-dirty #82
[ 240.290318] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
[ 240.290662] swapper D 8051c44c 0 1 0 0x00000000
[ 240.292245] [<8051c44c>] (__schedule) from [<8051c73c>] (schedule+0x40/0x98)
[ 240.292473] [<8051c73c>] (schedule) from [<8051e7b8>] (schedule_timeout+0x114/0x168)
[ 240.292781] [<8051e7b8>] (schedule_timeout) from [<8051d248>] (wait_for_common+0x88/0x130)
[ 240.292953] [<8051d248>] (wait_for_common) from [<80262c74>] (imx_rng_init+0x158/0x2a8)
[ 240.293117] [<80262c74>] (imx_rng_init) from [<80262574>] (set_current_rng+0xc0/0x15c)
[ 240.293276] [<80262574>] (set_current_rng) from [<80262874>] (hwrng_register+0x190/0x1b8)
[ 240.293436] [<80262874>] (hwrng_register) from [<807c3fd8>] (imx_rng_probe+0xd4/0x134)
[ 240.293682] [<807c3fd8>] (imx_rng_probe) from [<802748e0>] (platform_drv_probe+0x44/0xac)
[ 240.293852] [<802748e0>] (platform_drv_probe) from [<802735ac>] (driver_probe_device+0x178/0x2b8)
[ 240.294009] [<802735ac>] (driver_probe_device) from [<802737bc>] (__driver_attach+0x8c/0x90)
[ 240.294158] [<802737bc>] (__driver_attach) from [<80271d50>] (bus_for_each_dev+0x68/0x9c)
[ 240.294352] [<80271d50>] (bus_for_each_dev) from [<802726bc>] (bus_add_driver+0x13c/0x1e4)
[ 240.294600] [<802726bc>] (bus_add_driver) from [<80273ed4>] (driver_register+0x78/0xf8)
[ 240.294843] [<80273ed4>] (driver_register) from [<807c434c>] (__platform_driver_probe+0x20/0x70)
[ 240.295092] [<807c434c>] (__platform_driver_probe) from [<807a9d78>] (do_one_initcall+0x118/0x1c4)
[ 240.295367] [<807a9d78>] (do_one_initcall) from [<807a9f48>] (kernel_init_freeable+0x124/0x1c4)
[ 240.295609] [<807a9f48>] (kernel_init_freeable) from [<8051883c>] (kernel_init+0x8/0xe8)
[ 240.295844] [<8051883c>] (kernel_init) from [<8000ef88>] (ret_from_fork+0x14/0x2c)
full log here
I will update this question when I have new findings, but i'm new to Qemu and I'm quite stuck and ran out of options. The repository i'm working in is here. Thanks for any input !
I haven't investigated too closely, but the fact that the backtrace shows a hang in the imx_rng_init function suggests that the problem is that QEMU doesn't have an emulation of the imx SoC's builtin RNG device, and so the guest is hanging forever waiting for a response from hardware that doesn't exist.
You'll need to either implement a model of that device, or else use a guest kernel which doesn't try to probe for that device.
More generally, running an Arm kernel that's intended for one piece of hardware on a different piece of hardware will usually not work. The sabrelite has the same SoC here, so booting works better than it would if you tried to do it with an entirely unrelated QEMU machine, but if at any time your guest code tries to access hardware outside the SoC which is specific to the reMarkable then you will find it doesn't work. If you really need to get the stock kernel for the hardware to boot you will probably at some point need to bite the bullet and implement a proper machine model of it in QEMU with the relevant devices present.
If you don't actually need to run anything on the guest that cares about the specific differences between one imx6 system and another, you might be able to get away with using a kernel and DTB for the sabrelite board plus the rootfs from the reMarkable.

Resources