diff options
-rw-r--r-- | meta/classes/kernel-yocto.bbclass | 159 | ||||
-rw-r--r-- | meta/recipes-kernel/kern-tools/kern-tools-native_git.bb | 2 | ||||
-rw-r--r-- | meta/recipes-kernel/linux/linux-yocto_5.4.bb | 2 |
3 files changed, 128 insertions, 35 deletions
diff --git a/meta/classes/kernel-yocto.bbclass b/meta/classes/kernel-yocto.bbclass index 70818cc01c..77849a28c9 100644 --- a/meta/classes/kernel-yocto.bbclass +++ b/meta/classes/kernel-yocto.bbclass | |||
@@ -405,6 +405,67 @@ do_kernel_configme() { | |||
405 | } | 405 | } |
406 | 406 | ||
407 | addtask kernel_configme before do_configure after do_patch | 407 | addtask kernel_configme before do_configure after do_patch |
408 | addtask config_analysis | ||
409 | |||
410 | do_config_analysis[depends] = "virtual/kernel:do_configure" | ||
411 | do_config_analysis[depends] += "kern-tools-native:do_populate_sysroot" | ||
412 | |||
413 | CONFIG_AUDIT_FILE ?= "${WORKDIR}/config-audit.txt" | ||
414 | CONFIG_ANALYSIS_FILE ?= "${WORKDIR}/config-analysis.txt" | ||
415 | |||
416 | python do_config_analysis() { | ||
417 | import re, string, sys, subprocess | ||
418 | |||
419 | s = d.getVar('S') | ||
420 | |||
421 | env = os.environ.copy() | ||
422 | env['PATH'] = "%s:%s%s" % (d.getVar('PATH'), s, "/scripts/util/") | ||
423 | env['LD'] = d.getVar('KERNEL_LD') | ||
424 | env['CC'] = d.getVar('KERNEL_CC') | ||
425 | env['ARCH'] = d.getVar('ARCH') | ||
426 | env['srctree'] = s | ||
427 | |||
428 | # read specific symbols from the kernel recipe or from local.conf | ||
429 | # i.e.: CONFIG_ANALYSIS_pn-linux-yocto-dev = 'NF_CONNTRACK LOCALVERSION' | ||
430 | config = d.getVar( 'CONFIG_ANALYSIS' ) | ||
431 | if not config: | ||
432 | config = [ "" ] | ||
433 | else: | ||
434 | config = config.split() | ||
435 | |||
436 | for c in config: | ||
437 | for action in ["analysis","audit"]: | ||
438 | if action == "analysis": | ||
439 | try: | ||
440 | analysis = subprocess.check_output(['symbol_why.py', '--dotconfig', '{}'.format( d.getVar('B') + '/.config' ), '--blame', c], cwd=s, env=env ).decode('utf-8') | ||
441 | except subprocess.CalledProcessError as e: | ||
442 | bb.fatal( "config analysis failed: %s" % e.output.decode('utf-8')) | ||
443 | |||
444 | outfile = d.getVar( 'CONFIG_ANALYSIS_FILE' ) | ||
445 | |||
446 | if action == "audit": | ||
447 | try: | ||
448 | analysis = subprocess.check_output(['symbol_why.py', '--dotconfig', '{}'.format( d.getVar('B') + '/.config' ), '--summary', '--extended', '--sanity', c], cwd=s, env=env ).decode('utf-8') | ||
449 | except subprocess.CalledProcessError as e: | ||
450 | bb.fatal( "config analysis failed: %s" % e.output.decode('utf-8')) | ||
451 | |||
452 | outfile = d.getVar( 'CONFIG_AUDIT_FILE' ) | ||
453 | |||
454 | if c: | ||
455 | outdir = os.path.dirname( outfile ) | ||
456 | outname = os.path.basename( outfile ) | ||
457 | outfile = outdir + '/'+ c + '-' + outname | ||
458 | |||
459 | if config and os.path.isfile(outfile): | ||
460 | os.remove(outfile) | ||
461 | |||
462 | with open(outfile, 'w+') as f: | ||
463 | f.write( analysis ) | ||
464 | |||
465 | bb.warn( "Configuration {} executed, see: {} for details".format(action,outfile )) | ||
466 | if c: | ||
467 | bb.warn( analysis ) | ||
468 | } | ||
408 | 469 | ||
409 | python do_kernel_configcheck() { | 470 | python do_kernel_configcheck() { |
410 | import re, string, sys, subprocess | 471 | import re, string, sys, subprocess |
@@ -414,57 +475,89 @@ python do_kernel_configcheck() { | |||
414 | # meta-series for processing | 475 | # meta-series for processing |
415 | kmeta = d.getVar("KMETA") or "meta" | 476 | kmeta = d.getVar("KMETA") or "meta" |
416 | if not os.path.exists(kmeta): | 477 | if not os.path.exists(kmeta): |
417 | kmeta = "." + kmeta | 478 | kmeta = subprocess.check_output(['kgit', '--meta']).decode('utf-8').rstrip() |
418 | 479 | ||
419 | s = d.getVar('S') | 480 | s = d.getVar('S') |
420 | 481 | ||
421 | env = os.environ.copy() | 482 | env = os.environ.copy() |
422 | env['PATH'] = "%s:%s%s" % (d.getVar('PATH'), s, "/scripts/util/") | 483 | env['PATH'] = "%s:%s%s" % (d.getVar('PATH'), s, "/scripts/util/") |
423 | env['LD'] = "${KERNEL_LD}" | 484 | env['LD'] = d.getVar('KERNEL_LD') |
485 | env['CC'] = d.getVar('KERNEL_CC') | ||
486 | env['ARCH'] = d.getVar('ARCH') | ||
487 | env['srctree'] = s | ||
424 | 488 | ||
425 | try: | 489 | try: |
426 | configs = subprocess.check_output(['scc', '--configs', '-o', s + '/.kernel-meta'], env=env).decode('utf-8') | 490 | configs = subprocess.check_output(['scc', '--configs', '-o', s + '/.kernel-meta'], env=env).decode('utf-8') |
427 | except subprocess.CalledProcessError as e: | 491 | except subprocess.CalledProcessError as e: |
428 | bb.fatal( "Cannot gather config fragments for audit: %s" % e.output.decode("utf-8") ) | 492 | bb.fatal( "Cannot gather config fragments for audit: %s" % e.output.decode("utf-8") ) |
429 | 493 | ||
430 | try: | ||
431 | subprocess.check_call(['kconf_check', '--report', '-o', | ||
432 | '%s/%s/cfg' % (s, kmeta), d.getVar('B') + '/.config', s, configs], cwd=s, env=env) | ||
433 | except subprocess.CalledProcessError: | ||
434 | # The configuration gathering can return different exit codes, but | ||
435 | # we interpret them based on the KCONF_AUDIT_LEVEL variable, so we catch | ||
436 | # everything here, and let the run continue. | ||
437 | pass | ||
438 | |||
439 | config_check_visibility = int(d.getVar("KCONF_AUDIT_LEVEL") or 0) | 494 | config_check_visibility = int(d.getVar("KCONF_AUDIT_LEVEL") or 0) |
440 | bsp_check_visibility = int(d.getVar("KCONF_BSP_AUDIT_LEVEL") or 0) | 495 | bsp_check_visibility = int(d.getVar("KCONF_BSP_AUDIT_LEVEL") or 0) |
441 | 496 | ||
442 | # if config check visibility is non-zero, report dropped configuration values | 497 | # if config check visibility is "1", that's the lowest level of audit. So |
443 | mismatch_file = d.expand("${S}/%s/cfg/mismatch.txt" % kmeta) | 498 | # we add the --classify option to the run, since classification will |
444 | if os.path.exists(mismatch_file): | 499 | # streamline the output to only report options that could be boot issues, |
445 | if config_check_visibility: | 500 | # or are otherwise required for proper operation. |
446 | with open (mismatch_file, "r") as myfile: | 501 | extra_params = "" |
502 | if config_check_visibility == 1: | ||
503 | extra_params = "--classify" | ||
504 | |||
505 | # category #1: mismatches | ||
506 | try: | ||
507 | analysis = subprocess.check_output(['symbol_why.py', '--dotconfig', '{}'.format( d.getVar('B') + '/.config' ), '--mismatches', extra_params], cwd=s, env=env ).decode('utf-8') | ||
508 | except subprocess.CalledProcessError as e: | ||
509 | bb.fatal( "config analysis failed: %s" % e.output.decode('utf-8')) | ||
510 | |||
511 | if analysis: | ||
512 | outfile = "{}/{}/cfg/mismatch.txt".format( s, kmeta ) | ||
513 | if os.path.isfile(outfile): | ||
514 | os.remove(outfile) | ||
515 | with open(outfile, 'w+') as f: | ||
516 | f.write( analysis ) | ||
517 | |||
518 | if config_check_visibility and os.stat(outfile).st_size > 0: | ||
519 | with open (outfile, "r") as myfile: | ||
447 | results = myfile.read() | 520 | results = myfile.read() |
448 | bb.warn( "[kernel config]: specified values did not make it into the kernel's final configuration:\n\n%s" % results) | 521 | bb.warn( "[kernel config]: specified values did not make it into the kernel's final configuration:\n\n%s" % results) |
449 | 522 | ||
450 | if bsp_check_visibility: | 523 | # category #2: invalid fragment elements |
451 | invalid_file = d.expand("${S}/%s/cfg/invalid.cfg" % kmeta) | 524 | extra_params = "" |
452 | if os.path.exists(invalid_file) and os.stat(invalid_file).st_size > 0: | 525 | if bsp_check_visibility > 1: |
453 | with open (invalid_file, "r") as myfile: | 526 | extra_params = "--strict" |
454 | results = myfile.read() | 527 | try: |
455 | bb.warn( "[kernel config]: This BSP sets config options that are not offered anywhere within this kernel:\n\n%s" % results) | 528 | analysis = subprocess.check_output(['symbol_why.py', '--dotconfig', '{}'.format( d.getVar('B') + '/.config' ), '--invalid', extra_params], cwd=s, env=env ).decode('utf-8') |
456 | errors_file = d.expand("${S}/%s/cfg/fragment_errors.txt" % kmeta) | 529 | except subprocess.CalledProcessError as e: |
457 | if os.path.exists(errors_file) and os.stat(errors_file).st_size > 0: | 530 | bb.fatal( "config analysis failed: %s" % e.output.decode('utf-8')) |
458 | with open (errors_file, "r") as myfile: | 531 | |
532 | if analysis: | ||
533 | outfile = "{}/{}/cfg/invalid.txt".format(s,kmeta) | ||
534 | if os.path.isfile(outfile): | ||
535 | os.remove(outfile) | ||
536 | with open(outfile, 'w+') as f: | ||
537 | f.write( analysis ) | ||
538 | |||
539 | if bsp_check_visibility and os.stat(outfile).st_size > 0: | ||
540 | with open (outfile, "r") as myfile: | ||
459 | results = myfile.read() | 541 | results = myfile.read() |
460 | bb.warn( "[kernel config]: This BSP contains fragments with errors:\n\n%s" % results) | 542 | bb.warn( "[kernel config]: This BSP contains fragments with warnings:\n\n%s" % results) |
461 | 543 | ||
462 | # if the audit level is greater than two, we report if a fragment has overriden | 544 | # category #3: redefined options (this is pretty verbose and is debug only) |
463 | # a value from a base fragment. This is really only used for new kernel introduction | 545 | try: |
464 | if bsp_check_visibility > 2: | 546 | analysis = subprocess.check_output(['symbol_why.py', '--dotconfig', '{}'.format( d.getVar('B') + '/.config' ), '--sanity'], cwd=s, env=env ).decode('utf-8') |
465 | redefinition_file = d.expand("${S}/%s/cfg/redefinition.txt" % kmeta) | 547 | except subprocess.CalledProcessError as e: |
466 | if os.path.exists(redefinition_file) and os.stat(redefinition_file).st_size > 0: | 548 | bb.fatal( "config analysis failed: %s" % e.output.decode('utf-8')) |
467 | with open (redefinition_file, "r") as myfile: | 549 | |
550 | if analysis: | ||
551 | outfile = "{}/{}/cfg/redefinition.txt".format(s,kmeta) | ||
552 | if os.path.isfile(outfile): | ||
553 | os.remove(outfile) | ||
554 | with open(outfile, 'w+') as f: | ||
555 | f.write( analysis ) | ||
556 | |||
557 | # if the audit level is greater than two, we report if a fragment has overriden | ||
558 | # a value from a base fragment. This is really only used for new kernel introduction | ||
559 | if bsp_check_visibility > 2 and os.stat(outfile).st_size > 0: | ||
560 | with open (outfile, "r") as myfile: | ||
468 | results = myfile.read() | 561 | results = myfile.read() |
469 | bb.warn( "[kernel config]: This BSP has configuration options defined in more than one config, with differing values:\n\n%s" % results) | 562 | bb.warn( "[kernel config]: This BSP has configuration options defined in more than one config, with differing values:\n\n%s" % results) |
470 | } | 563 | } |
diff --git a/meta/recipes-kernel/kern-tools/kern-tools-native_git.bb b/meta/recipes-kernel/kern-tools/kern-tools-native_git.bb index 4f1af731d6..4402e14754 100644 --- a/meta/recipes-kernel/kern-tools/kern-tools-native_git.bb +++ b/meta/recipes-kernel/kern-tools/kern-tools-native_git.bb | |||
@@ -4,7 +4,7 @@ LIC_FILES_CHKSUM = "file://tools/kgit;beginline=5;endline=9;md5=9c30e971d435e249 | |||
4 | 4 | ||
5 | DEPENDS = "git-native" | 5 | DEPENDS = "git-native" |
6 | 6 | ||
7 | SRCREV = "c66833e1caac25279a5052fceb13213f5e4f79f9" | 7 | SRCREV = "8b6fa727013daba5e8d72e5fc61d80caed944c6a" |
8 | PR = "r12" | 8 | PR = "r12" |
9 | PV = "0.2+git${SRCPV}" | 9 | PV = "0.2+git${SRCPV}" |
10 | 10 | ||
diff --git a/meta/recipes-kernel/linux/linux-yocto_5.4.bb b/meta/recipes-kernel/linux/linux-yocto_5.4.bb index 3829748269..556eaa6b89 100644 --- a/meta/recipes-kernel/linux/linux-yocto_5.4.bb +++ b/meta/recipes-kernel/linux/linux-yocto_5.4.bb | |||
@@ -38,7 +38,7 @@ DEPENDS += "openssl-native util-linux-native" | |||
38 | PV = "${LINUX_VERSION}+git${SRCPV}" | 38 | PV = "${LINUX_VERSION}+git${SRCPV}" |
39 | 39 | ||
40 | KMETA = "kernel-meta" | 40 | KMETA = "kernel-meta" |
41 | KCONF_BSP_AUDIT_LEVEL = "2" | 41 | KCONF_BSP_AUDIT_LEVEL = "1" |
42 | 42 | ||
43 | KERNEL_DEVICETREE_qemuarmv5 = "versatile-pb.dtb" | 43 | KERNEL_DEVICETREE_qemuarmv5 = "versatile-pb.dtb" |
44 | 44 | ||