reolinkfw


Namereolinkfw JSON
Version 2.0.0 PyPI version JSON
download
home_page
SummaryExtract information and files from Reolink firmwares.
upload_time2023-12-23 11:05:29
maintainer
docs_urlNone
author
requires_python>=3.9
license
keywords reolink firmware
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # reolinkfw

<p align="left">
<a><img alt="Python versions" src="https://img.shields.io/pypi/pyversions/reolinkfw"></a>
<a href="https://pypi.org/project/reolinkfw/"><img alt="PyPI" src="https://img.shields.io/pypi/v/reolinkfw"></a>
<!-- <a href="https://github.com/psf/black"><img alt="Code style: black" src="https://img.shields.io/badge/code%20style-black-000000.svg"></a> -->
<a href="https://github.com/AT0myks/reolink-fw/blob/main/LICENSE"><img alt="License" src="https://img.shields.io/pypi/l/reolinkfw"></a>
</p>

* [Description](#description)
* [Requirements](#requirements)
* [Installation](#installation)
* [Usage](#usage)
* [Notes](#notes)

## Description

This is a tool and library to read and extract Reolink firmwares.
It supports ZIP and PAK files, local or remote.
Information is retrieved directly from the files contained inside a firmware.

It can extract:
- File systems
- Decompressed U-Boot
- Decompressed kernel
- Kernel config (some firmwares)
- Devicetree source (some firmwares)

This is what powers the
[firmware archive](https://github.com/AT0myks/reolink-fw-archive)
where you can also find
[details](https://github.com/AT0myks/reolink-fw-archive/blob/main/pak_info.json)
about all of the firmwares it lists without having to install the tool yourself.

## Requirements

- Python 3.9+
- [python-lzo](https://github.com/jd-boyd/python-lzo)

## Installation

```
pip install -i https://test.pypi.org/simple/ python-lzo
pip install reolinkfw
```

python-lzo doesn't have wheels on PyPI for Linux and for Python 3.9+ on macOS yet.
A [PR](https://github.com/jd-boyd/python-lzo/pull/75) has been merged to provide
wheels for all version on all platforms but there needs to be a new release first.
In the meantime you can install wheels from
[TestPyPI](https://test.pypi.org/project/python-lzo/) as shown above.

> [!IMPORTANT]  
> No Python 3.12 wheels exist yet for lz4. To build it from source see
> [here](https://python-lz4.readthedocs.io/en/stable/install.html#installing-from-source).

## Usage

### Command line

#### Info

```
usage: reolinkfw info [-h] [--no-cache] [-j [indent]] file_or_url

positional arguments:
  file_or_url                   URL or on-disk file

options:
  -h, --help                    show this help message and exit
  --no-cache                    don't use cache for remote files (URLs)
  -j [indent], --json [indent]  JSON output with optional indentation level for pretty print
```

Example:

```
$ reolinkfw info RLC-410-5MP_20_20052300.zip
IPC_51516M5M.20_20052300.RLC-410-5MP.OV05A10.5MP.REOLINK.pak
Model:                RLC-410-5MP
Hardware info:        IPC_51516M5M
Device type:          IPC
Firmware version:     v3.0.0.20_20052300
Build date:           2020-05-23
Architecture:         MIPS
OS:                   Linux
Kernel image name:    Linux-4.1.0
Linux banner:         Linux version 4.1.0 (lwy@ubuntu) (gcc version 4.9.3 (Buildroot 2015.11.1-00003-gfd1edb1) ) #1 PREEMPT Tue Feb 26 18:19:48 CST 2019
U-Boot version:       U-Boot 2014.07 (Feb 26 2019 - 18:20:07)
U-Boot compiler:      mipsel-24kec-linux-uclibc-gcc.br_real (Buildroot 2015.11.1-00003-gfd1edb1) 4.9.3
U-Boot linker:        GNU ld (GNU Binutils) 2.24
File system:          squashfs
File system sections: fs
Board vendor:         Novatek
Board:                Novatek NA51023 evaluation board
```

Or with JSON output:

```
$ reolinkfw info RLC-410-5MP_20_20052300.zip -j 2
[
  {
    "firmware_version_prefix": "v3.0.0",
    "board_type": "IPC_51516M5M",
    "board_name": "IPC_51516M5M",
    "build_date": "200523",
    "display_type_info": "RLC-410-5MP",
    "detail_machine_type": "IPC_51516M5M",
    "type": "IPC",
    "version_file": "20_20052300",
    "os": "Linux",
    "architecture": "MIPS",
    "kernel_image_name": "Linux-4.1.0",
    "uboot_version": "U-Boot 2014.07 (Feb 26 2019 - 18:20:07)",
    "uboot_compiler": "mipsel-24kec-linux-uclibc-gcc.br_real (Buildroot 2015.11.1-00003-gfd1edb1) 4.9.3",
    "uboot_linker": "GNU ld (GNU Binutils) 2.24",
    "linux_banner": "Linux version 4.1.0 (lwy@ubuntu) (gcc version 4.9.3 (Buildroot 2015.11.1-00003-gfd1edb1) ) #1 PREEMPT Tue Feb 26 18:19:48 CST 2019",
    "board": "Novatek NA51023 evaluation board",
    "board_vendor": "Novatek",
    "filesystems": [
      {
        "name": "fs",
        "type": "squashfs"
      }
    ],
    "sha256": "6ef371a51b61d7b21d8f7016d90b5fc1ed3eaa8a3f30f1e202a3474bfb4807e5",
    "file": "RLC-410-5MP_20_20052300.zip",
    "pak": "IPC_51516M5M.20_20052300.RLC-410-5MP.OV05A10.5MP.REOLINK.pak"
  }
]
```

`file` is the given argument, a file or URL. The value of `pak` depends on the
argument. If it's a local or remote ZIP file it will be the path of the PAK file
inside it. If it's a remote PAK file, it will be the value of the `name` query
parameter or `None` if not found. And finally for a local PAK file it will be
the file name.

#### Extract

```
usage: reolinkfw extract [-h] [--no-cache] [-d DEST] [-f] file_or_url

Extract the file system and a few other files from a Reolink firmware

positional arguments:
  file_or_url           URL or on-disk file

options:
  -h, --help            show this help message and exit
  --no-cache            don't use cache for remote files (URLs)
  -d DEST, --dest DEST  destination directory. Default: current directory
  -f, --force           overwrite existing files. Does not apply to UBIFS. Default: False
```

A firmware's file system can be laid out in two different ways inside a PAK file:
1. In a single section named `fs` or `rootfs` containing the whole file system
1. In two sections with the second one named `app` containing the files that go in `/mnt/app`

In the second case, the contents of `app` will be extracted to the appropriate
location so that the files are organized the same way as they are when the
camera is running.

Consider the result of this command a one-way operation.
You should not use it to repack a custom firmware.

### As a library

```py
import asyncio
from reolinkfw import ReolinkFirmware, firmware_info

async def main():
    url = "https://reolink-storage.s3.amazonaws.com/website/firmware/20200523firmware/RLC-410-5MP_20_20052300.zip"
    print(await firmware_info(url))
    pak = "/home/ben/RLC-410-5MP_20_20052300.pak"
    with ReolinkFirmware.from_file(pak) as fw:
        print(await fw.get_info())
        fw.extract()

asyncio.run(main())
```

In most cases where a URL is used, it will be a direct link to the file
(meaning if you were to open it in a browser, the download would start).

But in some cases (for example beta firmwares) Reolink gives a Google Drive or
a bit.ly link (that redirects to a Google Drive link).

These URLs are automatically handled so that you don't have to figure out the
"real" download link, and in this case the `file` value(s) in the result JSON
will not be the link that you gave but the direct download one.

However the Google Drive folder links (`drive.google.com/drive/folders`) are not
handled and in these cases you must find the real URL, or you can also download
the file.

## Notes

There are 3 types of file systems used for Reolink firmwares:
- [cramfs](https://www.kernel.org/doc/html/latest/filesystems/cramfs.html) (handled by [pycramfs](https://github.com/AT0myks/pycramfs))
- [squashfs](https://www.kernel.org/doc/html/latest/filesystems/squashfs.html) (handled by [PySquashfsImage](https://github.com/matteomattei/PySquashfsImage))
- [UBIFS](https://www.kernel.org/doc/html/latest/filesystems/ubifs.html) (handled by [ubi_reader](https://github.com/jrspruitt/ubi_reader))

Some ZIP files provided by Reolink contain multiple PAKs. This is why
`firmware_info` always returns a list.

Here's a map of vendors to hardware versions:

Cameras:
- MStar/SigmaStar: IPC_30, IPC_32, IPC_MS
- Grain Media: IPC_35, IPC_36, IPC_38
- Novatek: DB_56, FE_52, IPC_51, IPC_52, IPC_56, IPC_NT

NVRs:
- Novatek: hardware version is H3MB18 or starts with N
- HiSilicon: hardware version starts with H (except H3MB18)

Grain Media was
[transferred](https://web.archive.org/web/20170703025339/https://www.grain-media.com/)
to Novatek around 2017.

            

Raw data

            {
    "_id": null,
    "home_page": "",
    "name": "reolinkfw",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.9",
    "maintainer_email": "",
    "keywords": "reolink,firmware",
    "author": "",
    "author_email": "AT0myks <at0myks.dev@gmail.com>",
    "download_url": "https://files.pythonhosted.org/packages/89/af/b17d6680549d9ee28c8a9ad0ae9f25311c33b34e5c567c78e47177fadfa7/reolinkfw-2.0.0.tar.gz",
    "platform": null,
    "description": "# reolinkfw\n\n<p align=\"left\">\n<a><img alt=\"Python versions\" src=\"https://img.shields.io/pypi/pyversions/reolinkfw\"></a>\n<a href=\"https://pypi.org/project/reolinkfw/\"><img alt=\"PyPI\" src=\"https://img.shields.io/pypi/v/reolinkfw\"></a>\n<!-- <a href=\"https://github.com/psf/black\"><img alt=\"Code style: black\" src=\"https://img.shields.io/badge/code%20style-black-000000.svg\"></a> -->\n<a href=\"https://github.com/AT0myks/reolink-fw/blob/main/LICENSE\"><img alt=\"License\" src=\"https://img.shields.io/pypi/l/reolinkfw\"></a>\n</p>\n\n* [Description](#description)\n* [Requirements](#requirements)\n* [Installation](#installation)\n* [Usage](#usage)\n* [Notes](#notes)\n\n## Description\n\nThis is a tool and library to read and extract Reolink firmwares.\nIt supports ZIP and PAK files, local or remote.\nInformation is retrieved directly from the files contained inside a firmware.\n\nIt can extract:\n- File systems\n- Decompressed U-Boot\n- Decompressed kernel\n- Kernel config (some firmwares)\n- Devicetree source (some firmwares)\n\nThis is what powers the\n[firmware archive](https://github.com/AT0myks/reolink-fw-archive)\nwhere you can also find\n[details](https://github.com/AT0myks/reolink-fw-archive/blob/main/pak_info.json)\nabout all of the firmwares it lists without having to install the tool yourself.\n\n## Requirements\n\n- Python 3.9+\n- [python-lzo](https://github.com/jd-boyd/python-lzo)\n\n## Installation\n\n```\npip install -i https://test.pypi.org/simple/ python-lzo\npip install reolinkfw\n```\n\npython-lzo doesn't have wheels on PyPI for Linux and for Python 3.9+ on macOS yet.\nA [PR](https://github.com/jd-boyd/python-lzo/pull/75) has been merged to provide\nwheels for all version on all platforms but there needs to be a new release first.\nIn the meantime you can install wheels from\n[TestPyPI](https://test.pypi.org/project/python-lzo/) as shown above.\n\n> [!IMPORTANT]  \n> No Python 3.12 wheels exist yet for lz4. To build it from source see\n> [here](https://python-lz4.readthedocs.io/en/stable/install.html#installing-from-source).\n\n## Usage\n\n### Command line\n\n#### Info\n\n```\nusage: reolinkfw info [-h] [--no-cache] [-j [indent]] file_or_url\n\npositional arguments:\n  file_or_url                   URL or on-disk file\n\noptions:\n  -h, --help                    show this help message and exit\n  --no-cache                    don't use cache for remote files (URLs)\n  -j [indent], --json [indent]  JSON output with optional indentation level for pretty print\n```\n\nExample:\n\n```\n$ reolinkfw info RLC-410-5MP_20_20052300.zip\nIPC_51516M5M.20_20052300.RLC-410-5MP.OV05A10.5MP.REOLINK.pak\nModel:                RLC-410-5MP\nHardware info:        IPC_51516M5M\nDevice type:          IPC\nFirmware version:     v3.0.0.20_20052300\nBuild date:           2020-05-23\nArchitecture:         MIPS\nOS:                   Linux\nKernel image name:    Linux-4.1.0\nLinux banner:         Linux version 4.1.0 (lwy@ubuntu) (gcc version 4.9.3 (Buildroot 2015.11.1-00003-gfd1edb1) ) #1 PREEMPT Tue Feb 26 18:19:48 CST 2019\nU-Boot version:       U-Boot 2014.07 (Feb 26 2019 - 18:20:07)\nU-Boot compiler:      mipsel-24kec-linux-uclibc-gcc.br_real (Buildroot 2015.11.1-00003-gfd1edb1) 4.9.3\nU-Boot linker:        GNU ld (GNU Binutils) 2.24\nFile system:          squashfs\nFile system sections: fs\nBoard vendor:         Novatek\nBoard:                Novatek NA51023 evaluation board\n```\n\nOr with JSON output:\n\n```\n$ reolinkfw info RLC-410-5MP_20_20052300.zip -j 2\n[\n  {\n    \"firmware_version_prefix\": \"v3.0.0\",\n    \"board_type\": \"IPC_51516M5M\",\n    \"board_name\": \"IPC_51516M5M\",\n    \"build_date\": \"200523\",\n    \"display_type_info\": \"RLC-410-5MP\",\n    \"detail_machine_type\": \"IPC_51516M5M\",\n    \"type\": \"IPC\",\n    \"version_file\": \"20_20052300\",\n    \"os\": \"Linux\",\n    \"architecture\": \"MIPS\",\n    \"kernel_image_name\": \"Linux-4.1.0\",\n    \"uboot_version\": \"U-Boot 2014.07 (Feb 26 2019 - 18:20:07)\",\n    \"uboot_compiler\": \"mipsel-24kec-linux-uclibc-gcc.br_real (Buildroot 2015.11.1-00003-gfd1edb1) 4.9.3\",\n    \"uboot_linker\": \"GNU ld (GNU Binutils) 2.24\",\n    \"linux_banner\": \"Linux version 4.1.0 (lwy@ubuntu) (gcc version 4.9.3 (Buildroot 2015.11.1-00003-gfd1edb1) ) #1 PREEMPT Tue Feb 26 18:19:48 CST 2019\",\n    \"board\": \"Novatek NA51023 evaluation board\",\n    \"board_vendor\": \"Novatek\",\n    \"filesystems\": [\n      {\n        \"name\": \"fs\",\n        \"type\": \"squashfs\"\n      }\n    ],\n    \"sha256\": \"6ef371a51b61d7b21d8f7016d90b5fc1ed3eaa8a3f30f1e202a3474bfb4807e5\",\n    \"file\": \"RLC-410-5MP_20_20052300.zip\",\n    \"pak\": \"IPC_51516M5M.20_20052300.RLC-410-5MP.OV05A10.5MP.REOLINK.pak\"\n  }\n]\n```\n\n`file` is the given argument, a file or URL. The value of `pak` depends on the\nargument. If it's a local or remote ZIP file it will be the path of the PAK file\ninside it. If it's a remote PAK file, it will be the value of the `name` query\nparameter or `None` if not found. And finally for a local PAK file it will be\nthe file name.\n\n#### Extract\n\n```\nusage: reolinkfw extract [-h] [--no-cache] [-d DEST] [-f] file_or_url\n\nExtract the file system and a few other files from a Reolink firmware\n\npositional arguments:\n  file_or_url           URL or on-disk file\n\noptions:\n  -h, --help            show this help message and exit\n  --no-cache            don't use cache for remote files (URLs)\n  -d DEST, --dest DEST  destination directory. Default: current directory\n  -f, --force           overwrite existing files. Does not apply to UBIFS. Default: False\n```\n\nA firmware's file system can be laid out in two different ways inside a PAK file:\n1. In a single section named `fs` or `rootfs` containing the whole file system\n1. In two sections with the second one named `app` containing the files that go in `/mnt/app`\n\nIn the second case, the contents of `app` will be extracted to the appropriate\nlocation so that the files are organized the same way as they are when the\ncamera is running.\n\nConsider the result of this command a one-way operation.\nYou should not use it to repack a custom firmware.\n\n### As a library\n\n```py\nimport asyncio\nfrom reolinkfw import ReolinkFirmware, firmware_info\n\nasync def main():\n    url = \"https://reolink-storage.s3.amazonaws.com/website/firmware/20200523firmware/RLC-410-5MP_20_20052300.zip\"\n    print(await firmware_info(url))\n    pak = \"/home/ben/RLC-410-5MP_20_20052300.pak\"\n    with ReolinkFirmware.from_file(pak) as fw:\n        print(await fw.get_info())\n        fw.extract()\n\nasyncio.run(main())\n```\n\nIn most cases where a URL is used, it will be a direct link to the file\n(meaning if you were to open it in a browser, the download would start).\n\nBut in some cases (for example beta firmwares) Reolink gives a Google Drive or\na bit.ly link (that redirects to a Google Drive link).\n\nThese URLs are automatically handled so that you don't have to figure out the\n\"real\" download link, and in this case the `file` value(s) in the result JSON\nwill not be the link that you gave but the direct download one.\n\nHowever the Google Drive folder links (`drive.google.com/drive/folders`) are not\nhandled and in these cases you must find the real URL, or you can also download\nthe file.\n\n## Notes\n\nThere are 3 types of file systems used for Reolink firmwares:\n- [cramfs](https://www.kernel.org/doc/html/latest/filesystems/cramfs.html) (handled by [pycramfs](https://github.com/AT0myks/pycramfs))\n- [squashfs](https://www.kernel.org/doc/html/latest/filesystems/squashfs.html) (handled by [PySquashfsImage](https://github.com/matteomattei/PySquashfsImage))\n- [UBIFS](https://www.kernel.org/doc/html/latest/filesystems/ubifs.html) (handled by [ubi_reader](https://github.com/jrspruitt/ubi_reader))\n\nSome ZIP files provided by Reolink contain multiple PAKs. This is why\n`firmware_info` always returns a list.\n\nHere's a map of vendors to hardware versions:\n\nCameras:\n- MStar/SigmaStar: IPC_30, IPC_32, IPC_MS\n- Grain Media: IPC_35, IPC_36, IPC_38\n- Novatek: DB_56, FE_52, IPC_51, IPC_52, IPC_56, IPC_NT\n\nNVRs:\n- Novatek: hardware version is H3MB18 or starts with N\n- HiSilicon: hardware version starts with H (except H3MB18)\n\nGrain Media was\n[transferred](https://web.archive.org/web/20170703025339/https://www.grain-media.com/)\nto Novatek around 2017.\n",
    "bugtrack_url": null,
    "license": "",
    "summary": "Extract information and files from Reolink firmwares.",
    "version": "2.0.0",
    "project_urls": {
        "Issues": "https://github.com/AT0myks/reolink-fw/issues",
        "Source": "https://github.com/AT0myks/reolink-fw"
    },
    "split_keywords": [
        "reolink",
        "firmware"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "fd1ea45ec87acd10c3767b1812c7c9d851adbcf55df4d24b4a1c281799cc5eed",
                "md5": "10db412c99a9adfa4bc392960467e33b",
                "sha256": "6edaf5499f86aa90ad3d9edd207ac7853913257778c5060b555e0a8d4ecf121f"
            },
            "downloads": -1,
            "filename": "reolinkfw-2.0.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "10db412c99a9adfa4bc392960467e33b",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.9",
            "size": 32204,
            "upload_time": "2023-12-23T11:05:28",
            "upload_time_iso_8601": "2023-12-23T11:05:28.024344Z",
            "url": "https://files.pythonhosted.org/packages/fd/1e/a45ec87acd10c3767b1812c7c9d851adbcf55df4d24b4a1c281799cc5eed/reolinkfw-2.0.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "89afb17d6680549d9ee28c8a9ad0ae9f25311c33b34e5c567c78e47177fadfa7",
                "md5": "729c2abe8acf49a89560cdda97e6d4cf",
                "sha256": "ead2ffc75965d885d7f7d5fec76efe7a05b3f547524788773d07cd5dc0f5b058"
            },
            "downloads": -1,
            "filename": "reolinkfw-2.0.0.tar.gz",
            "has_sig": false,
            "md5_digest": "729c2abe8acf49a89560cdda97e6d4cf",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.9",
            "size": 33162,
            "upload_time": "2023-12-23T11:05:29",
            "upload_time_iso_8601": "2023-12-23T11:05:29.140108Z",
            "url": "https://files.pythonhosted.org/packages/89/af/b17d6680549d9ee28c8a9ad0ae9f25311c33b34e5c567c78e47177fadfa7/reolinkfw-2.0.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-12-23 11:05:29",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "AT0myks",
    "github_project": "reolink-fw",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "reolinkfw"
}
        
Elapsed time: 0.15464s