Skip to content

Commit 1fb8c0c

Browse files
TheMipmapkubajj
andcommitted
Fix for motherboards where efibootmgr returns UTF-8.
Some motherboards return UTF-8 for the efibootmgr. This results in IPA not being able to remove duplicate records, etc. This change implements a check for UTF-16 compatibility and tries to decode efibootmgr output as UTF-8 otherwise. Closes-bug: #2072336 Co-Authored-By: Jakub Jelinek <jakub.jelinek@cern.ch> Change-Id: I35432773826d13edb1dc9dd25f99bb0907a8fa0d Signed-off-by: Morten Stephansen <morten.kaastrup.stephansen@cern.ch> Signed-off-by: Jakub Jelinek <jakub.jelinek@cern.ch> (cherry picked from commit f302c1c)
1 parent d11fa50 commit 1fb8c0c

File tree

2 files changed

+102
-2
lines changed

2 files changed

+102
-2
lines changed

ironic_python_agent/efi_utils.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -285,8 +285,15 @@ def get_boot_records():
285285
# Also ignore errors on decoding, as we can basically get
286286
# garbage out of the nvram record, this way we don't fail
287287
# hard on unrelated records.
288-
cmd_output = efi_output[0].decode('utf-16', errors='ignore')
289-
for line in cmd_output.split('\n'):
288+
cmd_output = efi_output[0].decode('utf-16', errors='ignore').split('\n')
289+
# Check that the output is encoded as UTF-16 otherwise try UTF-8.
290+
_DETECT_ENCODING_STRING = "BootCurrent: "
291+
for line in cmd_output:
292+
if line.startswith(_DETECT_ENCODING_STRING):
293+
break
294+
else:
295+
cmd_output = efi_output[0].decode('utf-8', errors='ignore').split('\n')
296+
for line in cmd_output:
290297
match = _ENTRY_LABEL.match(line)
291298
if match is not None:
292299
yield (match[1], match[2], match[4], match[3])

ironic_python_agent/tests/unit/test_efi_utils.py

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,99 @@ def test_get_boot_record(self, mock_utils_efi_part,
296296
'CDROM(1,0x265,0x2000)'),
297297
result[13])
298298

