Error - Takes 1 positional argument but 2 were given - python

I'm getting an error message saying 'Traceback (most recent call last): File "C:\Users\SUL-I\fatest2.py", line 42, in leftsensor = fa.ReadLine(0) File "C:\Users\SUL-I\FA.py", line 180, in ReadLine self._flush(self) TypeError: _flush() takes 1 positional argument but 2 were given' when I run a bit of Python code I've written.
Here is the code:
#brings in external references
import FA
import time
#defines some constants
black = 0
white = 200
correction = 10
w = 0
#controls the first robot, remember to update the com port number
fa = FA.Create()
comport = 7
fa.ComOpen(comport)
time.sleep(5)
fa.PlayNote(294,800)
fa.PlayNote(330,800)
fa.PlayNote(262,800)
fa.LEDWrite(24)
time.sleep(0.25)
fa.LEDWrite(60)
time.sleep(0.25)
fa.LEDWrite(36)
time.sleep(0.25)
fa.LEDWrite(102)
time.sleep(0.25)
fa.LEDWrite(66)
time.sleep(0.25)
fa.LEDWrite(195)
time.sleep(0.25)
fa.LEDWrite(129)
time.sleep(0.25)
fa.LEDWrite(195)
time.sleep(0.25)
fa.LEDWrite(66)
time.sleep(0.25)
fa.LEDWrite(102)
time.sleep(0.25)
fa.LEDWrite(36)
time.sleep(0.25)
fa.LEDWrite(60)
leftsensor = fa.ReadLine(0)
rightsensor = fa.ReadLine(1)
while w < 100:
if leftsensor >= white:
fa.SetMotors(20,10)
elif rightsensor >= white:
fa.SetMotors(10,20)
else:
fa.Forwards(10)
w = w+1
ComClose(comport)
Here is ReadLine in the FA module:
def ReadLine(self, index):
"""Read the line sensor value
Args:
index: Line sensor to query (0 to 1)
Returns:
int: Value of Line sensor (0 to 4095)
"""
self._flush(self)
s = 'ReadLine {0}\n'.format(int(index))
self.__ser.write(s.encode())
r = self._readval("ReadLine", 1, 1)
return(r);
definition of readval:
def _readval(self, cmd, loop_max):
r = -1
loop = 0
while (loop < loop_max):
try:
r = int(self.__ser.readline().rstrip())
if (self.__verbose != 0):
msg = '{0}: {1}'.format(cmd, r)
print(msg)
loop = loop_max + 1 #break out of loop
except ValueError:
if (self.__verbose != 0):
msg = '{0}: No return({1})'.format(cmd,loop)
print(msg)
loop = loop + 1
return(r);

Having resolved the error involving _flush_, your second error occurs for similar reasons.
Compare the definition of _readval:
def _readval(self, cmd, loop_max):
to your call:
r = self._readval("ReadLine", 1, 1)
"Readline" is assigned to cmd, and the first 1 is assigned to loop_max. There are no parameter left for the second 1 to be assigned to, so you get the observed error.

Related

AttributeError, What am I doing wrong here?

