summaryrefslogtreecommitdiffstats
path: root/meta/lib/oeqa/selftest/cases/fitimage.py
diff options
context:
space:
mode:
Diffstat (limited to 'meta/lib/oeqa/selftest/cases/fitimage.py')
-rw-r--r--meta/lib/oeqa/selftest/cases/fitimage.py537
1 files changed, 509 insertions, 28 deletions
diff --git a/meta/lib/oeqa/selftest/cases/fitimage.py b/meta/lib/oeqa/selftest/cases/fitimage.py
index 02692de822..347c065377 100644
--- a/meta/lib/oeqa/selftest/cases/fitimage.py
+++ b/meta/lib/oeqa/selftest/cases/fitimage.py
@@ -1,11 +1,12 @@
1# 1#
2# Copyright OpenEmbedded Contributors
3#
2# SPDX-License-Identifier: MIT 4# SPDX-License-Identifier: MIT
3# 5#
4 6
5from oeqa.selftest.case import OESelftestTestCase 7from oeqa.selftest.case import OESelftestTestCase
6from oeqa.utils.commands import runCmd, bitbake, get_bb_var, runqemu 8from oeqa.utils.commands import runCmd, bitbake, get_bb_var, get_bb_vars
7import os 9import os
8import json
9import re 10import re
10 11
11class FitImageTests(OESelftestTestCase): 12class FitImageTests(OESelftestTestCase):
@@ -32,6 +33,8 @@ KERNEL_CLASSES = " kernel-fitimage "
32# RAM disk variables including load address and entrypoint for kernel and RAM disk 33# RAM disk variables including load address and entrypoint for kernel and RAM disk
33IMAGE_FSTYPES += "cpio.gz" 34IMAGE_FSTYPES += "cpio.gz"
34INITRAMFS_IMAGE = "core-image-minimal" 35INITRAMFS_IMAGE = "core-image-minimal"
36# core-image-minimal is used as initramfs here, drop the rootfs suffix
37IMAGE_NAME_SUFFIX:pn-core-image-minimal = ""
35UBOOT_RD_LOADADDRESS = "0x88000000" 38UBOOT_RD_LOADADDRESS = "0x88000000"
36UBOOT_RD_ENTRYPOINT = "0x88000000" 39UBOOT_RD_ENTRYPOINT = "0x88000000"
37UBOOT_LOADADDRESS = "0x80080000" 40UBOOT_LOADADDRESS = "0x80080000"
@@ -41,15 +44,14 @@ FIT_DESC = "A model description"
41 self.write_config(config) 44 self.write_config(config)
42 45
43 # fitImage is created as part of linux recipe 46 # fitImage is created as part of linux recipe
44 bitbake("virtual/kernel") 47 image = "virtual/kernel"
48 bitbake(image)
49 bb_vars = get_bb_vars(['DEPLOY_DIR_IMAGE', 'INITRAMFS_IMAGE_NAME', 'KERNEL_FIT_LINK_NAME'], image)
45 50
46 image_type = "core-image-minimal" 51 fitimage_its_path = os.path.join(bb_vars['DEPLOY_DIR_IMAGE'],
47 deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE') 52 "fitImage-its-%s-%s" % (bb_vars['INITRAMFS_IMAGE_NAME'], bb_vars['KERNEL_FIT_LINK_NAME']))
48 machine = get_bb_var('MACHINE') 53 fitimage_path = os.path.join(bb_vars['DEPLOY_DIR_IMAGE'],
49 fitimage_its_path = os.path.join(deploy_dir_image, 54 "fitImage-%s-%s" % (bb_vars['INITRAMFS_IMAGE_NAME'], bb_vars['KERNEL_FIT_LINK_NAME']))
50 "fitImage-its-%s-%s-%s" % (image_type, machine, machine))
51 fitimage_path = os.path.join(deploy_dir_image,
52 "fitImage-%s-%s-%s" % (image_type, machine, machine))
53 55
54 self.assertTrue(os.path.exists(fitimage_its_path), 56 self.assertTrue(os.path.exists(fitimage_its_path),
55 "%s image tree source doesn't exist" % (fitimage_its_path)) 57 "%s image tree source doesn't exist" % (fitimage_its_path))
@@ -114,22 +116,22 @@ KERNEL_CLASSES = " kernel-fitimage test-mkimage-wrapper "
114UBOOT_SIGN_ENABLE = "1" 116UBOOT_SIGN_ENABLE = "1"
115FIT_GENERATE_KEYS = "1" 117FIT_GENERATE_KEYS = "1"
116UBOOT_SIGN_KEYDIR = "${TOPDIR}/signing-keys" 118UBOOT_SIGN_KEYDIR = "${TOPDIR}/signing-keys"
117UBOOT_SIGN_KEYNAME = "oe-selftest" 119UBOOT_SIGN_IMG_KEYNAME = "img-oe-selftest"
120UBOOT_SIGN_KEYNAME = "cfg-oe-selftest"
118FIT_SIGN_INDIVIDUAL = "1" 121FIT_SIGN_INDIVIDUAL = "1"
119UBOOT_MKIMAGE_SIGN_ARGS = "-c 'a smart comment'" 122UBOOT_MKIMAGE_SIGN_ARGS = "-c 'a smart comment'"
120""" 123"""
121 self.write_config(config) 124 self.write_config(config)
122 125
123 # fitImage is created as part of linux recipe 126 # fitImage is created as part of linux recipe
124 bitbake("virtual/kernel") 127 image = "virtual/kernel"
128 bitbake(image)
129 bb_vars = get_bb_vars(['DEPLOY_DIR_IMAGE', 'KERNEL_FIT_LINK_NAME'], image)
125 130
126 image_type = "core-image-minimal" 131 fitimage_its_path = os.path.join(bb_vars['DEPLOY_DIR_IMAGE'],
127 deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE') 132 "fitImage-its-%s" % (bb_vars['KERNEL_FIT_LINK_NAME']))
128 machine = get_bb_var('MACHINE') 133 fitimage_path = os.path.join(bb_vars['DEPLOY_DIR_IMAGE'],
129 fitimage_its_path = os.path.join(deploy_dir_image, 134 "fitImage-%s.bin" % (bb_vars['KERNEL_FIT_LINK_NAME']))
130 "fitImage-its-%s" % (machine,))
131 fitimage_path = os.path.join(deploy_dir_image,
132 "fitImage-%s.bin" % (machine,))
133 135
134 self.assertTrue(os.path.exists(fitimage_its_path), 136 self.assertTrue(os.path.exists(fitimage_its_path),
135 "%s image tree source doesn't exist" % (fitimage_its_path)) 137 "%s image tree source doesn't exist" % (fitimage_its_path))
@@ -173,11 +175,11 @@ UBOOT_MKIMAGE_SIGN_ARGS = "-c 'a smart comment'"
173 175
174 reqsigvalues_image = { 176 reqsigvalues_image = {
175 'algo': '"sha256,rsa2048"', 177 'algo': '"sha256,rsa2048"',
176 'key-name-hint': '"oe-selftest"', 178 'key-name-hint': '"img-oe-selftest"',
177 } 179 }
178 reqsigvalues_config = { 180 reqsigvalues_config = {
179 'algo': '"sha256,rsa2048"', 181 'algo': '"sha256,rsa2048"',
180 'key-name-hint': '"oe-selftest"', 182 'key-name-hint': '"cfg-oe-selftest"',
181 'sign-images': '"kernel", "fdt"', 183 'sign-images': '"kernel", "fdt"',
182 } 184 }
183 185
@@ -202,7 +204,7 @@ UBOOT_MKIMAGE_SIGN_ARGS = "-c 'a smart comment'"
202 signed_sections = {} 204 signed_sections = {}
203 for line in result.output.splitlines(): 205 for line in result.output.splitlines():
204 if line.startswith((' Configuration', ' Image')): 206 if line.startswith((' Configuration', ' Image')):
205 in_signed = re.search('\((.*)\)', line).groups()[0] 207 in_signed = re.search(r'\((.*)\)', line).groups()[0]
206 elif re.match('^ *', line) in (' ', ''): 208 elif re.match('^ *', line) in (' ', ''):
207 in_signed = None 209 in_signed = None
208 elif in_signed: 210 elif in_signed:
@@ -215,7 +217,10 @@ UBOOT_MKIMAGE_SIGN_ARGS = "-c 'a smart comment'"
215 self.assertIn('conf-am335x-boneblack.dtb', signed_sections) 217 self.assertIn('conf-am335x-boneblack.dtb', signed_sections)
216 for signed_section, values in signed_sections.items(): 218 for signed_section, values in signed_sections.items():
217 value = values.get('Sign algo', None) 219 value = values.get('Sign algo', None)
218 self.assertEqual(value, 'sha256,rsa2048:oe-selftest', 'Signature algorithm for %s not expected value' % signed_section) 220 if signed_section.startswith("conf"):
221 self.assertEqual(value, 'sha256,rsa2048:cfg-oe-selftest', 'Signature algorithm for %s not expected value' % signed_section)
222 else:
223 self.assertEqual(value, 'sha256,rsa2048:img-oe-selftest', 'Signature algorithm for %s not expected value' % signed_section)
219 value = values.get('Sign value', None) 224 value = values.get('Sign value', None)
220 self.assertEqual(len(value), 512, 'Signature value for section %s not expected length' % signed_section) 225 self.assertEqual(len(value), 512, 'Signature value for section %s not expected length' % signed_section)
221 226
@@ -231,6 +236,480 @@ UBOOT_MKIMAGE_SIGN_ARGS = "-c 'a smart comment'"
231 result = runCmd('grep "### uboot-mkimage signing wrapper message" %s/log.do_assemble_fitimage' % tempdir, ignore_status=True) 236 result = runCmd('grep "### uboot-mkimage signing wrapper message" %s/log.do_assemble_fitimage' % tempdir, ignore_status=True)
232 self.assertEqual(result.status, 0, 'UBOOT_MKIMAGE_SIGN did not work') 237 self.assertEqual(result.status, 0, 'UBOOT_MKIMAGE_SIGN did not work')
233 238
239 def test_uboot_fit_image(self):
240 """
241 Summary: Check if Uboot FIT image and Image Tree Source
242 (its) are built and the Image Tree Source has the
243 correct fields.
244 Expected: 1. u-boot-fitImage and u-boot-its can be built
245 2. The type, load address, entrypoint address and
246 default values of U-boot image are correct in the
247 Image Tree Source. Not all the fields are tested,
248 only the key fields that wont vary between
249 different architectures.
250 Product: oe-core
251 Author: Klaus Heinrich Kiwi <klaus@linux.vnet.ibm.com>
252 based on work by Usama Arif <usama.arif@arm.com>
253 """
254 config = """
255# We need at least CONFIG_SPL_LOAD_FIT and CONFIG_SPL_OF_CONTROL set
256MACHINE = "qemuarm"
257UBOOT_MACHINE = "am57xx_evm_defconfig"
258SPL_BINARY = "MLO"
259
260# Enable creation of the U-Boot fitImage
261UBOOT_FITIMAGE_ENABLE = "1"
262
263# (U-boot) fitImage properties
264UBOOT_LOADADDRESS = "0x80080000"
265UBOOT_ENTRYPOINT = "0x80080000"
266UBOOT_FIT_DESC = "A model description"
267
268# Enable creation of Kernel fitImage
269KERNEL_IMAGETYPES += " fitImage "
270KERNEL_CLASSES = " kernel-fitimage"
271UBOOT_SIGN_ENABLE = "1"
272FIT_GENERATE_KEYS = "1"
273UBOOT_SIGN_KEYDIR = "${TOPDIR}/signing-keys"
274UBOOT_SIGN_IMG_KEYNAME = "img-oe-selftest"
275UBOOT_SIGN_KEYNAME = "cfg-oe-selftest"
276FIT_SIGN_INDIVIDUAL = "1"
277"""
278 self.write_config(config)
279
280 # The U-Boot fitImage is created as part of the U-Boot recipe
281 bitbake("virtual/bootloader")
282
283 deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE')
284 machine = get_bb_var('MACHINE')
285 fitimage_its_path = os.path.join(deploy_dir_image,
286 "u-boot-its-%s" % (machine,))
287 fitimage_path = os.path.join(deploy_dir_image,
288 "u-boot-fitImage-%s" % (machine,))
289
290 self.assertTrue(os.path.exists(fitimage_its_path),
291 "%s image tree source doesn't exist" % (fitimage_its_path))
292 self.assertTrue(os.path.exists(fitimage_path),
293 "%s FIT image doesn't exist" % (fitimage_path))
294
295 # Check that the type, load address, entrypoint address and default
296 # values for kernel and ramdisk in Image Tree Source are as expected.
297 # The order of fields in the below array is important. Not all the
298 # fields are tested, only the key fields that wont vary between
299 # different architectures.
300 its_field_check = [
301 'description = "A model description";',
302 'type = "standalone";',
303 'load = <0x80080000>;',
304 'entry = <0x80080000>;',
305 'default = "conf";',
306 'loadables = "uboot";',
307 'fdt = "fdt";'
308 ]
309
310 with open(fitimage_its_path) as its_file:
311 field_index = 0
312 for line in its_file:
313 if field_index == len(its_field_check):
314 break
315 if its_field_check[field_index] in line:
316 field_index +=1
317
318 if field_index != len(its_field_check): # if its equal, the test passed
319 self.assertTrue(field_index == len(its_field_check),
320 "Fields in Image Tree Source File %s did not match, error in finding %s"
321 % (fitimage_its_path, its_field_check[field_index]))
322
323 def test_uboot_sign_fit_image(self):
324 """
325 Summary: Check if Uboot FIT image and Image Tree Source
326 (its) are built and the Image Tree Source has the
327 correct fields, in the scenario where the Kernel
328 is also creating/signing it's fitImage.
329 Expected: 1. u-boot-fitImage and u-boot-its can be built
330 2. The type, load address, entrypoint address and
331 default values of U-boot image are correct in the
332 Image Tree Source. Not all the fields are tested,
333 only the key fields that wont vary between
334 different architectures.
335 Product: oe-core
336 Author: Klaus Heinrich Kiwi <klaus@linux.vnet.ibm.com>
337 based on work by Usama Arif <usama.arif@arm.com>
338 """
339 config = """
340# We need at least CONFIG_SPL_LOAD_FIT and CONFIG_SPL_OF_CONTROL set
341MACHINE = "qemuarm"
342UBOOT_MACHINE = "am57xx_evm_defconfig"
343SPL_BINARY = "MLO"
344
345# Enable creation of the U-Boot fitImage
346UBOOT_FITIMAGE_ENABLE = "1"
347
348# (U-boot) fitImage properties
349UBOOT_LOADADDRESS = "0x80080000"
350UBOOT_ENTRYPOINT = "0x80080000"
351UBOOT_FIT_DESC = "A model description"
352KERNEL_IMAGETYPES += " fitImage "
353KERNEL_CLASSES = " kernel-fitimage "
354INHERIT += "test-mkimage-wrapper"
355UBOOT_SIGN_ENABLE = "1"
356FIT_GENERATE_KEYS = "1"
357UBOOT_SIGN_KEYDIR = "${TOPDIR}/signing-keys"
358UBOOT_SIGN_IMG_KEYNAME = "img-oe-selftest"
359UBOOT_SIGN_KEYNAME = "cfg-oe-selftest"
360FIT_SIGN_INDIVIDUAL = "1"
361UBOOT_MKIMAGE_SIGN_ARGS = "-c 'a smart U-Boot comment'"
362"""
363 self.write_config(config)
364
365 # The U-Boot fitImage is created as part of the U-Boot recipe
366 bitbake("virtual/bootloader")
367
368 deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE')
369 machine = get_bb_var('MACHINE')
370 fitimage_its_path = os.path.join(deploy_dir_image,
371 "u-boot-its-%s" % (machine,))
372 fitimage_path = os.path.join(deploy_dir_image,
373 "u-boot-fitImage-%s" % (machine,))
374
375 self.assertTrue(os.path.exists(fitimage_its_path),
376 "%s image tree source doesn't exist" % (fitimage_its_path))
377 self.assertTrue(os.path.exists(fitimage_path),
378 "%s FIT image doesn't exist" % (fitimage_path))
379
380 # Check that the type, load address, entrypoint address and default
381 # values for kernel and ramdisk in Image Tree Source are as expected.
382 # The order of fields in the below array is important. Not all the
383 # fields are tested, only the key fields that wont vary between
384 # different architectures.
385 its_field_check = [
386 'description = "A model description";',
387 'type = "standalone";',
388 'load = <0x80080000>;',
389 'entry = <0x80080000>;',
390 'default = "conf";',
391 'loadables = "uboot";',
392 'fdt = "fdt";'
393 ]
394
395 with open(fitimage_its_path) as its_file:
396 field_index = 0
397 for line in its_file:
398 if field_index == len(its_field_check):
399 break
400 if its_field_check[field_index] in line:
401 field_index +=1
402
403 if field_index != len(its_field_check): # if its equal, the test passed
404 self.assertTrue(field_index == len(its_field_check),
405 "Fields in Image Tree Source File %s did not match, error in finding %s"
406 % (fitimage_its_path, its_field_check[field_index]))
407
408
409 def test_sign_standalone_uboot_fit_image(self):
410 """
411 Summary: Check if U-Boot FIT image and Image Tree Source (its) are
412 created and signed correctly for the scenario where only
413 the U-Boot proper fitImage is being created and signed.
414 Expected: 1) U-Boot its and FIT image are built successfully
415 2) Scanning the its file indicates signing is enabled
416 as requested by SPL_SIGN_ENABLE (using keys generated
417 via UBOOT_FIT_GENERATE_KEYS)
418 3) Dumping the FIT image indicates signature values
419 are present
420 4) Examination of the do_uboot_assemble_fitimage
421 runfile/logfile indicate that UBOOT_MKIMAGE, UBOOT_MKIMAGE_SIGN
422 and SPL_MKIMAGE_SIGN_ARGS are working as expected.
423 Product: oe-core
424 Author: Klaus Heinrich Kiwi <klaus@linux.vnet.ibm.com> based upon
425 work by Paul Eggleton <paul.eggleton@microsoft.com> and
426 Usama Arif <usama.arif@arm.com>
427 """
428 config = """
429# There's no U-boot deconfig with CONFIG_FIT_SIGNATURE yet, so we need at
430# least CONFIG_SPL_LOAD_FIT and CONFIG_SPL_OF_CONTROL set
431MACHINE = "qemuarm"
432UBOOT_MACHINE = "am57xx_evm_defconfig"
433SPL_BINARY = "MLO"
434# The kernel-fitimage class is a dependency even if we're only
435# creating/signing the U-Boot fitImage
436KERNEL_CLASSES = " kernel-fitimage"
437INHERIT += "test-mkimage-wrapper"
438# Enable creation and signing of the U-Boot fitImage
439UBOOT_FITIMAGE_ENABLE = "1"
440SPL_SIGN_ENABLE = "1"
441SPL_SIGN_KEYNAME = "spl-oe-selftest"
442SPL_SIGN_KEYDIR = "${TOPDIR}/signing-keys"
443UBOOT_DTB_BINARY = "u-boot.dtb"
444UBOOT_ENTRYPOINT = "0x80000000"
445UBOOT_LOADADDRESS = "0x80000000"
446UBOOT_DTB_LOADADDRESS = "0x82000000"
447UBOOT_ARCH = "arm"
448SPL_MKIMAGE_DTCOPTS = "-I dts -O dtb -p 2000"
449SPL_MKIMAGE_SIGN_ARGS = "-c 'a smart U-Boot comment'"
450UBOOT_EXTLINUX = "0"
451UBOOT_FIT_GENERATE_KEYS = "1"
452UBOOT_FIT_HASH_ALG = "sha256"
453"""
454 self.write_config(config)
455
456 # The U-Boot fitImage is created as part of the U-Boot recipe
457 bitbake("virtual/bootloader")
458
459 image_type = "core-image-minimal"
460 deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE')
461 machine = get_bb_var('MACHINE')
462 fitimage_its_path = os.path.join(deploy_dir_image,
463 "u-boot-its-%s" % (machine,))
464 fitimage_path = os.path.join(deploy_dir_image,
465 "u-boot-fitImage-%s" % (machine,))
466
467 self.assertTrue(os.path.exists(fitimage_its_path),
468 "%s image tree source doesn't exist" % (fitimage_its_path))
469 self.assertTrue(os.path.exists(fitimage_path),
470 "%s FIT image doesn't exist" % (fitimage_path))
471
472 req_itspaths = [
473 ['/', 'images', 'uboot'],
474 ['/', 'images', 'uboot', 'signature'],
475 ['/', 'images', 'fdt'],
476 ['/', 'images', 'fdt', 'signature'],
477 ]
478
479 itspath = []
480 itspaths = []
481 linect = 0
482 sigs = {}
483 with open(fitimage_its_path) as its_file:
484 linect += 1
485 for line in its_file:
486 line = line.strip()
487 if line.endswith('};'):
488 itspath.pop()
489 elif line.endswith('{'):
490 itspath.append(line[:-1].strip())
491 itspaths.append(itspath[:])
492 elif itspath and itspath[-1] == 'signature':
493 itsdotpath = '.'.join(itspath)
494 if not itsdotpath in sigs:
495 sigs[itsdotpath] = {}
496 if not '=' in line or not line.endswith(';'):
497 self.fail('Unexpected formatting in %s sigs section line %d:%s' % (fitimage_its_path, linect, line))
498 key, value = line.split('=', 1)
499 sigs[itsdotpath][key.rstrip()] = value.lstrip().rstrip(';')
500
501 for reqpath in req_itspaths:
502 if not reqpath in itspaths:
503 self.fail('Missing section in its file: %s' % reqpath)
504
505 reqsigvalues_image = {
506 'algo': '"sha256,rsa2048"',
507 'key-name-hint': '"spl-oe-selftest"',
508 }
509
510 for itspath, values in sigs.items():
511 reqsigvalues = reqsigvalues_image
512 for reqkey, reqvalue in reqsigvalues.items():
513 value = values.get(reqkey, None)
514 if value is None:
515 self.fail('Missing key "%s" in its file signature section %s' % (reqkey, itspath))
516 self.assertEqual(value, reqvalue)
517
518 # Dump the image to see if it really got signed
519 bitbake("u-boot-tools-native -c addto_recipe_sysroot")
520 result = runCmd('bitbake -e u-boot-tools-native | grep ^RECIPE_SYSROOT_NATIVE=')
521 recipe_sysroot_native = result.output.split('=')[1].strip('"')
522 dumpimage_path = os.path.join(recipe_sysroot_native, 'usr', 'bin', 'dumpimage')
523 result = runCmd('%s -l %s' % (dumpimage_path, fitimage_path))
524 in_signed = None
525 signed_sections = {}
526 for line in result.output.splitlines():
527 if line.startswith((' Image')):
528 in_signed = re.search(r'\((.*)\)', line).groups()[0]
529 elif re.match(' \w', line):
530 in_signed = None
531 elif in_signed:
532 if not in_signed in signed_sections:
533 signed_sections[in_signed] = {}
534 key, value = line.split(':', 1)
535 signed_sections[in_signed][key.strip()] = value.strip()
536 self.assertIn('uboot', signed_sections)
537 self.assertIn('fdt', signed_sections)
538 for signed_section, values in signed_sections.items():
539 value = values.get('Sign algo', None)
540 self.assertEqual(value, 'sha256,rsa2048:spl-oe-selftest', 'Signature algorithm for %s not expected value' % signed_section)
541 value = values.get('Sign value', None)
542 self.assertEqual(len(value), 512, 'Signature value for section %s not expected length' % signed_section)
543
544 # Check for SPL_MKIMAGE_SIGN_ARGS
545 result = runCmd('bitbake -e virtual/bootloader | grep ^T=')
546 tempdir = result.output.split('=', 1)[1].strip().strip('')
547 result = runCmd('grep "a smart U-Boot comment" %s/run.do_uboot_assemble_fitimage' % tempdir, ignore_status=True)
548 self.assertEqual(result.status, 0, 'SPL_MKIMAGE_SIGN_ARGS value did not get used')
549
550 # Check for evidence of test-mkimage-wrapper class
551 result = runCmd('grep "### uboot-mkimage wrapper message" %s/log.do_uboot_assemble_fitimage' % tempdir, ignore_status=True)
552 self.assertEqual(result.status, 0, 'UBOOT_MKIMAGE did not work')
553 result = runCmd('grep "### uboot-mkimage signing wrapper message" %s/log.do_uboot_assemble_fitimage' % tempdir, ignore_status=True)
554 self.assertEqual(result.status, 0, 'UBOOT_MKIMAGE_SIGN did not work')
555
556 def test_sign_cascaded_uboot_fit_image(self):
557 """
558 Summary: Check if U-Boot FIT image and Image Tree Source (its) are
559 created and signed correctly for the scenario where both
560 U-Boot proper and Kernel fitImages are being created and
561 signed.
562 Expected: 1) U-Boot its and FIT image are built successfully
563 2) Scanning the its file indicates signing is enabled
564 as requested by SPL_SIGN_ENABLE (using keys generated
565 via UBOOT_FIT_GENERATE_KEYS)
566 3) Dumping the FIT image indicates signature values
567 are present
568 4) Examination of the do_uboot_assemble_fitimage
569 runfile/logfile indicate that UBOOT_MKIMAGE, UBOOT_MKIMAGE_SIGN
570 and SPL_MKIMAGE_SIGN_ARGS are working as expected.
571 Product: oe-core
572 Author: Klaus Heinrich Kiwi <klaus@linux.vnet.ibm.com> based upon
573 work by Paul Eggleton <paul.eggleton@microsoft.com> and
574 Usama Arif <usama.arif@arm.com>
575 """
576 config = """
577# There's no U-boot deconfig with CONFIG_FIT_SIGNATURE yet, so we need at
578# least CONFIG_SPL_LOAD_FIT and CONFIG_SPL_OF_CONTROL set
579MACHINE = "qemuarm"
580UBOOT_MACHINE = "am57xx_evm_defconfig"
581SPL_BINARY = "MLO"
582# Enable creation and signing of the U-Boot fitImage
583UBOOT_FITIMAGE_ENABLE = "1"
584SPL_SIGN_ENABLE = "1"
585SPL_SIGN_KEYNAME = "spl-cascaded-oe-selftest"
586SPL_SIGN_KEYDIR = "${TOPDIR}/signing-keys"
587UBOOT_DTB_BINARY = "u-boot.dtb"
588UBOOT_ENTRYPOINT = "0x80000000"
589UBOOT_LOADADDRESS = "0x80000000"
590UBOOT_MKIMAGE_DTCOPTS = "-I dts -O dtb -p 2000"
591UBOOT_MKIMAGE_SIGN_ARGS = "-c 'a smart cascaded Kernel comment'"
592UBOOT_DTB_LOADADDRESS = "0x82000000"
593UBOOT_ARCH = "arm"
594SPL_MKIMAGE_DTCOPTS = "-I dts -O dtb -p 2000"
595SPL_MKIMAGE_SIGN_ARGS = "-c 'a smart cascaded U-Boot comment'"
596UBOOT_EXTLINUX = "0"
597UBOOT_FIT_GENERATE_KEYS = "1"
598UBOOT_FIT_HASH_ALG = "sha256"
599KERNEL_IMAGETYPES += " fitImage "
600KERNEL_CLASSES = " kernel-fitimage "
601INHERIT += "test-mkimage-wrapper"
602UBOOT_SIGN_ENABLE = "1"
603FIT_GENERATE_KEYS = "1"
604UBOOT_SIGN_KEYDIR = "${TOPDIR}/signing-keys"
605UBOOT_SIGN_IMG_KEYNAME = "img-oe-selftest"
606UBOOT_SIGN_KEYNAME = "cfg-oe-selftest"
607FIT_SIGN_INDIVIDUAL = "1"
608"""
609 self.write_config(config)
610
611 # The U-Boot fitImage is created as part of the U-Boot recipe
612 bitbake("virtual/bootloader")
613
614 image_type = "core-image-minimal"
615 deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE')
616 machine = get_bb_var('MACHINE')
617 fitimage_its_path = os.path.join(deploy_dir_image,
618 "u-boot-its-%s" % (machine,))
619 fitimage_path = os.path.join(deploy_dir_image,
620 "u-boot-fitImage-%s" % (machine,))
621
622 self.assertTrue(os.path.exists(fitimage_its_path),
623 "%s image tree source doesn't exist" % (fitimage_its_path))
624 self.assertTrue(os.path.exists(fitimage_path),
625 "%s FIT image doesn't exist" % (fitimage_path))
626
627 req_itspaths = [
628 ['/', 'images', 'uboot'],
629 ['/', 'images', 'uboot', 'signature'],
630 ['/', 'images', 'fdt'],
631 ['/', 'images', 'fdt', 'signature'],
632 ]
633
634 itspath = []
635 itspaths = []
636 linect = 0
637 sigs = {}
638 with open(fitimage_its_path) as its_file:
639 linect += 1
640 for line in its_file:
641 line = line.strip()
642 if line.endswith('};'):
643 itspath.pop()
644 elif line.endswith('{'):
645 itspath.append(line[:-1].strip())
646 itspaths.append(itspath[:])
647 elif itspath and itspath[-1] == 'signature':
648 itsdotpath = '.'.join(itspath)
649 if not itsdotpath in sigs:
650 sigs[itsdotpath] = {}
651 if not '=' in line or not line.endswith(';'):
652 self.fail('Unexpected formatting in %s sigs section line %d:%s' % (fitimage_its_path, linect, line))
653 key, value = line.split('=', 1)
654 sigs[itsdotpath][key.rstrip()] = value.lstrip().rstrip(';')
655
656 for reqpath in req_itspaths:
657 if not reqpath in itspaths:
658 self.fail('Missing section in its file: %s' % reqpath)
659
660 reqsigvalues_image = {
661 'algo': '"sha256,rsa2048"',
662 'key-name-hint': '"spl-cascaded-oe-selftest"',
663 }
664
665 for itspath, values in sigs.items():
666 reqsigvalues = reqsigvalues_image
667 for reqkey, reqvalue in reqsigvalues.items():
668 value = values.get(reqkey, None)
669 if value is None:
670 self.fail('Missing key "%s" in its file signature section %s' % (reqkey, itspath))
671 self.assertEqual(value, reqvalue)
672
673 # Dump the image to see if it really got signed
674 bitbake("u-boot-tools-native -c addto_recipe_sysroot")
675 result = runCmd('bitbake -e u-boot-tools-native | grep ^RECIPE_SYSROOT_NATIVE=')
676 recipe_sysroot_native = result.output.split('=')[1].strip('"')
677 dumpimage_path = os.path.join(recipe_sysroot_native, 'usr', 'bin', 'dumpimage')
678 result = runCmd('%s -l %s' % (dumpimage_path, fitimage_path))
679 in_signed = None
680 signed_sections = {}
681 for line in result.output.splitlines():
682 if line.startswith((' Image')):
683 in_signed = re.search(r'\((.*)\)', line).groups()[0]
684 elif re.match(' \w', line):
685 in_signed = None
686 elif in_signed:
687 if not in_signed in signed_sections:
688 signed_sections[in_signed] = {}
689 key, value = line.split(':', 1)
690 signed_sections[in_signed][key.strip()] = value.strip()
691 self.assertIn('uboot', signed_sections)
692 self.assertIn('fdt', signed_sections)
693 for signed_section, values in signed_sections.items():
694 value = values.get('Sign algo', None)
695 self.assertEqual(value, 'sha256,rsa2048:spl-cascaded-oe-selftest', 'Signature algorithm for %s not expected value' % signed_section)
696 value = values.get('Sign value', None)
697 self.assertEqual(len(value), 512, 'Signature value for section %s not expected length' % signed_section)
698
699 # Check for SPL_MKIMAGE_SIGN_ARGS
700 result = runCmd('bitbake -e virtual/bootloader | grep ^T=')
701 tempdir = result.output.split('=', 1)[1].strip().strip('')
702 result = runCmd('grep "a smart cascaded U-Boot comment" %s/run.do_uboot_assemble_fitimage' % tempdir, ignore_status=True)
703 self.assertEqual(result.status, 0, 'SPL_MKIMAGE_SIGN_ARGS value did not get used')
704
705 # Check for evidence of test-mkimage-wrapper class
706 result = runCmd('grep "### uboot-mkimage wrapper message" %s/log.do_uboot_assemble_fitimage' % tempdir, ignore_status=True)
707 self.assertEqual(result.status, 0, 'UBOOT_MKIMAGE did not work')
708 result = runCmd('grep "### uboot-mkimage signing wrapper message" %s/log.do_uboot_assemble_fitimage' % tempdir, ignore_status=True)
709 self.assertEqual(result.status, 0, 'UBOOT_MKIMAGE_SIGN did not work')
710
711
712
234 def test_initramfs_bundle(self): 713 def test_initramfs_bundle(self):
235 """ 714 """
236 Summary: Verifies the content of the initramfs bundle node in the FIT Image Tree Source (its) 715 Summary: Verifies the content of the initramfs bundle node in the FIT Image Tree Source (its)
@@ -264,9 +743,11 @@ UBOOT_LOADADDRESS = "0x80000000"
264UBOOT_DTB_LOADADDRESS = "0x82000000" 743UBOOT_DTB_LOADADDRESS = "0x82000000"
265UBOOT_ARCH = "arm" 744UBOOT_ARCH = "arm"
266UBOOT_MKIMAGE_DTCOPTS = "-I dts -O dtb -p 2000" 745UBOOT_MKIMAGE_DTCOPTS = "-I dts -O dtb -p 2000"
746UBOOT_MKIMAGE_KERNEL_TYPE = "kernel"
267UBOOT_EXTLINUX = "0" 747UBOOT_EXTLINUX = "0"
268FIT_GENERATE_KEYS = "1" 748FIT_GENERATE_KEYS = "1"
269KERNEL_IMAGETYPE_REPLACEMENT = "zImage" 749KERNEL_IMAGETYPE_REPLACEMENT = "zImage"
750FIT_KERNEL_COMP_ALG = "none"
270FIT_HASH_ALG = "sha256" 751FIT_HASH_ALG = "sha256"
271""" 752"""
272 self.write_config(config) 753 self.write_config(config)
@@ -288,9 +769,9 @@ FIT_HASH_ALG = "sha256"
288 769
289 kernel_load = str(get_bb_var('UBOOT_LOADADDRESS')) 770 kernel_load = str(get_bb_var('UBOOT_LOADADDRESS'))
290 kernel_entry = str(get_bb_var('UBOOT_ENTRYPOINT')) 771 kernel_entry = str(get_bb_var('UBOOT_ENTRYPOINT'))
291 initramfs_bundle_format = str(get_bb_var('KERNEL_IMAGETYPE_REPLACEMENT')) 772 kernel_type = str(get_bb_var('UBOOT_MKIMAGE_KERNEL_TYPE'))
773 kernel_compression = str(get_bb_var('FIT_KERNEL_COMP_ALG'))
292 uboot_arch = str(get_bb_var('UBOOT_ARCH')) 774 uboot_arch = str(get_bb_var('UBOOT_ARCH'))
293 initramfs_bundle = "arch/" + uboot_arch + "/boot/" + initramfs_bundle_format + ".initramfs"
294 fit_hash_alg = str(get_bb_var('FIT_HASH_ALG')) 775 fit_hash_alg = str(get_bb_var('FIT_HASH_ALG'))
295 776
296 its_file = open(fitimage_its_path) 777 its_file = open(fitimage_its_path)
@@ -300,11 +781,11 @@ FIT_HASH_ALG = "sha256"
300 exp_node_lines = [ 781 exp_node_lines = [
301 'kernel-1 {', 782 'kernel-1 {',
302 'description = "Linux kernel";', 783 'description = "Linux kernel";',
303 'data = /incbin/("' + initramfs_bundle + '");', 784 'data = /incbin/("linux.bin");',
304 'type = "kernel";', 785 'type = "' + kernel_type + '";',
305 'arch = "' + uboot_arch + '";', 786 'arch = "' + uboot_arch + '";',
306 'os = "linux";', 787 'os = "linux";',
307 'compression = "none";', 788 'compression = "' + kernel_compression + '";',
308 'load = <' + kernel_load + '>;', 789 'load = <' + kernel_load + '>;',
309 'entry = <' + kernel_entry + '>;', 790 'entry = <' + kernel_entry + '>;',
310 'hash-1 {', 791 'hash-1 {',