On Fri, Oct 31, 2025 at 8:46 AM Markus Armbruster <[email protected]> wrote:
>
> Clément Chigot <[email protected]> writes:
>
> > On Mon, Oct 27, 2025 at 1:09 PM Markus Armbruster <[email protected]> wrote:
> >>
> >> Clément Chigot <[email protected]> writes:
> >>
> >> > On Fri, Oct 24, 2025 at 10:35 AM Markus Armbruster <[email protected]> 
> >> > wrote:
> >> >>
> >> >> Kevin Wolf <[email protected]> writes:
> >> >>
> >> >> > Am 03.09.2025 um 09:57 hat Clément Chigot geschrieben:
> >> >> >> This allows more flexibility to vvfat backend. The value for "Number 
> >> >> >> of
> >> >> >> Heads" and "Sectors per track" are based on SD specifications Part 2.
> >> >>
> >> >> This is too terse to remind me of how vvfat picks cylinders, heads, and
> >> >> sectors before this patch, so I need to go dig through the source code.
> >> >> I figure it depends on configuration parameters @floppy and @fat-type
> >> >> like this:
> >> >>
> >> >>     floppy  fat-type    cyls heads secs   cyls*heads*secs*512
> >> >>     false      12         64    16   63         31.5 MiB
> >> >>     false      16       1024    16   63        504   MiB
> >> >>     false      32       1024    16   63        504   MiB
> >> >>     true       12         80     2   18       1440   KiB
> >> >>     true       16         80     2   36       2880   KiB
> >> >>     true       32         80     2   36       2880   KiB
> >> >>
> >> >> How exactly does the new parameter @size change this?
> >> >
> >> > My prime goal was to create a 256 Mib VVFAT disk. As you can see,
> >> > today for hard-disks there are only two possibilities: 31.5 Mib or 504
> >> > Mib. Hence, I've introduced the option `size=xxx` to allow more
> >> > granular choices.
> >> > This option changes how cyls, heads and secs parameters are computed
> >> > to be as closed as possible of its value.
> >> >
> >> > I did try to keep it simple. I could have introduced options to select
> >> > cylinders, heads, etc. But I think "size=xxx" would be more intuitive.
> >> > There are also approximations made, as not all sizes can be reached. I
> >> > didn't add errors or warnings for them. I'm fine adding them.
> >>
> >> I don't have an opinion on whether we should support more sizes and/or
> >> provide full control over CHS geometry.
> >>
> >> >> >> Some limitations remains, the size parameter is recognized only when
> >> >> >> "format=vvfat" is passed. In particular, "format=raw,size=xxx" is
> >> >> >> keeping the previously hardcoded value: 504MB for FAT16 and 32 MB for
> >> >> >> FAT12. FAT32 has not been adjusted and thus still default to 504MB.
> >> >>
> >> >> 31.5MiB unless I'm mistaken.
> >> >
> >> > True, I will fix it.
> >> >
> >> >> I'm not sure what you're trying to convey in this paragraph.  As far as
> >> >> I can tell, you're adding a @size parameter to vvfat, so of course it
> >> >> doesn't affect raw.
> >> >
> >> > Yes, but AFAICT, `if=sd,format=raw` will result in vvfat backend being
> >> > called. I didn't manage to make the new option work with
> >> > `if=sd,format=raw,size=256Mb`. Thus, when the "size" option is not
> >> > provided, I keep the previous value (those for your above comment).
> >> > Hence this paragraph to mostly warn people about the current
> >> > limitation.
> >>
> >> Are you talking about -drive?
> >>
> >> Complete examples, please.
> >>
> >> I'm confused about the connection between SD (from if=sd here, and "SD
> >> specification" above) and vvfat.  SD is a frontend.  vvfat is a backend.
> >
> > Alright, I'll try to explain how I came up with this patch. And sorry
> > if it's a bit blurry, I made it some months ago hence I don't remember
> > all the details...
> > So, first, my prime goal was to access a local folder in a QNX system
> > running on Raspi 4B emulation.
> > My usual way to pass such a local folder is through `-drive
> > file=fat:rw:<host_folder>,format=raw`. For virt, it's usually
> > connected to virtio-blk-device: `-drive id=disk0,if=none,... -device
> > virtio-blk-device,drive=disk0`. For the Raspi 4b, adding the
> > virtio-blk-device is not possible, hence I have to connect it as a SD
> > card: `-drive if=sd,...`.
> >
> > However, without any `size=` argument, QEMU will complain that the SD
> > card has not a valid size:
> >   | (host) $ qemu-system-aarch64 -M raspi4b -kernel raspi4b-kernel
> > -nographic -no-reboot -append "earlycon=pl011,mmio32,0xfe201000
> > console=ttyAMA0 noreboot" -dtb bcm2711-rpi-4-b.dtb -initrd
> > rootfs.cpio.gz  -drive
> > id=sdcard,file=fat:rw:<host_folder>,format=raw,if=sd
> >   | qemu-system-aarch64: Invalid SD card size: 504 MiB
> >   | SD card size has to be a power of 2, e.g. 512 MiB.
> >   | You can resize disk images with 'qemu-img resize <imagefile> <new-size>'
> >   | (note that this will lose data if you make the image smaller than
> > it currently is).
>
> Fun!
>
> > ("raspi4b-kernel", the dtb and the rootfs come from
> > functional/aarch64/test_raspi4.py)
> >
> > Hence, I've added `size=256M` to reduce the size of that SD card and
> > make QEMU happy. This allows me to mount my host folder on Linux:
> >   | (host) $ qemu-system-aarch64 -M raspi4b -kernel raspi4b-kernel
> > -nographic -no-reboot -append "earlycon=pl011,mmio32,0xfe201000
> > console=ttyAMA0 noreboot" -dtb bcm2711-rpi-4-b.dtb -initrd
> > rootfs.cpio.gz  -drive
> > id=sdcard,file=fat:rw:<host_folder>,format=raw,if=sd,size=256M
> >   | (QEMU) # fdisk -l /dev/mmcblk1
> >   | Disk /dev/mmcblk1: 256 MB, 268435456 bytes, 524288 sectors
> >   | 520 cylinders, 16 heads, 63 sectors/track
> >   | Units: sectors of 1 * 512 = 512 bytes
>
> 520 * 16 * 63 is 524160 sectors, 128 less than the 524288 reported.  I
> figure that's harmless.  Only ancient software should look at CHS, and
> losing a few sectors with ancient software is fine.
>
> >   |
> >   | Device       Boot StartCHS    EndCHS        StartLBA     EndLBA
> > Sectors  Size Id Type
> >   | /dev/mmcblk1p1 *  0,1,1       1023,15,63          63    1032191
> > 1032129  503M  6 FAT16
> >
> > As you can see the "Disk" has the right size (256MB) but the partition
> > still has a 503M size.
>
> The partition table's EndLBA is 1032191 even though the disk has only
> 524288 cylinders.  Scary!
>
> Its EndCHS is consistent with its EndLBA: 1024*16*63 = 1032191 + 1.
>
> >                        However, Linux doesn't seem to care too much
> > about that as I'm able to mount this partition, and perform IO
> > operations.
> >   | (QEMU) # mount /dev/mmcblk1p1 /mnt
> >   | (QEMU) # ls /mnt
> >   | file.txt
> >   | (QEMU) # cat /mnt/file.txt
> >   | Hello World
> >   | (QEMU) # echo "OK" > /mnt/test.txt
> >   | (host) $ cat <host_folder>/test.txt
> >   | OK
>
> Have you tried with a host folder containing more than 256MiB?  What
> happens if you try to read all of it?