I have a program that I cannot call to run, where I try to call the linearSearch() def from spellCheck.py. Can someone help me understand why my code gives me a AttributeError? I do not understand why when calling initial.linearSearch(choice) won't give me anything.
spellCheck.py:
class SpellCheck():
def __init__(self):
try:
open("dictionary.txt", "r")
except FileNotFoundError:
print("Dictionary file not found")
else:
#store all elements in a list
dictionary = []
#open dictionary.txt
with open("dictionary.txt", "r") as f:
for line in f:
dictionary.append(line.strip())
def binarySearch(self, word):
steps = 0
low = 0
high = len(dictionary) - 1
while low <= high:
middle = (low + high) // 2
if(dictionary[middle] == word):
steps += 1
return (f"{bcolors.OKGREEN}Found {bcolors.BOLD}{word}{bcolors.ENDC}{bcolors.OKGREEN} after {steps} steps!{bcolors.ENDC}")
elif (dictionary[middle] < word):
steps += 1
low = middle + 1
else:
steps += 1
high = middle - 1
return(f"{bcolors.FAIL}The word {bcolors.BOLD}{word}{bcolors.ENDC}{bcolors.FAIL} wasn't found!{bcolors.ENDC}")
def linearSearch(word):
steps = 0
for i in range(len(dictionary)):
steps += 1
if dictionary[i] == self.word:
steps += 1
return(f"{bcolors.OKGREEN}Found {bcolors.BOLD}{self.word}{bcolors.ENDC}{bcolors.OKGREEN} after {steps - 1} steps!{bcolors.ENDC}")
return(f"{bcolors.FAIL}The word {bcolors.BOLD}{self.word}{bcolors.ENDC}{bcolors.FAIL} wasn't found!{bcolors.ENDC}")
#color coding for terminal
#source: https://stackoverflow.com/a/287944
#either True or False
class bcolors:
BOLD = '\033[1m'
OKGREEN = '\033[92m'
FAIL = '\033[91m'
ENDC = '\033[0m'
YELLOW = '\033[93m'
#debug statement
#if debug == True:
#print(f"Debug Colors:\n{BOLD}BOLD{ENDC}\n{OKGREEN}OKGREEN{ENDC}\n{FAIL}FAIL{ENDC}\n{YELLOW}YELLOW{ENDC}")
#end of color codes
main.py
from spellCheck import SpellCheck
#from spellCheck import bcolors
def main():
choice = input("Enter the word to look for:\n> ")
initial = SpellCheck()
initial.__init__()
initial.linearSearch(choice)
main()
Here is the output of the terminal:
Enter the word to look for:
> apple
Traceback (most recent call last):
File "main.py", line 11, in <module>
main()
File "main.py", line 8, in main
initial.linearSearch(choice)
AttributeError: 'SpellCheck' object has no attribute 'linearSearch'
binarySearch(self, word) and linearSearch(word) are the functions of __init__
that's why you are not getting any error on initial.linearSearch(choice).
If you want them to be separate functions of SpellCheck() then unindent them.

Cannot unpack noniterable bool object

