* fbt: added hooks for build & dist environments * Moved env hooks to an optional file * Fixed var name * Added fw origin to device info * Bumped device info version * fbt: added FIRMWARE_ORIGIN option. Different implementation for FW_ORIGIN_* C macro. * api: bumped versions * fbt: added fbt_options_local.py * gitignore: cleanup Co-authored-by: あく <alleteam@gmail.com>
		
			
				
	
	
		
			124 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			124 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
from dataclasses import dataclass, field
 | 
						|
from typing import Dict, Optional
 | 
						|
 | 
						|
import gdb
 | 
						|
 | 
						|
 | 
						|
# Must match FuriHalRtcRegisterVersion index in FuriHalRtcRegister enum
 | 
						|
RTC_BACKUP_VERSION_REGISTER_IDX = 0x2
 | 
						|
 | 
						|
RTC_BASE = 0x40002800
 | 
						|
RTC_BACKUP_BASE = RTC_BASE + 0x50
 | 
						|
 | 
						|
VERSION_REGISTER_ADDRESS = RTC_BACKUP_BASE + RTC_BACKUP_VERSION_REGISTER_IDX * 4
 | 
						|
 | 
						|
VERSION_STRUCT_MAGIC = 0xBE40
 | 
						|
 | 
						|
 | 
						|
@dataclass
 | 
						|
class VersionData:
 | 
						|
    git_hash: str
 | 
						|
    git_branch: str
 | 
						|
    build_date: str
 | 
						|
    version: str
 | 
						|
    target: int
 | 
						|
    build_is_dirty: bool
 | 
						|
    # Since version 1.1
 | 
						|
    firmware_origin: str = ""
 | 
						|
    git_origin: str = ""
 | 
						|
    # More fields may be added in the future
 | 
						|
    extra: Optional[Dict[str, str]] = field(default_factory=dict)
 | 
						|
 | 
						|
 | 
						|
class VersionLoader:
 | 
						|
    def __init__(self, version_ptr):
 | 
						|
        self.version_ptr = version_ptr
 | 
						|
        self._cstr_type = gdb.lookup_type("char").pointer()
 | 
						|
        self._uint_type = gdb.lookup_type("unsigned int")
 | 
						|
 | 
						|
        version_signature = version_ptr.dereference().cast(self._uint_type)
 | 
						|
        is_versioned = (version_signature & (0xFFFF)) == VERSION_STRUCT_MAGIC
 | 
						|
        if is_versioned:
 | 
						|
            self._version_data = self.load_versioned(
 | 
						|
                major=version_signature >> 16 & 0xFF,
 | 
						|
                minor=version_signature >> 24 & 0xFF,
 | 
						|
            )
 | 
						|
        else:
 | 
						|
            self._version_data = self.load_unversioned()
 | 
						|
 | 
						|
    @property
 | 
						|
    def version(self) -> VersionData:
 | 
						|
        return self._version_data
 | 
						|
 | 
						|
    def load_versioned(self, major, minor):
 | 
						|
        if major != 1:
 | 
						|
            raise ValueError("Unsupported version struct major version")
 | 
						|
 | 
						|
        # Struct version 1.0
 | 
						|
        extra_data = int(self.version_ptr[5].cast(self._uint_type))
 | 
						|
        version_data = VersionData(
 | 
						|
            git_hash=self.version_ptr[1].cast(self._cstr_type).string(),
 | 
						|
            git_branch=self.version_ptr[2].cast(self._cstr_type).string(),
 | 
						|
            build_date=self.version_ptr[3].cast(self._cstr_type).string(),
 | 
						|
            version=self.version_ptr[4].cast(self._cstr_type).string(),
 | 
						|
            target=extra_data & 0xF,
 | 
						|
            build_is_dirty=bool((extra_data >> 8) & 0xF),
 | 
						|
        )
 | 
						|
        if minor >= 1:
 | 
						|
            version_data.firmware_origin = (
 | 
						|
                self.version_ptr[6].cast(self._cstr_type).string()
 | 
						|
            )
 | 
						|
            version_data.git_origin = self.version_ptr[7].cast(self._cstr_type).string()
 | 
						|
        return version_data
 | 
						|
 | 
						|
    def load_unversioned(self):
 | 
						|
        """Parse an early version of the version struct."""
 | 
						|
        extra_data = int(self.version_ptr[5].cast(self._uint_type))
 | 
						|
        return VersionData(
 | 
						|
            git_hash=self.version_ptr[0].cast(self._cstr_type).string(),
 | 
						|
            git_branch=self.version_ptr[1].cast(self._cstr_type).string(),
 | 
						|
            # branch number is #2, but we don't care about it
 | 
						|
            build_date=self.version_ptr[3].cast(self._cstr_type).string(),
 | 
						|
            version=self.version_ptr[4].cast(self._cstr_type).string(),
 | 
						|
            target=extra_data & 0xF,
 | 
						|
            build_is_dirty=bool((extra_data >> 8) & 0xF),
 | 
						|
        )
 | 
						|
 | 
						|
 | 
						|
class FlipperFwVersion(gdb.Command):
 | 
						|
    """Print the version of Flipper's firmware."""
 | 
						|
 | 
						|
    def __init__(self):
 | 
						|
        super(FlipperFwVersion, self).__init__("fw-version", gdb.COMMAND_USER)
 | 
						|
 | 
						|
    def invoke(self, arg, from_tty):
 | 
						|
        void_ptr_type = gdb.lookup_type("void").pointer().pointer()
 | 
						|
        version_ptr_ptr = gdb.Value(VERSION_REGISTER_ADDRESS).cast(void_ptr_type)
 | 
						|
 | 
						|
        if not version_ptr_ptr:
 | 
						|
            print("RTC version register is NULL")
 | 
						|
            return
 | 
						|
 | 
						|
        version_ptr = version_ptr_ptr.dereference()
 | 
						|
        if not version_ptr:
 | 
						|
            print("Pointer to version struct is NULL")
 | 
						|
            return
 | 
						|
 | 
						|
        version_struct = version_ptr.cast(void_ptr_type)
 | 
						|
 | 
						|
        v = VersionLoader(version_struct)
 | 
						|
        print("Firmware version on attached Flipper:")
 | 
						|
        print(f"\tVersion:     {v.version.version}")
 | 
						|
        print(f"\tBuilt on:    {v.version.build_date}")
 | 
						|
        print(f"\tGit branch:  {v.version.git_branch}")
 | 
						|
        print(f"\tGit commit:  {v.version.git_hash}")
 | 
						|
        print(f"\tDirty:       {v.version.build_is_dirty}")
 | 
						|
        print(f"\tHW Target:   {v.version.target}")
 | 
						|
        if v.version.firmware_origin:
 | 
						|
            print(f"\tOrigin:      {v.version.firmware_origin}")
 | 
						|
        if v.version.git_origin:
 | 
						|
            print(f"\tGit origin:  {v.version.git_origin}")
 | 
						|
 | 
						|
 | 
						|
FlipperFwVersion()
 |