|
1 | 1 | import re |
2 | 2 | from ctypes import BigEndianStructure, c_char, c_uint32, c_uint8, sizeof |
3 | 3 | from enum import IntEnum |
| 4 | +from typing import BinaryIO, Optional |
4 | 5 |
|
| 6 | +import pybcl |
5 | 7 | from pakler import PAK |
6 | 8 |
|
7 | 9 | from reolinkfw.util import FileType |
@@ -84,12 +86,27 @@ def from_fd(cls, fd): |
84 | 86 | return cls.from_buffer_copy(fd.read(sizeof(cls))) |
85 | 87 |
|
86 | 88 |
|
87 | | -def get_uboot_version(pak: PAK): |
| 89 | +def is_bcl_compressed(fd: BinaryIO) -> bool: |
| 90 | + size = len(pybcl.BCL_MAGIC_BYTES) |
| 91 | + magic = fd.read(size) |
| 92 | + fd.seek(-size, 1) |
| 93 | + return magic == pybcl.BCL_MAGIC_BYTES |
| 94 | + |
| 95 | + |
| 96 | +def get_uboot_version(pak: PAK) -> Optional[str]: |
88 | 97 | for section in pak.sections: |
89 | 98 | if section.len and "uboot" in section.name.lower(): |
90 | 99 | # This section is always named 'uboot' or 'uboot1'. |
91 | 100 | pak._fd.seek(section.start) |
92 | | - match = re.search(b"U-Boot [0-9]{4}\.[0-9]{2}.*? \(.*?\)", pak._fd.read(section.len)) |
| 101 | + if is_bcl_compressed(pak._fd): |
| 102 | + # Sometimes section.len - sizeof(hdr) is 1 to 3 bytes larger |
| 103 | + # than hdr.size. The extra bytes are 0xff (padding?). This |
| 104 | + # could explain why the compressed size is added to the header. |
| 105 | + hdr = pybcl.HeaderVariant.from_fd(pak._fd) |
| 106 | + data = pybcl.decompress(pak._fd.read(hdr.size), hdr.algo, hdr.outsize) |
| 107 | + else: |
| 108 | + data = pak._fd.read(section.len) |
| 109 | + match = re.search(b"U-Boot [0-9]{4}\.[0-9]{2}.*? \(.*?\)", data) |
93 | 110 | return match.group().decode() if match is not None else None |
94 | 111 | return None |
95 | 112 |
|
|
0 commit comments