Brad Bishop | 96ff198 | 2019-08-19 13:50:42 -0400 | [diff] [blame^] | 1 | # |
| 2 | # This program is free software; you can redistribute it and/or modify |
| 3 | # it under the terms of the GNU General Public License version 2 as |
| 4 | # published by the Free Software Foundation. |
| 5 | # |
| 6 | # This program is distributed in the hope that it will be useful, |
| 7 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 8 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 9 | # GNU General Public License for more details. |
| 10 | # |
| 11 | # You should have received a copy of the GNU General Public License along |
| 12 | # with this program; if not, write to the Free Software Foundation, Inc., |
| 13 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
| 14 | # |
| 15 | # DESCRIPTION |
| 16 | # This implements the 'bootimg-biosplusefi' source plugin class for 'wic' |
| 17 | # |
| 18 | # AUTHORS |
| 19 | # William Bourque <wbourque [at) gmail.com> |
| 20 | |
| 21 | import types |
| 22 | |
| 23 | from wic.pluginbase import SourcePlugin |
| 24 | from importlib.machinery import SourceFileLoader |
| 25 | |
| 26 | class BootimgBiosPlusEFIPlugin(SourcePlugin): |
| 27 | """ |
| 28 | Create MBR + EFI boot partition |
| 29 | |
| 30 | This plugin creates a boot partition that contains both |
| 31 | legacy BIOS and EFI content. It will be able to boot from both. |
| 32 | This is useful when managing PC fleet with some older machines |
| 33 | without EFI support. |
| 34 | |
| 35 | Note it is possible to create an image that can boot from both |
| 36 | legacy BIOS and EFI by defining two partitions : one with arg |
| 37 | --source bootimg-efi and another one with --source bootimg-pcbios. |
| 38 | However, this method has the obvious downside that it requires TWO |
| 39 | partitions to be created on the storage device. |
| 40 | Both partitions will also be marked as "bootable" which does not work on |
| 41 | most BIOS, has BIOS often uses the "bootable" flag to determine |
| 42 | what to boot. If you have such a BIOS, you need to manually remove the |
| 43 | "bootable" flag from the EFI partition for the drive to be bootable. |
| 44 | Having two partitions also seems to confuse wic : the content of |
| 45 | the first partition will be duplicated into the second, even though it |
| 46 | will not be used at all. |
| 47 | |
| 48 | Also, unlike "isoimage-isohybrid" that also does BIOS and EFI, this plugin |
| 49 | allows you to have more than only a single rootfs partitions and does |
| 50 | not turn the rootfs into an initramfs RAM image. |
| 51 | |
| 52 | This plugin is made to put everything into a single /boot partition so it |
| 53 | does not have the limitations listed above. |
| 54 | |
| 55 | The plugin is made so it does tries not to reimplement what's already |
| 56 | been done in other plugins; as such it imports "bootimg-pcbios" |
| 57 | and "bootimg-efi". |
| 58 | Plugin "bootimg-pcbios" is used to generate legacy BIOS boot. |
| 59 | Plugin "bootimg-efi" is used to generate the UEFI boot. Note that it |
| 60 | requires a --sourceparams argument to know which loader to use; refer |
| 61 | to "bootimg-efi" code/documentation for the list of loader. |
| 62 | |
| 63 | Imports are handled with "SourceFileLoader" from importlib as it is |
| 64 | otherwise very difficult to import module that has hyphen "-" in their |
| 65 | filename. |
| 66 | The SourcePlugin() methods used in the plugins (do_install_disk, |
| 67 | do_configure_partition, do_prepare_partition) are then called on both, |
| 68 | beginning by "bootimg-efi". |
| 69 | |
| 70 | Plugin options, such as "--sourceparams" can still be passed to a |
| 71 | plugin, as long they does not cause issue in the other plugin. |
| 72 | |
| 73 | Example wic configuration: |
| 74 | part /boot --source bootimg-biosplusefi --sourceparams="loader=grub-efi"\\ |
| 75 | --ondisk sda --label os_boot --active --align 1024 --use-uuid |
| 76 | """ |
| 77 | |
| 78 | name = 'bootimg-biosplusefi' |
| 79 | |
| 80 | __PCBIOS_MODULE_NAME = "bootimg-pcbios" |
| 81 | __EFI_MODULE_NAME = "bootimg-efi" |
| 82 | |
| 83 | __imgEFIObj = None |
| 84 | __imgBiosObj = None |
| 85 | |
| 86 | @classmethod |
| 87 | def __init__(cls): |
| 88 | """ |
| 89 | Constructor (init) |
| 90 | """ |
| 91 | |
| 92 | # XXX |
| 93 | # For some reasons, __init__ constructor is never called. |
| 94 | # Something to do with how pluginbase works? |
| 95 | cls.__instanciateSubClasses() |
| 96 | |
| 97 | @classmethod |
| 98 | def __instanciateSubClasses(cls): |
| 99 | """ |
| 100 | |
| 101 | """ |
| 102 | |
| 103 | # Import bootimg-pcbios (class name "BootimgPcbiosPlugin") |
| 104 | modulePath = os.path.join(os.path.dirname(os.path.realpath(__file__)), |
| 105 | cls.__PCBIOS_MODULE_NAME + ".py") |
| 106 | loader = SourceFileLoader(cls.__PCBIOS_MODULE_NAME, modulePath) |
| 107 | mod = types.ModuleType(loader.name) |
| 108 | loader.exec_module(mod) |
| 109 | cls.__imgBiosObj = mod.BootimgPcbiosPlugin() |
| 110 | |
| 111 | # Import bootimg-efi (class name "BootimgEFIPlugin") |
| 112 | modulePath = os.path.join(os.path.dirname(os.path.realpath(__file__)), |
| 113 | cls.__EFI_MODULE_NAME + ".py") |
| 114 | loader = SourceFileLoader(cls.__EFI_MODULE_NAME, modulePath) |
| 115 | mod = types.ModuleType(loader.name) |
| 116 | loader.exec_module(mod) |
| 117 | cls.__imgEFIObj = mod.BootimgEFIPlugin() |
| 118 | |
| 119 | @classmethod |
| 120 | def do_install_disk(cls, disk, disk_name, creator, workdir, oe_builddir, |
| 121 | bootimg_dir, kernel_dir, native_sysroot): |
| 122 | """ |
| 123 | Called after all partitions have been prepared and assembled into a |
| 124 | disk image. |
| 125 | """ |
| 126 | |
| 127 | if ( (not cls.__imgEFIObj) or (not cls.__imgBiosObj) ): |
| 128 | cls.__instanciateSubClasses() |
| 129 | |
| 130 | cls.__imgEFIObj.do_install_disk( |
| 131 | disk, |
| 132 | disk_name, |
| 133 | creator, |
| 134 | workdir, |
| 135 | oe_builddir, |
| 136 | bootimg_dir, |
| 137 | kernel_dir, |
| 138 | native_sysroot) |
| 139 | |
| 140 | cls.__imgBiosObj.do_install_disk( |
| 141 | disk, |
| 142 | disk_name, |
| 143 | creator, |
| 144 | workdir, |
| 145 | oe_builddir, |
| 146 | bootimg_dir, |
| 147 | kernel_dir, |
| 148 | native_sysroot) |
| 149 | |
| 150 | @classmethod |
| 151 | def do_configure_partition(cls, part, source_params, creator, cr_workdir, |
| 152 | oe_builddir, bootimg_dir, kernel_dir, |
| 153 | native_sysroot): |
| 154 | """ |
| 155 | Called before do_prepare_partition() |
| 156 | """ |
| 157 | |
| 158 | if ( (not cls.__imgEFIObj) or (not cls.__imgBiosObj) ): |
| 159 | cls.__instanciateSubClasses() |
| 160 | |
| 161 | cls.__imgEFIObj.do_configure_partition( |
| 162 | part, |
| 163 | source_params, |
| 164 | creator, |
| 165 | cr_workdir, |
| 166 | oe_builddir, |
| 167 | bootimg_dir, |
| 168 | kernel_dir, |
| 169 | native_sysroot) |
| 170 | |
| 171 | cls.__imgBiosObj.do_configure_partition( |
| 172 | part, |
| 173 | source_params, |
| 174 | creator, |
| 175 | cr_workdir, |
| 176 | oe_builddir, |
| 177 | bootimg_dir, |
| 178 | kernel_dir, |
| 179 | native_sysroot) |
| 180 | |
| 181 | @classmethod |
| 182 | def do_prepare_partition(cls, part, source_params, creator, cr_workdir, |
| 183 | oe_builddir, bootimg_dir, kernel_dir, |
| 184 | rootfs_dir, native_sysroot): |
| 185 | """ |
| 186 | Called to do the actual content population for a partition i.e. it |
| 187 | 'prepares' the partition to be incorporated into the image. |
| 188 | """ |
| 189 | |
| 190 | if ( (not cls.__imgEFIObj) or (not cls.__imgBiosObj) ): |
| 191 | cls.__instanciateSubClasses() |
| 192 | |
| 193 | cls.__imgEFIObj.do_prepare_partition( |
| 194 | part, |
| 195 | source_params, |
| 196 | creator, |
| 197 | cr_workdir, |
| 198 | oe_builddir, |
| 199 | bootimg_dir, |
| 200 | kernel_dir, |
| 201 | rootfs_dir, |
| 202 | native_sysroot) |
| 203 | |
| 204 | cls.__imgBiosObj.do_prepare_partition( |
| 205 | part, |
| 206 | source_params, |
| 207 | creator, |
| 208 | cr_workdir, |
| 209 | oe_builddir, |
| 210 | bootimg_dir, |
| 211 | kernel_dir, |
| 212 | rootfs_dir, |
| 213 | native_sysroot) |