Parse efibootmgr type and details

This change improves the regex to match an exact entry name, and to also
match with the the entry type from a set of recognised types.
The boot entry details start from the recognised type onwards.

This can be used by a step which deletes all entries of type 'HW' and
UsbClass.

Related-Bug: #2041901
Change-Id: I5d879f724efc2919b541fd3fef0f931df67ff9c7
This commit is contained in:
Steve Baker 2023-11-06 15:29:13 +13:00
parent 768aa17442
commit 352df0bc54
2 changed files with 62 additions and 41 deletions

View File

@ -267,13 +267,16 @@ def _get_efi_bootloaders(location):
# NOTE(TheJulia): regex used to identify entries in the efibootmgr
# output on stdout.
_ENTRY_LABEL = re.compile(r'Boot([0-9a-f-A-F]+)\*?\s(.*).*$')
_ENTRY_LABEL = re.compile(
r'Boot([0-9a-f-A-F]+)\*?\s+(.*?)\s+'
r'((BBS|HD|FvFile|FvVol|PciRoot|VenMsg|VenHw|UsbClass)\(.*)$')
def get_boot_records():
"""Executes efibootmgr and returns boot records.
:return: an iterator yielding pairs (boot number, boot record).
:return: An iterator yielding tuples
(boot number, boot record, root device type, device path).
"""
# Invokes binary=True so we get a bytestream back.
efi_output = utils.execute('efibootmgr', '-v', binary=True)
@ -286,7 +289,7 @@ def get_boot_records():
for line in cmd_output.split('\n'):
match = _ENTRY_LABEL.match(line)
if match is not None:
yield (match[1], match[2])
yield (match[1], match[2], match[4], match[3])
def add_boot_record(device, efi_partition, loader, label):
@ -358,11 +361,11 @@ def _run_efibootmgr(valid_efi_bootloaders, device, efi_partition,
label = label + " " + str(label_suffix)
# Iterate through standard out, and look for duplicates
for boot_num, boot_rec in boot_records:
for boot_num, boot_rec, boot_type, boot_details in boot_records:
# Look for the base label in the string if a line match
# occurs, so we can identify if we need to eliminate the
# entry.
if label in boot_rec:
if label == boot_rec:
LOG.debug("Found bootnum %s matching label", boot_num)
remove_boot_record(boot_num)

View File

@ -211,9 +211,9 @@ class TestManageUefi(base.IronicAgentTest):
BootCurrent: 0001
Timeout: 0 seconds
BootOrder: 0001,0000,001B,001C,001D,001E,001F,0020,0021,0022,0012,0011,0023,0024,0002
Boot0000* Red Hat Enterprise Linux HD(1,GPT,34178504-2340-4fe0-8001-264372cf9b2d,0x800,0x64000)/File(\EFI\redhat\shimx64.efi)
Boot0001* Fedora HD(1,GPT,da6b4491-61f2-42b0-8ab1-7c4a87317c4e,0x800,0x64000)/File(\EFI\fedora\shimx64.efi)
Boot0002* Linux-Firmware-Updater HD(1,GPT,da6b4491-61f2-42b0-8ab1-7c4a87317c4e,0x800,0x64000)/File(\EFI\fedora\fwupdx64.efi)
Boot0000* Red Hat Enterprise Linux HD(1,GPT,34178504-2340-4fe0-8001-264372cf9b2d,0x800,0x64000)/File(\\EFI\\redhat\\shimx64.efi)
Boot0001* Fedora HD(1,GPT,da6b4491-61f2-42b0-8ab1-7c4a87317c4e,0x800,0x64000)/File(\\EFI\\fedora\\shimx64.efi)
Boot0002* Linux-Firmware-Updater HD(1,GPT,da6b4491-61f2-42b0-8ab1-7c4a87317c4e,0x800,0x64000)/File(\\EFI\\fedora\\fwupdx64.efi)
Boot0003 ThinkShield secure wipe FvFile(3593a0d5-bd52-43a0-808e-cbff5ece2477)
Boot0004 LENOVO CLOUD VenMsg(bc7838d2-0f82-4d60-8316-c068ee79d25b,ad38ccbbf7edf04d959cf42aa74d3650)/Uri(https://download.lenovo.com/pccbbs/cdeploy/efi/boot.efi)
Boot0005 IDER BOOT CDROM PciRoot(0x0)/Pci(0x14,0x0)/USB(11,1)
@ -229,53 +229,71 @@ Boot0009* Internal CD/DVD ROM Drive (UEFI) PciRoot(0x0)/Pci(0x11,0x0)/Sata(
mock_execute.return_value = (efibootmgr_resp, '')
result = list(efi_utils.get_boot_records())
def assertEntry(expected, actual):
self.assertEqual(2, len(actual))
self.assertEqual(expected[0], actual[0])
self.assertIn(expected[1], actual[1])
assertEntry(
('0000', 'Red Hat Enterprise Linux'),
self.assertEqual(
('0000', 'Red Hat Enterprise Linux', 'HD',
'HD(1,GPT,34178504-2340-4fe0-8001-264372cf9b2d,0x800,0x64000)/'
'File(\\EFI\\redhat\\shimx64.efi)'),
result[0])
assertEntry(
('0001', 'Fedora'),
self.assertEqual(
('0001', 'Fedora', 'HD',
'HD(1,GPT,da6b4491-61f2-42b0-8ab1-7c4a87317c4e,0x800,0x64000)/'
'File(\\EFI\\fedora\\shimx64.efi)'),
result[1])
assertEntry(
('0002', 'Linux-Firmware-Updater'),
self.assertEqual(
('0002', 'Linux-Firmware-Updater', 'HD',
'HD(1,GPT,da6b4491-61f2-42b0-8ab1-7c4a87317c4e,0x800,0x64000)/'
'File(\\EFI\\fedora\\fwupdx64.efi)'),
result[2])
assertEntry(
('0003', 'ThinkShield secure wipe'),
self.assertEqual(
('0003', 'ThinkShield secure wipe', 'FvFile',
'FvFile(3593a0d5-bd52-43a0-808e-cbff5ece2477)'),
result[3])
assertEntry(
('0004', 'LENOVO CLOUD'),
self.assertEqual(
('0004', 'LENOVO CLOUD', 'VenMsg',
'VenMsg(bc7838d2-0f82-4d60-8316-c068ee79d25b,'
'ad38ccbbf7edf04d959cf42aa74d3650)/'
'Uri(https://download.lenovo.com/pccbbs/cdeploy/efi/boot.efi)'),
result[4])
assertEntry(
('0005', 'IDER BOOT CDROM'),
self.assertEqual(
('0005', 'IDER BOOT CDROM', 'PciRoot',
'PciRoot(0x0)/Pci(0x14,0x0)/USB(11,1)'),
result[5])
assertEntry(
('0006', 'ATA HDD'),
self.assertEqual(
('0006', 'ATA HDD', 'VenMsg',
'VenMsg(bc7838d2-0f82-4d60-8316-c068ee79d25b,'
'91af625956449f41a7b91f4f892ab0f6)'),
result[6])
assertEntry(
('0007', 'Hard drive C:'),
self.assertEqual(
('0007', 'Hard drive C:', 'VenHw',
mock.ANY),
result[7])
assertEntry(
('AAA8', 'IBA GE Slot 0100 v1588'),
self.assertEqual(
('AAA8', 'IBA GE Slot 0100 v1588', 'BBS',
mock.ANY),
result[8])
assertEntry(
('0FF9', 'Virtual CD/DVD'),
self.assertEqual(
('0FF9', 'Virtual CD/DVD', 'PciRoot',
'PciRoot(0x0)/Pci(0x14,0x0)/USB(13,0)/USB(3,0)/USB(1,0)'),
result[9])
assertEntry(
('123A', 'Integrated NIC 1 Port 1 Partition 1'),
self.assertEqual(
('123A', 'Integrated NIC 1 Port 1 Partition 1', 'VenHw',
'VenHw(33391845-5f86-4e78-8fce-c4cff59f9bbb)'),
result[10])
assertEntry(
self.assertEqual(
('000B',
'UEFI: PXE IPv4 Realtek PCIe 2.5GBE Family Controller'),
'UEFI: PXE IPv4 Realtek PCIe 2.5GBE Family Controller',
'PciRoot',
'PciRoot(0x0)/Pci(0x1c,0x0)/Pci(0x0,0x0)/MAC([REDACTED],0)/'
'IPv4(0.0.0.00.0.0.0,0,0)..BO'),
result[11])
assertEntry(
('0008', 'Generic USB Boot'),
self.assertEqual(
('0008', 'Generic USB Boot', 'UsbClass',
'UsbClass(ffff,ffff,255,255)'),
result[12])
assertEntry(
('0009', 'Internal CD/DVD ROM Drive (UEFI'),
self.assertEqual(
('0009', 'Internal CD/DVD ROM Drive (UEFI)', 'PciRoot',
'PciRoot(0x0)/Pci(0x11,0x0)/Sata(1,65535,0)/'
'CDROM(1,0x265,0x2000)'),
result[13])
@mock.patch.object(os.path, 'exists', lambda *_: False)