diff options
Diffstat (limited to 'meta/classes/kernel-yocto.bbclass')
-rw-r--r-- | meta/classes/kernel-yocto.bbclass | 361 |
1 files changed, 361 insertions, 0 deletions
diff --git a/meta/classes/kernel-yocto.bbclass b/meta/classes/kernel-yocto.bbclass new file mode 100644 index 0000000000..f42a5c2534 --- /dev/null +++ b/meta/classes/kernel-yocto.bbclass | |||
@@ -0,0 +1,361 @@ | |||
1 | S = "${WORKDIR}/linux" | ||
2 | |||
3 | # remove tasks that modify the source tree in case externalsrc is inherited | ||
4 | SRCTREECOVEREDTASKS += "do_kernel_link_vmlinux do_kernel_configme do_validate_branches do_kernel_configcheck do_kernel_checkout do_patch" | ||
5 | |||
6 | # returns local (absolute) path names for all valid patches in the | ||
7 | # src_uri | ||
8 | def find_patches(d): | ||
9 | patches = src_patches(d) | ||
10 | patch_list=[] | ||
11 | for p in patches: | ||
12 | _, _, local, _, _, _ = bb.fetch.decodeurl(p) | ||
13 | patch_list.append(local) | ||
14 | |||
15 | return patch_list | ||
16 | |||
17 | # returns all the elements from the src uri that are .scc files | ||
18 | def find_sccs(d): | ||
19 | sources=src_patches(d, True) | ||
20 | sources_list=[] | ||
21 | for s in sources: | ||
22 | base, ext = os.path.splitext(os.path.basename(s)) | ||
23 | if ext and ext in [".scc", ".cfg"]: | ||
24 | sources_list.append(s) | ||
25 | elif base and base in 'defconfig': | ||
26 | sources_list.append(s) | ||
27 | |||
28 | return sources_list | ||
29 | |||
30 | # check the SRC_URI for "kmeta" type'd git repositories. Return the name of | ||
31 | # the repository as it will be found in WORKDIR | ||
32 | def find_kernel_feature_dirs(d): | ||
33 | feature_dirs=[] | ||
34 | fetch = bb.fetch2.Fetch([], d) | ||
35 | for url in fetch.urls: | ||
36 | urldata = fetch.ud[url] | ||
37 | parm = urldata.parm | ||
38 | if "type" in parm: | ||
39 | type = parm["type"] | ||
40 | if "destsuffix" in parm: | ||
41 | destdir = parm["destsuffix"] | ||
42 | if type == "kmeta": | ||
43 | feature_dirs.append(destdir) | ||
44 | |||
45 | return feature_dirs | ||
46 | |||
47 | # find the master/machine source branch. In the same way that the fetcher proceses | ||
48 | # git repositories in the SRC_URI we take the first repo found, first branch. | ||
49 | def get_machine_branch(d, default): | ||
50 | fetch = bb.fetch2.Fetch([], d) | ||
51 | for url in fetch.urls: | ||
52 | urldata = fetch.ud[url] | ||
53 | parm = urldata.parm | ||
54 | if "branch" in parm: | ||
55 | branches = urldata.parm.get("branch").split(',') | ||
56 | return branches[0] | ||
57 | |||
58 | return default | ||
59 | |||
60 | do_patch() { | ||
61 | cd ${S} | ||
62 | export KMETA=${KMETA} | ||
63 | |||
64 | # if kernel tools are available in-tree, they are preferred | ||
65 | # and are placed on the path before any external tools. Unless | ||
66 | # the external tools flag is set, in that case we do nothing. | ||
67 | if [ -f "${S}/scripts/util/configme" ]; then | ||
68 | if [ -z "${EXTERNAL_KERNEL_TOOLS}" ]; then | ||
69 | PATH=${S}/scripts/util:${PATH} | ||
70 | fi | ||
71 | fi | ||
72 | |||
73 | machine_branch="${@ get_machine_branch(d, "${KBRANCH}" )}" | ||
74 | machine_srcrev="${SRCREV_machine}" | ||
75 | if [ -z "${machine_srcrev}" ]; then | ||
76 | # fallback to SRCREV if a non machine_meta tree is being built | ||
77 | machine_srcrev="${SRCREV}" | ||
78 | fi | ||
79 | |||
80 | # if we have a defined/set meta branch we should not be generating | ||
81 | # any meta data. The passed branch has what we need. | ||
82 | if [ -n "${KMETA}" ]; then | ||
83 | createme_flags="--disable-meta-gen --meta ${KMETA}" | ||
84 | fi | ||
85 | |||
86 | createme ${createme_flags} ${ARCH} ${machine_branch} | ||
87 | if [ $? -ne 0 ]; then | ||
88 | bbfatal "Could not create ${machine_branch}" | ||
89 | fi | ||
90 | |||
91 | sccs="${@" ".join(find_sccs(d))}" | ||
92 | patches="${@" ".join(find_patches(d))}" | ||
93 | feat_dirs="${@" ".join(find_kernel_feature_dirs(d))}" | ||
94 | |||
95 | set +e | ||
96 | # add any explicitly referenced features onto the end of the feature | ||
97 | # list that is passed to the kernel build scripts. | ||
98 | if [ -n "${KERNEL_FEATURES}" ]; then | ||
99 | for feat in ${KERNEL_FEATURES}; do | ||
100 | addon_features="$addon_features --feature $feat" | ||
101 | done | ||
102 | fi | ||
103 | |||
104 | # check for feature directories/repos/branches that were part of the | ||
105 | # SRC_URI. If they were supplied, we convert them into include directives | ||
106 | # for the update part of the process | ||
107 | if [ -n "${feat_dirs}" ]; then | ||
108 | for f in ${feat_dirs}; do | ||
109 | if [ -d "${WORKDIR}/$f/meta" ]; then | ||
110 | includes="$includes -I${WORKDIR}/$f/meta" | ||
111 | elif [ -d "${WORKDIR}/$f" ]; then | ||
112 | includes="$includes -I${WORKDIR}/$f" | ||
113 | fi | ||
114 | done | ||
115 | fi | ||
116 | |||
117 | # updates or generates the target description | ||
118 | updateme ${updateme_flags} -DKDESC=${KMACHINE}:${LINUX_KERNEL_TYPE} \ | ||
119 | ${includes} ${addon_features} ${ARCH} ${KMACHINE} ${sccs} ${patches} | ||
120 | if [ $? -ne 0 ]; then | ||
121 | bbfatal "Could not update ${machine_branch}" | ||
122 | fi | ||
123 | |||
124 | # executes and modifies the source tree as required | ||
125 | patchme ${KMACHINE} | ||
126 | if [ $? -ne 0 ]; then | ||
127 | bberror "Could not apply patches for ${KMACHINE}." | ||
128 | bbfatal "Patch failures can be resolved in the devshell (bitbake -c devshell ${PN})" | ||
129 | fi | ||
130 | |||
131 | # check to see if the specified SRCREV is reachable from the final branch. | ||
132 | # if it wasn't something wrong has happened, and we should error. | ||
133 | if [ "${machine_srcrev}" != "AUTOINC" ]; then | ||
134 | if ! [ "$(git rev-parse --verify ${machine_srcrev})" = "$(git merge-base ${machine_srcrev} HEAD)" ]; then | ||
135 | bberror "SRCREV ${machine_srcrev} was specified, but is not reachable" | ||
136 | bbfatal "Check the BSP description for incorrect branch selection, or other errors." | ||
137 | fi | ||
138 | fi | ||
139 | } | ||
140 | |||
141 | do_kernel_checkout() { | ||
142 | set +e | ||
143 | |||
144 | # A linux yocto SRC_URI should use the bareclone option. That | ||
145 | # ensures that all the branches are available in the WORKDIR version | ||
146 | # of the repository. | ||
147 | source_dir=`echo ${S} | sed 's%/$%%'` | ||
148 | source_workdir="${WORKDIR}/git" | ||
149 | if [ -d "${WORKDIR}/git/" ] && [ -d "${WORKDIR}/git/.git" ]; then | ||
150 | # case2: the repository is a non-bare clone | ||
151 | |||
152 | # if S is WORKDIR/git, then we shouldn't be moving or deleting the tree. | ||
153 | if [ "${source_dir}" != "${source_workdir}" ]; then | ||
154 | rm -rf ${S} | ||
155 | mv ${WORKDIR}/git ${S} | ||
156 | fi | ||
157 | cd ${S} | ||
158 | elif [ -d "${WORKDIR}/git/" ] && [ ! -d "${WORKDIR}/git/.git" ]; then | ||
159 | # case2: the repository is a bare clone | ||
160 | |||
161 | # if S is WORKDIR/git, then we shouldn't be moving or deleting the tree. | ||
162 | if [ "${source_dir}" != "${source_workdir}" ]; then | ||
163 | rm -rf ${S} | ||
164 | mkdir -p ${S}/.git | ||
165 | mv ${WORKDIR}/git/* ${S}/.git | ||
166 | rm -rf ${WORKDIR}/git/ | ||
167 | fi | ||
168 | cd ${S} | ||
169 | git config core.bare false | ||
170 | else | ||
171 | # case 3: we have no git repository at all. | ||
172 | # To support low bandwidth options for building the kernel, we'll just | ||
173 | # convert the tree to a git repo and let the rest of the process work unchanged | ||
174 | |||
175 | # if ${S} hasn't been set to the proper subdirectory a default of "linux" is | ||
176 | # used, but we can't initialize that empty directory. So check it and throw a | ||
177 | # clear error | ||
178 | |||
179 | cd ${S} | ||
180 | if [ ! -f "Makefile" ]; then | ||
181 | bberror "S is not set to the linux source directory. Check " | ||
182 | bbfatal "the recipe and set S to the proper extracted subdirectory" | ||
183 | fi | ||
184 | git init | ||
185 | git add . | ||
186 | git commit -q -m "baseline commit: creating repo for ${PN}-${PV}" | ||
187 | fi | ||
188 | # end debare | ||
189 | |||
190 | # convert any remote branches to local tracking ones | ||
191 | for i in `git branch -a --no-color | grep remotes | grep -v HEAD`; do | ||
192 | b=`echo $i | cut -d' ' -f2 | sed 's%remotes/origin/%%'`; | ||
193 | git show-ref --quiet --verify -- "refs/heads/$b" | ||
194 | if [ $? -ne 0 ]; then | ||
195 | git branch $b $i > /dev/null | ||
196 | fi | ||
197 | done | ||
198 | |||
199 | # If KMETA is defined, the branch must exist, but a machine branch | ||
200 | # can be missing since it may be created later by the tools. | ||
201 | if [ -n "${KMETA}" ]; then | ||
202 | git show-ref --quiet --verify -- "refs/heads/${KMETA}" | ||
203 | if [ $? -eq 1 ]; then | ||
204 | bberror "The branch '${KMETA}' is required and was not found" | ||
205 | bberror "Ensure that the SRC_URI points to a valid linux-yocto" | ||
206 | bbfatal "kernel repository" | ||
207 | fi | ||
208 | fi | ||
209 | |||
210 | |||
211 | # Create a working tree copy of the kernel by checking out a branch | ||
212 | machine_branch="${@ get_machine_branch(d, "${KBRANCH}" )}" | ||
213 | git show-ref --quiet --verify -- "refs/heads/${machine_branch}" | ||
214 | if [ $? -eq 0 ]; then | ||
215 | machine_branch="master" | ||
216 | fi | ||
217 | |||
218 | # checkout and clobber any unimportant files | ||
219 | git checkout -f ${machine_branch} | ||
220 | } | ||
221 | do_kernel_checkout[dirs] = "${S}" | ||
222 | |||
223 | addtask kernel_checkout before do_patch after do_unpack | ||
224 | |||
225 | do_kernel_configme[dirs] += "${S} ${B}" | ||
226 | do_kernel_configme() { | ||
227 | bbnote "kernel configme" | ||
228 | export KMETA=${KMETA} | ||
229 | |||
230 | if [ -n "${KCONFIG_MODE}" ]; then | ||
231 | configmeflags=${KCONFIG_MODE} | ||
232 | else | ||
233 | # If a defconfig was passed, use =n as the baseline, which is achieved | ||
234 | # via --allnoconfig | ||
235 | if [ -f ${WORKDIR}/defconfig ]; then | ||
236 | configmeflags="--allnoconfig" | ||
237 | fi | ||
238 | fi | ||
239 | |||
240 | cd ${S} | ||
241 | PATH=${PATH}:${S}/scripts/util | ||
242 | configme ${configmeflags} --reconfig --output ${B} ${LINUX_KERNEL_TYPE} ${KMACHINE} | ||
243 | if [ $? -ne 0 ]; then | ||
244 | bbfatal "Could not configure ${KMACHINE}-${LINUX_KERNEL_TYPE}" | ||
245 | fi | ||
246 | |||
247 | echo "# Global settings from linux recipe" >> ${B}/.config | ||
248 | echo "CONFIG_LOCALVERSION="\"${LINUX_VERSION_EXTENSION}\" >> ${B}/.config | ||
249 | } | ||
250 | |||
251 | addtask kernel_configme after do_patch | ||
252 | |||
253 | python do_kernel_configcheck() { | ||
254 | import re, string, sys | ||
255 | |||
256 | bb.plain("NOTE: validating kernel config, see log.do_kernel_configcheck for details") | ||
257 | |||
258 | # if KMETA isn't set globally by a recipe using this routine, we need to | ||
259 | # set the default to 'meta'. Otherwise, kconf_check is not passed a valid | ||
260 | # meta-series for processing | ||
261 | kmeta = d.getVar( "KMETA", True ) or "meta" | ||
262 | if not os.path.exists(kmeta): | ||
263 | kmeta = "." + kmeta | ||
264 | |||
265 | pathprefix = "export PATH=%s:%s; " % (d.getVar('PATH', True), "${S}/scripts/util/") | ||
266 | cmd = d.expand("cd ${S}; kconf_check -config- %s/meta-series ${S} ${B}" % kmeta) | ||
267 | ret, result = oe.utils.getstatusoutput("%s%s" % (pathprefix, cmd)) | ||
268 | |||
269 | config_check_visibility = d.getVar( "KCONF_AUDIT_LEVEL", True ) or 1 | ||
270 | if config_check_visibility == 1: | ||
271 | bb.debug( 1, "%s" % result ) | ||
272 | else: | ||
273 | bb.note( "%s" % result ) | ||
274 | } | ||
275 | |||
276 | # Ensure that the branches (BSP and meta) are on the locations specified by | ||
277 | # their SRCREV values. If they are NOT on the right commits, the branches | ||
278 | # are corrected to the proper commit. | ||
279 | do_validate_branches() { | ||
280 | set +e | ||
281 | cd ${S} | ||
282 | export KMETA=${KMETA} | ||
283 | |||
284 | machine_branch="${@ get_machine_branch(d, "${KBRANCH}" )}" | ||
285 | machine_srcrev="${SRCREV_machine}" | ||
286 | |||
287 | # if SRCREV is AUTOREV it shows up as AUTOINC there's nothing to | ||
288 | # check and we can exit early | ||
289 | if [ "${machine_srcrev}" = "AUTOINC" ]; then | ||
290 | bbnote "SRCREV validation is not required for AUTOREV" | ||
291 | elif [ "${machine_srcrev}" = "" ] && [ "${SRCREV}" != "AUTOINC" ]; then | ||
292 | # SRCREV_machine_<MACHINE> was not set. This means that a custom recipe | ||
293 | # that doesn't use the SRCREV_FORMAT "machine_meta" is being built. In | ||
294 | # this case, we need to reset to the give SRCREV before heading to patching | ||
295 | bbnote "custom recipe is being built, forcing SRCREV to ${SRCREV}" | ||
296 | force_srcrev="${SRCREV}" | ||
297 | else | ||
298 | git cat-file -t ${machine_srcrev} > /dev/null | ||
299 | if [ $? -ne 0 ]; then | ||
300 | bberror "${machine_srcrev} is not a valid commit ID." | ||
301 | bbfatal "The kernel source tree may be out of sync" | ||
302 | fi | ||
303 | force_srcrev=${machine_srcrev} | ||
304 | fi | ||
305 | |||
306 | ## KMETA branch validation. | ||
307 | target_meta_head="${SRCREV_meta}" | ||
308 | if [ "${target_meta_head}" = "AUTOINC" ] || [ "${target_meta_head}" = "" ]; then | ||
309 | bbnote "SRCREV validation skipped for AUTOREV or empty meta branch" | ||
310 | else | ||
311 | meta_head=`git show-ref -s --heads ${KMETA}` | ||
312 | |||
313 | git cat-file -t ${target_meta_head} > /dev/null | ||
314 | if [ $? -ne 0 ]; then | ||
315 | bberror "${target_meta_head} is not a valid commit ID" | ||
316 | bbfatal "The kernel source tree may be out of sync" | ||
317 | fi | ||
318 | if [ "$meta_head" != "$target_meta_head" ]; then | ||
319 | bbnote "Setting branch ${KMETA} to ${target_meta_head}" | ||
320 | git branch -m ${KMETA} ${KMETA}-orig | ||
321 | git checkout -q -b ${KMETA} ${target_meta_head} | ||
322 | if [ $? -ne 0 ];then | ||
323 | bbfatal "Could not checkout ${KMETA} branch from known hash ${target_meta_head}" | ||
324 | fi | ||
325 | fi | ||
326 | fi | ||
327 | |||
328 | git checkout -q -f ${machine_branch} | ||
329 | if [ -n "${force_srcrev}" ]; then | ||
330 | # see if the branch we are about to patch has been properly reset to the defined | ||
331 | # SRCREV .. if not, we reset it. | ||
332 | branch_head=`git rev-parse HEAD` | ||
333 | if [ "${force_srcrev}" != "${branch_head}" ]; then | ||
334 | current_branch=`git rev-parse --abbrev-ref HEAD` | ||
335 | git branch "$current_branch-orig" | ||
336 | git reset --hard ${force_srcrev} | ||
337 | fi | ||
338 | fi | ||
339 | } | ||
340 | |||
341 | # Many scripts want to look in arch/$arch/boot for the bootable | ||
342 | # image. This poses a problem for vmlinux based booting. This | ||
343 | # task arranges to have vmlinux appear in the normalized directory | ||
344 | # location. | ||
345 | do_kernel_link_vmlinux() { | ||
346 | if [ ! -d "${B}/arch/${ARCH}/boot" ]; then | ||
347 | mkdir ${B}/arch/${ARCH}/boot | ||
348 | fi | ||
349 | cd ${B}/arch/${ARCH}/boot | ||
350 | ln -sf ../../../vmlinux | ||
351 | } | ||
352 | |||
353 | OE_TERMINAL_EXPORTS += "GUILT_BASE KBUILD_OUTPUT" | ||
354 | GUILT_BASE = "meta" | ||
355 | KBUILD_OUTPUT = "${B}" | ||
356 | |||
357 | python () { | ||
358 | # If diffconfig is available, ensure it runs after kernel_configme | ||
359 | if 'do_diffconfig' in d: | ||
360 | bb.build.addtask('do_diffconfig', None, 'do_kernel_configme', d) | ||
361 | } | ||