Skip to content

Commit 6442ae4

Browse files
committed
Support BCL-compressed uboot sections
1 parent 6aa257c commit 6442ae4

File tree

2 files changed

+20
-2
lines changed

2 files changed

+20
-2
lines changed

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ dependencies = [
2828
"aiohttp",
2929
"lxml >= 4.9.2",
3030
"pakler ~= 0.2.0",
31+
"pybcl ~= 1.0.0",
3132
"pycramfs ~= 1.1.0",
3233
"PySquashfsImage ~= 0.9.0",
3334
"python-lzo ~= 1.15",

reolinkfw/uboot.py

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import re
22
from ctypes import BigEndianStructure, c_char, c_uint32, c_uint8, sizeof
33
from enum import IntEnum
4+
from typing import BinaryIO, Optional
45

6+
import pybcl
57
from pakler import PAK
68

79
from reolinkfw.util import FileType
@@ -84,12 +86,27 @@ def from_fd(cls, fd):
8486
return cls.from_buffer_copy(fd.read(sizeof(cls)))
8587

8688

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]:
8897
for section in pak.sections:
8998
if section.len and "uboot" in section.name.lower():
9099
# This section is always named 'uboot' or 'uboot1'.
91100
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)
93110
return match.group().decode() if match is not None else None
94111
return None
95112

0 commit comments

Comments
 (0)