blob: 76e7b033fbc6d1eefe0351d7c0cb71fbbbf26bd0 [file] [log] [blame]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001# 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
21import os
22from wic import kickstart
23from wic import msger
24from wic.utils import syslinux
25from wic.utils import runner
26from wic.utils.oe import misc
27from wic.utils.errors import ImageError
28from wic.pluginbase import SourcePlugin
29
30
31# pylint: disable=no-init
32class 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)