swupdate.bbclass 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. # Copyright (C) 2015 Stefano Babic <sbabic@denx.de>
  2. #
  3. # Some parts from the patch class
  4. #
  5. # swupdate allows to generate a compound image for the
  6. # in the "swupdate" format, used for updating the targets
  7. # in field.
  8. # See also http://sbabic.github.io/swupdate/
  9. #
  10. #
  11. # To use, add swupdate to the inherit clause and set
  12. # set the images (all of them must be found in deploy directory)
  13. # that are part of the compound image.
  14. S = "${WORKDIR}/${PN}"
  15. DEPENDS += "${@ 'openssl-native' if d.getVar('SWUPDATE_SIGNING', True) == '1' else ''}"
  16. IMAGE_DEPENDS ?= ""
  17. def swupdate_is_hash_needed(s, filename):
  18. with open(os.path.join(s, "sw-description"), 'r') as f:
  19. for line in f:
  20. if line.find("@%s" % (filename)) != -1:
  21. return True
  22. return False
  23. def swupdate_get_sha256(s, filename):
  24. import hashlib
  25. m = hashlib.sha256()
  26. with open(os.path.join(s, filename), 'rb') as f:
  27. while True:
  28. data = f.read(1024)
  29. if not data:
  30. break
  31. m.update(data)
  32. return m.hexdigest()
  33. def swupdate_write_sha256(s, filename, hash):
  34. write_lines = []
  35. with open(os.path.join(s, "sw-description"), 'r') as f:
  36. for line in f:
  37. write_lines.append(line.replace("@%s" % (filename), hash))
  38. with open(os.path.join(s, "sw-description"), 'w+') as f:
  39. for line in write_lines:
  40. f.write(line)
  41. def swupdate_getdepends(d):
  42. def adddep(depstr, deps):
  43. for i in (depstr or "").split():
  44. if i not in deps:
  45. deps.append(i)
  46. deps = []
  47. images = (d.getVar('IMAGE_DEPENDS', True) or "").split()
  48. for image in images:
  49. adddep(image , deps)
  50. depstr = ""
  51. for dep in deps:
  52. depstr += " " + dep + ":do_populate_sysroot"
  53. return depstr
  54. do_swuimage[dirs] = "${TOPDIR}"
  55. do_swuimage[cleandirs] += "${S}"
  56. do_swuimage[umask] = "022"
  57. do_configure[noexec] = "1"
  58. do_compile[noexec] = "1"
  59. do_install[noexec] = "1"
  60. do_package[noexec] = "1"
  61. do_package_qa[noexec] = "1"
  62. do_packagedata[noexec] = "1"
  63. do_package_write_ipk[noexec] = "1"
  64. do_package_write_deb[noexec] = "1"
  65. do_package_write_rpm[noexec] = "1"
  66. python () {
  67. deps = " " + swupdate_getdepends(d)
  68. d.appendVarFlag('do_build', 'depends', deps)
  69. }
  70. do_install () {
  71. }
  72. do_createlink () {
  73. cd ${DEPLOY_DIR_IMAGE}
  74. ln -sf ${IMAGE_NAME}.swu ${IMAGE_LINK_NAME}.swu
  75. }
  76. python do_swuimage () {
  77. import shutil
  78. workdir = d.getVar('WORKDIR', True)
  79. images = (d.getVar('SWUPDATE_IMAGES', True) or "").split()
  80. s = d.getVar('S', True)
  81. shutil.copyfile(os.path.join(workdir, "sw-description"), os.path.join(s, "sw-description"))
  82. fetch = bb.fetch2.Fetch([], d)
  83. list_for_cpio = ["sw-description"]
  84. for url in fetch.urls:
  85. local = fetch.localpath(url)
  86. filename = os.path.basename(local)
  87. shutil.copyfile(local, os.path.join(s, "%s" % filename ))
  88. if (filename != 'sw-description'):
  89. list_for_cpio.append(filename)
  90. deploydir = d.getVar('DEPLOY_DIR_IMAGE', True)
  91. if d.getVar('SWUPDATE_SIGNING', True) == '1':
  92. list_for_cpio.append('sw-description.sig')
  93. for image in images:
  94. imagename = image + '-' + d.getVar('MACHINE', True)
  95. fstypes = (d.getVarFlag("SWUPDATE_IMAGES_FSTYPES", image, True) or "").split()
  96. for fstype in fstypes:
  97. imagebase = image + '-' + d.getVar('MACHINE', True)
  98. imagename = imagebase + fstype
  99. src = os.path.join(deploydir, "%s" % imagename)
  100. dst = os.path.join(s, "%s" % imagename)
  101. shutil.copyfile(src, dst)
  102. list_for_cpio.append(imagename)
  103. for file in list_for_cpio:
  104. if file != 'sw-description' and swupdate_is_hash_needed(s, file):
  105. hash = swupdate_get_sha256(s, file)
  106. swupdate_write_sha256(s, file, hash)
  107. if d.getVar('SWUPDATE_SIGNING', True) == '1':
  108. privkey = d.getVar('SWUPDATE_PRIVATE_KEY', True)
  109. if not privkey:
  110. bb.fatal("SWUPDATE_PRIVATE_KEY isn't set")
  111. if not os.path.exists(privkey):
  112. bb.fatal("SWUPDATE_PRIVATE_KEY %s doesn't exist" % (privkey))
  113. signcmd = "openssl dgst -sha256 -sign '%s' -out '%s' '%s'" % (
  114. privkey,
  115. os.path.join(s, 'sw-description.sig'),
  116. os.path.join(s, 'sw-description'))
  117. if os.system(signcmd) != 0:
  118. bb.fatal("Failed to sign sw-description with %s" % (privkey))
  119. line = 'for i in ' + ' '.join(list_for_cpio) + '; do echo $i;done | cpio -ov -H crc >' + os.path.join(deploydir,d.getVar('IMAGE_NAME', True) + '.swu')
  120. os.system("cd " + s + ";" + line)
  121. }
  122. COMPRESSIONTYPES = ""
  123. PACKAGE_ARCH = "${MACHINE_ARCH}"
  124. addtask do_swuimage after do_unpack before do_install
  125. addtask do_createlink after do_swuimage before do_install