I'm new to Python and posting on SO.
I'm doing a class project on trying to create an automated climate control system with a Raspberry pi(Pi4 4GB) and a DHT.
Here is my current error and code and I'm not sure what's causing the fail in the loop. It works for a while then errors out. It seems to error when it gets a bad read from the sensor, but until then it works fine.
Traceback (most recent call last):
File "/home/pi/raphael-kit/python/Climatecontrol.py", line 156, in <module>
main()
File "/home/pi/raphael-kit/python/Climatecontrol.py", line 118, in main
humidity, temperature = readDht11()
TypeError: cannot unpack non-iterable bool object
import RPi.GPIO as GPIO
import time
import LCD1602
dhtPin = 17
relayPin = 23 # Set GPIO23 as control pin
set_temp = 25 # this is the required temperature
GPIO.setmode(GPIO.BCM)
# Set relayPin's mode to output,
# and initial level to High(3.3v)
GPIO.setup(relayPin, GPIO.OUT, initial=GPIO.HIGH)
MAX_UNCHANGE_COUNT = 100
STATE_INIT_PULL_DOWN = 1
STATE_INIT_PULL_UP = 2
STATE_DATA_FIRST_PULL_DOWN = 3
STATE_DATA_PULL_UP = 4
STATE_DATA_PULL_DOWN = 5
def readDht11():
GPIO.setup(dhtPin, GPIO.OUT)
GPIO.output(dhtPin, GPIO.HIGH)
time.sleep(0.05)
GPIO.output(dhtPin, GPIO.LOW)
time.sleep(0.02)
GPIO.setup(dhtPin, GPIO.IN, GPIO.PUD_UP)
unchanged_count = 0
last = -1
data = []
while True:
current = GPIO.input(dhtPin)
data.append(current)
if last != current:
unchanged_count = 0
last = current
else:
unchanged_count += 1
if unchanged_count > MAX_UNCHANGE_COUNT:
break
state = STATE_INIT_PULL_DOWN
lengths = []
current_length = 0
for current in data:
current_length += 1
if state == STATE_INIT_PULL_DOWN:
if current == GPIO.LOW:
state = STATE_INIT_PULL_UP
else:
continue
if state == STATE_INIT_PULL_UP:
if current == GPIO.HIGH:
state = STATE_DATA_FIRST_PULL_DOWN
else:
continue
if state == STATE_DATA_FIRST_PULL_DOWN:
if current == GPIO.LOW:
state = STATE_DATA_PULL_UP
else:
continue
if state == STATE_DATA_PULL_UP:
if current == GPIO.HIGH:
current_length = 0
state = STATE_DATA_PULL_DOWN
else:
continue
if state == STATE_DATA_PULL_DOWN:
if current == GPIO.LOW:
lengths.append(current_length)
state = STATE_DATA_PULL_UP
else:
continue
if len(lengths) != 40:
#print ("Data not good, skip")
return False
shortest_pull_up = min(lengths)
longest_pull_up = max(lengths)
halfway = (longest_pull_up + shortest_pull_up) / 2
bits = []
the_bytes = []
byte = 0
for length in lengths:
bit = 0
if length > halfway:
bit = 1
bits.append(bit)
#print ("bits: %s, length: %d" % (bits, len(bits)))
for i in range(0, len(bits)):
byte = byte << 1
if (bits[i]):
byte = byte | 1
else:
byte = byte | 0
if ((i + 1) % 8 == 0):
the_bytes.append(byte)
byte = 0
#print (the_bytes)
checksum = (the_bytes[0] + the_bytes[1] + the_bytes[2] + the_bytes[3]) & 0xFF
#if the_bytes[4] != checksum:
#print ("Data not good, skip")
#return False
return the_bytes[0], the_bytes[2]
def main():
while True:
humidity, temperature = readDht11()
if humidity is not None and temperature is not None:
print("Temp={0:0.1f}*C Humidity={1:0.1f}%".format(temperature, humidity))
# test for low temperature
if temperature < set_temp:
print(GPIO.output(relayPin, GPIO.LOW))
# test for high temperature
if temperature > (set_temp + 1):
print(GPIO.output(relayPin, GPIO.HIGH))
else:
print("Failed to retrieve data from humidity sensor")
time.sleep(5) #this is the time between taking readings and acting on them you can reduce it but not below 5 seconds
# Define a destroy function for clean up everything after
# the script finished
def setup():
LCD1602.init(0x27, 1) # init(slave address, background light)
LCD1602.write(0, 0, 'Temperature: %s C')
LCD1602.write(1, 1, 'humidity: %s %%')
time.sleep(2)
def destroy():
# set relay to off
GPIO.output(relayPin, GPIO.LOW)
# Release resource
GPIO.cleanup()
if __name__ == '__main__':
try:
setup()
except KeyboardInterrupt:
destroy()
as a note I haven't managed to get the LCD working in tandem but im more worried about the main functionality

IndexError: index -1 is out of bounds for axis 0 with size 0