The access is crashing:
  | (host) $ du -sh vvfat-test/huge_file
  | 251M vvfat-test/huge_file
  | (host) $ qemu-system ... -drive
file=fat:rw:vvfat-test,format=raw,if=sd,size=128M
  | (QEMU) # tail /mnt/huge_file
  | [   29.325885] attempt to access beyond end of device
  | [   29.325885] mmcblk1p1: rw=524288, want=510657, limit=262081
  | [   29.337672] attempt to access beyond end of device
  | [   29.337672] mmcblk1p1: rw=0, want=510657, limit=262081
  | tail: read error: I/O error


> > Now, QNX comes into play.
> > First, the SD card must be connected to another bus. That patch is not
> > part of this series as I'm considering it a QNX issue. Just FTR here
> > is the patch:
> >   | --- a/hw/arm/bcm2838_peripherals.c
> >   | +++ b/hw/arm/bcm2838_peripherals.c
> >   | @@ -190,7 +190,7 @@ static void
> > bcm2838_peripherals_realize(DeviceState *dev, Error **errp)
> >   |          &s_base->peri_mr, GPIO_OFFSET,
> >   |          sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->gpio), 0));
> >   |
> >   | -    object_property_add_alias(OBJECT(s), "sd-bus",
> > OBJECT(&s->gpio), "sd-bus");
> >   | +    object_property_add_alias(OBJECT(s), "sd-bus",
> > OBJECT(&s->emmc2), "sd-bus");
> >   |
> >   |      /* BCM2838 RPiVid ASB must be mapped to prevent kernel crash */
> >
> > Afterwards, QNX is able to see the SD card, but not able to mount it.
> > It complains about the filesystem being corrupted. Looking at `fdisk`
> > output, it shows a mismatch between the "total section" value and the
> > Cylinders/Heads/etc values.
> >   | (QEMU) # fdisk /dev/hd0 info
> >   | Physical disk characteristics: (/dev/hd0)
> >   |     Disk type        : Direct Access (0)
> >   |     Cylinders        : 520
> >   |     Heads            : 16
> >   |     Sectors/Track    : 63
> >   |     Total Sectors    : 524288
> >   |     Block Size       : 512
> >   |
> >   | Warning: total sectors field does not agree with
> >   |            cylinders*sectors/track*heads!! (524288 vs 524160)
>
> I'm not sure this mismatch causes the problem.  I suspect the bogus
> EndLBA does.
>
> > The "no-mbr" option introduced in patch 1 is something we (Adacore's
> > QEMU team) have for a long time. I don't remember the details but we
> > are using it for other OSes as well (notably RTEMS).
>
> Suppressing MBR initialization avoids the partially bogus partition
> table.
>
> But if we create a partition table, it better make sense, don't you
> think?

