unleashed-firmware/scripts/debug/flipperversion.py
hedger 8d2ea14f06
[FL-3330] fbt: added hooks for build & dist environments; added FW_ORIGIN_* macro for apps & SDK (#2705)
* 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>
2023-05-30 01:40:56 +09:00

123 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()