I get an index -1 is out of bounds for axis 0 with size 0 error from scipy when trying to implement a text generator with ngrams.
Traceback (most recent call last):
File "C:\Users\hp\PycharmProjects\N-gram poems\trigram_model.py", line 125, in <module>
generate()
File "C:\Users\hp\PycharmProjects\N-gram poems\trigram_model.py", line 118, in generate
singleverse(int(c))
File "C:\Users\hp\PycharmProjects\N-gram poems\trigram_model.py", line 80, in singleverse
result = stats.multinomial.rvs(1, word_probabilities)
File "C:\Users\hp\PycharmProjects\N-gram poems\venv\lib\site-packages\scipy\stats\_multivariate.py", line 3242, in rvs
n, p, npcond = self._process_parameters(n, p)
File "C:\Users\hp\PycharmProjects\N-gram poems\venv\lib\site-packages\scipy\stats\_multivariate.py", line 3036, in _process_parameters
p[..., -1] = 1. - p[..., :-1].sum(axis=-1)
IndexError: index -1 is out of bounds for axis 0 with size 0
It's in a for loop and when the error occurs changes each time. Some times it does not occur at all. It mostly occur close to the end of the program.
This is the code where the error occurs:
def singleverse(num):
TrTrigrams = [((filtered_tokens[i], filtered_tokens[i + 1]), filtered_tokens[i + 2]) for i in
range(len(filtered_tokens) - 2)]
TrTrigramCFD = nltk.ConditionalFreqDist(TrTrigrams)
TrTrigramPbs = nltk.ConditionalProbDist(TrTrigramCFD, nltk.MLEProbDist)
rand = random.choice(random_choice_list)
start_word = ('<s>', rand)
data = []
for i in range(10):
probable_words = list(TrTrigramPbs[start_word].samples())
word_probabilities = [TrTrigramPbs[start_word].prob(word) for word in probable_words]
result = stats.multinomial.rvs(1, word_probabilities)
index_of_probable_word = list(result).index(1)
start_word = (start_word[1], (probable_words[index_of_probable_word]))
data.append(start_word[1])
line = []
for i in data:
if i != "<s>" and i != "</s>":
line.append(i)
poem_line = ' '.join([str(i) for i in line]).capitalize()
print(poem_line)
def generate():
"""Generates the final poem with user input of structure."""
print("What structure do you want?(e.g., 3 x 4, 2 x 4, 2 x 5): ")
while True:
try:
x, y, z = input().split()
except:
print("Enter the structure as shown above.")
continue
break
while True:
try:
for stanza in range(1):
for first_verse in range(1):
b = random.randint(7, 12)
firstverse(int(b))
for verse in range(int(z) - 1):
a = random.randint(7, 12)
singleverse(int(a))
print('\n')
for stanza in range(int(x) - 1):
for verse in range(int(z)):
c = random.randint(7, 12)
singleverse(int(c))
print('\n')
except KeyError:
print("This was not a valid seed word please try again.")
continue
break
generate()

bluepy.btle.BTLEManagementError: Failed to execute management command 'le on' (code: 20, error: Permission Denied)

I utilised and modified the code that is shown below, from https://www.instructables.com/Monitor-and-Record-Temperature-With-Bluetooth-LE-a/
The problem I run into is that the device seems to be blocking me from accessing it's values, although I am unsure of this.
Here is my code:
from bluepy.btle import Scanner, DefaultDelegate
import time
import struct
SENSOR_ADDRESS = [""ec:fe:4e:12:b8:72""]
class DecodeErrorException(Exception):
def __init__(self, value):
self.value = value
def __str__(self):
return repr(self.value)
class ScanDelegate(DefaultDelegate):
def __init__(self):
DefaultDelegate.__init__(self)
def handleDiscovery(self, dev, isNewDev, isNewData):
if isNewDev:
print("Discovered device", dev.addr)
elif isNewData:
print("Received new data from", dev.addr)
scanner = Scanner().withDelegate(ScanDelegate())
ManuDataHex = []
ReadLoop = True
try:
while (ReadLoop):
devices = scanner.scan(2.0)
ManuData = ""
for dev in devices:
entry = 0
TempData = 0
for saddr in SENSOR_ADDRESS:
entry += 1
if (dev.addr == saddr):
CurrentDevAddr = saddr
for (adtype, desc, value) in dev.getScanData():
if (desc == "Manufacturer"):
ManuData = value
if (ManuData == ""):
print("No data received, end decoding")
continue
print(ManuData)
for i, j in zip(ManuData[::2], ManuData[1::2]):
ManuDataHex.append(int(i+j, 16))
if ((ManuDataHex[0] == 0x85) and (ManuDataHex[1] == 0x00)):
print("Header byte 0x0085 found")
else:
print("Header byte 0x0085 not found, decoding stop")
continue
idx = 7
print("TotalLen: " + str(len(ManuDataHex)))
while idx < len(ManuDataHex):
if (ManuDataHex[idx] == 0x43):
idx += 1
TempData = ManuDataHex[idx]
TempData += ManuDataHex[idx+1] * 0x100
TempData = TempData * 0.0625
idx += 2
else:
idx += 1
print("Device Address: " + CurrentDevAddr)
print("Temp Data: " + str(TempData))
ReadLoop = False
except DecodeErrorException:
pass
The exception is as follows:
Traceback (most recent call last):
File "/home/pi/Desktop/lameteo/print.py", line 31, in
devices = scanner.scan(2.0)
File "/usr/local/lib/python3.7/dist-packages/bluepy/btle.py", line 852, in scan
self.start(passive=passive)
File "/usr/local/lib/python3.7/dist-packages/bluepy/btle.py", line 790, in start
self._mgmtCmd("le on")
File "/usr/local/lib/python3.7/dist-packages/bluepy/btle.py", line 312, in _mgmtCmd
raise BTLEManagementError("Failed to execute management command '%s'" % (cmd), rsp)
bluepy.btle.BTLEManagementError: Failed to execute management command 'le on' (code: 20, error: > Permission Denied)
If you have any expertise in this area I would greatly appreciate your help.
use sudo infront when you call the script in your terminal

