 7ce305fca3
			
		
	
	
		7ce305fca3
		
			
		
	
	
	
	
		
			
			* C2OTA: wip * Update Cube to 1.13.3 * Fixed prio * Functional Core2 updater * Removed hardware CRC usage; code cleanup & linter fixes * Moved hardcoded stack params to copro.mk * Fixing CI bundling of core2 fw * Removed last traces of hardcoded radio stack * OB processing draft * Python scripts cleanup * Support for comments in ob data * Sacrificed SD card icon in favor of faster update. Waiting for Storage fix * Additional handling for OB mismatched values * Description for new furi_hal apis; spelling fixes * Rework of OB write, WIP * Properly restarting OB verification loop * Split update_task_workers.c * Checking OBs after enabling post-update mode * Moved OB verification before flashing * Removed ob.data for custom stacks * Fixed progress calculation for OB * Removed unnecessary OB mask cast Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
		
			
				
	
	
		
			188 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			188 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| import struct
 | |
| import math
 | |
| import os, os.path
 | |
| import sys
 | |
| 
 | |
| 
 | |
| #  From STM32CubeWB\Middlewares\ST\STM32_WPAN\interface\patterns\ble_thread\shci\shci.h
 | |
| __STACK_TYPE_CODES = {
 | |
|     "BLE_FULL": 0x01,
 | |
|     "BLE_HCI": 0x02,
 | |
|     "BLE_LIGHT": 0x03,
 | |
|     "BLE_BEACON": 0x04,
 | |
|     "BLE_BASIC": 0x05,
 | |
|     "BLE_FULL_EXT_ADV": 0x06,
 | |
|     "BLE_HCI_EXT_ADV": 0x07,
 | |
|     "THREAD_FTD": 0x10,
 | |
|     "THREAD_MTD": 0x11,
 | |
|     "ZIGBEE_FFD": 0x30,
 | |
|     "ZIGBEE_RFD": 0x31,
 | |
|     "MAC": 0x40,
 | |
|     "BLE_THREAD_FTD_STATIC": 0x50,
 | |
|     "BLE_THREAD_FTD_DYAMIC": 0x51,
 | |
|     "802154_LLD_TESTS": 0x60,
 | |
|     "802154_PHY_VALID": 0x61,
 | |
|     "BLE_PHY_VALID": 0x62,
 | |
|     "BLE_LLD_TESTS": 0x63,
 | |
|     "BLE_RLV": 0x64,
 | |
|     "802154_RLV": 0x65,
 | |
|     "BLE_ZIGBEE_FFD_STATIC": 0x70,
 | |
|     "BLE_ZIGBEE_RFD_STATIC": 0x71,
 | |
|     "BLE_ZIGBEE_FFD_DYNAMIC": 0x78,
 | |
|     "BLE_ZIGBEE_RFD_DYNAMIC": 0x79,
 | |
|     "RLV": 0x80,
 | |
|     "BLE_MAC_STATIC": 0x90,
 | |
| }
 | |
| 
 | |
| 
 | |
| class CoproException(ValueError):
 | |
|     pass
 | |
| 
 | |
| 
 | |
| #  Formats based on AN5185
 | |
| class CoproFooterBase:
 | |
|     SIG_BIN_SIZE = 5 * 4
 | |
|     _SIG_BIN_COMMON_SIZE = 2 * 4
 | |
| 
 | |
|     def get_version(self):
 | |
|         return f"Version {self.version_major}.{self.version_minor}.{self.version_sub}, branch {self.version_branch}, build {self.version_build} (magic {self.magic:X})"
 | |
| 
 | |
|     def get_details(self):
 | |
|         raise CoproException("Not implemented")
 | |
| 
 | |
|     def __init__(self, raw: bytes):
 | |
|         if len(raw) != self.SIG_BIN_SIZE:
 | |
|             raise CoproException("Invalid footer size")
 | |
|         sig_common_part = raw[-self._SIG_BIN_COMMON_SIZE :]
 | |
|         parts = struct.unpack("BBBBI", sig_common_part)
 | |
|         self.version_major = parts[3]
 | |
|         self.version_minor = parts[2]
 | |
|         self.version_sub = parts[1]
 | |
|         #  AN5185 mismatch: swapping byte halves
 | |
|         self.version_build = parts[0] & 0x0F
 | |
|         self.version_branch = (parts[0] & 0xF0) >> 4
 | |
|         self.magic = parts[4]
 | |
| 
 | |
| 
 | |
| class CoproFusFooter(CoproFooterBase):
 | |
|     FUS_MAGIC_IMG_STACK = 0x23372991
 | |
|     FUS_MAGIC_IMG_FUS = 0x32279221
 | |
|     FUS_MAGIC_IMG_OTHER = 0x42769811
 | |
| 
 | |
|     FUS_BASE = 0x80F4000
 | |
|     FLASH_PAGE_SIZE = 4 * 1024
 | |
| 
 | |
|     def __init__(self, raw: bytes):
 | |
|         super().__init__(raw)
 | |
|         if self.magic not in (
 | |
|             self.FUS_MAGIC_IMG_OTHER,
 | |
|             self.FUS_MAGIC_IMG_FUS,
 | |
|             self.FUS_MAGIC_IMG_STACK,
 | |
|         ):
 | |
|             raise CoproException(f"Invalid FUS img magic {self.magic:x}")
 | |
