 f57f0efc48
			
		
	
	
		f57f0efc48
		
			
		
	
	
	
	
		
			
			* Debug: revert cortex debug to lxml * Debug: update PyCortexMDebug readme * fbt: moved "debug" dir to "scripts" subfolder * ufbt: added missing debug_other & debug_other_blackmagic targets; github: fixed script bundling * lint: fixed formatting on debug scripts * vscode: updated configuration for debug dir changes --------- Co-authored-by: hedger <hedger@users.noreply.github.com> Co-authored-by: hedger <hedger@nanode.su>
		
			
				
	
	
		
			110 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			110 lines
		
	
	
		
			3.7 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
 | |
|     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))
 | |
|         return 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),
 | |
|         )
 | |
| 
 | |
|     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}")
 | |
| 
 | |
| 
 | |
| FlipperFwVersion()
 |