A problem with compatibility of the script on Windows

This script works perfectly on Mac OS and Linux but when I try it on Windows it does not work.
When I try to try it on Windows, this error appears...
I imagine the problem from switch_user(dev).
I tried it with her (dev) but I couldn't solve it.
Whereas when Check GPT is verified, it stops and the error occurs.
PS C:\Users\motc-pc\Desktop\amonet-karnak-\amonet\modules> python main.py
[2020-06-03 22:03:49.653199] Waiting for bootrom
[2020-06-03 22:03:59.339064] Found port = COM22
[2020-06-03 22:03:59.348800] Handshake
* * * If you have a short attached, remove it now * * *
* * * Press Enter to continue * * *
[2020-06-03 22:04:02.368897] Init crypto engine
[2020-06-03 22:04:02.422396] Disable caches
[2020-06-03 22:04:02.424535] Disable bootrom range checks
[2020-06-03 22:04:02.459386] Load payload from ../brom-payload/build/payload.bin = 0x4888 bytes
[2020-06-03 22:04:02.469524] Send payload
[2020-06-03 22:04:03.440416] Let's rock
[2020-06-03 22:04:03.442368] Wait for the payload to come online...
[2020-06-03 22:04:04.163004] all good
[2020-06-03 22:04:04.165239] Check GPT
Traceback (most recent call last):
File "main.py", line 450, in <module>
main()
File "main.py", line 361, in main
switch_user(dev)
File "main.py", line 321, in switch_user
block = dev.emmc_read(0)
File "main.py", line 196, in emmc_read
raise RuntimeError("read fail")
RuntimeError: read fail
This script is full.
As I said earlier when I trying it on Linux or MacOS it works normally without problems
import struct
import os
import sys
import time
from handshake import handshake
from load_payload import load_payload, UserInputThread
from logger import log
import struct
import glob
import serial
from logger import log
BAUD = 115200
TIMEOUT = 5
CRYPTO_BASE = 0x10210000 # for karnak
def serial_ports ():
""" Lists available serial ports
:raises EnvironmentError:
On unsupported or unknown platforms
:returns:
A set containing the serial ports available on the system
"""
if sys.platform.startswith("win"):
ports = [ "COM{0:d}".format(i + 1) for i in range(256) ]
elif sys.platform.startswith("linux"):
ports = glob.glob("/dev/ttyACM*")
elif sys.platform.startswith("darwin"):
ports = glob.glob("/dev/cu.usbmodem*")
else:
raise EnvironmentError("Unsupported platform")
result = set()
for port in ports:
try:
s = serial.Serial(port, timeout=TIMEOUT)
s.close()
result.add(port)
except (OSError, serial.SerialException):
pass
return result
def p32_be(x):
return struct.pack(">I", x)
class Device:
def __init__(self, port=None):
self.dev = None
if port:
self.dev = serial.Serial(port, BAUD, timeout=TIMEOUT)
def find_device(self,preloader=False):
if self.dev:
raise RuntimeError("Device already found")
if preloader:
log("Waiting for preloader")
else:
log("Waiting for bootrom")
old = serial_ports()
while True:
new = serial_ports()
# port added
if new > old:
port = (new - old).pop()
break
# port removed
elif old > new:
old = new
time.sleep(0.25)
log("Found port = {}".format(port))
self.dev = serial.Serial(port, BAUD, timeout=TIMEOUT)
def check(self, test, gold):
if test != gold:
raise RuntimeError("ERROR: Serial protocol mismatch")
def check_int(self, test, gold):
test = struct.unpack('>I', test)[0]
self.check(test, gold)
def _writeb(self, out_str):
self.dev.write(out_str)
return self.dev.read()
def handshake(self):
# look for start byte
while True:
c = self._writeb(b'\xa0')
if c == b'\x5f':
break
self.dev.flushInput()
# complete sequence
self.check(self._writeb(b'\x0a'), b'\xf5')
self.check(self._writeb(b'\x50'), b'\xaf')
self.check(self._writeb(b'\x05'), b'\xfa')
def handshake2(self, cmd='FACTFACT'):
# look for start byte
c = 0
while c != b'Y':
c = self.dev.read()
log("Preloader ready, sending " + cmd)
command = str.encode(cmd)
self.dev.write(command)
self.dev.flushInput()
def read32(self, addr, size=1):
result = []
self.dev.write(b'\xd1')
self.check(self.dev.read(1), b'\xd1') # echo cmd
self.dev.write(struct.pack('>I', addr))
self.check_int(self.dev.read(4), addr) # echo addr
self.dev.write(struct.pack('>I', size))
self.check_int(self.dev.read(4), size) # echo size
self.check(self.dev.read(2), b'\x00\x00') # arg check
for _ in range(size):
data = struct.unpack('>I', self.dev.read(4))[0]
result.append(data)
self.check(self.dev.read(2), b'\x00\x00') # status
# support scalar
if len(result) == 1:
return result[0]
else:
return result
def write32(self, addr, words, status_check=True):
# support scalar
if not isinstance(words, list):
words = [ words ]
self.dev.write(b'\xd4')
self.check(self.dev.read(1), b'\xd4') # echo cmd
self.dev.write(struct.pack('>I', addr))
self.check_int(self.dev.read(4), addr) # echo addr
self.dev.write(struct.pack('>I', len(words)))
self.check_int(self.dev.read(4), len(words)) # echo size
self.check(self.dev.read(2), b'\x00\x01') # arg check
for word in words:
self.dev.write(struct.pack('>I', word))
self.check_int(self.dev.read(4), word) # echo word
if status_check:
self.check(self.dev.read(2), b'\x00\x01') # status
def run_ext_cmd(self, cmd):
self.dev.write(b'\xC8')
self.check(self.dev.read(1), b'\xC8') # echo cmd
cmd = bytes([cmd])
self.dev.write(cmd)
self.check(self.dev.read(1), cmd)
self.dev.read(1)
self.dev.read(2)
def wait_payload(self):
data = self.dev.read(4)
if data != b"\xB1\xB2\xB3\xB4":
raise RuntimeError("received {} instead of expected pattern".format(data))
def emmc_read(self, idx):
# magic
self.dev.write(p32_be(0xf00dd00d))
# cmd
self.dev.write(p32_be(0x1000))
# block to read
self.dev.write(p32_be(idx))
data = self.dev.read(0x200)
if len(data) != 0x200:
raise RuntimeError("read fail")
return data
def emmc_write(self, idx, data):
if len(data) != 0x200:
raise RuntimeError("data must be 0x200 bytes")
# magic
self.dev.write(p32_be(0xf00dd00d))
# cmd
self.dev.write(p32_be(0x1001))
# block to write
self.dev.write(p32_be(idx))
# data
self.dev.write(data)
code = self.dev.read(4)
if code != b"\xd0\xd0\xd0\xd0":
raise RuntimeError("device failure")
def emmc_switch(self, part):
# magic
self.dev.write(p32_be(0xf00dd00d))
# cmd
self.dev.write(p32_be(0x1002))
# partition
self.dev.write(p32_be(part))
def reboot(self):
# magic
self.dev.write(p32_be(0xf00dd00d))
# cmd
self.dev.write(p32_be(0x3000))
def kick_watchdog(self):
# magic
self.dev.write(p32_be(0xf00dd00d))
# cmd
self.dev.write(p32_be(0x3001))
def rpmb_read(self):
# magic
self.dev.write(p32_be(0xf00dd00d))
# cmd
self.dev.write(p32_be(0x2000))
data = self.dev.read(0x100)
if len(data) != 0x100:
raise RuntimeError("read fail")
return data
def rpmb_write(self, data):
if len(data) != 0x100:
raise RuntimeError("data must be 0x100 bytes")
# magic
self.dev.write(p32_be(0xf00dd00d))
# cmd
self.dev.write(p32_be(0x2001))
# data
self.dev.write(data)
def switch_boot0(dev):
dev.emmc_switch(1)
block = dev.emmc_read(0)
if block[0:9] != b"EMMC_BOOT" and block != b"\x00" * 0x200:
dev.reboot()
raise RuntimeError("what's wrong with your BOOT0?")
dev.kick_watchdog()
def flash_data(dev, data, start_block, max_size=0):
while len(data) % 0x200 != 0:
data += b"\x00"
if max_size and len(data) > max_size:
raise RuntimeError("data too big to flash")
blocks = len(data) // 0x200
for x in range(blocks):
print("[{} / {}]".format(x + 1, blocks), end='\r')
dev.emmc_write(start_block + x, data[x * 0x200:(x + 1) * 0x200])
if x % 10 == 0:
dev.kick_watchdog()
print("")
def flash_binary(dev, path, start_block, max_size=0):
with open(path, "rb") as fin:
data = fin.read()
while len(data) % 0x200 != 0:
data += b"\x00"
flash_data(dev, data, start_block, max_size=0)
def dump_binary(dev, path, start_block, max_size=0):
with open(path, "w+b") as fout:
blocks = max_size // 0x200
for x in range(blocks):
print("[{} / {}]".format(x + 1, blocks), end='\r')
fout.write(dev.emmc_read(start_block + x))
if x % 10 == 0:
dev.kick_watchdog()
print("")
def force_fastboot(dev, gpt):
switch_user(dev)
block = list(dev.emmc_read(gpt["MISC"][0]))
block[0:16] = "FASTBOOT_PLEASE\x00".encode("utf-8")
dev.emmc_write(gpt["MISC"][0], bytes(block))
block = dev.emmc_read(gpt["MISC"][0])
def force_recovery(dev, gpt):
switch_user(dev)
block = list(dev.emmc_read(gpt["MISC"][0]))
block[0:16] = "boot-recovery\x00\x00\x00".encode("utf-8")
dev.emmc_write(gpt["MISC"][0], bytes(block))
block = dev.emmc_read(gpt["MISC"][0])
def switch_user(dev):
dev.emmc_switch(0)
block = dev.emmc_read(0)
dev.kick_watchdog()
def parse_gpt(dev):
data = dev.emmc_read(0x400 // 0x200) + dev.emmc_read(0x600 // 0x200) + dev.emmc_read(0x800 // 0x200) + dev.emmc_read(0xA00 // 0x200)
num = len(data) // 0x80
parts = dict()
for x in range(num):
part = data[x * 0x80:(x + 1) * 0x80]
part_name = part[0x38:].decode("utf-16le").rstrip("\x00")
part_start = struct.unpack("<Q", part[0x20:0x28])[0]
part_end = struct.unpack("<Q", part[0x28:0x30])[0]
parts[part_name] = (part_start, part_end - part_start + 1)
return parts
def main():
minimal = False
dev = Device()
dev.find_device()
# 0.1) Handshake
handshake(dev)
# 0.2) Load brom payload
load_payload(dev, "../brom-payload/build/payload.bin")
dev.kick_watchdog()
if len(sys.argv) == 2 and sys.argv[1] == "minimal":
thread = UserInputThread(msg = "Running in minimal mode, assuming LK, TZ, LK-payload and TWRP to have already been flashed.\nIf this is correct (i.e. you used \"brick\" option in step 1) press enter, otherwise terminate with Ctrl+C")
thread.start()
while not thread.done:
dev.kick_watchdog()
time.sleep(1)
minimal = True
# 1) Sanity check GPT
log("Check GPT")
switch_user(dev)
# 1.1) Parse gpt
gpt = parse_gpt(dev)
log("gpt_parsed = {}".format(gpt))
if "lk" not in gpt or "tee1" not in gpt or "boot" not in gpt or "recovery" not in gpt:
raise RuntimeError("bad gpt")
# 2) Sanity check boot0
log("Check boot0")
switch_boot0(dev)
# 3) Sanity check rpmb
log("Check rpmb")
rpmb = dev.rpmb_read()
if rpmb[0:4] != b"AMZN":
thread = UserInputThread(msg = "rpmb looks broken; if this is expected (i.e. you're retrying the exploit) press enter, otherwise terminate with Ctrl+C")
thread.start()
while not thread.done:
dev.kick_watchdog()
time.sleep(1)
# Clear preloader so, we get into bootrom without shorting, should the script stall (we flash preloader as last step)
# 4) Downgrade preloader
log("Clear preloader header")
switch_boot0(dev)
flash_data(dev, b"EMMC_BOOT" + b"\x00" * ((0x200 * 8) - 9), 0)
# 5) Zero out rpmb to enable downgrade
log("Downgrade rpmb")
dev.rpmb_write(b"\x00" * 0x100)
log("Recheck rpmb")
rpmb = dev.rpmb_read()
if rpmb != b"\x00" * 0x100:
dev.reboot()
raise RuntimeError("downgrade failure, giving up")
log("rpmb downgrade ok")
dev.kick_watchdog()
if not minimal:
# 6) Install preloader
log("Flash preloader")
switch_boot0(dev)
flash_binary(dev, "../bin/preloader.bin", 8)
flash_binary(dev, "../bin/preloader.bin", 520)
# 6) Install lk-payload
log("Flash lk-payload")
switch_boot0(dev)
flash_binary(dev, "../lk-payload/build/payload.bin", 1024)
# 7) Downgrade tz
log("Flash tz")
switch_user(dev)
flash_binary(dev, "../bin/tz.img", gpt["tee1"][0], gpt["tee1"][1] * 0x200)
# 8) Downgrade lk
log("Flash lk")
switch_user(dev)
flash_binary(dev, "../bin/lk.bin", gpt["lk"][0], gpt["lk"][1] * 0x200)
# 9) Flash microloader
log("Inject microloader")
switch_user(dev)
boot_hdr1 = dev.emmc_read(gpt["boot"][0]) + dev.emmc_read(gpt["boot"][0] + 1)
boot_hdr2 = dev.emmc_read(gpt["boot"][0] + 2) + dev.emmc_read(gpt["boot"][0] + 3)
flash_binary(dev, "../bin/microloader.bin", gpt["boot"][0], 2 * 0x200)
if boot_hdr2[0:8] != b"ANDROID!":
flash_data(dev, boot_hdr1, gpt["boot"][0] + 2, 2 * 0x200)
if not minimal:
log("Force fastboot")
force_fastboot(dev, gpt)
else:
log("Force recovery")
force_recovery(dev, gpt)
# 10) Downgrade preloader
log("Flash preloader header")
switch_boot0(dev)
flash_binary(dev, "../bin/preloader.hdr0", 0, 4)
flash_binary(dev, "../bin/preloader.hdr1", 4, 4)
# Reboot (to fastboot or recovery)
log("Reboot")
dev.reboot()
if __name__ == "__main__":
main()

Categories

Resources