My understanding is that `format=vvfat,size=xxxM` results in a valid
EndLBA. Is that enough to make a valid partition table ?
However, I'm still getting the corrupted error without `no-mbr`.
Though, the warning is gone too (compared to `format=raw,size=xxx`).
So this is something else QNX doesn't like...

Something weird if just noticed, the disk CHS values are changed when
passing `no-mbr`
  | (host) $ qemu-system-aarch64 -drive
file=fat:rw:<host_folder>:format=vvfat,size=128M
  | (QEMU) # fdisk -l /dev/mmcblk1
  | Disk /dev/mmcblk1: 128 MB, 134217728 bytes, 262144 sectors
  | 1024 cylinders, 8 heads, 32 sectors/track
  |
  | (host) $ qemu-system-aarch64 -drive
file=fat:rw:no-mbr:<host_folder>:format=vvfat,size=128M
  | (QEMU) # fdisk -l /dev/mmcblk1
  | Disk /dev/mmcblk1: 128 MB, 134217728 bytes, 262144 sectors
  | 4096 cylinders, 4 heads, 16 sectors/track

Not sure if it could be related.

> > Once added, and the drive command line updated for `-drive
> > id=sdcard,file=fat:rw:no-mbr:<host_folder>,format=raw,if=sd,size=256M`,
> > I don't have this warning anymore. Though, I'm still getting the
> > corrupted filesystem error.
> >
> > Afterwards, it's a bit blurry but I think by trial and errors we ended
> > up removing the SD size error and realize that `-drive
> > id=sdcard,file=fat:rw:no-mbr:<host_folder>,format=raw,if=sd` was
> > working. However, `size=256M` still results in a corrupted filesystem.
> > As a comment in vvfat.c states that it either creates a "32MB or 504
> > MB disk". I decided to check if I can adapt, hence this patch.
> >
> > I didn't find any VFAT documentation explaining the relation between
> > the size and the cylinders, heads, sector per track values. However,
> > the SD documentation was giving some recommandations, hence I used it
> > as a base.
> >
> > I was unable to make `vvfat.c` recognize the "size" argument passed
> > along `format=raw`, even if hardcoding the value in `vvfat.c` did make
> > a difference. And that's why I'm adding the warning in the commit
> > message.
>
> This one:
>
>     Some limitations remains, the size parameter is recognized only when
>     "format=vvfat" is passed. In particular, "format=raw,size=xxx" is
>     keeping the previously hardcoded value: 504MB for FAT16 and 32 MB for
>     FAT12. FAT32 has not been adjusted and thus still default to 504MB.
>
> > I've also realized that following my patch, the mismatch in between
> > the disk and the partition in Linux was going away when using `-drive
> > format=vvfat,size=xxx`. Making it not just QNX-oriented.
> >   | (host) $ qemu-system-aarch64 -M raspi4b -kernel raspi4b-kernel
> > -nographic -no-reboot -append "earlycon=pl011,mmio32,0xfe201000
> > console=ttyAMA0 noreboot" -dtb bcm2711-rpi-4-b.dtb -initrd
> > rootfs.cpio.gz  -drive
> > id=sdcard,file=fat:rw:<host_folder>,format=vvfat,if=sd,size=256M
> >   | (QEMU) # fdisk -l /dev/mmcblk1
> >   | Disk /dev/mmcblk1: 256 MB, 268435456 bytes, 524288 sectors
> >   | 1024 cylinders, 16 heads, 32 sectors/track
> >   | Units: sectors of 1 * 512 = 512 bytes
> >   |
> >   | Device       Boot StartCHS    EndCHS        StartLBA     EndLBA
> > Sectors  Size Id Type
> >   | /dev/mmcblk1p1 *  0,1,32      1023,15,32          63     524287
> >  524225  255M  6 FAT16
>
> EndLBA matches disk size.  EndCHS still matches EndLBA.  Good.
>
> The difference to the command line you showed above is format=raw (bad)
> vs. format=vvfat (good).
>
> With format=raw,size=256M you get that size, but a bogus partition
> table.
>
> With format=vvfat,size=256M you get that size, and a sensible partition
> table.
>
> Correct?

Yes and the main reason for that is because I don't know how to
retrieve the size given to "raw" within `vvfat_open`.
My understanding is that raw-format.c is suppressing that option,
through `qemu_opts_del` in `raw_read_options`, before calling its
block childs (here vvfat). Hence, it assumes the default size 512M.

> > I probably missed a few things, but I hope this is clearer to you why
> > and how this series was made.
>

Reply via email to