[FL-3180] OTP programmer: return exit code based on error type (#2504)
This commit is contained in:
		@@ -1,6 +1,7 @@
 | 
			
		||||
import logging
 | 
			
		||||
import os
 | 
			
		||||
import typing
 | 
			
		||||
from enum import Enum
 | 
			
		||||
 | 
			
		||||
from flipper.utils.programmer import Programmer
 | 
			
		||||
from flipper.utils.openocd import OpenOCD
 | 
			
		||||
@@ -8,6 +9,14 @@ from flipper.utils.stm32wb55 import STM32WB55
 | 
			
		||||
from flipper.assets.obdata import OptionBytesData
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class OpenOCDProgrammerResult(Enum):
 | 
			
		||||
    Success = 0
 | 
			
		||||
    ErrorGeneric = 1
 | 
			
		||||
    ErrorAlignment = 2
 | 
			
		||||
    ErrorAlreadyWritten = 3
 | 
			
		||||
    ErrorValidation = 4
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class OpenOCDProgrammer(Programmer):
 | 
			
		||||
    def __init__(
 | 
			
		||||
        self,
 | 
			
		||||
@@ -199,18 +208,18 @@ class OpenOCDProgrammer(Programmer):
 | 
			
		||||
 | 
			
		||||
        return True
 | 
			
		||||
 | 
			
		||||
    def otp_write(self, address: int, file_path: str) -> bool:
 | 
			
		||||
    def otp_write(self, address: int, file_path: str) -> OpenOCDProgrammerResult:
 | 
			
		||||
        # Open file, check that it aligned to 8 bytes
 | 
			
		||||
        with open(file_path, "rb") as f:
 | 
			
		||||
            data = f.read()
 | 
			
		||||
            if len(data) % 8 != 0:
 | 
			
		||||
                self.logger.error(f"File {file_path} is not aligned to 8 bytes")
 | 
			
		||||
                return False
 | 
			
		||||
                return OpenOCDProgrammerResult.ErrorAlignment
 | 
			
		||||
 | 
			
		||||
        # Check that address is aligned to 8 bytes
 | 
			
		||||
        if address % 8 != 0:
 | 
			
		||||
            self.logger.error(f"Address {address} is not aligned to 8 bytes")
 | 
			
		||||
            return False
 | 
			
		||||
            return OpenOCDProgrammerResult.ErrorAlignment
 | 
			
		||||
 | 
			
		||||
        # Get size of data
 | 
			
		||||
        data_size = len(data)
 | 
			
		||||
@@ -218,7 +227,7 @@ class OpenOCDProgrammer(Programmer):
 | 
			
		||||
        # Check that data size is aligned to 8 bytes
 | 
			
		||||
        if data_size % 8 != 0:
 | 
			
		||||
            self.logger.error(f"Data size {data_size} is not aligned to 8 bytes")
 | 
			
		||||
            return False
 | 
			
		||||
            return OpenOCDProgrammerResult.ErrorAlignment
 | 
			
		||||
 | 
			
		||||
        self.logger.debug(f"Writing {data_size} bytes to OTP at {address:08X}")
 | 
			
		||||
        self.logger.debug(f"Data: {data.hex().upper()}")
 | 
			
		||||
@@ -241,14 +250,14 @@ class OpenOCDProgrammer(Programmer):
 | 
			
		||||
                    self.logger.error(
 | 
			
		||||
                        f"OTP memory at {address + i:08X} is not empty: {device_word:08X}"
 | 
			
		||||
                    )
 | 
			
		||||
                    raise Exception("OTP memory is not empty")
 | 
			
		||||
                    return OpenOCDProgrammerResult.ErrorAlreadyWritten
 | 
			
		||||
 | 
			
		||||
                if device_word != file_word:
 | 
			
		||||
                    already_written = False
 | 
			
		||||
 | 
			
		||||
            if already_written:
 | 
			
		||||
                self.logger.info(f"OTP memory is already written with the given data")
 | 
			
		||||
                return True
 | 
			
		||||
                return OpenOCDProgrammerResult.Success
 | 
			
		||||
 | 
			
		||||
            self.reset(self.RunMode.Stop)
 | 
			
		||||
            stm32.clear_flash_errors(oocd)
 | 
			
		||||
@@ -278,4 +287,8 @@ class OpenOCDProgrammer(Programmer):
 | 
			
		||||
            stm32.reset(oocd, stm32.RunMode.Run)
 | 
			
		||||
            oocd.stop()
 | 
			
		||||
 | 
			
		||||
        return validation_result
 | 
			
		||||
        return (
 | 
			
		||||
            OpenOCDProgrammerResult.Success
 | 
			
		||||
            if validation_result
 | 
			
		||||
            else OpenOCDProgrammerResult.ErrorValidation
 | 
			
		||||
        )
 | 
			
		||||
 
 | 
			
		||||
@@ -34,8 +34,16 @@ OTP_DISPLAYS = {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
from flipper.app import App
 | 
			
		||||
from flipper.cube import CubeProgrammer
 | 
			
		||||
from flipper.utils.programmer_openocd import OpenOCDProgrammer
 | 
			
		||||
from flipper.utils.programmer_openocd import OpenOCDProgrammer, OpenOCDProgrammerResult
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class OTPException(Exception):
 | 
			
		||||
    def __init__(self, message: str, result: OpenOCDProgrammerResult):
 | 
			
		||||
        self.message = message
 | 
			
		||||
        self.result = result
 | 
			
		||||
 | 
			
		||||
    def get_exit_code(self) -> int:
 | 
			
		||||
        return int(self.result.value)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Main(App):
 | 
			
		||||
@@ -183,13 +191,14 @@ class Main(App):
 | 
			
		||||
                self.args.serial,
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
            if not openocd.otp_write(0x1FFF7000, filename):
 | 
			
		||||
                raise Exception("Failed to flash OTP")
 | 
			
		||||
            programmer_result = openocd.otp_write(0x1FFF7000, filename)
 | 
			
		||||
            if programmer_result != OpenOCDProgrammerResult.Success:
 | 
			
		||||
                raise OTPException("Failed to flash OTP", programmer_result)
 | 
			
		||||
 | 
			
		||||
            self.logger.info(f"Flashed Successfully")
 | 
			
		||||
        except Exception as e:
 | 
			
		||||
        except OTPException as e:
 | 
			
		||||
            self.logger.exception(e)
 | 
			
		||||
            return 1
 | 
			
		||||
            return e.get_exit_code()
 | 
			
		||||
        finally:
 | 
			
		||||
            os.remove(filename)
 | 
			
		||||
 | 
			
		||||
@@ -215,13 +224,14 @@ class Main(App):
 | 
			
		||||
                self.args.serial,
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
            if not openocd.otp_write(0x1FFF7010, filename):
 | 
			
		||||
                raise Exception("Failed to flash OTP")
 | 
			
		||||
            programmer_result = openocd.otp_write(0x1FFF7010, filename)
 | 
			
		||||
            if programmer_result != OpenOCDProgrammerResult.Success:
 | 
			
		||||
                raise OTPException("Failed to flash OTP", programmer_result)
 | 
			
		||||
 | 
			
		||||
            self.logger.info(f"Flashed Successfully")
 | 
			
		||||
        except Exception as e:
 | 
			
		||||
        except OTPException as e:
 | 
			
		||||
            self.logger.exception(e)
 | 
			
		||||
            return 1
 | 
			
		||||
            return e.get_exit_code()
 | 
			
		||||
        finally:
 | 
			
		||||
            os.remove(filename)
 | 
			
		||||
 | 
			
		||||
@@ -249,13 +259,14 @@ class Main(App):
 | 
			
		||||
                self.args.serial,
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
            if not openocd.otp_write(0x1FFF7000, filename):
 | 
			
		||||
                raise Exception("Failed to flash OTP")
 | 
			
		||||
            programmer_result = openocd.otp_write(0x1FFF7000, filename)
 | 
			
		||||
            if programmer_result != OpenOCDProgrammerResult.Success:
 | 
			
		||||
                raise OTPException("Failed to flash OTP", programmer_result)
 | 
			
		||||
 | 
			
		||||
            self.logger.info(f"Flashed Successfully")
 | 
			
		||||
        except Exception as e:
 | 
			
		||||
        except OTPException as e:
 | 
			
		||||
            self.logger.exception(e)
 | 
			
		||||
            return 1
 | 
			
		||||
            return e.get_exit_code()
 | 
			
		||||
        finally:
 | 
			
		||||
            os.remove(filename)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user