|         own_data = raw[: -self._SIG_BIN_COMMON_SIZE]
 | |
|         parts = struct.unpack("IIBBBB", own_data)
 | |
|         self.info1 = parts[0]
 | |
|         self.info2 = parts[1]
 | |
|         self.sram2b_1ks = parts[5]
 | |
|         self.sram2a_1ks = parts[4]
 | |
|         self.flash_4ks = parts[2]
 | |
| 
 | |
|     def get_details(self):
 | |
|         return f"SRAM2b={self.sram2b_1ks}k SRAM2a={self.sram2a_1ks}k flash={self.flash_4ks}p"
 | |
| 
 | |
|     def is_stack(self):
 | |
|         return self.magic == self.FUS_MAGIC_IMG_STACK
 | |
| 
 | |
|     def get_flash_pages(self, fullsize):
 | |
|         return math.ceil(fullsize / self.FLASH_PAGE_SIZE)
 | |
| 
 | |
|     def get_flash_base(self, fullsize):
 | |
|         if not self.is_stack():
 | |
|             raise CoproException("Not a stack image")
 | |
|         return self.FUS_BASE - self.get_flash_pages(fullsize) * self.FLASH_PAGE_SIZE
 | |
| 
 | |
| 
 | |
| class CoproSigFooter(CoproFooterBase):
 | |
|     SIG_MAGIC_ST = 0xD3A12C5E
 | |
|     SIG_MAGIC_CUSTOMER = 0xE2B51D4A
 | |
| 
 | |
|     def __init__(self, raw: bytes):
 | |
|         super().__init__(raw)
 | |
|         if self.magic not in (self.SIG_MAGIC_ST, self.SIG_MAGIC_CUSTOMER):
 | |
|             raise CoproException(f"Invalid FUS img magic {self.magic:x}")
 | |
|         own_data = raw[: -self._SIG_BIN_COMMON_SIZE]
 | |
|         parts = struct.unpack("IIBBH", own_data)
 | |
|         self.reserved_1 = parts[0]
 | |
|         self.reserved_2 = parts[1]
 | |
|         self.size = parts[2]
 | |
|         self.source = parts[3]
 | |
|         self.reserved_34 = parts[4]
 | |
| 
 | |
|     def get_details(self):
 | |
|         return f"Signature Src {self.source:x} size {self.size:x}"
 | |
| 
 | |
| 
 | |
| class CoproBinary:
 | |
|     def __init__(self, binary_path):
 | |
|         self.binary_path = binary_path
 | |
|         self.img_sig_footer = None
 | |
|         self.img_sig = None
 | |
|         self.binary_size = -1
 | |
|         self._load()
 | |
| 
 | |
|     def _load(self):
 | |
|         with open(self.binary_path, "rb") as fin:
 | |
|             whole_file = fin.read()
 | |
|             self.binary_size = len(whole_file)
 | |
| 
 | |
|             img_sig_footer_bin = whole_file[-CoproFooterBase.SIG_BIN_SIZE :]
 | |
|             self.img_sig_footer = CoproSigFooter(img_sig_footer_bin)
 | |
|             img_sig_size = self.img_sig_footer.size + CoproSigFooter.SIG_BIN_SIZE
 | |
|             img_sig_bin = whole_file[
 | |
|                 -(img_sig_size + CoproFusFooter.SIG_BIN_SIZE) : -img_sig_size
 | |
|             ]
 | |
|             self.img_sig = CoproFusFooter(img_sig_bin)
 | |
| 
 | |
|     def is_valid(self):
 | |
|         return self.img_sig_footer is not None and self.img_sig is not None
 | |
| 
 | |
|     def is_stack(self):
 | |
|         return self.img_sig and self.img_sig.is_stack()
 | |
| 
 | |
|     def get_flash_load_addr(self):
 | |
|         if not self.is_stack():
 | |
|             raise CoproException("Not a stack image")
 | |
|         return self.img_sig.get_flash_base(self.binary_size)
 | |
| 
 | |
| 
 | |
| def get_stack_type(typestr: str):
 | |
|     stack_code = __STACK_TYPE_CODES.get(typestr.upper(), None)
 | |
|     if stack_code is None:
 | |
|         raise CoproException(f"Unknown stack type {typestr}. See shci.h")
 | |
|     return stack_code
 | |
| 
 | |
| 
 | |
| def _load_bin(binary_path: str):
 | |
|     print(binary_path)
 | |
|     copro_bin = CoproBinary(binary_path)
 | |
|     print(copro_bin.img_sig.get_version())
 | |
|     if copro_bin.img_sig.is_stack():
 | |
|         print(f"\t>> FLASH AT {copro_bin.get_flash_load_addr():X}\n")
 | |
| 
 | |
| 
 | |
| def main():
 | |
|     coprodir = (
 | |
|         sys.argv[1]
 | |
|         if len(sys.argv) > 1
 | |
|         else "../../../lib/STM32CubeWB/Projects/STM32WB_Copro_Wireless_Binaries/STM32WB5x"
 | |
|     )
 | |
|     for fn in os.listdir(coprodir):
 | |
|         if not fn.endswith(".bin"):
 | |
|             continue
 | |
|         _load_bin(os.path.join(coprodir, fn))
 | |
| 
 | |
| 
 | |
| if __name__ == "__main__":
 | |
|     main()
 |