Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 1 | # ex:ts=4:sw=4:sts=4:et |
| 2 | # -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- |
| 3 | # |
| 4 | # This program is free software; you can distribute it and/or modify |
| 5 | # it under the terms of the GNU General Public License version 2 as |
| 6 | # published by the Free Software Foundation. |
| 7 | # |
| 8 | # This program is distributed in the hope that it will be useful, |
| 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 11 | # GNU General Public License for mo details. |
| 12 | # |
| 13 | # You should have received a copy of the GNU General Public License along |
| 14 | # with this program; if not, write to the Free Software Foundation, Inc., |
| 15 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
| 16 | # |
| 17 | # AUTHOR |
| 18 | # Adrian Freihofer <adrian.freihofer (at] neratec.com> |
| 19 | # |
| 20 | |
| 21 | import os |
| 22 | from wic import kickstart |
| 23 | from wic import msger |
| 24 | from wic.utils import syslinux |
| 25 | from wic.utils import runner |
| 26 | from wic.utils.oe import misc |
| 27 | from wic.utils.errors import ImageError |
| 28 | from wic.pluginbase import SourcePlugin |
| 29 | |
| 30 | |
| 31 | # pylint: disable=no-init |
| 32 | class RootfsPlugin(SourcePlugin): |
| 33 | """ |
| 34 | Create root partition and install syslinux bootloader |
| 35 | |
| 36 | This plugin creates a disk image containing a bootable root partition with |
| 37 | syslinux installed. The filesystem is ext2/3/4, no extra boot partition is |
| 38 | required. |
| 39 | |
| 40 | Example kickstart file: |
| 41 | part / --source rootfs-pcbios-ext --ondisk sda --fstype=ext4 --label rootfs --align 1024 |
| 42 | bootloader --source rootfs-pcbios-ext --timeout=0 --append="rootwait rootfstype=ext4" |
| 43 | |
| 44 | The first line generates a root file system including a syslinux.cfg file |
| 45 | The "--source rootfs-pcbios-ext" in the second line triggers the installation |
| 46 | of ldlinux.sys into the image. |
| 47 | """ |
| 48 | |
| 49 | name = 'rootfs-pcbios-ext' |
| 50 | |
| 51 | @staticmethod |
| 52 | def _get_rootfs_dir(rootfs_dir): |
| 53 | """ |
| 54 | Find rootfs pseudo dir |
| 55 | |
| 56 | If rootfs_dir is a directory consider it as rootfs directory. |
| 57 | Otherwise ask bitbake about the IMAGE_ROOTFS directory. |
| 58 | """ |
| 59 | if os.path.isdir(rootfs_dir): |
| 60 | return rootfs_dir |
| 61 | |
| 62 | image_rootfs_dir = misc.get_bitbake_var("IMAGE_ROOTFS", rootfs_dir) |
| 63 | if not os.path.isdir(image_rootfs_dir): |
| 64 | msg = "No valid artifact IMAGE_ROOTFS from image named" |
| 65 | msg += " %s has been found at %s, exiting.\n" % \ |
| 66 | (rootfs_dir, image_rootfs_dir) |
| 67 | msger.error(msg) |
| 68 | |
| 69 | return image_rootfs_dir |
| 70 | |
| 71 | # pylint: disable=unused-argument |
| 72 | @classmethod |
| 73 | def do_configure_partition(cls, part, source_params, image_creator, |
| 74 | image_creator_workdir, oe_builddir, bootimg_dir, |
| 75 | kernel_dir, native_sysroot): |
| 76 | """ |
| 77 | Creates syslinux config in rootfs directory |
| 78 | |
| 79 | Called before do_prepare_partition() |
| 80 | """ |
| 81 | options = image_creator.ks.handler.bootloader.appendLine |
| 82 | |
| 83 | syslinux_conf = "" |
| 84 | syslinux_conf += "PROMPT 0\n" |
| 85 | |
| 86 | timeout = kickstart.get_timeout(image_creator.ks) |
| 87 | if not timeout: |
| 88 | timeout = 0 |
| 89 | syslinux_conf += "TIMEOUT " + str(timeout) + "\n" |
| 90 | syslinux_conf += "ALLOWOPTIONS 1\n" |
| 91 | |
| 92 | # Derive SERIAL... line from from kernel boot parameters |
| 93 | syslinux_conf += syslinux.serial_console_form_kargs(options) + "\n" |
| 94 | |
| 95 | syslinux_conf += "DEFAULT linux\n" |
| 96 | syslinux_conf += "LABEL linux\n" |
| 97 | syslinux_conf += " KERNEL /boot/bzImage\n" |
| 98 | |
| 99 | syslinux_conf += " APPEND label=boot root=%s %s\n" % \ |
| 100 | (image_creator.rootdev, options) |
| 101 | |
| 102 | syslinux_cfg = os.path.join(image_creator.rootfs_dir['ROOTFS_DIR'], "boot", "syslinux.cfg") |
| 103 | msger.debug("Writing syslinux config %s" % syslinux_cfg) |
| 104 | with open(syslinux_cfg, "w") as cfg: |
| 105 | cfg.write(syslinux_conf) |
| 106 | |
| 107 | @classmethod |
| 108 | def do_prepare_partition(cls, part, source_params, image_creator, |
| 109 | image_creator_workdir, oe_builddir, bootimg_dir, |
| 110 | kernel_dir, krootfs_dir, native_sysroot): |
| 111 | """ |
| 112 | Creates partition out of rootfs directory |
| 113 | |
| 114 | Prepare content for a rootfs partition i.e. create a partition |
| 115 | and fill it from a /rootfs dir. |
| 116 | Install syslinux bootloader into root partition image file |
| 117 | """ |
| 118 | def is_exe(exepath): |
| 119 | """Verify exepath is an executable file""" |
| 120 | return os.path.isfile(exepath) and os.access(exepath, os.X_OK) |
| 121 | |
| 122 | # Make sure syslinux-nomtools is available in native sysroot or fail |
| 123 | native_syslinux_nomtools = os.path.join(native_sysroot, "usr/bin/syslinux-nomtools") |
| 124 | if not is_exe(native_syslinux_nomtools): |
| 125 | msger.info("building syslinux-native...") |
| 126 | misc.exec_cmd("bitbake syslinux-native") |
| 127 | if not is_exe(native_syslinux_nomtools): |
| 128 | msger.error("Couldn't find syslinux-nomtools (%s), exiting\n" % |
| 129 | native_syslinux_nomtools) |
| 130 | |
| 131 | if part.rootfs is None: |
| 132 | if 'ROOTFS_DIR' not in krootfs_dir: |
| 133 | msger.error("Couldn't find --rootfs-dir, exiting") |
| 134 | rootfs_dir = krootfs_dir['ROOTFS_DIR'] |
| 135 | else: |
| 136 | if part.rootfs in krootfs_dir: |
| 137 | rootfs_dir = krootfs_dir[part.rootfs] |
| 138 | elif part.rootfs: |
| 139 | rootfs_dir = part.rootfs |
| 140 | else: |
| 141 | msg = "Couldn't find --rootfs-dir=%s connection" |
| 142 | msg += " or it is not a valid path, exiting" |
| 143 | msger.error(msg % part.rootfs) |
| 144 | |
| 145 | real_rootfs_dir = cls._get_rootfs_dir(rootfs_dir) |
| 146 | |
| 147 | part.set_rootfs(real_rootfs_dir) |
| 148 | part.prepare_rootfs(image_creator_workdir, oe_builddir, real_rootfs_dir, native_sysroot) |
| 149 | |
| 150 | # install syslinux into rootfs partition |
| 151 | syslinux_cmd = "syslinux-nomtools -d /boot -i %s" % part.source_file |
| 152 | misc.exec_native_cmd(syslinux_cmd, native_sysroot) |
| 153 | |
| 154 | @classmethod |
| 155 | def do_install_disk(cls, disk, disk_name, image_creator, workdir, oe_builddir, |
| 156 | bootimg_dir, kernel_dir, native_sysroot): |
| 157 | """ |
| 158 | Assemble partitions to disk image |
| 159 | |
| 160 | Called after all partitions have been prepared and assembled into a |
| 161 | disk image. In this case, we install the MBR. |
| 162 | """ |
| 163 | mbrfile = os.path.join(native_sysroot, "usr/share/syslinux/") |
| 164 | if image_creator.ptable_format == 'msdos': |
| 165 | mbrfile += "mbr.bin" |
| 166 | elif image_creator.ptable_format == 'gpt': |
| 167 | mbrfile += "gptmbr.bin" |
| 168 | else: |
| 169 | msger.error("Unsupported partition table: %s" % \ |
| 170 | image_creator.ptable_format) |
| 171 | |
| 172 | if not os.path.exists(mbrfile): |
| 173 | msger.error("Couldn't find %s. Has syslinux-native been baked?" % mbrfile) |
| 174 | |
| 175 | full_path = disk['disk'].device |
| 176 | msger.debug("Installing MBR on disk %s as %s with size %s bytes" \ |
| 177 | % (disk_name, full_path, disk['min_size'])) |
| 178 | |
| 179 | ret_code = runner.show(['dd', 'if=%s' % mbrfile, 'of=%s' % full_path, 'conv=notrunc']) |
| 180 | if ret_code != 0: |
| 181 | raise ImageError("Unable to set MBR to %s" % full_path) |