diff --git a/doc/source/image_description/elements.rst b/doc/source/image_description/elements.rst
index d8dcb5a87ef..6f9fbe779a6 100644
--- a/doc/source/image_description/elements.rst
+++ b/doc/source/image_description/elements.rst
@@ -402,7 +402,7 @@ efifatimagesize="nonNegativeInteger":
efiparttable="msdos|gpt":
For images with an EFI firmware specifies the partition
table type to use. If not set defaults to the GPT partition
- table type
+ table type for disk images, MBR (msdos) for ISO images.
dosparttable_extended_layout="true|false":
For oem disk images, specifies to make use of logical partitions
@@ -889,7 +889,14 @@ force_mbr="true|false":
partitions
gpt_hybrid_mbr="true|false":
- For GPT disk types only: Create a hybrid GPT/MBR partition table
+ For disk types, create a hybrid GPT/MBR partition table with an
+ 'accurate' MBR table that will have no 'bootable' flagged partition
+ For ISO types, create a hybrid GPT/MBR partition table where the
+ MBR partition table contains a whole-disk 'protective' partition
+ and a second bootable-flagged partition (intended to make the image
+ bootable in both UEFI and BIOS modes on as much hardware as possible)
+ In both cases, only has any effect if the EFI partition table
+ type is GPT
hybridpersistent="true|false":
For the live ISO type, triggers the creation of a partition for
diff --git a/kiwi/builder/install.py b/kiwi/builder/install.py
index bebf16ce4bc..40adc305a6d 100644
--- a/kiwi/builder/install.py
+++ b/kiwi/builder/install.py
@@ -161,6 +161,8 @@ def create_install_iso(self) -> None:
'mbr_id': self.mbrid.get_id(),
'application_id': self.xml_state.build_type.get_application_id(),
'efi_mode': self.firmware.efi_mode(),
+ 'efi_partition_table': self.firmware.get_partition_table_type(),
+ 'gpt_hybrid_mbr': self.firmware.gpt_hybrid_mbr,
'ofw_mode': self.firmware.ofw_mode(),
'legacy_bios_mode': self.firmware.legacy_bios_mode()
}
diff --git a/kiwi/builder/live.py b/kiwi/builder/live.py
index 509f9016ca3..988701aa434 100644
--- a/kiwi/builder/live.py
+++ b/kiwi/builder/live.py
@@ -144,6 +144,8 @@ def create(self) -> Result:
'mbr_id': self.mbrid.get_id(),
'application_id': self.application_id,
'efi_mode': self.firmware.efi_mode(),
+ 'efi_partition_table': self.firmware.get_partition_table_type(),
+ 'gpt_hybrid_mbr': self.firmware.gpt_hybrid_mbr,
'legacy_bios_mode': self.firmware.legacy_bios_mode()
}
}
diff --git a/kiwi/filesystem/isofs.py b/kiwi/filesystem/isofs.py
index 96df8e4395c..a2c14229c08 100644
--- a/kiwi/filesystem/isofs.py
+++ b/kiwi/filesystem/isofs.py
@@ -50,6 +50,6 @@ def create_on_file(
iso_tool.init_iso_creation_parameters(meta_data)
if efi_loader:
- iso_tool.add_efi_loader_parameters(efi_loader)
+ iso_tool.add_efi_loader_parameters(efi_loader, meta_data)
iso_tool.create_iso(self.filename)
diff --git a/kiwi/firmware.py b/kiwi/firmware.py
index 8b03f4fae4b..624a21f2cdd 100644
--- a/kiwi/firmware.py
+++ b/kiwi/firmware.py
@@ -42,6 +42,7 @@ def __init__(self, xml_state):
self.firmware = xml_state.build_type.get_firmware()
self.efipart_mbytes = xml_state.build_type.get_efipartsize()
self.efi_partition_table = xml_state.build_type.get_efiparttable()
+ self.gpt_hybrid_mbr = xml_state.build_type.get_gpt_hybrid_mbr()
self.efi_csm = True if xml_state.build_type.get_eficsm() is None \
else xml_state.build_type.get_eficsm()
diff --git a/kiwi/iso_tools/base.py b/kiwi/iso_tools/base.py
index 02973a64b2f..fa0cf182812 100644
--- a/kiwi/iso_tools/base.py
+++ b/kiwi/iso_tools/base.py
@@ -19,7 +19,7 @@
import shutil
import logging
from typing import (
- Dict, List, Union
+ Dict, List, Optional, Union
)
# project
@@ -72,7 +72,9 @@ def init_iso_creation_parameters(
"""
raise NotImplementedError
- def add_efi_loader_parameters(self, loader_file: str) -> None:
+ def add_efi_loader_parameters(
+ self, loader_file: str, custom_args: Optional[Dict[str, Union[str, bool]]] = None
+ ) -> None:
"""
Add ISO creation parameters to embed the EFI loader
diff --git a/kiwi/iso_tools/xorriso.py b/kiwi/iso_tools/xorriso.py
index 39eab4f3204..f532584aae6 100644
--- a/kiwi/iso_tools/xorriso.py
+++ b/kiwi/iso_tools/xorriso.py
@@ -103,6 +103,11 @@ def init_iso_creation_parameters(
self.iso_parameters += [
'-compliance', 'untranslated_names'
]
+ else:
+ self.iso_parameters += [
+ # https://lists.gnu.org/archive/html/bug-xorriso/2024-11/msg00012.html
+ '-compliance', 'no_emul_toc'
+ ]
if Defaults.is_x86_arch(self.arch) and legacy_bios_mode:
mbr_file = os.sep.join(
@@ -145,7 +150,9 @@ def init_iso_creation_parameters(
'-boot_image', 'any', 'load_size=2048'
]
- def add_efi_loader_parameters(self, loader_file: str) -> None:
+ def add_efi_loader_parameters(
+ self, loader_file: str, custom_args: Optional[Dict[str, Union[str, bool]]] = None
+ ) -> None:
"""
Add ISO creation parameters to embed the EFI loader
@@ -156,6 +163,18 @@ def add_efi_loader_parameters(self, loader_file: str) -> None:
file refer to _create_embedded_fat_efi_image() from
bootloader/config/grub2.py
"""
+ if custom_args:
+ efi_partition_table = custom_args.get('efi_partition_table', '')
+ legacy_bios_mode = custom_args.get('legacy_bios_mode', False)
+ gpt_hybrid_mbr = custom_args.get('gpt_hybrid_mbr', False)
+ if efi_partition_table == 'gpt':
+ self.iso_loaders += [
+ '-boot_image', 'any', 'appended_part_as=gpt',
+ ]
+ if gpt_hybrid_mbr and legacy_bios_mode:
+ self.iso_loaders += [
+ '-boot_image', 'any', 'mbr_force_bootable=on',
+ ]
self.iso_loaders += [
'-append_partition', '2', '0xef', loader_file,
'-boot_image', 'any', 'next',
@@ -189,3 +208,10 @@ def create_iso(
'-chmod', '0755', '/', '--'
] + self.iso_loaders + hidden_files_parameters
)
+ report_call = Command.run(
+ [
+ self.get_tool_name(), '-indev', filename,
+ '-report_system_area', 'plain'
+ ]
+ )
+ log.debug(report_call.output)
diff --git a/kiwi/schema/kiwi.rnc b/kiwi/schema/kiwi.rnc
index e029c613ee9..80db9bcde6c 100644
--- a/kiwi/schema/kiwi.rnc
+++ b/kiwi/schema/kiwi.rnc
@@ -1687,7 +1687,7 @@ div {
attribute efiparttable { "msdos" | "gpt" }
>> sch:pattern [ id = "efiparttable" is-a = "image_type"
sch:param [ name = "attr" value = "efiparttable" ]
- sch:param [ name = "types" value = "oem" ]
+ sch:param [ name = "types" value = "oem iso" ]
]
k.type.bootprofile.attribute =
## Specifies the boot profile defined in the boot image
@@ -2012,7 +2012,7 @@ div {
attribute gpt_hybrid_mbr { xsd:boolean }
>> sch:pattern [ id = "gpt_hybrid_mbr" is-a = "image_type"
sch:param [ name = "attr" value = "gpt_hybrid_mbr" ]
- sch:param [ name = "types" value = "oem" ]
+ sch:param [ name = "types" value = "oem iso" ]
]
k.type.initrd_system.attribute =
## specify which initrd builder to use, default is dracut
diff --git a/kiwi/schema/kiwi.rng b/kiwi/schema/kiwi.rng
index 409d4dded60..ecb9bb46521 100644
--- a/kiwi/schema/kiwi.rng
+++ b/kiwi/schema/kiwi.rng
@@ -2473,7 +2473,7 @@ table type.
-
+
@@ -2907,7 +2907,7 @@ create a hybrid GPT/MBR partition table
-
+
diff --git a/test/unit/builder/live_test.py b/test/unit/builder/live_test.py
index 0925838a57f..7addf9d8f06 100644
--- a/test/unit/builder/live_test.py
+++ b/test/unit/builder/live_test.py
@@ -247,6 +247,8 @@ def side_effect():
self.setup.export_package_list.return_value = '.packages'
self.firmware.bios_mode.return_value = False
+ self.firmware.get_partition_table_type.return_value = 'gpt'
+ self.firmware.gpt_hybrid_mbr = False
self.live_image.create()
self.setup.import_cdroot_files.assert_called_once_with('temp_media_dir')
@@ -369,6 +371,8 @@ def side_effect():
'volume_id': 'volid',
'efi_mode': 'uefi',
'efi_loader': 'kiwi-tmpfile',
+ 'efi_partition_table': 'gpt',
+ 'gpt_hybrid_mbr': False,
'udf': True,
'legacy_bios_mode': True
}
diff --git a/test/unit/filesystem/isofs_test.py b/test/unit/filesystem/isofs_test.py
index 6eef15435a2..b5abdb4aee8 100644
--- a/test/unit/filesystem/isofs_test.py
+++ b/test/unit/filesystem/isofs_test.py
@@ -58,5 +58,6 @@ def test_create_on_file_EFI_enabled(self, mock_IsoTools):
self.isofs.create_on_file('myimage')
iso_tool.create_iso.assert_called_once_with('myimage')
iso_tool.add_efi_loader_parameters.assert_called_once_with(
- 'esp-image-file'
+ 'esp-image-file',
+ {'efi_mode': 'uefi', 'efi_loader': 'esp-image-file'}
)
diff --git a/test/unit/iso_tools/xorriso_test.py b/test/unit/iso_tools/xorriso_test.py
index 9eb5112d718..36e86eb6680 100644
--- a/test/unit/iso_tools/xorriso_test.py
+++ b/test/unit/iso_tools/xorriso_test.py
@@ -1,5 +1,7 @@
import logging
-from unittest.mock import patch
+from unittest.mock import (
+ patch, call
+)
from pytest import (
raises, fixture
)
@@ -94,7 +96,8 @@ def test_init_iso_creation_parameters_efi(self, mock_os_path_exists):
'-preparer_id', 'preparer',
'-volid', 'vol_id',
'-joliet', 'on',
- '-padding', '0'
+ '-padding', '0',
+ '-compliance', 'no_emul_toc'
]
assert self.iso_tool.iso_loaders == [
'-boot_image', 'grub',
@@ -133,7 +136,8 @@ def test_init_iso_creation_parameters_efi_custom_app_id(
'-preparer_id', 'preparer',
'-volid', 'vol_id',
'-joliet', 'on',
- '-padding', '0'
+ '-padding', '0',
+ '-compliance', 'no_emul_toc'
]
def test_add_efi_loader_parameters(self):
@@ -147,6 +151,41 @@ def test_add_efi_loader_parameters(self):
'-boot_image', 'any', 'emul_type=no_emulation'
]
+ def test_add_efi_loader_parameters_gpt(self):
+ self.iso_tool.add_efi_loader_parameters(
+ 'target_dir/efi-loader',
+ {'efi_partition_table': 'gpt'}
+ )
+ assert self.iso_tool.iso_loaders == [
+ '-boot_image', 'any', 'appended_part_as=gpt',
+ '-append_partition', '2', '0xef', 'target_dir/efi-loader',
+ '-boot_image', 'any', 'next',
+ '-boot_image', 'any',
+ 'efi_path=--interval:appended_partition_2:all::',
+ '-boot_image', 'any', 'platform_id=0xef',
+ '-boot_image', 'any', 'emul_type=no_emulation'
+ ]
+
+ def test_add_efi_loader_parameters_gpt_hybrid(self):
+ self.iso_tool.add_efi_loader_parameters(
+ 'target_dir/efi-loader',
+ {
+ 'efi_partition_table': 'gpt',
+ 'legacy_bios_mode': True,
+ 'gpt_hybrid_mbr': True
+ }
+ )
+ assert self.iso_tool.iso_loaders == [
+ '-boot_image', 'any', 'appended_part_as=gpt',
+ '-boot_image', 'any', 'mbr_force_bootable=on',
+ '-append_partition', '2', '0xef', 'target_dir/efi-loader',
+ '-boot_image', 'any', 'next',
+ '-boot_image', 'any',
+ 'efi_path=--interval:appended_partition_2:all::',
+ '-boot_image', 'any', 'platform_id=0xef',
+ '-boot_image', 'any', 'emul_type=no_emulation'
+ ]
+
@patch('kiwi.iso_tools.xorriso.Command.run')
@patch('kiwi.iso_tools.xorriso.Path.wipe')
@patch('kiwi.iso_tools.xorriso.Path.which')
@@ -154,15 +193,23 @@ def test_create_iso(self, mock_which, mock_wipe, mock_command):
mock_which.return_value = '/usr/bin/xorriso'
self.iso_tool.create_iso('myiso', hidden_files=['hide_me'])
mock_wipe.assert_called_once_with('myiso')
- mock_command.assert_called_once_with(
- [
- '/usr/bin/xorriso',
- '-outdev', 'myiso',
- '-map', 'source-dir', '/',
- '-chmod', '0755', '/', '--',
- '--', '-find', 'hide_me', '-exec', 'hide', 'on'
- ]
- )
+ assert mock_command.call_args_list == [
+ call(
+ [
+ '/usr/bin/xorriso',
+ '-outdev', 'myiso',
+ '-map', 'source-dir', '/',
+ '-chmod', '0755', '/', '--',
+ '--', '-find', 'hide_me', '-exec', 'hide', 'on'
+ ]
+ ),
+ call(
+ [
+ '/usr/bin/xorriso', '-indev', 'myiso',
+ '-report_system_area', 'plain'
+ ]
+ )
+ ]
def test_has_iso_hybrid_capability(self):
assert self.iso_tool.has_iso_hybrid_capability() is True