blob: f59821fea6fedcb6a0cabc69636b15c0d6fb10ac [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# Copyright (c) 2013, Intel Corporation.
5# All rights reserved.
6#
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License version 2 as
9# published by the Free Software Foundation.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License along
17# with this program; if not, write to the Free Software Foundation, Inc.,
18# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19#
20# DESCRIPTION
21
22# This module implements the image creation engine used by 'wic' to
23# create images. The engine parses through the OpenEmbedded kickstart
24# (wks) file specified and generates images that can then be directly
25# written onto media.
26#
27# AUTHORS
28# Tom Zanussi <tom.zanussi (at] linux.intel.com>
29#
30
Brad Bishop6e60e8b2018-02-01 10:27:11 -050031import logging
Patrick Williamsc124f4f2015-09-15 14:41:29 -050032import os
Patrick Williamsc124f4f2015-09-15 14:41:29 -050033
Brad Bishop6e60e8b2018-02-01 10:27:11 -050034from wic import WicError
35from wic.pluginbase import PluginMgr
36from wic.utils.misc import get_bitbake_var
Patrick Williamsc124f4f2015-09-15 14:41:29 -050037
Brad Bishop6e60e8b2018-02-01 10:27:11 -050038logger = logging.getLogger('wic')
Patrick Williamsc124f4f2015-09-15 14:41:29 -050039
40def verify_build_env():
41 """
42 Verify that the build environment is sane.
43
44 Returns True if it is, false otherwise
45 """
46 if not os.environ.get("BUILDDIR"):
Brad Bishop6e60e8b2018-02-01 10:27:11 -050047 raise WicError("BUILDDIR not found, exiting. (Did you forget to source oe-init-build-env?)")
Patrick Williamsc124f4f2015-09-15 14:41:29 -050048
49 return True
50
51
52CANNED_IMAGE_DIR = "lib/wic/canned-wks" # relative to scripts
53SCRIPTS_CANNED_IMAGE_DIR = "scripts/" + CANNED_IMAGE_DIR
Brad Bishop6e60e8b2018-02-01 10:27:11 -050054WIC_DIR = "wic"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050055
56def build_canned_image_list(path):
Brad Bishop6e60e8b2018-02-01 10:27:11 -050057 layers_path = get_bitbake_var("BBLAYERS")
Patrick Williamsc124f4f2015-09-15 14:41:29 -050058 canned_wks_layer_dirs = []
59
60 if layers_path is not None:
61 for layer_path in layers_path.split():
Brad Bishop6e60e8b2018-02-01 10:27:11 -050062 for wks_path in (WIC_DIR, SCRIPTS_CANNED_IMAGE_DIR):
63 cpath = os.path.join(layer_path, wks_path)
64 if os.path.isdir(cpath):
65 canned_wks_layer_dirs.append(cpath)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050066
67 cpath = os.path.join(path, CANNED_IMAGE_DIR)
68 canned_wks_layer_dirs.append(cpath)
69
70 return canned_wks_layer_dirs
71
72def find_canned_image(scripts_path, wks_file):
73 """
74 Find a .wks file with the given name in the canned files dir.
75
76 Return False if not found
77 """
78 layers_canned_wks_dir = build_canned_image_list(scripts_path)
79
80 for canned_wks_dir in layers_canned_wks_dir:
81 for root, dirs, files in os.walk(canned_wks_dir):
82 for fname in files:
83 if fname.endswith("~") or fname.endswith("#"):
84 continue
85 if fname.endswith(".wks") and wks_file + ".wks" == fname:
86 fullpath = os.path.join(canned_wks_dir, fname)
87 return fullpath
88 return None
89
90
91def list_canned_images(scripts_path):
92 """
93 List the .wks files in the canned image dir, minus the extension.
94 """
95 layers_canned_wks_dir = build_canned_image_list(scripts_path)
96
97 for canned_wks_dir in layers_canned_wks_dir:
98 for root, dirs, files in os.walk(canned_wks_dir):
99 for fname in files:
100 if fname.endswith("~") or fname.endswith("#"):
101 continue
102 if fname.endswith(".wks"):
103 fullpath = os.path.join(canned_wks_dir, fname)
104 with open(fullpath) as wks:
105 for line in wks:
106 desc = ""
107 idx = line.find("short-description:")
108 if idx != -1:
109 desc = line[idx + len("short-description:"):].strip()
110 break
111 basename = os.path.splitext(fname)[0]
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600112 print(" %s\t\t%s" % (basename.ljust(30), desc))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500113
114
115def list_canned_image_help(scripts_path, fullpath):
116 """
117 List the help and params in the specified canned image.
118 """
119 found = False
120 with open(fullpath) as wks:
121 for line in wks:
122 if not found:
123 idx = line.find("long-description:")
124 if idx != -1:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600125 print()
126 print(line[idx + len("long-description:"):].strip())
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500127 found = True
128 continue
129 if not line.strip():
130 break
131 idx = line.find("#")
132 if idx != -1:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600133 print(line[idx + len("#:"):].rstrip())
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500134 else:
135 break
136
137
138def list_source_plugins():
139 """
140 List the available source plugins i.e. plugins available for --source.
141 """
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500142 plugins = PluginMgr.get_plugins('source')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500143
144 for plugin in plugins:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600145 print(" %s" % plugin)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500146
147
148def wic_create(wks_file, rootfs_dir, bootimg_dir, kernel_dir,
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500149 native_sysroot, options):
150 """
151 Create image
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500152
153 wks_file - user-defined OE kickstart file
154 rootfs_dir - absolute path to the build's /rootfs dir
155 bootimg_dir - absolute path to the build's boot artifacts directory
156 kernel_dir - absolute path to the build's kernel directory
157 native_sysroot - absolute path to the build's native sysroots dir
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500158 image_output_dir - dirname to create for image
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500159 options - wic command line options (debug, bmap, etc)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500160
161 Normally, the values for the build artifacts values are determined
162 by 'wic -e' from the output of the 'bitbake -e' command given an
163 image name e.g. 'core-image-minimal' and a given machine set in
164 local.conf. If that's the case, the variables get the following
165 values from the output of 'bitbake -e':
166
167 rootfs_dir: IMAGE_ROOTFS
168 kernel_dir: DEPLOY_DIR_IMAGE
169 native_sysroot: STAGING_DIR_NATIVE
170
171 In the above case, bootimg_dir remains unset and the
172 plugin-specific image creation code is responsible for finding the
173 bootimg artifacts.
174
175 In the case where the values are passed in explicitly i.e 'wic -e'
176 is not used but rather the individual 'wic' options are used to
177 explicitly specify these values.
178 """
179 try:
180 oe_builddir = os.environ["BUILDDIR"]
181 except KeyError:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500182 raise WicError("BUILDDIR not found, exiting. (Did you forget to source oe-init-build-env?)")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500183
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500184 if not os.path.exists(options.outdir):
185 os.makedirs(options.outdir)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500186
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500187 pname = 'direct'
188 plugin_class = PluginMgr.get_plugins('imager').get(pname)
189 if not plugin_class:
190 raise WicError('Unknown plugin: %s' % pname)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500191
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500192 plugin = plugin_class(wks_file, rootfs_dir, bootimg_dir, kernel_dir,
193 native_sysroot, oe_builddir, options)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500194
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500195 plugin.do_create()
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600196
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500197 logger.info("The image(s) were created using OE kickstart file:\n %s", wks_file)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500198
199
200def wic_list(args, scripts_path):
201 """
202 Print the list of images or source plugins.
203 """
204 if len(args) < 1:
205 return False
206
207 if args == ["images"]:
208 list_canned_images(scripts_path)
209 return True
210 elif args == ["source-plugins"]:
211 list_source_plugins()
212 return True
213 elif len(args) == 2 and args[1] == "help":
214 wks_file = args[0]
215 fullpath = find_canned_image(scripts_path, wks_file)
216 if not fullpath:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500217 raise WicError("No image named %s found, exiting. "
218 "(Use 'wic list images' to list available images, "
219 "or specify a fully-qualified OE kickstart (.wks) "
220 "filename)" % wks_file)
221
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500222 list_canned_image_help(scripts_path, fullpath)
223 return True
224
225 return False
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500226
227def find_canned(scripts_path, file_name):
228 """
229 Find a file either by its path or by name in the canned files dir.
230
231 Return None if not found
232 """
233 if os.path.exists(file_name):
234 return file_name
235
236 layers_canned_wks_dir = build_canned_image_list(scripts_path)
237 for canned_wks_dir in layers_canned_wks_dir:
238 for root, dirs, files in os.walk(canned_wks_dir):
239 for fname in files:
240 if fname == file_name:
241 fullpath = os.path.join(canned_wks_dir, fname)
242 return fullpath
243
244def get_custom_config(boot_file):
245 """
246 Get the custom configuration to be used for the bootloader.
247
248 Return None if the file can't be found.
249 """
250 # Get the scripts path of poky
251 scripts_path = os.path.abspath("%s/../.." % os.path.dirname(__file__))
252
253 cfg_file = find_canned(scripts_path, boot_file)
254 if cfg_file:
255 with open(cfg_file, "r") as f:
256 config = f.read()
257 return config