layerscape: convert to python3 for rcw
authorYangbo Lu <yangbo.lu@nxp.com>
Wed, 19 Jun 2019 03:12:19 +0000 (11:12 +0800)
committerPetr Štetiar <ynezz@true.cz>
Fri, 26 Jul 2019 06:09:16 +0000 (08:09 +0200)
Python 2.7 will not be maintained past 2020. Let's convert
to python3 for rcw. Also drop byte swapping since TF-A had
been already used which handled byte swapping instead.

Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
package/firmware/layerscape/ls-rcw/patches/0001-Disable-byte-swapping.patch [new file with mode: 0644]
package/firmware/layerscape/ls-rcw/patches/0001-rcw-support-byte-swapping-without-tclsh-tool.patch [deleted file]
package/firmware/layerscape/ls-rcw/patches/0002-Convert-to-python3.patch [new file with mode: 0644]

diff --git a/package/firmware/layerscape/ls-rcw/patches/0001-Disable-byte-swapping.patch b/package/firmware/layerscape/ls-rcw/patches/0001-Disable-byte-swapping.patch
new file mode 100644 (file)
index 0000000..2ea260b
--- /dev/null
@@ -0,0 +1,44 @@
+From ef78dc0683a7f5ae80b27878a8a2f91d504e3290 Mon Sep 17 00:00:00 2001
+From: Yangbo Lu <yangbo.lu@nxp.com>
+Date: Wed, 19 Jun 2019 10:50:29 +0800
+Subject: [PATCH 1/2] Disable byte swapping
+
+Because TF-A had already handled rcw byte swapping, the
+byte swapping in rcw could be dropped.
+
+Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+---
+ Makefile     | 4 ----
+ Makefile.inc | 1 -
+ 2 files changed, 5 deletions(-)
+
+diff --git a/Makefile b/Makefile
+index f697241..837b69e 100644
+--- a/Makefile
++++ b/Makefile
+@@ -14,10 +14,6 @@ TCLSH := $(shell command -v tclsh 2> /dev/null)
+ VER = $(shell git describe --tags)
+ all install clean:
+-ifndef TCLSH
+-      $(error "tclsh is not available. please  install it.")
+-      exit 1
+-endif
+       @for board in $(BOARDS); do \
+               $(MAKE) -C $$board $@ DESTDIR=$(DESTDIR)/$$board; \
+       done
+diff --git a/Makefile.inc b/Makefile.inc
+index 87639bc..7d9a3d3 100644
+--- a/Makefile.inc
++++ b/Makefile.inc
+@@ -17,7 +17,6 @@ targets = $(txt_sources:.txt=.bin) $(rcw_sources:.rcw=.bin) $(swap_sources)
+       $(RCW) -i $< -o $@
+ all: $(targets)
+-      $(QSPI_SWAP_SCRIPT) $(QSPI_SWAP_LIST)
+ install: $(targets)
+       $(INSTALL) -d $(DESTDIR)
+-- 
+2.7.4
+
diff --git a/package/firmware/layerscape/ls-rcw/patches/0001-rcw-support-byte-swapping-without-tclsh-tool.patch b/package/firmware/layerscape/ls-rcw/patches/0001-rcw-support-byte-swapping-without-tclsh-tool.patch
deleted file mode 100644 (file)
index 08492dd..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-From c87a500c45f36ad248b1298d63e590d1d7e74f12 Mon Sep 17 00:00:00 2001
-From: Yangbo Lu <yangbo.lu@nxp.com>
-Date: Tue, 3 Jul 2018 11:06:47 +0800
-Subject: [PATCH] rcw: support byte swapping without tclsh tool
-
-Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
----
- Makefile     |    4 ----
- byte_swap.py |   32 ++++++++++++++++++++++++++++++++
- qspi_swap.sh |    2 +-
- 3 files changed, 33 insertions(+), 5 deletions(-)
- create mode 100755 byte_swap.py
-
-diff --git a/Makefile b/Makefile
-index 9f0587e..393bb2c 100644
---- a/Makefile
-+++ b/Makefile
-@@ -13,10 +13,6 @@ TCLSH := $(shell command -v tclsh 2> /dev/null)
- VER = $(shell git describe --tags)
- all install clean:
--ifndef TCLSH
--      $(error "tclsh is not available. please  install it.")
--      exit 1
--endif
-       @for board in $(BOARDS); do \
-               $(MAKE) -C $$board $@ DESTDIR=$(DESTDIR)/$$board; \
-       done
-diff --git a/byte_swap.py b/byte_swap.py
-new file mode 100755
-index 0000000..386310e
---- /dev/null
-+++ b/byte_swap.py
-@@ -0,0 +1,32 @@
-+#!/usr/bin/env python
-+"""
-+Swap the 4/8 bytes endian except for PBI CRC
-+2016-10-9: Initial version
-+
-+Usage:
-+      ./byte_swap.py <file_name> <byte>
-+"""
-+import sys
-+
-+try:
-+    file_name = sys.argv[1]
-+    byte = int(sys.argv[2])
-+except:
-+    print("Usage: ./byte_swap.py <file_name> <byte>")
-+    print("E.g.: ./byte_swap.py rcw_1600.bin 8\n")
-+    exit
-+
-+with open(file_name,'rb') as file:
-+    tmp = file.read()
-+file.close()
-+
-+with open(file_name + '.swapped','wb') as file:
-+    for i in range(0, len(tmp) - 1, byte):
-+      if(tmp[i:i+4].encode('hex')) == "08610040":
-+          #print("PBI CRC command")
-+          file.write(tmp[i:i+8])
-+          break
-+      file.write(tmp[i:i+byte][::-1])
-+file.close()
-+
-+print("Swapped file: " + file_name + '.swapped')
-diff --git a/qspi_swap.sh b/qspi_swap.sh
-index 0b58e44..d23fd8b 100755
---- a/qspi_swap.sh
-+++ b/qspi_swap.sh
-@@ -9,7 +9,7 @@ do
-       if [ "$board_name" = "$current_dir" ]; then
-               if [ -e $filename ]; then
-                       swapped_file="$filename.swapped"
--                      tclsh ../tools/byte_swap.tcl $filename $swapped_file 8
-+                      ../byte_swap.py $filename 8
-               fi
-       fi
- done < $1
--- 
-1.7.1
-
diff --git a/package/firmware/layerscape/ls-rcw/patches/0002-Convert-to-python3.patch b/package/firmware/layerscape/ls-rcw/patches/0002-Convert-to-python3.patch
new file mode 100644 (file)
index 0000000..8aa629d
--- /dev/null
@@ -0,0 +1,504 @@
+From 7bd43eb9e5cdf2035793d50a31bf13052eb9812a Mon Sep 17 00:00:00 2001
+From: Yangbo Lu <yangbo.lu@nxp.com>
+Date: Wed, 19 Jun 2019 10:25:41 +0800
+Subject: [PATCH 2/2] Convert to python3
+
+Python 2.7 will not be maintained past 2020. Let's convert
+to python3 for rcw. Below were the changes of this patch.
+- Adapted print usage
+- Didn't use tab anymore
+- Handled str and bytes type separately
+- Other minor changes
+
+Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+---
+ Makefile.inc |   2 +-
+ rcw.py       | 144 +++++++++++++++++++++++++++++------------------------------
+ 2 files changed, 73 insertions(+), 73 deletions(-)
+
+diff --git a/Makefile.inc b/Makefile.inc
+index 7d9a3d3..8bee2be 100644
+--- a/Makefile.inc
++++ b/Makefile.inc
+@@ -1,6 +1,6 @@
+ DESTDIR = $(shell basename $(CURDIR))
+ INSTALL = install
+-PYTHON ?= python2
++PYTHON ?= python3
+ RCW = $(PYTHON) ../rcw.py
+ QSPI_SWAP_LIST = $(shell pwd)/../qspi_swap_list.txt
+ QSPI_SWAP_SCRIPT=$(shell pwd)/../qspi_swap.sh
+diff --git a/rcw.py b/rcw.py
+index e5cd28b..619770a 100755
+--- a/rcw.py
++++ b/rcw.py
+@@ -1,4 +1,4 @@
+-#!/usr/bin/env python2
++#!/usr/bin/env python3
+ # rcw.py -- compiles an RCW source file into an PBL/RCW binary
+@@ -95,7 +95,7 @@ from optparse import OptionParser, OptionGroup
+ class ordered_dict(dict):
+     def __init__(self, *args, **kwargs):
+         dict.__init__(self, *args, **kwargs)
+-        self._order = self.keys()
++        self._order = list(self.keys())
+     def __setitem__(self, key, value):
+         dict.__setitem__(self, key, value)
+@@ -132,7 +132,7 @@ def crc32(data):
+     crc = 0xffffffff
+     for i in data:
+-        crc = (crc << 8) ^ table[(crc >> 24) ^ ord(i)]
++        crc = (crc << 8) ^ table[(crc >> 24) ^ int(i)]
+         crc = crc & 0xffffffff
+     return crc
+@@ -187,7 +187,7 @@ def command_line():
+         options.output = '/dev/stdout'
+     if options.reverse and not options.rcwi:
+-        print "Error: -r option requires --rcw"
++        print("Error: -r option requires --rcw")
+         sys.exit(1)
+ # Checks if the bits for the given field overlap those of another field that
+@@ -196,27 +196,27 @@ def check_for_overlap(name, begin, end):
+     global symbols
+     if name in symbols:
+-        print 'Error: Duplicate bitfield definition for', name
++        print('Error: Duplicate bitfield definition for', name)
+         return
+     # Iterate over the list of symbols that have already been defined
+-    for n, [b, e] in symbols.iteritems():
++    for n, [b, e] in symbols.items():
+         # check if either 'begin' or 'end' is inside an bitfield range
+         if (b <= begin <= e) or (b <= end <= e):
+-            print 'Error: Bitfield', name, 'overlaps with', n
++            print('Error: Bitfield', name, 'overlaps with', n)
+ #
+ # Build a u-boot PBI section for SPI/SD/NAND boot
+-#     refer: Chapter 10, u-boot of QorIQ_SDK_Infocenter.pdf
++#         refer: Chapter 10, u-boot of QorIQ_SDK_Infocenter.pdf
+ #
+ # pre-cond 1: u-boot.xxd should be created
+ # how to create u-boot.xxd
+-#     xxd u-boot.bin > u-boot.xxd1 && cut -d " " -f1-10 u-boot.xxd1 > u-boot.xxd && rm -f u-boot.xxd1
++#         xxd u-boot.bin > u-boot.xxd1 && cut -d " " -f1-10 u-boot.xxd1 > u-boot.xxd && rm -f u-boot.xxd1
+ #
+ # rcw file should include spi_boot.rcw as well
+ #
+ def build_pbi_uboot(lines):
+-    subsection = ''
++    subsection = b''
+     cnt = 1
+     l_tmp = []
+@@ -224,55 +224,55 @@ def build_pbi_uboot(lines):
+     for l in lines:
+         # prepare 0x40 per lines except the last one
+         # add flush at the end 
+-      lstr = l.split()
+-      addr = int(lstr[0][:-1], 16)
++        lstr = l.split()
++        addr = int(lstr[0][:-1], 16)
+         
+         # print l
+         #
+         # last two lines take  0x20 numbers
+         #
+-      if ((cnt % 2 == 0) and (cnt > len(lines) -4)):
++        if ((cnt % 2 == 0) and (cnt > len(lines) -4)):
+             l_tmp.append(l)
+             b = []
+-          for t in l_tmp:
++            for t in l_tmp:
+                 lstr = t.split()
+-              for i in range(1, len(lstr)):
++                for i in range(1, len(lstr)):
+                     b.append(int(lstr[i], 16))
+             subsection += struct.pack('>LHHHHHHHHHHHHHHHH',\
+-              0x0C1F80000 + (addr - 0x10),\
+-              b[0],  b[1],  b[2],  b[3],  b[4],  b[5],  b[6],  b[7],\
+-              b[8],  b[9],  b[10], b[11], b[12], b[13], b[14], b[15])
++                0x0C1F80000 + (addr - 0x10),\
++                b[0],  b[1],  b[2],  b[3],  b[4],  b[5],  b[6],  b[7],\
++                b[8],  b[9],  b[10], b[11], b[12], b[13], b[14], b[15])
+             l_tmp = []
+         #
+         # the rest of lines take 0x40 numbers
+         elif (cnt % 4 == 0):
+             l_tmp.append(l)
+-          b = []
+-          for t in l_tmp:
++            b = []
++            for t in l_tmp:
+                 lstr = t.split()
+-              for i in range(1, len(lstr)):
++                for i in range(1, len(lstr)):
+                     b.append(int(lstr[i], 16))
+             subsection += struct.pack('>LHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH',\
+-              0x081F80000 + (addr - 0x30),\
+-              b[0],  b[1],  b[2],  b[3],  b[4],  b[5],  b[6],  b[7],\
+-              b[8],  b[9],  b[10], b[11], b[12], b[13], b[14], b[15],\
+-              b[16], b[17], b[18], b[19], b[20], b[21], b[22], b[23], \
+-              b[24], b[25], b[26], b[27], b[28], b[29], b[30], b[31])
++                0x081F80000 + (addr - 0x30),\
++                b[0],  b[1],  b[2],  b[3],  b[4],  b[5],  b[6],  b[7],\
++                b[8],  b[9],  b[10], b[11], b[12], b[13], b[14], b[15],\
++                b[16], b[17], b[18], b[19], b[20], b[21], b[22], b[23], \
++                b[24], b[25], b[26], b[27], b[28], b[29], b[30], b[31])
+             l_tmp = []
+         else:
+             l_tmp.append(l)
+-      cnt = cnt + 1
++        cnt = cnt + 1
+     return subsection
+ # Build a PBI section
+ def build_pbi(lines):
+-    subsection = ''
++    subsection = b''
+     global vars
+     if 'pbiformat' in vars:
+@@ -286,9 +286,9 @@ def build_pbi(lines):
+     for l in lines:
+         # Check for an instruction without 0-2 parameters
+         # The + ' ' is a hack to make the regex work for just 'flush'
+-        m = re.match(r'\s*([a-z]+)(|\.b1|\.b2|\.b4|\.short|\.long)\s*(?<=\s)([^,]*),?([^,]*),?([^,]*),?([^,]*)', l + ' ')
++        m = re.match(r'\s*([a-z]+)(|\.b1|\.b2|\.b4|\.short|\.long)\s*(?<=\s)([^,]*),?([^,]*),?([^,]*),?([^,]*)', l.decode("ascii") + ' ')
+         if not m:
+-            print 'Unknown PBI subsection command "%s"' % l
++            print('Unknown PBI subsection command "%s"' % l)
+             return ''
+         op = m.group(1)
+         opsize = m.group(2)
+@@ -306,7 +306,7 @@ def build_pbi(lines):
+         p4 = eval(p4, {"__builtins__":None}, {}) if len(p4) else None
+         if op == 'wait':
+             if p1 == None:
+-                print 'Error: "wait" instruction requires one parameter'
++                print('Error: "wait" instruction requires one parameter')
+                 return ''
+             if pbiformat == 2:
+                 v1 = struct.pack(endianess + 'L', 0x80820000 | p1)
+@@ -318,7 +318,7 @@ def build_pbi(lines):
+                 subsection += v2
+         elif op == 'write':
+             if p1 == None or p2 == None:
+-                print 'Error: "write" instruction requires two parameters'
++                print('Error: "write" instruction requires two parameters')
+                 return ''
+             if pbiformat == 2:
+                 v1 = struct.pack(endianess + 'L', (opsizebytes << 28) | p1)
+@@ -329,7 +329,7 @@ def build_pbi(lines):
+             subsection += v2
+         elif op == 'awrite':
+             if p1 == None or p2 == None:
+-                print 'Error: "awrite" instruction requires two parameters'
++                print('Error: "awrite" instruction requires two parameters')
+                 return ''
+             if pbiformat == 2:
+                 v1 = struct.pack(endianess + 'L', 0x80000000 + (opsizebytes << 26) + p1)
+@@ -340,10 +340,10 @@ def build_pbi(lines):
+             subsection += v2
+         elif op == 'poll':
+             if pbiformat != 2:
+-                print 'Error: "poll" not support for old PBI format'
++                print('Error: "poll" not support for old PBI format')
+                 return ''
+             if p1 == None or p2 == None or p3 == None:
+-                print 'Error: "poll" instruction requires three parameters'
++                print('Error: "poll" instruction requires three parameters')
+                 return ''
+             if opsize == '.long':
+                 cmd = 0x81
+@@ -357,19 +357,19 @@ def build_pbi(lines):
+             subsection += v3
+         elif op == 'loadacwindow':
+             if pbiformat != 2:
+-                print 'Error: "loadacwindow" not supported for old PBI format'
++                print('Error: "loadacwindow" not supported for old PBI format')
+                 return ''
+             if p1 == None:
+-                print 'Error: "loadacwindow" instruction requires one parameter'
++                print('Error: "loadacwindow" instruction requires one parameter')
+                 return ''
+             v1 = struct.pack(endianess + 'L', 0x80120000 + p1)
+             subsection += v1
+         elif op == 'blockcopy':
+             if pbiformat != 2:
+-                print 'Error: "blockcopy" not supported for old PBI format'
++                print('Error: "blockcopy" not supported for old PBI format')
+                 return ''
+             if p1 == None or p2 == None or p3 == None or p4 == None:
+-                print 'Error: "blockcopy" instruction requires four parameters'
++                print('Error: "blockcopy" instruction requires four parameters')
+                 return ''
+             v1 = struct.pack(endianess + 'L', 0x80000000 + (p1 & 0xff))
+             v2 = struct.pack(endianess + 'L', p2)
+@@ -382,7 +382,7 @@ def build_pbi(lines):
+         elif op == 'flush':
+             subsection += struct.pack('>LL', 0x09000000 | (int(vars['pbladdr'], 16) & 0x00ffff00), 0)
+         else:
+-            print 'Unknown PBI subsection command "%s"' % l
++            print('Unknown PBI subsection command "%s"' % l)
+             return ''
+     return subsection
+@@ -394,7 +394,7 @@ def parse_subsection(header, lines):
+     elif header == "uboot":
+         return build_pbi_uboot(lines)
+-    print 'Error: unknown subsection "%s"' % header
++    print('Error: unknown subsection "%s"' % header)
+     return ''
+ # Parse the .rcw file, one line at a time
+@@ -408,10 +408,10 @@ def parse_source_file(source):
+     symbols = ordered_dict()
+     in_subsection = False   # True == we're in a subsection
+-    pbi = ''
++    pbi = b''
+     for l2 in source:
+-        l = re.sub(r'\s+', '', l2) # Remove all whitespace
++        l = re.sub(r'\s+', '', l2.decode("ascii")) # Remove all whitespace
+         if not len(l):  # Skip blank or comment-only lines
+             continue
+@@ -466,14 +466,14 @@ def parse_source_file(source):
+             (name, value) = m.groups()
+             value = int(value, 0)
+             if not name in symbols:
+-                print 'Error: Unknown bitfield', name
++                print('Error: Unknown bitfield', name)
+             else:
+                 if options.warnings and (name in assignments):
+-                    print 'Warning: Duplicate assignment for bitfield', name
++                    print('Warning: Duplicate assignment for bitfield', name)
+                 assignments[name] = value
+             continue
+-        print 'Error: unknown command', ' '.join(l2)
++        print('Error: unknown command', ' '.join(l2))
+ # Parse the -D command line parameter for additional bitfield assignments
+ def parse_cmdline_bitfields():
+@@ -484,12 +484,12 @@ def parse_cmdline_bitfields():
+         # This is the same regex as used in parse_source_file()
+         m = re.search(r'([A-Z0-9_]+)=([0-9a-zA-Z]+)', l)
+         if not m:
+-            print 'Unrecognized command-line bitfield:', l
++            print('Unrecognized command-line bitfield:', l)
+         else:
+             (name, value) = m.groups()
+             value = int(value, 0)
+             if not name in symbols:
+-                print 'Error: Unknown bitfield', name
++                print('Error: Unknown bitfield', name)
+             else:
+                 # Don't bother printing a warning, since the command-line will
+                 # normally be used to overwrite values in the .rcw file
+@@ -510,7 +510,7 @@ def read_source_file(filename):
+     global options
+     if not find_program('gcc'):
+-        print 'Could not find gcc in PATH'
++        print('Could not find gcc in PATH')
+         return None
+     i = ['-I', '.']     # Always look in the current directory
+@@ -521,7 +521,7 @@ def read_source_file(filename):
+         shell=False, stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+     ret = p.communicate()
+     if p.returncode != 0:
+-        print ret[1],
++        print(ret[1],)
+         return None
+     return ret[0].splitlines()
+@@ -532,13 +532,13 @@ def check_vars():
+     global options
+     if not 'size' in vars:
+-        print 'Error: "%size" variable must be specified'
++        print('Error: "%size" variable must be specified')
+         sys.exit(1)
+     if options.pbl:
+         if 'pbiformat' in vars and int(vars['pbiformat'], 0) == 2:
+             if 'sysaddr' in vars:
+-                print 'Error: PBL format does not use %sysaddr'
++                print('Error: PBL format does not use %sysaddr')
+                 sys.exit(1)
+             #if 'pbladdr' in vars:
+             #    print 'Error: PBL format does not use %pbladdr'
+@@ -546,7 +546,7 @@ def check_vars():
+         else:
+             # If we want the PBL header/footer, the vars for those must be defined
+             if not 'sysaddr' in vars:
+-                print 'Error: PBL format requires %sysaddr to be defined'
++                print('Error: PBL format requires %sysaddr to be defined')
+                 sys.exit(1)
+ # Create a .bin file
+@@ -581,7 +581,7 @@ def create_binary():
+     dont64bswapcrc = 0
+     if 'dont64bswapcrc' in vars and int(vars['dont64bswapcrc'], 0):
+         dont64bswapcrc = 1
+-    bits = 0L
++    bits = 0
+     # Magic hack. If a pbi is specified and we didn't set the size,
+     # set it for the new format!
+@@ -593,7 +593,7 @@ def create_binary():
+                 pbilen += 2
+             assignments['PBI_LENGTH'] = pbilen
+             
+-    for n, v in assignments.iteritems():
++    for n, v in assignments.items():
+         # n = name of symbol
+         # v = value to assign
+         bb, ee = symbols[n]   # First bit and last bit
+@@ -603,13 +603,13 @@ def create_binary():
+         # Make sure it's not too large
+         if v >= (1 << s):
+-            print 'Error: Value', v, 'is too large for field', n
++            print('Error: Value', v, 'is too large for field', n)
+             continue
+         # If we treat the bitfield as "classic" numbered, reverse
+         # the value before adding it!
+         if b != bb:
+-            v = int(bin(v)[2:].zfill(s)[::-1], 2)
++            v = int(bin(int(v))[2:].zfill(s)[::-1], 2)
+                 
+         # Set the bits.  We assume that bits [b:e] are already zero.  They can be
+         # non-zero only if we have overlapping bitfield definitions, which we
+@@ -617,7 +617,7 @@ def create_binary():
+         bits += v << ((size - 1) - e)
+     # Generate the binary.  First, apply the preamble, if requested
+-    binary = ''
++    binary = b''
+     if options.pbl:
+         # Starting with LS2, we have a larger field and a different
+         # format.
+@@ -626,7 +626,7 @@ def create_binary():
+             # Load RCW command
+             binary += struct.pack(endianess + 'L', 0x80100000)
+         else:
+-            length_byte = (((size / 8) & 63) << 1) | 1
++            length_byte = (((size // 8) & 63) << 1) | 1
+             binary += struct.pack(endianess + 'L', (length_byte << 24) | (int(vars['sysaddr'], 16) & 0x00ffffff))
+     # Then convert 'bits' into an array of bytes
+@@ -634,7 +634,7 @@ def create_binary():
+         byte = bits >> i & 0xff
+         if classicbitnumbers:
+             byte = int(bin(byte)[2:].zfill(8)[::-1], 2)
+-        binary += chr(byte)
++        binary += bytes([byte])
+     if options.pbl:
+         if pbiformat == 2:
+@@ -672,11 +672,11 @@ def create_binary():
+             # Precise bit any byte ordering of the CRC calculation is
+             # not clearly specified. This is empirical.
+             if classicbitnumbers:
+-                    newcrcbinary = ''
++                    newcrcbinary = b''
+                     for c in crcbinary:
+-                        byte = ord(c)
++                        byte = int(c)
+                         byte = int(bin(byte)[2:].zfill(8)[::-1], 2)
+-                        newcrcbinary += chr(byte)
++                        newcrcbinary += bytes([byte])
+                     crcbinary = newcrcbinary
+             # Calculate and add the CRC
+@@ -693,7 +693,7 @@ def create_binary():
+         l = len(binary)
+         if dont64bswapcrc and options.pbl:
+             l -= 8
+-        newbinary = ''
++        newbinary = b''
+         for i in range(0, l, 8):
+                 x64 = struct.unpack('>Q', binary[i:i + 8])[0]
+                 newbinary += struct.pack('<Q', x64)
+@@ -771,7 +771,7 @@ def create_source():
+                 # We skip the checksum field
+                 pbi = binary[8 + (size / 8) + 4:]
+             else:
+-                print 'Weird binary RCW format!'
++                print('Weird binary RCW format!')
+                 bitbytes = ''
+         else:
+             if binary[0:4] == preambletst:
+@@ -780,7 +780,7 @@ def create_source():
+                 bitbytes = rcw
+                 pbi = binary[8 + (size / 8):]
+             else:
+-                print 'Weird binary RCW format!'
++                print('Weird binary RCW format!')
+                 bitbytes = ''
+     else:
+         bitbytes = binary
+@@ -827,16 +827,16 @@ def create_source():
+             bits &= ~(mask << shift)
+     if bits:
+-        print 'Unknown bits in positions:',
++        print('Unknown bits in positions:',)
+         mask = 1
+         n = 0
+         while bits:
+             if (bits & mask):
+-                print n,
++                print(n,)
+             n += 1
+             bits &= ~mask
+             mask <<= 1
+-        print
++        print()
+     if len(pbi) > 0:
+         l = len(pbi)
+@@ -953,7 +953,7 @@ def create_source():
+                     if cnt == 0:
+                         cnt = 64
+                     if i + cnt >= l:
+-                        print 'Error in write 0x%08x at offset %d within PBI\n' % (word, i)
++                        print('Error in write 0x%08x at offset %d within PBI\n' % (word, i))
+                     if (addr & 0x00ffff00 == pbladdr):
+                         arg1 = struct.unpack(endianess + 'L', pbi[i:i+4])[0]
+                         i += 4
+@@ -986,8 +986,8 @@ def create_source():
+     return source
+-if (sys.version_info < (2,6)) or (sys.version_info >= (3,0)):
+-    print 'Only Python versions 2.6 or 2.7 are supported.'
++if (sys.version_info < (3,0)):
++    print('Only Python versions 3.0+ are supported.')
+     sys.exit(1)
+ # Make all 'print' statements output to stderr instead of stdout
+-- 
+2.7.4
+