swupdate.bbclass 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  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_build"
  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. if d.getVar('SWUPDATE_SIGNING', True) == '1':
  85. list_for_cpio.append('sw-description.sig')
  86. for url in fetch.urls:
  87. local = fetch.localpath(url)
  88. filename = os.path.basename(local)
  89. if (filename != 'sw-description'):
  90. shutil.copyfile(local, os.path.join(s, "%s" % filename ))
  91. list_for_cpio.append(filename)
  92. # SWUPDATE_IMAGES refers to images in the DEPLOY directory
  93. # If they are not there, additional file can be added
  94. # by fetching from URLs
  95. deploydir = d.getVar('DEPLOY_DIR_IMAGE', True)
  96. for image in images:
  97. fstypes = (d.getVarFlag("SWUPDATE_IMAGES_FSTYPES", image, True) or "").split()
  98. if not fstypes:
  99. fstypes = [""]
  100. for fstype in fstypes:
  101. appendmachine = d.getVarFlag("SWUPDATE_IMAGES_NOAPPEND_MACHINE", image, True)
  102. if appendmachine == None:
  103. imagebase = image + '-' + d.getVar('MACHINE', True)
  104. else:
  105. imagebase = image
  106. imagename = imagebase + fstype
  107. src = os.path.join(deploydir, "%s" % imagename)
  108. dst = os.path.join(s, "%s" % imagename)
  109. shutil.copyfile(src, dst)
  110. list_for_cpio.append(imagename)
  111. for file in list_for_cpio:
  112. if file != 'sw-description' and swupdate_is_hash_needed(s, file):
  113. hash = swupdate_get_sha256(s, file)
  114. swupdate_write_sha256(s, file, hash)
  115. if d.getVar('SWUPDATE_SIGNING', True) == '1':
  116. privkey = d.getVar('SWUPDATE_PRIVATE_KEY', True)
  117. if not privkey:
  118. bb.fatal("SWUPDATE_PRIVATE_KEY isn't set")
  119. if not os.path.exists(privkey):
  120. bb.fatal("SWUPDATE_PRIVATE_KEY %s doesn't exist" % (privkey))
  121. passout = d.getVar('SWUPDATE_PASSWORD_FILE', True)
  122. if passout:
  123. passout = "-passin file:'%s' " % (passout)
  124. else:
  125. passout = ""
  126. signcmd = "openssl dgst -sha256 -sign '%s' %s -out '%s' '%s'" % (
  127. privkey,
  128. passout,
  129. os.path.join(s, 'sw-description.sig'),
  130. os.path.join(s, 'sw-description'))
  131. if os.system(signcmd) != 0:
  132. bb.fatal("Failed to sign sw-description with %s" % (privkey))
  133. 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')
  134. os.system("cd " + s + ";" + line)
  135. }
  136. COMPRESSIONTYPES = ""
  137. PACKAGE_ARCH = "${MACHINE_ARCH}"
  138. addtask do_swuimage after do_unpack before do_install
  139. addtask do_createlink after do_swuimage before do_install