Skip to content

Commit 0887d7d

Browse files
committed
snagrecover ambarella
1 parent f758c1e commit 0887d7d

File tree

4 files changed

+112
-2
lines changed

4 files changed

+112
-2
lines changed

src/snagrecover/config.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
"stm32mp": "0483:df11",
2828
"sama5": "03eb:6124",
2929
"sunxi": "1f3a:efe8",
30+
"ambarella": "4255:0013",
3031
"am6x": "0451:6165",
3132
"am62lx": "0451:6165",
3233
"zynqmp": "03fd:0050",
@@ -114,4 +115,3 @@ def init_config(args: list):
114115
# store input arguments in config
115116
recovery_config["args"] = vars(args)
116117
logger.debug(f"recovery_config:{str(recovery_config)}")
117-

src/snagrecover/firmware/firmware.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,33 @@
1818
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
1919

2020
import logging
21+
from pathlib import Path
22+
from typing import Optional
23+
2124
logger = logging.getLogger("snagrecover")
2225
from snagrecover.protocols import dfu
2326
from snagrecover.config import recovery_config
2427
from snagrecover.utils import cli_error
2528

29+
class FirmwareError(Exception):
30+
"""Base class for firmware-related errors."""
31+
pass
32+
33+
class Firmware:
34+
"""Base class for firmware handlers."""
35+
36+
def __init__(self):
37+
"""Initialize firmware handler."""
38+
pass
39+
40+
def load(self) -> None:
41+
"""Load firmware files.
42+
43+
Raises:
44+
FirmwareError: If loading fails
45+
"""
46+
raise NotImplementedError("Subclasses must implement load()")
47+
2648
def stm32mp_run(port, fw_name: str, fw_blob: bytes):
2749
"""
2850
There isn't a lot of complicated logic to handle stm32mp firmware

src/snagrecover/recoveries/ambarella.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,3 +213,41 @@ def flash_firmware(self, firmware: Path) -> None:
213213
with open(firmware, 'rb') as f:
214214
fw_data = f.read()
215215
self.protocol.send_file(fw_info.memfw_prog_addr, fw_data)
216+
217+
def main() -> None:
218+
"""Main recovery function.
219+
220+
Raises:
221+
AmbaUsbError: On recovery error
222+
"""
223+
from snagrecover.config import recovery_config
224+
from snagrecover.utils import get_usb
225+
226+
# Get USB device
227+
usb_path = recovery_config["usb_path"]
228+
device = UsbDevice(get_usb(usb_path))
229+
230+
# Initialize recovery handler
231+
recovery = AmbarellaRecovery(device)
232+
233+
# Get firmware configuration
234+
fw_config = recovery_config.get("firmware", {})
235+
236+
# Initialize DRAM if script provided
237+
if "dram_script" in fw_config:
238+
dram_script = Path(fw_config["dram_script"]["path"])
239+
recovery.initialize_dram(dram_script)
240+
241+
# Load bootloader if provided
242+
if "bootloader" in fw_config:
243+
bootloader = Path(fw_config["bootloader"]["path"])
244+
recovery.load_bootloader(bootloader)
245+
246+
# Flash firmware if provided in steps
247+
steps = recovery_config.get("steps", [])
248+
for step in steps:
249+
if step.get("action") == "flash_firmware":
250+
firmware_path = step.get("args", {}).get("firmware")
251+
if firmware_path:
252+
firmware = Path(firmware_path)
253+
recovery.flash_firmware(firmware)

src/snagrecover/usb.py

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,57 @@
44
import gc
55
import importlib
66
import sys
7+
from typing import Optional
8+
9+
class UsbError(Exception):
10+
"""Base class for USB-related errors."""
11+
pass
12+
13+
class UsbDevice:
14+
"""USB device wrapper class."""
15+
16+
def __init__(self, device: usb.core.Device):
17+
"""Initialize USB device.
18+
19+
Args:
20+
device: PyUSB device object
21+
"""
22+
self.device = device
23+
24+
# Set default configuration
25+
try:
26+
self.device.set_configuration()
27+
except usb.core.USBError as e:
28+
raise UsbError(f"Failed to set configuration: {e}")
29+
30+
def write(self, data: bytes) -> None:
31+
"""Write data to device.
32+
33+
Args:
34+
data: Data to write
35+
36+
Raises:
37+
UsbError: On write error
38+
"""
39+
try:
40+
self.device.write(0x1, data) # EP1 OUT
41+
except usb.core.USBError as e:
42+
raise UsbError(f"Write failed: {e}")
43+
44+
def read(self, buffer: bytearray) -> None:
45+
"""Read data from device into buffer.
46+
47+
Args:
48+
buffer: Buffer to read into
49+
50+
Raises:
51+
UsbError: On read error
52+
"""
53+
try:
54+
read_data = self.device.read(0x81, len(buffer)) # EP1 IN
55+
buffer[:len(read_data)] = read_data
56+
except usb.core.USBError as e:
57+
raise UsbError(f"Read failed: {e}")
758

859
class SnagbootUSBContext():
960
"""
@@ -67,4 +118,3 @@ def find(**args):
67118
tests = (hasattr(dev, key) and val == getattr(dev, key) for key, val in args.items())
68119
if all(tests):
69120
yield weakref.proxy(dev)
70-

0 commit comments

Comments
 (0)