cannot use uefi-vars device on Windows (ucrt)
Host environment
- Operating system: Windows 11 23H2
- OS/kernel version:
MINGW64_NT-10.0-22631 MyHost 3.6.4-23a25d49.x86_64 <date> x86_64 Msys - Architecture: x64
- QEMU flavor:
qemu-system-x86_64 - QEMU version: master/
10.0.91 (v10.1.0-rc1-12-g4e06566dbd) - QEMU command line:
.\qemu-system-x86_64.exe -device uefi-vars-x64,jsonfile=uefi_vars.json ...
Emulated/Virtualized environment
- Operating system: UEFI
- OS/kernel version: OVMF (edk2 @a1b509c1a4)
- Architecture: x64
Description of problem
The uefi-vars device cannot read the JSON file on Windows (when using ucrt). When starting qemu, I get the following warning:
qemu-system-x86_64.exe: -device uefi-vars-x64,jsonfile=uefi_vars.json: warning: uefi_vars_json_load: read error
Steps to reproduce
- Start qemu once with the example command provided above, to initially create the
uefi_vars.jsonfile. - Start qemu again and notice the error message.
Additional information
The issue is with the way the uefi_vars_json_load tries to read the json file: It first gets the file size using lseek, before actually reading the file. However, the lseek always returns a higher number than is actually read. According to the UCRT docs, read converts the contents internally:
In text mode, each carriage return-line feed pair
\r\nis replaced with a single line feed character\n.
This causes the short read, because lseek reports the original size, while the read reports the shrinked file. The same applies to writing the file (see UCRT docs as well).
This may hint to a broader issue with the UCRT. A naive regex search (lseek\(.+, SEEK_END\);([^\n]*\n){1,20}[^\n]+read\() for similar call-sites fortunately didn't find any more results. However that may be because reading and opening may be separated (e.g. see get_image_size/load_image_size).
I'm happy to provide a patch, but I'm not sure how to resolve this. One option might be to open the file in binary mode, rather than text mode? However, I'm sure how that affects POSIX/Linux.