299+
def test_get_boot_records_utf_8(self, mock_utils_efi_part,
300+
mock_get_part_path,
301+
mock_get_part_uuid, mock_execute,
302+
mock_rescan):
303+
efibootmgr_resp = """
304+
BootCurrent: 0001
305+
Timeout: 0 seconds
306+
BootOrder: 0001,0000,001B,001C,001D,001E,001F,0020,0021,0022,0012,0011,0023,0024,0002
307+
Boot0000* Red Hat Enterprise Linux HD(1,GPT,34178504-2340-4fe0-8001-264372cf9b2d,0x800,0x64000)/File(\\EFI\\redhat\\shimx64.efi)
308+
Boot0001* Fedora HD(1,GPT,da6b4491-61f2-42b0-8ab1-7c4a87317c4e,0x800,0x64000)/File(\\EFI\\fedora\\shimx64.efi)
309+
Boot0002* Linux-Firmware-Updater HD(1,GPT,da6b4491-61f2-42b0-8ab1-7c4a87317c4e,0x800,0x64000)/File(\\EFI\\fedora\\fwupdx64.efi)
310+
Boot0003 ThinkShield secure wipe FvFile(3593a0d5-bd52-43a0-808e-cbff5ece2477)
311+
Boot0004 LENOVO CLOUD VenMsg(bc7838d2-0f82-4d60-8316-c068ee79d25b,ad38ccbbf7edf04d959cf42aa74d3650)/Uri(https://download.lenovo.com/pccbbs/cdeploy/efi/boot.efi)
312+
Boot0005 IDER BOOT CDROM PciRoot(0x0)/Pci(0x14,0x0)/USB(11,1)
313+
Boot0006 ATA HDD VenMsg(bc7838d2-0f82-4d60-8316-c068ee79d25b,91af625956449f41a7b91f4f892ab0f6)
314+
Boot0007* Hard drive C: VenHw(d6c0639f-c705-4eb9-aa4f-5802d8823de6)......................................................................................A.....................P.E.R.C. .H.7.3.0.P. .M.i.n.i.(.b.u.s. .1.8. .d.e.v. .0.0.)...
315+
BootAAA8* IBA GE Slot 0100 v1588 BBS(128,IBA GE Slot 0100 v1588,0x0)........................B.............................................................A.....................I.B.A. .G.E. .S.l.o.t. .0.1.0.0. .v.1.5.8.8...
316+
Boot0FF9* Virtual CD/DVD PciRoot(0x0)/Pci(0x14,0x0)/USB(13,0)/USB(3,0)/USB(1,0)
317+
Boot123A* Integrated NIC 1 Port 1 Partition 1 VenHw(33391845-5f86-4e78-8fce-c4cff59f9bbb)
318+
Boot000B* UEFI: PXE IPv4 Realtek PCIe 2.5GBE Family Controller PciRoot(0x0)/Pci(0x1c,0x0)/Pci(0x0,0x0)/MAC([REDACTED],0)/IPv4(0.0.0.00.0.0.0,0,0)..BO
319+
Boot0008* Generic USB Boot UsbClass(ffff,ffff,255,255)
320+
Boot0009* Internal CD/DVD ROM Drive (UEFI) PciRoot(0x0)/Pci(0x11,0x0)/Sata(1,65535,0)/CDROM(1,0x265,0x2000)
321+
""".encode('utf-8') # noqa This is a giant literal string for testing.
322+
mock_execute.return_value = (efibootmgr_resp, '')
323+
result = list(efi_utils.get_boot_records())
324+
325+
self.assertEqual(
326+
('0000', 'Red Hat Enterprise Linux', 'HD',
327+
'HD(1,GPT,34178504-2340-4fe0-8001-264372cf9b2d,0x800,0x64000)/'
328+
'File(\\EFI\\redhat\\shimx64.efi)'),
329+
result[0])
330+
self.assertEqual(
331+
('0001', 'Fedora', 'HD',
332+
'HD(1,GPT,da6b4491-61f2-42b0-8ab1-7c4a87317c4e,0x800,0x64000)/'
333+
'File(\\EFI\\fedora\\shimx64.efi)'),
334+
result[1])
335+
self.assertEqual(
336+
('0002', 'Linux-Firmware-Updater', 'HD',
337+
'HD(1,GPT,da6b4491-61f2-42b0-8ab1-7c4a87317c4e,0x800,0x64000)/'
338+
'File(\\EFI\\fedora\\fwupdx64.efi)'),
339+
result[2])
340+
self.assertEqual(
341+
('0003', 'ThinkShield secure wipe', 'FvFile',
342+
'FvFile(3593a0d5-bd52-43a0-808e-cbff5ece2477)'),
343+
result[3])
344+
self.assertEqual(
345+
('0004', 'LENOVO CLOUD', 'VenMsg',
346+
'VenMsg(bc7838d2-0f82-4d60-8316-c068ee79d25b,'
347+
'ad38ccbbf7edf04d959cf42aa74d3650)/'
348+
'Uri(https://download.lenovo.com/pccbbs/cdeploy/efi/boot.efi)'),
349+
result[4])
350+
self.assertEqual(
351+
('0005', 'IDER BOOT CDROM', 'PciRoot',
352+
'PciRoot(0x0)/Pci(0x14,0x0)/USB(11,1)'),
353+
result[5])
354+
self.assertEqual(
355+
('0006', 'ATA HDD', 'VenMsg',
356+
'VenMsg(bc7838d2-0f82-4d60-8316-c068ee79d25b,'
357+
'91af625956449f41a7b91f4f892ab0f6)'),
358+
result[6])
359+
self.assertEqual(
360+
('0007', 'Hard drive C:', 'VenHw',
361+
mock.ANY),
362+
result[7])
363+
self.assertEqual(
364+
('AAA8', 'IBA GE Slot 0100 v1588', 'BBS',
365+
mock.ANY),
366+
result[8])
367+
self.assertEqual(
368+
('0FF9', 'Virtual CD/DVD', 'PciRoot',
369+
'PciRoot(0x0)/Pci(0x14,0x0)/USB(13,0)/USB(3,0)/USB(1,0)'),
370+
result[9])
371+
self.assertEqual(
372+
('123A', 'Integrated NIC 1 Port 1 Partition 1', 'VenHw',
373+
'VenHw(33391845-5f86-4e78-8fce-c4cff59f9bbb)'),
374+
result[10])
375+
self.assertEqual(
376+
('000B',
377+
'UEFI: PXE IPv4 Realtek PCIe 2.5GBE Family Controller',
378+
'PciRoot',
379+
'PciRoot(0x0)/Pci(0x1c,0x0)/Pci(0x0,0x0)/MAC([REDACTED],0)/'
380+
'IPv4(0.0.0.00.0.0.0,0,0)..BO'),
381+
result[11])
382+
self.assertEqual(
383+
('0008', 'Generic USB Boot', 'UsbClass',
384+
'UsbClass(ffff,ffff,255,255)'),
385+
result[12])
386+
self.assertEqual(
387+
('0009', 'Internal CD/DVD ROM Drive (UEFI)', 'PciRoot',
388+
'PciRoot(0x0)/Pci(0x11,0x0)/Sata(1,65535,0)/'
389+
'CDROM(1,0x265,0x2000)'),
390+
result[13])
391+
299392
@mock.patch.object(os.path, 'exists', lambda *_: False)
300393
@mock.patch.object(hardware, 'is_md_device', autospec=True)
301394
@mock.patch.object(efi_utils, '_get_efi_bootloaders', autospec=True)

0 commit comments

Comments
 (0)