diff options
Diffstat (limited to 'package')
3 files changed, 548 insertions, 82 deletions
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 index 0000000000..2ea260bfd4 --- /dev/null +++ b/package/firmware/layerscape/ls-rcw/patches/0001-Disable-byte-swapping.patch @@ -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 index 08492dd479..0000000000 --- a/package/firmware/layerscape/ls-rcw/patches/0001-rcw-support-byte-swapping-without-tclsh-tool.patch +++ /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 index 0000000000..8aa629dd85 --- /dev/null +++ b/package/firmware/layerscape/ls-rcw/patches/0002-Convert-to-python3.patch @@ -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 + |