Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Restart dumping a partition #60

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions lglaf.lua
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ function lglaf.dissector(tvb, pinfo, tree)
local endpoint = usb_endpoint().value

-- Process only bulk packets from (EP 5) and to the device (EP 3)
if not ((endpoint == 0x85 or endpoint == 3) and transfer_type == 3) then
return 0
end
-- if not ((endpoint == 0x85 or endpoint == 3) and transfer_type == 3) then
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would say this should be a separate PR as it is not related to the topic right?!

-- return 0
-- end

pinfo.cols.protocol = lglaf.name

Expand Down
2 changes: 1 addition & 1 deletion lglaf.py
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ def close(self):
class USBCommunication(Communication):
VENDOR_ID_LG = 0x1004
# Read timeout. Set to 0 to disable timeouts
READ_TIMEOUT_MS = 60000
READ_TIMEOUT_MS = 6000
def __init__(self):
super(USBCommunication, self).__init__()
# Match device using heuristics on the interface/endpoint descriptors,
Expand Down
76 changes: 62 additions & 14 deletions partitions.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@
from __future__ import print_function
from collections import OrderedDict
from contextlib import closing, contextmanager
import argparse, logging, os, io, struct, sys
import argparse, logging, os, io, struct, sys, time
import lglaf
import gpt
import usb.core, usb.util

_logger = logging.getLogger("partitions")

Expand All @@ -37,7 +38,7 @@ def get_partitions(comm, fd_num):
table_data = b''
while read_offset < end_offset:
chunksize = min(end_offset - read_offset, BLOCK_SIZE * MAX_BLOCK_SIZE)
data = laf_read(comm, fd_num, read_offset // BLOCK_SIZE, chunksize)
data, fd_num = laf_read(comm, fd_num, read_offset // BLOCK_SIZE, chunksize)
table_data += data
read_offset += chunksize

Expand Down Expand Up @@ -67,11 +68,46 @@ def laf_open_disk(comm):
def laf_read(comm, fd_num, offset, size):
"""Read size bytes at the given block offset."""
read_cmd = lglaf.make_request(b'READ', args=[fd_num, offset, size])
header, response = comm.call(read_cmd)
for attempt in range(3):
try:
header, response = comm.call(read_cmd)
break
except usb.core.USBError as e:
if attempt == 2:
raise # last attempt
if e.strerror == 'Overflow':
_logger.debug("Overflow on READ %d %d %d", fd_num, offset, size)
for attempt in range(3):
try:
comm.reset()
comm._read(-1) # clear line
break
except usb.core.USBError:
pass
continue
elif e.strerror == 'Operation timed out':
_logger.debug("Timeout on READ %d %d %d", fd_num, offset, size)
comm.close()
time.sleep(3)
comm.__init__()
try:
lglaf.try_hello(comm)
except usb.core.USBError:
pass
close_cmd = lglaf.make_request(b'CLSE', args=[fd_num])
comm.call(close_cmd)
open_cmd = lglaf.make_request(b'OPEN', body=b'\0')
open_header = comm.call(open_cmd)[0]
fd_num = read_uint32(open_header, 4)
read_cmd = lglaf.make_request(b'READ', args=[fd_num, offset, size])
continue
else:
raise # rethrow

# Ensure that response fd, offset and length are sane (match the request)
assert read_cmd[4:4+12] == header[4:4+12], "Unexpected read response"
assert len(response) == size
return response
return response, fd_num

def laf_erase(comm, fd_num, sector_start, sector_count):
"""TRIM some sectors."""
Expand All @@ -95,10 +131,20 @@ def laf_write(comm, fd_num, offset, data):

def open_local_writable(path):
if path == '-':
try: return sys.stdout.buffer
except: return sys.stdout
try: return (sys.stdout.buffer,0)
except: return (sys.stdout,0)
else:
return open(path, "wb")
try:
s = os.stat(path)
except OSError:
s = 0
f = open(path, "wb")
else:
s = s.st_size
assert not s%BLOCK_SIZE
f = open(path, "ab")
return (f,s)


def open_local_readable(path):
if path == '-':
Expand Down Expand Up @@ -136,23 +182,25 @@ def dump_partition(comm, disk_fd, local_path, part_offset, part_size):
# Read offsets must be a multiple of 512 bytes, enforce this
read_offset = BLOCK_SIZE * (part_offset // BLOCK_SIZE)
end_offset = part_offset + part_size
unaligned_bytes = part_offset % BLOCK_SIZE
_logger.debug("Will read %d bytes at disk offset %d", part_size, part_offset)
if unaligned_bytes:
_logger.debug("Unaligned read, read will start at %d", read_offset)

with open_local_writable(local_path) as f:
_f,s = open_local_writable(local_path)
with _f as f:
read_offset += s
unaligned_bytes = read_offset % BLOCK_SIZE
if unaligned_bytes:
_logger.debug("Unaligned read, read will start at %d", read_offset)
_logger.debug("Will read %d bytes at disk offset %d", part_size, part_offset)
# Offset should be aligned to block size. If not, read at most a
# whole block and drop the leading bytes.
if unaligned_bytes:
chunksize = min(end_offset - read_offset, BLOCK_SIZE)
data = laf_read(comm, disk_fd, read_offset // BLOCK_SIZE, chunksize)
data, disk_fd = laf_read(comm, disk_fd, read_offset // BLOCK_SIZE, chunksize)
f.write(data[unaligned_bytes:])
read_offset += BLOCK_SIZE

while read_offset < end_offset:
chunksize = min(end_offset - read_offset, BLOCK_SIZE * MAX_BLOCK_SIZE)
data = laf_read(comm, disk_fd, read_offset // BLOCK_SIZE, chunksize)
data, disk_fd = laf_read(comm, disk_fd, read_offset // BLOCK_SIZE, chunksize)
f.write(data)
read_offset += chunksize
_logger.info("Wrote %d bytes to %s", part_size, local_path)
Expand Down