1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
|
Author: Michael Tokarev <mjt@tls.msk.ru>
Origin: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1121761#5
Bug: https://gitlab.com/kraxel/virt-firmware/-/issues/18
Bug-Debian: https://bugs.debian.org/1121761
Last-Updated: 2025-12-02
There's a bug in virt/firmware/varstore/edk2.py when
reading varstore images, - it uses native endiannes
instead of little-endian.
def parse_volume(self):
...
(vlen, sig, attr, hlen, csum, xoff, rev, blocks, blksize) = \
struct.unpack_from("=QLLHHHxBLL", self.filedata, offset + 32)
logging.debug('vol=%s vlen=0x%x rev=%d blocks=%d*%d (0x%x)',
guids.name(guid), vlen, rev,
blocks, blksize, blocks * blksize)
if sig != 0x4856465f:
logging.error('%s: not a firmware volume', self.filename)
sys.exit(1)
When reading AAVMF_VARS.fd, on a little-endian system, this results in:
DEBUG:root:vol=guid:NvData vlen=0xc0000 rev=2 blocks=3*262144 (0xc0000)
The same code and input, when run on s390x, results in:
DEBUG:root:vol=guid:NvData vlen=0xc0000000000 rev=2 blocks=50331648*1024 (0xc00000000)
ERROR:root:AAVMF_VARS.fd: not a firmware volume
The unpack_from() call should have "<" (little-endian) as the first symbol
instead of "=" (native-endian), since it is reading an image defined as
having little-endian characteristics.
See two edk2 debci runs, on amd64 (sucessful) and on s390x (failed):
https://ci.debian.net/packages/e/edk2/testing/amd64/66712410/
https://ci.debian.net/packages/e/edk2/testing/s390x/66711962/
There are other places in this file where the same "=" (native) conversion
is used, - these should probably be fixed too.
Attached is a small patch (untested yet) which should fix this.
Thanks,
/mjt
diff --git a/virt/firmware/varstore/edk2.py b/virt/firmware/varstore/edk2.py
index 33b2738..54db6e1 100644
--- a/virt/firmware/varstore/edk2.py
+++ b/virt/firmware/varstore/edk2.py
@@ -62,5 +62,5 @@ class Edk2VarStore:
guid = guids.parse_bin(self.filedata, offset + 16)
(vlen, sig, attr, hlen, csum, xoff, rev, blocks, blksize) = \
- struct.unpack_from("=QLLHHHxBLL", self.filedata, offset + 32)
+ struct.unpack_from("<QLLHHHxBLL", self.filedata, offset + 32)
logging.debug('vol=%s vlen=0x%x rev=%d blocks=%d*%d (0x%x)',
guids.name(guid), vlen, rev,
@@ -76,5 +76,5 @@ class Edk2VarStore:
def parse_varstore(self, start):
guid = guids.parse_bin(self.filedata, start)
- (size, storefmt, state) = struct.unpack_from("=LBB", self.filedata, start + 16)
+ (size, storefmt, state) = struct.unpack_from("<LBB", self.filedata, start + 16)
logging.debug('varstore=%s size=0x%x format=0x%x state=0x%x',
guids.name(guid), size, storefmt, state)
@@ -97,8 +97,8 @@ class Edk2VarStore:
varlist = efivar.EfiVarList()
while pos < self.end:
- (magic, state, attr, count) = struct.unpack_from("=HBxLQ", self.filedata, pos)
+ (magic, state, attr, count) = struct.unpack_from("<HBxLQ", self.filedata, pos)
if magic != 0x55aa:
break
- (pk, nsize, dsize) = struct.unpack_from("=LLL", self.filedata, pos + 32)
+ (pk, nsize, dsize) = struct.unpack_from("<LLL", self.filedata, pos + 32)
if state == 0x3f:
|