pax_global_header00006660000000000000000000000064146214131370014514gustar00rootroot0000000000000052 comment=da3cd53f056a7868fdffaa631e4e426847aec309 mfgtools-uuu_1.5.182/000077500000000000000000000000001462141313700144225ustar00rootroot00000000000000mfgtools-uuu_1.5.182/.github/000077500000000000000000000000001462141313700157625ustar00rootroot00000000000000mfgtools-uuu_1.5.182/.github/workflows/000077500000000000000000000000001462141313700200175ustar00rootroot00000000000000mfgtools-uuu_1.5.182/.github/workflows/build.yaml000066400000000000000000000030131462141313700217770ustar00rootroot00000000000000name: Build for x64 ubuntu on: push: branches: - master tags: - uuu* pull_request: types: - opened - synchronize jobs: build: name: Build for x64 ubuntu runs-on: ${{ matrix.os }} strategy: matrix: os: - ubuntu-20.04 - ubuntu-22.04 steps: - name: Checkout repository uses: actions/checkout@v3 with: fetch-depth: 0 - name: Set up environment run: sudo DEBIAN_FRONTEND=noninteractive apt-get --yes --force-yes install libusb-1.0-0-dev libbz2-dev libzstd-dev libtinyxml2-dev - name: Build run: | git fetch --tags --force # Retrieve annotated tags. #issue 290 if [ "${{ matrix.os }}" == "ubuntu-20.04" ]; then git submodule update --init tinyxml2; cd tinyxml2; cmake .; make; cd ..; fi; if [ "${{ matrix.os }}" == "ubuntu-20.04" ]; then cmake -D 'STATIC=1' -D 'FORCE_OLD=on' . ; else cmake .; fi; make - name: Upload Build Artifacts if: matrix.os == 'ubuntu-20.04' uses: actions/upload-artifact@v3 with: name: uuu path: ./uuu/uuu - name: Create or Update Release if: matrix.os == 'ubuntu-20.04' && github.ref_type == 'tag' uses: ncipollo/release-action@v1 with: name: Release ${{ github.ref_name }} tag: ${{ github.ref_name }} commit: ${{ github.sha }} allowUpdates: true prerelease: true artifacts: "./uuu/uuu" mfgtools-uuu_1.5.182/.github/workflows/build_arm.yaml000066400000000000000000000052631462141313700226470ustar00rootroot00000000000000name: Build for arm ubuntu on: push: branches: - master tags: - uuu* pull_request: types: - opened - synchronize jobs: build_job: # The host should always be linux runs-on: ubuntu-latest name: Build on ${{ matrix.distro }} ${{ matrix.arch }} # Run steps on a matrix of 4 arch/distro combinations strategy: matrix: include: - arch: aarch64 distro: ubuntu20.04 - arch: armv7 distro: ubuntu20.04 steps: - uses: actions/checkout@v3 with: fetch-depth: 0 - uses: uraimo/run-on-arch-action@v2 name: Build artifact id: build with: arch: ${{ matrix.arch }} distro: ${{ matrix.distro }} # Not required, but speeds up builds githubToken: ${{ github.token }} # Mount the artifacts directory as /artifacts in the container dockerRunArgs: | --volume "${PWD}:/mfgtools" # Pass some environment variables to the container env: | # YAML, but pipe character is necessary artifact_name: git-${{ matrix.distro }}_${{ matrix.arch }} # The shell to run commands with in the container shell: /bin/sh # Install some dependencies in the container. This speeds up builds if # you are also using githubToken. Any dependencies installed here will # be part of the container image that gets cached, so subsequent # builds don't have to re-install them. The image layer is cached # publicly in your project's package repository, so it is vital that # no secrets are present in the container state or logs. install: apt-get update -q -y; apt-get install -q -y libusb-1.0-0-dev libbz2-dev libzstd-dev pkg-config cmake libssl-dev g++ zlib1g-dev git libtinyxml2-dev # Produce a binary artifact and place it in the mounted volume run: | git config --global --add safe.directory /mfgtools cd /mfgtools cmake -D 'STATIC=1' . make - name: Rename run: cp uuu/uuu uuu_${{ matrix.arch }} - name: Upload Build Artifacts uses: actions/upload-artifact@v3 with: name: uuu_${{ matrix.arch }} path: uuu_${{ matrix.arch }} - name: Create or Update Release if: github.ref_type == 'tag' uses: ncipollo/release-action@v1 with: name: Release ${{ github.ref_name }} tag: ${{ github.ref_name }} commit: ${{ github.sha }} allowUpdates: true prerelease: true artifacts: "uuu_${{ matrix.arch }}" mfgtools-uuu_1.5.182/.github/workflows/doc.yaml000066400000000000000000000027521462141313700214560ustar00rootroot00000000000000name: Build pdf document on: push: branches: - master tags: - uuu* pull_request: types: - opened - synchronize jobs: build: name: Build for pdf runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v3 with: fetch-depth: 0 repository: nxp-imx/mfgtools.wiki.git path: wiki ref: master - name: Set up environment run: | sudo apt-get update sudo DEBIAN_FRONTEND=noninteractive apt-get --yes --force-yes install asciidoc rename - name: Build run: | cd wiki rename -f 's/\.asciidoc$//' * echo "" > UUU-docinfo.xml git log -n25 --reverse --format="format:%h%cd%an%s" >> UUU-docinfo.xml echo "" >> UUU-docinfo.xml a2x -L -a docinfo UUU - name: Upload Build Artifacts uses: actions/upload-artifact@v3 with: name: UUU.pdf path: wiki/UUU.pdf - name: Create or Update Release if: github.ref_type == 'tag' uses: ncipollo/release-action@v1 with: name: Release ${{ github.ref_name }} tag: ${{ github.ref_name }} commit: ${{ github.sha }} allowUpdates: true prerelease: true artifacts: "wiki/UUU.pdf" mfgtools-uuu_1.5.182/.github/workflows/macOS.yaml000066400000000000000000000032571462141313700217140ustar00rootroot00000000000000name: macOS Build on: push: branches: - master tags: - uuu* pull_request: types: - opened - synchronize jobs: build: name: macOS Build runs-on: ${{ matrix.os }} strategy: matrix: os: - macos-14 - macos-12 steps: - name: Checkout repository uses: actions/checkout@v3 with: fetch-depth: 0 - name: Set up environment run: brew install libusb pkg-config zstd tinyxml2 - name: Build run: | git fetch --tags --force # Retrieve annotated tags. #issue 290 export PATH="/usr/local/Cellar/pkg-config/0.29.2_3/bin:${PATH}"; pkg-config --list-all; cmake -DOPENSSL_ROOT_DIR=$(brew --prefix)/opt/openssl . ; make - name: Rename_x86 if: matrix.os == 'macos-12' run: cp uuu/uuu uuu_mac_x86 - name: Rename_arm if: matrix.os == 'macos-14' run: cp uuu/uuu uuu_mac_arm - name: Upload Build Artifacts if: matrix.os == 'macos-12' uses: actions/upload-artifact@v3 with: name: uuu_mac_x86 path: uuu_mac_x86 - name: Upload Build Artifacts if: matrix.os == 'macos-14' uses: actions/upload-artifact@v3 with: name: uuu_mac_arm path: uuu_mac_arm - name: Create or Update Release if: github.ref_type == 'tag' uses: ncipollo/release-action@v1 with: name: Release ${{ github.ref_name }} tag: ${{ github.ref_name }} commit: ${{ github.sha }} allowUpdates: true prerelease: true artifacts: "uuu_mac_*" mfgtools-uuu_1.5.182/.github/workflows/tar.yaml000066400000000000000000000034041462141313700214720ustar00rootroot00000000000000name: Create source package on: push: branches: - master tags: - uuu* pull_request: types: - opened - synchronize jobs: build: name: Create source package runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v3 with: fetch-depth: 0 submodules: true - name: Build run: | git archive --prefix "uuu-${{ github.ref_name }}/" -o "uuu_source-${{ github.ref_name }}.tar" HEAD ; git submodule foreach --recursive "git archive --prefix=uuu-${{ github.ref_name }}/\$path/ --output=\$sha1.tar HEAD && tar --concatenate --file=$(pwd)/uuu_source-${{ github.ref_name }}.tar \$sha1.tar && rm \$sha1.tar" mkdir uuu-${{ github.ref_name }}; git describe --tags --long >uuu-${{ github.ref_name }}/.tarball-version tar -r uuu-${{ github.ref_name }}/.tarball-version -f uuu_source-${{ github.ref_name }}.tar gzip uuu_source-${{ github.ref_name }}.tar tar xzf uuu_source-${{ github.ref_name }}.tar.gz && zip uuu_source-${{ github.ref_name }}.zip $(tar tf uuu_source-${{ github.ref_name }}.tar.gz) - name: Upload Build Artifacts uses: actions/upload-artifact@v3 with: name: uuu_source-${{ github.ref_name }}.tar.gz path: uuu_source-${{ github.ref_name }}.tar.gz - name: Create or Update Release if: github.ref_type == 'tag' uses: ncipollo/release-action@v1 with: name: Release ${{ github.ref_name }} tag: ${{ github.ref_name }} commit: ${{ github.sha }} allowUpdates: true prerelease: true artifacts: "uuu_source-${{ github.ref_name }}.tar.gz, uuu_source-${{ github.ref_name }}.zip" mfgtools-uuu_1.5.182/.github/workflows/win.yaml000066400000000000000000000030411462141313700214760ustar00rootroot00000000000000name: Build with VS Studio on: push: branches: - master tags: - uuu* pull_request: types: - opened - synchronize jobs: build: runs-on: windows-latest strategy: matrix: configuration: ['Debug', 'Release'] platform: ['x86', 'x64'] steps: - name: Checkout code uses: actions/checkout@v3 with: fetch-depth: 0 submodules: true - name: Set up Visual Studio uses: microsoft/setup-msbuild@v1.1 - name: Build static solution run: | git fetch --tags --force # Retrieve annotated tags. #issue 290 msbuild /p:Configuration=${{ matrix.configuration }} /p:PlatformToolset=v143 /p:Platform=${{ matrix.platform }} msvc/uuu-static-link.sln - name: Upload Build Artifacts if: matrix.configuration == 'Release' && matrix.platform == 'x64' uses: actions/upload-artifact@v3 with: name: uuu.exe path: msvc/x64/Release/uuu.exe - name: Create or Update Release if: matrix.configuration == 'Release' && matrix.platform == 'x64' && github.ref_type == 'tag' uses: ncipollo/release-action@v1 with: name: Release ${{ github.ref_name }} tag: ${{ github.ref_name }} commit: ${{ github.sha }} allowUpdates: true prerelease: true artifacts: msvc/x64/Release/uuu.exe - name: Build dynamic solution run: msbuild /p:Configuration=${{ matrix.configuration }} /p:PlatformToolset=v143 /p:Platform=${{ matrix.platform }} msvc/uuu.sln mfgtools-uuu_1.5.182/.gitignore000066400000000000000000000002101462141313700164030ustar00rootroot00000000000000Debug Release gitversion.h *.user .vs CMakeFiles *.cmake *.swp *.a *.so uuu/uuu Makefile CMakeCache.txt *.clst *.snap node_modules buildmfgtools-uuu_1.5.182/.gitmodules000066400000000000000000000006361462141313700166040ustar00rootroot00000000000000[submodule "libusb"] path = libusb url = https://github.com/libusb/libusb.git [submodule "zlib"] path = zlib url = https://github.com/madler/zlib.git [submodule "bzip2"] path = bzip2 url = git://sourceware.org/git/bzip2.git [submodule "zstd"] path = zstd url = https://github.com/facebook/zstd.git [submodule "tinyxml2"] path = tinyxml2 url = https://github.com/leethomason/tinyxml2.git branch = master mfgtools-uuu_1.5.182/.travis.yml000066400000000000000000000013111462141313700165270ustar00rootroot00000000000000language: c++ matrix: include: - os: osx osx_image: xcode9.4 compiler: clang - os: osx osx_image: xcode9.4 compiler: gcc - os: osx osx_image: xcode10.1 compiler: clang - os: osx osx_image: xcode10.1 compiler: gcc - os: osx osx_image: xcode11.6 compiler: clang - os: osx osx_image: xcode11.6 compiler: gcc addons: homebrew: update: true packages: - cmake - libusb - openssl - pkg-config script: - cmake -DOPENSSL_ROOT_DIR=$(brew --prefix)/opt/openssl . && make mfgtools-uuu_1.5.182/CMakeLists.txt000066400000000000000000000020201462141313700171540ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.4) project(uuu) set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_SKIP_RPATH ON) option(BUILD_DOC "Build documentation" OFF) add_subdirectory(libuuu) add_subdirectory(uuu) if (BUILD_DOC) # check if Doxygen is installed find_package(Doxygen) if (DOXYGEN_FOUND) # set input and output files set(DOXYGEN_IN ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in) set(DOXYGEN_OUT ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile) # request to configure the file configure_file(${DOXYGEN_IN} ${DOXYGEN_OUT} @ONLY) message("Doxygen build started") # note the option ALL which allows to build the docs together with the application add_custom_target( doc_doxygen ALL COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_OUT} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMENT "Generating documentation with Doxygen" VERBATIM ) else (DOXYGEN_FOUND) message("Doxygen need to be installed to generate the doxygen documentation") endif (DOXYGEN_FOUND) endif (BUILD_DOC) mfgtools-uuu_1.5.182/Doxyfile.in000066400000000000000000000010341462141313700165330ustar00rootroot00000000000000PROJECT_NAME = "uuu" PROJECT_BRIEF = "uuu (Universal Update Utility), mfgtools 3.0" DOXYFILE_ENCODING = UTF-8 OUTPUT_DIRECTORY = @CMAKE_CURRENT_BINARY_DIR@/docs/ INPUT = @CMAKE_CURRENT_SOURCE_DIR@/uuu/ @CMAKE_CURRENT_SOURCE_DIR@/libuuu/ RECURSIVE = YES EXTRACT_ALL = YES EXTRACT_PRIVATE = YES EXTRACT_PACKAGE = YES EXTRACT_STATIC = YES EXTRACT_LOCAL_CLASSES = YES EXTRACT_LOCAL_METHODS = YES CALL_GRAPH = YES CALLER_GRAPH = YES mfgtools-uuu_1.5.182/LICENSE000066400000000000000000000026761462141313700154420ustar00rootroot00000000000000Copyright 2018 NXP. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the Freescale Semiconductor nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. mfgtools-uuu_1.5.182/README.md000066400000000000000000000114141462141313700157020ustar00rootroot00000000000000# uuu (Universal Update Utility), mfgtools 3.0 [![macOS Build](https://github.com/nxp-imx/mfgtools/actions/workflows/macOS.yaml/badge.svg?branch=master)](https://github.com/nxp-imx/mfgtools/actions/workflows/macOS.yaml) [![Build with VS Studio](https://github.com/nxp-imx/mfgtools/actions/workflows/win.yaml/badge.svg)](https://github.com/nxp-imx/mfgtools/actions/workflows/win.yaml) [![Build for x64 ubuntu-lastest](https://github.com/nxp-imx/mfgtools/actions/workflows/build.yaml/badge.svg)](https://github.com/nxp-imx/mfgtools/actions/workflows/build.yaml) ![GitHub](https://img.shields.io/github/license/nxp-imx/mfgtools.svg) [![universal-update-utility](https://snapcraft.io/universal-update-utility/badge.svg)](https://snapcraft.io/universal-update-utility) Freescale/NXP I.MX Chip image deploy tools. **original linux version uses "linux" branch, windows version uses "windows" branch** uuu (universal update utility) for nxp imx chips -- libuuu-1.0.1-gffd9837 Succeded:0 Failed:3 Wait for Known USB Devices to Appear... 1:11 5/5 [ ] SDP: jump -f u-boot-dtb.imx -ivtinitramf.... 2:1 1/5 [===> ] SDP: boot -f u-boot-imx7dsabresd_sd.imx .... # Key features - The real cross platform. Linux, Windows, MacOS(not test yet) - Multi devices program support - Daemon mode support - Few dependencies (only libusb, zlibc, libbz2) - Firmware (uboot/kernel) uses WCID to auto load the winusb driver on the Windows side. Windows7 users need to install the winusb driver from https://zadig.akeo.ie/ Windows10 will install the driver automatically. # Examples: ``` uuu u-boot.imx Download u-boot.imx via HID device uuu list.uu Run all the commands in list.uu uuu -s Enter shell mode. Input command. uuu -v u-boot.imx verbose mode uuu -d u-boot.imx Once it detects the attachment of a known device, download boot.imx. u-boot.imx can be replaced, new file will be download once board reset. Do not unplug the SD card, write to the SD card, nor plug in a SD card when debugging uboot. uuu -b emmc u-boot.imx write u-boot.imx to emmc boot partition. u-boot.imx need enable fastboot uuu -b emmc_all wic.zst decompress wic.zst file and download the whole image into emmc ``` # Prebuilt Image and pdf document The prebuilt image and document are here: - https://github.com/nxp-imx/mfgtools/releases - **ubuntu 22.04, 'apt-get install uuu'** - UUU.pdf is snapshot of [wiki](https://github.com/nxp-imx/mfgtools/wiki) # How to Build: ## Windows - `git clone --recurse-submodules https://github.com/nxp-imx/mfgtools.git` - `cd mfgtools` - `open msvs/uuu.sln with Visual Studio 2017` Visual Studio Note that, since uuu is an OSI compliant Open Source project, you are entitled to download and use the freely available Visual Studio Community Edition to build, run or develop for uuu. As per the Visual Studio Community Edition license this applies regardless of whether you are an individual or a corporate user. ## Linux - `git clone https://github.com/nxp-imx/mfgtools.git` - `cd mfgtools` - `sudo apt-get install libusb-1.0-0-dev libbz2-dev libzstd-dev pkg-config cmake libssl-dev g++ zlib1g-dev libtinyxml2-dev` - `cmake . && make` The above commands build mfgtools in source. To build it out of source (requires cmake 3.13 or newer): - `cmake -S . -B build` - `cmake --build build --target all` For cmake prior 3.13: - `mkdir build && cd build` - `cmake .. && make` ## macOS - `git clone https://github.com/nxp-imx/mfgtools.git` - `cd mfgtools` - `brew install cmake libusb openssl pkg-config tinyxml2` - `cmake -DOPENSSL_ROOT_DIR=$(brew --prefix)/opt/openssl . && make` Note that we assume [brew](https://brew.sh) is installed and can be used to resolve dependencies as shown above. The remaining dependency `libbz2` can be resolved via the XCode supplied libraries. Note if you meet "can't detach kernel driver" try to check libusb version. ``` brew info libusb ==> libusb: stable 1.0.26 (bottled), HEAD ``` # Run environment - Windows 10 64 bit - Linux (Ubuntu) 64 bit - macOS (Catalina) - 32 bit systems will have problems with big files. # License uuu is licensed under the BSD license. See LICENSE. The BSD licensed prebuilt Windows binary version of uuu is statically linked with the LGPL libusb library, which remains LGPL. - bzip2 (BSD license) is from https://github.com/enthought/bzip2-1.0.6 - zlib (zlib license) is from https://github.com/madler/zlib.git - libusb (LGPL-2.1) is from https://github.com/libusb/libusb.git - zstd (Dual BSD\GPLv2 Licenses) is from https://github.com/facebook/zstd - tinyxml (zlib license) is from https://github.com/leethomason/tinyxml2 mfgtools-uuu_1.5.182/SCR-mfgtools.txt000066400000000000000000000031141462141313700174410ustar00rootroot00000000000000 Package: mfgtools.git Version: 3 Outgoing License: BSD-3-Clause License File: LICENSE Type of Content: source Description and comments: NXP I.MX Chip image deploy tools. Use uuu. Release Location: https://github.com/NXPmicro/mfgtools -b master Origin: NXP (BSD-3-clause) zlib (zlib) - https://github.com/madler/zlib libusb (LGPL-2.1) - https://github.com/libusb/libusb.git Android Open Source Project (Apache-2.0) [sparse_format.h] - https://developer.android.com/ Generated Binary: uuu, uuu.exe, uuu_mac Outgoing License: BSD-3-Clause Description and comments: NXP I.MX Chip image deploy tools Release Location: https://github.com/NXPmicro/mfgtools/releases Origin: NXP (BSD-3-clause) bzip2 (BSD-4-Clause) - https://github.com/enthought/bzip2-1.0.6 zlib (zlib) - https://github.com/madler/zlib zstd (BSD-3-clause) - https://github.com/facebook/zstd libusb (LGPL-2.1) - https://github.com/libusb/libusb.git Android Open Source Project (Apache-2.0) [sparse_format.h] - https://developer.android.com/ snapcraft.yaml allows uuu to be built by snap (MIT) - https://snapcraft.io/ create-react-app (MIT) - https://github.com/facebook/create-react-app/ mfgtools-uuu_1.5.182/appveyor.yml000066400000000000000000000133201462141313700170110ustar00rootroot00000000000000version: 1.5.{build} image: - Visual Studio 2019 - Visual Studio 2022 - Ubuntu1804 - macOS configuration: - Debug - Release platform: - x86 - x64 init: - sh: if [ "${CONFIGURATION}" = "Debug" ] ; then exit 0; fi - sh: if [ "${PLATFORM}" = "x86" ]; then exit 0; fi skip_tags: true install: - cmd: echo %APPVEYOR_BUILD_FOLDER% - cmd: git submodule update --init - cmd: cd %APPVEYOR_BUILD_FOLDER%\libusb - cmd: cd .. - sh: if [ "${APPVEYOR_BUILD_WORKER_IMAGE}" = "macOS" ]; then brew install libusb pkg-config zstd; fi - sh: if [ "${APPVEYOR_BUILD_WORKER_IMAGE}" != "macOS" ]; then sudo apt-get update; fi - sh: if [ "${APPVEYOR_BUILD_WORKER_IMAGE}" != "macOS" ]; then sudo DEBIAN_FRONTEND=noninteractive apt-get --yes --force-yes install libusb-1.0-0-dev libbz2-dev libzstd-dev asciidoc rename; fi build_script: # below powershell actions equals to retarget projects to newest SDK and tool v142 in visual studio 2019 - cmd: if "%APPVEYOR_BUILD_WORKER_IMAGE%" == "Visual Studio 2019" (set PLATFORMTOOLSET=v142) - cmd: if "%APPVEYOR_BUILD_WORKER_IMAGE%" == "Visual Studio 2022" (set PLATFORMTOOLSET=v143) - cmd: if "%APPVEYOR_BUILD_WORKER_IMAGE%" == "Visual Studio 2019" (msbuild %APPVEYOR_BUILD_FOLDER%/msvc/uuu.sln /p:PlatformToolset=%PLATFORMTOOLSET% /verbosity:minimal /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll") #coverity tool is only available to visual studio 2017 imagine in appveyor #- cmd: if "%APPVEYOR_BUILD_WORKER_IMAGE%" == "Visual Studio 2017" (cov-build --dir cov-int msbuild %APPVEYOR_BUILD_FOLDER%/msvc/uuu.sln /p:PlatformToolset=%PLATFORMTOOLSET% /verbosity:minimal /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll") #- cmd: if "%APPVEYOR_BUILD_WORKER_IMAGE%" == "Visual Studio 2017" (7z a -tzip mfg.zip cov-int) #- cmd: if "%APPVEYOR_BUILD_WORKER_IMAGE%" == "Visual Studio 2017" (curl --form token=%coverity_token% --form email=frank.li@nxp.com --form file=@mfg.zip --form version="automation test" --form description="testing coverity automation" https://scan.coverity.com/builds?project=NXPmicro%2Fmfgtools) - cmd: git clean -dxf . - cmd: msbuild %APPVEYOR_BUILD_FOLDER%/msvc/uuu-static-link.sln /p:PlatformToolset=%PLATFORMTOOLSET% /verbosity:minimal /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" - cmd: if exist %APPVEYOR_BUILD_FOLDER%\msvc\x64\release\uuu.exe cp %APPVEYOR_BUILD_FOLDER%\msvc\x64\release\uuu.exe %APPVEYOR_BUILD_FOLDER%\uuu.exe - sh: if [ "${APPVEYOR_BUILD_WORKER_IMAGE}" = "macOS" ]; then export PATH="/usr/local/Cellar/pkg-config/0.29.2_3/bin:${PATH}"; pkg-config --list-all; cmake -DOPENSSL_ROOT_DIR=$(brew --prefix)/opt/openssl; else cmake -D 'STATIC=1' .; fi - sh: make - sh: if [ "${APPVEYOR_BUILD_WORKER_IMAGE}" = "macOS" ]; then ls uuu; mv uuu/uuu uuu/uuu_mac; fi - sh: if [ "${APPVEYOR_BUILD_WORKER_IMAGE}" != "macOS" ]; then git submodule init; fi - sh: if [ "${APPVEYOR_BUILD_WORKER_IMAGE}" != "macOS" ]; then git submodule update; fi - sh: if [ "${APPVEYOR_BUILD_WORKER_IMAGE}" != "macOS" ]; then git archive --prefix "uuu-${APPVEYOR_BUILD_VERSION}/" -o "uuu_source-${APPVEYOR_BUILD_VERSION}.tar" HEAD ; fi - sh: if [ "${APPVEYOR_BUILD_WORKER_IMAGE}" != "macOS" ]; then git submodule foreach --recursive "git archive --prefix=uuu-${APPVEYOR_BUILD_VERSION}/\$path/ --output=\$sha1.tar HEAD && tar --concatenate --file=$(pwd)/uuu_source-${APPVEYOR_BUILD_VERSION}.tar \$sha1.tar && rm \$sha1.tar" ; fi - sh: if [ "${APPVEYOR_BUILD_WORKER_IMAGE}" != "macOS" ]; then mkdir uuu-${APPVEYOR_BUILD_VERSION}; git describe --tags --long >uuu-${APPVEYOR_BUILD_VERSION}/.tarball-version ; fi - sh: if [ "${APPVEYOR_BUILD_WORKER_IMAGE}" != "macOS" ]; then tar -r uuu-${APPVEYOR_BUILD_VERSION}/.tarball-version -f uuu_source-${APPVEYOR_BUILD_VERSION}.tar ; fi - sh: if [ "${APPVEYOR_BUILD_WORKER_IMAGE}" != "macOS" ]; then gzip uuu_source-${APPVEYOR_BUILD_VERSION}.tar; fi - sh: if [ "${APPVEYOR_BUILD_WORKER_IMAGE}" != "macOS" ]; then tar xzf uuu_source-${APPVEYOR_BUILD_VERSION}.tar.gz && zip uuu_source-${APPVEYOR_BUILD_VERSION}.zip $(tar tf uuu_source-${APPVEYOR_BUILD_VERSION}.tar.gz); fi - sh: if [ "${APPVEYOR_BUILD_WORKER_IMAGE}" != "macOS" ]; then git clone https://github.com/NXPmicro/mfgtools.wiki.git; fi - sh: if [ "${APPVEYOR_BUILD_WORKER_IMAGE}" != "macOS" ]; then cd mfgtools.wiki; fi - sh: if [ "${APPVEYOR_BUILD_WORKER_IMAGE}" != "macOS" ]; then rename -f 's/\.asciidoc$//' *; fi - sh: if [ "${APPVEYOR_BUILD_WORKER_IMAGE}" != "macOS" ]; then echo "" > UUU-docinfo.xml; fi - sh: if [ "${APPVEYOR_BUILD_WORKER_IMAGE}" != "macOS" ]; then git log -n25 --reverse --format="format:%h%cd%an%s" >> UUU-docinfo.xml; fi - sh: if [ "${APPVEYOR_BUILD_WORKER_IMAGE}" != "macOS" ]; then echo "" >> UUU-docinfo.xml; fi - sh: if [ "${APPVEYOR_BUILD_WORKER_IMAGE}" != "macOS" ]; then a2x -L -a docinfo UUU; fi - sh: if [ "${APPVEYOR_BUILD_WORKER_IMAGE}" = "macOS" ]; then pkg-config --cflags libzstd; fi artifacts: - path: uuu.exe - path: uuu/uuu - path: uuu/uuu_mac - path: mfgtools.wiki/UUU.pdf - path: uuu_source-${APPVEYOR_BUILD_VERSION}.tar.gz - path: uuu_source-${APPVEYOR_BUILD_VERSION}.zip before_deploy: - cmd: '' #deploy: #- provider: GitHub # description: prebuild for $(APPVEYOR_REPO_COMMIT) \n\n $(APPVEYOR_REPO_COMMIT_MESSAGE) # auth_token: # secure: SWWVkwSfPyVIaPChBBl+uAA3Fau9Rl5iNPQ9VRL8yyggXvc6wPcr/O9iXBMVM7Ju # artifact: uuu.exe; uuu/uuu; uuu/uuu_mac; mfgtools.wiki/UUU.pdf; uuu_source-${APPVEYOR_BUILD_VERSION}.tar.gz; uuu_source-${APPVEYOR_BUILD_VERSION}.zip # draft: true environment: coverity_token: secure: 5VvyV4fYfI6xPsqaeDHvBamkUmmVNjZj0J5pLLQ6NCw= mfgtools-uuu_1.5.182/bzip2/000077500000000000000000000000001462141313700154505ustar00rootroot00000000000000mfgtools-uuu_1.5.182/libusb/000077500000000000000000000000001462141313700157025ustar00rootroot00000000000000mfgtools-uuu_1.5.182/libuuu/000077500000000000000000000000001462141313700157275ustar00rootroot00000000000000mfgtools-uuu_1.5.182/libuuu/CMakeLists.txt000066400000000000000000000031411462141313700204660ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.4) set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_SKIP_RPATH ON) find_package(BZip2 REQUIRED) find_package(PkgConfig REQUIRED) pkg_check_modules(LIBUSB REQUIRED libusb-1.0>=1.0.16) pkg_check_modules(LIBZSTD REQUIRED libzstd) find_package(Threads) pkg_check_modules(TINYXML2 REQUIRED tinyxml2) if (STATIC) set(OPENSSL_USE_STATIC_LIBS TRUE) endif() find_package(OpenSSL) if(OPENSSL_FOUND) set(UUUSSL "-DUUUSSL") set(UUUOPENSLL_INCLUDE_DIR ${OPENSSL_INCLUDE_DIR}) endif() include_directories(${LIBUSB_INCLUDE_DIRS} ${LIBZSTD_INCLUDE_DIRS} ${UUUOPENSLL_INCLUDE_DIR} ${TINYXML2_INCLUDE_DIRS} include) if (FORCE_OLD) set(FORCE_OLDLIBUSB "-DFORCE_OLDLIBUSB") endif() set(CMAKE_CXX_FLAGS_DEBUG "-g -Wall -Wstrict-aliasing -Wextra ${UUUSSL} ${FORCE_OLDLIBUSB}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${UUUSSL} ${FORCE_OLDLIBUSB}") set(SOURCES error.cpp buffer.cpp cmd.cpp config.cpp notify.cpp sdps.cpp trans.cpp usbhotplug.cpp version.cpp sdp.cpp gitversion.h fastboot.cpp zip.cpp fat.cpp tar.cpp rominfo.cpp http.cpp hidreport.cpp sparse.cpp bmap.cpp ) set(generated_files_dir "${CMAKE_BINARY_DIR}/libuuu/gen") set(gitversion_h "${generated_files_dir}/gitversion.h") add_custom_command( OUTPUT gitversion.h PRE_BUILD COMMAND mkdir -p ${generated_files_dir} COMMAND sh -c 'cd ${CMAKE_CURRENT_SOURCE_DIR} && rm -f ${gitversion_h} && ./gen_ver.sh "${gitversion_h}.tmp" && mv -f "${gitversion_h}.tmp" "${gitversion_h}"' ) include_directories(${generated_files_dir}) #add_library( uuc SHARED ${SOURCES} )) add_library( uuc_s STATIC ${SOURCES} ) mfgtools-uuu_1.5.182/libuuu/backfile.h000066400000000000000000000032431462141313700176420ustar00rootroot00000000000000/* * Copyright 2020 NXP. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * Neither the name of the NXP Semiconductor nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #pragma once #include class Backfile { public: const std::string& get_filename() const noexcept { return m_filename; } protected: std::string m_filename; }; mfgtools-uuu_1.5.182/libuuu/bmap.cpp000066400000000000000000000072661462141313700173650ustar00rootroot00000000000000#include #include #include "bmap.h" #include "buffer.h" #include "libcomm.h" #include "libuuu.h" extern int g_verbose; bool bmap_t::is_mapped_block(size_t index) const { if (index >= m_gap_begin && index < m_gap_end) return false; if (index >= m_gap_end && index < m_next_gap_begin) return true; if (index >= m_blk_count) return false; m_gap_begin = 0; for(auto iter = m_blk_map.begin(); iter != m_blk_map.end(); ++iter) { m_gap_end = iter->first; m_next_gap_begin = iter->second + 1; if (index >= m_gap_begin && index < m_gap_end) return false; if (index >= m_gap_end && index < m_next_gap_begin) return true; m_gap_begin = m_next_gap_begin; } return true; } static bool parse_image_size(bmap_t &bmap, const tinyxml2::XMLElement* elem) { auto img_size = elem->Int64Text(); if (img_size <= 0) { set_last_err_string("Invalid image size."); return false; } bmap.set_image_size(img_size); return true; } static bool parse_block_size(bmap_t &bmap, const tinyxml2::XMLElement* elem) { auto blk_size = elem->Int64Text(); if (blk_size <= 0) { set_last_err_string("Invalid block size."); return false; } bmap.set_block_size(blk_size); return true; } static bool parse_blocks_count(bmap_t &bmap, const tinyxml2::XMLElement* elem) { auto blk_count = elem->Int64Text(); if (blk_count <= 0) { set_last_err_string("Invalid blocks count."); return false; } bmap.set_blocks_count(blk_count); return true; } static bool parse_block_map(bmap_t &bmap, const tinyxml2::XMLElement* elem) { for (auto ch = elem->FirstChildElement(); ch != nullptr; ch = ch->NextSiblingElement()) { if (strcmp(ch->Name(), "Range")) { continue; } std::string text = ch->GetText(); auto f = std::strtoul(text.data(), nullptr, 0); auto l = f; auto pos = text.find('-'); if (pos != std::string::npos) l = std::strtoul(text.data() + pos + 1, nullptr, 0); bmap.set_mapped_range(f, l); } return true; } static const std::map handlers{ { "ImageSize", parse_image_size }, { "BlockSize", parse_block_size }, { "BlocksCount", parse_blocks_count }, { "BlockMap", parse_block_map }, }; void send_info(std::string msg) { uuu_notify nt; nt.type = uuu_notify::NOTIFY_CMD_INFO; nt.str = (char*)msg.c_str(); call_notify(nt); } bool load_bmap(const std::string& filename, bmap_t& bmap) { tinyxml2::XMLDocument doc; auto fbuf = get_file_buffer(filename, true); if (fbuf == nullptr) { return -1; } auto dbuf = fbuf->request_data(0, fbuf->size()); if (dbuf == nullptr) { return -1; } auto err = doc.Parse((char*)dbuf->data(), dbuf->size()); if (err != tinyxml2::XML_SUCCESS) { return -1; } auto elem = doc.FirstChildElement(); if (!elem) { set_last_err_string("No bmap element"); return -1; } if (elem) { if (!elem->Attribute("version", "2.0")) { set_last_err_string("Invalid bmap version. 2.0 is expected."); return -1; } } for (auto ch = elem->FirstChildElement(); ch != nullptr; ch = ch->NextSiblingElement()) { auto it = handlers.find(ch->Name()); if (it == handlers.end()) continue; if (!it->second(bmap, ch)) return -1; } if (g_verbose) { auto info = std::string("\nUsing block map:") + "\n ImageSize: " + std::to_string(bmap.image_size()) + "\n BlockSize: " + std::to_string(bmap.block_size()) + "\n BlocksCount: " + std::to_string(bmap.blocks_count()) + "\n BlockMap:"; for (auto& r: bmap.mapped_ranges()) { if (r.first == r.second) info += "\n Range: " + std::to_string(r.first); else info += "\n Range: " + std::to_string(r.first) + "-" + std::to_string(r.second); } send_info(info + "\n"); } return true; } mfgtools-uuu_1.5.182/libuuu/bmap.h000066400000000000000000000027671462141313700170330ustar00rootroot00000000000000#pragma once #include #include struct bmap_t { using bmap_type = std::vector>; bmap_t() = default; // fully mapped image bmap_t(size_t img_size, size_t blk_size = 4096) : m_img_size(img_size), m_blk_size(blk_size), m_blk_count(default_blocks_count(img_size, blk_size)) { set_mapped_range(0, m_blk_count - 1); } bmap_t& set_image_size(size_t size) { m_img_size = size; return *this; } bmap_t& set_block_size(size_t size = 4096) { m_blk_size = size; return *this; } bmap_t& set_blocks_count(size_t size = 0) { if (size) m_blk_count = size; else m_blk_count = default_blocks_count(m_img_size, m_blk_size); return *this; } bmap_t& set_mapped_range(size_t begin, size_t end) { m_blk_map.emplace_back(begin, end); return *this; } static size_t default_blocks_count(size_t img_size, size_t blk_size) { return img_size / blk_size + (img_size % blk_size ? 1 : 0); } size_t image_size() const { return m_img_size; } size_t block_size() const { return m_blk_size; } size_t blocks_count() const { return m_blk_count; } const bmap_type& mapped_ranges() const { return m_blk_map; } bool is_mapped_block(size_t index) const; private: size_t m_img_size = 0; size_t m_blk_size = 4096; size_t m_blk_count = 0; bmap_type m_blk_map; mutable bool m_gap_set = false; mutable size_t m_gap_begin = 0; mutable size_t m_gap_end = 0; mutable size_t m_next_gap_begin = 0; }; bool load_bmap(const std::string& filename, bmap_t& bmap); mfgtools-uuu_1.5.182/libuuu/buffer.cpp000066400000000000000000001312221462141313700177050ustar00rootroot00000000000000/* * Copyright 2018-2022 NXP. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * Neither the name of the NXP Semiconductor nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #include #include "buffer.h" #include #include "liberror.h" #include #include #include "libcomm.h" #include "libuuu.h" #include "zip.h" #include "fat.h" #include "tar.h" #include #include "bzlib.h" #include "stdio.h" #include #include "http.h" #include "zstd.h" #include "libusb.h" #ifdef WIN32 #define stat_os _stat64 #elif defined(__APPLE__) #define stat_os stat #include "dirent.h" #else #define stat_os stat64 #include "dirent.h" #endif static map> g_filebuffer_map; static mutex g_mutex_map; static bool g_small_memory = true; #define MAGIC_PATH '>' string g_current_dir = ">"; void set_current_dir(const string &dir) { g_current_dir = MAGIC_PATH; g_current_dir += dir; } int DataBuffer:: resize(size_t sz) { if (m_allocate_way != ALLOCATION_WAYS::MALLOC) { set_last_err_string("data buffer ref can't resize"); assert(false); return -1; } if (sz > m_MemSize) { m_pDatabuffer = (uint8_t*)realloc(m_pDatabuffer, sz); if (!m_pDatabuffer) { set_last_err_string("fail alloc memory"); return -1; } m_MemSize = sz; } m_DataSize = sz; return 0; } int DataBuffer::ref_other_buffer(std::shared_ptr p, size_t offset, size_t size) { if (!p->IsRefable()) return -1; if (p->m_allocate_way == FileBuffer::ALLOCATION_WAYS::SEGMENT) { shared_ptr blk; blk = p->get_map_it(offset); if (offset + size < blk->m_output_offset + blk->m_actual_size) { m_pDatabuffer = blk->m_data.data() + offset - blk->m_output_offset; } else { return -1; } } else { m_pDatabuffer = p->data() + offset; } m_DataSize = size; m_allocate_way = ALLOCATION_WAYS::REF; m_ref = p; return 0; }; class FSBasic { public: friend class DataBuffer; friend class FileBuffer; virtual int get_file_timesample(const string &filename, uint64_t *ptime) = 0; virtual int load(const string &backfile, const string &filename, shared_ptr p) = 0; virtual bool exist(const string &backfile, const string &filename) = 0; virtual int for_each_ls(uuu_ls_file fn, const string &backfile, const string &filename, void *p) = 0; virtual int Decompress(const string& /*backfifle*/, shared_ptr /*outp*/) { return 0; }; virtual bool seekable(const string& /*backfile*/) { return false; } virtual std::shared_ptr ScanCompressblock(const string& /*backfile*/, size_t& /*input_offset*/, size_t& /*output_offset*/) { return NULL; }; virtual int PreloadWorkThread(shared_ptroutp); virtual int split(const string &filename, string *outbackfile, string *outfilename, bool dir=false) { string path = str_to_upper(filename); if (m_ext == nullptr || strlen(m_ext) == 0) { if(dir) { size_t pos = path.rfind("/"); if(pos == string::npos) { *outbackfile = MAGIC_PATH; *outbackfile += "./"; *outfilename = filename; } else { *outbackfile = filename.substr(0, pos); if(filename.size() >= pos + 1) *outfilename = filename.substr(pos + 1); else outfilename->clear(); } }else { *outbackfile = filename; } return 0; } string ext = m_ext; if(!dir) ext += "/"; size_t pos = path.rfind(ext); if (pos == string::npos) { string err = "can't find ext name in path: "; err += filename; set_last_err_string(err); return -1; } *outbackfile = filename.substr(0, pos + strlen(m_ext)); if(filename.size() >= pos + strlen(m_ext) + 1) *outfilename = filename.substr(pos + strlen(m_ext) + 1); else outfilename->clear(); return 0; } protected: const char * m_ext = nullptr; const char * m_Prefix = nullptr; public: bool m_small_pool = false; }; static class FSFlat: public FSBasic { public: FSFlat() { m_ext = ""; } int get_file_timesample(const string &filename, uint64_t *ptime) override { struct stat_os st; if (stat_os(filename.c_str() + 1, &st)) { set_last_err_string("stat_os failure"); return -1; } *ptime = st.st_mtime; return 0; } bool exist(const string &backfile, const string & /*filename*/) override { struct stat_os st; int off = 1; if (backfile[0] != MAGIC_PATH) off = 0; return stat_os(backfile.c_str() + off, &st) == 0 && ((st.st_mode & S_IFDIR) == 0); } int load(const string &backfile, const string &/*filename*/, shared_ptr p) override { struct stat_os st; if (stat_os(backfile.c_str() + 1, &st)) { set_last_err_string("stat_os failure"); return -1; } p->unmapfile(); if (p->mapfile(backfile.substr(1), st.st_size)) return -1; p->m_available_size = st.st_size; atomic_fetch_or(&p->m_dataflags, FILEBUFFER_FLAG_LOADED | FILEBUFFER_FLAG_NEVER_FREE); p->m_request_cv.notify_all(); return 0; } int for_each_ls(uuu_ls_file fn, const string &backfile, const string &filename, void *p) override { struct stat_os st; if(stat_os(backfile.c_str() + 1, &st)) { return -1; } if(st.st_mode & S_IFDIR) { #ifdef WIN32 string str = backfile.substr(1); if (filename.empty()) str += "/*"; else str += "/" + filename; WIN32_FIND_DATA fd; HANDLE handle = FindFirstFile(str.c_str(), &fd); BOOL b = false; do { if (handle == INVALID_HANDLE_VALUE) break; string path = backfile + "/" + fd.cFileName; if(fd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) path += "/"; fn(path.c_str() + 1, p); } while (FindNextFile(handle, &fd)); CloseHandle(handle); return 0; #else DIR *dir; dir = opendir(backfile.c_str() + 1); struct dirent *dp; while ((dp=readdir(dir)) != nullptr) { string name = dp->d_name; if(name.substr(0, filename.size()) == filename || filename.empty()) { string path = backfile + "/" + name; if(dp->d_type == DT_DIR) path += "/"; fn(path.c_str() + 1, p); } } closedir(dir); return 0; #endif }else { return fn(backfile.c_str() + 1, p); } } } g_fsflat; class FSNetwork : public FSBasic { protected: int m_Port; public: int split(const string &filename, string *outbackfile, string *outfilename, bool /*dir = false*/) override { if (m_Prefix == nullptr) return -1; if (filename.size() < strlen(m_Prefix)) return -1; string path = str_to_upper(filename); if (path.compare(1, strlen(m_Prefix), m_Prefix) == 0) { size_t pos; pos = filename.find('/', 1 + strlen(m_Prefix)); *outbackfile = filename.substr(1 + strlen(m_Prefix), pos - 1 - strlen(m_Prefix)); size_t cpos; cpos = outbackfile->find(':'); if (cpos != string::npos) { m_Port = str_to_uint32(outbackfile->substr(cpos + 1)); *outbackfile = outbackfile->substr(0, cpos); } *outfilename = filename.substr(pos); return 0; } return -1; } }; static class FSHttp : public FSNetwork { public: FSHttp() { m_Prefix = "HTTP://"; m_Port = 80; } int load(const string &backfile, const string &filename, shared_ptr p) override; virtual bool exist(const string &backfile, const string &filename) override { shared_ptr http = make_shared(); if (http->HttpGetHeader(backfile, filename, m_Port, typeid(*this) != typeid(FSHttp))) return false; return true; }; int for_each_ls(uuu_ls_file /*fn*/, const string &/*backfile*/, const string &/*filename*/, void * /*p*/) override { return 0; }; int get_file_timesample(const string &/*filename*/, uint64_t * /*ptime*/) override { return 0; }; int http_load(shared_ptr http, shared_ptr p, string filename); }g_fshttp; static class FSHttps : public FSHttp { public: FSHttps() { m_Prefix = "HTTPS://"; m_Port = 443; } }g_fshttps; int FSHttp::http_load(shared_ptr http, shared_ptr p, string filename) { size_t max = 0x10000; uuu_notify ut; ut.type = uuu_notify::NOTIFY_DOWNLOAD_START; ut.str = (char*)filename.c_str(); call_notify(ut); ut.type = uuu_notify::NOTIFY_TRANS_SIZE; ut.total = p->size(); call_notify(ut); for (size_t i = 0; i < p->size() && !p->m_reset_stream; i += max) { size_t sz = p->size() - i; if (sz > max) sz = max; if (http->HttpDownload((char*)(p->data() + i), sz) < 0) { atomic_fetch_or(&p->m_dataflags, FILEBUFFER_FLAG_ERROR_BIT); p->m_request_cv.notify_all(); return -1; } p->m_available_size = i + sz; p->m_request_cv.notify_all(); ut.type = uuu_notify::NOTIFY_TRANS_POS; ut.total = i + sz; call_notify(ut); } atomic_fetch_or(&p->m_dataflags, FILEBUFFER_FLAG_LOADED | FILEBUFFER_FLAG_NEVER_FREE); p->m_request_cv.notify_all(); ut.type = uuu_notify::NOTIFY_DOWNLOAD_END; ut.str = (char*)filename.c_str(); call_notify(ut); return 0; } class FSBackFile : public FSBasic { public: int get_file_timesample(const string &filename, uint64_t *ptime) override; }; static class FSZip : public FSBackFile { public: FSZip() { m_ext = ".ZIP"; }; int load(const string &backfile, const string &filename, shared_ptr p) override; bool exist(const string &backfile, const string &filename) override; int for_each_ls(uuu_ls_file fn, const string &backfile, const string &filename, void *p) override; }g_fszip; static class FSTar: public FSBackFile { public: FSTar() {m_ext = ".TAR"; }; int load(const string &backfile, const string &filename, shared_ptr p) override; bool exist(const string &backfile, const string &filename) override; int for_each_ls(uuu_ls_file fn, const string &backfile, const string &filename, void *p) override; }g_fstar; static class FSFat : public FSBackFile { public: FSFat() { m_ext = ".SDCARD"; }; int load(const string &backfile, const string &filename, shared_ptr p) override; bool exist(const string &backfile, const string &filename) override; int for_each_ls(uuu_ls_file fn, const string &backfile, const string &filename, void *p) override; }g_fsfat; class CommonStream { public: virtual int set_input_buff(void* p, size_t sz) = 0; virtual int set_output_buff(void* p, size_t sz) = 0; virtual size_t get_input_pos() = 0; virtual size_t get_output_pos() = 0; virtual int decompress() = 0; virtual size_t get_default_input_size() { return 0x1000; } virtual size_t decompress_size(const string& /*backfile*/) { return 0; } }; class FSCompressStream : public FSBackFile { public: FSCompressStream() { m_small_pool = g_small_memory; } int load(const string& backfile, const string& filename, shared_ptroutp) override; bool exist(const string& backfile, const string& filename) override; int for_each_ls(uuu_ls_file fn, const string &backfile, const string &filename, void *p) override; int Decompress(const string& backfile, shared_ptroutp) override; virtual std::shared_ptr create_stream() { return nullptr; }; }; class Bz2stream : public CommonStream { bz_stream m_strm; size_t m_in_size = 0; size_t m_out_size = 0; public: Bz2stream() { memset(&m_strm, 0, sizeof(m_strm)); BZ2_bzDecompressInit(&m_strm, 0, 0); } virtual ~Bz2stream() { BZ2_bzDecompressEnd(&m_strm); } virtual int set_input_buff(void* p, size_t sz) override { m_strm.next_in = (char*)p; m_strm.avail_in = m_in_size = sz; return 0; }; virtual int set_output_buff(void* p, size_t sz) override { m_strm.next_out = (char*)p; m_strm.avail_out = m_out_size = sz; return 0; }; virtual size_t get_input_pos() override { return m_in_size - m_strm.avail_in; }; virtual size_t get_output_pos() override { return m_out_size - m_strm.avail_out; }; virtual int decompress() override { return BZ2_bzDecompress(&m_strm); }; virtual size_t get_default_input_size() override { return 0x10000; } }; static class FSBz2 : public FSCompressStream { public: FSBz2() { m_ext = ".BZ2"; }; virtual bool seekable(const string& backfile) override; virtual std::shared_ptr create_stream() override { return std::make_shared(); } virtual std::shared_ptr ScanCompressblock(const string& backfile, size_t& input_offset, size_t& output_offset) override; }g_fsbz2; class Gzstream : public CommonStream { z_stream m_strm; size_t m_in_size = 0; size_t m_out_size = 0; public: Gzstream() { memset(&m_strm, 0, sizeof(m_strm)); inflateInit2(&m_strm, 15 + 16); } virtual ~Gzstream() { deflateEnd(&m_strm); } virtual int set_input_buff(void* p, size_t sz) override { m_strm.next_in = (Bytef*)p; m_strm.avail_in = m_in_size = sz; return 0; }; virtual int set_output_buff(void* p, size_t sz) override { m_strm.next_out = (Bytef*)p; m_strm.avail_out = m_out_size = sz; return 0; }; virtual size_t get_input_pos() override { return m_in_size - m_strm.avail_in; }; virtual size_t get_output_pos() override { return m_out_size - m_strm.avail_out; }; virtual int decompress() override { return inflate(&m_strm, Z_SYNC_FLUSH); }; virtual size_t get_default_input_size() override { return 0x10000; } }; static class FSGz : public FSCompressStream { public: FSGz() { m_ext = ".GZ"; }; virtual std::shared_ptr create_stream() { return std::make_shared(); } }g_fsgz; class ZstdStream:public CommonStream { ZSTD_DCtx* m_dctx; ZSTD_outBuffer m_output = { 0, 0, 0 }; ZSTD_inBuffer m_input = { 0, 0, 0 }; public: virtual int set_input_buff(void* p, size_t sz) override { m_input.src = p; m_input.pos = 0; m_input.size = sz; return 0; }; virtual int set_output_buff(void* p, size_t sz) override { m_output.dst = p; m_output.pos = 0; m_output.size = sz; return 0; }; virtual size_t get_input_pos() override { return m_input.pos; }; virtual size_t get_output_pos() override { return m_output.pos; }; virtual int decompress() override { return ZSTD_decompressStream(m_dctx, &m_output, &m_input); }; virtual size_t get_default_input_size() override { return ZSTD_DStreamInSize(); } size_t decompress_size(const string& backfile) override { shared_ptr inp = get_file_buffer(backfile, true); if (inp == nullptr) { return 0; } size_t sz = ZSTD_DStreamInSize(); shared_ptr pb = inp->request_data(0, sz); if (!pb) return 0; size_t decompressed_sz = ZSTD_getFrameContentSize(pb->data(), sz); return decompressed_sz; } ZstdStream() { m_dctx = ZSTD_createDCtx(); }; virtual ~ZstdStream() { ZSTD_freeDCtx(m_dctx); } }; static class FSzstd : public FSCompressStream { public: FSzstd() { m_ext = ".ZST"; }; virtual std::shared_ptr create_stream() { return make_shared(); }; }g_FSzstd; static class FS_DATA { public: vector m_pFs; FS_DATA() { m_pFs.push_back(&g_fsflat); m_pFs.push_back(&g_fszip); m_pFs.push_back(&g_fstar); m_pFs.push_back(&g_fsbz2); m_pFs.push_back(&g_fsfat); m_pFs.push_back(&g_fsgz); m_pFs.push_back(&g_FSzstd); m_pFs.push_back(&g_fshttps); m_pFs.push_back(&g_fshttp); } int get_file_timesample(const string &filename, uint64_t *ptimesample) { if (ptimesample == nullptr) { set_last_err_string("ptimesample is null\n"); return -1; } for (size_t i = 0; i < m_pFs.size(); i++) { if (!m_pFs[i]->get_file_timesample(filename, ptimesample)) return 0; } return -1; } int for_each_ls(uuu_ls_file fn, string path, void *p) { for (int i = m_pFs.size() -1; i >= 0; i--) { string back, filename; if (m_pFs[i]->split(path, &back, &filename, true) == 0) if(m_pFs[i]->for_each_ls(fn, back, filename, p)==0) { return 0; } } return 0; } bool exist(const string &filename) { for (size_t i = 0; i < m_pFs.size(); i++) { string back, fn; if (m_pFs[i]->split(filename, &back, &fn) == 0) if (m_pFs[i]->exist(back, fn)) return true; } return false; } bool need_small_mem(const string& filename) { for (size_t i = 0; i < m_pFs.size(); i++) { string back, fn; if (m_pFs[i]->split(filename, &back, &fn) == 0) if (m_pFs[i]->exist(back, fn)) return m_pFs[i]->m_small_pool; } return false; } int load(const string &filename, shared_ptr p) { for (size_t i = 0; i < m_pFs.size(); i++) { string back, fn; if (m_pFs[i]->split(filename, &back, &fn) == 0) { if (m_pFs[i]->load(back, fn, p) == 0) return 0; } } string err; err = "fail open file: "; err += filename; set_last_err_string(err); return -1; } }g_fs_data; int FSBackFile::get_file_timesample(const string &filename, uint64_t *ptime) { string back, file; if (split(filename, &back, &file)) return -1; return g_fs_data.get_file_timesample(back, ptime); } bool FSZip::exist(const string &backfile, const string &filename) { Zip zip; if (zip.Open(backfile)) return false; return zip.check_file_exist(filename); } int FSZip::for_each_ls(uuu_ls_file fn, const string &backfile, const string &filename, void *p) { Zip zip; if (zip.Open(backfile)) return -1; for(auto it = zip.m_filemap.begin(); it!=zip.m_filemap.end(); ++it) { if(it->first.substr(0, filename.size()) == filename || filename.empty()) { string name = backfile; name += "/"; name += it->first; fn(name.c_str()+1, p); } } return 0; } int zip_async_load(string zipfile, string fn, shared_ptr buff) { std::lock_guard lock(buff->m_async_mutex); Zip zip; if (zip.Open(zipfile)) return -1; if(zip.get_file_buff(fn, buff)) return -1; buff->m_available_size = buff->m_DataSize; atomic_fetch_or(&buff->m_dataflags, FILEBUFFER_FLAG_LOADED); buff->m_request_cv.notify_all(); return 0; } int FSZip::load(const string &backfile, const string &filename, shared_ptr p) { Zip zip; if (zip.Open(backfile)) return -1; if (!zip.check_file_exist(filename)) return -1; if(zip.get_file_buff(filename, p)) return -1; atomic_fetch_or(&p->m_dataflags, FILEBUFFER_FLAG_LOADED); p->m_request_cv.notify_all(); return 0; } bool FSTar::exist(const string &backfile, const string &filename) { Tar tar; if (tar.Open(backfile)) return false; return tar.check_file_exist(filename); } int FSTar::for_each_ls(uuu_ls_file fn, const string &backfile, const string &filename, void *p) { Tar tar; if (tar.Open(backfile)) return -1; for(auto it = tar.m_filemap.begin(); it!=tar.m_filemap.end(); ++it) { if(it->first.substr(0, filename.size()) == filename || filename.empty()) { string name = backfile; name += "/"; name += it->first; fn(name.c_str()+1, p); } } return 0; } int FSTar::load(const string &backfile, const string &filename, shared_ptr p) { Tar tar; if (tar.Open(backfile)) return -1; if (!tar.check_file_exist(filename)) return -1; if(tar.get_file_buff(filename, p)) return -1; p->m_available_size = p->m_DataSize; atomic_fetch_or(&p->m_dataflags, FILEBUFFER_FLAG_LOADED); p->m_request_cv.notify_all(); return 0; } bool FSFat::exist(const string &backfile, const string &filename) { Fat fat; if (fat.Open(backfile)) { return false; } return fat.m_filemap.find(filename) != fat.m_filemap.end(); } int FSFat::load(const string &backfile, const string &filename, shared_ptr p) { Fat fat; if (fat.Open(backfile)) { return -1; } if(fat.get_file_buff(filename, p)) return -1; atomic_fetch_or(&p->m_dataflags, FILEBUFFER_FLAG_LOADED); p->m_request_cv.notify_all(); return 0; } int FSFat::for_each_ls(uuu_ls_file fn, const string &backfile, const string &filename, void *p) { Fat fat; if (fat.Open(backfile)) { return -1; } for(auto it = fat.m_filemap.begin(); it != fat.m_filemap.end(); ++it) { if(it->first.substr(0, filename.size()) == filename || filename.empty()) { string name = backfile; name += "/"; name += it->first; fn(name.c_str()+1, p); } } return 0; } bool FSCompressStream::exist(const string &backfile, const string &filename) { if (!g_fs_data.exist(backfile)) return false; if (filename == "*") return true; return false; } int FSCompressStream::for_each_ls(uuu_ls_file fn, const string &backfile, const string &/*filename*/, void *p) { if(!g_fs_data.exist(backfile)) return -1; string str; str = backfile + "/*"; fn(str.c_str() + 1, p); return 0; } class Bz2FragmentBlock: public FragmentBlock { public: virtual ~Bz2FragmentBlock() {} int DataConvert() override { std::lock_guard lock(m_mutex); m_actual_size = m_output_size; m_data.resize(m_output_size); shared_ptr input = m_input->request_data(m_input_offset, m_input_sz); if (!input) return -1; unsigned int len = m_output_size; m_ret = BZ2_bzBuffToBuffDecompress((char*)m_data.data(), &len, (char*)input->data(), m_input_sz, 0, 0); m_actual_size = len; m_data.resize(m_actual_size); assert(m_output_size >= m_actual_size); atomic_fetch_or(&m_dataflags, (int)CONVERT_DONE); return m_ret; } }; shared_ptr FSBz2::ScanCompressblock(const string& backfile, size_t& input_offset, size_t& output_offset) { shared_ptr pbz; pbz = get_file_buffer(backfile, true); if (pbz == nullptr) { return NULL; } size_t request_size = 1 * 1000 * 1000; shared_ptr pd = pbz->request_data(input_offset, request_size); if (!pd) return NULL; uint8_t* p1 = pd->data(); size_t sz = min(request_size - 10, pd->size()); for (size_t i = 0; i < sz; i++) { uint16_t* header = (uint16_t*)p1++; if (*header == 0x5a42) //"BZ" { uint32_t* magic1 = (uint32_t*)&pd->at(i + 4); if (*magic1 == 0x26594131 && pd->at(i + 2) == 'h') //PI 3.1415926 { uint16_t* magic2 = (uint16_t*)&pd->at(i + 8); if (*magic2 == 0x5953) { shared_ptr p = shared_ptr(new Bz2FragmentBlock); p->m_input = pbz; p->m_actual_size = 0; p->m_dataflags = 0; p->m_input_offset = input_offset + i; p->m_output_offset = output_offset; p->m_output_size = (pd->at(i + 3) - '0') * 100 * 1000; /* not l024 for bz2 */ p->m_input_sz = request_size; input_offset += i + 8; output_offset += p->m_output_size; return p; } } } } return NULL; } bool FSBz2::seekable(const string& backfile) { shared_ptr file = get_file_buffer(backfile, true); shared_ptr p = file->request_data(0, 1024*1024); if (!p) return false; int header_num = 0; uint8_t* ptr = p->data(); for (size_t i = 0; i < p->size(); i++) { if (ptr[0] == 'B' && ptr[1] == 'Z' && ptr[2] == 'h' && ptr[4] == '1' && ptr[5] == 'A' && ptr[6] == 'Y' && ptr[7] == '&' && ptr[8] == 'S' && ptr[9] == 'Y') { header_num++; } ptr++; if (header_num > 1) return true; } return false; } int FSCompressStream::Decompress(const string& backfile, shared_ptroutp) { shared_ptr cs = create_stream(); if (!cs) return -1; ssize_t lastRet = 0; size_t outOffset = 0; shared_ptr inp = get_file_buffer(backfile, true); if (inp == nullptr) { return -1; } size_t sz = cs->decompress_size(backfile); if (sz) { outp->resize(sz); atomic_fetch_or(&outp->m_dataflags, FILEBUFFER_FLAG_KNOWN_SIZE); } std::shared_ptr buff; buff = inp->request_data(0, 0x1000); if (!buff) return -1; size_t offset = 0; uuu_notify ut; ut.type = uuu_notify::NOTIFY_DECOMPRESS_START; ut.str = (char*)backfile.c_str(); call_notify(ut); shared_ptr blk; blk = outp->get_map_it(0, true); if (!blk) blk = outp->request_new_blk(); { lock_guard l(outp->m_seg_map_mutex); outp->m_last_db = blk; } cs->set_output_buff(blk->data(), blk->m_output_size); while ((buff = inp->request_data(offset, cs->get_default_input_size()))) { if (!buff) return -1; //ZSTD_inBuffer input = { buff->data(), buff->size(), 0 }; cs->set_input_buff(buff->data(), buff->size()); /* Given a valid frame, zstd won't consume the last byte of the frame * until it has flushed all of the decompressed data of the frame. * Therefore, instead of checking if the return code is 0, we can * decompress just check if input.pos < input.size. */ while (cs->get_input_pos() < min(buff->size(), inp->m_DataSize - offset)) { /* The return code is zero if the frame is complete, but there may * be multiple frames concatenated together. Zstd will automatically * reset the context when a frame is complete. Still, calling * ZSTD_DCtx_reset() can be useful to reset the context to a clean * state, for instance if the last decompression call returned an * error. */ size_t old = cs->get_output_pos(); ssize_t const ret = cs->decompress(); //ZSTD_decompressStream(dctx, &output, &input); lastRet = min(lastRet, ret); outOffset += cs->get_output_pos() - old; if (ret < 0) { blk->m_ret = ret; set_last_err_string("decompress error"); outp->m_request_cv.notify_all(); return -1; } blk->m_ret = 0; blk->m_actual_size = cs->get_output_pos(); atomic_fetch_or(&blk->m_dataflags, (int)FragmentBlock::CONVERT_PARTIAL); ut.type = uuu_notify::NOTIFY_DECOMPRESS_POS; ut.index = outOffset; call_notify(ut); outp->m_available_size = outOffset; outp->m_request_cv.notify_all(); if (cs->get_output_pos() == blk->m_output_size) { atomic_fetch_or(&blk->m_dataflags, (int)FragmentBlock::CONVERT_DONE); if (!(cs->get_input_pos() == buff->size() && buff->size() == (inp->size() - offset))) { blk = outp->get_map_it(outOffset, true); if(!blk) blk = outp->request_new_blk(); cs->set_output_buff(blk->data(), blk->m_output_size); { lock_guard l(outp->m_seg_map_mutex); outp->m_last_db = blk; } } } if (outp->m_reset_stream) { outp->m_reset_stream = false; return -1; } } offset += cs->get_default_input_size(); } outp->resize(outOffset); atomic_fetch_or(&blk->m_dataflags, (int)FragmentBlock::CONVERT_DONE); atomic_fetch_or(&outp->m_dataflags, FILEBUFFER_FLAG_LOADED); outp->m_request_cv.notify_all(); if (lastRet < 0) return -1; return 0; } uint64_t get_file_timesample(string filename) { uint64_t time=0; g_fs_data.get_file_timesample(filename, &time); return time; } shared_ptr get_file_buffer(string filename, bool async) { filename = remove_quota(filename); if (!filename.empty() && filename[0] != MAGIC_PATH) { if (filename == "..") filename = g_current_dir.substr(0, g_current_dir.size() - 1); else filename = g_current_dir + filename; } string_ex path; path += filename; path.replace('\\', '/'); filename = path; bool find; { std::lock_guard lock(g_mutex_map); find = (g_filebuffer_map.find(filename) == g_filebuffer_map.end()); } if (find) { shared_ptr p(new FileBuffer); if (p->reload(filename, async)) return nullptr; { std::lock_guard lock(g_mutex_map); g_filebuffer_map[filename] = p; } return p; } else { shared_ptr p; { std::lock_guard lock(g_mutex_map); p= g_filebuffer_map[filename]; } if (p->m_timesample != get_file_timesample(filename)) if (p->reload(filename, async)) { return nullptr; } if (!p->IsLoaded() && !async) { std::lock_guard lock(p->m_async_mutex); if(p->m_async_thread.joinable()) p->m_async_thread.join(); if(!p->IsLoaded()) { return nullptr; } } return p; } } FileBuffer::FileBuffer() { m_pDatabuffer = nullptr; m_DataSize = 0; m_MemSize = 0; m_dataflags = 0; m_available_size = 0; } FileBuffer::FileBuffer(void *p, size_t sz) { m_pDatabuffer = nullptr; m_DataSize = 0; m_MemSize = 0; m_pDatabuffer = (uint8_t*)malloc(sz); m_MemSize = m_DataSize = sz; memcpy(m_pDatabuffer, p, sz); m_dataflags = 0; atomic_fetch_or(&m_dataflags, FILEBUFFER_FLAG_LOADED); } FileBuffer::~FileBuffer() { m_reset_stream = true; if(m_async_thread.joinable()) m_async_thread.join(); if (m_pDatabuffer) { if(m_allocate_way == ALLOCATION_WAYS::MMAP) unmapfile(); if(m_allocate_way == ALLOCATION_WAYS::MALLOC) free(m_pDatabuffer); } } int FileBuffer::mapfile(const string &filename, size_t sz) { #ifdef _MSC_VER m_Request.StructureVersion = REQUEST_OPLOCK_CURRENT_VERSION; m_Request.StructureLength = sizeof(REQUEST_OPLOCK_INPUT_BUFFER); m_Request.RequestedOplockLevel = (OPLOCK_LEVEL_CACHE_READ | OPLOCK_LEVEL_CACHE_HANDLE); m_Request.Flags = REQUEST_OPLOCK_INPUT_FLAG_REQUEST; REQUEST_OPLOCK_OUTPUT_BUFFER Response; m_OverLapped.hEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr); ResetEvent(m_OverLapped.hEvent); m_file_handle = CreateFile(filename.c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_OVERLAPPED, nullptr); if (m_file_handle == INVALID_HANDLE_VALUE) { string err = "Create File Failure "; err += filename; set_last_err_string(err); return -1; } BOOL bSuccess = DeviceIoControl(m_file_handle, FSCTL_REQUEST_OPLOCK, &m_Request, sizeof(m_Request), &Response, sizeof(Response), nullptr, &m_OverLapped); if (bSuccess || GetLastError() == ERROR_IO_PENDING) { m_file_monitor = thread(file_overwrite_monitor, filename, this); } m_file_map = CreateFileMapping(m_file_handle, nullptr, PAGE_READONLY, 0, 0, nullptr); if (m_file_map == INVALID_HANDLE_VALUE) { set_last_err_string("Fail create Map"); return -1; } m_pDatabuffer = (uint8_t *)MapViewOfFile(m_file_map, FILE_MAP_READ, 0, 0, sz); m_DataSize = sz; m_MemSize = sz; m_allocate_way = ALLOCATION_WAYS::MMAP; #else int fd = open(filename.c_str(), O_RDONLY); if (fd == -1) { string err; err += "xx Failure open file: "; err + filename; set_last_err_string(err); return -1; } m_pDatabuffer = (uint8_t *)mmap64(0, sz, PROT_READ, MAP_SHARED, fd, 0); if (m_pDatabuffer == MAP_FAILED) { m_pDatabuffer = nullptr; set_last_err_string("mmap failure\n"); return -1; } m_DataSize = sz; m_MemSize = sz; m_allocate_way = ALLOCATION_WAYS::MMAP; close(fd); #endif if (m_pDatabuffer) return 0; set_last_err_string("mmap file failure"); return -1; } int FileBuffer::ref_other_buffer(shared_ptr p, size_t offset, size_t size) { m_pDatabuffer = p->data() + offset; m_DataSize = m_MemSize = size; m_available_size = m_DataSize; m_allocate_way = ALLOCATION_WAYS::REF; m_ref = p; atomic_fetch_or(&m_dataflags, FILEBUFFER_FLAG_LOADED); return 0; } int FileBuffer::reload(string filename, bool async) { if(async) { if(!g_fs_data.exist(filename)) return - 1; if (g_fs_data.need_small_mem(filename)) m_allocate_way = ALLOCATION_WAYS::SEGMENT; if(m_async_thread.joinable()) m_async_thread.join(); m_dataflags = 0; m_async_thread = thread(&FS_DATA::load, &g_fs_data, filename, shared_from_this()); } else { if(g_fs_data.load(filename, shared_from_this())) return - 1; } m_timesample = get_file_timesample(filename); m_filename = filename; return 0; } int FileBuffer::request_data(std::vector &data, size_t offset, size_t sz) { int64_t ret; ret = request_data(data.data(), offset, sz); if (ret < 0) { data.clear(); return -1; } data.resize(ret); return 0; } void FileBuffer::truncate_old_data_in_pool() { if (!g_small_memory) return; std::unique_lock lock(this->m_seg_map_mutex); if (m_last_request_offset < m_total_buffer_size/2) return; size_t off = m_last_request_offset - m_total_buffer_size/2; for (auto it= m_seg_map.lower_bound(off); it != m_seg_map.end(); it++) { auto blk = it->second; std::unique_lock lock(blk->m_mutex); if ((blk->m_dataflags & FragmentBlock::CONVERT_DONE) /* && !(blk->m_dataflags & FragmentBlock::USING)*/ ) { blk->m_dataflags = 0; blk->m_actual_size = 0; vector v; blk->m_data.swap(v); } } } int64_t FileBuffer::request_data_from_segment(void *data, size_t offset, size_t sz) { size_t return_sz = 0; do { m_last_request_offset = offset; std::unique_lock lck(m_request_cv_mutex); shared_ptr blk; m_pool_load_cv.notify_all(); while (!(blk = get_map_it(offset))) { if (IsKnownSize()) { if(offset >= this->m_DataSize) return -1; } auto now = std::chrono::system_clock::now(); m_request_cv.wait_until(lck, now + 500ms); } do { shared_ptr last_decompress_db; { std::unique_lock lock(m_seg_map_mutex); last_decompress_db = m_last_db; } { /*lock hold*/ std::unique_lock lock(blk->m_mutex); if (blk->m_actual_size >= (offset + sz - blk->m_output_offset)) break; if (!(m_dataflags & FILEBUFFER_FLAG_PARTIAL_RELOADABLE)) { if (last_decompress_db) { if (offset < last_decompress_db->m_output_offset && !(blk->m_dataflags & FragmentBlock::CONVERT_DONE)) { m_reset_stream = true; break; } } } if (blk->m_ret) return -1; if ((blk->m_dataflags & FragmentBlock::CONVERT_DONE)) { atomic_fetch_or(&blk->m_dataflags, (int)FragmentBlock::USING); break; } } auto now = std::chrono::system_clock::now(); m_request_cv.wait_until(lck, now + 500ms); } while (1); if (m_reset_stream) { m_dataflags = 0; m_available_size = 0; this->m_async_thread.join(); m_reset_stream = false; this->reload(m_filename, true); continue; } { /*hold lock*/ std::unique_lock lock(blk->m_mutex); size_t off = offset - blk->m_output_offset; assert(offset >= blk->m_output_offset); size_t item_sz = blk->m_actual_size - off; if (off > blk->m_actual_size) return -1; if (item_sz >= sz) { memcpy(data, blk->data() + off, sz); atomic_fetch_and(&blk->m_dataflags, ~FragmentBlock::USING); return_sz += sz; return return_sz; } else if (item_sz == 0) { return return_sz; } else { memcpy(data, blk->m_data.data() + off, item_sz); data = ((uint8_t*)data) + item_sz; sz -= item_sz; offset += item_sz; return_sz += item_sz; } } } while (1); return -1; } int64_t FileBuffer::request_data(void *data, size_t offset, size_t sz) { bool needlock = false; int ret = 0; if (IsLoaded()) { if (offset >= this->size()) { set_last_err_string("request offset exceed memory size"); return -1; } if (this->m_allocate_way == FileBuffer::ALLOCATION_WAYS::SEGMENT) return request_data_from_segment(data, offset, sz); } else { if (this->m_allocate_way == FileBuffer::ALLOCATION_WAYS::SEGMENT) return request_data_from_segment(data, offset, sz); std::unique_lock lck(m_request_cv_mutex); while ((offset + sz > m_available_size) && !IsLoaded()) { if (IsError()) { set_last_err_string("Async request data error"); return -1; } m_request_cv.wait(lck); } if (IsLoaded()) { if (offset > m_available_size) { set_last_err_string("request offset execeed memory size"); return -1; } } needlock = true; } size_t size = sz; if (offset + size >= m_available_size) size = m_available_size - offset; if (needlock) m_data_mutex.lock(); if (this->data()) { memcpy(data, this->data() + offset, size); ret = size; } else { set_last_err_string("Out of memory"); ret = ERR_OUT_MEMORY; } if (needlock) m_data_mutex.unlock(); return ret; } std::shared_ptr FileBuffer::request_new_blk() { if (m_allocate_way == ALLOCATION_WAYS::SEGMENT) { if (m_seg_map.empty()) { std::shared_ptr p(new FragmentBlock); lock_guard lock(m_seg_map_mutex); p->m_output_size = m_seg_blk_size; p->m_data.resize(m_seg_blk_size); m_seg_map[0] = p; return p; } size_t offset; if (g_small_memory) { truncate_old_data_in_pool(); { lock_guard lock(m_seg_map_mutex); shared_ptr p = m_seg_map.begin()->second; offset = p->m_output_offset; } while (offset > m_last_request_offset + m_total_buffer_size) { if (m_reset_stream) return NULL; std::unique_lock lck(m_pool_load_cv_mutex); m_pool_load_cv.wait(lck); } } { lock_guard lock(m_seg_map_mutex); shared_ptr p = m_seg_map.begin()->second; offset = p->m_output_offset; } offset += m_seg_blk_size; std::shared_ptr p(new FragmentBlock); p->m_output_size = m_seg_blk_size; p->m_output_offset = offset; p->m_data.resize(m_seg_blk_size); { lock_guard lock(m_seg_map_mutex); m_seg_map[offset] = p; } return p; } else { std::shared_ptr p(new FragmentBlock); p->m_pData = this->m_pDatabuffer; p->m_output_size = this->m_MemSize; return p; } } std::shared_ptr FileBuffer::request_data(size_t offset, size_t sz) { shared_ptr p(new DataBuffer); if (IsLoaded() && IsRefable()) { if (offset >= this->size()) { set_last_err_string("request offset bigger than file size"); return nullptr; } size_t size = sz; if (offset + sz > this->size()) size = this->size() - offset; if (!p->ref_other_buffer(shared_from_this(), offset, size)) return p; } if (sz == SIZE_MAX) sz = size() - offset; p->resize(sz); int64_t ret = request_data(p->m_pDatabuffer, offset, sz); if (ret < 0) return nullptr; p->resize(ret); return p; } int FileBuffer::reserve(size_t sz) { assert(m_allocate_way == ALLOCATION_WAYS::MALLOC); if (sz > m_MemSize) { m_pDatabuffer = (uint8_t*)realloc(m_pDatabuffer, sz); m_MemSize = sz; if (m_pDatabuffer == nullptr) { set_last_err_string("Out of memory\n"); return -1; } } return 0; } int FileBuffer::resize(size_t sz) { if (this->m_allocate_way == ALLOCATION_WAYS::SEGMENT) { m_DataSize = sz; return 0; } if (this->m_allocate_way == ALLOCATION_WAYS::REF) { if (sz > m_DataSize) { assert(true); return 0; } m_DataSize = sz; return m_DataSize; } int ret = reserve(sz); m_DataSize = sz; return ret; } int FileBuffer::swap(FileBuffer &a) { std::swap(m_pDatabuffer, a.m_pDatabuffer); std::swap(m_DataSize, a.m_DataSize); std::swap(m_MemSize, a.m_MemSize); std::swap(m_allocate_way, a.m_allocate_way); return 0; } int FileBuffer::unmapfile() { if (m_pDatabuffer) { #ifdef _MSC_VER UnmapViewOfFile(m_pDatabuffer); m_pDatabuffer = nullptr; CloseHandle(m_file_map); CloseHandle(m_file_handle); SetEvent(m_OverLapped.hEvent); if (m_file_monitor.joinable()) m_file_monitor.join(); CloseHandle(m_OverLapped.hEvent); m_OverLapped.hEvent = m_file_map = m_file_handle = INVALID_HANDLE_VALUE; #else munmap(m_pDatabuffer, m_DataSize); #endif m_pDatabuffer = nullptr; } return 0; } bool check_file_exist(string filename, bool /*start_async_load*/) { string_ex fn; fn += remove_quota(filename); string_ex path; if (!fn.empty() && fn[0] != MAGIC_PATH) { if (fn == "..") path += g_current_dir.substr(0, g_current_dir.size() - 1); else path += g_current_dir + fn; } else { path = fn; } path.replace('\\', '/'); if (path.empty()) path += "./"; return g_fs_data.exist(path); } #ifdef WIN32 int file_overwrite_monitor(string filename, FileBuffer *p) { WaitForSingleObject(p->m_OverLapped.hEvent, INFINITE); string str; str = ">"; str += filename; if(p->m_pDatabuffer && p->get_m_allocate_way() == FileBuffer::ALLOCATION_WAYS::MMAP) { std::lock_guard lock(g_mutex_map); p->m_file_monitor.detach(); /*Detach itself, erase will delete p*/ if(g_filebuffer_map.find(str) != g_filebuffer_map.end()) g_filebuffer_map.erase(str); } return 0; } #endif int uuu_for_each_ls_file(uuu_ls_file fn, const char *file_path, void *p) { string_ex path; path +=">"; string f = file_path; if(f.size() == 0) { path += "./"; }else if( f[0] == '/') { path += "//"; }else { path += "./"; } path+=file_path; path.replace('\\', '/'); f = path; return g_fs_data.for_each_ls(fn, f, p); } int FSCompressStream::load(const string& backfile, const string& filename, shared_ptroutp) { if (!g_fs_data.exist(backfile)) { string str; str = "Failure open file:"; str += backfile; set_last_err_string(str); return -1; } if (filename != "*") { string star("/*"); string decompressed_name = backfile + star; shared_ptr decompressed_file = get_file_buffer(decompressed_name); Tar tar; tar.Open(decompressed_name); if (tar.get_file_buff(filename, outp)) return -1; outp->m_available_size = outp->m_DataSize; } if (seekable(backfile)) { size_t offset = 0; size_t decompress_off = 0; shared_ptr p; size_t total_size = 0; atomic_fetch_or(&outp->m_dataflags, FILEBUFFER_FLAG_PARTIAL_RELOADABLE); int nthread = thread::hardware_concurrency(); vector threads; for (int i = 0; i < nthread; i++) { threads.push_back(thread(&FSCompressStream::PreloadWorkThread, this, outp)); } while ((p = ScanCompressblock(backfile, offset, decompress_off))) { if (!p) return 0; { lock_guard lock(outp->m_seg_map_mutex); outp->m_seg_map[p->m_output_offset] = p; } outp->m_request_cv.notify_all(); outp->m_pool_load_cv.notify_all(); total_size = p->m_output_offset + p->m_output_size; if (outp->m_reset_stream) return -1; } outp->m_DataSize = total_size; atomic_fetch_or(&outp->m_dataflags, FILEBUFFER_FLAG_KNOWN_SIZE | FILEBUFFER_FLAG_SEG_DONE); outp->m_request_cv.notify_one(); for (int i = 0; i < nthread; i++) { threads[i].join(); } return 0; } return Decompress(backfile, outp); } int FSBasic::PreloadWorkThread(shared_ptroutp) { while (!outp->m_reset_stream) { size_t request_offset = outp->m_last_request_offset; { lock_guard lock(outp->m_seg_map_mutex); if (!outp->m_offset_request.empty()) { request_offset = outp->m_offset_request.front(); outp->m_offset_request.pop(); } } shared_ptr blk; { lock_guard lock(outp->m_seg_map_mutex); auto low = outp->m_seg_map.begin(); low = outp->m_seg_map.lower_bound(request_offset); int count = 0; while (low != outp->m_seg_map.end() ) { if (!(low->second->m_dataflags & (FragmentBlock::CONVERT_START))) break; low--; count++; if (g_small_memory && count >= 5) break; } if (low != outp->m_seg_map.end()) { if (!(low->second->m_dataflags & FragmentBlock::CONVERT_START)) { atomic_fetch_or(&low->second->m_dataflags, (int)FragmentBlock::CONVERT_START); blk = low->second; } } } if (!blk || (blk && (blk->m_dataflags & FragmentBlock::CONVERT_DONE)) ) { std::unique_lock lck(outp->m_pool_load_cv_mutex); outp->m_pool_load_cv.wait(lck); continue; } outp->truncate_old_data_in_pool(); if (blk->DataConvert() < 0) { // todo error handle; continue; } atomic_fetch_or(&blk->m_dataflags, (int)FragmentBlock::CONVERT_DONE); outp->m_request_cv.notify_all(); } return 0; } int FSHttp::load(const string& backfile, const string& filename, shared_ptr p) { shared_ptr http = make_shared(); if (http->HttpGetHeader(backfile, filename, m_Port, typeid(*this) == typeid(FSHttps))) return -1; size_t sz = http->HttpGetFileSize(); p->resize(sz); atomic_fetch_or(&p->m_dataflags, FILEBUFFER_FLAG_KNOWN_SIZE); p->m_request_cv.notify_all(); return http_load(http, p, backfile); } void uuu_set_small_mem(uint32_t val) { g_small_memory = !!val; } void clean_up_filemap() { for (auto it : g_filebuffer_map) { it.second->m_reset_stream = true; it.second->m_pool_load_cv.notify_all(); if (it.second->m_async_thread.joinable()) it.second->m_async_thread.join(); } g_filebuffer_map.clear(); } mfgtools-uuu_1.5.182/libuuu/buffer.h000066400000000000000000000204671462141313700173620ustar00rootroot00000000000000/* * Copyright 2018 NXP. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * Neither the name of the NXP Semiconductor nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #pragma once #include #include #include #include #include #include #include #include #include #include "liberror.h" #include #ifdef _MSC_VER #include #else #include #include #include #endif #ifdef __APPLE__ #define mmap64 mmap #endif #ifdef WIN32 class FileBuffer; int file_overwrite_monitor(std::string filename, FileBuffer *p); #endif //bit 0, data loaded //bit 1, data total size known #define FILEBUFFER_FLAG_LOADED_BIT 0x1 #define FILEBUFFER_FLAG_KNOWN_SIZE_BIT 0x2 #define FILEBUFFER_FLAG_ERROR_BIT 0x4 #define FILEBUFFER_FLAG_NEVER_FREE 0x8 #define FILEBUFFER_FLAG_PARTIAL_RELOADABLE 0x10 #define FILEBUFFER_FLAG_SEG_DONE 0x20 #define FILEBUFFER_FLAG_LOADED (FILEBUFFER_FLAG_LOADED_BIT|FILEBUFFER_FLAG_KNOWN_SIZE_BIT) // LOADED must be known size #define FILEBUFFER_FLAG_KNOWN_SIZE FILEBUFFER_FLAG_KNOWN_SIZE_BIT class FileBuffer; class FSBasic; class FragmentBlock { public: enum { CONVERT_DONE = 0x1, USING = 0x2, CONVERT_START = 0x4, CONVERT_PARTIAL = 0x8, }; size_t m_input_offset = 0; size_t m_input_sz = 0; std::shared_ptr m_input; size_t m_ret = 0; size_t m_actual_size = 0; size_t m_output_size = 0; size_t m_output_offset = 0; virtual int DataConvert() { return -1; }; std::vector m_data; std::mutex m_mutex; std::atomic_int m_dataflags{0}; uint8_t* m_pData = NULL; uint8_t* data() { if (m_pData) return m_pData; return m_data.data(); } virtual ~FragmentBlock() {} }; class DataBuffer : public std::enable_shared_from_this { enum class ALLOCATION_WAYS { MALLOC, REF, }; protected: ALLOCATION_WAYS get_m_allocate_way() const noexcept { return m_allocate_way; } uint8_t* m_pDatabuffer = NULL; size_t m_DataSize = 0; size_t m_MemSize = 0; std::shared_ptr m_ref; ALLOCATION_WAYS m_allocate_way = ALLOCATION_WAYS::MALLOC; public: DataBuffer() { m_allocate_way = ALLOCATION_WAYS::MALLOC; } DataBuffer(void* p, size_t sz) { m_allocate_way = ALLOCATION_WAYS::MALLOC; resize(sz); memcpy(data(), p, sz); } uint8_t* data() { return m_pDatabuffer; } size_t size() { return m_DataSize; } int resize(size_t sz); int ref_other_buffer(std::shared_ptr p, size_t offset, size_t size); uint8_t& operator[] (size_t index) { assert(m_pDatabuffer); assert(index < m_DataSize); return *(m_pDatabuffer + index); } uint8_t& at(size_t index) { return (*this)[index]; } virtual ~DataBuffer() { if (m_allocate_way == ALLOCATION_WAYS::MALLOC) { free(m_pDatabuffer); } } friend class FileBuffer; }; class FileBuffer: public std::enable_shared_from_this { public: friend class DataBuffer; friend class FSBase; friend class FSFlat; friend class FSHttps; friend class FSHttp; friend class FSGz; friend class FSzstd; friend class FSCompressStream; friend class Fat; friend class Tar; friend class Zip; friend class Zip_file_Info; enum class ALLOCATION_WAYS { MALLOC, MMAP, REF, VMALLOC, SEGMENT, }; std::mutex m_data_mutex; uint8_t *m_pDatabuffer; size_t m_DataSize; size_t m_MemSize; std::shared_ptr m_ref; int ref_other_buffer(std::shared_ptr p, size_t offset, size_t size); std::mutex m_async_mutex; std::map, std::greater> m_seg_map; std::mutex m_seg_map_mutex; std::queue m_offset_request; size_t m_last_request_offset = 0; std::condition_variable m_pool_load_cv; std::mutex m_pool_load_cv_mutex; std::shared_ptr m_last_db; size_t m_seg_blk_size = 0x800000; size_t m_total_buffer_size = 8 * m_seg_blk_size; std::atomic_bool m_reset_stream { false }; //used for continue decompress\loading only std::shared_ptr request_new_blk(); bool check_offset_in_seg(size_t offset, std::shared_ptr blk) { if (offset >= blk->m_output_offset && offset < blk->m_output_offset + blk->m_output_size) return true; return false; } std::shared_ptr get_map_it(size_t offset, bool alloc = false) { { std::lock_guard lock(m_seg_map_mutex); auto it = m_seg_map.lower_bound(offset); if ( it == m_seg_map.end()) return NULL; auto blk = it->second; if (check_offset_in_seg(offset, blk)) { if (alloc) { std::lock_guard lck(blk->m_mutex); blk->m_data.resize(blk->m_output_size); } return blk; } return NULL; } } void truncate_old_data_in_pool(); std::atomic_int m_dataflags; std::thread m_async_thread; std::atomic_size_t m_available_size; std::condition_variable m_request_cv; std::mutex m_request_cv_mutex; #ifdef WIN32 OVERLAPPED m_OverLapped; REQUEST_OPLOCK_INPUT_BUFFER m_Request; HANDLE m_file_handle; HANDLE m_file_map; std::thread m_file_monitor; #endif uint64_t m_timesample; FileBuffer(); FileBuffer(void*p, size_t sz); ~FileBuffer(); ALLOCATION_WAYS get_m_allocate_way() const noexcept { return m_allocate_way; } int64_t request_data(void * data, size_t offset, size_t sz); int request_data(std::vector &data, size_t offset, size_t sz); std::shared_ptr request_data(size_t offset, size_t sz); bool IsLoaded() const noexcept { return m_dataflags & FILEBUFFER_FLAG_LOADED_BIT; } bool IsRefable() const noexcept { return m_dataflags & FILEBUFFER_FLAG_NEVER_FREE; } bool IsKnownSize() const noexcept { return m_dataflags & FILEBUFFER_FLAG_KNOWN_SIZE_BIT; } bool IsError() const noexcept { return m_dataflags & FILEBUFFER_FLAG_ERROR_BIT; } int reload(std::string filename, bool async = false); size_t size() { if (IsKnownSize()) return m_DataSize; std::unique_lock lck(m_request_cv_mutex); while (!(m_dataflags & FILEBUFFER_FLAG_KNOWN_SIZE_BIT)) m_request_cv.wait(lck); return m_DataSize; } protected: uint8_t * data() noexcept { return m_pDatabuffer ; } uint8_t & operator[] (size_t index) { assert(m_pDatabuffer); assert(index < m_DataSize); return *(m_pDatabuffer + index); } uint8_t & at(size_t index) { return (*this)[index]; } int resize(size_t sz); int reserve(size_t sz); int swap(FileBuffer & a); int mapfile(const std::string &filename, size_t sz); int unmapfile(); //Read write lock; protected: int64_t request_data_from_segment(void* data, size_t offset, size_t sz); int m_pool_size = 10; std::string m_filename; private: ALLOCATION_WAYS m_allocate_way = ALLOCATION_WAYS::MALLOC; }; std::shared_ptr get_file_buffer(std::string filename, bool async=false); bool check_file_exist(std::string filename, bool start_async_load=true); void set_current_dir(const std::string &dir); bool IsMBR(std::shared_ptr p); size_t ScanTerm(std::shared_ptr p, size_t& pos, size_t offset = 512, size_t limited = 0x800000); void clean_up_filemap(); mfgtools-uuu_1.5.182/libuuu/cmd.cpp000066400000000000000000000605211462141313700172020ustar00rootroot00000000000000/* * Copyright 2018 NXP. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * Neither the name of the NXP Semiconductor nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include "cmd.h" #include "libcomm.h" #include "liberror.h" #include "libuuu.h" #include "config.h" #include "trans.h" #include "sdps.h" #include #include "buffer.h" #include "sdp.h" #include "fastboot.h" #include #include #include #include static CmdMap g_cmd_map; static CmdObjCreateMap g_cmd_create_map; static string g_cmd_list_file; static map> g_environment; int insert_env_variable(string key, string value) { g_environment[std::this_thread::get_id()][key] = value; return 0; } string get_env_variable(string key) { return g_environment[std::this_thread::get_id()][key]; } int clear_env() { return g_environment.erase(std::this_thread::get_id()); } bool is_env_exist(string key) { return g_environment[std::this_thread::get_id()].find(key) != g_environment[std::this_thread::get_id()].end(); } int get_string_in_square_brackets(const std::string &cmd, std::string &context); int parser_cmd_list_file(shared_ptr pbuff, CmdMap *pCmdMap = nullptr); std::string remove_square_brackets(const std::string &cmd); template void * create_object() { return new T; } typedef void * (*FN)(); FN g_fn = create_object; CmdCtx::~CmdCtx() { } CmdBase::~CmdBase() { } int CmdBase::parser(char *p) { size_t pos = 0; string param; if (parser_protocol(p, pos)) return -1; if (pos < m_cmd.size()) param = get_next_param(m_cmd, pos); size_t index = 0; while (pos < m_cmd.size()) { param = get_next_param(m_cmd, pos); struct Param *pp = nullptr; if (m_NoKeyParam) { if (index > m_param.size()) { set_last_err_string("More parameter then expected"); return -1; } pp = &(m_param[index]); index++; } else { for (size_t i = 0; i < m_param.size(); i++) { string key = string(m_param[i].key); if (compare_str(param, key, m_param[i].ignore_case)) { pp = &(m_param[i]); break; } } } if (pp == nullptr) { string err; err = "unknown Option"; err += param; set_last_err_string(err); return -1; } if (pp->type == Param::Type::e_uint32) { if (!m_NoKeyParam) param = get_next_param(m_cmd, pos); *(uint32_t*)pp->pData = str_to_uint32(param); } if (pp->type == Param::Type::e_uint64) { if (!m_NoKeyParam) param = get_next_param(m_cmd, pos); *(uint64_t*)pp->pData = str_to_uint64(param); } if (pp->type == Param::Type::e_string_filename) { if (!m_NoKeyParam) param = get_next_param(m_cmd, pos); *(string*)pp->pData = param; if (!check_file_exist(param)) return -1; } if (pp->type == Param::Type::e_string) { if (!m_NoKeyParam) param = get_next_param(m_cmd, pos); *(string*)pp->pData = remove_quota(param); } if (pp->type == Param::Type::e_bool) { *(bool*)pp->pData = true; } if (pp->type == Param::Type::e_null) { } } if (m_bCheckTotalParam) { if (index < m_param.size()) { string str; str += "Missed: "; str += m_param[index].Error; set_last_err_string(str); return -1; } } return 0; } int CmdBase::parser_protocol(char *p, size_t &pos) { if (p) m_cmd = *p; string prot = get_next_param(m_cmd, pos, ':'); string param; if (get_string_in_square_brackets(prot, param)) return -1; if (!param.empty()) { size_t param_pos = 0; string s = get_next_param(param, param_pos); if (s == "-t") { string timeout; timeout = get_next_param(param, param_pos); m_timeout = str_to_uint32(timeout); } else { string err; err = "Unknown option: "; err += s; err += " for protocol: "; err += remove_square_brackets(prot); set_last_err_string(err); return -1; } } return 0; } int CmdBase::dump() { uuu_notify nt; nt.type = uuu_notify::NOTIFY_CMD_INFO; string str = m_cmd; str += "\n"; nt.str = (char*)str.c_str(); call_notify(nt); return 0; } int CmdList::run_all(CmdCtx *p, bool dry) { CmdList::iterator it; int ret; uuu_notify nt; nt.type = uuu_notify::NOTIFY_CMD_TOTAL; nt.total = size(); call_notify(nt); int i = 0; for (it = begin(); it != end(); it++, i++) { uuu_notify nt; nt.type = uuu_notify::NOTIFY_CMD_INDEX; nt.index = i; call_notify(nt); nt.type = uuu_notify::NOTIFY_CMD_START; nt.str = (char *)(*it)->get_cmd().c_str(); call_notify(nt); if (dry) ret = (*it)->dump(); else ret = (*it)->run(p); nt.type = uuu_notify::NOTIFY_CMD_END; nt.status = ret; call_notify(nt); if (ret) return ret; if ((*it)->get_lastcmd()) break; } return ret; } int CmdMap::run_all(const std::string &protocol, CmdCtx *p, bool dry_run) { if (find(protocol) == end()) { set_last_err_id(-1); std::string err; err.append("Unknown Protocol:"); err.append(protocol); set_last_err_string(err); return -1; } return at(protocol)->run_all(p, dry_run); } string get_next_param(const string &cmd, size_t &pos, char separate) { string str; if (pos == string::npos) return str; if (pos >= cmd.size()) return str; //trim left space while (cmd[pos] == separate && pos < cmd.size()) pos++; bool quote = false; size_t end = string::npos; for (size_t s = pos; s < cmd.size(); s++) { if (cmd[s] == '"') quote = !quote; if (!quote && cmd[s] == separate) { end = s; break; } } if (end == cmd.npos) end = cmd.size(); str = cmd.substr(pos, end - pos); pos = end + 1; return str; } string remove_square_brackets(const string &cmd) { size_t sz=cmd.find('['); return cmd.substr(0, sz); } int get_string_in_square_brackets(const string &cmd, string &context) { size_t start = cmd.find('['); if (start == string::npos) { context.clear(); return 0; } size_t end = cmd.find(']', start); if (end == string::npos) { set_last_err_string("missed ]"); return -1; } context = cmd.substr(start + 1, end - start - 1); return 0; } template T str_to_uint(const std::string &str, bool * conversion_succeeded) { if (conversion_succeeded) *conversion_succeeded = false; int base = 10; if (str.size() > 2) { if (str.substr(0, 2).compare("0x") == 0) { base = 16; } } try { const auto tmp_val = std::stoull(str, nullptr, base); if (tmp_val <= MAX_VAL) { if (conversion_succeeded) *conversion_succeeded = true; return static_cast(tmp_val); } } catch (const std::invalid_argument &) { } catch (const std::out_of_range &) { } set_last_err_string("Conversion of string to unsigned failed"); return MAX_VAL; } uint16_t str_to_uint16(const string &str, bool * conversion_succeeded) { return str_to_uint(str, conversion_succeeded); } uint32_t str_to_uint32(const string &str, bool * conversion_succeeded) { return str_to_uint(str, conversion_succeeded); } uint64_t str_to_uint64(const string &str, bool * conversion_succeeded) { return str_to_uint(str, conversion_succeeded); } template shared_ptr new_cmd_obj(char *p) { return shared_ptr(new T(p)); } CmdObjCreateMap::CmdObjCreateMap() { (*this)["CFG:"] = new_cmd_obj; (*this)["SDPS:BOOT"] = new_cmd_obj; (*this)["SDP:DCD"] = new_cmd_obj; (*this)["SDP:JUMP"] = new_cmd_obj; (*this)["SDP:RDMEM"] = new_cmd_obj; (*this)["SDP:WRMEM"] = new_cmd_obj; (*this)["SDP:WRITE"] = new_cmd_obj; (*this)["SDP:STATUS"] = new_cmd_obj; (*this)["SDP:BOOT"] = new_cmd_obj; (*this)["SDP:BLOG"] = new_cmd_obj; (*this)["SDPU:JUMP"] = new_cmd_obj; (*this)["SDPU:WRITE"] = new_cmd_obj; (*this)["SDPU:BLOG"] = new_cmd_obj; (*this)["SDPV:JUMP"] = new_cmd_obj; (*this)["SDPV:WRITE"] = new_cmd_obj; (*this)["SDPV:BLOG"] = new_cmd_obj; (*this)["FB:GETVAR"] = new_cmd_obj; (*this)["FASTBOOT:GETVAR"] = new_cmd_obj; (*this)["FB:UCMD"] = new_cmd_obj; (*this)["FASTBOOT:UCMD"] = new_cmd_obj; (*this)["FB:CRC"] = new_cmd_obj; (*this)["FASTBOOT:CRC"] = new_cmd_obj; (*this)["FB:WRITE"] = new_cmd_obj; (*this)["FASTBOOT:WRITE"] = new_cmd_obj; (*this)["FB:ACMD"] = new_cmd_obj; (*this)["FASTBOOT:ACMD"] = new_cmd_obj; (*this)["FB:DOWNLOAD"] = new_cmd_obj; (*this)["FASTBOOT:DOWNLOAD"] = new_cmd_obj; (*this)["FB:UPLOAD"] = new_cmd_obj; (*this)["FASTBOOT:UPLOAD"] = new_cmd_obj; (*this)["FB:FLASH"] = new_cmd_obj; (*this)["FASTBOOT:FLASH"] = new_cmd_obj; (*this)["FB:ERASE"] = new_cmd_obj; (*this)["FASTBOOT:ERASE"] = new_cmd_obj; (*this)["FB:REBOOT"] = new_cmd_obj; (*this)["FASTBOOT:REBOOT"] = new_cmd_obj; (*this)["FB:OEM"] = new_cmd_obj; (*this)["FASTBOOT:OEM"] = new_cmd_obj; (*this)["FB:FLASHING"] = new_cmd_obj; (*this)["FASTBOOT:FLASHING"] = new_cmd_obj; (*this)["FB:SET_ACTIVE"] = new_cmd_obj; (*this)["FASTBOOT:SET_ACTIVE"] = new_cmd_obj; (*this)["FB:BOOT"] = new_cmd_obj; (*this)["FASTBOOT:BOOT"] = new_cmd_obj; (*this)["FB:CONTINUE"] = new_cmd_obj; (*this)["FASTBOOT:CONTINUE"] = new_cmd_obj; (*this)["FB:UPDATE-SUPER"] = new_cmd_obj; (*this)["FASTBOOT:UPDATE-SUPER"] = new_cmd_obj; (*this)["FB:CREATE-LOGICAL-PARTITION"] = new_cmd_obj; (*this)["FASTBOOT:CREATE-LOGICAL-PARTITION"] = new_cmd_obj; (*this)["FB:DELETE-LOGICAL-PARTITION"] = new_cmd_obj; (*this)["FASTBOOT:DELETE-LOGICAL-PARTITION"] = new_cmd_obj; (*this)["FB:RESIZE-LOGICAL-PARTITION"] = new_cmd_obj; (*this)["FASTBOOT:RESIZE-LOGICAL-PARTITION"] = new_cmd_obj; (*this)["FBK:UCMD"] = new_cmd_obj; (*this)["FBK:ACMD"] = new_cmd_obj; (*this)["FBK:SYNC"] = new_cmd_obj; (*this)["FBK:UCP"] = new_cmd_obj; (*this)["_ALL:DONE"] = new_cmd_obj; (*this)["_ALL:DELAY"] = new_cmd_obj; (*this)["_ALL:SH"] = new_cmd_obj; (*this)["_ALL:SHELL"] = new_cmd_obj; (*this)["_ALL:<"] = new_cmd_obj; (*this)["_ALL:@"] = new_cmd_obj; (*this)["_ALL:ERROR"] = new_cmd_obj; (*this)["_ALL:IF"] = new_cmd_obj; } shared_ptr create_cmd_obj(string cmd) { string param; size_t pos = 0; param = get_next_param(cmd, pos, ':'); param = remove_square_brackets(param); param += ":"; param = str_to_upper(param); if (g_cmd_create_map.find(param) == g_cmd_create_map.end()) { string s = param; param = get_next_param(cmd, pos); s += str_to_upper(param); if (g_cmd_create_map.find(s) != g_cmd_create_map.end()) return g_cmd_create_map[s]((char*)cmd.c_str()); string commoncmd = "_ALL:"; commoncmd += str_to_upper(param); if (g_cmd_create_map.find(commoncmd) != g_cmd_create_map.end()) return g_cmd_create_map[commoncmd]((char*)cmd.c_str()); } else { return g_cmd_create_map[param]((char*)cmd.c_str()); } string err; err = "Unknown Command:"; err += cmd; set_last_err_string(err); return nullptr; } int uuu_run_cmd(const char * cmd, int dry) { return run_cmd(nullptr, cmd, dry); } int run_cmd(CmdCtx *pCtx, const char * cmd, int dry) { shared_ptr p; p = create_cmd_obj(cmd); int ret; if (p == nullptr) return -1; uuu_notify nt; nt.type = uuu_notify::NOTIFY_CMD_TOTAL; nt.total = 1; call_notify(nt); nt.type = uuu_notify::NOTIFY_CMD_START; nt.str = (char *)p->get_cmd().c_str(); call_notify(nt); if (typeid(*p) != typeid(CfgCmd)) { size_t pos = 0; string c = cmd; string pro = get_next_param(c, pos, ':'); pro = remove_square_brackets(pro); pro += ":"; if (p->parser()) ret = -1; else { if (dry) { ret = p->dump(); }else { CmdUsbCtx ctx; if (pCtx == nullptr) { ret = ctx.look_for_match_device(pro.c_str()); if (ret) return ret; pCtx = &ctx; } ret = p->run(pCtx); } } } else { return ret = dry? p->dump() : p->run(nullptr); } nt.type = uuu_notify::NOTIFY_CMD_END; nt.status = ret; call_notify(nt); return ret; } int CmdDone::run(CmdCtx *) { uuu_notify nt; nt.type = uuu_notify::NOTIFY_DONE; call_notify(nt); return 0; } int CmdDelay::parser(char * /*p*/) { size_t pos = 0; string param = get_next_param(m_cmd, pos); if (param.find(':') != string::npos) param = get_next_param(m_cmd, pos); if (str_to_upper(param) != "DELAY") { string err = "Unknown Command:"; err += param; set_last_err_string(err); return -1; } string ms = get_next_param(m_cmd, pos); m_ms = str_to_uint32(ms); return 0; } int CmdDelay::run(CmdCtx *) { std::this_thread::sleep_for(std::chrono::milliseconds(m_ms)); return 0; } int CmdError::parser(char *p) { if (p) m_cmd = p; size_t pos = 0; string s; if (parser_protocol(p, pos)) return -1; s = get_next_param(m_cmd, pos); m_error = m_cmd.substr(pos); return 0; } int CmdError::run(CmdCtx * /*pCtx*/) { set_last_err_string(m_error); return -1; } int CmdShell::parser(char * p) { if (p) m_cmd = p; size_t pos = 0; string s; if (parser_protocol(p, pos)) return -1; m_protocol = m_cmd.substr(0, pos); s = get_next_param(m_cmd, pos); m_dyn = (s == "<"); if (pos != string::npos && pos < m_cmd.size()) m_shellcmd = m_cmd.substr(pos); return 0; } int CmdShell::run(CmdCtx*pCtx) { #ifndef WIN32 #define _popen popen #define _pclose pclose #endif FILE *pipe = _popen(m_shellcmd.c_str(), "r"); if (pipe == nullptr) { string err = "failure popen: "; err += m_shellcmd.c_str(); set_last_err_string(err); return -1; } string str; str.resize(256); while (fgets((char*)str.c_str(), str.size(), pipe)) { if (m_dyn) { string cmd; cmd = m_protocol; str.resize(strlen(str.c_str())); cmd += ' '; cmd += str; size_t pos = cmd.find_first_of("\r\n"); if (pos != string::npos) cmd = cmd.substr(0, pos); return run_cmd(pCtx, cmd.c_str(), 0); } uuu_notify nt; nt.type = uuu_notify::NOTIFY_CMD_INFO; nt.str = (char*)str.c_str(); call_notify(nt); } /* Close pipe and print return value of pPipe. */ if (feof(pipe)) { int ret = _pclose(pipe); string_ex str; str.format("\nProcess returned %d\n", ret);; if (ret) { set_last_err_string(str.c_str()); return ret; } } else { set_last_err_string("Error: Failed to read the end of the pipe.\n"); return -1; } return 0; } int CmdEnv::parser(char *p) { if (p) m_cmd = p; size_t pos = 0; if (parser_protocol(p, pos)) return -1; if (pos == string::npos || pos >= m_cmd.size()) return -1; m_unfold_cmd = m_cmd.substr(0, pos); m_unfold_cmd.append(" "); // read the '@' get_next_param(m_cmd, pos); auto cmd = m_cmd.substr(pos); regex expr { "@[0-9a-zA-Z_]+@" }; smatch result; auto last_pos = static_cast(cmd).begin(); auto cmd_end = static_cast(cmd).end(); while (regex_search(last_pos, cmd_end, result, expr)) { for (auto &i : result) { string key { i.first + 1, i.second - 1 }; auto value = [&key]() -> pair { #ifndef WIN32 auto ptr = getenv(key.c_str()); if (ptr) return {true, ptr}; return {true, "\0"}; #else size_t len; getenv_s(&len, nullptr, 0, key.c_str()); if (!len){ /* To have the same behavior as Linux when uuu is provided with variables in the way : -e var= * We return null char as windows cannot store empty environment variables */ return {true, "\0"}; } string value(len-1, '\0'); getenv_s(&len, &value[0], len, key.c_str()); return {true, value}; #endif }(); if (!value.first) { set_last_err_string("variable '" + key + "' is not defined"); return -1; } auto begin = value.second.begin(); auto end = value.second.end(); auto pos = find_if(begin, end, [](char c){ return c == '\r' || c == '\n'; }); m_unfold_cmd.append(&*last_pos, distance(last_pos, i.first)); m_unfold_cmd.append(begin, pos); last_pos = i.second; } } if(last_pos != cmd.end()) m_unfold_cmd.append(&*last_pos); return 0; } int CmdIf::parser(char *p) { if (p) m_cmd = p; string s; size_t pos = 0; if (parser_protocol(p, pos)) return -1; m_protocol = m_cmd.substr(0, pos); if (pos == string::npos || pos >= m_cmd.size()) return -1; s = get_next_param(m_cmd, pos); if (str_to_upper(s) != "IF") { string err = "Unknown command: "; err += s; set_last_err_string(s); return -1; } size_t lc = pos; get_next_param(m_cmd, pos); size_t end = m_cmd.find("then", pos); if (end == string::npos) { set_last_err_string("missed key word: then"); return -1; } m_condition = m_cmd.substr(lc, end - lc); m_true_cmd = m_cmd.substr(end + 4); return 0; } void CmdIf::build_map(CmdCtx*p) { string_ex s; s.format("0x%04X", p->m_config_item->m_vid); insert_env_variable("@VID@", s); s.format("0x%04X", p->m_config_item->m_pid); insert_env_variable("@PID@", s); s.format("0x%04X", p->m_current_bcd); insert_env_variable("@BCD@", s); insert_env_variable("@CHIP@", p->m_config_item->m_chip); } int CmdIf::run(CmdCtx *p) { string l, r; string cmp[] = { "==", "!=", "" }; int i = 0; for (i = 0; !cmp[i].empty(); i++) { size_t pos = m_condition.find(cmp[i], 0); if (pos != string::npos) { l = m_condition.substr(0, pos); r = m_condition.substr(pos + cmp[i].size() + 1); break; } } l = str_to_upper(trim(l)); r = str_to_upper(trim(r)); build_map(p); if (is_env_exist(l)) l = get_env_variable(l); if (is_env_exist(r)) r = get_env_variable(r); switch (i) { case 0: // == if (l != r) return 0; break; case 1: // != if (l == r) return 0; break; default: set_last_err_string("unknown if condition"); return -1; } //Pass condition check; string cmd = m_protocol; cmd += ' '; cmd += this->m_true_cmd; return run_cmd(p, cmd.c_str(), 0); } int CmdEnv::run(CmdCtx *p) { return run_cmd(p, m_unfold_cmd.c_str(), 0); } int run_cmds(const char *protocol, CmdCtx *p) { CmdMap cmdmap, *pCmdMap; if (!g_cmd_list_file.empty()) { shared_ptr pin = get_file_buffer(g_cmd_list_file); if (pin == nullptr) return -1; shared_ptr pbuff = pin->request_data(0, UINT64_MAX); if (!pbuff) return -1; if(parser_cmd_list_file(pbuff, &cmdmap)) return -1; pCmdMap = &cmdmap; } else { pCmdMap = &g_cmd_map; } if (pCmdMap->find(protocol) == pCmdMap->end()) { return 0; } return (*pCmdMap)[protocol]->run_all(p); } static int insert_one_cmd(const char * cmd, CmdMap *pCmdMap) { string s = cmd; size_t pos = 0; string pro = get_next_param(s, pos, ':'); pro = remove_square_brackets(pro); pro += ":"; pro = str_to_upper(pro); shared_ptr p = create_cmd_obj(s); if (p == nullptr) return -1; if (p->parser()) return -1; if (pCmdMap->find(pro) == pCmdMap->end()) { shared_ptr list(new CmdList); (*pCmdMap)[pro] = list; } (*pCmdMap)[pro]->push_back(p); return 0; } static int added_default_boot_cmd(const char *filename) { string str; str = "SDPS: boot -f "; str += "\""; str += filename; str += "\""; int ret = insert_one_cmd(str.c_str(), &g_cmd_map); if (ret) return ret; insert_one_cmd("SDPS: done", &g_cmd_map); str = "SDP: boot -f "; str += "\""; str += filename; str += "\""; ret = insert_one_cmd(str.c_str(), &g_cmd_map); if (ret) return ret; insert_one_cmd("SDP: done", &g_cmd_map); str = "SDPU: write -f "; str += "\""; str += filename; str += "\""; str += " -offset 0x57c00"; insert_one_cmd(str.c_str(), &g_cmd_map); insert_one_cmd("SDPU: jump", &g_cmd_map); insert_one_cmd("SDPU: done", &g_cmd_map); str = "SDPV: write -f "; str += "\""; str += filename; str += "\""; str += " -skipspl"; insert_one_cmd(str.c_str(), &g_cmd_map); insert_one_cmd("SDPV: jump", &g_cmd_map); insert_one_cmd("SDPV: done", &g_cmd_map); return 0; } int check_version(string str) { int x = 0; int ver = 0; for (size_t i = 0; i < str.size(); i++) { char c = str[i]; if (c >= '0' && c <= '9') { x *= 10; x += c - '0'; } if (c == '.' || i == str.size()-1 || c == '\n') { ver <<= 12; ver += x; x = 0; } } int cur = uuu_get_version(); if (ver > cur) { string str; str = "This version of uuu is too old, please download the latest one"; set_last_err_string(str); return -1; } return 0; } int uuu_run_cmd_script(const char * buff, int /*dry*/) { shared_ptr p(new DataBuffer((void*)buff, strlen(buff))); return parser_cmd_list_file(p); } int parser_cmd_list_file(shared_ptr pbuff, CmdMap *pCmdMap) { char uuu_version[] = "uuu_version"; string str; if (pCmdMap == nullptr) pCmdMap = &g_cmd_map; pCmdMap->clear(); for (size_t i = 0; i < pbuff->size(); i++) { uint8_t c = pbuff->at(i); if (c == '\r') continue; if(c != '\n') str.push_back(c); if (c == '\n' || c == 0 || i == pbuff->size() - 1) { if (str.substr(0, strlen(uuu_version)) == uuu_version) { if (check_version(str.substr(strlen(uuu_version), 10))) { return -1; } }else if (str.size() > 1) { if (str[0] != '#') if (insert_one_cmd(str.c_str(), pCmdMap)) return -1; } str.clear(); } } return 0; } int uuu_auto_detect_file(const char *filename) { string_ex fn; fn += remove_quota(filename); fn.replace('\\', '/'); if (fn.empty()) fn += "./"; string oldfn =fn; fn += "/uuu.auto"; shared_ptr buffer = get_file_buffer(fn); if (buffer == nullptr) { fn.clear(); fn += oldfn; size_t pos = str_to_upper(fn).find("ZIP"); if(pos == string::npos || pos != fn.size() - 3) { pos = str_to_upper(fn).find("SDCARD"); if (pos == string::npos || pos != fn.size() - 6) buffer = get_file_buffer(fn); //we don't try open a zip file here } if(buffer == nullptr) return -1; } string str= "uuu_version"; shared_ptr pData = buffer->request_data(0, UINT_MAX); if (!pData) return -1; void *p1 = pData->data(); void *p2 = (void*)str.data(); if (memcmp(p1, p2, str.size()) == 0) { size_t pos = fn.rfind('/'); if (pos != string::npos) set_current_dir(fn.substr(0, pos + 1)); g_cmd_list_file = fn.substr(pos+1); return parser_cmd_list_file(pData); } //flash.bin or uboot.bin return added_default_boot_cmd(fn.c_str()); } int notify_done(uuu_notify nt, void *p) { if(nt.type == uuu_notify::NOTIFY_DONE) *(std::atomic *) p = 1; if (nt.type == uuu_notify::NOTIFY_CMD_END && nt.status) *(std::atomic *) p = 1; return 0; } int uuu_wait_uuu_finish(int deamon, int dry) { std::atomic exit; exit = 0; if(dry) { for(auto it=g_cmd_map.begin(); it != g_cmd_map.end(); it++) { for(auto cmd = it->second->begin(); cmd != it->second->end(); cmd++) { (*cmd)->dump(); } } return 0; } if (!deamon) uuu_register_notify_callback(notify_done, &exit); if(polling_usb(exit)) return -1; clean_up_filemap(); return 0; } mfgtools-uuu_1.5.182/libuuu/cmd.h000066400000000000000000000121261462141313700166450ustar00rootroot00000000000000/* * Copyright 2018 NXP. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * Neither the name of the NXP Semiconductor nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #pragma once #include #include #include #include class ConfigItem; std::string get_next_param(const std::string &cmd, size_t &pos, char separate = ' '); class CmdCtx { public: CmdCtx() = default; CmdCtx(const CmdCtx&) = delete; CmdCtx& operator=(const CmdCtx&) = delete; virtual ~CmdCtx(); ConfigItem *m_config_item = nullptr; void *m_dev = nullptr; short m_current_bcd; }; class CmdUsbCtx : public CmdCtx { public: ~CmdUsbCtx() override; int look_for_match_device(const char * protocol); }; struct Param { enum class Type { e_uint32, e_uint64, e_bool, e_string, e_null, e_string_filename, }; const char * const key; const char * const Error; void *pData; const Type type; const bool ignore_case; Param(const char *ky, void *pD, Type tp, bool ignore = true, const char *error = nullptr) : key{ky}, Error{error}, pData{pD}, type{tp}, ignore_case{ignore} { } }; class CmdBase { public: CmdBase() = default; CmdBase(char *p) { if (p) m_cmd = p; } virtual ~CmdBase(); virtual int dump(); const std::string& get_cmd() const noexcept { return m_cmd; } bool get_lastcmd() const noexcept { return m_lastcmd; } void insert_param_info(const char *key, void *pD, Param::Type tp, bool ignore_case = true, const char* err = nullptr) { m_param.emplace_back(Param{key, pD, tp, ignore_case, err}); } virtual int parser_protocol(char *p, size_t &pos); virtual int parser(char *p = nullptr); virtual int run(CmdCtx *p) = 0; protected: bool m_bCheckTotalParam = false; std::string m_cmd; bool m_lastcmd = false; bool m_NoKeyParam = false; int m_timeout = 10000; private: std::vector m_param; }; using CreateCmdObj = std::shared_ptr (*) (char *); class CmdObjCreateMap:public std::map { public: CmdObjCreateMap(); }; class CmdDone :public CmdBase { public: CmdDone(char *p) :CmdBase(p) { m_lastcmd = true; } int run(CmdCtx *p) override; }; class CmdDelay :public CmdBase { public: CmdDelay(char *p) :CmdBase(p) {} int parser(char *p = nullptr) override; int run(CmdCtx *p) override; private: int m_ms = 0; }; class CmdError : public CmdBase { public: CmdError(char *p) :CmdBase(p) {} int parser(char *p = nullptr) override; int run(CmdCtx *p) override; private: std::string m_error; }; class CmdShell : public CmdBase { public: CmdShell(char *p) : CmdBase(p) {} int parser(char *p = nullptr) override; int run(CmdCtx *p) override; private: bool m_dyn = false; std::string m_protocol; std::string m_shellcmd; }; class CmdIf : public CmdBase { public: CmdIf(char *p) : CmdBase(p) {} int parser(char *p = nullptr) override; int run(CmdCtx *p) override; private: std::string m_condition; std::string m_protocol; std::string m_true_cmd; void build_map(CmdCtx *p); }; class CmdEnv : public CmdBase { public: using CmdBase::CmdBase; int parser(char *p = nullptr) override; int run(CmdCtx *p) override; private: std::string m_unfold_cmd; }; class CmdList : public std::vector> { public: int run_all(CmdCtx *p, bool dry_run = false); }; class CmdMap : public std::map> { public: int run_all(const std::string &protocol, CmdCtx *p, bool dry_run = false); }; class CfgCmd :public CmdBase { public: CfgCmd(char *cmd) :CmdBase(cmd) {} int parser(char * /*p*/) override { return 0; } int run(CmdCtx *p) override; }; int run_cmds(const char *protocol, CmdCtx *p); int run_cmd(CmdCtx *pCtx, const char * cmd, int dry); int insert_env_variable(std::string key, std::string value); std::string get_env_variable(std::string key); int clear_env(); bool is_evn_exist(std::string key); mfgtools-uuu_1.5.182/libuuu/config.cpp000066400000000000000000000161701462141313700177050ustar00rootroot00000000000000/* * Copyright 2018 NXP. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * Neither the name of the NXP Semiconductor nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #include "config.h" #include "cmd.h" #include "libcomm.h" #include "liberror.h" #include "libuuu.h" using namespace std; static Config g_config; constexpr uint16_t FSL_VID = 0x15A2; constexpr uint16_t NXP_VID = 0x1FC9; constexpr uint16_t BD_VID = 0x3016; Config::Config() { emplace_back(ConfigItem{"SDPS:", "MX8QXP", nullptr, NXP_VID, 0x012F, 0x0002}); emplace_back(ConfigItem{"SDPS:", "MX8QM", "MX8QXP", NXP_VID, 0x0129, 0x0002}); emplace_back(ConfigItem{"SDPS:", "MX8DXL", "MX8QXP", NXP_VID, 0x0147}); emplace_back(ConfigItem{"SDPS:", "MX28", nullptr, FSL_VID, 0x004f}); emplace_back(ConfigItem{"SDPS:", "MX815", nullptr, NXP_VID, 0x013E}); emplace_back(ConfigItem{"SDPS:", "MX865", "MX815", NXP_VID, 0x0146}); emplace_back(ConfigItem{"SDPS:", "MX8ULP", "MX815", NXP_VID, 0x014A}); emplace_back(ConfigItem{"SDPS:", "MX8ULP", "MX815", NXP_VID, 0x014B}); emplace_back(ConfigItem{"SDPS:", "MX93", "MX815", NXP_VID, 0x014E}); emplace_back(ConfigItem{"SDPS:", "MX91", "MX815", NXP_VID, 0x0159}); emplace_back(ConfigItem{"SDPS:", "MX95", nullptr, NXP_VID, 0x015D}); emplace_back(ConfigItem{"SDPS:", "MX95", nullptr, NXP_VID, 0x015C}); emplace_back(ConfigItem{"SDP:", "MX7D", nullptr, FSL_VID, 0x0076}); emplace_back(ConfigItem{"SDP:", "MX6Q", nullptr, FSL_VID, 0x0054}); emplace_back(ConfigItem{"SDP:", "MX6D", "MX6Q", FSL_VID, 0x0061}); emplace_back(ConfigItem{"SDP:", "MX6SL", "MX6Q", FSL_VID, 0x0063}); emplace_back(ConfigItem{"SDP:", "MX6SX", "MX6Q", FSL_VID, 0x0071}); emplace_back(ConfigItem{"SDP:", "MX6UL", "MX7D", FSL_VID, 0x007D}); emplace_back(ConfigItem{"SDP:", "MX6ULL", "MX7D", FSL_VID, 0x0080}); emplace_back(ConfigItem{"SDP:", "MX6SLL", "MX7D", NXP_VID, 0x0128}); emplace_back(ConfigItem{"SDP:", "MX7ULP", nullptr, NXP_VID, 0x0126}); emplace_back(ConfigItem{"SDP:", "MXRT106X", nullptr, NXP_VID, 0x0135}); emplace_back(ConfigItem{"SDP:", "MX8MM", "MX8MQ", NXP_VID, 0x0134}); emplace_back(ConfigItem{"SDP:", "MX8MQ", "MX8MQ", NXP_VID, 0x012B}); emplace_back(ConfigItem{"SDPU:", "SPL", "SPL", 0x0525, 0xB4A4, 0, 0x04FF}); emplace_back(ConfigItem{"SDPV:", "SPL1", "SPL", 0x0525, 0xB4A4, 0x0500, 0x9998}); emplace_back(ConfigItem{"SDPV:", "SPL1", "SPL", NXP_VID, 0x0151, 0x0500, 0x9998}); emplace_back(ConfigItem{"SDPU:", "SPL", "SPL", 0x0525, 0xB4A4, 0x9999, 0x9999}); /*old i.MX8 MQEVk use bcd 9999*/ emplace_back(ConfigItem{"SDPU:", "SPL", "SPL", BD_VID, 0x1001, 0, 0x04FF}); emplace_back(ConfigItem{"SDPV:", "SPL1", "SPL", BD_VID, 0x1001, 0x0500, 0x9998}); emplace_back(ConfigItem{"FBK:", nullptr, nullptr, 0x066F, 0x9AFE}); emplace_back(ConfigItem{"FBK:", nullptr, nullptr, 0x066F, 0x9BFF}); emplace_back(ConfigItem{"FBK:", nullptr, nullptr, NXP_VID, 0x0153}); emplace_back(ConfigItem{"FB:", nullptr, nullptr, 0x0525, 0xA4A5}); emplace_back(ConfigItem{"FB:", nullptr, nullptr, 0x18D1, 0x0D02}); emplace_back(ConfigItem{"FB:", nullptr, nullptr, BD_VID, 0x0001}); emplace_back(ConfigItem{"FB:", nullptr, nullptr, NXP_VID, 0x0152}); emplace_back(ConfigItem{"FB:", nullptr, nullptr, 0x0483, 0x0afb}); } int uuu_for_each_cfg(uuu_show_cfg fn, void *p) { for (const auto &configItem : g_config) { if (fn(configItem.m_protocol.c_str(), configItem.m_chip.c_str(), configItem.m_compatible.c_str(), configItem.m_vid, configItem.m_pid, configItem.m_bcdVerMin, configItem.m_bcdVerMax, p)) return -1; } return 0; } Config * get_config() noexcept { return &g_config; } ConfigItem * Config::find(uint16_t vid, uint16_t pid, uint16_t ver) { for (auto it = begin(); it != end(); it++) { if (vid == it->m_vid && pid == it->m_pid) { if (ver >= it->m_bcdVerMin && ver <= it->m_bcdVerMax) return &(*it); } } return nullptr; } Config Config::find(const string &pro) { Config items; for (auto it = begin(); it != end(); it++) { if (it->m_protocol == pro) items.emplace_back(*it); } return items; } int CfgCmd::run(CmdCtx *) { size_t pos = 0; string param; ConfigItem item; param = get_next_param(m_cmd, pos); if (str_to_upper(param) == "CFG:") param = get_next_param(m_cmd, pos); if (param.empty()) { set_last_err_string("Wrong param"); return -1; } item.m_protocol = str_to_upper(param); bool conversion_succeeded = false; while (pos < m_cmd.size()) { param = get_next_param(m_cmd, pos); if (param == "-pid") { param = get_next_param(m_cmd, pos); item.m_pid = str_to_uint16(param, &conversion_succeeded); if (!conversion_succeeded) return -1; continue; } if (param == "-vid") { param = get_next_param(m_cmd, pos); item.m_vid = str_to_uint16(param, &conversion_succeeded); if (!conversion_succeeded) return -1; continue; } if (param == "-bcdversion") { param = get_next_param(m_cmd, pos); item.m_bcdVerMin = item.m_bcdVerMax = str_to_uint16(param, &conversion_succeeded); if (!conversion_succeeded) return -1; continue; } if (param == "-bcdmin") { param = get_next_param(m_cmd, pos); item.m_bcdVerMin = str_to_uint16(param, &conversion_succeeded); if (!conversion_succeeded) return -1; continue; } if (param == "-bcdmax") { param = get_next_param(m_cmd, pos); item.m_bcdVerMax = str_to_uint16(param, &conversion_succeeded); if (!conversion_succeeded) return -1; continue; } if (param == "-chip") { param = get_next_param(m_cmd, pos); item.m_chip = param; continue; } if (param == "-compatible") { param = get_next_param(m_cmd, pos); item.m_compatible = param; continue; } } ConfigItem *pItem= g_config.find(item.m_vid, item.m_pid, item.m_bcdVerMax); if (pItem) *pItem = item; else g_config.emplace_back(item); return 0; } mfgtools-uuu_1.5.182/libuuu/config.h000066400000000000000000000044241462141313700173510ustar00rootroot00000000000000/* * Copyright 2018 NXP. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * Neither the name of the NXP Semiconductor nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #pragma once #include #include #include class ConfigItem { public: ConfigItem() = default; ConfigItem(const char *pro, const char *chip, const char *comp, uint16_t vid, uint16_t pid, uint16_t verLow = 0, uint16_t verUp = UINT16_MAX) : m_pid{pid}, m_vid{vid}, m_bcdVerMin{verLow}, m_bcdVerMax{verUp} { if (pro) m_protocol = pro; if (chip) m_chip = chip; if (comp) m_compatible = comp; } std::string m_protocol; std::string m_chip; std::string m_compatible; uint16_t m_pid = 0; uint16_t m_vid = 0; uint16_t m_bcdVerMin = 0; uint16_t m_bcdVerMax = UINT16_MAX; }; class Config :public std::vector { public: Config(); ConfigItem *find(uint16_t vid, uint16_t pid, uint16_t ver); Config find(const std::string &protocol); }; Config * get_config() noexcept; mfgtools-uuu_1.5.182/libuuu/error.cpp000066400000000000000000000046461462141313700175760ustar00rootroot00000000000000/* * Copyright 2018 NXP. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * Neither the name of the NXP Semiconductor nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #include "liberror.h" #include "libuuu.h" #include "libusb.h" #include #include using namespace std; static mutex g_last_error_str_mutex; static string g_last_error_str; static atomic g_last_err_id; static uint32_t g_debug_level; int get_libusb_debug_level() noexcept { return g_debug_level & 0xFFFF; } void uuu_set_debug_level(uint32_t mask) { g_debug_level = mask; #if LIBUSB_API_VERSION > 0x01000106 && !defined(FORCE_OLDLIBUSB) libusb_set_option(nullptr, LIBUSB_OPTION_LOG_LEVEL, get_libusb_debug_level()); #else libusb_set_debug(nullptr, get_libusb_debug_level()); #endif } const char * uuu_get_last_err_string() { lock_guard l(g_last_error_str_mutex); return g_last_error_str.c_str(); } void set_last_err_string(const string &str) { lock_guard l(g_last_error_str_mutex); g_last_error_str = str; } int uuu_get_last_err() { return g_last_err_id.load(); } void set_last_err_id(int id) { g_last_err_id = id; } mfgtools-uuu_1.5.182/libuuu/fastboot.cpp000066400000000000000000000634631462141313700202700ustar00rootroot00000000000000/* * Copyright 2018, 2022 NXP. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * Neither the name of the NXP Semiconductor nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ /* Android fastboot protocol define at https://android.googlesource.com/platform/system/core/+/master/fastboot/ */ #include #include "fastboot.h" #include "libcomm.h" #include "cmd.h" #include "buffer.h" #include "liberror.h" #include "libuuu.h" #include #include #include #include "sparse.h" #include "ffu_format.h" #include "libcomm.h" #include "trans.h" #include #include "rominfo.h" #include "zlib.h" #include "libusb.h" int FastBoot::Transport(string cmd, void *p, size_t size, vector *input) { if (m_pTrans->write((void*)cmd.data(), cmd.size())) return -1; char buff[65]; memset(buff, 0, 65); while ( strncmp(buff, "OKAY", 4) && strncmp(buff, "FAIL", 4)) { size_t actual; memset(buff, 0, 65); if (m_pTrans->read(buff, 64, &actual)) return -1; if (strncmp(buff, "DATA",4) == 0) { size_t sz; sz = strtoul(buff+4, nullptr, 16); if (input) { size_t rz, rsize = 0; input->resize(sz); while (rsize < sz) { if (m_pTrans->read(input->data() + rsize, sz - rsize, &rz)) { set_last_err_string("Error on DATA read!"); return -1; } rsize += rz; } } else { if (sz > size) sz = size; if (m_pTrans->write(p, sz)) return -1; } }else { string s; s = buff + 4; m_info += s; uuu_notify nt; nt.type = uuu_notify::NOTIFY_CMD_INFO; nt.str = buff + 4; call_notify(nt); } } if (strncmp(buff, "OKAY", 4) == 0) return 0; set_last_err_string(m_info); return -1; } int FBGetVar::parser(char *p) { if (p) m_cmd = p; size_t pos = 0; string param = get_next_param(m_cmd, pos); if (param.find(':') != string::npos) param = get_next_param(m_cmd, pos); if (str_to_upper(param) != "GETVAR") { string err = "Unknown Command:"; err += param; set_last_err_string(err); return -1; } m_var = get_next_param(m_cmd, pos); return 0; } int FBGetVar::run(CmdCtx *ctx) { BulkTrans dev; if (dev.open(ctx->m_dev)) return -1; FastBoot fb(&dev); string cmd; cmd = "getvar:"; cmd += m_var; if (fb.Transport(cmd, nullptr, 0)) return -1; m_val = fb.m_info; string key = "@"; key += str_to_upper(m_var); key += "@"; insert_env_variable(key, str_to_upper(fb.m_info)); return 0; } int FBCmd::parser(char *p) { if (p) m_cmd = p; size_t pos = 0; string s; if (parser_protocol(p, pos)) return -1; s = get_next_param(m_cmd, pos); if (str_to_upper(s) != str_to_upper(m_fb_cmd)) { string err = "Unknown command: "; err += s; set_last_err_string(s); return -1; } if(pos!=string::npos && pos < m_cmd.size()) m_uboot_cmd = m_cmd.substr(pos); return 0; } int FBCmd::run(CmdCtx *ctx) { BulkTrans dev{m_timeout}; if (dev.open(ctx->m_dev)) return -1; FastBoot fb(&dev); string cmd; cmd = m_fb_cmd; cmd += m_separator; cmd += m_uboot_cmd; if (fb.Transport(cmd, nullptr, 0)) return -1; return 0; } int FBPartNumber::run(CmdCtx *ctx) { BulkTrans dev{m_timeout}; if (dev.open(ctx->m_dev)) return -1; FastBoot fb(&dev); string_ex cmd; cmd.format("%s:%s:%08x", m_fb_cmd.c_str(), m_partition_name.c_str(), (uint32_t)m_Size); if (fb.Transport(cmd, nullptr, 0)) return -1; return 0; } int FBUpdateSuper::run(CmdCtx *ctx) { BulkTrans dev{m_timeout}; if (dev.open(ctx->m_dev)) return -1; FastBoot fb(&dev); string_ex cmd; cmd.format("%s:%s:%s", m_fb_cmd.c_str(), m_partition_name.c_str(), m_opt.c_str()); if (fb.Transport(cmd, nullptr, 0)) return -1; return 0; } int FBDownload::run(CmdCtx *ctx) { BulkTrans dev; if (dev.open(ctx->m_dev)) return -1; FastBoot fb(&dev); shared_ptr buff = get_file_buffer(m_filename); if (buff == nullptr) return -1; shared_ptr pdata = buff->request_data(0, SIZE_MAX); if (!pdata) return -1; string_ex cmd; cmd.format("download:%08x", pdata->size()); if (fb.Transport(cmd, pdata->data(), pdata->size())) return -1; return 0; } int FBUpload::run(CmdCtx* ctx) { BulkTrans dev; if (dev.open(ctx->m_dev)) return -1; FastBoot fb(&dev); string_ex cmd; if (m_var.length()) cmd.format("upload:%s", m_var.c_str()); else cmd.format("upload"); std::vector buff; if (fb.Transport(cmd, nullptr, buff.size(), &buff)) return -1; std::ofstream fout(m_filename, ios::out | ios::trunc | ios::binary); std::copy(buff.begin(), buff.end(), std::ostream_iterator(fout)); fout.flush(); fout.close(); return 0; } int FBCopy::parser(char *p) { if (p) m_cmd = p; size_t pos = 0; string s; s = get_next_param(m_cmd, pos); if (s.find(":") != s.npos) s = get_next_param(m_cmd, pos); if ((str_to_upper(s) != "UCP")) { string err = "Unknown command: "; err += s; set_last_err_string(s); return -1; } string source; string dest; source = get_next_param(m_cmd, pos); dest = get_next_param(m_cmd, pos); if (source.empty()) { set_last_err_string("ucp: source missed"); return -1; } if (dest.empty()) { set_last_err_string("ucp: destination missed"); return -1; } if (source.find("T:") == 0 || source.find("t:") == 0) { if (dest.find("T:") == 0 || dest.find("t:") == 0) { set_last_err_string("ucp just support one is remote file start with t:"); return -1; } m_target_file = source.substr(2); m_bDownload = false; //upload a file m_local_file = dest; } else if (dest.find("T:") == 0 || dest.find("t:") == 0) { m_target_file = dest.substr(2); m_bDownload = true; m_local_file = source; get_file_buffer(source, true); } else { set_last_err_string("ucp must a remote file name, start with t:"); return -1; } return 0; } int FBCopy::run(CmdCtx *ctx) { BulkTrans dev; if (dev.open(ctx->m_dev)) return -1; FastBoot fb(&dev); string_ex cmd; if(m_bDownload) { size_t i; shared_ptr pin = get_file_buffer(m_local_file); if (pin == nullptr) { return -1; } shared_ptr buff = pin->request_data(0, SIZE_MAX); if (!buff) return -1; cmd.format("WOpen:%s", m_target_file.c_str()); if (fb.Transport(cmd, nullptr, 0)) { if (fb.m_info == "DIR") { Path p; p.append(m_local_file); string target = m_target_file; target += "/"; target += p.get_file_name(); cmd.format("WOpen:%s", target.c_str()); if (fb.Transport(cmd, nullptr, 0)) return -1; } else { return -1; } } uuu_notify nt; nt.type = uuu_notify::NOTIFY_TRANS_SIZE; nt.total = buff->size(); call_notify(nt); for (i = 0; i < buff->size(); i += this->m_Maxsize_pre_cmd) { size_t sz = buff->size() - i; if (sz > m_Maxsize_pre_cmd) sz = m_Maxsize_pre_cmd; cmd.format("donwload:%08X", sz); if (fb.Transport(cmd, buff->data() + i, sz)) { if (fb.m_info == "EPIPE") set_last_err_string("pipe closed by target"); else set_last_err_string("target return unknown error"); cmd.format("Close"); if (fb.Transport(cmd, nullptr, 0)) return -1; return -1; } nt.type = uuu_notify::NOTIFY_TRANS_POS; nt.index = i; call_notify(nt); } nt.type = uuu_notify::NOTIFY_TRANS_POS; nt.index = buff->size(); call_notify(nt); } else { cmd.format("ROpen:%s", m_target_file.c_str()); if (fb.Transport(cmd, nullptr, 0)) return -1; uuu_notify nt; nt.type = uuu_notify::NOTIFY_TRANS_SIZE; size_t total = nt.total = strtoul(fb.m_info.c_str(), nullptr, 16); call_notify(nt); nt.index = 0; ofstream of; struct stat st; Path localfile; localfile.append(m_local_file); if (stat(localfile.c_str(), &st) == 0) { if (st.st_mode & S_IFDIR) { localfile += "/"; Path t; t.append(m_target_file); localfile += t.get_file_name(); } } of.open(localfile, ofstream::binary); if (!of) { string err; err = "Fail to open file"; err += localfile; set_last_err_string(err); } do { vector data; if (fb.Transport("upload", nullptr, 0, &data)) return -1; of.write((const char*)data.data(), data.size()); nt.type = uuu_notify::NOTIFY_TRANS_POS; nt.index += data.size(); call_notify(nt); if (data.size() == 0) break; } while (nt.index < total || total == 0 ); // If total is 0, it is stream nt.type = uuu_notify::NOTIFY_TRANS_POS; call_notify(nt); } cmd.format("Close"); if (fb.Transport(cmd, nullptr, 0)) return -1; return 0; } int FBFlashCmd::parser(char *p) { if (FBCmd::parser(p)) return -1; string subcmd = m_uboot_cmd; size_t pos = 0; m_partition = get_next_param(subcmd, pos); if (m_partition == "-raw2sparse") { m_raw2sparse = true; if (uuu_force_bmap()) m_use_bmap = true; m_partition = get_next_param(subcmd, pos); if (m_partition == "-no-bmap") { m_use_bmap = false; m_partition = get_next_param(subcmd, pos); } else if (m_partition == "-bmap") { m_use_bmap = true; m_bmap_filename = get_next_param(subcmd, pos); m_partition = get_next_param(subcmd, pos); } if (uuu_ignore_bmap()) m_use_bmap = false; } if (m_partition == "-scanterm") { m_scanterm = true; m_partition = get_next_param(subcmd, pos); } if (m_partition == "-S") { m_partition = get_next_param(subcmd, pos); bool conversion_success = false; m_sparse_limit = str_to_uint64(m_partition, &conversion_success); if (!conversion_success) { set_last_err_string("FB: flash failed to parse size argument given to -S: "s + m_partition); return -1; } m_partition = get_next_param(subcmd, pos); } if (m_partition == "-scanlimited") { m_partition = get_next_param(subcmd, pos); bool conversion_success = false; m_scan_limited = str_to_uint64(m_partition, &conversion_success); if (!conversion_success) { set_last_err_string("FB: flash failed to parse size argument given to -scanlimited: "s + m_partition); return -1; } m_partition = get_next_param(subcmd, pos); } if (pos == string::npos || m_partition.empty()) { set_last_err_string("Missed partition name"); return -1; } m_filename = get_next_param(subcmd, pos); if (m_filename.empty()) { set_last_err_string("Missed file name"); return -1; } if (!check_file_exist(m_filename)) { set_last_err_string("FB: image file not found"); return -1; } if (m_use_bmap && m_bmap_filename.size() && !check_file_exist(m_bmap_filename)) { set_last_err_string("FB: bmap file not found"); return -1; } if (m_use_bmap && m_bmap_filename.empty()) { m_bmap_filename = m_filename; auto p = m_bmap_filename.rfind('.'); if (p != string::npos) { m_bmap_filename.replace(p, string::npos, ".bmap"); if (check_file_exist(m_bmap_filename)) return 0; } m_bmap_filename = m_filename; m_bmap_filename.append(".bmap"); if (check_file_exist(m_bmap_filename)) return 0; m_use_bmap = false; } return 0; } int FBFlashCmd::flash(FastBoot *fb, void * pdata, size_t sz) { string_ex cmd; cmd.format("download:%08x", sz); if (fb->Transport(cmd, pdata, sz)) return -1; cmd.format("flash:%s", m_partition.c_str()); if (fb->Transport(cmd, nullptr, 0)) return -1; return 0; } int FBFlashCmd::flash_raw2sparse(FastBoot *fb, shared_ptr pdata, size_t max) { SparseFile sf; vector data; if (max > m_sparse_limit) max = m_sparse_limit; size_t block_size = m_bmap.block_size(); sf.init_header(m_bmap.block_size(), (max + block_size - 1) / block_size); data.resize(block_size); uuu_notify nt; bool bload = pdata->IsKnownSize(); nt.type = uuu_notify::NOTIFY_TRANS_SIZE; if (bload) nt.total = pdata->size(); else nt.total = 0; call_notify(nt); size_t i = 0; int r; while (!(r=pdata->request_data(data, i*block_size, block_size))) { int ret = sf.push_one_block(data.data(), !m_bmap.is_mapped_block(i)); if (ret) { if (flash(fb, sf.m_data.data(), sf.m_data.size())) return -1; sf.init_header(block_size, (max + block_size - 1) / block_size); chunk_header_t ct; ct.chunk_type = CHUNK_TYPE_DONT_CARE; ct.chunk_sz = i + 1; ct.reserved1 = 0; ct.total_sz = sizeof(ct); sf.push_one_chuck(&ct, nullptr); nt.type = uuu_notify::NOTIFY_TRANS_POS; nt.total = i * block_size; call_notify(nt); } i++; if (bload != pdata->IsKnownSize()) { nt.type = uuu_notify::NOTIFY_TRANS_SIZE; nt.total = pdata->size(); call_notify(nt); bload = pdata->IsKnownSize(); } } if (r == ERR_OUT_MEMORY) return r; if (flash(fb, sf.m_data.data(), sf.m_data.size())) return -1; nt.type = uuu_notify::NOTIFY_TRANS_SIZE; nt.total = pdata->size(); call_notify(nt); nt.type = uuu_notify::NOTIFY_TRANS_POS; nt.total = pdata->size(); call_notify(nt); return 0; } int FBFlashCmd::run(CmdCtx *ctx) { FBGetVar getvar((char*)"FB: getvar max-download-size"); if (getvar.parser(nullptr)) return -1; if (getvar.run(ctx)) return -1; size_t max = getvar.m_val.empty() ? m_sparse_limit : str_to_uint32(getvar.m_val); BulkTrans dev{m_timeout}; if (dev.open(ctx->m_dev)) return -1; FastBoot fb(&dev); if (m_raw2sparse) { // fully mapped image if (!m_use_bmap) { size_t block_size = 4096; if (getvar.parser((char*)"FB: getvar logical-block-size")) return -1; if (!getvar.run(ctx)) block_size = str_to_uint32(getvar.m_val); if (block_size == 0) { set_last_err_string("Device report block_size is 0"); return -1; } m_bmap = bmap_t{SIZE_MAX, block_size}; // load mappings from the file } else if (!load_bmap(m_bmap_filename, m_bmap)) { set_last_err_string("Failed to load BMAP"); return -1; } shared_ptr pdata = get_file_buffer(m_filename, true); if (pdata == nullptr) return -1; if (isffu(pdata)) { string str; str = "FB: getvar partition-size:"; str += m_partition; if (getvar.parser((char*)str.c_str())) return -1; if (getvar.run(ctx)) return -1; m_totalsize = str_to_uint64(getvar.m_val); return flash_ffu(&fb, pdata); } return flash_raw2sparse(&fb, pdata, max); } shared_ptr pin = get_file_buffer(m_filename, true); if (pin == nullptr) return -1; shared_ptr pb = pin->request_data(0, sizeof(sparse_header)); if (!pb) return -1; if (SparseFile::is_validate_sparse_file(pb->data(), sizeof(sparse_header))) { /* Limited max size to 16M for sparse file to avoid long timeout at read status*/ if (max > m_sparse_limit) max = m_sparse_limit; } if (m_scanterm) { pb = pin->request_data(0, m_scan_limited); if (!pb) return -1; size_t length,pos=0; if (IsMBR(pb)) { length = ScanTerm(pb, pos); if (length == 0) { set_last_err_string("This wic have NOT terminate tag after bootloader, please use new yocto"); return -1; } ssize_t offset = pos - length; if (offset < 0) { set_last_err_string("This wic boot length is wrong"); return -1; } return flash(&fb, pb->data() + offset, length); } } if (pin->size() <= max) { pb = pin->request_data(0, pin->size()); if (!pb) return -1; if (flash(&fb, pb->data(), pb->size())) return -1; } else { size_t pos = 0; pb = pin->request_data(0, sizeof(sparse_header)); if (!pb) return -1; sparse_header * pfile = (sparse_header *)pb->data(); if (!SparseFile::is_validate_sparse_file(pb->data(), sizeof(sparse_header))) { set_last_err_string("Sparse file magic miss matched"); return -1; } SparseFile sf; size_t startblock; chunk_header_t * pheader; uuu_notify nt; nt.type = uuu_notify::NOTIFY_TRANS_SIZE; nt.total = pfile->total_blks; call_notify(nt); sf.init_header(pfile->blk_sz, max / pfile->blk_sz); startblock = 0; pos = pfile->file_hdr_sz; for(size_t nblk=0; nblk < pfile->total_chunks && pos <= pin->size(); nblk++) { pb = pin->request_data(pos, sizeof(chunk_header_t)); if (!pb) return -1; pheader = (chunk_header_t*)pb->data(); size_t oldpos = pos; pos += pheader->total_sz; pb = pin->request_data(oldpos, pos - oldpos); if (!pb) return -1; pheader = (chunk_header_t*)pb->data(); size_t sz = sf.push_one_chuck(pheader, pheader + 1); if (sz == pheader->total_sz - sizeof(chunk_header_t)) { startblock += pheader->chunk_sz; } else if (sz == 0) { //whole chuck have not push into data. if (flash(&fb, sf.m_data.data(), sf.m_data.size())) return -1; sf.init_header(pfile->blk_sz, max / pfile->blk_sz); chunk_header_t ct; ct.chunk_type = CHUNK_TYPE_DONT_CARE; ct.chunk_sz = startblock; ct.reserved1 = 0; ct.total_sz = sizeof(ct); sz = sf.push_one_chuck(&ct, nullptr); /* roll back pos to previous failure chunck and let it push again into new sparse file. can't push it here because next chuck may big size chuck and need split as below else logic. */ pos = oldpos; nblk--; uuu_notify nt; nt.type = uuu_notify::NOTIFY_TRANS_POS; nt.total = startblock; call_notify(nt); } else { size_t off = sz + sizeof(chunk_header_t); startblock += sz / pfile->blk_sz; do { if (flash(&fb, sf.m_data.data(), sf.m_data.size())) return -1; sf.init_header(pfile->blk_sz, max / pfile->blk_sz); chunk_header_t ct; ct.chunk_type = CHUNK_TYPE_DONT_CARE; ct.chunk_sz = startblock; ct.reserved1 = 0; ct.total_sz = sizeof(ct); sz = sf.push_one_chuck(&ct, nullptr); sz = sf.push_raw_data(pb->data() + off, pb->size() - off); off += sz; startblock += sz / pfile->blk_sz; uuu_notify nt; nt.type = uuu_notify::NOTIFY_TRANS_POS; nt.total = startblock; call_notify(nt); } while (off + oldpos < pos); } } //send last data if (flash(&fb, sf.m_data.data(), sf.m_data.size())) return -1; sparse_header * pf = (sparse_header *)sf.m_data.data(); nt.type = uuu_notify::NOTIFY_TRANS_POS; nt.total = startblock + pf->total_blks; call_notify(nt); } return 0; } bool FBFlashCmd::isffu(shared_ptr p) { shared_ptr data = p->request_data(0, sizeof(FFU_SECURITY_HEADER)); if (!data) return -1; FFU_SECURITY_HEADER *h = (FFU_SECURITY_HEADER*)data->data(); if (strncmp((const char*)h->signature, FFU_SECURITY_SIGNATURE, sizeof(h->signature)) == 0) return true; else return false; } int FBFlashCmd::flash_ffu_oneblk(FastBoot *fb, shared_ptr pin, size_t off, size_t blksz, size_t blkindex) { SparseFile sf; sf.init_header(blksz, 10); shared_ptr p; p = pin->request_data(off, blksz); if (!p) return -1; chunk_header_t ct; ct.chunk_type = CHUNK_TYPE_DONT_CARE; ct.chunk_sz = blkindex; ct.reserved1 = 0; ct.total_sz = sizeof(ct); sf.push_one_chuck(&ct, nullptr); if (sf.push_one_block(p->data())) return -1; return flash(fb, sf.m_data.data(), sf.m_data.size()); } int FBFlashCmd::flash_ffu(FastBoot *fb, shared_ptr pin) { shared_ptr p = pin->request_data(0, sizeof(FFU_SECURITY_HEADER)); if (!p) return -1; FFU_SECURITY_HEADER *h = (FFU_SECURITY_HEADER*)p->data(); if (strncmp((const char*)h->signature, FFU_SECURITY_SIGNATURE, sizeof(h->signature)) != 0) { set_last_err_string("Invalidate FFU Security header signature"); return -1; } size_t off; off = h->dwCatalogSize + h->dwHashTableSize; off = round_up(off, (size_t)h->dwChunkSizeInKb * 1024); p = pin->request_data(0, off + sizeof(FFU_IMAGE_HEADER)); if (!p) return -1; FFU_IMAGE_HEADER *pIh = (FFU_IMAGE_HEADER *)(p->data() + off); if (strncmp((const char*)pIh->Signature, FFU_SIGNATURE, sizeof(pIh->Signature)) != 0) { set_last_err_string("Invalidate FFU Security header signature"); return -1; } off += pIh->ManifestLength + pIh->cbSize; off = round_up(off, (size_t)h->dwChunkSizeInKb * 1024); p = pin->request_data(0, off + sizeof(FFU_STORE_HEADER)); if (!p) return -1; FFU_STORE_HEADER *pIs = (FFU_STORE_HEADER*) (p->data() + off); if(pIs->MajorVersion == 1) off += pIs->dwValidateDescriptorLength + offsetof(FFU_STORE_HEADER, NumOfStores); else off += pIs->dwValidateDescriptorLength + sizeof(FFU_STORE_HEADER); p = pin->request_data(0, off + pIs->dwWriteDescriptorLength); if (!p) return -1; size_t block_off = off + pIs->dwWriteDescriptorLength; block_off = round_up(block_off, (size_t)h->dwChunkSizeInKb * 1024); uuu_notify nt; nt.type = uuu_notify::NOTIFY_TRANS_SIZE; nt.total = pIs->dwWriteDescriptorCount; call_notify(nt); size_t current_block = 0; size_t i; for (i = 0; i < pIs->dwWriteDescriptorCount; i++) { FFU_BLOCK_DATA_ENTRY *entry = (FFU_BLOCK_DATA_ENTRY*)(p->data() + off); off += sizeof(FFU_BLOCK_DATA_ENTRY) + (entry->dwLocationCount -1) * sizeof(_DISK_LOCATION); if (current_block >= pIs->dwInitialTableIndex && current_block < pIs->dwInitialTableIndex + pIs->dwInitialTableCount) { //Skip Init Block } else { for (uint32_t loc = 0; loc < entry->dwLocationCount; loc++) { //printf("block 0x%x write to 0x%x seek %d\n", current_block, entry->rgDiskLocations[loc].dwBlockIndex, entry->rgDiskLocations[loc].dwDiskAccessMethod); uint32_t blockindex; if (entry->rgDiskLocations[loc].dwDiskAccessMethod == DISK_BEGIN) blockindex = entry->rgDiskLocations[loc].dwBlockIndex; else blockindex = m_totalsize / pIs->dwBlockSizeInBytes - 1 - entry->rgDiskLocations[loc].dwBlockIndex; for (uint32_t blk = 0; blk < entry->dwBlockCount; blk++) { if (flash_ffu_oneblk(fb, pin, block_off + (current_block + blk) * pIs->dwBlockSizeInBytes, pIs->dwBlockSizeInBytes, blockindex + blk)) return -1; } } } nt.type = uuu_notify::NOTIFY_TRANS_POS; nt.total = i; call_notify(nt); current_block += entry->dwBlockCount; } nt.type = uuu_notify::NOTIFY_TRANS_POS; nt.total = i; call_notify(nt); return 0; } FBLoop::FBLoop(char* p): CmdBase(p) { insert_param_info("-f", &m_filename, Param::Type::e_string_filename); insert_param_info("-format", &m_uboot_cmd, Param::Type::e_string); insert_param_info("-blksz", &m_blksize, Param::Type::e_uint32); insert_param_info("-each", &m_each, Param::Type::e_uint32); insert_param_info("-seek", &m_seek, Param::Type::e_uint32); insert_param_info("-skip", &m_skip, Param::Type::e_uint32); insert_param_info("-nostop", &m_nostop, Param::Type::e_bool); } string FBLoop::build_cmd(string& cmd, size_t off, size_t sz) { string ucmd="UCmd: "; ucmd += cmd; string_ex ex; size_t pos= ucmd.find("@off"); if (pos != string::npos) { ex.format("0x%llx", off); ucmd = ucmd.replace(pos, 4, ex); } pos = ucmd.find("@size"); if (pos != string::npos) { ex.format("0x%llx", sz); ucmd = ucmd.replace(pos, 5, ex); } return ucmd; } int FBLoop::run(CmdCtx* ctx) { BulkTrans dev{ m_timeout }; if (dev.open(ctx->m_dev)) return -1; int ret = 0; string_ex err; size_t offset = 0; size_t seek = 0; FastBoot fb(&dev); string_ex cmd; shared_ptr p1 = get_file_buffer(m_filename, true); if (p1 == nullptr) return 0; shared_ptr fbuff; bool bload = p1->IsKnownSize(); uuu_notify nt; nt.type = uuu_notify::NOTIFY_TRANS_SIZE; if (bload) nt.total = p1->size(); else nt.total = 0; call_notify(nt); offset = m_skip; seek = m_seek; while((fbuff = p1->request_data(offset, m_each))) { ret = this->each(fb, fbuff, seek); offset += fbuff->size(); seek += fbuff->size(); if (!m_nostop && ret) return ret; nt.type = uuu_notify::NOTIFY_TRANS_POS; nt.total = offset; call_notify(nt); if (bload != p1->IsKnownSize()) { nt.type = uuu_notify::NOTIFY_TRANS_SIZE; nt.total = p1->size(); call_notify(nt); bload = p1->IsKnownSize(); } } if (!p1->IsKnownSize()) { set_last_err_string("Have not get all data"); return -1; } if (offset != p1->size()) { set_last_err_string("some data missed"); return -1; } nt.type = uuu_notify::NOTIFY_TRANS_POS; nt.total = offset; call_notify(nt); return ret; } int FBCRC::each(FastBoot& fb, std::shared_ptr fbuff, size_t off) { uint32_t crc = crc32(0, fbuff->data(), fbuff->size()); string cmd = build_cmd(m_uboot_cmd, off / m_blksize, div_round_up(fbuff->size(), m_blksize)); if (fb.Transport(cmd, nullptr, 0)) return -1; string_ex crc_cmd; crc_cmd.format("UCmd: crc32 -v $loadaddr 0x%x %08x", min(m_each, fbuff->size()), crc); int ret = fb.Transport(crc_cmd, nullptr, 0); if (ret) { string_ex err; err.format("crc32 check error at 0x%llx", off); set_last_err_string(err); } return ret; } int FBWrite::each(FastBoot& fb, std::shared_ptr fbuff, size_t off) { string_ex cmd; cmd.format("download:%08x", fbuff->size()); if (fb.Transport(cmd, fbuff->data(), fbuff->size())) return -1; string cmd_w = build_cmd(m_uboot_cmd, off / m_blksize, div_round_up(fbuff->size(), m_blksize)); if (fb.Transport(cmd_w, nullptr, 0)) return -1; return 0; } mfgtools-uuu_1.5.182/libuuu/fastboot.h000066400000000000000000000171421462141313700177260ustar00rootroot00000000000000/* * Copyright 2018, 2022 NXP. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * Neither the name of the NXP Semiconductor nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #pragma once #include "cmd.h" #include "bmap.h" #include class FBFlashCmd; class FileBuffer; class DataBuffer; class TransBase; /* Android fastboot protocol define at https://android.googlesource.com/platform/system/core/+/master/fastboot/ */ class FastBoot { public: FastBoot(TransBase *p) : m_pTrans{p} {} int Transport(std::string cmd, void *p = nullptr, size_t size = 0, std::vector *input = nullptr); int Transport(std::string cmd, std::vector data, std::vector *input = nullptr) { return Transport(cmd, data.data(), data.size(), input); } std::string m_info; private: TransBase *const m_pTrans = nullptr; }; class FBGetVar : public CmdBase { public: FBGetVar(char *p) :CmdBase(p) {} int parser(char *p = nullptr) override; int run(CmdCtx *ctx) override; private: std::string m_val; std::string m_var; friend FBFlashCmd; }; class FBCmd: public CmdBase { public: FBCmd(char *p, std::string &&fb_cmd, char separator =':') : CmdBase(p), m_fb_cmd{std::move(fb_cmd)}, m_separator(separator) {} int parser(char *p = nullptr) override; int run(CmdCtx *ctx) override; protected: std::string m_uboot_cmd; private: const std::string m_fb_cmd; const char m_separator = ':'; }; class FBLoop : public CmdBase { public: std::string m_uboot_cmd = "mmc read $loadaddr"; size_t m_blksize = 512; size_t m_each = 0x4000000; //byte address size_t m_seek = 0; //byte address size_t m_skip = 0; //byte address bool m_nostop = false; std::string m_filename; FBLoop(char* p); virtual int each(FastBoot& fb, std::shared_ptr fbuff, size_t off) = 0; int run(CmdCtx* ctx) override; std::string build_cmd(std::string& cmd, size_t off, size_t sz); }; class FBCRC : public FBLoop { public: int each(FastBoot& fb, std::shared_ptr fbuff, size_t off) override; FBCRC(char* p) : FBLoop(p) { m_uboot_cmd = "mmc read $loadaddr @off @size"; insert_param_info("CRC", nullptr, Param::Type::e_null); }; }; class FBWrite : public FBLoop { public: int each(FastBoot& fb, std::shared_ptr fbuff, size_t off) override; FBWrite(char* p) : FBLoop(p) { m_uboot_cmd = "mmc write ${fastboot_buffer} @off @size"; insert_param_info("WRITE", nullptr, Param::Type::e_null); }; }; class FBUCmd : public FBCmd { public: FBUCmd(char *p) :FBCmd(p, "UCmd") {} }; class FBACmd : public FBCmd { public: FBACmd(char *p) :FBCmd(p, "ACmd") {} }; class FBSyncCmd: public FBCmd { public: FBSyncCmd(char *p) : FBCmd(p, "Sync") {} }; class FBFlashingCmd : public FBCmd { public: FBFlashingCmd(char *p) : FBCmd(p, "flashing") {} }; class FBOemCmd : public FBCmd { public: FBOemCmd(char *p) : FBCmd(p, "oem", ' ') {} }; class FBFlashCmd : public FBCmd { public: FBFlashCmd(char *p) : FBCmd(p, "flash") { m_timeout = 10000; } int parser(char *p = nullptr) override; int run(CmdCtx *ctx) override; int flash(FastBoot *fb, void *p, size_t sz); int flash_raw2sparse(FastBoot *fb, std::shared_ptr p, size_t max); bool isffu(std::shared_ptr p); int flash_ffu(FastBoot *fb, std::shared_ptr p); int flash_ffu_oneblk(FastBoot *fb, std::shared_ptr p, size_t off, size_t blksz, size_t blkindex); private: bmap_t m_bmap; std::string m_filename; std::string m_bmap_filename; std::string m_partition; bool m_raw2sparse = false; bool m_use_bmap = false; size_t m_sparse_limit = 0x1000000; uint64_t m_totalsize; bool m_scanterm = false; uint64_t m_scan_limited = UINT64_MAX; }; class FBDelPartition : public FBCmd { public: FBDelPartition(char*p) : FBCmd(p, "delete-logical-partition") {} }; class FBPartNumber : public CmdBase { public: FBPartNumber(char *p, std::string &&fb_cmd) :CmdBase(p), m_fb_cmd{std::move(fb_cmd)} { m_Size = 0; m_bCheckTotalParam = true; m_NoKeyParam = true; insert_param_info(nullptr, &m_partition_name, Param::Type::e_string, false, "partition name"); insert_param_info(nullptr, &m_Size, Param::Type::e_uint32, false, "partition size"); } int run(CmdCtx *ctx) override; private: const std::string m_fb_cmd; std::string m_partition_name; uint32_t m_Size; }; class FBCreatePartition : public FBPartNumber { public: FBCreatePartition(char*p) :FBPartNumber(p, "create-logical-partition") {} }; class FBResizePartition : public FBPartNumber { public: FBResizePartition(char*p) :FBPartNumber(p, "resize-logical-partition") {} }; class FBUpdateSuper : public CmdBase { public: FBUpdateSuper(char *p) :CmdBase(p) { m_bCheckTotalParam = true; m_NoKeyParam = true; insert_param_info(nullptr, &m_partition_name, Param::Type::e_string, false, "partition name"); insert_param_info(nullptr, &m_opt, Param::Type::e_string, false, "partition size"); } int run(CmdCtx *ctx) override; private: const std::string m_fb_cmd = "update-super"; std::string m_opt; std::string m_partition_name; }; class FBEraseCmd : public FBCmd { public: FBEraseCmd(char *p) : FBCmd(p, "erase") {} }; class FBRebootCmd : public FBCmd { public: FBRebootCmd(char *p) : FBCmd(p, "reboot") {} }; class FBSetActiveCmd : public FBCmd { public: FBSetActiveCmd(char *p) : FBCmd(p, "set_active") {} }; class FBDownload : public CmdBase { public: FBDownload(char *p) :CmdBase(p) { insert_param_info("download", nullptr, Param::Type::e_null); insert_param_info("-f", &m_filename, Param::Type::e_string_filename); } int run(CmdCtx *ctx) override; private: std::string m_filename; }; class FBCopy : public CmdBase { public: FBCopy(char *p) :CmdBase(p) {} int parser(char *p = nullptr) override; int run(CmdCtx *ctx) override; private: bool m_bDownload; std::string m_local_file; size_t m_Maxsize_pre_cmd = 0x10000; std::string m_target_file; }; class FBBootCmd : public FBCmd { public: FBBootCmd(char *p) : FBCmd(p, "boot") {} }; class FBContinueCmd : public FBCmd { public: FBContinueCmd(char *p) : FBCmd(p, "continue") {} }; class FBUpload : public CmdBase { public: FBUpload(char* p) : CmdBase(p) { insert_param_info("upload", nullptr, Param::Type::e_null); insert_param_info("-v", &m_var, Param::Type::e_string); insert_param_info("-f", &m_filename, Param::Type::e_string); } int run(CmdCtx* ctx) override; private: std::string m_var; std::string m_filename; }; mfgtools-uuu_1.5.182/libuuu/fat.cpp000066400000000000000000000117661462141313700172200ustar00rootroot00000000000000/* * Copyright 2018 NXP. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * Neither the name of the NXP Semiconductor nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include "libcomm.h" #include "libuuu.h" #include "liberror.h" #include "fat.h" int Fat::Open(string filename) { m_filename = filename; shared_ptr pbuff = get_file_buffer(m_filename); if (pbuff == nullptr) return -1; if (pbuff->size() < 512) { set_last_err_string("File too small"); return -1; } if (pbuff->at(510) != 0x55|| pbuff->at(511) != 0xAA) { set_last_err_string("Partition signature miss matched"); return -1; } Partition *pPart = (Partition *)(pbuff->data() + 446); m_fat_part_start = pPart->lba_start * 512; uint8_t *boot = pbuff->data() + m_fat_part_start; if (boot[510] != 0x55 || boot[511] != 0xAA) { set_last_err_string("Boot Sector signature miss matched"); return -1; } m_logical_sector_perfat = boot[0x16]; m_logical_sector_perfat += boot[0x17] << 8; if (m_logical_sector_perfat == 0) { m_logical_sector_perfat = boot[0x24]; m_logical_sector_perfat += boot[0x25] << 8; m_logical_sector_perfat += boot[0x26] << 16; m_logical_sector_perfat += boot[0x27] << 24; } m_fat_table_offset = boot[0xE]; m_fat_table_offset += boot[0xF] << 8; m_fat_table_offset *= 512; m_cluster = boot[0xD]; m_cluster *= 512; int num_of_fat = boot[0x10]; m_root_dir_offset = m_logical_sector_perfat * 512 * num_of_fat + m_fat_table_offset; m_num_of_rootdir = boot[0x11]; m_num_of_rootdir = boot[0x12] << 8; FatDirEntry *entry; entry = (FatDirEntry*)(boot + m_root_dir_offset); m_filemap.clear(); for (int i = 0; i < m_num_of_rootdir; i++) { string filename; if (entry->attr == 0x8) entry++; if (entry->filename[0] == 0) break; filename.clear(); while (entry->attr == 0xF) { filename.insert(0, lfn2string((FatLFN *)entry)); entry++; } if (filename.empty()) { filename.append((char*)entry->filename, 8); if (entry->ext[0]) { filename.append("."); filename.append((char*)entry->ext, 3); } } m_filemap[filename] = *entry; entry++; if (entry->filename[0] == 0) break; } return 0; } int Fat::get_next_cluster(shared_ptr p, int cluster) { uint16_t *pfat = (uint16_t*)(p->data() + m_fat_part_start + m_fat_table_offset); return pfat[cluster]; } void *Fat::get_data_buff(shared_ptr p, int cluster) { void *p1 = p->data() + m_fat_part_start + m_root_dir_offset + (cluster-2) * m_cluster + m_num_of_rootdir * 32; return p1; } int Fat::get_file_buff(string filename, shared_ptrp) { if (m_filemap.find(filename) == m_filemap.end()) { string err; err = "Can't find file "; err += filename; set_last_err_string(err); return -1; } shared_ptr pbuff = get_file_buffer(m_filename); size_t filesize = m_filemap[filename].file_size; p->resize(filesize); int cur = m_filemap[filename].start_cluster; size_t off; for (off = 0; off < filesize; off += m_cluster) { size_t sz; sz = filesize - off; if (sz > m_cluster) sz = m_cluster; if (cur == 0xFFFF) { set_last_err_string("Early finished at fat"); return -1; } void *pcluster = get_data_buff(pbuff, cur); memcpy(p->data() + off, pcluster, sz); cur = get_next_cluster(pbuff, cur); } return 0; } std::string Fat::lfn2string(FatLFN *p) { string str; for (int i = 0; i < 10; i += 2) if (p->name1[i] == 0) return str; else str += p->name1[i]; for (int i = 0; i < 12; i += 2) if (p->name2[i] == 0) return str; else str += p->name2[i]; for (int i = 0; i < 4; i += 2) if (p->name3[i] == 0) return str; else str += p->name3[i]; return str; } mfgtools-uuu_1.5.182/libuuu/fat.h000066400000000000000000000053431462141313700166570ustar00rootroot00000000000000/* * Copyright 2018 NXP. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * Neither the name of the NXP Semiconductor nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #pragma once #include "backfile.h" #include "buffer.h" #include #pragma pack(1) struct Partition { uint8_t status; uint8_t start_head; uint8_t start_sector; uint8_t start_cylinder; uint8_t type; uint8_t end_head; uint8_t end_sector; uint8_t end_cylinder; uint32_t lba_start; uint32_t lba_num; }; struct FatDirEntry { uint8_t filename[8]; uint8_t ext[3]; uint8_t attr; uint8_t user_attr; uint8_t delete_char; uint16_t create_time; uint16_t create_date; uint16_t userid; uint16_t access; uint16_t modify_time; uint16_t modify_date; uint16_t start_cluster; uint32_t file_size; }; struct FatLFN { uint8_t seq; uint8_t name1[10]; uint8_t attr; uint8_t type; uint8_t sum; uint8_t name2[12]; uint16_t start_cluster; uint8_t name3[4]; }; #pragma pack() class Fat : public Backfile { public: void *get_data_buff(shared_ptr p, int cluster); int get_file_buff(string filename, shared_ptrp); int get_next_cluster(shared_ptr p, int cluster); string lfn2string(FatLFN *p); int Open(string filename); map m_filemap; private: uint64_t m_cluster; uint64_t m_fat_part_start; uint64_t m_fat_table_offset; uint64_t m_logical_sector_perfat; int m_num_of_rootdir; uint64_t m_root_dir_offset; }; mfgtools-uuu_1.5.182/libuuu/ffu_format.h000066400000000000000000000113241462141313700202310ustar00rootroot00000000000000/* * Copyright 2020 NXP. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * Neither the name of the NXP Semiconductor nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ //ref: https://docs.microsoft.com/en-us/windows-hardware/manufacture/mobile/ffu-image-format #ifndef LIBSPARSE_FFU_FORMAT_H #define LIBSPARSE_FFU_FORMAT_H #include #define FFU_SECURITY_SIGNATURE "SignedImage " #pragma pack(1) typedef struct _FFU_SECURITY_HEADER { uint32_t cbSize; // size of struct, overall uint8_t signature[12]; // "SignedImage " uint32_t dwChunkSizeInKb; // size of a hashed chunk within the image uint32_t dwAlgId; // algorithm used to hash uint32_t dwCatalogSize; // size of catalog to validate uint32_t dwHashTableSize; // size of hash table } FFU_SECURITY_HEADER; #define FFU_SIGNATURE "ImageFlash " typedef struct _IMAGE_HEADER { uint32_t cbSize; // sizeof(ImageHeader) uint8_t Signature[12]; // "ImageFlash " uint32_t ManifestLength; // in bytes uint32_t dwChunkSize; // Used only during image generation. } FFU_IMAGE_HEADER; typedef struct _STORE_HEADER { uint32_t dwUpdateType; // indicates partial or full flash uint16_t MajorVersion, MinorVersion; // used to validate struct uint16_t FullFlashMajorVersion, FullFlashMinorVersion; // FFU version, i.e. the image format uint8_t szPlatformId[192]; // string which indicates what device this FFU is intended to be written to uint32_t dwBlockSizeInBytes; // size of an image block in bytes - the device's actual sector size may differ uint32_t dwWriteDescriptorCount; // number of write descriptors to iterate through uint32_t dwWriteDescriptorLength; // total size of all the write descriptors, in bytes (included so they can be read out up front and interpreted later) uint32_t dwValidateDescriptorCount; // number of validation descriptors to check uint32_t dwValidateDescriptorLength; // total size of all the validation descriptors, in bytes uint32_t dwInitialTableIndex; // block index in the payload of the initial (invalid) GPT uint32_t dwInitialTableCount; // count of blocks for the initial GPT, i.e. the GPT spans blockArray[idx..(idx + count -1)] uint32_t dwFlashOnlyTableIndex; // first block index in the payload of the flash-only GPT (included so safe flashing can be accomplished) uint32_t dwFlashOnlyTableCount; // count of blocks in the flash-only GPT uint32_t dwFinalTableIndex; // index in the table of the real GPT uint32_t dwFinalTableCount; // number of blocks in the real GPT uint16_t NumOfStores; // Total number of stores (V2 only) uint16_t StoreIndex; // Current store index, 1-based (V2 only) uint64_t StorePayloadSize; // Payload data only, excludes padding (V2 only) uint16_t DevicePathLength; // Length of the device path (V2 only) uint16_t DevicePath[1]; // Device path has no NUL at then end (V2 only) } FFU_STORE_HEADER; typedef struct _VALIDATION_ENTRY { uint32_t dwSectorIndex; uint32_t dwSectorOffset; uint32_t dwByteCount; uint8_t rgCompareData[1]; // size is dwByteCount } FFU_VALIDATION_ENTRY; enum DISK_ACCESS_METHOD { DISK_BEGIN = 0, DISK_END = 2 }; typedef struct _DISK_LOCATION { uint32_t dwDiskAccessMethod; uint32_t dwBlockIndex; } FFU_DISK_LOCATION; typedef struct _BLOCK_DATA_ENTRY { uint32_t dwLocationCount; uint32_t dwBlockCount; FFU_DISK_LOCATION rgDiskLocations[1]; } FFU_BLOCK_DATA_ENTRY; #pragma pack() #endif // LIBSPARSE_FFU_FORMAT_H mfgtools-uuu_1.5.182/libuuu/gen_ver.sh000077500000000000000000000011401462141313700177070ustar00rootroot00000000000000#!/bin/sh # Input parameters file_to_write="$1" set -e if [ -f ../.tarball-version ] then echo "#define GIT_VERSION \"lib$(cat ../.tarball-version)\"" > "$file_to_write" exit 0 fi if [ "${APPVEYOR_BUILD_VERSION}" = "" ]; then echo build not in appveyor else git tag -m"uuu ${APPVEYOR_BUILD_VERSION}" uuu_${APPVEYOR_BUILD_VERSION} fi # Test if we are in a repo if [ "$(git rev-parse --is-inside-work-tree 2>/dev/null)" = "true" ]; then #echo "In a repo" # Get the version of the last commit of the repo version=`git describe --long` echo "#define GIT_VERSION \"lib$version\"" > $file_to_write fi mfgtools-uuu_1.5.182/libuuu/hidreport.cpp000066400000000000000000000061751462141313700204440ustar00rootroot00000000000000/* * Copyright 2020 NXP. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * Neither the name of the NXP Semiconductor nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #include "hidreport.h" #include "libcomm.h" #include "liberror.h" #include "trans.h" #include "zip.h" #include HIDReport::~HIDReport() { } void HIDReport::notify(size_t index, uuu_notify::NOTIFY_TYPE type) { uuu_notify nf; nf.type = type; if(type == uuu_notify::NOTIFY_TRANS_POS) nf.index = index + m_postion_base; if (type == uuu_notify::NOTIFY_TRANS_SIZE) { nf.index = m_notify_total > index ? m_notify_total : index; } call_notify(nf); } int HIDReport::read(std::vector &buff) { if (buff.size() < m_size_in + m_size_payload) { set_last_err_string("buffer to small to get a package"); return -1; } size_t rs; int ret = m_pdev->read(buff.data(), m_size_in + m_size_payload, &rs); return ret; } int HIDReport::write(const void *p, size_t sz, uint8_t report_id) { notify(sz, uuu_notify::NOTIFY_TRANS_SIZE); const uint8_t * const buff = reinterpret_cast(p); size_t off = 0; for (; off < sz; off += m_size_out) { m_out_buff[0] = report_id; size_t s = sz - off; if (s > m_size_out) s = m_size_out; memcpy(m_out_buff.data() + m_size_payload, buff + off, s); /* * The Windows HIDAPI is ver strict. It always require to send * buffers of the size reported by the HID Report Descriptor. * Therefore we must to send m_size_out buffers for HID ID 2 * albeit it may not required for the last buffer. */ if (report_id == 2) s = m_size_out; int ret = m_pdev->write(m_out_buff.data(), s + m_size_payload); if (ret < 0) return -1; if (off % 0x1F == 0) { notify(off, uuu_notify::NOTIFY_TRANS_POS); } } notify(sz, uuu_notify::NOTIFY_TRANS_POS); return 0; } mfgtools-uuu_1.5.182/libuuu/hidreport.h000066400000000000000000000052021462141313700200770ustar00rootroot00000000000000/* * Copyright 2018 NXP. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * Neither the name of the NXP Semiconductor nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #pragma once #include "libuuu.h" #include class TransBase; class HIDReport { public: HIDReport(TransBase *trans) : m_pdev{trans} { m_out_buff.resize(m_size_out + m_size_payload); } virtual ~HIDReport(); size_t get_out_package_size() noexcept { return m_size_out; } virtual void notify(size_t index, uuu_notify::NOTIFY_TYPE type); int read(std::vector &buff); void set_notify_total(size_t notify_total) noexcept { m_notify_total = notify_total; } void set_out_package_size(size_t sz) { m_size_out = sz; m_out_buff.resize(m_size_out + m_size_payload); } void set_position_base(size_t position_base) noexcept { m_postion_base = position_base; } void set_skip_notify(bool skip_notify) noexcept { m_skip_notify = skip_notify; } int write(const void *p, size_t sz, uint8_t report_id); int write(const std::vector &buff, uint8_t report_id) { return write(buff.data(), buff.size(), report_id); } private: size_t m_notify_total = 0; std::vector m_out_buff; TransBase * const m_pdev = nullptr; size_t m_postion_base = 0; size_t m_size_in = 64; size_t m_size_out = 1024; size_t m_size_payload = 1; bool m_skip_notify = true; }; mfgtools-uuu_1.5.182/libuuu/http.cpp000066400000000000000000000332201462141313700174120ustar00rootroot00000000000000/* * Copyright 2019, 2023 NXP. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * Neither the name of the NXP Semiconductor nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #ifdef _WIN32 // request += "Connection: Keep-Alive\n"; #include #include #include #pragma comment(lib, "Winhttp.lib") #else #include #include #include #define INVALID_SOCKET -1 #include #endif #include "http.h" #include "libuuu.h" #include "liberror.h" #include "libcomm.h" #include #include #include uuu_askpasswd g_ask_passwd; int uuu_set_askpasswd(uuu_askpasswd ask) { g_ask_passwd = ask; return 0; } map> g_passwd_map; #ifdef UUUSSL #include #include static const char* base64_table = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789+/"; static string base64_encode(string str) { string ret; for (size_t i = 0; i < str.length(); i += 3) { ret.push_back(base64_table[(str[i] >> 2) & 0x3f]); if (i + 1 < str.length()) { int index; index = ((str[i] & 3) << 4) + ((str[i + 1] >> 4) & 0xf); ret.push_back(base64_table[index]); } else { ret.push_back(base64_table[(str[i] & 0x3) << 4]); ret.push_back('='); ret.push_back('='); return ret; } if (i + 2 < str.length()) { int index; index = (((str[i + 1]) & 0xF) << 2) + (((str[i + 2]) >> 6) & 0x3); ret.push_back(base64_table[index]); index = str[i + 2] & 0x3f; ret.push_back(base64_table[index]); } else { ret.push_back(base64_table[((str[i + 1]) & 0xF) << 2]); ret.push_back('='); return ret; } } return ret; } class CUUUSSL { public: CUUUSSL() { #if OPENSSL_VERSION_NUMBER < 0x10100000L SSL_library_init(); SSLeay_add_ssl_algorithms(); SSL_load_error_strings(); #else OPENSSL_init_ssl(0, nullptr); SSLeay_add_ssl_algorithms(); #endif } ~CUUUSSL() { } }; static CUUUSSL g_uuussl; #endif using namespace std; #ifdef _WIN32 /* Win32 implement*/ DWORD ChooseAuthScheme(DWORD dwSupportedSchemes) { if (dwSupportedSchemes & WINHTTP_AUTH_SCHEME_NEGOTIATE) return WINHTTP_AUTH_SCHEME_NEGOTIATE; else if (dwSupportedSchemes & WINHTTP_AUTH_SCHEME_NTLM) return WINHTTP_AUTH_SCHEME_NTLM; else if (dwSupportedSchemes & WINHTTP_AUTH_SCHEME_PASSPORT) return WINHTTP_AUTH_SCHEME_PASSPORT; else if (dwSupportedSchemes & WINHTTP_AUTH_SCHEME_DIGEST) return WINHTTP_AUTH_SCHEME_DIGEST; else if (dwSupportedSchemes & WINHTTP_AUTH_SCHEME_BASIC) return WINHTTP_AUTH_SCHEME_BASIC; return 0; } HttpStream::HttpStream() { m_buff.empty(); m_hConnect = 0; m_hSession = 0; m_hRequest = 0; } int HttpStream::HttpGetHeader(std::string host, std::string path, int port, bool ishttps) { m_hSession = WinHttpOpen(L"WinHTTP UUU/1.0", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0); if (!m_hSession) { set_last_err_string("fail WinHttpOpen"); return -1; } wstring_convert> converter; wstring whost = converter.from_bytes(host); if (m_hSession) m_hConnect = WinHttpConnect(m_hSession, whost.c_str(), port, 0); if (!m_hConnect) { set_last_err_string("Fail Connection"); return -1; } wstring wpath = converter.from_bytes(path); m_hRequest = WinHttpOpenRequest(m_hConnect, L"GET", wpath.c_str(), nullptr, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, ishttps ?WINHTTP_FLAG_SECURE:0); BOOL bResults = FALSE; if (!m_hRequest) { set_last_err_string("Fail WinHttpOpenRequest"); return -1; } DWORD dwProxyAuthScheme = 0; int retry = 3; pair up = g_passwd_map[host]; while (1) { DWORD status = 0; DWORD dwSize = sizeof(status); bResults = WinHttpSendRequest(m_hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0); // End the request. if (bResults) bResults = WinHttpReceiveResponse(m_hRequest, NULL); // Resend the request in case of // ERROR_WINHTTP_RESEND_REQUEST error. if (!bResults && GetLastError() == ERROR_WINHTTP_RESEND_REQUEST) continue; // Check the status code. if (bResults) bResults = WinHttpQueryHeaders(m_hRequest, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &dwSize, NULL); if (bResults) { DWORD dwSupportedSchemes; DWORD dwFirstScheme; DWORD dwSelectedScheme; DWORD dwTarget; switch (status) { case HTTP_STATUS_OK: //200 g_passwd_map[host] = up; return 0; case HTTP_STATUS_DENIED: //401 // The server requires authentication. if(g_passwd_map[host].first.empty()) { char user[MAX_USER_LEN]; char passwd[MAX_USER_LEN]; if (g_ask_passwd((char*)host.c_str(), user, passwd)) return -1; up.first = user; up.second = passwd; } // Obtain the supported and preferred schemes. bResults = WinHttpQueryAuthSchemes(m_hRequest, &dwSupportedSchemes, &dwFirstScheme, &dwTarget); // Set the credentials before resending the request. if (bResults) { dwSelectedScheme = ChooseAuthScheme(dwSupportedSchemes); std::wstring_convert> convert; if (dwSelectedScheme == 0) { set_last_err_string("unsupported http auth"); return -1; } else bResults = WinHttpSetCredentials(m_hRequest, dwTarget, dwSelectedScheme, convert.from_bytes(up.first).c_str(), convert.from_bytes(up.second).c_str(), NULL); } retry--; if (!retry) return -1; break; case HTTP_STATUS_PROXY_AUTH_REQ: set_last_err_string("unsupported proxy auth"); return -1; default: g_passwd_map[host] = up; // The status code does not indicate success. string_ex str; str.format("Error. Status code %d returned.\n", status); set_last_err_string(str); return -1; } } } return -1; } size_t HttpStream::HttpGetFileSize() { DWORD dwSize = 0; BOOL bResults = FALSE; wstring out; WinHttpQueryHeaders(m_hRequest, WINHTTP_QUERY_CONTENT_LENGTH, WINHTTP_HEADER_NAME_BY_INDEX, nullptr, &dwSize, WINHTTP_NO_HEADER_INDEX); // Allocate memory for the buffer. if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { out.resize(dwSize / sizeof(WCHAR)); // Now, use WinHttpQueryHeaders to retrieve the header. bResults = WinHttpQueryHeaders(m_hRequest, WINHTTP_QUERY_CONTENT_LENGTH, WINHTTP_HEADER_NAME_BY_INDEX, (LPVOID)out.c_str(), &dwSize, WINHTTP_NO_HEADER_INDEX); } return _wtoll(out.c_str()); } int HttpStream::HttpDownload(char *buff, size_t sz) { DWORD dwSize = 0; DWORD dwDownloaded = 0; while (sz) { if (!WinHttpQueryDataAvailable(m_hRequest, &dwSize)) { set_last_err_string("WinHttpQueryDataAvailable"); return -1; } if (dwSize > sz) dwSize = sz; if (!WinHttpReadData(m_hRequest, (LPVOID)buff, dwSize, &dwDownloaded)) { set_last_err_string("Fail at WinHttpReadData"); return -1; } buff += dwDownloaded; sz -= dwDownloaded; } return 0; } HttpStream::~HttpStream() { if (m_hRequest) WinHttpCloseHandle(m_hRequest); if (m_hConnect) WinHttpCloseHandle(m_hConnect); if (m_hSession) WinHttpCloseHandle(m_hSession); } #else HttpStream::HttpStream() { m_buff.empty(); } int HttpStream::SendPacket(char *buff, size_t sz) { #ifdef UUUSSL if(m_ssl) return SSL_write((SSL*)m_ssl, buff, sz); #endif return send(m_socket, buff, sz, 0); } int HttpStream::RecvPacket(char *buff, size_t sz) { #ifdef UUUSSL if(m_ssl) return SSL_read((SSL*)m_ssl, buff, sz); #endif return recv(m_socket, buff, sz, 0); } class CAutoAddrInfo { addrinfo *m_p; public: CAutoAddrInfo(addrinfo *pAddrInfo) { m_p = pAddrInfo; } ~CAutoAddrInfo() { freeaddrinfo(m_p); } }; #include int HttpStream::HttpGetHeader(std::string host, std::string path, int port, bool ishttps) { int ret; addrinfo *pAddrInfo; char s_port[10]; snprintf(s_port, 10, "%d", port); if (getaddrinfo(host.c_str(), s_port, 0, &pAddrInfo)) { set_last_err_string("get network address error"); return -1; } CAutoAddrInfo A(pAddrInfo); m_socket = socket(pAddrInfo->ai_family, pAddrInfo->ai_socktype, pAddrInfo->ai_protocol); struct timeval tv; tv.tv_sec = 10; tv.tv_usec = 0; setsockopt(m_socket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof(tv)); if (m_socket == INVALID_SOCKET) { set_last_err_string("Can't get sock"); return -1; } if (connect(m_socket, pAddrInfo->ai_addr, pAddrInfo->ai_addrlen)) { set_last_err_string("connect error"); return -1; } if(ishttps) { #ifdef UUUSSL const SSL_METHOD* meth = #if (OPENSSL_VERSION_NUMBER < 0x10100000L) TLSv1_2_client_method(); #else TLS_client_method(); #endif if(!meth) { set_last_err_string("Failure at TLSv1_2_client_method\n"); return -1; } SSL_CTX *ctx = SSL_CTX_new (meth); if(!ctx) { set_last_err_string("Error create ssl ctx\n"); return -1; } m_ssl = SSL_new (ctx); if(!m_ssl) { set_last_err_string("Error create SSL\n"); return -1; } SSL_set_fd((SSL*)m_ssl, m_socket); if( SSL_connect((SSL*)m_ssl) <= 0) { set_last_err_string("error build ssl connection"); return -1; } #else set_last_err_string("Can't support https"); return -1; #endif } int retry = 3; pair up = g_passwd_map[host]; while(retry--) { string userpd = up.first + ":" + up.second; string httppath = path; if(ishttps) httppath = "https://" + host + path; string request = "GET " + httppath + " HTTP/1.1\r\n"; request += "Host: " + host + "\r\n"; if (!up.first.empty()) request += "Authorization: Basic " + base64_encode(userpd) + "\r\n"; request += "User-Agent:uuu\r\nAccept: */*\r\n"; request += "\r\n"; ret = SendPacket((char*)request.c_str(), request.size()); if ((size_t)(ret) != request.size()) { set_last_err_string("http send error"); return -1; } m_buff.resize(1024); ret = RecvPacket((char*)m_buff.data(), m_buff.size()); if (ret < 0) { set_last_err_string("http recv Error"); return -1; } int i; for (i = 0; i < 1024 - 4; i++) { if (m_buff[i] == 0xd && m_buff[i + 1] == 0xa && m_buff[i + 2] == 0xd && m_buff[i + 3] == 0xa) { break; } } if (i >= 1024 - 4) { set_last_err_string("Can't find terminate"); return -1; } m_data_start = i + 4; string str; str.resize(i + 2); memcpy((void*)str.c_str(), m_buff.data(), i + 2); int ret = parser_response(str); if (ret == ERR_ACCESS_DENIED) { if(g_passwd_map[host].first.empty()) { char user[MAX_USER_LEN]; char passwd[MAX_USER_LEN]; if (g_ask_passwd((char*)host.c_str(), user, passwd)) return -1; up.first = user; up.second = passwd; } continue; } else if(ret == 0) { g_passwd_map[host] = up; return 0; } g_passwd_map[host] = up; } return -1; } size_t HttpStream::HttpGetFileSize() { return atoll(m_response["Content-Length"].c_str()); } int HttpStream::parser_response(string rep) { size_t pos = rep.find("\r\n"); if (pos == string::npos) { set_last_err_string("Can't find \r\n"); return -1; } string str = rep.substr(0, pos); if (str == "HTTP/1.1 401 Unauthorized") return ERR_ACCESS_DENIED; if (str != "HTTP/1.1 200 OK") { set_last_err_string(str); return -1; } m_response.clear(); while (pos != string::npos) { pos += 2; size_t split = rep.find(':', pos); if (split == string::npos) break; string key = rep.substr(pos, split - pos); pos = rep.find("\r\n", pos); string value = rep.substr(split + 1, pos - split - 1); m_response[key] = value; } return 0; } int HttpStream::HttpDownload(char *buff, size_t sz) { size_t left = 0; if (m_data_start < m_buff.size()) left = m_buff.size() - m_data_start; size_t trim_transferred = 0; if (left) { trim_transferred = sz; if (trim_transferred > left) trim_transferred = left; memcpy(buff, m_buff.data() + m_data_start, trim_transferred); m_data_start += trim_transferred; } if (trim_transferred < sz) { int ret = 0; sz -= trim_transferred; buff += trim_transferred; while (sz && ((ret = RecvPacket(buff, sz)) > 0)) { buff += ret; sz -= ret; } if (ret < 0) { set_last_err_string("recv error"); return -1; } } return 0; } HttpStream::~HttpStream() { close(m_socket); #ifdef UUUSSL if(m_ssl) { SSL_CTX_free(SSL_get_SSL_CTX((SSL*)m_ssl)); SSL_free((SSL*)m_ssl); } #endif } #endif mfgtools-uuu_1.5.182/libuuu/http.h000066400000000000000000000042121462141313700170560ustar00rootroot00000000000000/* * Copyright 2020 NXP. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * Neither the name of the NXP Semiconductor nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #pragma once #include #include #include class HttpStream { std::vector m_buff; int m_socket = -1; std::map m_response; size_t m_data_start; #ifdef _WIN32 void far * m_hSession; void far * m_hConnect; void far * m_hRequest; #endif void * m_ssl = nullptr; int parser_response(std::string rep); public: HttpStream(); int HttpGetHeader(std::string host, std::string path, int port = 80, bool ishttps=false); size_t HttpGetFileSize(); int HttpDownload(char *buff, size_t sz); ~HttpStream(); private: int RecvPacket(char *buff, size_t sz); int SendPacket(char *buff, size_t sz); }; mfgtools-uuu_1.5.182/libuuu/libcomm.h000066400000000000000000000103111462141313700175160ustar00rootroot00000000000000/* * Copyright 2018 NXP. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * Neither the name of the NXP Semiconductor nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include #include #pragma once using namespace std; void call_notify(struct uuu_notify nf); #define log printf #define dbg printf int get_libusb_debug_level() noexcept; class string_ex : public std::string { public: int format(const char *fmt, ...) { va_list args; va_start(args, fmt); size_t len = std::vsnprintf(nullptr, 0, fmt, args); va_end(args); this->resize(len); va_start(args, fmt); std::vsnprintf((char*)c_str(), len+1, fmt, args); va_end(args); return 0; } void replace(char a, char b) { for (size_t i = 0; i < size(); i++) if (at(i) == a) (*this)[i] = b; } }; class Path : public string_ex { public: string get_file_name() { replace('\\', '/'); size_t pos; pos = rfind('/'); if (pos == string::npos) return *this; return substr(pos + 1); } }; inline uint64_t EndianSwap(uint64_t x) { return (((x & 0x00000000000000ffLL) << 56) | ((x & 0x000000000000ff00LL) << 40) | ((x & 0x0000000000ff0000LL) << 24) | ((x & 0x00000000ff000000LL) << 8) | ((x & 0x000000ff00000000LL) >> 8) | ((x & 0x0000ff0000000000LL) >> 24) | ((x & 0x00ff000000000000LL) >> 40) | ((x & 0xff00000000000000LL) >> 56)); } inline uint32_t EndianSwap(uint32_t x) { return (x >> 24) | ((x << 8) & 0x00FF0000) | ((x >> 8) & 0x0000FF00) | (x << 24); } inline uint16_t EndianSwap(uint16_t x) { return (x >> 8) | ((x << 8) & 0xFF00); } inline string str_to_upper(const string &str) { std::locale loc; string s; for (size_t i = 0; i < str.size(); i++) s.push_back(std::toupper(str[i], loc)); return s; } inline string remove_quota(string str) { if (!str.empty()) { if (str[0] == '"') { str.erase(0, 1); if (!str.empty() && str[str.size() - 1] == '"') str.erase(str.size() - 1, 1); } } return str; } inline bool compare_str(const string &str1, const string &str2, bool ignore_case) { if (ignore_case) return str_to_upper(str1) == str_to_upper(str2); else return str1 == str2; } uint16_t str_to_uint16(const string &str, bool * conversion_succeeded = nullptr); uint32_t str_to_uint32(const string &str, bool * conversion_succeeded = nullptr); uint64_t str_to_uint64(const string &str, bool * conversion_succeeded = nullptr); template inline T round_up(T x, T align) { return (x + align - 1) / align * align; } template inline T div_round_up(T x, T align) { return (x + align - 1) / align; } inline std::string trim(const std::string &s) { auto wsfront = std::find_if_not(s.begin(), s.end(), [](int c) {return std::isspace(c); }); return std::string(wsfront, std::find_if_not(s.rbegin(), std::string::const_reverse_iterator(wsfront), [](int c) {return std::isspace(c); }).base()); } mfgtools-uuu_1.5.182/libuuu/liberror.h000066400000000000000000000032041462141313700177170ustar00rootroot00000000000000/* * Copyright 2018 NXP. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * Neither the name of the NXP Semiconductor nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #pragma once #include void set_last_err_string(const std::string &str); void set_last_err_id(int id); #define ERR_OUT_MEMORY -2 #define ERR_ACCESS_DENIED -3 mfgtools-uuu_1.5.182/libuuu/libuuu.h000066400000000000000000000113731462141313700174120ustar00rootroot00000000000000/* * Copyright 2018 NXP. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * Neither the name of the NXP Semiconductor nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #ifndef __libuuu___ #define __libuuu___ #include #include #ifdef __cplusplus #define EXT extern "C" #else #define EXT #endif /** * Get Last error string * @return last error string */ EXT const char * uuu_get_last_err_string(); /** * Get Last error code * @return last error code */ EXT int uuu_get_last_err(); EXT const char * uuu_get_version_string(); /** * 1.0.1 * bit[31:24].bit[23:12].bit[11:0] */ EXT int uuu_get_version(); struct uuu_notify { enum NOTIFY_TYPE { NOTIFY_CMD_TOTAL, NOTIFY_CMD_START, /* str is command name*/ NOTIFY_CMD_END, /* status show command finish status. 0 is success. Other failure.*/ NOTIFY_CMD_INDEX, /*Current running command index*/ NOTIFY_CMD_INFO, /* Status info string */ NOTIFY_PHASE_TOTAL, NOTIFY_PHASE_INDEX, /*Current running phase*/ NOTIFY_TRANS_SIZE, /*Total size*/ NOTIFY_TRANS_POS, /*Current finished transfer pos*/ NOTIFY_WAIT_FOR, NOTIFY_DEV_ATTACH, NOTIFY_DECOMPRESS_START, NOTIFY_DECOMPRESS_SIZE, NOTIFY_DECOMPRESS_POS, NOTIFY_DOWNLOAD_START, NOTIFY_DOWNLOAD_END, NOTIFY_THREAD_EXIT, NOTIFY_DONE, }; NOTIFY_TYPE type; uint64_t id; uint64_t timestamp; union { int status; size_t index; size_t total; char *str; }; }; typedef int (*uuu_notify_fun)(struct uuu_notify, void *data); int uuu_register_notify_callback(uuu_notify_fun f, void *data); int uuu_unregister_notify_callback(uuu_notify_fun f); typedef int(*uuu_show_cfg)(const char *pro, const char *chip, const char *comp, uint16_t vid, uint16_t pid, uint16_t bcdlow, uint16_t bcdhigh, void *p); int uuu_for_each_cfg(uuu_show_cfg fn, void *p); typedef int(*uuu_ls_file)(const char *path, void *p); int uuu_for_each_ls_file(uuu_ls_file fn, const char *path, void *p); typedef int(*uuu_ls_usb_devices)(const char *path, const char *chip, const char *pro, uint16_t vid, uint16_t pid, uint16_t bcd, const char *serial_no, void *p); int uuu_for_each_devices(uuu_ls_usb_devices fn, void *p); int uuu_run_cmd(const char * cmd, int dry); int uuu_run_cmd_script(const char *script, int dry); int uuu_auto_detect_file(const char * filename); int uuu_wait_uuu_finish(int deamon, int dry); int uuu_add_usbpath_filter(const char *path); int uuu_add_usbserial_no_filter(const char *serial_no); /*Set timeout wait for known devices appeared*/ int uuu_set_wait_timeout(int timeout_in_seconds); /*Set timeout wait for next devices appeared, e.g. FB -> FBK*/ int uuu_set_wait_next_timeout(int timeout_in_seconds); /*Set usb device polling period */ void uuu_set_poll_period(int period_in_milliseconds); /* * bit 0:15 for libusb * bit 16:31 for uuu */ void uuu_set_debug_level(uint32_t mask); /* * 0 disable small memory mode, buffer all data, it is used for multi-board program. */ void uuu_set_small_mem(uint32_t val); #define MAX_USER_LEN 128 typedef int (*uuu_askpasswd)(char* prompt, char user[MAX_USER_LEN], char passwd[MAX_USER_LEN]); int uuu_set_askpasswd(uuu_askpasswd ask); enum class bmap_mode { Default, Force, Ignore }; /*Get .bmap handling mode*/ static inline bmap_mode uuu_get_bmap_mode() { extern bmap_mode g_bmap_mode; return g_bmap_mode; } static inline int uuu_force_bmap() { return uuu_get_bmap_mode() == bmap_mode::Force; } static inline int uuu_ignore_bmap() { return uuu_get_bmap_mode() == bmap_mode::Ignore; } #endif mfgtools-uuu_1.5.182/libuuu/notify.cpp000066400000000000000000000051041462141313700177430ustar00rootroot00000000000000/* * Copyright 2018 NXP. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * Neither the name of the NXP Semiconductor nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #include "libuuu.h" #include #include #include #include #include using namespace std; static map g_notification_map; static mutex g_mutex_notify; using namespace std::chrono; static const time_point g_now = steady_clock::now(); int uuu_register_notify_callback(uuu_notify_fun f, void *data) { std::lock_guard lock(g_mutex_notify); return g_notification_map.emplace(f, data).second ? 0 : 1; } int uuu_unregister_notify_callback(uuu_notify_fun f) { std::lock_guard lock(g_mutex_notify); return g_notification_map.erase(f) > 0 ? 0 : 1; } void call_notify(struct uuu_notify nf) { //Change RW lock later; std::lock_guard lock(g_mutex_notify); nf.id = std::hash{}(std::this_thread::get_id()); nf.timestamp = static_cast( duration_cast(steady_clock::now() - g_now).count()); for (const auto &item : g_notification_map) { try { item.first(nf, item.second); } catch (const std::exception& e) { std::cerr << "notify exception: " << e.what() << std::endl; } } } mfgtools-uuu_1.5.182/libuuu/rominfo.cpp000066400000000000000000000156351462141313700201160ustar00rootroot00000000000000/* * Copyright 2018 NXP. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * Neither the name of the NXP Semiconductor nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #include "rominfo.h" #include "buffer.h" #include "config.h" #include "libcomm.h" #include #include using namespace std; static constexpr std::array g_RomInfo { ROM_INFO{ "MX6Q", 0x00910000, ROM_INFO_HID | ROM_INFO_HID_MX6, 0}, ROM_INFO{ "MX6D", 0x00910000, ROM_INFO_HID | ROM_INFO_HID_MX6, 0}, ROM_INFO{ "MX6SL", 0x00910000, ROM_INFO_HID | ROM_INFO_HID_MX6, 0}, ROM_INFO{ "MX7D", 0x00911000, ROM_INFO_HID | ROM_INFO_HID_MX6 | ROM_INFO_HID_SKIP_DCD, 0}, ROM_INFO{ "MX6UL", 0x00910000, ROM_INFO_HID | ROM_INFO_HID_MX6 | ROM_INFO_HID_SKIP_DCD, 0}, ROM_INFO{ "MX6ULL", 0x00910000, ROM_INFO_HID | ROM_INFO_HID_MX6 | ROM_INFO_HID_SKIP_DCD, 0}, ROM_INFO{ "MX6SLL", 0x00910000, ROM_INFO_HID | ROM_INFO_HID_MX6 | ROM_INFO_HID_SKIP_DCD, 0}, ROM_INFO{ "MX8MQ", 0x00910000, ROM_INFO_HID | ROM_INFO_HID_MX6 | ROM_INFO_HID_SKIP_DCD | ROM_INFO_NEED_BAREBOX_FULL_IMAGE, 4}, ROM_INFO{ "MX7ULP", 0x2f018000, ROM_INFO_HID | ROM_INFO_HID_MX6 | ROM_INFO_HID_SKIP_DCD, 0}, ROM_INFO{ "MXRT106X", 0x1000, ROM_INFO_HID | ROM_INFO_HID_MX6 | ROM_INFO_HID_SKIP_DCD, 0}, ROM_INFO{ "MX8QXP", 0x0, ROM_INFO_HID | ROM_INFO_HID_NO_CMD | ROM_INFO_HID_UID_STRING, 4}, ROM_INFO{ "MX28", 0x0, ROM_INFO_HID, 0}, ROM_INFO{ "MX815", 0x0, ROM_INFO_HID | ROM_INFO_HID_NO_CMD | ROM_INFO_HID_UID_STRING | ROM_INFO_HID_EP1 | ROM_INFO_HID_PACK_SIZE_1020 | ROM_INFO_HID_ROMAPI, 4}, ROM_INFO{ "MX95", 0x0, ROM_INFO_HID | ROM_INFO_HID_NO_CMD | ROM_INFO_HID_UID_STRING | ROM_INFO_HID_EP1 | ROM_INFO_HID_PACK_SIZE_1020, 4}, ROM_INFO{ "SPL", 0x0, ROM_INFO_HID | ROM_INFO_HID_MX6 | ROM_INFO_SPL_JUMP | ROM_INFO_HID_SDP_NO_MAX_PER_TRANS, 0}, ROM_INFO{ "SPL1", 0x0, ROM_INFO_HID | ROM_INFO_HID_MX6 | ROM_INFO_SPL_JUMP | ROM_INFO_HID_SDP_NO_MAX_PER_TRANS | ROM_INFO_AUTO_SCAN_UBOOT_POS, 0}, }; const ROM_INFO * search_rom_info(const std::string &s) { for (const auto &rom_info : g_RomInfo) { if (s == rom_info.m_name) { return &rom_info; } } return nullptr; } const ROM_INFO * search_rom_info(const ConfigItem *item) { if (item == nullptr) { return nullptr; } const ROM_INFO * const p = search_rom_info(item->m_chip); if (p) { return p; } return search_rom_info(item->m_compatible); } #define IV_MAX_LEN 32 #define HASH_MAX_LEN 64 #define CONTAINER_HDR_ALIGNMENT 0x400 static constexpr uint8_t CONTAINER_TAG = 0x87; #pragma pack (1) struct rom_container { uint8_t version; uint8_t length_l; uint8_t length_m; uint8_t tag; uint32_t flags; uint16_t sw_version; uint8_t fuse_version; uint8_t num_images; uint16_t sig_blk_offset; uint16_t reserved; }; struct rom_bootimg { uint32_t offset; uint32_t size; uint64_t destination; uint64_t entry; uint32_t flags; uint32_t meta; uint8_t hash[HASH_MAX_LEN]; uint8_t iv[IV_MAX_LEN]; }; static constexpr uint32_t IMG_FCB_COPY = 0x08; static constexpr uint32_t IMG_V2X = 0x0B; #pragma pack () size_t GetContainerActualSize(shared_ptr p, size_t offset, bool bROMAPI, bool skipspl) { if(bROMAPI) return p->size() - offset; auto hdr = reinterpret_cast(p->data() + offset + CONTAINER_HDR_ALIGNMENT); if (hdr->tag != CONTAINER_TAG) { return p->size() - offset; } /* Check if include V2X container*/ auto image = reinterpret_cast(p->data() + offset + CONTAINER_HDR_ALIGNMENT + sizeof(struct rom_container)); unsigned int cindex = 1; if ((image->flags & 0xF) == IMG_V2X) { cindex = 2; hdr = reinterpret_cast(p->data() + offset + cindex * CONTAINER_HDR_ALIGNMENT); if (hdr->tag != CONTAINER_TAG) { return p->size() - offset; } } image = reinterpret_cast(p->data() + offset + cindex * CONTAINER_HDR_ALIGNMENT + sizeof(struct rom_container) + sizeof(struct rom_bootimg) * (hdr->num_images - 1)); /* Check if the image is FCB copy */ if (((image->flags & 0xF) == IMG_FCB_COPY) && !skipspl) { image--; } uint32_t sz = image->size + image->offset + cindex * CONTAINER_HDR_ALIGNMENT; sz = round_up(sz, static_cast(CONTAINER_HDR_ALIGNMENT)); if (sz > (p->size() - offset)) { return p->size() - offset; } return sz; } bool CheckHeader(uint32_t *p) { static constexpr std::array FlashHeaderMagic { 0xc0ffee01, 0x42464346 }; for (const auto magic_val : FlashHeaderMagic) { if (*p == magic_val) { return true; } } return false; } size_t GetFlashHeaderSize(shared_ptr p, size_t offset) { static constexpr std::array offsets { 0, 0x400, 0x1fc, 0x5fc }; for (const auto test_offset : offsets) { if (p->size() < (offset + test_offset)) { return 0; } if (CheckHeader(reinterpret_cast(p->data() + offset + test_offset))) { return 0x1000; } } return 0; } bool IsMBR(shared_ptr p) { uint16_t * m = (uint16_t *)(p->data() + 510); if (*m == 0xaa55) return true; return false; } size_t ScanTerm(std::shared_ptr p, size_t &pos, size_t offset, size_t limited) { const char *tag = "UUUBURNXXOEUZX7+A-XY5601QQWWZ"; if (limited >= p->size()) limited = p->size(); limited = limited - strlen(tag) - 64; if (offset > limited) return 0; for (size_t i = offset; i < limited; i++) { char *c = (char*)p->data() + i; size_t length = strlen(tag); size_t j; for (j = 0; j < length; j++) { if (tag[j] != c[j]) break; } if (j == length) { pos = i; return atoll(c + length); } } return 0; } mfgtools-uuu_1.5.182/libuuu/rominfo.h000066400000000000000000000055151462141313700175570ustar00rootroot00000000000000/* * Copyright 2018 NXP. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * Neither the name of the NXP Semiconductor nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #pragma once #include #include #include class ConfigItem; class FileBuffer; class DataBuffer; constexpr uint32_t ROM_INFO_HID = 0x1; constexpr uint32_t ROM_INFO_HID_MX23 = 0x2; constexpr uint32_t ROM_INFO_HID_MX50 = 0x4; constexpr uint32_t ROM_INFO_HID_MX6 = 0x8; constexpr uint32_t ROM_INFO_HID_SKIP_DCD = 0x10; constexpr uint32_t ROM_INFO_HID_MX8_MULTI_IMAGE = 0x20; constexpr uint32_t ROM_INFO_HID_MX8_STREAM = 0x40; constexpr uint32_t ROM_INFO_HID_UID_STRING = 0x80; // Omitted value: 0x100 // Omitted value: 0x200 constexpr uint32_t ROM_INFO_HID_NO_CMD = 0x400; constexpr uint32_t ROM_INFO_SPL_JUMP = 0x800; constexpr uint32_t ROM_INFO_HID_EP1 = 0x1000; constexpr uint32_t ROM_INFO_HID_PACK_SIZE_1020 = 0x2000; constexpr uint32_t ROM_INFO_HID_SDP_NO_MAX_PER_TRANS = 0x4000; constexpr uint32_t ROM_INFO_AUTO_SCAN_UBOOT_POS = 0x8000; constexpr uint32_t ROM_INFO_HID_ROMAPI = 0x10000; constexpr uint32_t ROM_INFO_NEED_BAREBOX_FULL_IMAGE = 0x20000; struct ROM_INFO { const char * m_name; uint32_t free_addr; uint32_t flags; int serial_idx; }; const ROM_INFO * search_rom_info(const std::string &s); const ROM_INFO * search_rom_info(const ConfigItem *item); size_t GetContainerActualSize(std::shared_ptr p, size_t offset, bool bROMAPI=false, bool skipspl=false); size_t GetFlashHeaderSize(std::shared_ptr p, size_t offset = 0); mfgtools-uuu_1.5.182/libuuu/sdp.cpp000066400000000000000000000476111462141313700172320ustar00rootroot00000000000000/* * Copyright 2018 NXP. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * Neither the name of the NXP Semiconductor nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #include #include "config.h" #include "sdps.h" #include "hidreport.h" #include "liberror.h" #include "libcomm.h" #include "buffer.h" #include "sdp.h" #include "rominfo.h" #include "libusb.h" #include "trans.h" #include int SDPCmdBase::check_ack(HIDReport *report, uint32_t ack) { if (get_hab_type(report) == HabUnknown) return -1; uint32_t status; if (get_status(report, status, 4)) return -1; if (ack != status) { set_last_err_string("Status Miss matched"); return -1; } return 0; } SDPCmdBase::HAB_t SDPCmdBase::get_hab_type(HIDReport *report) { uint32_t status; if (get_status(report, status, 3)) return HabUnknown; if (status == HabEnabled) return HabEnabled; if (status == HabDisabled) return HabDisabled; set_last_err_string("unknown hab type"); return HabUnknown; } int SDPCmdBase::get_status(HIDReport *p, uint32_t &status, uint8_t report_id) { m_input.resize(1025); m_input[0] = report_id; int ret = p->read(m_input); if (ret < 0) return -1; if (m_input.size() < (1 + sizeof(uint32_t))) { set_last_err_string("HID report size is too small"); return -1; } status = *(uint32_t*)(m_input.data() + 1); return 0; } int SDPCmdBase::init_cmd() { memset(&m_spdcmd, 0, sizeof(m_spdcmd)); insert_param_info("-scanlimited", &m_scan_limited, Param::Type::e_uint64); return 0; } IvtHeader *SDPCmdBase::search_ivt_header(shared_ptr data, size_t &off, size_t limit) { if (limit >= data->size()) limit = data->size(); for (; off < limit; off += 0x4) { IvtHeader *p = (IvtHeader*)(data->data() + off); if (p->IvtBarker == IVT_BARKER_HEADER) return p; if (p->IvtBarker == IVT_BARKER2_HEADER) { BootData *pDB = (BootData *) &(data->at(off + p->BootData - p->SelfAddr)); /*Skip HDMI firmware for i.MX8MQ*/ if (pDB->PluginFlag & 0xFFFFFFFE) continue; return p; } } off = -1; return nullptr; } int SDPCmdBase::send_cmd(HIDReport *p) { return p->write(&m_spdcmd, sizeof(m_spdcmd), 1); } SDPDcdCmd::SDPDcdCmd(char *p) : SDPCmdBase(p) { insert_param_info("dcd", nullptr, Param::Type::e_null); insert_param_info("-f", &m_filename, Param::Type::e_string_filename); insert_param_info("-dcdaddr", &m_dcd_addr, Param::Type::e_uint32); m_dcd_addr = 0; } int SDPDcdCmd::run(CmdCtx*ctx) { const ROM_INFO * rom = search_rom_info(ctx->m_config_item); if (rom == nullptr) { string_ex err; err.format("%s:%d can't get rom info", __FUNCTION__, __LINE__); set_last_err_string(err); return -1; } init_cmd(); shared_ptr p = get_file_buffer(m_filename, true); if (!p) return -1; shared_ptr buff; buff = p->request_data(0, m_scan_limited); if (!buff) return -1; size_t off = 0; IvtHeader *pIVT = search_ivt_header(buff, off); if (pIVT == nullptr) { return 0; } if (pIVT->DCDAddress == 0) return 0; uint8_t * pdcd = &(buff->at(off + pIVT->DCDAddress - pIVT->SelfAddr)); if (pdcd[0] != HAB_TAG_DCD) { string_ex err; err.format("%s:%d DCD TAG miss matched", __FUNCTION__, __LINE__); set_last_err_string(err); return -1; } uint32_t size = (pdcd[1] << 8) | pdcd[2]; if (size >= m_scan_limited) { set_last_err_string("dcd bigger than 8M"); return -1; } // point maybe change after new requisition buffer. pdcd = &(buff->at(off + pIVT->DCDAddress - pIVT->SelfAddr)); m_spdcmd.m_cmd = ROM_KERNEL_CMD_DCD_WRITE; m_spdcmd.m_addr = EndianSwap(m_dcd_addr ? m_dcd_addr : rom->free_addr); m_spdcmd.m_count = EndianSwap(size); HIDTrans dev(m_timeout); if (dev.open(ctx->m_dev)) return -1; HIDReport report(&dev); if (report.write(&m_spdcmd, sizeof(m_spdcmd), 1)) return -1; if (report.write(pdcd, size, 2)) return -1; if (check_ack(&report, ROM_WRITE_ACK)) return -1; return 0; } SDPSkipDCDCmd::SDPSkipDCDCmd(char *p) : SDPCmdBase(p) { m_spdcmd.m_cmd = ROM_KERNEL_CMD_SKIP_DCD_HEADER; } int SDPSkipDCDCmd::run(CmdCtx*ctx) { HIDTrans dev(m_timeout); if (dev.open(ctx->m_dev)) return -1; HIDReport report(&dev); if (report.write(&m_spdcmd, sizeof(m_spdcmd), 1)) return -1; if (check_ack(&report, ROM_OK_ACK)) return -1; return 0; } SDPBootCmd::SDPBootCmd(char *p) : SDPCmdBase(p) { insert_param_info("boot", nullptr, Param::Type::e_null); insert_param_info("-f", &m_filename, Param::Type::e_string_filename); insert_param_info("-nojump", &m_nojump, Param::Type::e_bool); insert_param_info("-cleardcd", &m_clear_dcd, Param::Type::e_bool); insert_param_info("-dcdaddr", &m_dcd_addr, Param::Type::e_uint32); insert_param_info("-scanlimited", &m_scan_limited, Param::Type::e_uint64); insert_param_info("-barebox", &m_barebox, Param::Type::e_bool); } # define BAREBOX_MAGIC_OFFSET 0x20 bool SDPBootCmd::is_barebox_img(void) { shared_ptr fbuf= get_file_buffer(m_filename, true); if (fbuf == nullptr) return false; string barebox_magic ("barebox"); shared_ptr dbuf = fbuf->request_data(0, BAREBOX_MAGIC_OFFSET + barebox_magic.length()); if (dbuf == nullptr) return false; string img ((const char *)&dbuf->at(BAREBOX_MAGIC_OFFSET), barebox_magic.length()); return img.compare(barebox_magic) == 0 ? true : false; } int SDPBootCmd::load_barebox(CmdCtx *ctx) { const ROM_INFO *rom = search_rom_info(ctx->m_config_item); if (!rom) return 0; // The barebox USB loading mechanism differs between SoCs due to SRAM // size limitations. // // E.g. all i.MX8M SoCs require a two stage loading, first the // pre-bootloader (PBL) is loaded to the internal SRAM and started. The // PBL intialize the DDR and uses the BootROM initialized USB // controller to load the remaining "full barebox image" to the DDR. // // On i.MX6 devices this is not the case since the DDR setup is done // via the DCD and we can load the image directly to the DDR. // // The ROM_INFO_NEED_BAREBOX_FULL_IMAGE flag indicates if the two-stage // load mechanism is required for a specific SoC. So the user can // always specify '-barebox' no matter if it's required or not: // // SDP: boot -barebox -f if (!(rom->flags & ROM_INFO_NEED_BAREBOX_FULL_IMAGE)) return 0; string str; str = "SDP: write -f "; str += m_filename; str += " -ivt 0"; str += " -barebox-bl33"; SDPWriteCmd wr((char *)str.c_str()); if (wr.parser()) return -1; return wr.run(ctx); } int SDPBootCmd::run(CmdCtx *ctx) { string str; str = "SDP: dcd -f "; str += m_filename; if (m_dcd_addr) { str += " -dcdaddr "; str += std::to_string(m_dcd_addr); } if (m_scan_limited != UINT64_MAX) { str += " -scanlimited "; str += std::to_string(m_scan_limited); } SDPDcdCmd dcd((char *)str.c_str()); if (m_scan_limited != UINT64_MAX) { str += " -scanlimited "; str += std::to_string(m_scan_limited); } if (dcd.parser()) return -1; if (dcd.run(ctx)) return -1; str = "SDP: write -f "; str += m_filename; str += " -ivt 0"; if (m_scan_limited != UINT64_MAX) { str += " -scanlimited "; str += std::to_string(m_scan_limited); } SDPWriteCmd wr((char *)str.c_str()); if (wr.parser()) return -1; if (wr.run(ctx)) return -1; str = "SDP: jump -f "; str += m_filename; str += " -ivt 0"; if (m_clear_dcd) str += " -cleardcd"; if (m_scan_limited != UINT64_MAX) { str += " -scanlimited "; str += std::to_string(m_scan_limited); } SDPJumpCmd jmp((char *)str.c_str()); if (!m_nojump) { if (jmp.parser()) return -1; if (jmp.run(ctx)) return -1; } if (m_barebox || is_barebox_img()) { if (load_barebox(ctx)) return -1; } SDPBootlogCmd log(nullptr); log.run(ctx); return 0; } SDPStatusCmd::SDPStatusCmd(char *p) : SDPCmdBase(p) { m_spdcmd.m_cmd = ROM_KERNEL_CMD_ERROR_STATUS; insert_param_info("status", nullptr, Param::Type::e_null); } int SDPStatusCmd::run(CmdCtx *ctx) { HIDTrans dev(m_timeout); if (dev.open(ctx->m_dev)) return -1; HIDReport report(&dev); if (report.write(&m_spdcmd, sizeof(m_spdcmd), 1)) return -1; if (get_hab_type(&report) == HabUnknown) return -1; uint32_t status; if (get_status(&report, status, 4)) return -1; return 0; } SDPWriteCmd::SDPWriteCmd(char *p) : SDPCmdBase(p) { m_spdcmd.m_cmd = ROM_KERNEL_CMD_WR_FILE; m_PlugIn = -1; m_Ivt = -1; m_max_download_pre_cmd = 0x200000; m_offset = 0; m_bIvtReserve = false; m_download_addr = 0; m_bskipspl = false; m_bscanterm = false; m_barebox_bl33 = false; insert_param_info("write", nullptr, Param::Type::e_null); insert_param_info("-f", &m_filename, Param::Type::e_string_filename); insert_param_info("-ivt", &m_Ivt, Param::Type::e_uint32); insert_param_info("-addr", &m_download_addr, Param::Type::e_uint32); insert_param_info("-barebox-bl33", &m_barebox_bl33, Param::Type::e_bool); insert_param_info("-offset", &m_offset, Param::Type::e_uint32); insert_param_info("-skipspl", &m_bskipspl, Param::Type::e_bool); insert_param_info("-skipfhdr", &m_bskipfhdr, Param::Type::e_bool); insert_param_info("-scanterm", &m_bscanterm, Param::Type::e_bool); } int SDPWriteCmd::run(CmdCtx*ctx) { size_t size; uint8_t *pbuff; ssize_t offset = 0; bool validate_run = true; shared_ptr p1= get_file_buffer(m_filename, true); if (p1 == nullptr) return -1; shared_ptr fbuff; fbuff = p1->request_data(0, m_scan_limited); if (!fbuff) return -1; if (m_Ivt < 0) { pbuff = fbuff->data(); size = fbuff->size(); offset = m_offset; if (m_bskipfhdr) offset += GetFlashHeaderSize(fbuff, offset); size_t pos = 0, length; if (m_bscanterm) { if (IsMBR(fbuff)) { length = ScanTerm(fbuff, pos); if (length == 0) { set_last_err_string("This wic have NOT terminate tag after bootloader, please use new yocto"); return -1; } offset = pos - length; if (offset < 0) { set_last_err_string("This wic boot length is wrong"); return -1; } size = pos; } } if (m_bskipspl) { const ROM_INFO * rom = search_rom_info(ctx->m_config_item); if(! (rom->flags & ROM_INFO_AUTO_SCAN_UBOOT_POS)) { set_last_err_string("SPL doesn't support auto scan uboot position"); return -1; } size_t off = offset; IvtHeader *pIvt = search_ivt_header(fbuff, off, 0x100000); if (pIvt) { if (pIvt->BootData) { BootData *pDB = (BootData *) &(fbuff->at(off + pIvt->BootData - pIvt->SelfAddr)); offset = off + pDB->ImageSize - (pIvt->SelfAddr - pDB->ImageStartAddr); } } else { offset += GetContainerActualSize(fbuff, offset, rom->flags & ROM_INFO_HID_ROMAPI, m_bskipspl); } if (size_t(offset) >= fbuff->size()) { set_last_err_string("Unknown Image type, can't use skipspl format"); return -1; } } size -= offset; } else { size_t off = 0; IvtHeader *pIvt = search_ivt_header(fbuff, off); for (int i = 0; i < m_Ivt; i++) { off += sizeof(IvtHeader); pIvt = search_ivt_header(fbuff, off, m_scan_limited); } if (pIvt == nullptr) { set_last_err_string("Cannot find valid IVT header"); return -1; } BootData *pDB = (BootData *) &(fbuff->at(off + pIvt->BootData - pIvt->SelfAddr)); m_download_addr = pIvt->SelfAddr; //size = fbuff->size() - off; size = pDB->ImageSize - (pIvt->SelfAddr - pDB->ImageStartAddr); if (size >= m_scan_limited) { set_last_err_string("TODO: image is too big"); return -1; } //ImageSize may be bigger than Imagesize because ImageSize include IVT offset //Difference boot storage have difference IVT offset. if (size > fbuff->size() - off) size = fbuff->size() - off; if (m_barebox_bl33) { if (pIvt->IvtBarker != IVT_BARKER_HEADER) { set_last_err_string("Barebox BL33 loading is only support for IVT Header V2"); return -1; } offset = pIvt->ImageStartAddr - pIvt->SelfAddr; size = fbuff->size() - off - offset; m_download_addr = 0; // Barebox does start as soon as the bl33 was loaded // and the check_ack() fails validate_run = false; } pbuff = (uint8_t*)pIvt; } return run(ctx, pbuff + offset, size, m_download_addr, validate_run); } int SDPWriteCmd::run(CmdCtx *ctx, void *pbuff, size_t size, uint32_t addr, bool validate) { HIDTrans dev(m_timeout); if (dev.open(ctx->m_dev)) return -1; HIDReport report(&dev); report.set_notify_total(size); const ROM_INFO * rom = search_rom_info(ctx->m_config_item); size_t max = m_max_download_pre_cmd; /* SPL needn't split transfer */ if (rom && (rom ->flags & ROM_INFO_HID_SDP_NO_MAX_PER_TRANS)) max = size; for (size_t i=0; i < size; i += max) { size_t sz; sz = size - i; if (sz > max) sz = max; m_spdcmd.m_addr = EndianSwap((uint32_t)(addr + i)); // force use 32bit endian swap function; m_spdcmd.m_count = EndianSwap((uint32_t)sz); //force use 32bit endian swap function; report.set_position_base(i); report.set_skip_notify(true); if (report.write(&m_spdcmd, sizeof(m_spdcmd), 1)) return -1; report.set_skip_notify(false); if (report.write(((uint8_t*)pbuff)+i, sz, 2)) return -1; if (validate && check_ack(&report, ROM_STATUS_ACK)) return -1; } return 0; } SDPReadMemCmd::SDPReadMemCmd(char *p) : SDPCmdBase(p) { m_spdcmd.m_cmd = ROM_KERNEL_CMD_RD_MEM; insert_param_info("rdmem", nullptr, Param::Type::e_null); insert_param_info("-addr", &m_mem_addr, Param::Type::e_uint32); insert_param_info("-format", &m_mem_format, Param::Type::e_uint32); } int SDPReadMemCmd::run(CmdCtx *ctx) { HIDTrans dev(m_timeout); if (dev.open(ctx->m_dev)) return -1; HIDReport report(&dev); printf("\nReading address 0x%08X ...\n", m_mem_addr); m_spdcmd.m_addr = EndianSwap(m_mem_addr); m_spdcmd.m_format = m_mem_format; switch (m_mem_format) { case 0x8: m_spdcmd.m_count = EndianSwap((uint32_t)0x1); break; case 0x10: m_spdcmd.m_count = EndianSwap((uint32_t)0x2); break; case 0x20: m_spdcmd.m_count = EndianSwap((uint32_t)0x4); break; default: set_last_err_string("Invalid format, use <8|16|32>"); return -1; break; } if (report.write(&m_spdcmd, sizeof(m_spdcmd), 1)) return -1; if (get_hab_type(&report) == HabUnknown) return -1; uint32_t mem_value; if (get_status(&report, mem_value, 4) == 0) { printf("\nValue of address 0x%08X: ", m_mem_addr); switch (m_mem_format) { case 0x8: printf("0x%02X\n", mem_value & 0xff); break; case 0x10: printf("0x%04X\n", mem_value & 0xffff); break; case 0x20: printf("0x%08X\n", mem_value); break; default: set_last_err_string("Invalid format, use <8|16|32>"); return -1; } } return 0; } SDPWriteMemCmd::SDPWriteMemCmd(char *p) : SDPCmdBase(p) { m_spdcmd.m_cmd = ROM_KERNEL_CMD_WR_MEM; insert_param_info("wrmem", nullptr, Param::Type::e_null); insert_param_info("-addr", &m_mem_addr, Param::Type::e_uint32); insert_param_info("-format", &m_mem_format, Param::Type::e_uint32); insert_param_info("-value", &m_mem_value, Param::Type::e_uint32); } int SDPWriteMemCmd::run(CmdCtx *ctx) { HIDTrans dev(m_timeout); if (dev.open(ctx->m_dev)) return -1; HIDReport report(&dev); printf("\nWriting 0x%08X to address 0x%08X ...\n", m_mem_value, m_mem_addr); m_spdcmd.m_addr = EndianSwap(m_mem_addr); m_spdcmd.m_format = m_mem_format; switch (m_mem_format) { case 0x8: m_spdcmd.m_count = EndianSwap((uint32_t)0x1); break; case 0x10: m_spdcmd.m_count = EndianSwap((uint32_t)0x2); break; case 0x20: m_spdcmd.m_count = EndianSwap((uint32_t)0x4); break; default: set_last_err_string("Invalid format, use <8|16|32>"); return -1; break; } m_spdcmd.m_data = EndianSwap(m_mem_value); if (report.write(&m_spdcmd, sizeof(m_spdcmd), 1)) return -1; if (get_hab_type(&report) == HabUnknown) return -1; uint32_t status; if (get_status(&report, status, 4) < 0 || status != ROM_WRITE_ACK) { string_ex err; err.format("%s:%d Failed to write to address 0x%X", __FUNCTION__, __LINE__, m_mem_addr); set_last_err_string(err); } return 0; } SDPJumpCmd::SDPJumpCmd(char *p) : SDPCmdBase(p) { m_spdcmd.m_cmd = ROM_KERNEL_CMD_JUMP_ADDR; insert_param_info("jump", nullptr, Param::Type::e_null); insert_param_info("-f", &m_filename, Param::Type::e_string_filename); insert_param_info("-ivt", &m_Ivt, Param::Type::e_uint32); insert_param_info("-plugin", &m_PlugIn, Param::Type::e_bool); insert_param_info("-addr", &m_jump_addr, Param::Type::e_uint32); insert_param_info("-cleardcd", &m_clear_dcd, Param::Type::e_bool); } int SDPJumpCmd::run(CmdCtx *ctx) { const ROM_INFO * rom = search_rom_info(ctx->m_config_item); HIDTrans dev(m_timeout); if (dev.open(ctx->m_dev)) return -1; HIDReport report(&dev); if (rom == nullptr) { string_ex err; err.format("%s:%d can't get rom info", __FUNCTION__, __LINE__); set_last_err_string(err); return -1; } if (rom->flags & ROM_INFO_SPL_JUMP) { m_spdcmd.m_addr = EndianSwap(m_jump_addr); if (report.write(&m_spdcmd, sizeof(m_spdcmd), 1)) return -1; //Omit last return value. check_ack(&report, ROM_OK_ACK); return 0; } shared_ptr p1 = get_file_buffer(m_filename, true); if (!p1) return -1; shared_ptr buff; buff = p1->request_data(0, m_scan_limited); if (!buff) return -1; size_t off = 0; IvtHeader *pIVT = search_ivt_header(buff, off, m_scan_limited); for (int i = 0; i < m_Ivt; i++) { off += sizeof(IvtHeader); pIVT = search_ivt_header(buff, off); } if (pIVT == nullptr) { set_last_err_string("Cannot find valid IVT header"); return -1; } m_spdcmd.m_addr = EndianSwap(pIVT->SelfAddr); if (rom->flags & ROM_INFO_HID_SKIP_DCD && !m_clear_dcd) { SDPSkipDCDCmd skipcmd(nullptr); if (skipcmd.run(ctx)) return -1; } else { /*Clear DCD*/ vector ivt; /* Need send out whole report size buffer avoid overwrite other data * Some platform require receive whole package for report id = 2 */ ivt.resize(report.get_out_package_size()); size_t sz = buff->size(); sz -= (uint8_t*)pIVT - (uint8_t*)buff->data(); if (sz > ivt.size()) sz = ivt.size(); memcpy(ivt.data(), pIVT, sz); IvtHeader *header = (IvtHeader *)ivt.data(); header->DCDAddress = 0; SDPWriteCmd writecmd(nullptr); if(writecmd.run(ctx, header, ivt.size(), pIVT->SelfAddr)) return -1; } if (report.write(&m_spdcmd, sizeof(m_spdcmd), 1)) return -1; //Omit last return value. check_ack(&report, ROM_OK_ACK); return 0; } SDPBootlogCmd::SDPBootlogCmd(char *p) : SDPCmdBase(p) { insert_param_info("blog", nullptr, Param::Type::e_null); } int SDPBootlogCmd::run(CmdCtx *ctx) { HIDTrans dev{2000}; if (dev.open(ctx->m_dev)) return -1; HIDReport report(&dev); vector v(65); v[0] = 'I'; uuu_notify nt; nt.type = uuu_notify::NOTIFY_CMD_INFO; int ret; while (1) { ret = report.read(v); if (ret) return 0; else { nt.str = (char*)(v.data() + 4); v[5] = 0; call_notify(nt); continue; } } return 0; } mfgtools-uuu_1.5.182/libuuu/sdp.h000066400000000000000000000117271462141313700166760ustar00rootroot00000000000000/* * Copyright 2018 NXP. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * Neither the name of the NXP Semiconductor nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #pragma once #include "cmd.h" #include class FileBuffer; class HIDReport; #pragma pack (1) struct SDPCmd { uint16_t m_cmd; uint32_t m_addr; uint8_t m_format; uint32_t m_count; uint32_t m_data; uint8_t m_rsvd; }; struct IvtHeader { uint32_t IvtBarker; uint32_t ImageStartAddr; uint32_t Reserved; uint32_t DCDAddress; uint32_t BootData; uint32_t SelfAddr; uint32_t Reserved2[2]; }; struct BootData { uint32_t ImageStartAddr; uint32_t ImageSize; uint32_t PluginFlag; }; #pragma pack () #define ROM_KERNEL_CMD_RD_MEM 0x0101 #define ROM_KERNEL_CMD_WR_MEM 0x0202 #define ROM_KERNEL_CMD_WR_FILE 0x0404 #define ROM_KERNEL_CMD_ERROR_STATUS 0x0505 #define RAM_KERNEL_CMD_HEADER 0x0606 //#define ROM_KERNEL_CMD_RE_ENUM 0x0909 #define ROM_KERNEL_CMD_DCD_WRITE 0x0A0A #define ROM_KERNEL_CMD_JUMP_ADDR 0x0B0B #define ROM_KERNEL_CMD_SKIP_DCD_HEADER 0x0C0C #define MAX_DCD_WRITE_REG_CNT 85 #define ROM_WRITE_ACK 0x128A8A12 #define ROM_STATUS_ACK 0x88888888 #define ROM_OK_ACK 0x900DD009 #define IVT_BARKER_HEADER 0x402000D1 #define IVT_BARKER2_HEADER 0x412000D1 #define HAB_TAG_DCD 0xd2 /**< Device Configuration Data */ class SDPCmdBase:public CmdBase { public: enum HAB_t { HabUnknown = -1, HabEnabled = 0x12343412, HabDisabled = 0x56787856 }; SDPCmdBase(char *p) :CmdBase(p) { init_cmd(); } protected: int check_ack(HIDReport *report, uint32_t ack); HAB_t get_hab_type(HIDReport *report); int get_status(HIDReport *p, uint32_t &status, uint8_t report_id); int init_cmd(); IvtHeader * search_ivt_header(std::shared_ptr data, size_t &off, size_t limit=ULLONG_MAX); std::string m_filename; SDPCmd m_spdcmd; uint64_t m_scan_limited = UINT64_MAX; private: int send_cmd(HIDReport *p); std::vector m_input; }; class SDPBootlogCmd : public SDPCmdBase { public: SDPBootlogCmd(char *p); int run(CmdCtx *) override; }; class SDPDcdCmd : public SDPCmdBase { public: SDPDcdCmd(char *p); int run(CmdCtx *) override; private: uint32_t m_dcd_addr; }; class SDPReadMemCmd : public SDPCmdBase { public: SDPReadMemCmd(char*p); int run(CmdCtx *) override; private: uint32_t m_mem_addr; uint8_t m_mem_format; }; class SDPWriteMemCmd : public SDPCmdBase { public: SDPWriteMemCmd(char*p); int run(CmdCtx *p) override; private: uint32_t m_mem_addr; uint8_t m_mem_format; uint32_t m_mem_value; }; class SDPWriteCmd : public SDPCmdBase { public: SDPWriteCmd(char*p); int run(CmdCtx *p) override; int run(CmdCtx *p, void *buff, size_t size, uint32_t addr, bool validate = true); private: uint32_t m_download_addr; int32_t m_Ivt; int m_PlugIn; uint32_t m_max_download_pre_cmd; uint32_t m_offset; bool m_bIvtReserve; bool m_bskipspl = false; bool m_bskipfhdr = false; bool m_bscanterm = false; bool m_barebox_bl33 = false; }; class SDPJumpCmd : public SDPCmdBase { public: SDPJumpCmd(char*p); int run(CmdCtx *p) override; private: bool m_clear_dcd = false; int32_t m_Ivt = -1; uint32_t m_jump_addr = 0; bool m_PlugIn = false; }; class SDPSkipDCDCmd :public SDPCmdBase { public: SDPSkipDCDCmd(char *p); int run(CmdCtx *p) override; }; class SDPStatusCmd :public SDPCmdBase { public: SDPStatusCmd(char *p); int run(CmdCtx *p) override; }; class SDPBootCmd : public SDPCmdBase { public: SDPBootCmd(char *p); int run(CmdCtx *p) override; private: bool is_barebox_img(void); int load_barebox(CmdCtx *ctx); bool m_clear_dcd = false; uint32_t m_dcd_addr = 0; bool m_nojump = false; bool m_barebox = false; }; mfgtools-uuu_1.5.182/libuuu/sdps.cpp000066400000000000000000000131451462141313700174100ustar00rootroot00000000000000/* * Copyright 2018 NXP. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * Neither the name of the NXP Semiconductor nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #include #include "sdps.h" #include "hidreport.h" #include "liberror.h" #include "libcomm.h" #include "buffer.h" #include "sdp.h" #include "trans.h" #include #include //------------------------------------------------------------------------------ // HID Command Block Wrapper (CBW) //------------------------------------------------------------------------------ #pragma pack (1) typedef struct _CDBHIDDOWNLOAD { uint8_t Command; uint32_t Length; uint8_t Reserved[11]; } CDBHIDDOWNLOAD, *PCDBHIDDOWNLOAD; struct _ST_HID_CBW { uint32_t Signature; // Signature: 0x43544C42:1129598018, o "BLTC" (little endian) for the BLTC CBW uint32_t Tag; // Tag: to be returned in the csw uint32_t XferLength; // XferLength: number of bytes to transfer uint8_t Flags; // Flags: // Bit 7: direction - device shall ignore this bit if the // XferLength field is zero, otherwise: // 0 = data-out from the host to the device, // 1 = data-in from the device to the host. // Bits 6..0: reserved - shall be zero. uint8_t Reserved[2]; // Reserved - shall be zero. CDBHIDDOWNLOAD Cdb; // cdb: the command descriptor block }; #define BLTC_DOWNLOAD_FW 2 #define HID_BLTC_REPORT_TYPE_DATA_OUT 2 #define HID_BLTC_REPORT_TYPE_COMMAND_OUT 1 #define CBW_BLTC_SIGNATURE 0x43544C42; // "BLTC" (little endian) #define CBW_PITC_SIGNATURE 0x43544950; // "PITC" (little endian) // Flags values for _ST_HID_CBW #define CBW_DEVICE_TO_HOST_DIR 0x80; // "Data Out" #define CBW_HOST_TO_DEVICE_DIR 0x00; // "Data In" #pragma pack () #include "rominfo.h" static bool is_ivt_barker_header(shared_ptr data, size_t off) { if (off + sizeof(IvtHeader) > data->size()) return false; IvtHeader *p = (IvtHeader*)(data->data() + off); if (p->IvtBarker == IVT_BARKER_HEADER || p->IvtBarker == IVT_BARKER2_HEADER) return true; return false; } int SDPSCmd::run(CmdCtx *pro) { const ROM_INFO * rom = search_rom_info(pro->m_config_item); if (rom == nullptr) { string_ex err; err.format("%s:%d can't get rom info", __FUNCTION__, __LINE__); set_last_err_string(err); return -1; } HIDTrans dev(m_timeout); if (rom->flags & ROM_INFO_HID_EP1) dev.set_hid_out_ep(1); if(dev.open(pro->m_dev)) return -1; shared_ptr p1 = get_file_buffer(m_filename, true); if (!p1) return -1; shared_ptr p; HIDReport report(&dev); report.set_skip_notify(false); size_t offset = m_offset; vector buff; if (m_bscanterm) { p = p1->request_data(0, m_scan_limited); if (!p) return -1; if (IsMBR(p)) { size_t pos = 0, length; length = ScanTerm(p, pos, 512, m_scan_limited); if (length == 0) { set_last_err_string("This wic have NOT terminate tag after bootloader, please use new yocto"); return -1; } offset = pos - length; if (ssize_t(offset) < 0) { set_last_err_string("This wic boot length is wrong"); return -1; } p->resize(pos); } } else { p = p1->request_data(0, SIZE_MAX); //request all data if (!p) return -1; } if (m_bskipflashheader) offset += GetFlashHeaderSize(p, offset); // Detect barebox binaries that have the IVT header at offset 32K if (!is_ivt_barker_header(p, offset) && is_ivt_barker_header(p, offset + 0x8000)) offset += 0x8000; if (offset >= p->size()) { set_last_err_string("Offset bigger than file size"); return -1; } size_t sz = GetContainerActualSize(p, offset, rom->flags & ROM_INFO_HID_ROMAPI); if (!(rom->flags & ROM_INFO_HID_NO_CMD)) { _ST_HID_CBW cbw; uint32_t length = (uint32_t) sz; memset(&cbw, 0, sizeof(_ST_HID_CBW)); cbw.Cdb.Command = BLTC_DOWNLOAD_FW; cbw.Cdb.Length = EndianSwap(length); ++cbw.Tag; cbw.Signature = CBW_BLTC_SIGNATURE; cbw.XferLength = (uint32_t)length; cbw.Flags = CBW_HOST_TO_DEVICE_DIR; int ret = report.write(&cbw, sizeof(_ST_HID_CBW), HID_BLTC_REPORT_TYPE_COMMAND_OUT); if (ret) return ret; } if (rom->flags & ROM_INFO_HID_PACK_SIZE_1020) report.set_out_package_size(1020); int ret = report.write(p->data() + offset, sz, 2); if (ret == 0) { SDPBootlogCmd log(nullptr); log.run(pro); } return ret; } mfgtools-uuu_1.5.182/libuuu/sdps.h000066400000000000000000000042251462141313700170540ustar00rootroot00000000000000/* * Copyright 2018 NXP. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * Neither the name of the NXP Semiconductor nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #include "cmd.h" class SDPSCmd : public CmdBase { public: SDPSCmd(char *cmd) :CmdBase(cmd) { insert_param_info("boot", nullptr, Param::Type::e_null); insert_param_info("-f", &m_filename, Param::Type::e_string_filename); insert_param_info("-offset", &m_offset, Param::Type::e_uint32); insert_param_info("-skipfhdr", &m_bskipflashheader, Param::Type::e_bool); insert_param_info("-scanterm", &m_bscanterm, Param::Type::e_bool); insert_param_info("-scanlimited", &m_scan_limited, Param::Type::e_uint64); } int run(CmdCtx *p) override; private: bool m_bskipflashheader=0; bool m_bscanterm=0; std::string m_filename; uint32_t m_offset = 0; uint64_t m_scan_limited = UINT64_MAX; }; mfgtools-uuu_1.5.182/libuuu/sparse.cpp000066400000000000000000000121551462141313700177340ustar00rootroot00000000000000/* * Copyright 2020 NXP. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * Neither the name of the NXP Semiconductor nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #include "sparse.h" #include "liberror.h" #include #include int SparseFile::init_header(size_t blsz, int blcount) { sparse_header header; memset(&header, 0, sizeof(header)); header.magic = SPARSE_HEADER_MAGIC; header.major_version = 1; header.minor_version = 0; header.file_hdr_sz = sizeof(header); header.chunk_hdr_sz = sizeof(chunk_header); header.blk_sz = blsz; m_cur_chunk_header_pos = 0; if (blcount) { m_data.reserve(blsz*blcount + 0x1000); m_max_size = blsz * blcount; } m_data.clear(); push(&header, sizeof(header)); m_pcrc = (uint32_t*)(m_data.data() + offsetof(sparse_header, image_checksum)); return 0; } bool SparseFile::is_append_old_chuck(int type, void *p) { chunk_header_t *pchunk; pchunk = (chunk_header_t *)(m_data.data() + m_cur_chunk_header_pos); if (m_cur_chunk_header_pos == 0) return false; if (pchunk->chunk_type != type) return false; if (type == CHUNK_TYPE_FILL) { uint32_t a = *(uint32_t*)(pchunk + 1); uint32_t b = *(uint32_t*)p; if (a != b) return false; } return true; } bool SparseFile::is_same_value(void *data, size_t sz) { uint32_t *p = (uint32_t *)data; uint32_t val = *p; for (size_t i = 0; i < sz / sizeof(uint32_t); i++) if (val != p[i]) return false; return true; } bool SparseFile::is_validate_sparse_file(void *p, size_t) { sparse_header *pheader = (sparse_header*)p; if (pheader->magic == SPARSE_HEADER_MAGIC) return true; return false; } int SparseFile::push(void *p, size_t sz) { size_t pos = m_data.size(); m_data.resize(pos + sz); memcpy(m_data.data() + pos, p, sz); return 0; } int SparseFile::push_one_block(void *data, bool skip) { chunk_header_t *pchunk; pchunk = (chunk_header_t *)(m_data.data() + m_cur_chunk_header_pos); sparse_header *pheader; pheader = (sparse_header *)m_data.data(); pheader->total_blks++; int type = skip ? CHUNK_TYPE_DONT_CARE : CHUNK_TYPE_RAW; if (!is_append_old_chuck(type, data)) { chunk_header_t header; header.chunk_type = type; header.chunk_sz = 1; header.total_sz = sizeof(chunk_header_t); if (type == CHUNK_TYPE_RAW) header.total_sz += pheader->blk_sz; header.reserved1 = 0; pheader->total_chunks++; m_cur_chunk_header_pos = m_data.size(); push(&header, sizeof(chunk_header_t)); if (type == CHUNK_TYPE_RAW) push(data, pheader->blk_sz); } else { pchunk->chunk_sz++; if (type == CHUNK_TYPE_RAW) { push(data, pheader->blk_sz); pchunk->total_sz += pheader->blk_sz; } } if (m_data.size() + 2 * pheader->blk_sz > m_max_size ) { return -1; } return 0; } size_t SparseFile::push_one_chuck(chunk_header_t *p, void *data) { chunk_header_t cheader = *p; sparse_header *pheader; pheader = (sparse_header *)m_data.data(); size_t sz = p->total_sz - sizeof(chunk_header); if (p->total_sz + m_data.size() > m_max_size) { if (p->chunk_type == CHUNK_TYPE_RAW) { size_t blk = (m_max_size - m_data.size()) / pheader->blk_sz; if (blk < 2) return 0; blk -= 2; cheader.chunk_sz = blk; sz = blk * pheader->blk_sz; cheader.total_sz = sizeof(chunk_header_t) + sz; } else return 0; } push(&cheader, sizeof(chunk_header)); pheader->total_chunks ++; pheader->total_blks += cheader.chunk_sz; if (data) { push(data, sz); } return sz; } size_t SparseFile::push_raw_data(void *data, size_t sz) { chunk_header_t cheader; cheader.chunk_type = CHUNK_TYPE_RAW; sparse_header *pheader; pheader = (sparse_header *)m_data.data(); cheader.chunk_sz = sz / pheader->blk_sz; cheader.total_sz = cheader.chunk_sz*pheader->blk_sz + sizeof(chunk_header_t); pheader = (sparse_header *)m_data.data(); return push_one_chuck(&cheader, data); } mfgtools-uuu_1.5.182/libuuu/sparse.h000066400000000000000000000041631462141313700174010ustar00rootroot00000000000000/* * Copyright 2018 NXP. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * Neither the name of the NXP Semiconductor nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #pragma once #include "sparse_format.h" #include #include class SparseFile { public: std::vector m_data; static chunk_header_t * get_next_chunk(uint8_t *p, size_t &pos); int init_header(size_t blsz, int blcount); bool is_append_old_chuck(int type, void *p); bool is_same_value(void *data, size_t sz); static bool is_validate_sparse_file(void *p, size_t sz); int push(void *p, size_t sz); int push_one_block(void *data, bool skip=false); size_t push_one_chuck(chunk_header_t *p, void *data); size_t push_raw_data(void *data, size_t sz); private: size_t m_cur_chunk_header_pos; size_t m_max_size; uint32_t *m_pcrc; }; mfgtools-uuu_1.5.182/libuuu/sparse_format.h000066400000000000000000000045351462141313700207540ustar00rootroot00000000000000/* * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef _LIBSPARSE_SPARSE_FORMAT_H_ #define _LIBSPARSE_SPARSE_FORMAT_H_ #include typedef uint32_t __le32; typedef uint16_t __le16; #pragma pack(1) typedef struct sparse_header { __le32 magic; /* 0xed26ff3a */ __le16 major_version; /* (0x1) - reject images with higher major versions */ __le16 minor_version; /* (0x0) - allow images with higher minor versions */ __le16 file_hdr_sz; /* 28 bytes for first revision of the file format */ __le16 chunk_hdr_sz; /* 12 bytes for first revision of the file format */ __le32 blk_sz; /* block size in bytes, must be a multiple of 4 (4096) */ __le32 total_blks; /* total blocks in the non-sparse output image */ __le32 total_chunks; /* total chunks in the sparse input image */ __le32 image_checksum; /* CRC32 checksum of the original data, counting "don't care" */ /* as 0. Standard 802.3 polynomial, use a Public Domain */ /* table implementation */ } sparse_header_t; #define SPARSE_HEADER_MAGIC 0xed26ff3a #define CHUNK_TYPE_RAW 0xCAC1 #define CHUNK_TYPE_FILL 0xCAC2 #define CHUNK_TYPE_DONT_CARE 0xCAC3 #define CHUNK_TYPE_CRC32 0xCAC4 typedef struct chunk_header { __le16 chunk_type; /* 0xCAC1 -> raw; 0xCAC2 -> fill; 0xCAC3 -> don't care */ __le16 reserved1; __le32 chunk_sz; /* in blocks in output image */ __le32 total_sz; /* in bytes of chunk input file including chunk header and data */ } chunk_header_t; /* Following a Raw or Fill or CRC32 chunk is data. * For a Raw chunk, it's the data in chunk_sz * blk_sz. * For a Fill chunk, it's 4 bytes of the fill data. * For a CRC32 chunk, it's 4 bytes of CRC32 */ #pragma pack() #endif mfgtools-uuu_1.5.182/libuuu/tar.cpp000066400000000000000000000075651462141313700172360ustar00rootroot00000000000000/* * Copyright 2020 NXP. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * Neither the name of the NXP Semiconductor nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include "zlib.h" #include #include "buffer.h" #include "liberror.h" #include "libuuu.h" #include #include #include "tar.h" #include #include using namespace std; int Tar::Open(const string &filename) { bool end_of_file=false; char end_of_file_blocks[2*TAR_BLOCK_SIZE]; memset(end_of_file_blocks, 0, sizeof(end_of_file_blocks) ); m_tarfilename=filename; shared_ptr file = get_file_buffer(filename); if(file == nullptr) return -1; uint8_t* data=file->data(); uint64_t block_counter=0; while(!end_of_file) { if(!memcmp(end_of_file_blocks,data+block_counter*TAR_BLOCK_SIZE,TAR_BLOCK_SIZE)) { end_of_file=true; break; } struct Tar_header* th=(Tar_header*)(data+block_counter*TAR_BLOCK_SIZE); uint64_t size; string octal_str((char*)th->size); //printf("block_counter: %d\n",block_counter ); //printf("name: %s\n",th->name ); //printf("signature: %s\n",th->ustar ); //printf("size: %s\n", th->size); size=stoll(octal_str, 0, 8); string name((char*)th->name); m_filemap[name].size=size; m_filemap[name].offset=(block_counter+1)*TAR_BLOCK_SIZE; //+1 because the data located right after the header block m_filemap[name].filename.assign((char*)th->name); block_counter++; //skip the data blocks uint64_t data_block_num=size/TAR_BLOCK_SIZE; data_block_num += (size%TAR_BLOCK_SIZE>0)? 1:0; block_counter+=data_block_num; } return 0; } bool Tar::check_file_exist(const string &filename) { if (m_filemap.find(filename) == m_filemap.end()) { string err; err += "Can't find file "; err += filename; set_last_err_string(err); return false; } return true; } int Tar::get_file_buff(const string &filename, shared_ptr p ) { if (m_filemap.find(filename) == m_filemap.end()) { string err; err += "Can't find file "; err += filename; set_last_err_string(err); return -1; } p->resize(m_filemap[filename].size); atomic_fetch_or(&p->m_dataflags, FILEBUFFER_FLAG_KNOWN_SIZE); p->m_request_cv.notify_all(); shared_ptr file; file = get_file_buffer(m_tarfilename); size_t offset= m_filemap[filename].offset; size_t size=m_filemap[filename].size; p->ref_other_buffer(file, offset, size); atomic_fetch_or(&p->m_dataflags, FILEBUFFER_FLAG_LOADED); p->m_request_cv.notify_all(); return 0; } mfgtools-uuu_1.5.182/libuuu/tar.h000066400000000000000000000045621462141313700166750ustar00rootroot00000000000000/* * Copyright 2020 NXP. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * Neither the name of the NXP Semiconductor nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #pragma once #include #include #include #include class FileBuffer; #define TAR_BLOCK_SIZE 512 #pragma pack(1) struct Tar_header { uint8_t name[100]; uint8_t mode[8]; uint8_t owner_id[8]; uint8_t group_id[8]; uint8_t size[12]; uint8_t modi_time[12]; uint8_t checksum[8]; uint8_t type[1]; uint8_t linkname[100]; uint8_t ustar[6]; uint8_t version[2]; uint8_t uname[32]; uint8_t gname[32]; uint8_t major_num[8]; uint8_t minor_num[8]; uint8_t prefix[155]; }; #pragma pack() class Tar_file_Info { public: std::string filename; uint64_t offset; uint64_t size; }; class Tar { std::string m_tarfilename; public: std::map m_filemap; int Open(const std::string &filename); bool check_file_exist(const std::string &filename); int get_file_buff(const std::string &filename, std::shared_ptr p); }; mfgtools-uuu_1.5.182/libuuu/trans.cpp000066400000000000000000000154171462141313700175720ustar00rootroot00000000000000/* * Copyright 2018 NXP. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * Neither the name of the NXP Semiconductor nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #include "trans.h" #include "libcomm.h" #include "libuuu.h" #include "liberror.h" #include "libusb.h" #include "zip.h" extern "C" { #include "libusb.h" } using namespace std; TransBase::~TransBase() { } int TransBase::write(void *buff, size_t size) { int ret; for (int retry = 0; retry < m_retry; retry++) { ret = write_simple(buff, size); switch (ret) { case 0: return 0; case LIBUSB_ERROR_TIMEOUT: continue; default: return ret; } } return LIBUSB_ERROR_TIMEOUT; } int TransBase::read(void *buff, size_t size, size_t *return_size) { int ret; for (int retry = 0; retry < m_retry; retry++) { ret = read_simple(buff, size, return_size); switch (ret) { case 0: return 0; case LIBUSB_ERROR_TIMEOUT: continue; default: return ret; } } return LIBUSB_ERROR_TIMEOUT; } int TransBase::read(vector &buff) { size_t size; const auto ret = read(buff.data(), buff.size(), &size); if (ret) return ret; buff.resize(size); return ret; } int USBTrans::open(void *p) { m_devhandle = p; string_ex err; int libusb_ret = 0; libusb_device_handle * handle = (libusb_device_handle *)m_devhandle; if (libusb_kernel_driver_active(handle, 0)) { libusb_ret = libusb_detach_kernel_driver((libusb_device_handle *)m_devhandle, 0); if(libusb_ret < 0 && libusb_ret != LIBUSB_ERROR_NOT_SUPPORTED) { err.format("detach kernel driver failure (%d)", libusb_ret); set_last_err_string(err); return libusb_ret; } } if ((libusb_ret = libusb_claim_interface(handle, 0))) { err.format("Failure claim interface (%d)", libusb_ret); set_last_err_string(err); return libusb_ret; } libusb_config_descriptor *config; if ((libusb_ret = libusb_get_active_config_descriptor(libusb_get_device(handle), &config))) { err.format("Can't get config descriptor (%d)", libusb_ret); set_last_err_string(err); return libusb_ret; } m_EPs.clear(); for (int i = 0; i < config->interface[0].altsetting[0].bNumEndpoints; i++) { m_EPs.push_back(EPInfo(config->interface[0].altsetting[0].endpoint[i].bEndpointAddress, config->interface[0].altsetting[0].endpoint[i].wMaxPacketSize)); }; libusb_free_config_descriptor(config); return 0; } int USBTrans::close() { /* needn't clean resource here libusb_close will release all resource when finish running cmd */ return 0; } int HIDTrans::open(void *p) { int ret; if ((ret = USBTrans::open(p))) return ret; for (const auto &ep : m_EPs) { if (ep.addr > 0 && ((ep.addr & 0x80) == 0)) m_outEP = ep.addr; } return 0; } int HIDTrans::write_simple(void *buff, size_t size) { int ret; uint8_t *p = (uint8_t *)buff; int actual_size; if (m_outEP) { ret = libusb_interrupt_transfer( (libusb_device_handle *)m_devhandle, m_outEP, p, size, &actual_size, m_timeout ); } else { ret = libusb_control_transfer( (libusb_device_handle *)m_devhandle, LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE, m_set_report, (2 << 8) | p[0], 0, p, size, m_timeout ); } if (ret < 0) { string_ex err; err.format("HID(W): %s (%d)", libusb_error_name(ret), ret); set_last_err_string(err); return ret; } return ret; } int HIDTrans::read_simple(void *buff, size_t size, size_t *rsize) { int ret; int actual; ret = libusb_interrupt_transfer( (libusb_device_handle *)m_devhandle, 0x81, (uint8_t*)buff, size, &actual, m_timeout ); *rsize = actual; if (ret < 0) { string_ex err; err.format("HID(R): %s (%d)", libusb_error_name(ret), ret); set_last_err_string(err); return ret; } return 0; } int BulkTrans::write_simple(void *buff, size_t size) { int ret = 0; int actual_length; for (size_t i = 0; i < size; i += m_MaxTransPreRequest) { uint8_t *p = (uint8_t *)buff; p += i; size_t sz; sz = size - i; if (sz > m_MaxTransPreRequest) sz = m_MaxTransPreRequest; ret = libusb_bulk_transfer( (libusb_device_handle *)m_devhandle, m_ep_out.addr, p, sz, &actual_length, m_timeout ); if (ret < 0) { string_ex err; err.format("Bulk(W): %s (%d)", libusb_error_name(ret), ret); set_last_err_string(err); return ret; } } //Send zero package if (m_b_send_zero && ( (size%m_ep_out.package_size) == 0)) { ret = libusb_bulk_transfer( (libusb_device_handle *)m_devhandle, m_ep_out.addr, nullptr, 0, &actual_length, 2000 ); if (ret < 0) { string_ex err; err.format("Bulk(W): %s (%d)", libusb_error_name(ret), ret); set_last_err_string(err); return ret; } } return ret; } int BulkTrans::open(void *p) { int ret; if ((ret = USBTrans::open(p))) return ret; for (size_t i = 0; i < m_EPs.size(); i++) { if (m_EPs[i].addr > 0) { if ((m_EPs[0].addr & 0x80) && m_ep_in.addr == 0) m_ep_in = m_EPs[i]; else if (m_ep_out.addr == 0) m_ep_out = m_EPs[i]; } } return 0; } int BulkTrans::read_simple(void *buff, size_t size, size_t *rsize) { int ret; int actual_length; uint8_t *p = (uint8_t *)buff; if (size == 0) { *rsize = 0; return 0; } ret = libusb_bulk_transfer( (libusb_device_handle *)m_devhandle, m_ep_in.addr, p, size, &actual_length, m_timeout ); *rsize = actual_length; if (ret < 0) { string_ex err; err.format("Bulk(R): %s (%d)", libusb_error_name(ret), ret); set_last_err_string(err); return ret; } return ret; } mfgtools-uuu_1.5.182/libuuu/trans.h000066400000000000000000000070471462141313700172370ustar00rootroot00000000000000/* * Copyright 2018 NXP. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * Neither the name of the NXP Semiconductor nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #pragma once #include #include #include class TransBase { public: TransBase(int retry = 1) : m_retry{retry} {} TransBase(const TransBase&) = delete; TransBase& operator=(const TransBase&) = delete; virtual ~TransBase(); virtual int open(void *) { return 0; } virtual int close() { return 0; } int write(void *buff, size_t size); int read(void *buff, size_t size, size_t *return_size); int write(std::vector & buff) { return write(buff.data(), buff.size()); } int read(std::vector &buff); protected: void * m_devhandle = nullptr; int m_retry = 1; virtual int write_simple(void *buff, size_t size) = 0; virtual int read_simple(void *buff, size_t size, size_t *return_size) = 0; }; class EPInfo { public: constexpr EPInfo() = default; constexpr EPInfo(int a, int size) : addr{a}, package_size{size} {} int addr = 0; int package_size = 64; }; class USBTrans : public TransBase { public: USBTrans(int retry = 1) : TransBase(retry) {} int open(void *p) override; int close() override; protected: std::vector m_EPs; }; class HIDTrans : public USBTrans { public: HIDTrans(int timeout = 1000) : USBTrans(2), m_timeout{timeout} {} ~HIDTrans() override { if (m_devhandle) close(); m_devhandle = nullptr; } int open(void *p) override; void set_hid_out_ep(int ep) noexcept { m_outEP = ep; } protected: int write_simple(void *buff, size_t size) override; int read_simple(void *buff, size_t size, size_t *return_size) override; private: int m_outEP = 0; const int m_timeout = 1000; int m_set_report = 9; }; class BulkTrans : public USBTrans { public: BulkTrans(int timeout = 2000) : USBTrans(2), m_timeout{timeout} {} ~BulkTrans() override { if (m_devhandle) close(); m_devhandle = nullptr; } int open(void *p) override; protected: int write_simple(void *buff, size_t size) override; int read_simple(void *buff, size_t size, size_t *return_size) override; private: size_t m_MaxTransPreRequest = 0x100000; int m_b_send_zero = 0; EPInfo m_ep_in; EPInfo m_ep_out; int m_timeout = 2000; }; int polling_usb(std::atomic& bexit); mfgtools-uuu_1.5.182/libuuu/usbhotplug.cpp000066400000000000000000000322311462141313700206300ustar00rootroot00000000000000/* * Copyright 2018 NXP. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * Neither the name of the NXP Semiconductor nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ /* * Windows libusb don't support hotplug yet * Will polling devices list every 100ms */ #include #include #include #include #include #include #include "libusb.h" #include "liberror.h" #include "config.h" #include "cmd.h" #include "libcomm.h" #include "libuuu.h" #include "rominfo.h" #include "vector" #include #include using chrono::milliseconds; using chrono::operator ""ms; using chrono::seconds; using chrono::operator ""s; static atomic g_wait_usb_timeout{-1s}; static atomic g_usb_poll_period{200ms}; static atomic g_wait_next_usb_timeout{-1s}; enum KnownDeviceState { NoKnownDevice, KnownDeviceToDo, KnownDeviceDone, WaitNextKnownDevice, }; static atomic g_known_device_state{NoKnownDevice}; class CAutoDeInit { public: CAutoDeInit() { if (libusb_init(nullptr) < 0) throw runtime_error{ "Call libusb_init failure" }; } ~CAutoDeInit() { libusb_exit(nullptr); } } g_autoDeInit; class CAutoList { public: libusb_device **list = nullptr; CAutoList(libusb_device **list) { this->list = list; m_rc = -1; } CAutoList(CAutoList &&other) { this->list = other.list; this->m_rc = other.m_rc; other.list = nullptr; } CAutoList() { m_rc = libusb_get_device_list(nullptr, &list); if (m_rc < 0) { set_last_err_string(std::string("libusb_get_device_list failed: ") + libusb_strerror(static_cast(m_rc))); } } ~CAutoList() { if (list != nullptr) { libusb_free_device_list(list, 1); } } CAutoList& operator=(CAutoList &&other) { this->list = other.list; this->m_rc = other.m_rc; other.list = nullptr; return *this; } CAutoList& operator=(const CAutoList&) = delete; // Prevent copy, allow move only CAutoList(const CAutoList&) = delete; // Prevent copy, allow move only bool good() const { return m_rc >= 0; } private: int m_rc = 0; }; struct filter { vector list; mutex lock; void push_back(string filter) { lock_guard guard{lock}; list.emplace_back(std::move(filter)); } }; static struct: public filter { bool is_valid(const string& path) { lock_guard guard{lock}; if (list.empty()) return true; auto end = list.end(); auto pos = find(list.begin(), end, path); return pos != end; } } g_filter_usbpath; static struct: public filter { bool is_valid(const string& serial_no) { lock_guard guard{lock}; if (list.empty()) return true; if (serial_no.empty()) return false; for(auto it: list) { if (compare_str(serial_no.substr(0, it.length()), it, true)) return true; } return false; } } g_filter_usbserial_no; struct Timer { using Clock = chrono::steady_clock; Clock::time_point start; explicit Timer(Clock::time_point start) : start{start} {} Timer() : Timer{Clock::now()} {} bool is_elapsed(Clock::duration interval) const { return (Clock::now() - start) >= interval; } void reset(Clock::time_point start) { this->start = start; } void reset() { reset(Clock::now()); } }; #ifdef _MSC_VER #define TRY_SUDO #else #define TRY_SUDO ",Try sudo uuu" #endif static string get_device_path(libusb_device *dev) { uint8_t path[8]; int bus = libusb_get_bus_number(dev); string_ex str; str.format("%d:", bus); int ret = libusb_get_port_numbers(dev, path, sizeof(path)); if (ret < 0) return ""; string_ex s; s.format("%d", path[0]); str.append(s); for (int j = 1; j < ret; j++) { s.format("%d", path[j]); str.append(s); } return str; } #define SERIAL_NO_MAX 512 static string get_device_serial_no(libusb_device *dev, struct libusb_device_descriptor *desc, ConfigItem *item) { string serial; struct libusb_device_handle *dev_handle = NULL; int sid = desc->iSerialNumber; int ret = 0; if (!sid) { const ROM_INFO *info= search_rom_info(item); if (info) sid = info->serial_idx; } serial.resize(SERIAL_NO_MAX); libusb_open(dev, &dev_handle); if (sid && dev_handle) ret = libusb_get_string_descriptor_ascii(dev_handle, sid, (unsigned char*)serial.c_str(), SERIAL_NO_MAX); libusb_close(dev_handle); if(ret >= 0) serial.resize(ret); return str_to_upper(serial); } static string get_device_serial_no(libusb_device *dev) { string str; struct libusb_device_descriptor desc; int r = libusb_get_device_descriptor(dev, &desc); if (r < 0) { set_last_err_string("failure get device descriptor"); return str; } ConfigItem *item = get_config()->find(desc.idVendor, desc.idProduct, desc.bcdDevice); return get_device_serial_no(dev, &desc, item); } static int open_libusb(libusb_device *dev, void **usb_device_handle) { int retry = 10; while (retry) { retry--; /* work around windows open device failure 1/10 * sometime HID device detect need some time, refresh list * to make sure HID driver installed. * * On linux, udev rules may need some time to kick in, * so also retry on -EACCES. */ CAutoList l; int ret; if ((ret = libusb_open(dev, (libusb_device_handle **)(usb_device_handle))) < 0) { if ((ret != LIBUSB_ERROR_NOT_SUPPORTED && ret != LIBUSB_ERROR_ACCESS) || (retry == 0)) { set_last_err_string("Failure open usb device" TRY_SUDO); return -1; } this_thread::sleep_for(200ms); } else { return 0; } } return -1; } /** Thread function. Didn't call this function directly. Unbalance libusb_unref_device. Before start thread, need call libusb_ref_device to dev is free libusb_get_list() libusb_ref_device // avoid free at libusb_free_list if run_usb_cmd have not open device in time. thread start run_usb_cmds; libusb_free_list() */ static int run_usb_cmds(ConfigItem *item, libusb_device *dev, short bcddevice) { int ret; uuu_notify nt; nt.type = uuu_notify::NOTIFY_DEV_ATTACH; string str; str = get_device_path(dev); str += "-"; str += get_device_serial_no(dev); nt.str = (char*)str.c_str(); call_notify(nt); CmdUsbCtx ctx; ctx.m_config_item = item; ctx.m_current_bcd = bcddevice; if ((ret = open_libusb(dev, &(ctx.m_dev)))) { nt.type = uuu_notify::NOTIFY_CMD_END; nt.status = -1; call_notify(nt); return ret; } ret = run_cmds(item->m_protocol.c_str(), &ctx); g_known_device_state = KnownDeviceDone; nt.type = uuu_notify::NOTIFY_THREAD_EXIT; call_notify(nt); libusb_unref_device(dev); //ref_device when start thread clear_env(); return ret; } static int usb_add(libusb_device *dev) { struct libusb_device_descriptor desc; int r = libusb_get_device_descriptor(dev, &desc); if (r < 0) { set_last_err_string("failure get device descriptor"); return r; } string str; str = get_device_path(dev); if (!g_filter_usbpath.is_valid(str)) return -1; ConfigItem *item = get_config()->find(desc.idVendor, desc.idProduct, desc.bcdDevice); if (item) { string serial = get_device_serial_no(dev, &desc, item); if (!g_filter_usbserial_no.is_valid(serial)) return -1; g_known_device_state = KnownDeviceToDo; /* * start new thread, need increase dev ref number. * otherwise polling thread, free_device_list free device if open device call after free_device_list. */ libusb_ref_device(dev); std::thread(run_usb_cmds, item, dev, desc.bcdDevice).detach(); } return 0; } static int usb_remove(libusb_device * /*dev*/) { return 0; } void compare_list(libusb_device ** old, libusb_device **nw) { libusb_device * dev; int i = 0; if (old == nullptr) { while ((dev = nw[i++]) != nullptr) { usb_add(dev); } return; } while ((dev = nw[i++]) != nullptr) { libusb_device * p; int j = 0; while ((p = old[j++]) != nullptr) { if (p == dev) break;//find it. }; if (p != dev) usb_add(dev); } i = 0; while ((dev = old[i++]) != nullptr) { libusb_device * p; int j = 0; while ((p = nw[j++]) != nullptr) { if (p == dev) break;//find it. }; if (p != dev) usb_remove(dev); } } static int check_usb_timeout(Timer& usb_timer) { auto known_device_state = g_known_device_state.load(); if (known_device_state == KnownDeviceDone) { g_known_device_state = known_device_state = WaitNextKnownDevice; usb_timer.reset(); } auto usb_timeout = g_wait_usb_timeout.load(); if (usb_timeout >= 0s && known_device_state == NoKnownDevice) { if (usb_timer.is_elapsed(usb_timeout)) { set_last_err_string("Timeout: Wait for Known USB Device"); return -1; } } usb_timeout = g_wait_next_usb_timeout.load(); if (usb_timeout >= 0s && g_known_device_state == WaitNextKnownDevice) { if (usb_timer.is_elapsed(usb_timeout)) { set_last_err_string("Timeout: Wait for next USB Device"); return -1; } } return 0; } int polling_usb(std::atomic& bexit) { if (run_cmds("CFG:", nullptr)) return -1; Timer usb_timer; CAutoList oldlist(nullptr); while(!bexit) { CAutoList newlist; if (!newlist.good()) { return -1; } compare_list(oldlist.list, newlist.list); std::swap(oldlist, newlist); this_thread::sleep_for(g_usb_poll_period.load()); if (check_usb_timeout(usb_timer)) return -1; } return 0; } CmdUsbCtx::~CmdUsbCtx() { if (m_dev) { libusb_close((libusb_device_handle*)m_dev); m_dev = 0; } } int CmdUsbCtx::look_for_match_device(const char *pro) { if (run_cmds("CFG:", nullptr)) return -1; Timer usb_timer; while (1) { CAutoList l; if (!l.good()) { break; } size_t i = 0; libusb_device *dev; while ((dev = l.list[i++]) != nullptr) { struct libusb_device_descriptor desc; int r = libusb_get_device_descriptor(dev, &desc); if (r < 0) { set_last_err_string("failure get device descriptor"); return -1; } string str = get_device_path(dev); if (!g_filter_usbpath.is_valid(str)) continue; ConfigItem *item = get_config()->find(desc.idVendor, desc.idProduct, desc.bcdDevice); string serial_no = get_device_serial_no(dev, &desc, item); if (!g_filter_usbserial_no.is_valid(serial_no)) continue; if (item && item->m_protocol == str_to_upper(pro)) { uuu_notify nt; nt.type = uuu_notify::NOTIFY_DEV_ATTACH; m_config_item = item; m_current_bcd = desc.bcdDevice; int ret; if ((ret = open_libusb(dev, &(m_dev)))) return ret; nt.str = (char*)str.c_str(); call_notify(nt); return 0; } } this_thread::sleep_for(200ms); uuu_notify nt; nt.type = nt.NOTIFY_WAIT_FOR; nt.str = (char*)"Wait for Known USB"; call_notify(nt); if (check_usb_timeout(usb_timer)) return -1; } return -1; } int uuu_add_usbpath_filter(const char *path) { g_filter_usbpath.push_back(path); return 0; } int uuu_add_usbserial_no_filter(const char *serial_no) { g_filter_usbserial_no.push_back(serial_no); return 0; } int uuu_for_each_devices(uuu_ls_usb_devices fn, void *p) { CAutoList l; size_t i = 0; libusb_device *dev; if (!l.good()) { return -1; } while ((dev = l.list[i++]) != nullptr) { struct libusb_device_descriptor desc; int r = libusb_get_device_descriptor(dev, &desc); if (r < 0) { set_last_err_string("failure get device descriptor"); return -1; } string str = get_device_path(dev); ConfigItem *item = get_config()->find(desc.idVendor, desc.idProduct, desc.bcdDevice); if (item) { string serial = get_device_serial_no(dev, &desc, item); if (fn(str.c_str(), item->m_chip.c_str(), item->m_protocol.c_str(), desc.idVendor, desc.idProduct, desc.bcdDevice, serial.c_str(), p)) { set_last_err_string("call back return error"); return -1; } } } return 0; } int uuu_set_wait_timeout(int timeout_in_seconds) { g_wait_usb_timeout = seconds{timeout_in_seconds}; return 0; } void uuu_set_poll_period(int period_in_milliseconds) { g_usb_poll_period = milliseconds{period_in_milliseconds}; } int uuu_set_wait_next_timeout(int timeout_in_seconds) { g_wait_next_usb_timeout = seconds{timeout_in_seconds}; return 0; } mfgtools-uuu_1.5.182/libuuu/version.cpp000066400000000000000000000051011462141313700201150ustar00rootroot00000000000000/* * Copyright 2018 NXP. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * Neither the name of the NXP Semiconductor nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #include "gitversion.h" #include "libuuu.h" #include using namespace std; static constexpr auto g_version = GIT_VERSION; const char *uuu_get_version_string() { return g_version; } int uuu_get_version() { string version_str{g_version}; // Find first dot because major version number must be before it auto pos = version_str.find("."); // Find the position of the character right before the start of the number auto vs = version_str.find_last_not_of("0123456789", pos - 1); // Let "vs" point exactly to the first character of the major version number ++vs; string temp_num_str = version_str.substr(vs, pos - vs); const auto maj = static_cast(stoll(temp_num_str, nullptr, 10)); version_str = version_str.substr(pos + 1); pos = version_str.find("."); temp_num_str = version_str.substr(0, pos); const auto min = static_cast(stoll(temp_num_str, nullptr, 10)); version_str = version_str.substr(pos + 1); temp_num_str = version_str.substr(0, pos = version_str.find("-")); const auto build = static_cast(stoll(temp_num_str, nullptr, 10)); return (maj << 24) | (min << 12) | build; } mfgtools-uuu_1.5.182/libuuu/zip.cpp000066400000000000000000000202301462141313700172320ustar00rootroot00000000000000/* * Copyright 2018 NXP. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * Neither the name of the NXP Semiconductor nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include "buffer.h" #include "libcomm.h" #include "libuuu.h" #include "liberror.h" #include "zip.h" #define CHUNK 0x10000 int Zip::BuildDirInfo() { shared_ptr zipfile = get_file_buffer(m_filename); if (zipfile == nullptr) { return -1; } size_t i; Zip_eocd *peocd = nullptr; Zip64_eocd_locator *peocd64_loc = nullptr; Zip64_eocd *peocd64 = nullptr; for (i = zipfile->size() - sizeof(Zip_eocd); i > 0; i--) { peocd = (Zip_eocd*)(zipfile->data() + i); if (peocd->sign == EOCD_SIGNATURE) { if (peocd->offset_of_central_dir == 0xFFFFFFFF) {//zip64 for (size_t j = i - sizeof(Zip64_eocd_locator); j > 0; j--) { peocd64_loc = (Zip64_eocd_locator*)(zipfile->data() + j); if (peocd64_loc->sign == EOCD64_LOCATOR_SIGNATURE) { peocd64 = (Zip64_eocd*)(zipfile->data() + peocd64_loc->offset_of_eocd); if (peocd64->sign != EOCD64_SIGNATURE) { set_last_err_string("Can't find EOCD64_SIGNATURE, not a zip64 file"); return -1; } break; } if (zipfile->size() - j > 0x10000) { set_last_err_string("Can't find EOCD, not a zip file"); return -1; } } } break; } if (zipfile->size() - i > 0x10000) { set_last_err_string("Can't find EOCD, not a zip file"); return -1; } } if (peocd == 0) { set_last_err_string("Can't find EOCD, not a zip file"); return -1; } i = peocd64? peocd64->offset:peocd->offset_of_central_dir; size_t total = i; total += peocd64 ? peocd64->size: peocd->size_of_central_dir; while (i < total) { Zip_central_dir *pdir = (Zip_central_dir *)(zipfile->data() + i); if (pdir->sign != DIR_SIGNATURE) { set_last_err_string("DIR signature mismatched"); return -1; } Zip_file_Info info; info.m_filename.append((char*)pdir->filename, pdir->file_name_length); info.m_offset = pdir->offset; info.m_filesize = pdir->uncompressed_size; info.m_timestamp = (pdir->last_modify_date << 16) + pdir->last_modify_time; info.m_compressedsize = pdir->compressed_size; if (pdir->extrafield_length) { size_t e; for (e = 0; e < pdir->extrafield_length; /*dummy*/) { Zip_ext *ext = (Zip_ext*)(zipfile->data() + e + i + sizeof(Zip_central_dir) + pdir->file_name_length); if (ext->tag == 0x1) { size_t cur64 = 0; if (info.m_filesize == 0xFFFFFFFF) { info.m_filesize = *((uint64_t*)(((uint8_t*)ext) + sizeof(Zip_ext) + cur64)); cur64 += 8; } if (cur64 > ext->size) { set_last_err_string("error pass zip64"); return -1; } if (info.m_compressedsize == 0xFFFFFFFF) { info.m_compressedsize = *((uint64_t*)(((uint8_t*)ext) + sizeof(Zip_ext) + cur64)); cur64 += 8; } if (cur64 > ext->size) { set_last_err_string("error pass zip64"); return -1; } if (info.m_offset == 0xFFFFFFFF) { info.m_offset = *((uint64_t*)(((uint8_t*)ext) + sizeof(Zip_ext) + cur64)); cur64 += 8; } if (cur64 > ext->size) { set_last_err_string("error pass zip64"); return -1; } break; } e += ext->size + sizeof(Zip_ext); } } i += sizeof(Zip_central_dir) + pdir->extrafield_length + pdir->file_name_length + pdir->file_comment_length; m_filemap[info.m_filename] = info; } return 0; } bool Zip::check_file_exist(string filename) { if (m_filemap.find(filename) == m_filemap.end()) { string err; err += "Can't find file "; err += filename; set_last_err_string(err); return false; } return true; } int Zip::get_file_buff(string filename, shared_ptr p) { if (m_filemap.find(filename) == m_filemap.end()) { string err; err += "Can't find file "; err += filename; set_last_err_string(err); return -1; } uuu_notify ut; ut.type = uuu_notify::NOTIFY_DECOMPRESS_START; ut.str = (char*)filename.c_str(); call_notify(ut); return m_filemap[filename].decompress(this, p); } int Zip::Open(string filename) { m_filename = filename; return BuildDirInfo(); } Zip_file_Info::Zip_file_Info() { } Zip_file_Info::~Zip_file_Info() { memset(&m_strm, 0, sizeof(m_strm)); } int Zip_file_Info::decompress(Zip *pZip, shared_ptrp) { p->resize(m_filesize); atomic_fetch_or(&p->m_dataflags, FILEBUFFER_FLAG_KNOWN_SIZE); p->m_request_cv.notify_all(); uuu_notify ut; ut.type = uuu_notify::NOTIFY_DECOMPRESS_SIZE; ut.total = m_filesize; call_notify(ut); size_t lastpos = 0; shared_ptr zipfile = get_file_buffer(pZip->get_filename()); if (zipfile == nullptr) return -1; Zip_file_desc *file_desc=(Zip_file_desc *)(zipfile->data() + m_offset); if (file_desc->sign != FILE_SIGNATURE) { set_last_err_string("file signature miss matched"); return -1; } size_t off = sizeof(Zip_file_desc) + file_desc->file_name_length + file_desc->extrafield_length; if (file_desc->compress_method == 0) { p->ref_other_buffer(zipfile, m_offset + off, m_filesize); atomic_fetch_or(&p->m_dataflags, FILEBUFFER_FLAG_LOADED); p->m_request_cv.notify_all(); return 0; } if (file_desc->compress_method != 8) { set_last_err_string("Unsupported compress method"); return -1; } int ret; size_t pos = 0; memset(&m_strm, 0, sizeof(m_strm)); inflateInit2(&m_strm, -MAX_WBITS); /* decompress until deflate stream ends or end of file */ m_strm.avail_in = m_compressedsize; m_strm.next_in = zipfile->data() + m_offset + off; m_strm.total_in = m_compressedsize; /* run inflate() on input until output buffer not full */ size_t each_out_size = CHUNK; do { if (p->size() - pos < each_out_size) each_out_size = p->size() - pos; m_strm.avail_out = each_out_size; m_strm.next_out = p->data() + pos; ret = inflate(&m_strm, Z_NO_FLUSH); //assert(ret != Z_STREAM_ERROR); /* state not clobbered */ switch (ret) { case Z_NEED_DICT: ret = Z_DATA_ERROR; /* and fall through */ FALLTHROUGH // FALLTHROUGH case Z_DATA_ERROR: FALLTHROUGH // FALLTHROUGH case Z_MEM_ERROR: (void)inflateEnd(&m_strm); return -1; } size_t have = each_out_size - m_strm.avail_out; p->m_available_size = pos; p->m_request_cv.notify_all(); pos += have; if (pos - lastpos > 100 * 1024 * 1024) { uuu_notify ut; ut.type = uuu_notify::NOTIFY_DECOMPRESS_POS; ut.index = pos; call_notify(ut); lastpos = pos; } } while (ret != Z_STREAM_END); /* clean up and return */ (void)inflateEnd(&m_strm); if (ret != Z_STREAM_END) { set_last_err_string("decompress error"); return -1; } p->m_available_size = m_filesize; atomic_fetch_or(&p->m_dataflags, FILEBUFFER_FLAG_LOADED); p->m_request_cv.notify_all(); ut.type = uuu_notify::NOTIFY_DECOMPRESS_POS; ut.index = m_filesize; call_notify(ut); return 0; } mfgtools-uuu_1.5.182/libuuu/zip.h000066400000000000000000000111351462141313700167030ustar00rootroot00000000000000/* * Copyright 2018 NXP. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * Neither the name of the NXP Semiconductor nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #pragma once #include "backfile.h" #include "zlib.h" #include #include #include /* Allow opportunistic use of the C++17 fall-through attribute . */ #if defined(__cplusplus) && __cplusplus >= 201703L #define FALLTHROUGH [[fallthrough]] #else #define FALLTHROUGH #endif class FileBuffer; #pragma pack(1) struct Zip_data_desc { uint32_t sign; uint32_t crc; uint32_t compressed_size; uint32_t uncompressed_size; }; struct Zip_file_desc { uint32_t sign; uint16_t version_mini_extract; uint16_t flags; uint16_t compress_method; uint16_t last_modify_time; uint16_t last_modify_date; uint32_t crc; uint32_t compressed_size; uint32_t uncompressed_size; uint16_t file_name_length; uint16_t extrafield_length; uint8_t filename[0]; }; struct Zip_central_dir { uint32_t sign; uint16_t version; uint16_t version_mini_extract; uint16_t flags; uint16_t compress_method; uint16_t last_modify_time; uint16_t last_modify_date; uint32_t crc; uint32_t compressed_size; uint32_t uncompressed_size; uint16_t file_name_length; uint16_t extrafield_length; uint16_t file_comment_length; uint16_t disk_number; uint16_t internal_file_attr; uint32_t external_file_attr; uint32_t offset; uint8_t filename[0]; }; struct Zip64_central_dir { uint32_t sign; uint16_t version; uint16_t version_mini_extract; uint16_t flags; uint16_t compress_method; uint16_t last_modify_time; uint16_t last_modify_date; uint32_t crc; uint32_t compressed_size; uint32_t uncompressed_size; uint16_t file_name_length; uint16_t extrafield_length; uint16_t file_comment_length; uint16_t disk_number; uint16_t internal_file_attr; uint32_t external_file_attr; uint32_t offset; uint8_t filename[0]; }; struct Zip_eocd { uint32_t sign; uint16_t num_of_thisdisk; uint16_t start_disk_of_dir; uint16_t num_of_dir_ondisk; uint16_t num_of_dir; uint32_t size_of_central_dir; uint32_t offset_of_central_dir; uint16_t length_of_comment; uint8_t comment[0]; }; struct Zip64_eocd_locator { uint32_t sign; uint32_t num_of_thisdisk; uint64_t offset_of_eocd; uint32_t total_num_disks; }; struct Zip64_eocd { uint32_t sign; uint64_t size_of_eocd; uint16_t version; uint16_t version_mini_extract; uint32_t num_of_dir_ondisk; uint32_t num_of_disk; uint64_t total_ondisk; uint64_t total; uint64_t size; uint64_t offset; }; struct Zip_ext { uint16_t tag; uint16_t size; }; #define EOCD_SIGNATURE 0x06054b50 #define DIR_SIGNATURE 0x02014b50 #define DATA_SIGNATURE 0x08074b50 #define FILE_SIGNATURE 0x04034b50 #define EOCD64_LOCATOR_SIGNATURE 0x07064b50 #define EOCD64_SIGNATURE 0x06064b50 class Zip; class Zip_file_Info { public: Zip_file_Info(); ~Zip_file_Info(); int decompress(Zip *pZip, std::shared_ptr p); private: std::string m_filename; uint32_t m_timestamp; size_t m_filesize; size_t m_compressedsize; size_t m_offset; z_stream m_strm; friend Zip; }; class Zip : public Backfile { public: int BuildDirInfo(); bool check_file_exist(std::string filename); int get_file_buff(std::string filename, std::shared_ptrp); int Open(std::string filename); std::map m_filemap; }; #pragma pack() mfgtools-uuu_1.5.182/msvc/000077500000000000000000000000001462141313700153725ustar00rootroot00000000000000mfgtools-uuu_1.5.182/msvc/bzip2.vcxproj000066400000000000000000000327541462141313700200500ustar00rootroot00000000000000 Debug Win32 Release Win32 Debug x64 Release x64 NotUsing NotUsing NotUsing NotUsing NotUsing NotUsing NotUsing NotUsing NotUsing NotUsing NotUsing NotUsing NotUsing NotUsing NotUsing NotUsing NotUsing NotUsing NotUsing NotUsing NotUsing NotUsing NotUsing NotUsing NotUsing NotUsing NotUsing NotUsing NotUsing NotUsing NotUsing NotUsing NotUsing NotUsing NotUsing NotUsing NotUsing NotUsing NotUsing NotUsing NotUsing NotUsing NotUsing NotUsing 15.0 {B54C35CD-5FFE-4FEA-90BA-32894BCFC6BF} Win32Proj bzip2 10.0 StaticLibrary true Unicode $(DefaultPlatformToolset) StaticLibrary false true Unicode $(DefaultPlatformToolset) StaticLibrary true MultiByte $(DefaultPlatformToolset) StaticLibrary false true Unicode $(DefaultPlatformToolset) true true $(SolutionDir)$(Platform)\$(Configuration)\ false $(SolutionDir)$(Platform)\$(Configuration)\ false Use Level3 Disabled false _DEBUG;_LIB;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS; _CRT_NONSTDC_NO_DEPRECATE;;_CRT_SECURE_NO_WARNINGS; _CRT_NONSTDC_NO_DEPRECATE; true Windows true true Use Level3 Disabled false WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) _CRT_SECURE_NO_WARNINGS setmode=_setmode;_CRT_SECURE_NO_WARNINGS; _CRT_NONSTDC_NO_DEPRECATE; true Windows true Use Level3 MaxSpeed true true false WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) _CRT_SECURE_NO_WARNINGS setmode=_setmode;_CRT_SECURE_NO_WARNINGS; _CRT_NONSTDC_NO_DEPRECATE; true MultiThreaded Windows true true true Use Level3 MaxSpeed true true false NDEBUG;_LIB;%(PreprocessorDefinitions) _CRT_SECURE_NO_WARNINGS setmode=_setmode;_CRT_SECURE_NO_WARNINGS; _CRT_NONSTDC_NO_DEPRECATE; true MultiThreaded Windows true true true mfgtools-uuu_1.5.182/msvc/bzip2.vcxproj.filters000066400000000000000000000036131462141313700215070ustar00rootroot00000000000000 {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hh;hpp;hxx;hm;inl;inc;xsd {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files mfgtools-uuu_1.5.182/msvc/createversion.bat000066400000000000000000000005501462141313700207330ustar00rootroot00000000000000@echo off call git --version IF ERRORLEVEL 1 ( echo build from tarball ) ELSE ( IF "%APPVEYOR_BUILD_VERSION%" == "" ( echo build not from appveryor ) ELSE ( git tag -m "uuu %APPVEYOR_BUILD_VERSION%" uuu_%APPVEYOR_BUILD_VERSION% ) FOR /F "tokens=*" %%a in ('call git describe --long') do ( echo #define GIT_VERSION "lib%%a" > %1/gitversion.h ) ) mfgtools-uuu_1.5.182/msvc/libuuu.filters000066400000000000000000000021711462141313700202720ustar00rootroot00000000000000 {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hh;hpp;hxx;hm;inl;inc;xsd {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms Header Files Header Files Source Files mfgtools-uuu_1.5.182/msvc/libuuu.vcxproj000066400000000000000000000253061462141313700203220ustar00rootroot00000000000000 Debug Win32 Release Win32 Debug x64 Release x64 15.0 {048A9BD1-EEF8-4119-9DEF-219D7E177AAC} Win32Proj StaticLib1 10.0 StaticLibrary true MultiByte $(DefaultPlatformToolset) StaticLibrary false true MultiByte $(DefaultPlatformToolset) StaticLibrary true MultiByte $(DefaultPlatformToolset) StaticLibrary false true MultiByte $(DefaultPlatformToolset) true $(Configuration)\$(ProjectName)\ $(SolutionDir)$(Platform)\$(Configuration)\ $(VC_IncludePath);$(WindowsSDK_IncludePath);..\zlib;..\libsparse\include;..\bzip2;..\zstd\lib;..\tinyxml2 true $(VC_IncludePath);$(WindowsSDK_IncludePath);..\zlib;..\libsparse\include;..\bzip2;..\zstd\lib;..\tinyxml2 false $(Configuration)\$(ProjectName)\ $(SolutionDir)$(Platform)\$(Configuration)\ $(VC_IncludePath);$(WindowsSDK_IncludePath);..\zlib;..\libsparse\include;..\bzip2;..\zstd\lib;..\tinyxml2 false $(VC_IncludePath);$(WindowsSDK_IncludePath);..\zlib;..\libsparse\include;..\bzip2;..\zstd\lib;..\tinyxml2 NotUsing Level3 Disabled true WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) true ..\libusb\libusb Windows true createversion.bat ..\libuuu NotUsing Level3 Disabled true _DEBUG;_LIB;%(PreprocessorDefinitions) true ..\libusb\libusb Windows true createversion.bat ..\libuuu NotUsing Level3 MaxSpeed true true true WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) true ..\libusb\libusb MultiThreaded Windows true true true createversion.bat ..\libuuu NotUsing Level3 MaxSpeed true true true NDEBUG;_LIB;%(PreprocessorDefinitions) true ..\libusb\libusb MultiThreaded Windows true true true createversion.bat ..\libuuu mfgtools-uuu_1.5.182/msvc/libuuu.vcxproj.filters000066400000000000000000000102211462141313700217570ustar00rootroot00000000000000 {56b8d729-e8e8-4b90-be62-ef7a1d4e77c2} {9880b066-0013-4325-97c5-de85ce13b31f} Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files mfgtools-uuu_1.5.182/msvc/tinyxml2.vcxproj000066400000000000000000000176131462141313700206050ustar00rootroot00000000000000 Debug Win32 Release Win32 Debug x64 Release x64 15.0 Win32Proj {1e79162b-c055-462b-9f6b-3b03507d3703} tinyxml2 10.0 StaticLibrary true MultiByte $(DefaultPlatformToolset) StaticLibrary false true MultiByte $(DefaultPlatformToolset) StaticLibrary true MultiByte $(DefaultPlatformToolset) StaticLibrary false true MultiByte $(DefaultPlatformToolset) $(SolutionDir)$(Platform)\$(Configuration)\ $(SolutionDir)$(Platform)\$(Configuration)\ NotUsing Level3 Disabled true _DEBUG;_LIB;%(PreprocessorDefinitions) true false Windows true true NotUsing Level3 Disabled true WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) true false Windows true true NotUsing Level3 MaxSpeed true true true WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) true false MultiThreaded Windows true true true true NotUsing Level3 MaxSpeed true true true NDEBUG;_LIB;%(PreprocessorDefinitions) true false MultiThreaded Windows true true true true mfgtools-uuu_1.5.182/msvc/tinyxml2.vcxproj.filters000066400000000000000000000015201462141313700222420ustar00rootroot00000000000000 {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx Header Files Source Files mfgtools-uuu_1.5.182/msvc/uuu-static-link.sln000066400000000000000000000247701462141313700211600ustar00rootroot00000000000000 Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 VisualStudioVersion = 15.0.27130.2027 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libuuu", "libuuu.vcxproj", "{048A9BD1-EEF8-4119-9DEF-219D7E177AAC}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlib", "zlib.vcxproj", "{59666402-A775-49AC-A9BD-19FD528F5FD9}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bzip2", "bzip2.vcxproj", "{B54C35CD-5FFE-4FEA-90BA-32894BCFC6BF}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "uuu-static-link", "uuu-static-link.vcxproj", "{2950F8EE-7895-4431-858A-C21EE105C242}" ProjectSection(ProjectDependencies) = postProject {048A9BD1-EEF8-4119-9DEF-219D7E177AAC} = {048A9BD1-EEF8-4119-9DEF-219D7E177AAC} {1E79162B-C055-462B-9F6B-3B03507D3703} = {1E79162B-C055-462B-9F6B-3B03507D3703} {349EE8F9-7D25-4909-AAF5-FF3FADE72187} = {349EE8F9-7D25-4909-AAF5-FF3FADE72187} {59666402-A775-49AC-A9BD-19FD528F5FD9} = {59666402-A775-49AC-A9BD-19FD528F5FD9} {8BFD8150-94D5-4BF9-8A50-7BD9929A0850} = {8BFD8150-94D5-4BF9-8A50-7BD9929A0850} {B54C35CD-5FFE-4FEA-90BA-32894BCFC6BF} = {B54C35CD-5FFE-4FEA-90BA-32894BCFC6BF} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libzstd", "..\zstd\build\VS2010\libzstd\libzstd.vcxproj", "{8BFD8150-94D5-4BF9-8A50-7BD9929A0850}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libusb_static", "..\libusb\msvc\libusb_static.vcxproj", "{349EE8F9-7D25-4909-AAF5-FF3FADE72187}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tinyxml2", "tinyxml2.vcxproj", "{1E79162B-C055-462B-9F6B-3B03507D3703}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|ARM = Debug|ARM Debug|ARM64 = Debug|ARM64 Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 Release|ARM = Release|ARM Release|ARM64 = Release|ARM64 Release|x64 = Release|x64 Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {048A9BD1-EEF8-4119-9DEF-219D7E177AAC}.Debug|ARM.ActiveCfg = Debug|x64 {048A9BD1-EEF8-4119-9DEF-219D7E177AAC}.Debug|ARM.Build.0 = Debug|x64 {048A9BD1-EEF8-4119-9DEF-219D7E177AAC}.Debug|ARM64.ActiveCfg = Debug|x64 {048A9BD1-EEF8-4119-9DEF-219D7E177AAC}.Debug|ARM64.Build.0 = Debug|x64 {048A9BD1-EEF8-4119-9DEF-219D7E177AAC}.Debug|x64.ActiveCfg = Debug|x64 {048A9BD1-EEF8-4119-9DEF-219D7E177AAC}.Debug|x64.Build.0 = Debug|x64 {048A9BD1-EEF8-4119-9DEF-219D7E177AAC}.Debug|x86.ActiveCfg = Debug|Win32 {048A9BD1-EEF8-4119-9DEF-219D7E177AAC}.Debug|x86.Build.0 = Debug|Win32 {048A9BD1-EEF8-4119-9DEF-219D7E177AAC}.Release|ARM.ActiveCfg = Release|x64 {048A9BD1-EEF8-4119-9DEF-219D7E177AAC}.Release|ARM.Build.0 = Release|x64 {048A9BD1-EEF8-4119-9DEF-219D7E177AAC}.Release|ARM64.ActiveCfg = Release|x64 {048A9BD1-EEF8-4119-9DEF-219D7E177AAC}.Release|ARM64.Build.0 = Release|x64 {048A9BD1-EEF8-4119-9DEF-219D7E177AAC}.Release|x64.ActiveCfg = Release|x64 {048A9BD1-EEF8-4119-9DEF-219D7E177AAC}.Release|x64.Build.0 = Release|x64 {048A9BD1-EEF8-4119-9DEF-219D7E177AAC}.Release|x86.ActiveCfg = Release|Win32 {048A9BD1-EEF8-4119-9DEF-219D7E177AAC}.Release|x86.Build.0 = Release|Win32 {59666402-A775-49AC-A9BD-19FD528F5FD9}.Debug|ARM.ActiveCfg = Debug|x64 {59666402-A775-49AC-A9BD-19FD528F5FD9}.Debug|ARM.Build.0 = Debug|x64 {59666402-A775-49AC-A9BD-19FD528F5FD9}.Debug|ARM64.ActiveCfg = Debug|x64 {59666402-A775-49AC-A9BD-19FD528F5FD9}.Debug|ARM64.Build.0 = Debug|x64 {59666402-A775-49AC-A9BD-19FD528F5FD9}.Debug|x64.ActiveCfg = Debug|x64 {59666402-A775-49AC-A9BD-19FD528F5FD9}.Debug|x64.Build.0 = Debug|x64 {59666402-A775-49AC-A9BD-19FD528F5FD9}.Debug|x86.ActiveCfg = Debug|Win32 {59666402-A775-49AC-A9BD-19FD528F5FD9}.Debug|x86.Build.0 = Debug|Win32 {59666402-A775-49AC-A9BD-19FD528F5FD9}.Release|ARM.ActiveCfg = Release|x64 {59666402-A775-49AC-A9BD-19FD528F5FD9}.Release|ARM.Build.0 = Release|x64 {59666402-A775-49AC-A9BD-19FD528F5FD9}.Release|ARM64.ActiveCfg = Release|x64 {59666402-A775-49AC-A9BD-19FD528F5FD9}.Release|ARM64.Build.0 = Release|x64 {59666402-A775-49AC-A9BD-19FD528F5FD9}.Release|x64.ActiveCfg = Release|x64 {59666402-A775-49AC-A9BD-19FD528F5FD9}.Release|x64.Build.0 = Release|x64 {59666402-A775-49AC-A9BD-19FD528F5FD9}.Release|x86.ActiveCfg = Release|Win32 {59666402-A775-49AC-A9BD-19FD528F5FD9}.Release|x86.Build.0 = Release|Win32 {B54C35CD-5FFE-4FEA-90BA-32894BCFC6BF}.Debug|ARM.ActiveCfg = Debug|x64 {B54C35CD-5FFE-4FEA-90BA-32894BCFC6BF}.Debug|ARM.Build.0 = Debug|x64 {B54C35CD-5FFE-4FEA-90BA-32894BCFC6BF}.Debug|ARM64.ActiveCfg = Debug|x64 {B54C35CD-5FFE-4FEA-90BA-32894BCFC6BF}.Debug|ARM64.Build.0 = Debug|x64 {B54C35CD-5FFE-4FEA-90BA-32894BCFC6BF}.Debug|x64.ActiveCfg = Debug|x64 {B54C35CD-5FFE-4FEA-90BA-32894BCFC6BF}.Debug|x64.Build.0 = Debug|x64 {B54C35CD-5FFE-4FEA-90BA-32894BCFC6BF}.Debug|x86.ActiveCfg = Debug|Win32 {B54C35CD-5FFE-4FEA-90BA-32894BCFC6BF}.Debug|x86.Build.0 = Debug|Win32 {B54C35CD-5FFE-4FEA-90BA-32894BCFC6BF}.Release|ARM.ActiveCfg = Release|x64 {B54C35CD-5FFE-4FEA-90BA-32894BCFC6BF}.Release|ARM.Build.0 = Release|x64 {B54C35CD-5FFE-4FEA-90BA-32894BCFC6BF}.Release|ARM64.ActiveCfg = Release|x64 {B54C35CD-5FFE-4FEA-90BA-32894BCFC6BF}.Release|ARM64.Build.0 = Release|x64 {B54C35CD-5FFE-4FEA-90BA-32894BCFC6BF}.Release|x64.ActiveCfg = Release|x64 {B54C35CD-5FFE-4FEA-90BA-32894BCFC6BF}.Release|x64.Build.0 = Release|x64 {B54C35CD-5FFE-4FEA-90BA-32894BCFC6BF}.Release|x86.ActiveCfg = Release|Win32 {B54C35CD-5FFE-4FEA-90BA-32894BCFC6BF}.Release|x86.Build.0 = Release|Win32 {2950F8EE-7895-4431-858A-C21EE105C242}.Debug|ARM.ActiveCfg = Debug|x64 {2950F8EE-7895-4431-858A-C21EE105C242}.Debug|ARM.Build.0 = Debug|x64 {2950F8EE-7895-4431-858A-C21EE105C242}.Debug|ARM64.ActiveCfg = Debug|x64 {2950F8EE-7895-4431-858A-C21EE105C242}.Debug|ARM64.Build.0 = Debug|x64 {2950F8EE-7895-4431-858A-C21EE105C242}.Debug|x64.ActiveCfg = Debug|x64 {2950F8EE-7895-4431-858A-C21EE105C242}.Debug|x64.Build.0 = Debug|x64 {2950F8EE-7895-4431-858A-C21EE105C242}.Debug|x86.ActiveCfg = Debug|Win32 {2950F8EE-7895-4431-858A-C21EE105C242}.Debug|x86.Build.0 = Debug|Win32 {2950F8EE-7895-4431-858A-C21EE105C242}.Release|ARM.ActiveCfg = Release|x64 {2950F8EE-7895-4431-858A-C21EE105C242}.Release|ARM.Build.0 = Release|x64 {2950F8EE-7895-4431-858A-C21EE105C242}.Release|ARM64.ActiveCfg = Release|x64 {2950F8EE-7895-4431-858A-C21EE105C242}.Release|ARM64.Build.0 = Release|x64 {2950F8EE-7895-4431-858A-C21EE105C242}.Release|x64.ActiveCfg = Release|x64 {2950F8EE-7895-4431-858A-C21EE105C242}.Release|x64.Build.0 = Release|x64 {2950F8EE-7895-4431-858A-C21EE105C242}.Release|x86.ActiveCfg = Release|Win32 {2950F8EE-7895-4431-858A-C21EE105C242}.Release|x86.Build.0 = Release|Win32 {8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Debug|ARM.ActiveCfg = Debug|x64 {8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Debug|ARM.Build.0 = Debug|x64 {8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Debug|ARM64.ActiveCfg = Debug|x64 {8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Debug|ARM64.Build.0 = Debug|x64 {8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Debug|x64.ActiveCfg = Debug|x64 {8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Debug|x64.Build.0 = Debug|x64 {8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Debug|x86.ActiveCfg = Debug|Win32 {8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Debug|x86.Build.0 = Debug|Win32 {8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Release|ARM.ActiveCfg = Release|x64 {8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Release|ARM.Build.0 = Release|x64 {8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Release|ARM64.ActiveCfg = Release|x64 {8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Release|ARM64.Build.0 = Release|x64 {8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Release|x64.ActiveCfg = Release|x64 {8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Release|x64.Build.0 = Release|x64 {8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Release|x86.ActiveCfg = Release|Win32 {8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Release|x86.Build.0 = Release|Win32 {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|ARM.ActiveCfg = Debug|ARM {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|ARM.Build.0 = Debug|ARM {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|ARM64.ActiveCfg = Debug|ARM64 {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|ARM64.Build.0 = Debug|ARM64 {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|x64.ActiveCfg = Debug|x64 {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|x64.Build.0 = Debug|x64 {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|x86.ActiveCfg = Debug|Win32 {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Debug|x86.Build.0 = Debug|Win32 {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|ARM.ActiveCfg = Release|ARM {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|ARM.Build.0 = Release|ARM {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|ARM64.ActiveCfg = Release|ARM64 {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|ARM64.Build.0 = Release|ARM64 {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|x64.ActiveCfg = Release|x64 {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|x64.Build.0 = Release|x64 {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|x86.ActiveCfg = Release|Win32 {349EE8F9-7D25-4909-AAF5-FF3FADE72187}.Release|x86.Build.0 = Release|Win32 {1E79162B-C055-462B-9F6B-3B03507D3703}.Debug|ARM.ActiveCfg = Debug|x64 {1E79162B-C055-462B-9F6B-3B03507D3703}.Debug|ARM.Build.0 = Debug|x64 {1E79162B-C055-462B-9F6B-3B03507D3703}.Debug|ARM64.ActiveCfg = Debug|x64 {1E79162B-C055-462B-9F6B-3B03507D3703}.Debug|ARM64.Build.0 = Debug|x64 {1E79162B-C055-462B-9F6B-3B03507D3703}.Debug|x64.ActiveCfg = Debug|x64 {1E79162B-C055-462B-9F6B-3B03507D3703}.Debug|x64.Build.0 = Debug|x64 {1E79162B-C055-462B-9F6B-3B03507D3703}.Debug|x86.ActiveCfg = Debug|Win32 {1E79162B-C055-462B-9F6B-3B03507D3703}.Debug|x86.Build.0 = Debug|Win32 {1E79162B-C055-462B-9F6B-3B03507D3703}.Release|ARM.ActiveCfg = Release|x64 {1E79162B-C055-462B-9F6B-3B03507D3703}.Release|ARM.Build.0 = Release|x64 {1E79162B-C055-462B-9F6B-3B03507D3703}.Release|ARM64.ActiveCfg = Release|x64 {1E79162B-C055-462B-9F6B-3B03507D3703}.Release|ARM64.Build.0 = Release|x64 {1E79162B-C055-462B-9F6B-3B03507D3703}.Release|x64.ActiveCfg = Release|x64 {1E79162B-C055-462B-9F6B-3B03507D3703}.Release|x64.Build.0 = Release|x64 {1E79162B-C055-462B-9F6B-3B03507D3703}.Release|x86.ActiveCfg = Release|Win32 {1E79162B-C055-462B-9F6B-3B03507D3703}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {93EA02D1-E396-4390-B160-58909BBB9556} EndGlobalSection EndGlobal mfgtools-uuu_1.5.182/msvc/uuu-static-link.vcxproj000066400000000000000000000477061462141313700220630ustar00rootroot00000000000000 Debug Win32 Release Win32 Debug x64 Release x64 15.0 {2950F8EE-7895-4431-858A-C21EE105C242} Win32Proj uuu 10.0 Application true MultiByte $(DefaultPlatformToolset) Application false true MultiByte $(DefaultPlatformToolset) Application true MultiByte $(DefaultPlatformToolset) Application false true MultiByte $(DefaultPlatformToolset) true $(Configuration)\$(ProjectName)\ $(Platform)\$(Configuration) Build uuu true Build $(Platform)\$(Configuration) uuu false $(Configuration)\$(ProjectName)\ $(Platform)\$(Configuration) Build uuu false Build $(Platform)\$(Configuration) uuu NotUsing Level3 Disabled true WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true Console true ..\libusb\$(LibusbRootDir)build\$(PlatformToolset)\$(Platform)\$(Configuration)\lib\libusb-1.0.lib;$(Platform)/$(Configuration)/libuuu.lib;$(Platform)/$(Configuration)/zlib.lib;%(AdditionalDependencies);$(Platform)/$(Configuration)/bzip2.lib;$(SolutionDir)bin\$(Platform)_$(Configuration)\libzstd_static.lib;$(Platform)/$(Configuration)/tinyxml2.lib echo R^"####( > $(SolutionDir)\..\uuu\uuu.clst type $(SolutionDir)\..\uuu\uuu.lst >> $(SolutionDir)\..\uuu\uuu.clst echo )####^" >> $(SolutionDir)\..\uuu\uuu.clst echo R^"####( > $(SolutionDir)\..\uuu\emmc_burn_loader.clst type $(SolutionDir)\..\uuu\emmc_burn_loader.lst >> $(SolutionDir)\..\uuu\emmc_burn_loader.clst echo )####^" >> $(SolutionDir)\..\uuu\emmc_burn_loader.clst echo R^"####( > $(SolutionDir)\..\uuu\qspi_burn_loader.clst type $(SolutionDir)\..\uuu\qspi_burn_loader.lst >> $(SolutionDir)\..\uuu\qspi_burn_loader.clst echo )####^" >> $(SolutionDir)\..\uuu\qspi_burn_loader.clst echo R^"####( > $(SolutionDir)\..\uuu\fspinand_burn_loader.clst type $(SolutionDir)\..\uuu\fspinand_burn_loader.lst >> $(SolutionDir)\..\uuu\fspinand_burn_loader.clst echo )####^" >> $(SolutionDir)\..\uuu\fspinand_burn_loader.clst echo R^"####( > $(SolutionDir)\..\uuu\nvme_burn_all.clst type $(SolutionDir)\..\uuu\nvme_burn_all.lst >> $(SolutionDir)\..\uuu\nvme_burn_all.clst echo )####^" >> $(SolutionDir)\..\uuu\nvme_burn_all.clst echo R^"####( > $(SolutionDir)\..\uuu\sd_burn_loader.clst type $(SolutionDir)\..\uuu\sd_burn_loader.lst >> $(SolutionDir)\..\uuu\sd_burn_loader.clst echo )####^" >> $(SolutionDir)\..\uuu\sd_burn_loader.clst echo R^"####( > $(SolutionDir)\..\uuu\spl_boot.clst type $(SolutionDir)\..\uuu\spl_boot.lst >> $(SolutionDir)\..\uuu\spl_boot.clst echo )####^" >> $(SolutionDir)\..\uuu\spl_boot.clst echo R^"####( > $(SolutionDir)\..\uuu\emmc_burn_all.clst type $(SolutionDir)\..\uuu\emmc_burn_all.lst >> $(SolutionDir)\..\uuu\emmc_burn_all.clst echo )####^" >> $(SolutionDir)\..\uuu\emmc_burn_all.clst echo R^"####( > $(SolutionDir)\..\uuu\sd_burn_all.clst type $(SolutionDir)\..\uuu\sd_burn_all.lst >> $(SolutionDir)\..\uuu\sd_burn_all.clst echo )####^" >> $(SolutionDir)\..\uuu\sd_burn_all.clst echo R^"####( > $(SolutionDir)\..\uuu\fat_write.clst type $(SolutionDir)\..\uuu\fat_write.lst >> $(SolutionDir)\..\uuu\fat_write.clst echo )####^" >> $(SolutionDir)\..\uuu\fat_write.clst echo R^"####( > $(SolutionDir)\..\uuu\nand_burn_loader.clst type $(SolutionDir)\..\uuu\nand_burn_loader.lst >> $(SolutionDir)\..\uuu\nand_burn_loader.clst echo )####^" >> $(SolutionDir)\..\uuu\nand_burn_loader.clst true NotUsing Level3 Disabled true _DEBUG;_CONSOLE;%(PreprocessorDefinitions) true Console true ..\libusb\$(LibusbRootDir)build\$(PlatformToolset)\$(Platform)\$(Configuration)\lib\libusb-1.0.lib;$(Platform)/$(Configuration)/libuuu.lib;$(Platform)/$(Configuration)/zlib.lib;%(AdditionalDependencies);$(Platform)/$(Configuration)/bzip2.lib;$(SolutionDir)bin\$(Platform)_$(Configuration)\libzstd_static.lib;$(Platform)/$(Configuration)/tinyxml2.lib echo R^"####( > $(SolutionDir)\..\uuu\uuu.clst type $(SolutionDir)\..\uuu\uuu.lst >> $(SolutionDir)\..\uuu\uuu.clst echo )####^" >> $(SolutionDir)\..\uuu\uuu.clst echo R^"####( > $(SolutionDir)\..\uuu\emmc_burn_loader.clst type $(SolutionDir)\..\uuu\emmc_burn_loader.lst >> $(SolutionDir)\..\uuu\emmc_burn_loader.clst echo )####^" >> $(SolutionDir)\..\uuu\emmc_burn_loader.clst echo R^"####( > $(SolutionDir)\..\uuu\qspi_burn_loader.clst type $(SolutionDir)\..\uuu\qspi_burn_loader.lst >> $(SolutionDir)\..\uuu\qspi_burn_loader.clst echo )####^" >> $(SolutionDir)\..\uuu\qspi_burn_loader.clst echo R^"####( > $(SolutionDir)\..\uuu\fspinand_burn_loader.clst type $(SolutionDir)\..\uuu\fspinand_burn_loader.lst >> $(SolutionDir)\..\uuu\fspinand_burn_loader.clst echo )####^" >> $(SolutionDir)\..\uuu\fspinand_burn_loader.clst echo R^"####( > $(SolutionDir)\..\uuu\nvme_burn_all.clst type $(SolutionDir)\..\uuu\nvme_burn_all.lst >> $(SolutionDir)\..\uuu\nvme_burn_all.clst echo )####^" >> $(SolutionDir)\..\uuu\nvme_burn_all.clst echo R^"####( > $(SolutionDir)\..\uuu\sd_burn_loader.clst type $(SolutionDir)\..\uuu\sd_burn_loader.lst >> $(SolutionDir)\..\uuu\sd_burn_loader.clst echo )####^" >> $(SolutionDir)\..\uuu\sd_burn_loader.clst echo R^"####( > $(SolutionDir)\..\uuu\spl_boot.clst type $(SolutionDir)\..\uuu\spl_boot.lst >> $(SolutionDir)\..\uuu\spl_boot.clst echo )####^" >> $(SolutionDir)\..\uuu\spl_boot.clst echo R^"####( > $(SolutionDir)\..\uuu\emmc_burn_all.clst type $(SolutionDir)\..\uuu\emmc_burn_all.lst >> $(SolutionDir)\..\uuu\emmc_burn_all.clst echo )####^" >> $(SolutionDir)\..\uuu\emmc_burn_all.clst echo R^"####( > $(SolutionDir)\..\uuu\sd_burn_all.clst type $(SolutionDir)\..\uuu\sd_burn_all.lst >> $(SolutionDir)\..\uuu\sd_burn_all.clst echo )####^" >> $(SolutionDir)\..\uuu\sd_burn_all.clst echo R^"####( > $(SolutionDir)\..\uuu\fat_write.clst type $(SolutionDir)\..\uuu\fat_write.lst >> $(SolutionDir)\..\uuu\fat_write.clst echo )####^" >> $(SolutionDir)\..\uuu\fat_write.clst echo R^"####( > $(SolutionDir)\..\uuu\nand_burn_loader.clst type $(SolutionDir)\..\uuu\nand_burn_loader.lst >> $(SolutionDir)\..\uuu\nand_burn_loader.clst echo )####^" >> $(SolutionDir)\..\uuu\nand_burn_loader.clst true NotUsing Level3 MaxSpeed true true true WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded Console true true true ..\libusb\$(LibusbRootDir)build\$(PlatformToolset)\$(Platform)\$(Configuration)\lib\libusb-1.0.lib;$(Platform)/$(Configuration)/libuuu.lib;$(Platform)/$(Configuration)/zlib.lib;%(AdditionalDependencies);$(Platform)/$(Configuration)/bzip2.lib;$(SolutionDir)bin\$(Platform)_$(Configuration)\libzstd_static.lib;$(Platform)/$(Configuration)/tinyxml2.lib echo R^"####( > $(SolutionDir)\..\uuu\uuu.clst type $(SolutionDir)\..\uuu\uuu.lst >> $(SolutionDir)\..\uuu\uuu.clst echo )####^" >> $(SolutionDir)\..\uuu\uuu.clst echo R^"####( > $(SolutionDir)\..\uuu\emmc_burn_loader.clst type $(SolutionDir)\..\uuu\emmc_burn_loader.lst >> $(SolutionDir)\..\uuu\emmc_burn_loader.clst echo )####^" >> $(SolutionDir)\..\uuu\emmc_burn_loader.clst echo R^"####( > $(SolutionDir)\..\uuu\qspi_burn_loader.clst type $(SolutionDir)\..\uuu\qspi_burn_loader.lst >> $(SolutionDir)\..\uuu\qspi_burn_loader.clst echo )####^" >> $(SolutionDir)\..\uuu\qspi_burn_loader.clst echo R^"####( > $(SolutionDir)\..\uuu\fspinand_burn_loader.clst type $(SolutionDir)\..\uuu\fspinand_burn_loader.lst >> $(SolutionDir)\..\uuu\fspinand_burn_loader.clst echo )####^" >> $(SolutionDir)\..\uuu\fspinand_burn_loader.clst echo R^"####( > $(SolutionDir)\..\uuu\nvme_burn_all.clst type $(SolutionDir)\..\uuu\nvme_burn_all.lst >> $(SolutionDir)\..\uuu\nvme_burn_all.clst echo )####^" >> $(SolutionDir)\..\uuu\nvme_burn_all.clst echo R^"####( > $(SolutionDir)\..\uuu\sd_burn_loader.clst type $(SolutionDir)\..\uuu\sd_burn_loader.lst >> $(SolutionDir)\..\uuu\sd_burn_loader.clst echo )####^" >> $(SolutionDir)\..\uuu\sd_burn_loader.clst echo R^"####( > $(SolutionDir)\..\uuu\spl_boot.clst type $(SolutionDir)\..\uuu\spl_boot.lst >> $(SolutionDir)\..\uuu\spl_boot.clst echo )####^" >> $(SolutionDir)\..\uuu\spl_boot.clst echo R^"####( > $(SolutionDir)\..\uuu\emmc_burn_all.clst type $(SolutionDir)\..\uuu\emmc_burn_all.lst >> $(SolutionDir)\..\uuu\emmc_burn_all.clst echo )####^" >> $(SolutionDir)\..\uuu\emmc_burn_all.clst echo R^"####( > $(SolutionDir)\..\uuu\sd_burn_all.clst type $(SolutionDir)\..\uuu\sd_burn_all.lst >> $(SolutionDir)\..\uuu\sd_burn_all.clst echo )####^" >> $(SolutionDir)\..\uuu\sd_burn_all.clst echo R^"####( > $(SolutionDir)\..\uuu\fat_write.clst type $(SolutionDir)\..\uuu\fat_write.lst >> $(SolutionDir)\..\uuu\fat_write.clst echo )####^" >> $(SolutionDir)\..\uuu\fat_write.clst echo R^"####( > $(SolutionDir)\..\uuu\nand_burn_loader.clst type $(SolutionDir)\..\uuu\nand_burn_loader.lst >> $(SolutionDir)\..\uuu\nand_burn_loader.clst echo )####^" >> $(SolutionDir)\..\uuu\nand_burn_loader.clst true NotUsing Level3 MaxSpeed true true true NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded Console true true true ..\libusb\$(LibusbRootDir)build\$(PlatformToolset)\$(Platform)\$(Configuration)\lib\libusb-1.0.lib;$(Platform)/$(Configuration)/libuuu.lib;$(Platform)/$(Configuration)/zlib.lib;%(AdditionalDependencies);$(Platform)/$(Configuration)/bzip2.lib;$(SolutionDir)bin\$(Platform)_$(Configuration)\libzstd_static.lib;$(Platform)/$(Configuration)/tinyxml2.lib echo R^"####( > $(SolutionDir)\..\uuu\uuu.clst type $(SolutionDir)\..\uuu\uuu.lst >> $(SolutionDir)\..\uuu\uuu.clst echo )####^" >> $(SolutionDir)\..\uuu\uuu.clst echo R^"####( > $(SolutionDir)\..\uuu\emmc_burn_loader.clst type $(SolutionDir)\..\uuu\emmc_burn_loader.lst >> $(SolutionDir)\..\uuu\emmc_burn_loader.clst echo )####^" >> $(SolutionDir)\..\uuu\emmc_burn_loader.clst echo R^"####( > $(SolutionDir)\..\uuu\qspi_burn_loader.clst type $(SolutionDir)\..\uuu\qspi_burn_loader.lst >> $(SolutionDir)\..\uuu\qspi_burn_loader.clst echo )####^" >> $(SolutionDir)\..\uuu\qspi_burn_loader.clst echo R^"####( > $(SolutionDir)\..\uuu\fspinand_burn_loader.clst type $(SolutionDir)\..\uuu\fspinand_burn_loader.lst >> $(SolutionDir)\..\uuu\fspinand_burn_loader.clst echo )####^" >> $(SolutionDir)\..\uuu\fspinand_burn_loader.clst echo R^"####( > $(SolutionDir)\..\uuu\nvme_burn_all.clst type $(SolutionDir)\..\uuu\nvme_burn_all.lst >> $(SolutionDir)\..\uuu\nvme_burn_all.clst echo )####^" >> $(SolutionDir)\..\uuu\nvme_burn_all.clst echo R^"####( > $(SolutionDir)\..\uuu\sd_burn_loader.clst type $(SolutionDir)\..\uuu\sd_burn_loader.lst >> $(SolutionDir)\..\uuu\sd_burn_loader.clst echo )####^" >> $(SolutionDir)\..\uuu\sd_burn_loader.clst echo R^"####( > $(SolutionDir)\..\uuu\spl_boot.clst type $(SolutionDir)\..\uuu\spl_boot.lst >> $(SolutionDir)\..\uuu\spl_boot.clst echo )####^" >> $(SolutionDir)\..\uuu\spl_boot.clst echo R^"####( > $(SolutionDir)\..\uuu\emmc_burn_all.clst type $(SolutionDir)\..\uuu\emmc_burn_all.lst >> $(SolutionDir)\..\uuu\emmc_burn_all.clst echo )####^" >> $(SolutionDir)\..\uuu\emmc_burn_all.clst echo R^"####( > $(SolutionDir)\..\uuu\sd_burn_all.clst type $(SolutionDir)\..\uuu\sd_burn_all.lst >> $(SolutionDir)\..\uuu\sd_burn_all.clst echo )####^" >> $(SolutionDir)\..\uuu\sd_burn_all.clst echo R^"####( > $(SolutionDir)\..\uuu\fat_write.clst type $(SolutionDir)\..\uuu\fat_write.lst >> $(SolutionDir)\..\uuu\fat_write.clst echo )####^" >> $(SolutionDir)\..\uuu\fat_write.clst echo R^"####( > $(SolutionDir)\..\uuu\nand_burn_loader.clst type $(SolutionDir)\..\uuu\nand_burn_loader.lst >> $(SolutionDir)\..\uuu\nand_burn_loader.clst echo )####^" >> $(SolutionDir)\..\uuu\nand_burn_loader.clst true mfgtools-uuu_1.5.182/msvc/uuu.sln000066400000000000000000000247321462141313700167360ustar00rootroot00000000000000 Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 VisualStudioVersion = 15.0.27130.2027 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "uuu", "uuu.vcxproj", "{2950F8EE-7895-4431-858A-C21EE105C242}" ProjectSection(ProjectDependencies) = postProject {048A9BD1-EEF8-4119-9DEF-219D7E177AAC} = {048A9BD1-EEF8-4119-9DEF-219D7E177AAC} {1E79162B-C055-462B-9F6B-3B03507D3703} = {1E79162B-C055-462B-9F6B-3B03507D3703} {349EE8FA-7D25-4909-AAF5-FF3FADE72187} = {349EE8FA-7D25-4909-AAF5-FF3FADE72187} {59666402-A775-49AC-A9BD-19FD528F5FD9} = {59666402-A775-49AC-A9BD-19FD528F5FD9} {8BFD8150-94D5-4BF9-8A50-7BD9929A0850} = {8BFD8150-94D5-4BF9-8A50-7BD9929A0850} {B54C35CD-5FFE-4FEA-90BA-32894BCFC6BF} = {B54C35CD-5FFE-4FEA-90BA-32894BCFC6BF} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libuuu", "libuuu.vcxproj", "{048A9BD1-EEF8-4119-9DEF-219D7E177AAC}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlib", "zlib.vcxproj", "{59666402-A775-49AC-A9BD-19FD528F5FD9}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bzip2", "bzip2.vcxproj", "{B54C35CD-5FFE-4FEA-90BA-32894BCFC6BF}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libzstd", "..\zstd\build\VS2010\libzstd\libzstd.vcxproj", "{8BFD8150-94D5-4BF9-8A50-7BD9929A0850}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libusb_dll", "..\libusb\msvc\libusb_dll.vcxproj", "{349EE8FA-7D25-4909-AAF5-FF3FADE72187}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tinyxml2", "tinyxml2.vcxproj", "{1E79162B-C055-462B-9F6B-3B03507D3703}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|ARM = Debug|ARM Debug|ARM64 = Debug|ARM64 Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 Release|ARM = Release|ARM Release|ARM64 = Release|ARM64 Release|x64 = Release|x64 Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {2950F8EE-7895-4431-858A-C21EE105C242}.Debug|ARM.ActiveCfg = Debug|x64 {2950F8EE-7895-4431-858A-C21EE105C242}.Debug|ARM.Build.0 = Debug|x64 {2950F8EE-7895-4431-858A-C21EE105C242}.Debug|ARM64.ActiveCfg = Debug|x64 {2950F8EE-7895-4431-858A-C21EE105C242}.Debug|ARM64.Build.0 = Debug|x64 {2950F8EE-7895-4431-858A-C21EE105C242}.Debug|x64.ActiveCfg = Debug|x64 {2950F8EE-7895-4431-858A-C21EE105C242}.Debug|x64.Build.0 = Debug|x64 {2950F8EE-7895-4431-858A-C21EE105C242}.Debug|x86.ActiveCfg = Debug|Win32 {2950F8EE-7895-4431-858A-C21EE105C242}.Debug|x86.Build.0 = Debug|Win32 {2950F8EE-7895-4431-858A-C21EE105C242}.Release|ARM.ActiveCfg = Release|x64 {2950F8EE-7895-4431-858A-C21EE105C242}.Release|ARM.Build.0 = Release|x64 {2950F8EE-7895-4431-858A-C21EE105C242}.Release|ARM64.ActiveCfg = Release|x64 {2950F8EE-7895-4431-858A-C21EE105C242}.Release|ARM64.Build.0 = Release|x64 {2950F8EE-7895-4431-858A-C21EE105C242}.Release|x64.ActiveCfg = Release|x64 {2950F8EE-7895-4431-858A-C21EE105C242}.Release|x64.Build.0 = Release|x64 {2950F8EE-7895-4431-858A-C21EE105C242}.Release|x86.ActiveCfg = Release|Win32 {2950F8EE-7895-4431-858A-C21EE105C242}.Release|x86.Build.0 = Release|Win32 {048A9BD1-EEF8-4119-9DEF-219D7E177AAC}.Debug|ARM.ActiveCfg = Debug|x64 {048A9BD1-EEF8-4119-9DEF-219D7E177AAC}.Debug|ARM.Build.0 = Debug|x64 {048A9BD1-EEF8-4119-9DEF-219D7E177AAC}.Debug|ARM64.ActiveCfg = Debug|x64 {048A9BD1-EEF8-4119-9DEF-219D7E177AAC}.Debug|ARM64.Build.0 = Debug|x64 {048A9BD1-EEF8-4119-9DEF-219D7E177AAC}.Debug|x64.ActiveCfg = Debug|x64 {048A9BD1-EEF8-4119-9DEF-219D7E177AAC}.Debug|x64.Build.0 = Debug|x64 {048A9BD1-EEF8-4119-9DEF-219D7E177AAC}.Debug|x86.ActiveCfg = Debug|Win32 {048A9BD1-EEF8-4119-9DEF-219D7E177AAC}.Debug|x86.Build.0 = Debug|Win32 {048A9BD1-EEF8-4119-9DEF-219D7E177AAC}.Release|ARM.ActiveCfg = Release|x64 {048A9BD1-EEF8-4119-9DEF-219D7E177AAC}.Release|ARM.Build.0 = Release|x64 {048A9BD1-EEF8-4119-9DEF-219D7E177AAC}.Release|ARM64.ActiveCfg = Release|x64 {048A9BD1-EEF8-4119-9DEF-219D7E177AAC}.Release|ARM64.Build.0 = Release|x64 {048A9BD1-EEF8-4119-9DEF-219D7E177AAC}.Release|x64.ActiveCfg = Release|x64 {048A9BD1-EEF8-4119-9DEF-219D7E177AAC}.Release|x64.Build.0 = Release|x64 {048A9BD1-EEF8-4119-9DEF-219D7E177AAC}.Release|x86.ActiveCfg = Release|Win32 {048A9BD1-EEF8-4119-9DEF-219D7E177AAC}.Release|x86.Build.0 = Release|Win32 {59666402-A775-49AC-A9BD-19FD528F5FD9}.Debug|ARM.ActiveCfg = Debug|x64 {59666402-A775-49AC-A9BD-19FD528F5FD9}.Debug|ARM.Build.0 = Debug|x64 {59666402-A775-49AC-A9BD-19FD528F5FD9}.Debug|ARM64.ActiveCfg = Debug|x64 {59666402-A775-49AC-A9BD-19FD528F5FD9}.Debug|ARM64.Build.0 = Debug|x64 {59666402-A775-49AC-A9BD-19FD528F5FD9}.Debug|x64.ActiveCfg = Debug|x64 {59666402-A775-49AC-A9BD-19FD528F5FD9}.Debug|x64.Build.0 = Debug|x64 {59666402-A775-49AC-A9BD-19FD528F5FD9}.Debug|x86.ActiveCfg = Debug|Win32 {59666402-A775-49AC-A9BD-19FD528F5FD9}.Debug|x86.Build.0 = Debug|Win32 {59666402-A775-49AC-A9BD-19FD528F5FD9}.Release|ARM.ActiveCfg = Release|x64 {59666402-A775-49AC-A9BD-19FD528F5FD9}.Release|ARM.Build.0 = Release|x64 {59666402-A775-49AC-A9BD-19FD528F5FD9}.Release|ARM64.ActiveCfg = Release|x64 {59666402-A775-49AC-A9BD-19FD528F5FD9}.Release|ARM64.Build.0 = Release|x64 {59666402-A775-49AC-A9BD-19FD528F5FD9}.Release|x64.ActiveCfg = Release|x64 {59666402-A775-49AC-A9BD-19FD528F5FD9}.Release|x64.Build.0 = Release|x64 {59666402-A775-49AC-A9BD-19FD528F5FD9}.Release|x86.ActiveCfg = Release|Win32 {59666402-A775-49AC-A9BD-19FD528F5FD9}.Release|x86.Build.0 = Release|Win32 {B54C35CD-5FFE-4FEA-90BA-32894BCFC6BF}.Debug|ARM.ActiveCfg = Debug|x64 {B54C35CD-5FFE-4FEA-90BA-32894BCFC6BF}.Debug|ARM.Build.0 = Debug|x64 {B54C35CD-5FFE-4FEA-90BA-32894BCFC6BF}.Debug|ARM64.ActiveCfg = Debug|x64 {B54C35CD-5FFE-4FEA-90BA-32894BCFC6BF}.Debug|ARM64.Build.0 = Debug|x64 {B54C35CD-5FFE-4FEA-90BA-32894BCFC6BF}.Debug|x64.ActiveCfg = Debug|x64 {B54C35CD-5FFE-4FEA-90BA-32894BCFC6BF}.Debug|x64.Build.0 = Debug|x64 {B54C35CD-5FFE-4FEA-90BA-32894BCFC6BF}.Debug|x86.ActiveCfg = Debug|Win32 {B54C35CD-5FFE-4FEA-90BA-32894BCFC6BF}.Debug|x86.Build.0 = Debug|Win32 {B54C35CD-5FFE-4FEA-90BA-32894BCFC6BF}.Release|ARM.ActiveCfg = Release|x64 {B54C35CD-5FFE-4FEA-90BA-32894BCFC6BF}.Release|ARM.Build.0 = Release|x64 {B54C35CD-5FFE-4FEA-90BA-32894BCFC6BF}.Release|ARM64.ActiveCfg = Release|x64 {B54C35CD-5FFE-4FEA-90BA-32894BCFC6BF}.Release|ARM64.Build.0 = Release|x64 {B54C35CD-5FFE-4FEA-90BA-32894BCFC6BF}.Release|x64.ActiveCfg = Release|x64 {B54C35CD-5FFE-4FEA-90BA-32894BCFC6BF}.Release|x64.Build.0 = Release|x64 {B54C35CD-5FFE-4FEA-90BA-32894BCFC6BF}.Release|x86.ActiveCfg = Release|Win32 {B54C35CD-5FFE-4FEA-90BA-32894BCFC6BF}.Release|x86.Build.0 = Release|Win32 {8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Debug|ARM.ActiveCfg = Debug|x64 {8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Debug|ARM.Build.0 = Debug|x64 {8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Debug|ARM64.ActiveCfg = Debug|x64 {8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Debug|ARM64.Build.0 = Debug|x64 {8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Debug|x64.ActiveCfg = Debug|x64 {8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Debug|x64.Build.0 = Debug|x64 {8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Debug|x86.ActiveCfg = Debug|Win32 {8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Debug|x86.Build.0 = Debug|Win32 {8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Release|ARM.ActiveCfg = Release|x64 {8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Release|ARM.Build.0 = Release|x64 {8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Release|ARM64.ActiveCfg = Release|x64 {8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Release|ARM64.Build.0 = Release|x64 {8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Release|x64.ActiveCfg = Release|x64 {8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Release|x64.Build.0 = Release|x64 {8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Release|x86.ActiveCfg = Release|Win32 {8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Release|x86.Build.0 = Release|Win32 {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Debug|ARM.ActiveCfg = Debug|ARM {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Debug|ARM.Build.0 = Debug|ARM {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Debug|ARM64.ActiveCfg = Debug|ARM64 {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Debug|ARM64.Build.0 = Debug|ARM64 {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Debug|x64.ActiveCfg = Debug|x64 {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Debug|x64.Build.0 = Debug|x64 {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Debug|x86.ActiveCfg = Debug|Win32 {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Debug|x86.Build.0 = Debug|Win32 {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Release|ARM.ActiveCfg = Release|ARM {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Release|ARM.Build.0 = Release|ARM {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Release|ARM64.ActiveCfg = Release|ARM64 {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Release|ARM64.Build.0 = Release|ARM64 {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Release|x64.ActiveCfg = Release|x64 {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Release|x64.Build.0 = Release|x64 {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Release|x86.ActiveCfg = Release|Win32 {349EE8FA-7D25-4909-AAF5-FF3FADE72187}.Release|x86.Build.0 = Release|Win32 {1E79162B-C055-462B-9F6B-3B03507D3703}.Debug|ARM.ActiveCfg = Debug|x64 {1E79162B-C055-462B-9F6B-3B03507D3703}.Debug|ARM.Build.0 = Debug|x64 {1E79162B-C055-462B-9F6B-3B03507D3703}.Debug|ARM64.ActiveCfg = Debug|x64 {1E79162B-C055-462B-9F6B-3B03507D3703}.Debug|ARM64.Build.0 = Debug|x64 {1E79162B-C055-462B-9F6B-3B03507D3703}.Debug|x64.ActiveCfg = Debug|x64 {1E79162B-C055-462B-9F6B-3B03507D3703}.Debug|x64.Build.0 = Debug|x64 {1E79162B-C055-462B-9F6B-3B03507D3703}.Debug|x86.ActiveCfg = Debug|Win32 {1E79162B-C055-462B-9F6B-3B03507D3703}.Debug|x86.Build.0 = Debug|Win32 {1E79162B-C055-462B-9F6B-3B03507D3703}.Release|ARM.ActiveCfg = Release|x64 {1E79162B-C055-462B-9F6B-3B03507D3703}.Release|ARM.Build.0 = Release|x64 {1E79162B-C055-462B-9F6B-3B03507D3703}.Release|ARM64.ActiveCfg = Release|x64 {1E79162B-C055-462B-9F6B-3B03507D3703}.Release|ARM64.Build.0 = Release|x64 {1E79162B-C055-462B-9F6B-3B03507D3703}.Release|x64.ActiveCfg = Release|x64 {1E79162B-C055-462B-9F6B-3B03507D3703}.Release|x64.Build.0 = Release|x64 {1E79162B-C055-462B-9F6B-3B03507D3703}.Release|x86.ActiveCfg = Release|Win32 {1E79162B-C055-462B-9F6B-3B03507D3703}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {93EA02D1-E396-4390-B160-58909BBB9556} EndGlobalSection EndGlobal mfgtools-uuu_1.5.182/msvc/uuu.vcxproj000066400000000000000000000510141462141313700176260ustar00rootroot00000000000000 Debug Win32 Release Win32 Debug x64 Release x64 15.0 {2950F8EE-7895-4431-858A-C21EE105C242} Win32Proj uuu 10.0 Application true $(DefaultPlatformToolset) MultiByte Application false $(DefaultPlatformToolset) true MultiByte Application true $(DefaultPlatformToolset) MultiByte Application false $(DefaultPlatformToolset) true MultiByte true $(Configuration)\$(ProjectName)\ $(Platform)\$(Configuration) Build true Build $(Platform)\$(Configuration) false $(Configuration)\$(ProjectName)\ $(Platform)\$(Configuration) Build false Build $(Platform)\$(Configuration) NotUsing Level3 Disabled true WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true Console true ..\libusb\$(LibusbRootDir)build\$(PlatformToolset)\$(Platform)\$(Configuration)\dll\libusb-1.0.lib;$(Platform)/$(Configuration)/libuuu.lib;$(Platform)/$(Configuration)/zlib.lib;%(AdditionalDependencies);$(Platform)/$(Configuration)/bzip2.lib;$(SolutionDir)bin\$(Platform)_$(Configuration)\libzstd_static.lib;$(Platform)/$(Configuration)/tinyxml2.lib echo R^"####( > $(SolutionDir)\..\uuu\uuu.clst type $(SolutionDir)\..\uuu\uuu.lst >> $(SolutionDir)\..\uuu\uuu.clst echo )####^" >> $(SolutionDir)\..\uuu\uuu.clst echo R^"####( > $(SolutionDir)\..\uuu\emmc_burn_loader.clst type $(SolutionDir)\..\uuu\emmc_burn_loader.lst >> $(SolutionDir)\..\uuu\emmc_burn_loader.clst echo )####^" >> $(SolutionDir)\..\uuu\emmc_burn_loader.clst echo R^"####( > $(SolutionDir)\..\uuu\qspi_burn_loader.clst type $(SolutionDir)\..\uuu\qspi_burn_loader.lst >> $(SolutionDir)\..\uuu\qspi_burn_loader.clst echo )####^" >> $(SolutionDir)\..\uuu\qspi_burn_loader.clst echo R^"####( > $(SolutionDir)\..\uuu\fspinand_burn_loader.clst type $(SolutionDir)\..\uuu\fspinand_burn_loader.lst >> $(SolutionDir)\..\uuu\fspinand_burn_loader.clst echo )####^" >> $(SolutionDir)\..\uuu\fspinand_burn_loader.clst echo R^"####( > $(SolutionDir)\..\uuu\nvme_burn_all.clst type $(SolutionDir)\..\uuu\nvme_burn_all.lst >> $(SolutionDir)\..\uuu\nvme_burn_all.clst echo )####^" >> $(SolutionDir)\..\uuu\nvme_burn_all.clst echo R^"####( > $(SolutionDir)\..\uuu\sd_burn_loader.clst type $(SolutionDir)\..\uuu\sd_burn_loader.lst >> $(SolutionDir)\..\uuu\sd_burn_loader.clst echo )####^" >> $(SolutionDir)\..\uuu\sd_burn_loader.clst echo R^"####( > $(SolutionDir)\..\uuu\spl_boot.clst type $(SolutionDir)\..\uuu\spl_boot.lst >> $(SolutionDir)\..\uuu\spl_boot.clst echo )####^" >> $(SolutionDir)\..\uuu\spl_boot.clst echo R^"####( > $(SolutionDir)\..\uuu\emmc_burn_all.clst type $(SolutionDir)\..\uuu\emmc_burn_all.lst >> $(SolutionDir)\..\uuu\emmc_burn_all.clst echo )####^" >> $(SolutionDir)\..\uuu\emmc_burn_all.clst echo R^"####( > $(SolutionDir)\..\uuu\sd_burn_all.clst type $(SolutionDir)\..\uuu\sd_burn_all.lst >> $(SolutionDir)\..\uuu\sd_burn_all.clst echo )####^" >> $(SolutionDir)\..\uuu\sd_burn_all.clst echo R^"####( > $(SolutionDir)\..\uuu\fat_write.clst type $(SolutionDir)\..\uuu\fat_write.lst >> $(SolutionDir)\..\uuu\fat_write.clst echo )####^" >> $(SolutionDir)\..\uuu\fat_write.clst echo R^"####( > $(SolutionDir)\..\uuu\nand_burn_loader.clst type $(SolutionDir)\..\uuu\nand_burn_loader.lst >> $(SolutionDir)\..\uuu\nand_burn_loader.clst echo )####^" >> $(SolutionDir)\..\uuu\nand_burn_loader.clst true copy /y "..\libusb\$(LibusbRootDir)build\$(PlatformToolset)\$(Platform)\$(Configuration)\dll\*.dll" $(Platform)\$(Configuration)\ NotUsing Level3 Disabled true _DEBUG;_CONSOLE;%(PreprocessorDefinitions) true Console true ..\libusb\$(LibusbRootDir)build\$(PlatformToolset)\$(Platform)\$(Configuration)\dll\libusb-1.0.lib;$(Platform)/$(Configuration)/libuuu.lib;$(Platform)/$(Configuration)/zlib.lib;%(AdditionalDependencies);$(Platform)/$(Configuration)/bzip2.lib;$(SolutionDir)bin\$(Platform)_$(Configuration)\libzstd_static.lib;$(Platform)/$(Configuration)/tinyxml2.lib echo R^"####( > $(SolutionDir)\..\uuu\uuu.clst type $(SolutionDir)\..\uuu\uuu.lst >> $(SolutionDir)\..\uuu\uuu.clst echo )####^" >> $(SolutionDir)\..\uuu\uuu.clst echo R^"####( > $(SolutionDir)\..\uuu\emmc_burn_loader.clst type $(SolutionDir)\..\uuu\emmc_burn_loader.lst >> $(SolutionDir)\..\uuu\emmc_burn_loader.clst echo )####^" >> $(SolutionDir)\..\uuu\emmc_burn_loader.clst echo R^"####( > $(SolutionDir)\..\uuu\qspi_burn_loader.clst type $(SolutionDir)\..\uuu\qspi_burn_loader.lst >> $(SolutionDir)\..\uuu\qspi_burn_loader.clst echo )####^" >> $(SolutionDir)\..\uuu\qspi_burn_loader.clst echo R^"####( > $(SolutionDir)\..\uuu\fspinand_burn_loader.clst type $(SolutionDir)\..\uuu\fspinand_burn_loader.lst >> $(SolutionDir)\..\uuu\fspinand_burn_loader.clst echo )####^" >> $(SolutionDir)\..\uuu\fspinand_burn_loader.clst echo R^"####( > $(SolutionDir)\..\uuu\nvme_burn_all.clst type $(SolutionDir)\..\uuu\nvme_burn_all.lst >> $(SolutionDir)\..\uuu\nvme_burn_all.clst echo )####^" >> $(SolutionDir)\..\uuu\nvme_burn_all.clst echo R^"####( > $(SolutionDir)\..\uuu\sd_burn_loader.clst type $(SolutionDir)\..\uuu\sd_burn_loader.lst >> $(SolutionDir)\..\uuu\sd_burn_loader.clst echo )####^" >> $(SolutionDir)\..\uuu\sd_burn_loader.clst echo R^"####( > $(SolutionDir)\..\uuu\spl_boot.clst type $(SolutionDir)\..\uuu\spl_boot.lst >> $(SolutionDir)\..\uuu\spl_boot.clst echo )####^" >> $(SolutionDir)\..\uuu\spl_boot.clst echo R^"####( > $(SolutionDir)\..\uuu\emmc_burn_all.clst type $(SolutionDir)\..\uuu\emmc_burn_all.lst >> $(SolutionDir)\..\uuu\emmc_burn_all.clst echo )####^" >> $(SolutionDir)\..\uuu\emmc_burn_all.clst echo R^"####( > $(SolutionDir)\..\uuu\sd_burn_all.clst type $(SolutionDir)\..\uuu\sd_burn_all.lst >> $(SolutionDir)\..\uuu\sd_burn_all.clst echo )####^" >> $(SolutionDir)\..\uuu\sd_burn_all.clst echo R^"####( > $(SolutionDir)\..\uuu\fat_write.clst type $(SolutionDir)\..\uuu\fat_write.lst >> $(SolutionDir)\..\uuu\fat_write.clst echo )####^" >> $(SolutionDir)\..\uuu\fat_write.clst echo R^"####( > $(SolutionDir)\..\uuu\nand_burn_loader.clst type $(SolutionDir)\..\uuu\nand_burn_loader.lst >> $(SolutionDir)\..\uuu\nand_burn_loader.clst echo )####^" >> $(SolutionDir)\..\uuu\nand_burn_loader.clst true copy /y "..\libusb\$(LibusbRootDir)build\$(PlatformToolset)\$(Platform)\$(Configuration)\dll\*.dll" $(Platform)\$(Configuration)\ NotUsing Level3 MaxSpeed true true true WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded Console true true true ..\libusb\$(LibusbRootDir)build\$(PlatformToolset)\$(Platform)\$(Configuration)\dll\libusb-1.0.lib;$(Platform)/$(Configuration)/libuuu.lib;$(Platform)/$(Configuration)/zlib.lib;%(AdditionalDependencies);$(Platform)/$(Configuration)/bzip2.lib;$(SolutionDir)bin\$(Platform)_$(Configuration)\libzstd_static.lib;$(Platform)/$(Configuration)/tinyxml2.lib echo R^"####( > $(SolutionDir)\..\uuu\uuu.clst type $(SolutionDir)\..\uuu\uuu.lst >> $(SolutionDir)\..\uuu\uuu.clst echo )####^" >> $(SolutionDir)\..\uuu\uuu.clst echo R^"####( > $(SolutionDir)\..\uuu\emmc_burn_loader.clst type $(SolutionDir)\..\uuu\emmc_burn_loader.lst >> $(SolutionDir)\..\uuu\emmc_burn_loader.clst echo )####^" >> $(SolutionDir)\..\uuu\emmc_burn_loader.clst echo R^"####( > $(SolutionDir)\..\uuu\qspi_burn_loader.clst type $(SolutionDir)\..\uuu\qspi_burn_loader.lst >> $(SolutionDir)\..\uuu\qspi_burn_loader.clst echo )####^" >> $(SolutionDir)\..\uuu\qspi_burn_loader.clst echo R^"####( > $(SolutionDir)\..\uuu\fspinand_burn_loader.clst type $(SolutionDir)\..\uuu\fspinand_burn_loader.lst >> $(SolutionDir)\..\uuu\fspinand_burn_loader.clst echo )####^" >> $(SolutionDir)\..\uuu\fspinand_burn_loader.clst echo R^"####( > $(SolutionDir)\..\uuu\nvme_burn_all.clst type $(SolutionDir)\..\uuu\nvme_burn_all.lst >> $(SolutionDir)\..\uuu\nvme_burn_all.clst echo )####^" >> $(SolutionDir)\..\uuu\nvme_burn_all.clst echo R^"####( > $(SolutionDir)\..\uuu\sd_burn_loader.clst type $(SolutionDir)\..\uuu\sd_burn_loader.lst >> $(SolutionDir)\..\uuu\sd_burn_loader.clst echo )####^" >> $(SolutionDir)\..\uuu\sd_burn_loader.clst echo R^"####( > $(SolutionDir)\..\uuu\spl_boot.clst type $(SolutionDir)\..\uuu\spl_boot.lst >> $(SolutionDir)\..\uuu\spl_boot.clst echo )####^" >> $(SolutionDir)\..\uuu\spl_boot.clst echo R^"####( > $(SolutionDir)\..\uuu\emmc_burn_all.clst type $(SolutionDir)\..\uuu\emmc_burn_all.lst >> $(SolutionDir)\..\uuu\emmc_burn_all.clst echo )####^" >> $(SolutionDir)\..\uuu\emmc_burn_all.clst echo R^"####( > $(SolutionDir)\..\uuu\sd_burn_all.clst type $(SolutionDir)\..\uuu\sd_burn_all.lst >> $(SolutionDir)\..\uuu\sd_burn_all.clst echo )####^" >> $(SolutionDir)\..\uuu\sd_burn_all.clst echo R^"####( > $(SolutionDir)\..\uuu\fat_write.clst type $(SolutionDir)\..\uuu\fat_write.lst >> $(SolutionDir)\..\uuu\fat_write.clst echo )####^" >> $(SolutionDir)\..\uuu\fat_write.clst echo R^"####( > $(SolutionDir)\..\uuu\nand_burn_loader.clst type $(SolutionDir)\..\uuu\nand_burn_loader.lst >> $(SolutionDir)\..\uuu\nand_burn_loader.clst echo )####^" >> $(SolutionDir)\..\uuu\nand_burn_loader.clst true copy /y "..\libusb\$(LibusbRootDir)build\$(PlatformToolset)\$(Platform)\$(Configuration)\dll\*.dll" $(Platform)\$(Configuration)\ NotUsing Level3 MaxSpeed true true true NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded Console true true true ..\libusb\$(LibusbRootDir)build\$(PlatformToolset)\$(Platform)\$(Configuration)\dll\libusb-1.0.lib;$(Platform)/$(Configuration)/libuuu.lib;$(Platform)/$(Configuration)/zlib.lib;%(AdditionalDependencies);$(Platform)/$(Configuration)/bzip2.lib;$(SolutionDir)bin\$(Platform)_$(Configuration)\libzstd_static.lib;$(Platform)/$(Configuration)/tinyxml2.lib echo R^"####( > $(SolutionDir)\..\uuu\uuu.clst type $(SolutionDir)\..\uuu\uuu.lst >> $(SolutionDir)\..\uuu\uuu.clst echo )####^" >> $(SolutionDir)\..\uuu\uuu.clst echo R^"####( > $(SolutionDir)\..\uuu\emmc_burn_loader.clst type $(SolutionDir)\..\uuu\emmc_burn_loader.lst >> $(SolutionDir)\..\uuu\emmc_burn_loader.clst echo )####^" >> $(SolutionDir)\..\uuu\emmc_burn_loader.clst echo R^"####( > $(SolutionDir)\..\uuu\qspi_burn_loader.clst type $(SolutionDir)\..\uuu\qspi_burn_loader.lst >> $(SolutionDir)\..\uuu\qspi_burn_loader.clst echo )####^" >> $(SolutionDir)\..\uuu\qspi_burn_loader.clst echo R^"####( > $(SolutionDir)\..\uuu\fspinand_burn_loader.clst type $(SolutionDir)\..\uuu\fspinand_burn_loader.lst >> $(SolutionDir)\..\uuu\fspinand_burn_loader.clst echo )####^" >> $(SolutionDir)\..\uuu\fspinand_burn_loader.clst echo R^"####( > $(SolutionDir)\..\uuu\nvme_burn_all.clst type $(SolutionDir)\..\uuu\nvme_burn_all.lst >> $(SolutionDir)\..\uuu\nvme_burn_all.clst echo )####^" >> $(SolutionDir)\..\uuu\nvme_burn_all.clst echo R^"####( > $(SolutionDir)\..\uuu\sd_burn_loader.clst type $(SolutionDir)\..\uuu\sd_burn_loader.lst >> $(SolutionDir)\..\uuu\sd_burn_loader.clst echo )####^" >> $(SolutionDir)\..\uuu\sd_burn_loader.clst echo R^"####( > $(SolutionDir)\..\uuu\spl_boot.clst type $(SolutionDir)\..\uuu\spl_boot.lst >> $(SolutionDir)\..\uuu\spl_boot.clst echo )####^" >> $(SolutionDir)\..\uuu\spl_boot.clst echo R^"####( > $(SolutionDir)\..\uuu\emmc_burn_all.clst type $(SolutionDir)\..\uuu\emmc_burn_all.lst >> $(SolutionDir)\..\uuu\emmc_burn_all.clst echo )####^" >> $(SolutionDir)\..\uuu\emmc_burn_all.clst echo R^"####( > $(SolutionDir)\..\uuu\sd_burn_all.clst type $(SolutionDir)\..\uuu\sd_burn_all.lst >> $(SolutionDir)\..\uuu\sd_burn_all.clst echo )####^" >> $(SolutionDir)\..\uuu\sd_burn_all.clst echo R^"####( > $(SolutionDir)\..\uuu\fat_write.clst type $(SolutionDir)\..\uuu\fat_write.lst >> $(SolutionDir)\..\uuu\fat_write.clst echo )####^" >> $(SolutionDir)\..\uuu\fat_write.clst echo R^"####( > $(SolutionDir)\..\uuu\nand_burn_loader.clst type $(SolutionDir)\..\uuu\nand_burn_loader.lst >> $(SolutionDir)\..\uuu\nand_burn_loader.clst echo )####^" >> $(SolutionDir)\..\uuu\nand_burn_loader.clst true copy /y "..\libusb\$(LibusbRootDir)build\$(PlatformToolset)\$(Platform)\$(Configuration)\dll\*.dll" $(Platform)\$(Configuration)\ mfgtools-uuu_1.5.182/msvc/uuu.vcxproj.filters000066400000000000000000000023711462141313700212770ustar00rootroot00000000000000 {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hh;hpp;hxx;hm;inl;inc;xsd {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms Source Files Source Files Source Files Header Files mfgtools-uuu_1.5.182/msvc/zlib.vcxproj000066400000000000000000000216051462141313700177530ustar00rootroot00000000000000 Debug Win32 Release Win32 Debug x64 Release x64 15.0 {59666402-A775-49AC-A9BD-19FD528F5FD9} Win32Proj zlib 10.0 StaticLibrary true MultiByte $(DefaultPlatformToolset) StaticLibrary false true MultiByte $(DefaultPlatformToolset) StaticLibrary true MultiByte $(DefaultPlatformToolset) StaticLibrary false true MultiByte $(DefaultPlatformToolset) true true $(SolutionDir)$(Platform)\$(Configuration)\ false $(SolutionDir)$(Platform)\$(Configuration)\ false NotUsing Level3 Disabled true _DEBUG;_LIB;%(PreprocessorDefinitions) true false Windows true true NotUsing Level3 Disabled true WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) true false Windows true true NotUsing Level3 MaxSpeed true true true WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) true false MultiThreaded Windows true true true true NotUsing Level3 MaxSpeed true true true NDEBUG;_LIB;%(PreprocessorDefinitions) true false MultiThreaded Windows true true true true mfgtools-uuu_1.5.182/msvc/zlib.vcxproj.filters000066400000000000000000000047071462141313700214260ustar00rootroot00000000000000 {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hh;hpp;hxx;hm;inl;inc;xsd {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms Header Files Header Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files mfgtools-uuu_1.5.182/snap/000077500000000000000000000000001462141313700153635ustar00rootroot00000000000000mfgtools-uuu_1.5.182/snap/gui/000077500000000000000000000000001462141313700161475ustar00rootroot00000000000000mfgtools-uuu_1.5.182/snap/gui/universal-update-utility.png000066400000000000000000000146141462141313700236540ustar00rootroot00000000000000PNG  IHDRɿsRGBgAMA a pHYs%%IR$!IDATx^ˑHȂ9+EEeLicf3ޕxCJl Qhz'v;ܯ:RMKOe/w;޸~oPc[)-wg$3Lm.]jpRS5\0ĉyb6sLri'Zj1;α5\&}~Q5sry̮gZ rc-6ݝ0 | 9>ZQ^:zr/b|i\;^vt#YU]:d&͓(x"pSyork:1iJhUTGSgU=;y4~n>˜4t0Au0Nҟ.B]c5QS26]#imW-%Vm}iR3M:[ SL(Lm!QT~yk4iMYkB 9T"BlTy_zFu=~WuRq%υh™Orƌ3_vDm-,gf(I#<\ [2lЈ k)&+6s~7>Iq'kβ[N~ ND%Tqmz惣8Y\6ݜ!tIf5jSUYP}|6L] ڗMw0fNyy7.:Ԋ8(OV&[b WUm5٥LY1ણ,M'nzE;[ֶ+ÁNx1p+ƥptk wsTe씍aIEI$T~p *G[*)eczWxc㱛A>\#qr&k[pqp#n*$ۢ97EpmK²9J̴hn$z:eYS_]6xV&ç9//)qgtHwCdLϢ1S- -";ZV[k]/ϊJ`%\><}9NY4DgW`'AvN{5}AQ,N4 yO365Ѫ}<>Wg@+j%H6,S3)4rk{spfB#Gsq<Ɲ$s: O^]u;>eEnNz˶S8fto*Qpc;kO>څ4f-i̴hZ6+eѭ]"==|j Is\3?i:|g;Vw'Osst-իSO1sGWam,oS9ۼepm>bzY ^ gs.j'JպNlԅy%cIG$'a:ao0z02myY\Gܷf٨$`2,Ebg||a?:bw3[95|x;1] ְ2Llq t::?>]Ex#>YYdXhl95:E{ wtoa&or+#ީ6|\B~^e]%2%KiӮyq}lKcÇ[qg_kc^|ETwZ-*+z"`kQ^kܞS`e"~R&۴gчnr5\JsD+[ fkg7XEkMA&bz)ε^3Mi'IV|׹1s 5.%΢WJ_=$qEh6gpYIWrKoiK{ U+3NLl2VVIxӴ)o:`L4pQEU$:4lk|.v0k%68t+ߨ;Si[ڕsD7Sֻ:cF,1F=Blxu:SiVV2<7%?\\-$Q  <1`=4^^7֨onMWnx|BX#Et9)6w`Ğv<1z%$8 ͼ$ۣL?U-kqV;?~~/_|qe#J%ϯȁϿC?~GDǯ3]ICAoa$Zo??qR^{]G۝/^X rLg9 Ms#岱GiaovayXoXy+֬2ӷ0U^gqYS [5Ukc^Xf 㘹|ެS䉉iO[;,}bqĤk/g?~Q ߱4dLJ8p u{gwzuc՗YPtWsʋ-tu,lyNzbZ֋VZvZXk(b6M-ΞsH3gc3& lc-KF csX¤62'OLĆJ5t>vspv#k 'F8{[ x郳v_EDYHsvf/c7Ro㋲$c?I"еD9jW1ٶnΜU{S<󴳩/ m%X,Fۦvpßb?-^ދA{Hֳ-cGNE󸞞I+Ol(I_4QMU&嶵czYv4l`Z͞VzO;ʆG?F쉙YCwK8ʛkToGvX-i"~d3ZOtkK5kHLKƤsK~;_xr|VaD[eLv}'(r0^rxtJ9>v6 IkP419 \1vv4X54<֡r6'fo컝9郏) e"Yn[n;eG<5^ a;nsg $TÎquh1Eۓ/е7ZCD07 ξʱNh/ʒd')' ~JWAL$Qøzu/(gY,?!Yx>x^o4cx zjahџYxM~PbIENDB`mfgtools-uuu_1.5.182/snap/hooks/000077500000000000000000000000001462141313700165065ustar00rootroot00000000000000mfgtools-uuu_1.5.182/snap/hooks/configure000077500000000000000000000013261462141313700204170ustar00rootroot00000000000000#!/usr/bin/env bash # Configure hook to set up configuration when `snap set` is called # # Copyright (c) 2021 Snapcrafters # lint: The use of backticks in the printf messages is intended # shellcheck disable=SC2016 set \ -o errexit \ -o errtrace \ -o nounset \ -o pipefail disable_snap_confinement_warnings="$(snapctl get disable-snap-confinement-warnings)" if test -n "${disable_snap_confinement_warnings}"; then if [[ ! "${disable_snap_confinement_warnings}" =~ (false|true) ]]; then printf -- \ 'Error: disable-snap-confinement-warnings must be either `true` or `false`.\n' \ 1>&2 exit 1 fi else snapctl set disable-snap-confinement-warnings=false fi mfgtools-uuu_1.5.182/snap/hooks/post-refresh000066400000000000000000000000161462141313700210470ustar00rootroot00000000000000#!/bin/sh -e mfgtools-uuu_1.5.182/snap/local/000077500000000000000000000000001462141313700164555ustar00rootroot00000000000000mfgtools-uuu_1.5.182/snap/local/LICENSE000066400000000000000000000020551462141313700174640ustar00rootroot00000000000000MIT License Copyright (c) 2017 Snapcrafters Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. mfgtools-uuu_1.5.182/snap/local/bash-completion/000077500000000000000000000000001462141313700215415ustar00rootroot00000000000000mfgtools-uuu_1.5.182/snap/local/bash-completion/universal-update-utility000066400000000000000000000001451462141313700264550ustar00rootroot00000000000000_uuu_autocomplete() { COMPREPLY=($(uuu $1 $2 $3)) } complete -o nospace -F _uuu_autocomplete uuu mfgtools-uuu_1.5.182/snap/local/launchers/000077500000000000000000000000001462141313700204415ustar00rootroot00000000000000mfgtools-uuu_1.5.182/snap/local/launchers/universal-update-utility-launch000077500000000000000000000046351462141313700266400ustar00rootroot00000000000000#!/usr/bin/env bash # This is the maintainence launcher for the snap, make necessary runtime # environment changes to make the snap work here. You may also insert # security confinement/deprecation/obsoletion notice of the snap here. # lint: The use of backticks in the printf messages is intended # shellcheck disable=SC2016 set \ -o errexit \ -o errtrace \ -o nounset \ -o pipefail #export IMPORTANT_ENVIRONMENT_VARIABLE=value # Run the command, if fails, check and present security confinement # warnings to the user if ! "${@}" \ && test "$(snapctl get disable-snap-confinement-warnings)" != true; then snap_confinement_warning_triggered=false if ! snapctl is-connected home; then snap_confinement_warning_triggered=true printf \ "Warning: It appears that the %s snap isn't connected to the \`home\` interface, accessing files under your home directory will not be possible.\n\n" \ "${SNAP_NAME}" \ 1>&2 printf \ "To fix this problem run the following command as root:\n\n snap connect %s:home\n\n" \ "${SNAP_NAME}" \ 1>&2 fi if ! snapctl is-connected raw-usb; then snap_confinement_warning_triggered=true printf \ "Warning: It appears that the %s snap isn't connected to the \`raw-usb\` interface, direct-access of USB devices will not be possible.\n\n" \ "${SNAP_NAME}" \ 1>&2 printf \ "To fix this problem run the following command as root:\n\n snap connect %s:raw-usb\n\n" \ "${SNAP_NAME}" \ 1>&2 fi if ! snapctl is-connected removable-media; then snap_confinement_warning_triggered=true printf \ "Warning: It appears that the %s snap isn't connected to the \`removable-media\` interface, accessing files under /media and /mnt directory will not be possible.\n\n" \ "${SNAP_NAME}" \ 1>&2 printf \ "To fix this problem run the following command as root:\n\n snap connect %s:removable-media\n\n" \ "${SNAP_NAME}" \ 1>&2 fi if test "${snap_confinement_warning_triggered}" == true; then printf \ "To disable these warnings, run the following command as root:\n\n snap set %s disable-snap-confinement-warnings=true\n\n" \ "${SNAP_NAME}" \ 1>&2 fi fi mfgtools-uuu_1.5.182/snap/local/screenshots/000077500000000000000000000000001462141313700210155ustar00rootroot00000000000000mfgtools-uuu_1.5.182/snap/local/screenshots/carbon-help.png000066400000000000000000002306001462141313700237160ustar00rootroot00000000000000PNG  IHDRJ9) IDATx9^:A(" HI B'@BJ0jPB{?3ݝ2:d3a'?FRj'YqZ [}l=</ϳU@-˶Tw?/ڤ]],PZYi&QBh~Q2$Vh"9G3,A sQN^RS(%.dJPM+G0J35-ft Ic s}e >EӰ՟nZa Y!4'{D!5t4F+6~@Q(͐ѣ!1$tU28fJ4 C0UJ3 fr%ldtT a< :9 !)8d +1hS0-V@0kgPP k< 4V`f(|2ь A?S8 )V`F( a ʹ8s%x*#5 4u(ni h(hOt.,h3P,aiWKLA?A4G! O3!.Jf [*z21-L-Ci"i%Q|ggAPհӰFҘPZ5_q4(aE ӰF QTm$4,q4CbhOQ) spHdLDhIitJ" S UG >RtG8-zMLU.uJ3!z9zTр(VT?éѦ2 *zJ+] jh@QYaLПVA64PD$ k { 454G8ԧX4V@8X͠ p.k@DL CHA b802\(2*KmC4ca4 O߂.jpZك2f( ~GЅР@BR=qtm(Q^R_Q4j {PqճQ8UM3.*]jRב4ѣQQ4#h/;S Q!wЯd-e\( j@QqTQ c ׭<Q@*M2UL]|×@~VDT4lTy0XYKnY*޷QR㨪0,V9TyA>" .éԻ`bvt-,Cg둪Eсԃ80C 4Ae@uOUGL .McRPH4qQQ𙙷 j)W5pp4`t ci\(3EITQGQd E $yDUOFSFzKB'4Q0QUQԗ!sFJ*?{V= iӰDS?iPKUBiP(4!M5:=vU5jTQUATGU"pbiz(ԂKݎ.+FRϩF F5 =Ne@\uQ FSL= Fn,J7[R#a FG]QA4 _П "x4M=eT0d*XdfPD$h߁8* aAP)zPSѥ^RPHvc䅖ͥ޵5$U @ p>yeK44QvtЉ ʠʨSS. 0FR#iSEڳ[,T.&^jtiSHTD5V P/͞<2.YyQPn$k=Dt)/R&>db2: lB_T{[sH "{^W寍jtʧK-CͶ4Hhnpс_@U[u:'K0IL=6Hf0fU,ҩҨPx$MsHu=_@Ur5jtiKF(M7:ޫHpi;0tAR,ƅ0DtUd_@U`zfv*tqEYyk6ej$]r,X^rW|TE+>6:]Ҽ5CiERB) ej, I @0̍.Sciy(]<%Zr (wź^gLCKcCjP$ZRO"iQz$%\jt/Ԫi&4Hd}/P %ӹD,N% I$P aPXj^iPHj7I @0>(44*f`$R 8.ciMyY W}8L4٦MVt޲_@U4oڴci|0 6.\bW4H:oZCP]bPd4Hjil$%t4MRJBiFd^G_@ULF(:ƇRP 輈ыX(.ߑtn~AP/6*X<ܰ8#)29.\!:z.醸P*YJ(0giXX4q(͠HJ(LTd;ܫ/P 'yK7KN7Bi*SKȜ%k z֐۽"#l^oԻF3}},سXl u(Msʽ͛DRB)@׳S7Oil, qfsSKUm+7,MJUKu$/xK7V[Uo,2r?{`ΛVwm yүkK> E,M{RS͍ ʦI J3[]R=fgg.21?:rt{UP Pej(wm gXj ZFe,DSmCuI>Xoej(daj2REFR_{I _&HXHɪf9cS-C)K(F$P Pez(dK3!FE5dT~bZ*]aq>|ʽH:k1 4Z,͔Hɪ&VK?źB)N%P([oUPJK3)F̼UҘ)QԣJSJrf]dP PUPɲI#YՌ>$^yTi\(R:RʯHVL,ߙI#Yբ4JS4*Mf]d;'3V~Ad~]{QP~]{{~+c(d]}ȸq$;;[};c"i$[R,Z4Q,c ECPɑP :Bi0?ߎyT>4BiDS޼a$hEUCyMA}ߖ}7x Vor ](z4uI")Jlj& >ɘCiXznF_9-IJr"Cil$%T~)&>bbdSGZRP:'%ѡThT;]*,$Tv%&ɔXpEXt4;UJ}rf]RHJ(*C(M%7bTT+U=q(U6MHJ(2=Iͷ {,57Xfs'5S OOkE+B LN"a,)Ҵ+x ~)v7DRB)@嗩M$5RϥK6wk ~P"*M`}uI_PNTg37:/+M} QsJՌ&u2>H:}/xK7V[Uo,2jH?_ޮ#N \RSU* *6pJgʽuI Ú#/xgnF,^ qfiQNb)lB(qʽuIHJ(][Czv&F,iL9XrRSmCIMw.2B)P :YTG& ތ&u3>v]R0u>JRSU:gGKf/]$ѤI'ZTR zK4?Q,M:߇Q F:)uI_ѹZNnGFRףInޔHJ~AUKBiX|';9UjJݏ&uSꑔP CsFKnfTJMݔ_”yK hʼ%)RSU*>&u1޼U(M9;ߣQY5kKRF;~ʼ%R zb JB. ~&5"iڣI#~AUKBiXͨRPhR8GRB)g~* *J0RwMJ(aJ>4ve(RuI$A?sQ^RQҐ&?P Es;4*?>ѤvS @p̡.7q.:>&?cAPQCiXr(jڽѤ9_@UtTisϚS(r4)FvNJ͡մ{W8MJ(9Jlf}JTģIPhRB) #94N|~](Ms'ѤF(M2t\/*3?Qv+bO:% q4P&NFJ`DRJlJ(5RP&N*FJ`}ΏQ^M&hq @MlTMi˗96qr;P CnGI(|J4>ѤR zKwTi߫l;TѤR PPjR6u >1>v4P:vڼ/*;mK4ԈVT{8Ŏ&%0BiQ*7ur:*["e}I @0>vTi]R7UnD(J}){?BSI%67 Lk;4M<~F(_zP۴R BͨRϦߧNU,.&v\{MLK(97:>~R=Jvh'B)s()0N c 1S؎* {G4IӘvR @0R7BiSjJO;z}R%ΑS@FOcRodže)M?\T{B) s(r딦JUOv}&NJ}.٦N{N}(`}iV{B) #*~J߻_4.Ntz?ɳ ɳ~j)s.O+>iR z(u;ޓuJ= Of}C={Edxw/JQԃ*)uJ\tRP{B) Ϲ~o X4Pj#i4IͣIcCy4)9N7SJ)MwC'#Icݿ?yVD{2a(v)++M+sR>/dr~?7ޟ<+~SNRIBIۇRV-9wѴD n4v}T(~::NPFN~OPZv1`rҾҡѓһMTvuM_ P: V IDAT*7tJJ\ʹ0NtKzguJ j6rv}Rh0amu >4{6$[?&/-2olqҪ>I>[A~ٹ[9"JcզeDRǽoeo}rd?wF(uKVk`{.:H_HrL?+VIׇ_սY:x|fk*. 3%rHo*ۼuAַ5~hZض]9wC_`r߉غ>}>n7b {N R6rR>ii& yxoK9ZTt}+;mOz~#nY/珛ayTqZ{r~*5Lu;9wP T5i.)U).Yl{6rJa}Ria OxΔ>ϼ;Ѵ2)-='HG_~B:kMf,\ky[=.,~å_n~!ǵh/ɕa-[>/=##G*—PGo ^OuO"c }{ݴjD.S/+M+sgK o3L&=t ,8[8vBsPJc߻\TN B霥2eBW9džt' S(dUcGoeȫ?z3R69eشoGo?*k M~ٹ[4LJNLg?yg )=V4L,\ֱ\WS|tߞiNU('C(*؆G>m0ڮOjJ)v}Bi+o&Hi鹨`zq76GZГ>ǚ>t|ڷO"YdT'_m\4Lvcn:RrhZlsP'B(*}οuJc7tJ=m,<>6:]4lTX2 )>v,*=S"6chZJn̴lhҽO!vS#+u.YXWtierpm w*=oa tJ Bi딚Ci{:J)P#'3_[St!?3*cܷ8ƅ esFyR[6Y{MySRRJYYGuJ=cG^C&P9wP T9qf 딦JndJxb#''듆=j]~3@=ŽCѢ0[{36&vok^:ķߏ:ݗ?{VzJs7@:ldJ/)s,Ϛ4'q(u}9X4SB`r#ungǩwM Ӷl\HI/+D; {IHݫoF7!o_SWt€Q1yDrJyWQa hZ|b \P:indJgJJ'IJ3d#L BzI;V&KϏ7nyڨ|^*\d_"JϏPѻPEdm_O+>n7y(U4R9PZ[$rYYpS;22[Iq_s~J4LJN=Pzo'Nɞ?)?/NCӵ2ķ߷R1:)Dvsl.zSSP:*B)LOۮ2Ҿ}RښȬFt=yg_߾y'47{~_w푆ycs~!oNCi+o16*ma z 6~㾞(V}n %>kCPPR98# Bg^4G(߹M+] Su~B:olZ8~qwힿ xhZ;|X +=oؤt{%#& 3GL.C?3RښoNCi$L:޸#z _>ϼ.{ Å ?f,?s}h GV'nc9qF`:yJ~Pj>iBizًpliqclה"?IԍhoKIJn )_n؜-FI:Fme*Vyn JݬSjJc7t2t6t F, 6;; ~xPjuie20OWښdJRZzNΞ)gk.mGdv?*Ksrew?Ѣ")-='ǎo[sȈnm2e׷;Li)9}Jv}Lzg=;wnBi$|*ne/1pἔ>%ml3-_С4UMY1)m;["Jc+e\_>n*&\J6trJIJS>i(USa }{~_*]>z(~݆NvC'G4ǬOM(Mӈ 9_J#dro2BbBFN)lD(|RTJS2St(MaC'OBi;'Z4J2Sl(bC 6tJJ/RG4v#'B)@(LJX:&)6:z#ٖ9J`CiP5"&\&m8xR 6r"\:% z, z,%p҄҉VJ']>}(UO'\uJ-CiڅX<~By+lCiR9J`$ 7trJgJ3ndJó=ߡjCP,y(]\BiR 4zJM9JmdJ]CFNR z(MJ) 7trJ/ҴBiFNR;J`JGOӃ z,uJQPjS 4IC B)P:q(M+Zm複R=#^CiPjmdR:BXY(ZJ9)ݛC @0R 6t2BiC'աTt w'"ƮSwD=44z#'B lT(͞j_qs:W}Bi:Xq(>6.=7r"[o2kK"!/PN,Rߧʨw.ieyW/H|,4G}E:5kA$Jҹe߯:OahY>{Խ@G/˧~,GY9tP+;fs'wTg.Z:5}s^I乲-ҽO~.3Xw(]jJX4Fmf(wrJCiL;/M+/H:~ fԛȾv >UFR{]Zu0EG^ }/;w'~yWog/7l76ieW?Wpu}%t=ifl|S:G1(MW~+&Hz}dӑet!ҹe{5{~Yf>~NUg'x 苏?uJ kry)9u2׹\}>]5eP7eӪrPJϟ'NȎmeʻc޿r;dZ9r萜)9-{%Ӈ{翁_C^mMwwrd>Y,A ɖ+IR{?wF~/פ4{+ftm(="NQ:J) Մ҄;+ BpZ6+/xxuKier_徿VOقPz4*C=ۏyo:ws ߵY6,8q3|=kELii|=6wT+yfZ*GPFoHie B4c^pɡ Fŋ,_ ZRێZ״2)=|Twvz(II(Kި$.vJM9 9iD;Jçw׌'$0ū&OzH\g?}#Fא}&n:wz i,ieڃ/vEEienj7wjT+yqJ 4Y4iNT "{W(M~ǝ R:\oBXyບR>Ѵ2mrnOaW}+uɪ&s+_>]{jH90"^UmnBi֜mMOJ1U_P~4Ꮈ^?ߖJg+o?bD]?S ̃掉o1}v5d&\ zA iG}^ qgCiCJJ#inCi0@ ^LaW}%=K~ اHʓ۶})9{D,'mje3Lk} wD.mbU?%~_vl.OKS]2 iqcÄ?-Og.~#GgJ…r uxR-od_3%9\X(A VJ6],owjHob9:P(떬Nym&Ҧ#cz)'Osr dڐli:IGkRz9xP~J NJxuneiެ,Z./alӶPq-un?r1]SCΝ-M+5 %OY~ݵG4Lvnޓ>nZ$KLN=*gϔo3jއWU?+S֬_wSry9{D[xեU1||fs?rDJϟcMˈn55nrȑKo&6[K;~|R{=S"ʡUao_"2eXپe-*w>ä-3ɱÇLiÏ͢n?c$X:p۳W4L~;FR?]!?nv)>vLJKɉGeOe%ңQo~YAsgKriyP9d{ uRo6eXpAqԬLn=R>9U\, 'Ζ76HV@B1ӣ^ mk/7V}͛f_{x3i6o_oɟ#զmosLIl!׮Ǯ^HXNKhտnjbL\WM Oܼ~)닙9t(V+o[ؐɪ wl#ًY#;SypeW${ uDrM}U jqQ/\xAJϟgj?2>vo~(V&ǎَtJ_}׷;lǼYOv|u)ޮBl[noo9/tם9_g7{=}uN}E4|&2AWdla M+M*uJCJrME:4zRqʡ4ΕȞ;Ed[> ʎ}ÝWxN6Zkv':~YD׸\Q3k絑);vݫ_UDo>*C7$o>;cٿ瓯3ˋMHS哕kx۳oBݼ9o<)mbgA}ny 4PRPRC錼! &a?tqWV3ǩ)&/  }S'eOG["7tBO'jrX϶Z^'nM?8?|dcC^xksʱF}RU:f}7Vk,GM4PZP:`uշZ> *m5cЁBOɭ}1^,j΋V|Dgf$<7yo$;sbѤ9bCSӊGo>,cny3(ͶٶqskgBPR=VP:P*;-mWu悍 KoK 5%i|D#xbyPdz'-G O_JϹ^_kj2kdm;low][TιYس'ͭ:5kk\:A(ul[VZzN%շʙӎΥd ~];fѢ"ixmc~coPɪie#"Y͌@WۥMAc4U8NM^۷|9pJ#YdDd\kH{Ks?w.4’S'RݫKcƇI:Vr}ˆ);;e}KUT(}{mӿ@(W(mb7::U(x_V|B4/a޼LiuMOwmʎ=\Xhg?kMJ.\8/V>7ō 55575BsۺySq?ZZtIDMz{ynyVC|OBisS3)Pik$G҇'}IGX}0Tgž5E4LΟ;#TOZREFݐM(+mKz~ȗWUgX5hZܷ_9wʏk3_1jj{$+7Ny w#|ͱNͿ(}J~nVb6maE_\?FQ~^;{Dצ3zjJ_ia6Q64LG{Ɏɪxnpt*B6y?g56QL RSy۾K4tRʼn$czGXM-P䎟5BiB~]H=Oɀ{S3q}H$; 2}sXwtui74un&H+nz>Zclaד1ϼt:QK%ٚs C錤TCiy, $.5B( $O'0aI6̏x1"MT]싷#EN}atľP X;w=jJC_h䭔ÅFdдY_>\9NqEq>_c7ϝ]/7ny]ҾNc?8E(ulΕS"c$yOy*U?2 k(5_x}]xA^lձ#Y25vGu I}ɖ>wmވjdRy8MJ7^Hk -}{k}[sڽW-l4rY5cw+F}PZP`NV-^Rmht}[Mיg2>c]߱}L>7wƾV>@ψdaO0o`cݼ:Mycsѯ)˲Yy_0aǭ꜇9ndJGOQJXI_BiB5tLP:PjTsΈiCmv<Sy#xԸy}D7V, Xō ~P*tbMQǹxl\mķO>)qEɡ;"wJ79tvx8$HT-U2JຊP:mHm*HV5?nhZ(@.HiV?B-*RrzX e`> WZ*h6Oʤc]; Ci5ie_.Sy$Sm|5cS  &M+_fm {~YZ<(0[YZzg'c7c=yDyܓd\WSZfn_THV5\VD7k3׮ǭP:=>m(5bie&̘PjݨDOXh_#Y_[' F޿ֲ>E٨t(dULS;o1ZpxwfDʤ}ϷPk}[syo3Kϟ_ {IHݫoF7!o%Lԏknt>yqVu݌RoO?VvэdU{Z˸JU o߸ZzsnO7׹XdTCi#{Gv?Oؑ޶uJk]~a~4L̚t J FZ]שoA0R}Esj ~o1{m[̩~#V&a==|5 x-hz:3`Q߳x<Ѵ2)++oZxuΝZ3a]1]_QlYe ik,jtÝFKW&l݊MO㶲f2Ѵ2)w ۺwI䲊H?ݕ۾e[Y4B{ZcfҦcھKySF۴_*T_k[◐Q%cvsw.QwR}ŋۣ/ }<*RkhB)oA9?_R}G=ƬIg"7TEUԏc=ԸmWY5͟Tm(ບ>cﳻΛq>8} V5us-?[:q{}Bu(ɍbitYP:3o?tPzi#L pe`Y]rԻF0= 9MHC'={k|_e72JkkJV_n6ܲ=3Or}) Zb}DB7l]qΝlL?ǘ~]Lnf*Ϲ>eeun~JM1} i:b#N=joFO*{ܱ*Ζͱ<_џLYxyUՍ $J悍i({sGX4ڙX;Q:ZIJKIz̀Ibٹ22dj(5;{NuM}Vzc{_wHA6jZTJ"6Ψb?䘟Nִ2ٶqGkh$33Rmusrlk>k ?9R=:5k>+<G׻Mcv.nԽ>p߁gTbrg}H*YO_[S57{Zsrt]?GVEܽyq;xN~qt58adK4Q(c) HVڿ#z _>ϼ.{ 1Z0R||dbYY\$}*=Z,;չZ09 Y 0J3m2ǻҥU׮Xh<;A_?^b/},>_LzF|ie2zcƴ M+b€Qsݥ]exwdmuXqJW]"%N|ԩtjV7l-]ZuI6`nju~;|X +=oؤt{%u*\ Vp=szk iZyseƿ]M^{6R)X\v#o> ~_t*Ϲy◝eTҧmWԩXh94'WOn6;|Xn<[L敛ͱ>n_$v>_WڬU,5iχof4"qYYmPMLiѴ2Y ?`L[ʗ+9b\wڥZ\{-DOT_Uҥ9ierwē?nq>H*3޹{O67L:gۿ!/6i#r?ZEv.: oeMsuSgOۮ2c$ٳcgԹ62bxny&tq0tyICiy$͌Pບ>aEI:Fm`U0C/tW,+|>?rrZ7Oz( lώ o/ier85^lF~/LKKYN;vJٹ;urgn%9#FHKյM<=xoU_"Q_r]SCg,Lzl7ooeN#tc} vlΝ{QM=a*8Īm_CϔNǀL J֗E85;{][YT_݆RF&5?|=.'k?؉u7Ln_CݾooJuLbXGͱJ:dl_7tC6S|XʟK0/b_m!_m7>cZMAowijmٳgJdѤ9)Gu9ԩmv}C=߳gDTBKvwJGL }(dHml?&.ӧ-;~f'x@V@ 'ΖHR|GhJw{vɟ#_ٛTO}# 3r ٹ{yo}o#YդmGd9v#ʦd=e)?&#-k7B)=VΔ*$6@y(}֦ol]k*.srq$oܤoTʮ~EERZzNv,۷|)+.g}r?r✯Z;ZXYd9xи떬Iz/3GL]Sry9U\,{%떬1og;]9o2w4RrꤔÅ~Yi5i]}/>vLfϴ]֭#3O]'NsgЁB8MZgNշʄ#eώLi9SrZvқ`7׹c}z,Ҵ׽ٻ(љYqy&k/+D*(Ⱦ((o"dl/.NwW'N\W::]uԩd%=C=f''{(-uy}1wG]EZP:~6YOQ._N(ʷɞc'5o‡!<~[ Jko(&էjJ;qZ9YY*..L]8M+Ӷoh([Pg3*ȷ窿c6l٣i-p*U9YYΙZ2}a =e[KݗzrzgahPZn}2k.=/{^ yޯV =oNPA]NՒiˀ( z_N0q5ӓ1,Y?ܧ.ʞ|ү^S걓ڷyVZמ*KSʼ~]Nі/6hʠw:Gwl]tY?AK{]Gn} <%atU,(]נ$$we=(vSƚ?hVBL:r$˺QYQ@{o(TFca갯CXRgX1(oXZAY2$A4ҪF}ü t`7yF6 O{{yl_)ۂ#( TC0/B:@һaisdP4MN#PpjF]5~Z1k954$c;qZoB7YOh) muEx=^q r?MIr ":.*(5RRHkV]þN@Cu:4޴Ϟ1P5_:oկqE=9@g\֭k.ۅ}]=.(- IJ?t A)dUۇ*am^!XM_љȞS?FL2l_I?A~ط 7A)*۫uhut!Eۿӌa JaA3,t֢~K J#T?<^)o:T j>T xJ:R /&(A3,ȠtWLPҩsBh꜅.:A6zΜ J.]r@$ YPrRgXJP dJ J?^FP T7:*.ZcP:Ww7,JKJ JQQP3R .,ҏ"(J?ZW@UhP KJ-(]%A)"!(5RRz]` IDAT@US^P K.(WAsU$,tA)A)PQ/Jҍ!Jg/e]ұ+jP^av;3SЬ)a_+:n>ӑ*M@E#(%(U5(凟d8}A#)2 ~᧰KeAik)(CYү\5^=kÅ1Gx]~ᕕmmީ fF u['JIs,o]kd:q$Ey9ٲ©T羲ĪIڰl:tuNrt)vRlP'ހ$zү\UA]<_#{hԹn/Tmj(~KkNX]>ұv|]|{ 캑c'm&%%T9̲= 6(R%T'JQ[*..T͛p6}N;0m7$V#|]8٣jòպuy~.ZƷ]*3=]ELO׎5zO8HAPJPAixҎԵK˽JA;y\B/HuĪ53iN׬*.*a8բa_o[LrdmX4M Wt=r85mwA/iӣ<λ_mi^}G;(k|s}3{,k]oU732R|n+_.+wjK|.Pj>m Eߒpk,w=O8ǂ]'Mtm_>cYfԗeחk}Py9brxk1@UFPJPAiﯣKضWG)1.A&޽ٮA鏻Wߺ^(pNT]2 yja_o[L٫*u߭c6la8tE߻c|6T&hY1ktAikZ8in-*m{j4GPr% e͑a8p+u28;2 rd\%%h$8dԧjןnןn cd~xWWVS>oo8jY#6...Ym׺({^ !{^N64c? ngfz }ɜrR%Ǐш*C%%h9rcA/u 掝Q]k?F\PVPZ:=ʭ;I;/40IvW&575cXFq˔zYY' 䂳}Y M?Z;л=Ñ}&ouu JzGqvВi=׿;>^׸U_-{bY7omSh7;6g~mީA{U'/EPJPAi\227y *kmܖ+.{}o7muUl^ G5֝'J2׽5+37=R쪲neW͛n݆}M J/S(33(P=ε:^T^N92{O-]>{^P[e{Oֈu 6;^(sԮո{ofdXr?s ')kP#\h~:C7,[m}o/9̠v{go6]muzY6(s횳WtQa:=Jns=d h9VPTvP:ⵁnl  ղ Jt3 oAsO`~6s{fl/F[;>R});wsfOnT%Z J-ri7۳q^[^۱*AiiAls.u_rnM2 2z|sۙn7a_!'޹S$(n-|7܇w-dKg3I 狲vof~2}9|TAvjV);C3 uW]V۵]x=7)]:_thcM oIeSktol/-s,v7(4Zv hVRE^ 4(uj|M엨S?b펀#@e#(%(r>bހ$%( >wzt߷ME2/ >wusڞ_)/9TVP ('(uSslb>l\eHiW~Yֵr}銫 Jn-&V[m]s}=m Jy2 vr- GPj[/܎oovk喷rY]AvA]keW#͟8a z4H6i|h]tYЮ [=umu١Pc9|"epV<\ry٫C=Bѓҭ7d͟8Ky8yUtonԲ5?A#&vt?|WҜ>Vl-=ӵU=gG 4Av͹._ +(LOa8}/JߒpNh%S纽,@᳜sʲ J zלhw۵,4(FyZxeٗTA8}o:{ áG >=7\_X{ޮAzz} ԟyqB]ܰKe_mn1Jiv8Q:C?vW1˗Kv}[HZ^Ysj%x?< J?$(+mjKklrcI]NOr(6ȼ~]Q򨸯9feNo\-[P:]O%%=M)(um:nqﯣGc洆Q9c< @8zzs#7 x}]x[]v()0zS)A7U5(m:ʾUoWw/1npϗ/s :@UVP65tY?tb<6Y<̛ԸY%MXYͧͷW{'-n`aX,_lkBo!c]Ծ9ߥUЉ-jߒ@ZikInHN硯9feN rKW vkP:}o)ݥ:.yqCJ\ac{T$RRyv?li|h>~?_V Jz 5n5KB6ahoz=u87QS_eN~W[#^|[Sa}XGa}0 VڽA'3g݂3%&'+Kqvp+[ZsI=zVgm3=U#\Oz<[k=}}ڵ: wp0~+(mP_zP[ JSl =>zy~:oZNt T%^u)fht׷ɺF?=bmXZc4hm^녷eB8R[Xض\ 4s挙n{GPzkt{P!Vl[ aC/jԼR%m\F2c9t=M Vb\O_/^2-ʆz5biRִklwe*ȷmP'M71v{nVZw{C'su[LISb]R%*P}4]'JQ'}o%/gf Kֺ+˞{=n^o8n>C3IZmz6~|a8tǟ5wLstC&h:s݆śzOX݆h$->O?8ȖTJhu挙oЂJ9xL=ߴb9ڼj(M7jY hބ𱸸g9e;6ӓffy?tFwoᓴy}ɧf9A-&VZv1bm[&Q]k$ڒsɳ/ԫ1߈ꋷawOAe[4-¶.A-&Vn2qnvUo׏׏:eG0}wYͧ<γ^mK=OxnaL!fɡ k{O{N^܉3!nj-sjַE2,[\\=Zl8R[Ly,ȡhSC[h]+͵uyܟzow4}Ȅc\-&S 5R9L(R[LF6|2k-jS?fjJ J}#zD<۷tNyJrUG;U/מzA|._Qa]Eʾ}Kg4gtVmER ۔q-MŅ*,FZ?U/SB>aN)(~*k'UXp7Ș=zZJA' 苹ut!e\K+iW q-M6l;Ɨ;҄#uxeߺ.=/.WHKSqQy%zW%R[L fOUƵ4替e?N6f(PZ\5c;vΝ8|{y:{>K^~>JCR9fgP9Yu1B]T!XhPԧjJ;qZ9YY*..L]8Ms Jm1jFZ|rBٺsHٺp*U;m֬QS ,C;(¥@": J JA)A)A)AP J JkP?OxYͧKJJRDPJP \ROe{RA)AP J JA)A)?R 2Qz@#(%(A)A)J JGPJP D=RR Qz@#(%(A)A)J JGPJP D=RR Qz@#(%(A)A)J JGPJP D=RR Qz@#(%(A)A)J JGPJP D=RR Qz@#(%(A)A)J JGPJP D=RR Qz@#(%(A)A)J JGPJP D=RR Qz@#(%(A)A)J JGPJP k IDATD=RR EG[i:Ak%SYΝ8-pq尯Ukywߦ['RL~+In/7}]Bz) coaʒ౮C YUH?hתhFDRRҩy3СOקT)Cs{t áGR¾.B=Ή#)2 ~᧰ogeAiu<#Y4c]Z}J Jᢺ\vI [/kמzA=v2{(WypCСf%NQ{)wՕ]&( pXE]Z52!(%(pXGmXo \uRl1sU@au.J#]٪9Vhתp ?J J:\#( NuRl1sU@]u? Jڵ:\#RRJS݃[ _!P (uWovj.E A;T C=WuJU󛠴z]Z52 (%( ׋ɳ k ]*MrӱvKngf}{l5|{O-M;RvW͛*ȷZ2c~\o_u6@ v[.\㇎*d0_Mu57]v|ڵa2ohG~hŷm6767Q h] 'u)ruN 78f5҂:{yLq͛R,7H x_>{^Ч3kre>,C->O3gu;3SEʾuK?AxܯGc=3PH=vRGOӉ)ȞOiAl5yӮY}0vM.?ؠv6D6ԅgu3#CEɺ?h9j?+nd:q$Ey9ٲ©T羲ĪIڰl:tuNrt)vߢzzm;R1uvꅋ2 2ӽοWa]/7lǘm=N?Bt_}k.+ߞn)Im[Iq e˄.\/}Y2x0ؓ#{蹿AC)w9~-;on}9~hBs+iӣ<]Z >+oU732+_. i= r~G9fY=ޑخ}1w9O8f#Aڅ+vOEF …Eoў+9~peݼi~T~#p(7;[KUb\& LRʁCfv+3=txee͑a8p+u2e_^l/X sW/F>CvZd=^V&տUW}4]33(u,{4h7p%%(9~~\/o7Z[`~?jt!"N%*w|qwo&pmk6iiJ1T_|S^'k4.3J?Jq Z4#]5ӍV۹mY:vs|:ni~+P|c>1Yg2ˬYˈznk~eۿs BJ?l]}n0Э~'b{ Jn-&V#^K|]VqդF1Hmq<\z~wQ\C\-4GmiH~Z1k eTۇ)ߥKϝ8s*9~F6P (1.AsZ=ޡ8#R׬Hm\VOeN ՠtxfS?I4mwjY_|S3%kۚo<>cHAPJP c|blse^n$^<׽hq[e{_Ԉן5?;nߏ=n•eg{|R9սm1Jnwy^ de_k:ft#-M\ Hz5{ŬEen~1vzg2 6,mܺZ卑 < 掛i.[NXoBm1=oV);C3 uW][]z~Z%vtoH JCYׂsJ]z#]s#cvnAlFIMo99!~> \#IJ J¯Xq{vsL!ʯ>zۿUɋ\ߎ:hӯ^+lWZnO yɹ뿦y]-מZdUGZPZu:o7ZVw5Ծl1pbyưa84gtws>o꣭?XjBϝ*3( E{?ϹTsn=m#\瘕fxGjj圥2Ʈ/6s_{^詃;~Pz=r @$!(%( /sK^SNm(Giyo=Jn[{`q-MTSOϛ/E( ]vzr%]g"-(ukNW^`s)UECv[/4Ě/e*pZC@CޮYգ45ӵU=gG 4-`› }Gt}+Rsh%Sꅋ| 4er @$!(%( ._mnNk^|sQqҏ{]qj[Xr\Nmwg벽5Fs{zS"-(}/Ν"CV:?cs$phc HR͌ ݹS9~lk6PPC@^]]95 97=bbj6fzY5t +Z-~uT4ʺpcVZip]8*[Xs dH>=A>q>QZ AFɼ C8YF …?7`2?w(iDzj>%oN9x;L.͛aȶXdݖa8yՆWJފZo/wg o@)~oRahi?WlCe,]}><v|._QqQqIW}<.ʠ4ZU>k9){GkV3co#_V۵) ߃2tKUJ=ޡk9fY9ޑܮyuw*f|N^a8s}?YPRϭ}\CܾҮY箆|m/=_jĚϸ{VOߺn|WVo[cܹST0T4ʺpcV뚕횫zm>~仃*ȷWhݯ#._kWPR^u[?K J}]#IJ J"pۚMJ?J;PrQڶ;w7ʔo͜ƞݞЉ:q8Ŝߕq.gio^hG̋oXZv]9Y7ҼߛV=7GWmPrŷ^M:+C͛Z-ZF R…E7y9J}ycɡլ6Y{k|{U/܉3cۚM^'ƕ]+Qt3DSd)饘]nyO7Z 6,ܲ g{\vD1%Ax{tvq-M}}Mw(hV8/6{jfer}U6vwScy԰tRkUX`W͛a羒rz&Խ&{(-uy}1w:繀eŬE:9*..ԍ4޸My̩teU걓|2b{4zY뗬R걓Beߺg+amZN|5Ҳ+6ۅSڹnf^څ+uTY>-?tT>Z:xmvoܦki*..Ta]7tt!x7{΢yl{tbBF[=FB>brHTX`Wqq2i׆zra]]joc{{nΤZ^wvvf }иCMf K;ꅋ ߮הzmީ鵧r~7y ;FZ oӯ/i5u*{CU"RBq#]s:.n*n׿?tRV[sH\_#Ԫy _~>JCR9fgP9Yu1B]qF#(%($} DRRAԾ9֪^ 2(OXMVfًgΆ}=*rc :E2~++V^a84~eSiJ JAhM=v2v7ZٷoeoUG=%tYSTG¾'kOV]sczP:dh[Ia_HwJ9x_}ĸԾjFeSiJ JA~vAh}2QS+uO\v? rbborU=(})ʯ2 ~xIQ/8w2zg E==z!(%(E-[L:nj#(E (UU=(ĪOKݗ~:~nqx}ssRRDʺ RD RX A)*xgn'+}i^J JARXEP]˶ОP‹&<$iە~ ʷ)5{@KUoN?7 ryʾuK7nϴWR:/**׵K5+ql5_R.].*h]^9girZG|zLY+AN]fqQzBC _kNrGsyƭ̛ҟe^54ˇMrOI)CGլS[mσmS yQ IDATyߑƷ^#'+KmUy#(%(E)o؏?keF1Hcڰl[9֏Wߺ^(pNT]2 yjfѥsrl۫E?_FӣLEMmW⛚1,Y|ĸeʶW#s_-{֭~'ur#a#A/DTc4ⵁJGq ;vfLPVI4AwV< j*d/YioנիIgoU%M̻ݱyDZPlf{0֒sIr9vsi%>1?;Aivyfym Jo飤J1T#FL̲޲m=ҦZѬnz;z~YvG[h{޵^Grerpŷ!iŬEf#P9J J⹿>MX}Zu5(mFĪj+'vi/Y%(jjx;_~wMxBϜ5o˶ڞM 9lPZ7%+u׸۶ˏ.3ЗG 'ͩ} J Jf*Fkt׷3d ? áG=.^ֺ%9r⯶?Ai婪Ai{Q͛f/?A|NIAvX54j>e3PSPjՅS2 挙n~e6bb5s$sz7};yTBVwh4uWsYc:ݑ0:rR% (%(i^NzruN۴UcdU˿5/-^uUFkk]8=^.Ai婪A-&Vva8tę  {TmjhvU")(Үk| VmsRoAsLO`~6s{fJ]^Pگes\KE{6ժP;.ߑ~:s á|uz=#gZ\\X慊b…v :s𺌪ze{~>̛}!(#(%(0J3#tJKЈrsyFw0ڴbe{j6E[Xr!_N/rՈ7)uFɘ\/6:z7s ga8rjPv2 bu47*sJ:Fi7:s9Q:]O%%m JmSCq JCݞ M*zm5(Cgp̥\r1.wCcKvkEŊF *XX7$F%QT4F vde3}g]/3̼.5yEMe5""""cPʠ\cyv5eԔJGeVucev_5VVhY@D?8"%Ðz=4drS!:hJK-ow JQ?}ny*ʕy,ӯ5&m ŅFṹ[RsLr﷣AK}q$رUֶsKo\|'~ Jm篳?/P:ֶ uz6 Jnk"?k9j]?m~n Mi A+/}V^*eBVؤ)/^}^А Jfmꧦ&=P*sz:~M~A"#$I9jR[NP*?WO7J!-5<[l疮7݇ LOȹ2(ׄj[iغd-換`,mp% mG*'EKHz@x@0挞l@G B͢;Ɔ fFmeRقSUrJo9A\>U t ƇJ|V{J̏jO;_\*susF@`D/pA9ǠA)? 菞UqIǵEkd(ט,}G.3K^Fth˱1rR7f|=ڪ ݝR7DF)rlXCuD#͞ ԌmʠR[VP%?WOkxRfv~+Mk;]xJ{SǠA)/<\H>l5*ˡ)+ENf͋Våċh8u jh Oƍ󗑰6 Fu?Ga~>J1oLղ {(ה\Sw36hA!h\>uOZm%J q-ٸCZ 3 "7Zm%4%z?lDuvyh*/o m꧙@[Udܾc:"( s eT![iR+.(ӌHMC;<ǡg;cUxvhJ~+3{5}vÞ;1*+4(zOi?wTϕS h;$ />av~+Mq?y9bfD!YVU\SgcX:mR"""`Pʠ1(ePJDDDDDDDD2(%""""""""x Jy< J<RDDDDDDDDDA)R"""""""""ǠA)cPʠ1(ePJDDDDDDDD2(%""""""""x Jy< J<RDDDDDDDDDA)R"""""""""ǠA)cPʠ1(ePJDDDDDDDD2(%""""""""x J7 玜ċ\h*7/^ÎU[]ъ;#(+)FChV3_[Pg>Ô~.OC=.]GP.~c,.<꼉aaPʠHqYiR?fLj`,ޏg> U uCD97/^ pxDD԰0(ePJD≳MѸ.,gjҶ99XS"V^S&^̌2"*6,V-A7?k_\X ;Ovy[/Ƽ!6PfpYx=+s9~#[҆xDD԰0(ePJDHo!:k￾uVu3?AU~뒵9vuz_!{.o A7?Y6apYx=+s9~#[҆xDD԰0(ePJDȯEo!c;^2G@?6niq?/rs!:wz :k_5톁M Jqu.1wdKPϛ JP[l#otZ?G}~D Ja>l JRD J _M?w J!`Pʠ<=Ai[4(b j8 ƇZ-vս'>{&] 4'OQ)Ceyj5o!y!EhjHX.!7[r UxL{G w 77~bTU35N;i)bxSv-Ņ '3 vjK=gH}ϟ@A^=`/Oѽ ͅ%EH͋VZOPr9|=oAMa*+4(G7&3(c>nQ8ܹ,hJQQA8)\۸%6E"]hJ)+ذ`%olkr[DBDDd RD֏4q.u޵zT=qtK {}ޡz+S]]0i.g}fiŲjm췭t?0Y-pp{?,v[y+џ=e|=fK;VU`nL>'OAܾV J'(mF|۪/mRqHϷq+۸C&{ԆPm{7?Uu7wʱ? zM,IF"Č($)! ffBM#2~6:^\1 o=P{صz"0kdL?aSnn `T;Rb '#o挞q,&v6ۓRGo-?{^DuE#zᲴ'*:T~;O}&G"t,~V[ AС\~U>w| 3նnnT v6ukϷgo&xCqaF5:SF‰盢b몰%Ҿ~\o{ͥ Z[s[NBDDd J1(ut֚Se%:To Mi AԔ+vً2nUY ڽ NkT6t 3ڽ Ņ?S÷qK͠GW "am~|ĺ1w4eҶZmQAFe 3Min^ߞ:|*(=}g[Hr/^# nnQCA)y8#(Uyy>rAe5v# rJ]m Jd>Z?M+ە ;(`lZdPTnؗVߞy]^9]3=:Ô⌠|bqiv;DD0(ePJDAi JE~{!n:d=z,R-v]n Ƈ'۸%Zƥ*tG$}pBC_uD||vo5CCx@S%SHufw]ymjDr)AIGM=ro9%E#J!nǠ Jנ/zֆB*)*V*]E^卣iDU:l ? PUY]-A8 %n AAbPn&ˊK[|o䍗/!:rMnHA۷q+ω#hN)Aw}FKV-ߡæHǞom,HBtHMjP|9o}sO'ۉuN1W|*v3m͑oDDTW2(%"W_^ Ҝi,A*;u^5WVhYI?P74ZP()* Ԭ8rVSZbv6^()* p8!ɦz7ȠԆ-.XTRTok~Gy +sԬJ~i`~+Lnc)@:u YzNڿz`(د[0>]B:Ry圷>{s6oV(.,*1WԔJ C̑7R""+ JA\>uޮӇԾl󺯚T:- lUZEڔ)>I}36N:Y >KX/}6P5(MVS۸z+(6nO;>{ l>nF?zF8+(Uyy#n:3_l.훟Jfˇ_mc)@5[ [XoWH[y볷?oF?KQm/se;5]:]ilfPJDDuA)R"@~-z#>~yq=ҿY \zy#RN?C3# ¾z۸NE]X8! cMd4Ү¯E_5@wA^VGDcYԔ+F>c4%8 @ VJAV[M*ZW1(ymĜ3d\,0pLRVMQ6`}>dR/\^3o碤H^jgWN_ӌʞ?z 8cL{bfF9-(\S IX6}!1,,Y Iuvo{'#?c3zVGD#?'ǶVy1(%"àA)y' W6Ң*o=PzA~݃;-dJq$K֎-~jD/P9YpMdXb_UYJ 0[iNkrww>GҶ_cSTQ~dATU3UI%O8~۫_H[b.@Dh*7=~Cx圷>G(ט-sy6n\{ܷq+;rRv[-DDDbPʠr[#ݰgd=| ^gkڮG{ڹNƩVCDeyj5nfyQaPʠ,[Vm?fZ⦝.)A)R"""  Y#xu2(%""2ӃRƭ7 {~~-zEDDDDDcPʠ,OJzRN\^'"""""r JԷqK?^w>GPVR=f. 4ϟ|)]^7!?q,Bd O<30(ePJD$8άk3jlcD vuUNfT3\^7;WS!:ܼxu!kzDD2(%"tYh\a3Xi ])? f/ũHXxcfFswvQL?–훟/.,ꝧV-]0(\mc<_&""A)y 3 P)CY{ԙ :<{?jcWKJ__?tU-]0(LmTmty}7y J@?ala ρH--En.A9[Dw:]1i7 lMAgAs5O=o""j2(%"uZ6N .?{:(%"c J=S}JaaPʠjWn}?Q3y'OO 8wd?yrM*+4S~+ {)zm{}a,=X$sFEڪ <#x??{[lY/@qaJ"c\#;c,ίï~ ܹbhJn:vf}v 77~bTU35N;iYwaRؼh5='PZ\*Tk"7.#}?Lǐr 5e3tzA1(Ug>ñCPg>CUe9 p5,Yvo{ A!yAmQl ]TP_^&߼x Ý[ 8{\h*PRTkؼh}R.~ SQ*5x k1Sڊڶ 84@a~>U(.(lBsԝ9u JcPZ?ͻym{^-g8:˟ 4%]>d#,/)*BPe{}^V[9ww&OlŲZm%|~\q4qN<7[ ʹ:(*\;{lr ^uѯݾ|`NDDdRD J[߶o[jK^Bm`!~g-c@&h97ncwĢɑk$}0m8̈B,SKT_oW̌B)5t2bDGұ~FݻqK wa i(&vQl#8tdmASV AASV͋V#gMU[VBt(Gۛ|L7>~}DF0?6t33ԁd$99j: _ODuv#8^ puç!tDE`MHm~cmX]$f}M_w}ϳ=9(wغd-G|]aSǡq\1Ͽ;rT @4:A=F(zjF6+f-6h7fNDDdRD߶kWPs#l}LkMhVZ6mf|=/_VCt~ڽL4gew^A甑cNR6EWQyŐzm3}ik߶ mUA0f>xd׾;4 V[U3*o~wK n/FYNf J𶬤ءE)͆vr1(ï*SS n]:vي| N A0ȓʫ&N^Jk T?'""2ƠA)y8j4QNV6/dsXg۰`T V:my^Xj@KsBNfT*\H>9gX O?bpmƣu=VK8O4'+d J.:5v粴ƓR-nn ݸ%͍+sGFE(z"{KF$m33%EENHV^RD֏TF!˗8ql_K 8HFmˋ"k1:t+l]hl5b4^>u' ~ )k :wءe~5e6SlZ.AS,n}rM3۹>DDD1(ePJDAi JE~{!n:d=z\;rZۿ9ܹAY|`N?o[^[.]^zqBJP"|2cO3:vsX0>}?vo-ע7.<甠4?'g+'O!:L:jsKaVGY [.`D||vo5CCx@k.ErF.qDi]ωcPʠ<\} Jͣ^)*V*_Ej°gæ sBͼ8ۢ7Ծ;sP{ۖkqNA0twyA}[ WyfBH>mQ}vBjFԴmnOtJPzeŅhvݕRRSRX:lٔ~cL9>nofw\yKyK+2I~5~ݝ9GZ]ωcPt;R"rk5(ڕ͍C>QuO\}eFE{Cc[h3Ut伭Xwz4b{u~HMj2d_h[+ҔYAhe]wWH9kJKύ>Vo=Pl&o)0sgMe,iq[Q–RP*Bt8d[/-R:7JP_svP2 JQCS_RU#o;7}#f/o'oŬV7~<?L"m?OphFxV*HX/]1YAiGpeV}Si,LT^C9~݅3ҶCPKyioc)({Ү۸5g ^I>`hJK :<Hh撠DDD A)y @?13o.4mJZY"q.,Qӱ&2iRעꭿzwA^VGDcYԔ+F>c4%8 @ VJaV[\s>MkCu{[|6mĜ3d\˰:l4\ѻ}?qԴA[i_OĘNC1 OԆ<&~:<ר,u:[9g bd0`]zx1JWA^6Ebڀqc RHtPFx@t|l]Bx@0MĶ ~4}] u >!)~7"F#oN $aO`y"MB2t1jc뫬b-niiGOanL1brQe9osy|?C!< QAHs[kWtHM3&z:{Q G5Wҟ9RD.0\9ݜq]݇;[4=sbYQ\Osjݏdϰz^Fty)ڊyXٹ8/#wN#m^C3]X^D]mV㌠T0i(.(zQMoW$y 2TX/pervcɦ5{ޢU,Ng]> WϘ?v ;9ү7ș2(%"PR7Ʃ(˃V[=|ƄX-; ?z/rsVBSZSF_gֻ۟aP?Deڪ  ]K<OӋl}S,)WP\X*霯N9 o=PRT~6szg/-3# OE֣ДִլlJ'cJ?aǪ-xvhSq@2MiF,+/\#+yCωA)R"""d*n4jωA)R"""oV}AIG]~~DDA) J%^P?̈́ "7GD)Q}A)[RZG2Vc&""bPJDDRDDDnI W≳X2e:ky%""RR""/2(%""""""""x JyxعAi JDg?%fPJDDDDDDDDD`Pʠ1(ePJDDDDDDDD2(%""""""""x Jy< J<Rw JWovy """"""""DKWofPʠȳyhPzPT K JFJŜP٠ R""""""""" Jy<fҍN JcocPJDDDDDDDDF19-(AimXʠHK<py]qω?c&35ԙ0_Bt&-!""rւR1cPʠ͋ :ܹ؟9WCr2 3(%"" RT4?nl]PRT*2dfoDZ`|(ڿIԐ?o~#MC~mIQ!Aqޞ.c*l ھi_qajw?F, =R"""<&(RTŚpjQ%waPn.+QCa`Pۺdt;:=WH^5{m՗A) !(sNR{ڰA))/֤1(}t/zDP4KťG2\^_y}5TAMa`ePJDDdALPv/ JŚ 7/^3ۤ]^_y}yBP*R"""Ӝ[v0(%5)ZP/-P) p|./QCa`PZƠ4Wy` JI8}r2PQY&+W\@uÑ_5e(.(e?DoObU>ow)+SocÂHkZPM5㶖 A!yAe+|`Y#fFw"'3 RTk1_w~ SQ*5x k1rSŶ 84@a~>U(.(lB ڪ 6/(~Mߠݰ{|#Yb]¦X\ŋ\TUtĆ~鄤(C 玜7_4(D6Hܼ /߀i&JQUY80 ]s9Ϸb5} VY)1[.~WTCSVGwӱk6H>c+7[[xt//rs@IQ!ҮbfwnoZ)ra_Ë\ïL?K3IA++5ϘDPi2jmTA)r J\t/7(R ߺt`i6QAؾ|w_/x$[O:J~?pѶC܏^s^~.jpRAc..}njƄHNE(+) $Z^s՚o[_X?|O'ǟFEn.|hh.V56(@?EɠԕܕgL9Jק$y3(%""RXJAi҆BUK}!5_0}vCNVٟqRP?5EE@A ݸer$3Ҷo~/BJͅ{MnnnY ,ʎ4೫gjF>s5Uy'yKMn۸tTGw!:meb}}-i2nߵss.g 1B*1*/o\#.V*/àVJnNi7~ߵ渙Yf{w}~mB km^|iM*1YwωִJSS?x [bR׿wuPk~M3d[S*(WW)7.3jl)ϖT2(mąN.:owY9/# X]771ŚkA[|svP* 5 13,n[RTAԁd\pҩrU񊝻~c[Ntrt\aHsyj BbqRʽ?5,i*\H>9gX O?bsb*+yAkh{wܕgLɶhP۸%͍R&|o? JǠA))הAjVhkäHpk_~m5%Sͮr~P*+G?c '[V<+/n3L<]N&.~|fq,A+lގw}*q[5ZQ<7[MwHr{_RW\sWkr1%ۚ#Aiu6C-aPJDDTTP} JWm?(q7OAxzev[1ŚsАzHO1͖~ɤ&?wǠf86\p~%EsANn Ƈ'۸%ZƥJ{.~]w>Gx@0v\Xtu:|ɶ~k`w J_) Jڃ :%ڽ = J\H JWmvt#7(Rn[S/}?0w۾R/Q]]AЎ}f/TX ė BtHMjsw J(Mxwg3ƭcuEN?Git29Q:hO5gkPjkF⦝R5fJ?|[9axnɟWԴ/Ώ-(k~M3d[+]Nﷰ}@MkeԿ)|ѳ6K """OzP*w J JbPϠM\qv5Rozgϥfrk_,@o!:NH2Yԁds1(Uy>?b>۰`T)|T^37RSYo[[N/DFƷq+kRSl J1է#4%f9#(?|B6;SJV:_)ľKtY\6wI&vս:HY;gY?"""wf>(` JkRۂR),eP[mU換esY/K?z 5 XSb-uڲ?6Gw J猞!;)~7T ?n04%0z^,eG:ro4RUϏ$[gJKir J}‰}QZ\':5|j KOpFxvP3B});d=c CjVGD[ݾZW>m=/(]5{n#o;9#7c3zVGDKs 2(%9@]^FtZ$F`M‰8PSPj-IY3 ~~>DšxTks2)'8Sy\RTq X]$G|faST,ç)~T^ VSZ`X6}!\Ir~Wc: ι /b1m8|]1})@R:(U?[Nڗ gۈݤ)*31bb8g S`5*˥mn]ucطuqPA5ϘRmͷq+izNͻpB"GMǚh]K_ >!c: ޣ33_5@ڶ /#랚rدG BnƆ fFm咩bR;R1,?(Π SSGOJj>w2(%9@*x/_V\y  1ǭR`2/r|mZfbrD# ٔ˧÷q+2JU^XmxPl..>#J6"rl =wGnbyjk`+W>cJ5Qئ~O'i5ւR~k~vwEDD  J|^bXjOP*2hn_by|jTUCSV,\?w 6JzѬq@2rj+QYAZ/#amـZm%A?1Ж}{~ U(.,@8x#2W*/+/Ax% V^BDqAfu {(ה\Sw36X-?q8 V"?'g?ycB\|*=AO:7(} Jkׂ{˵}SĆʊ_vNDDDDD KW9A[ J_*+(YA)$<'/_Vcx.QCd*(YM^P*Gt]P5AZ JkRDDDdoV=I?"""""j,bg)(:J2(%"",) 鴈[u"""""j:9( K-RDDD$mc]N] jxo-(s? J7 J`PJDDDDDDDDTO8 J7UP*.d>(=h_P*,JnA)QtP*xomJZ JŅ]P* J܋TDP*rR),JWqA' J|$)(RAT K̏xo-(ry$(tR:(RAi{ J7뎄xp>4%35.$9￾Fe6E"eը(נ\S,8-,sHMl5*+4Uo>*ď;鷎3;3v1 FGTDI(*APD *Y,A@(P "&49pBU:y~}i|oU-Y):?)OfJRu<_6o\'.n$ O?+7[]Wb|c{c\sR~ttg.ygmGˇdȴ8]Bi]Ν P}}P{^(uR'zCi9R =Zv#|}ApvsT'뾷|Ug2ղ}V _n};p&8&En]p\og{~rMq>BiN/UTmxmBi6(n6B CqIs{R7J'(9: :Jv+PѪ$OXsBiYҢur PZV|ga=t}:Bĩ~uM(-M%7gGVxP^J'Ys(<;Z(; Sj΅Ni?JKk%ϗ)UǏʾ~ՋWH{ ?Ձ#݅|=f3-[-׍~zn_e֘qzv9|B;"SY>yszl߲UT}yK K]?ǎwFP_KdhlBzӗr:&/*c!W-J(}ϽLzqT'[>BmtkȦj†5?7,ի/Lu'V]49P]n7>$;O7ɰglCAټso4=ɺWˁ{Jf2 rS+B[ξR^9Io*ǎV={dUҧ]wtҋcBσv/}T -;kҞ<"-_lwmh?<ū{}vl\^*;~ٱu|Z2l\}ۿcGb>住+1U7WՋWȶ/7={QطO>Z W.ST^/^7fxz(=K]4׍4RP:P qY0yN|E󒟜#~(LT:myvjKvKCc|>UU<}ta9ȭC_PE"gŒTcGNYh<(fO.fSڲ&ߘ4;{{D ;.{72w#5ah=ˇ+~uaJmP:kNi:ϽAEFbJU^{3#{PlW 7+$4P:0SJ(7 }_zthRvnede܀ >W%>,g[׷q/yן;~~_' c<{RvN.=Zv~?.k޿Rg+D~zIAVZ?Ç**ds/K?{ˆ5ܯUOc nc{%풟{gSv`;~ MBw> $=[=,zP IDATY~>`~S)K:J&wWޭȄAC2u;A]损=q#zU9'vJ]䱻!>~}6(EvJ=.rJ*:=T/tTv(=KBi؅N}Ni/{Kc bG350ܯ1k)W_ eTgiow^pT?*L,1/h}$[v/sozv(|c|c{w:M_n 6s}Wܕ>~؟g{|&S-'N3Iy*^}7/yP(zӗT˖Ͼ{ʎ;niOj%;!__m?q({c@ifϊeMr`N~|kdb)f_ɶ| Qk>4O7S'U}B'M_g,{*۾\߂ÇW{~v+' oY9չPuSÕkN/|'CwoϏ;~1=ZvvJ塃[U8[7o<׽BiVK&S8c1BiY~{{OYz,@I"M{r+OmLZ.[wJu~/cX,Y}W'$WWC?RyE3~v|N@{I&S-{w @eOY|cSq3~9Մtf(uJ: JE7.^9uK~swɒ 䇝;sݻݭһv|9IҲzPE>F'~ϋ%?9Gh=j!.?n ۷l4g5p8q\Mi6rKnzŷ6[pߞJ&S>s'nxǤJ[ZgeR M<_^~r|S<|-[OҬON8.k't >9>U,hU?c6W ENYBiEN9t9UCKt߇Ҡ CX~ mٓ*掟]#~ǡM+:-׽ctB49AζU/srW^;vhn^ x a{/6^fS8UͥL_ | g*k_s.ڹשWk#K#ˉABiY q^w|vʰӰ|sgJq~N >{S+?AV9]]]{F~ܯ ROUPx۾ܜv~lr[^tc6<,ysz{gr۩bx_6P:ܯtfYr5t^xERV/<]aͺDBiYəLt3wп#B)ŭ6md,U 甆RsJORsJ 7݅dig+w?TsOLZTpRlѴR]]%ޙ{.7L>i{ҡYKr[Gwag(j2y>D2a(wJ.Qa9j $O2k?3n=6 P]]%<+՗[p\ש7,PǟȃIk<"FOɹ]{P%>1.t2 lfR}c9TQ!LlhC"sDn, g('dLJὍnuS-}i=-s<=<_C;4hRg ro, l(ީdբ=?__$\G*^>lg2ղՁSƎKh?PCiYdSa]{Q-}9Eo3~'ZVԟ|ٓa9V 9Մ1jB'ۡ4w}a(ʫ?JKƷɬ1Se_ɡ 9qT'׭i#&H˲N}ix_}YD]Y^s[7M掟&_}I-UUǤb>fײa`)Ct3dEg.:&{vsIf-߿w,{_ge>&'엯7})3ro.sɎɡ :& k?ɵsvcG+Jٹ[yͷτƶHgVs>=/UǏʑòmȭ^y'dw5]U1Ny|tShxYtkb>9vRLy [ξRf,;&ǎVʁ{ɶB'u^9$S_QMh [ICrH|&YhL:V8?w2/"n$_%nTU;de@'}G`xwÛO7BQ?cB˃CiЅN4҅N)MJI^Kdyd, .t}NQS R=M/rʿ>0^J)}PO"7+/t2Q( RPj>(EG^u/rrCi/{:Sj{}Pvy9M)_*cy7Z>4vN(& a:>d}Pvz>ENfR#-nOJm#=47[j(59{ҴMvo|IsOE)y$)c}Pvڡ4sJmm;9(Ea8EvTRű|RmZ Űމi?@)*&-mt~M(pNiヲJ @O&^|ҚP:_/fҠPz*J~ R2Mjgmf.Ԟ&J J})mxB)Kv2FvJb96\(8Ž>?zEҜP:urPKCBi{'o7*MJiR'zMjm?M:u4: 75(E*Ӥ8xB{:@(KnWf~ RkHݻt܌7ʍC{:eO@d8O\x~(^w4(E6IvJbj(uSTiPI-\JU"g(rIgҴ%5M׶ioJ /u2UzP3ΏeCR,5~vӨP5Uzퟚ`?5U&uB4%NƷݫҸJö;w}TWJJɽWm4MҰiҸ/qroP(վIswgR0Rҫ3֦Im\dJǫҤ.u2U:liF?@)OMeIOZI'&9UtTKNz>}^(QIkBiӤyCi\g>.{mD&M&Jc40L?Mi)՗xGPIUBi\T+ƩR7 #OxAe?<@p/7'm/iRP>B,U QJG&OKZ g_)  .ş6׶^ݞD8IP%l?Jg. r4+?ƸNacбk$/1dk'M!& #' #'Wʠˠ1V+ϟ1ܰܰ2`(0t.Fv"(m%dFt8]'8Aٍ!/IN_rzӟ>RNrӱ۷/9}lIn7s:՜ΦI}3\JM'>UrXJb鐠X: C J,ui`0Ս>pOu~P- ZujAa$ғ4EVHs#H:<Ҩ4NqMFvJ÷ߧ1UKuJCcRX?]5&LMipP+Ž]èIM(ڊ٭(HJu#i`(5VIݻt⬅s/x7~KR-n,Mr Xj0 ْ%ӰxP Cjq$X+A ,Q-viV4-FF(͋qmm8k\PvSS~x4Xwnti`4eMu©J<1Ujkk{_%QQ@je<"J4HaT'P4UR:)XJMcta0M©Bڙ.!*FSpO=fD#P*kFFhrTo4HW(;5MJJ/u*R۱t+`tI4NuoDSbz7h^WYGqT R@j~$e4h۽ECBiNE9U|XZpɓf,5.LLUQ8!j*R\Q0GuGi)RH:P3֥-FӤ87sBiRqRKb4 *,*Sŀj#Z z\eBPU&4V:Ic& v6MJ &OIDAT:LcV熏>]u4F6 Z &V(66ЪuJU56H=#iVcJ,4Mzo +}BiSmO!*m.M0F4$TCT1\gz@~?PUqR)RH㎤imOc0N֒-/xҹ)l+tN0+SxP#T+6yWYFQ0j9R)RA6Yl{#Z*U 1lu^iT{+~4B4 T1+)nY{OՍiR1FR[Ʊ>ICiS;ۂV,5݊o4]LES4,ڊqEU(klE#Q8H"-jb$8IPsCi|S[Wj?[z*[j<]L0- i`8U50ZX@1IrY4@WLiH:! K$z.dIO.Jsߧ5UjbiVi4 :4,SŀQjʑ4m|Xj ~/V$"鹤[S&vJ__TJc*{ ~RsKK#S3LՂI45 JT#ڈW,Jbk&WY0%bHuHunO+ƽ>ixJmorTӥ*4hNԈ15 @RluAT-ڎ:4VHZr4iA(=U|遱4;ڌLDSp=F 1UjkNq4@j;f,H Im=MJ J /vRقz^N1RӭFӥ4j4NMnDT 45]U0)jR)Rí1ER˛% rӤn(4wJmN^dH4dg,U8ti@0 :+ڋ,T[Ac+XѽQ;ڈa4D S~jER.o'iIsJWZ,8/m.-Mip4(Zقp^iܱ4'ҰsK Kö3L5F4U fDTGWRdͮBU4RmSaG6[$5=4Җ{PIP:ua4-.w2塱4쒧:=҈4hj#S!Y(&6ԺyFè85F)Ұ6Frk4M mwL|vϞ]1Sz[m^d=Fيoc4`MmSxPCjq:[gTh0GS[DRK7ErorcwRթR-q`j%*nO&&M©VsIUIP:mY/ķ_Ҥc񹥶KUiOR4 ,jGTQ ZFYv Eh8H.iH#DHӌfFr`ŬPjs ~F4(9]j;MixZPu"ZXĸ6Y{`Eè8j;>EIGp.iPtuA(Me ~ 4iShNz@Qbj*Z;hm:I q4@V"qm]t(RҨƔi4NU~DU qUJdm n5ӣ zSu=rJ}b-'F.M+*F(4<T-GVB,ε]2L¨JM#j_4-N- [kC,-4jMT-x*-:] 4(FFuh@m}S)*n 3BJks,5.LuLFpO~HU .:^u(55GUGmħHHj\ҼPtPJ,0]L05F4$TSmE .5s]4N8Bh8@ 4EJ$ G)X_u4`j= T5TͰfhX鮧uZJ{afM#NF=V$qyΖPPZci2ӥуi)Sh5*SŀQG՘+E%s5jGPiAM4QQ4):I,]#3JM'K^doTR{4hNr@ՈjZۤN58W U9T{֥MiD҈[ Bek ~3J#jOF܎o%ZAv< BjqRfk Tڃ(F-Q{liD8%u]67XV|qSk4p!Ԙ*aP6 &!$6h"VIPWXIENDB`mfgtools-uuu_1.5.182/snap/snapcraft.yaml000066400000000000000000000074521462141313700202400ustar00rootroot00000000000000%YAML 1.1 --- # Snapcraft Recipe for uuu (Universal Update Utility) # ------------------------------ # This file is in the YAML data serialization format: # http://yaml.org # For the spec. of writing this file refer the following documentation: # * The snapcraft format # https://docs.snapcraft.io/the-snapcraft-format/8337 # * Snap Documentation # https://docs.snapcraft.io # * Topics under the doc category in the Snapcraft Forum # https://forum.snapcraft.io/c/doc # For support refer to the snapcraft section in the Snapcraft Forum: # https://forum.snapcraft.io/c/snapcraft # # Copyright (c) 2017 Snapcrafters # name: universal-update-utility title: Universal Update Utility - UUU summary: Freescale/NXP I.MX Chip image deploy tools description: | **Key features** - The real cross platform. Linux, Windows, MacOS(not test yet) - Multi devices program support - Daemon mode support - Few depedencies (only libusb, zlibc, libbz2) - Firmware (uboot/kernel) uses WCID to auto load the winusb driver on the Windows side. Windows7 users need to install the winusb driver from [https://zadig.akeo.ie/](https://zadig.akeo.ie/) Windows10 will install the driver automatically. **Search keywords** mfgtools, uuu, nxp, nxpmicro icon: snap/gui/universal-update-utility.png license: BSD-3-Clause adopt-info: main assumes: - command-chain # required by the `snapctl is-connected` command - snapd2.43 base: core18 confinement: strict grade: stable parts: # Launcher programs to fix problems at runtime launchers: source: snap/local/launchers plugin: dump organize: '*': bin/ stage: - -bin/README.* # Bash completion snippets bash-completion: source: snap/local/bash-completion plugin: dump organize: '*': bash-completion/ # Check out the tagged release revision if it isn't promoted to the stable channel # https://forum.snapcraft.io/t/selective-checkout-check-out-the-tagged-release-revision-if-it-isnt-promoted-to-the-stable-channel/10617 selective-checkout: source: https://github.com/Lin-Buo-Ren/selective-checkout.git source-tag: v2.0.2 plugin: dump build-packages: - curl - jq - sed - git stage: - scriptlets/selective-checkout prime: - -* main: after: - selective-checkout source: . source-depth: 50 override-pull: | set -o nounset snapcraftctl pull "${SNAPCRAFT_STAGE}"/scriptlets/selective-checkout \ --release-tag-pattern='uuu_[[:digit:]]+(\.[[:digit:]]+){2}' \ --release-tag-prefix=uuu_ build-snaps: - cmake build-packages: # CMake shipped in Ubuntu 18.04(3.10.2) is too old #- cmake - g++ - libbz2-dev - libzstd-dev - libusb-1.0-0-dev - libssl-dev - zlib1g-dev - pkg-config plugin: cmake stage-packages: - libbz2-1.0 - libusb-1.0-0 - libssl1.0.0 filesets: docs-copyright: - usr/share/doc/*/copyright executables: - bin/* library-shared: - lib/**/*.so* prime: - $docs-copyright - $executables - $library-shared apps: universal-update-utility: adapter: full command: bin/uuu command-chain: - bin/universal-update-utility-launch completer: bash-completion/universal-update-utility environment: # Snap runtime only ship C.UTF-8 locale LANG: C.UTF-8 LC_ALL: C.UTF-8 plugs: # Regular files access home: # Allow reading the SUDO_USER's uuu script when run as root # (by default only scripts under root's home dir is readable) read: all removable-media: # Non-A/C # NOTE: This only lifts the snapd side of confinement, the user still # require classic read/write access to the target device node raw-usb: network-bind: mfgtools-uuu_1.5.182/tinyxml2/000077500000000000000000000000001462141313700162105ustar00rootroot00000000000000mfgtools-uuu_1.5.182/uuu/000077500000000000000000000000001462141313700152405ustar00rootroot00000000000000mfgtools-uuu_1.5.182/uuu/CMakeLists.txt000066400000000000000000000042121462141313700177770ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.4) set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_SKIP_RPATH ON) find_package(PkgConfig REQUIRED) pkg_check_modules(LIBUSB REQUIRED libusb-1.0>=1.0.16) pkg_check_modules(LIBZ REQUIRED zlib) pkg_check_modules(LIBZSTD REQUIRED libzstd) find_package(Threads) pkg_check_modules(TINYXML2 REQUIRED tinyxml2) if (STATIC) set(OPENSSL_USE_STATIC_LIBS TRUE) endif() find_package(OpenSSL) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread -O2") if (STATIC) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libstdc++ -static-libgcc") set(TINYXML2_LIBRARY_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/../tinyxml2") set(TINYXML2_LIBRARIES "tinyxml2.a") endif() set(LSTS uuu.lst emmc_burn_loader.lst emmc_burn_all.lst fat_write.lst qspi_burn_loader.lst fspinand_burn_loader.lst sd_burn_loader.lst spl_boot.lst sd_burn_all.lst nand_burn_loader.lst nvme_burn_all.lst ) link_directories(${CMAKE_CURRENT_SOURCE_DIR}/libuuu ${LIBUSB_LIBRARY_DIRS} ${LIBZSTD_LIBRARY_DIRS} ${LIBZ_LIBRARY_DIRS} ${TINYXML2_LIBRARY_DIRS}) set(CLIST_EXECUTABLE ${CMAKE_CURRENT_SOURCE_DIR}/gen_txt_include.sh) set(generated_files_dir "${CMAKE_BINARY_DIR}/uuu/gen") function(preprocess_clst out_var) set(result) foreach(in_f ${ARGN}) set(out_f "${generated_files_dir}/${in_f}") string(REPLACE ".lst" ".clst" out_f ${out_f}) add_custom_command(OUTPUT ${out_f} PRE_BUILD COMMAND mkdir -p ${generated_files_dir} COMMAND ${CLIST_EXECUTABLE} ${in_f} ${out_f} DEPENDS ${in_f} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMENT "Creating preprocessed clst file ${out_f}" VERBATIM ) list(APPEND result ${out_f}) endforeach() set(${out_var} "${result}" PARENT_SCOPE) endfunction() preprocess_clst(CLSTS ${LSTS}) include_directories(${generated_files_dir}) set(SOURCES uuu.cpp buildincmd.cpp autocomplete.cpp ${CLSTS} ) add_executable(uuu ${SOURCES}) target_link_libraries(uuu uuc_s ${OPENSSL_LIBRARIES} ${LIBUSB_LIBRARIES} ${LIBZ_LIBRARIES} ${LIBZSTD_LIBRARIES} ${TINYXML2_LIBRARIES} dl bz2) install(TARGETS uuu DESTINATION bin) target_compile_definitions(uuu PRIVATE "TARGET_PATH=\"${CMAKE_INSTALL_PREFIX}/bin/uuu\"" ) mfgtools-uuu_1.5.182/uuu/autocomplete.cpp000066400000000000000000000124021462141313700204440ustar00rootroot00000000000000/* * Copyright 2018 NXP. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * Neither the name of the NXP Semiconductor nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "buildincmd.h" #include "../libuuu/libuuu.h" #ifndef _MSC_VER #include #include #else #include #endif using namespace std; void linux_auto_arg(const char *space = " ", const char * filter = "") { string str = filter; const char *param[] = { "-b", "-d", "-v", "-V", "-s", NULL }; int i = 0; for (int i = 0; param[i]; i++) { if (str.find(param[i]) == string::npos) cout << param[i] << space << endl; } } int linux_autocomplete_ls(const char *path, void *p) { cout << path + 2 << endl; return 0; } void linux_autocomplete(int argc, char **argv) { string last; string cur; if (argc == 3) { last = argv[2]; }else { cur = argv[2]; last = argv[3]; } if (cur[0] == '-') { if (cur.size() == 1) linux_auto_arg(); else cout << cur << " " << endl; return; } if (last.size()>=3) { if (last.substr(last.size() - 3) == "uuu" &&(cur.empty() || cur[0] == '-')) { linux_auto_arg(); cout << cur << endl; } }else if(last.empty()) { linux_auto_arg(); } else if (last == "-b") { return g_BuildScripts.PrintAutoComplete(cur); }else if(last[0] == '-') { linux_auto_arg(); } uuu_for_each_ls_file(linux_autocomplete_ls, cur.c_str(), NULL); } string get_next_word(string str, size_t &pos) { size_t start = 0; start = str.find(' ', pos); string sub = str.substr(pos, start - pos); pos = start == string::npos ? start : start + 1; return sub; } void power_shell_autocomplete(const char *p) { string pstr = p; size_t pos = 0; string file; vector argv; string params; while (pos != string::npos && pos < pstr.size()) { file = get_next_word(pstr, pos); argv.push_back(file); if (file.size() && file[0] == '-') params += " " + file; } string last = argv[argv.size() - 1]; string prev = argv.size() > 1 ? argv[argv.size() - 2] : ""; if (last == "-b" || prev == "-b") { string cur; if (prev == "-b") cur = last; if (g_BuildScripts.find(cur) == g_BuildScripts.end()) g_BuildScripts.PrintAutoComplete(cur, ""); last.clear(); } else { if (last[0] == '-' || argv.size() == 1) linux_auto_arg("", params.c_str()); } if (argv.size() == 1) last.clear(); uuu_for_each_ls_file(linux_autocomplete_ls, last.c_str(), NULL); } int auto_complete(int argc, char**argv) { if (argc == 4 || argc == 3) { string str = argv[1]; if (str.size() >= 3) if (str.substr(str.size() - 3) == "uuu") { linux_autocomplete(argc, argv); return 0; } } if (argc >= 2) { string str = argv[1]; if (str == "-autocomplete") { power_shell_autocomplete(argc == 2 ? "" : argv[2]); return 0; } } return 1; } void print_autocomplete_help() { #ifndef _MSC_VER { cout << "Enjoy auto [tab] command complete by put below script into /etc/bash_completion.d/uuu" << endl; cout << g_vt_kcyn; cout << " _uuu_autocomplete()" < #include #include static std::string replace_str(std::string str, std::string key, std::string replace); static std::string str_to_upper(const std::string &str); /** * @brief Parse characters between argument name and its description and check * if its an optional one * @param[in] option The characters between argument name and its description to * be parsed * @return `0` in any case */ void BuiltInScript::Arg::parser(const std::string &option) { const auto pos = option.find('['); if (pos == std::string::npos) { return; } m_fallback_option = option.substr(pos + 1, option.find(']') - pos - 1); m_flags = ARG_OPTION | ARG_OPTION_KEY; } /** * @brief Create a new BuiltInScript instance by extracting information from a * BuiltInScriptRawData instance * @param[in] p The BuiltInScriptRawData containing all data of the script this * BuiltInScript instance shall represent */ BuiltInScript::BuiltInScript(const BuiltInScriptRawData * const p) : m_text{p->m_text}, m_desc{p->m_desc ? p->m_desc : ""}, m_name{p->m_name ? p->m_name : ""} { // Regular expression to detect script argument name occurrences static const std::regex arg_name_regexp{R"####((@| )(_\S+))####"}; for (std::sregex_iterator it = std::sregex_iterator{m_text.cbegin(), m_text.cend(), arg_name_regexp}; it != std::sregex_iterator{}; ++it) { const std::string param{it->str(2)}; if (!find_args(param)) { Arg a; a.m_name = param; a.m_flags = Arg::ARG_MUST; m_args.emplace_back(std::move(a)); } } for (size_t i = 0; i < m_args.size(); i++) { std::string str; str += "@"; str += m_args[i].m_name; const auto pos = m_text.find(str); if (pos != std::string::npos) { const auto start_descript = m_text.find('|', pos); if (start_descript != std::string::npos) { m_args[i].m_desc = m_text.substr(start_descript + 1, m_text.find('\n', start_descript) - start_descript - 1); const std::string def{m_text.substr(pos, start_descript - pos)}; m_args[i].parser(def); } } } } /** * @brief Check if the BuiltInScript instance has an argument called `arg` * @param[in] arg The argument for which its existence in the BuiltInScript * shall be checked * @return `true` if BuiltInScript has an argument named `arg`, `false` * otherwise */ bool BuiltInScript::find_args(const std::string &arg) const { return std::any_of(m_args.cbegin(), m_args.cend(), [&arg](const Arg &brg){ return brg.m_name == arg; }); } /** * @brief Replace built-in script's arguments by actual values given in `args` * @param[in] args The actual values that shall replace the arguments (the order * must fit the order of the arguments in the script) * @return A copy of the built-in script with the arguments replaced by their * actual values */ std::string BuiltInScript::replace_script_args(const std::vector &args) const { std::string script = m_text; for (size_t i = 0; i < args.size() && i < m_args.size(); i++) { script = replace_str(script, m_args[i].m_name, args[i]); } //handle option args; for (size_t i = args.size(); i < m_args.size(); i++) { if (m_args[i].m_flags & Arg::ARG_OPTION_KEY) { for (size_t j = 0; j < args.size(); j++) { if (m_args[j].m_name == m_args[i].m_fallback_option) { script = replace_str(script, m_args[i].m_name, args[j]); break; } } } } return script; } /** * @brief Print the built-in script to `stdout` followed by a newline */ void BuiltInScript::show() const { printf("%s\n", m_text.c_str()); } /** * @brief Print the script's name, its description and its arguments to stdout */ void BuiltInScript::show_cmd() const { printf("\t%s%s%s\t%s\n", g_vt_boldwhite, m_name.c_str(), g_vt_default, m_desc.c_str()); for (auto i = 0u; i < m_args.size(); ++i) { std::string desc{m_args[i].m_name}; if (m_args[i].m_flags & Arg::ARG_OPTION) { desc += g_vt_boldwhite; desc += "[Optional]"; desc += g_vt_default; } desc += " "; desc += m_args[i].m_desc; printf("\t\targ%u: %s\n", i, desc.c_str()); } } /** * @brief Create a new map by parsing an array of BuiltInScriptRawData instances * @param[in] p Pointer to the first element of a BuiltInScriptRawData array */ BuiltInScriptMap::BuiltInScriptMap(const BuiltInScriptRawData*p) { while (p->m_name) { emplace(p->m_name, p); ++p; } } /** * @brief Auto-complete names of built-in scripts if they match `match` * @param[in] match The string against which the scripts' names will be matched * @param[in] space A separator character which shall be printed after the * completed script name */ void BuiltInScriptMap::PrintAutoComplete(const std::string &match, const char *space) const { for (const auto &script_pair : *this) { if(script_pair.first.substr(0, match.size()) == match) { printf("%s%s\n", script_pair.first.c_str(), space); } } } /** * @brief Print information about all contained scripts to stdout */ void BuiltInScriptMap::ShowAll() const { for (const auto &script_pair : *this) { script_pair.second.show_cmd(); } } /** * @brief Print the names of all contained scripts to the given stream * @param[in] file The stream to which the names shall be printed */ void BuiltInScriptMap::ShowCmds(FILE * const file) const { fprintf(file, "<"); for (auto iCol = begin(); iCol != end(); ++iCol) { fprintf(file, "%s", iCol->first.c_str()); auto i = iCol; i++; if(i != end()) { fprintf(file, "|"); } } fprintf(file, ">"); } /** * @brief Replace a `key` substring of a string `str` by a replacement `replace` * @param[in] str The string of which a copy with the replacements shall be * created * @param[in] key The string which shall be replaced * @param[in] replace The string that shall replace occurrences of `key` * @return A new string instance with the replacements conducted on it */ static std::string replace_str(std::string str, std::string key, std::string replace) { std::string s5, s4; std::string match[] = { ".BZ2", ".ZST" }; if (replace.size() > 4) { if (replace[replace.size() - 1] == '\"') { s5 = str_to_upper(replace.substr(replace.size() - 5)); for (std::string it : match) { if (s5 == it) { replace = replace.substr(0, replace.size() - 1); replace += "/*\""; } } } else { s4 = str_to_upper(replace.substr(replace.size() - 4)); for (std::string it : match) { if (it == s4) { replace += "/*"; } } } } for (size_t j = 0; (j = str.find(key, j)) != std::string::npos;) { if (j == 0 || (j!=0 && str[j - 1] == ' ')) str.replace(j, key.size(), replace); j += key.size(); } return str; } /** * @brief Returns a copy of `str` with all applicable characters converted to * uppercase * @param[in] str The string for which an uppercase copy shall be created * @return The copy of `str` converted to uppercase */ static std::string str_to_upper(const std::string &str) { const std::locale loc; std::string s; s.reserve(str.size()); for (size_t i = 0; i < str.size(); ++i) { s.push_back(std::toupper(str[i], loc)); } return s; } //! Array containing raw information about all the built-in scripts of uuu static constexpr BuiltInScriptRawData g_builtin_cmd[] = { { "emmc", #include "emmc_burn_loader.clst" ,"burn boot loader to eMMC boot partition" }, { "emmc_all", #include "emmc_burn_all.clst" ,"burn whole image to eMMC" }, { "fat_write", #include "fat_write.clst" ,"update one file in fat partition, require uboot fastboot running in board" }, { "nand", #include "nand_burn_loader.clst" ,"burn boot loader to NAND flash" }, { "qspi", #include "qspi_burn_loader.clst" ,"burn boot loader to qspi nor flash" }, { "spi_nand", #include "fspinand_burn_loader.clst" ,"burn boot loader to spi nand flash" }, { "sd", #include "sd_burn_loader.clst" ,"burn boot loader to sd card" }, { "sd_all", #include "sd_burn_all.clst" ,"burn whole image to sd card" }, { "spl", #include "spl_boot.clst" ,"boot spl and uboot" }, { "nvme_all", #include "nvme_burn_all.clst" ,"burn whole image io nvme storage" }, { nullptr, nullptr, nullptr, } }; //! A map of the built-in scripts' names to their BuiltInScript representations BuiltInScriptMap g_BuildScripts(g_builtin_cmd); mfgtools-uuu_1.5.182/uuu/buildincmd.h000066400000000000000000000074071462141313700175330ustar00rootroot00000000000000/* * Copyright 2018-2021 NXP. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * Neither the name of the NXP Semiconductor nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #pragma once #include #include #include #include extern const char * g_vt_boldwhite; extern const char * g_vt_default; extern const char * g_vt_kcyn; extern const char * g_vt_green; extern const char * g_vt_red ; extern const char * g_vt_yellow; /** * @brief Structure to hold the raw data of a built-in script */ struct BuiltInScriptRawData { //! The name of the built-in script const char * const m_name = nullptr; //! The actual built-in script itself const char * const m_text = nullptr; //! A description of the built-in script's purpose const char * const m_desc = nullptr; }; class BuiltInScript { public: /** * @brief A class for representing arguments of built-in scripts represented * by BuiltInScript */ class Arg { public: enum { ARG_MUST = 0x1, ARG_OPTION = 0x2, ARG_OPTION_KEY = 0x4, }; void parser(const std::string &option); //! The name of the argument std::string m_name; //! A description of the argument std::string m_desc; //! Flags of the argument (basically if it's optional or not) uint32_t m_flags = ARG_MUST; //! The argument whose value this one will fall back to if it's optional //! and not given explicitly std::string m_fallback_option; }; BuiltInScript() {}; BuiltInScript(const BuiltInScriptRawData*p); std::string replace_script_args(const std::vector &args) const; void show() const; void show_cmd() const; //! The actual script which is being represented const std::string m_text; //! A description of the script's purpose const std::string m_desc; //! A short name of the built-in script const std::string m_name; //! The arguments of the built-in script std::vector m_args; private: bool find_args(const std::string &arg) const; }; /** * @brief A map of all built-in scripts indexed by their names * * Each built-in script is represented by a BuiltInScript instance. */ class BuiltInScriptMap : public std::map { public: BuiltInScriptMap(const BuiltInScriptRawData*p); void PrintAutoComplete(const std::string &match, const char *space = " ") const; void ShowAll() const; void ShowCmds(FILE * file=stdout) const; }; //! A map of the built-in scripts' names to their BuiltInScript representations extern BuiltInScriptMap g_BuildScripts; mfgtools-uuu_1.5.182/uuu/emmc_burn_all.lst000066400000000000000000000022101462141313700205560ustar00rootroot00000000000000uuu_version 1.4.149 # @_flash.bin | bootloader, which can extract from wic image # @_image [_flash.bin] | wic image burn to emmc. # This command will be run when i.MX6/7 i.MX8MM, i.MX8MQ SDP: boot -f _flash.bin -scanlimited 0x800000 # This command will be run when ROM support stream mode # i.MX8QXP, i.MX8QM SDPS: boot -scanterm -f _flash.bin -scanlimited 0x800000 # These commands will be run when use SPL and will be skipped if no spl # SDPU will be deprecated. please use SDPV instead of SDPU # { SDPU: delay 1000 SDPU: write -f _flash.bin -offset 0x57c00 SDPU: jump -scanlimited 0x800000 # } # These commands will be run when use SPL and will be skipped if no spl # if (SPL support SDPV) # { SDPV: delay 1000 SDPV: write -f _flash.bin -skipspl -scanterm -scanlimited 0x800000 SDPV: jump -scanlimited 0x800000 # } FB: ucmd setenv fastboot_dev mmc FB: ucmd setenv mmcdev ${emmc_dev} FB: ucmd mmc dev ${emmc_dev} FB: flash -raw2sparse all _image FB: flash -scanterm -scanlimited 0x800000 bootloader _flash.bin FB: ucmd if env exists emmc_ack; then ; else setenv emmc_ack 0; fi; FB: ucmd mmc partconf ${emmc_dev} ${emmc_ack} 1 0 FB: done mfgtools-uuu_1.5.182/uuu/emmc_burn_loader.lst000066400000000000000000000016721462141313700212670ustar00rootroot00000000000000uuu_version 1.2.39 # @_flash.bin | bootloader # @_image [_flash.bin] | image burn to emmc, default is the same as bootloader # This command will be run when i.MX6/7 i.MX8MM, i.MX8MQ SDP: boot -f _flash.bin # This command will be run when ROM support stream mode # i.MX8QXP, i.MX8QM SDPS: boot -f _flash.bin # These commands will be run when use SPL and will be skipped if no spl # SDPU will be deprecated. please use SDPV instead of SDPU # { SDPU: delay 1000 SDPU: write -f _flash.bin -offset 0x57c00 SDPU: jump # } # These commands will be run when use SPL and will be skipped if no spl # if (SPL support SDPV) # { SDPV: delay 1000 SDPV: write -f _flash.bin -skipspl SDPV: jump # } FB: ucmd setenv fastboot_dev mmc FB: ucmd setenv mmcdev ${emmc_dev} FB: ucmd mmc dev ${emmc_dev} FB: flash bootloader _image FB: ucmd if env exists emmc_ack; then ; else setenv emmc_ack 0; fi; FB: ucmd mmc partconf ${emmc_dev} ${emmc_ack} 1 0 FB: Done mfgtools-uuu_1.5.182/uuu/fat_write.lst000066400000000000000000000010061462141313700177450ustar00rootroot00000000000000uuu_version 1.1.4 # @_image | image, which cp to fat partition # @_device | storage device, mmc\sata # @_partition | fat partition number, like 1:1 # @_filename [_image] | file name in target fat partition, only support rootdir now FB: ucmd setenv fastboot_buffer ${loadaddr} FB: download -f _image FB: ucmd if test ! -n "$fastboot_bytes"; then setenv fastboot_bytes $filesize; else true; fi FB[-t 20000]: ucmd fatwrite _device _partition ${fastboot_buffer} _filename ${fastboot_bytes} FB: done mfgtools-uuu_1.5.182/uuu/fspinand_burn_loader.lst000066400000000000000000000017721462141313700221510ustar00rootroot00000000000000uuu_version 1.2.39 # @_flexspi.bin | bootloader # @_image [_flexspi.bin] | image burn to fspinand, default is the same as bootloader # This command will be run when i.MX6/7 i.MX8MM, i.MX8MQ SDP: boot -f _flexspi.bin # This command will be run when ROM support stream mode # i.MX8QXP, i.MX8QM, skip QSPI header SDPS: boot -f _flexspi.bin -skipfhdr # These commands will be run when use SPL and will be skipped if no spl # SDPU will be deprecated. please use SDPV instead of SDPU # { SDPU: delay 1000 SDPU: write -f _flexspi.bin -offset 0x10000 -skipfhdr SDPU: jump # } # These commands will be run when use SPL and will be skipped if no spl # if (SPL support SDPV) # { SDPV: delay 1000 SDPV: write -f _flexspi.bin -skipspl -skipfhdr SDPV: jump # } FB: ucmd setenv fastboot_buffer ${loadaddr} FB: download -f _image FB: ucmd if test ! -n "$fastboot_bytes"; then setenv fastboot_bytes $filesize; else true; fi FB[-t 60000]: ucmd fspinand init spi-nand0 ${fastboot_buffer} ${fastboot_bytes} FB: done mfgtools-uuu_1.5.182/uuu/gen_txt_include.sh000077500000000000000000000001021462141313700207430ustar00rootroot00000000000000#!/bin/sh echo "R\"####(" > $2 cat $1 >> $2 echo ")####\"" >> $2 mfgtools-uuu_1.5.182/uuu/nand_burn_loader.lst000066400000000000000000000021421462141313700212570ustar00rootroot00000000000000uuu_version 1.2.39 # @_flash.bin | bootloader # @_image [_flash.bin] | image burn to nand, default is the same as bootloader # This command will be run when i.MX6/7 i.MX8MM, i.MX8MQ SDP: boot -f _flash.bin # This command will be run when ROM support stream mode # i.MX8QXP, i.MX8QM SDPS: boot -f _flash.bin # These commands will be run when use SPL and will be skipped if no spl # SDPU will be deprecated. please use SDPV instead of SDPU # { SDPU: delay 1000 SDPU: write -f _flash.bin -offset 0x57c00 SDPU: jump # } # These commands will be run when use SPL and will be skipped if no spl # if (SPL support SDPV) # { SDPV: delay 1000 SDPV: write -f _flash.bin -skipspl SDPV: jump # } FB: ucmd setenv fastboot_buffer ${loadaddr} FB: download -f _image FB: ucmd if test ! -n "$fastboot_bytes"; then setenv fastboot_bytes $filesize; else true; fi # Burn image to nandfit partition if needed FB: ucmd if env exists nandfit_part; then nand erase.part nandfit; nand write ${fastboot_buffer} nandfit ${fastboot_bytes}; else true; fi; FB: ucmd nandbcb init ${fastboot_buffer} nandboot ${fastboot_bytes} FB: Done mfgtools-uuu_1.5.182/uuu/nvme_burn_all.lst000066400000000000000000000017561462141313700206200ustar00rootroot00000000000000uuu_version 1.4.149 # @_flash.bin | bootloader, which can extract from wic image # @_image [_flash.bin] | wic image burn to emmc. # This command will be run when i.MX6/7 i.MX8MM, i.MX8MQ SDP: boot -f _flash.bin -scanlimited 0x800000 # This command will be run when ROM support stream mode # i.MX8QXP, i.MX8QM SDPS: boot -scanterm -f _flash.bin -scanlimited 0x800000 # These commands will be run when use SPL and will be skipped if no spl # SDPU will be deprecated. please use SDPV instead of SDPU # { SDPU: delay 1000 SDPU: write -f _flash.bin -offset 0x57c00 SDPU: jump -scanlimited 0x800000 # } # These commands will be run when use SPL and will be skipped if no spl # if (SPL support SDPV) # { SDPV: delay 1000 SDPV: write -f _flash.bin -skipspl -scanterm -scanlimited 0x800000 SDPV: jump -scanlimited 0x800000 # } FB: ucmd pci FB: ucmd nvme scan FB: ucmd setenv fastboot_buffer ${loadaddr} FB: write -format "nvme write ${fastboot_buffer} @off @size" -blksz 512 -f _image FB: done mfgtools-uuu_1.5.182/uuu/qspi_burn_loader.lst000066400000000000000000000031351462141313700213160ustar00rootroot00000000000000uuu_version 1.2.39 # @_flexspi.bin | bootloader # @_image [_flexspi.bin] | image burn to flexspi, default is the same as bootloader # This command will be run when i.MX6/7 i.MX8MM, i.MX8MQ SDP: boot -f _flexspi.bin # This command will be run when ROM support stream mode # i.MX8QXP, i.MX8QM, skip QSPI header SDPS: boot -f _flexspi.bin -skipfhdr # These commands will be run when use SPL and will be skipped if no spl # SDPU will be deprecated. please use SDPV instead of SDPU # { SDPU: delay 1000 SDPU: write -f _flexspi.bin -offset 0x10000 -skipfhdr SDPU: jump # } # These commands will be run when use SPL and will be skipped if no spl # if (SPL support SDPV) # { SDPV: delay 1000 SDPV: write -f _flexspi.bin -skipspl -skipfhdr SDPV: jump # } FB: ucmd setenv fastboot_buffer ${loadaddr} FB: download -f _image FB: ucmd if test ! -n "$fastboot_bytes"; then setenv fastboot_bytes $filesize; else true; fi # Check Image if include flexspi header FB: ucmd if qspihdr dump ${fastboot_buffer}; then setenv qspihdr_exist yes; else setenv qspihdr_exist no; fi; FB[-t 60000]: ucmd if test ${qspihdr_exist} = yes; then qspihdr init ${fastboot_buffer} ${fastboot_bytes} safe; else true; fi; #if uboot can't support qspihdr command, use uboot image to write qspi image, which require image include qspi flash header FB: ucmd if test ${qspihdr_exist} = no; then sf probe; else true; fi; FB[-t 40000]: ucmd if test ${qspihdr_exist} = no; then sf erase 0 +${fastboot_bytes}; else true; fi; FB[-t 20000]: ucmd if test ${qspihdr_exist} = no; then sf write ${fastboot_buffer} 0 ${fastboot_bytes}; else true; fi; FB: done mfgtools-uuu_1.5.182/uuu/sd_burn_all.lst000066400000000000000000000020431462141313700202470ustar00rootroot00000000000000uuu_version 1.4.149 # @_flash.bin | bootloader, which can extract from wic image # @_image [_flash.bin] | wic image burn to emmc. # This command will be run when i.MX6/7 i.MX8MM, i.MX8MQ SDP: boot -f _flash.bin -scanlimited 0x800000 # This command will be run when ROM support stream mode # i.MX8QXP, i.MX8QM SDPS: boot -scanterm -f _flash.bin -scanlimited 0x800000 # These commands will be run when use SPL and will be skipped if no spl # SDPU will be deprecated. please use SDPV instead of SDPU # { SDPU: delay 1000 SDPU: write -f _flash.bin -offset 0x57c00 -scanlimited 0x800000 SDPU: jump -scanlimited 0x800000 # } # These commands will be run when use SPL and will be skipped if no spl # if (SPL support SDPV) # { SDPV: delay 1000 SDPV: write -f _flash.bin -skipspl -scanterm -scanlimited 0x800000 SDPV: jump -scanlimited 0x800000 # } FB: ucmd setenv fastboot_dev mmc FB: ucmd setenv mmcdev ${sd_dev} FB: ucmd mmc dev ${sd_dev} FB: flash -raw2sparse all _image FB: flash -scanterm -scanlimited 0x800000 bootloader _flash.bin FB: done mfgtools-uuu_1.5.182/uuu/sd_burn_loader.lst000066400000000000000000000015001462141313700207420ustar00rootroot00000000000000uuu_version 1.2.39 # @_flash.bin | bootloader # @_image [_flash.bin] | image burn to emmc, default is the same as bootloader # This command will be run when i.MX6/7 i.MX8MM, i.MX8MQ SDP: boot -f _flash.bin # This command will be run when ROM support stream mode # i.MX8QXP, i.MX8QM SDPS: boot -f _flash.bin # These commands will be run when use SPL and will be skipped if no spl # SDPU will be deprecated. please use SDPV instead of SDPU # { SDPU: delay 1000 SDPU: write -f _flash.bin -offset 0x57c00 SDPU: jump # } # These commands will be run when use SPL and will be skipped if no spl # if (SPL support SDPV) # { SDPV: delay 1000 SDPV: write -f _flash.bin -skipspl SDPV: jump # } FB: ucmd setenv fastboot_dev mmc FB: ucmd setenv mmcdev ${sd_dev} FB: ucmd mmc dev ${sd_dev} FB: flash bootloader _image FB: Done mfgtools-uuu_1.5.182/uuu/spl_boot.lst000066400000000000000000000011451462141313700176060ustar00rootroot00000000000000uuu_version 1.2.39 # This command will be run when i.MX6/7 i.MX8MM, i.MX8MQ SDP: boot -f _flash.bin # This command will be run when ROM support stream mode # i.MX8QXP, i.MX8QM SDPS[-t 10000]: boot -f _flash.bin # These commands will be run when use SPL and will be skipped if no spl # SDPU will be deprecated. please use SDPV instead of SDPU # { SDPU: delay 1000 SDPU: write -f _flash.bin -offset 0x57c00 SDPU: jump SDPU: done # } # These commands will be run when use SPL and will be skipped if no spl # if (SPL support SDPV) # { SDPV: delay 1000 SDPV: write -f _flash.bin -skipspl SDPV: jump SDPV: done # } mfgtools-uuu_1.5.182/uuu/uuu.cpp000066400000000000000000000642221462141313700165700ustar00rootroot00000000000000/* * Copyright 2018 NXP. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * Neither the name of the NXP Semiconductor nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "buildincmd.h" #include #include #include "../libuuu/libuuu.h" const char * g_vt_yellow = "\x1B[93m"; const char * g_vt_default = "\x1B[0m"; const char * g_vt_green = "\x1B[92m"; const char * g_vt_red = "\x1B[91m"; const char * g_vt_kcyn = "\x1B[36m"; const char * g_vt_boldwhite = "\x1B[97m"; void clean_vt_color() noexcept { g_vt_yellow = ""; g_vt_default = g_vt_yellow; g_vt_green = g_vt_yellow; g_vt_red = g_vt_yellow; g_vt_kcyn = g_vt_yellow; g_vt_boldwhite = g_vt_yellow; } using namespace std; int get_console_width(); void print_oneline(string str); int auto_complete(int argc, char**argv); void print_autocomplete_help(); char g_sample_cmd_list[] = { #include "uuu.clst" }; vector g_usb_path_filter; vector g_usb_serial_no_filter; int g_verbose = 0; static bool g_start_usb_transfer; bmap_mode g_bmap_mode = bmap_mode::Default; class AutoCursor { public: ~AutoCursor() { printf("\x1b[?25h\n\n\n"); } }; void ctrl_c_handle(int) { do { AutoCursor a; } while(0); exit(1); } class string_ex : public std::string { public: int format(const char *fmt, ...) { va_list args; va_start(args, fmt); size_t len = std::vsnprintf(NULL, 0, fmt, args); va_end(args); this->resize(len); va_start(args, fmt); std::vsnprintf((char*)c_str(), len + 1, fmt, args); va_end(args); return 0; } }; #ifdef _WIN32 #include #else #include #include #endif int ask_passwd(char* prompt, char user[MAX_USER_LEN], char passwd[MAX_USER_LEN]) { cout << endl << prompt << " Required Login"< MAX_USER_LEN -1) return -1; memcpy(passwd, pd.data(), pd.size()); i=pd.size(); #endif passwd[i] = 0; cout << endl; return 0; } void print_help(bool detail = false) { const char help[] = "uuu [-d -m -v -V -bmap -no-bmap] <" "bootloader|cmdlists|cmd" ">\n\n" " bootloader download bootloader to board by usb\n" " cmdlist run all commands in cmdlist file\n" " If it is path, search uuu.auto in dir\n" " If it is zip, search uuu.auto in zip\n" " cmd Run one command, use -H see detail\n" " example: SDPS: boot -f flash.bin\n" " -d Daemon mode, wait for forever.\n" " -v -V verbose mode, -V enable libusb error\\warning info\n" " -dry Dry run mode, check if script or cmd correct \n" " -bmap Try using .bmap files even if flash commands do not specify them\n" " -no-bmap Ignore .bmap files even if flash commands specify them\n" " -m USBPATH Only monitor these paths.\n" " -m 1:2 -m 1:3\n\n" " -ms serial_no Monitor the serial number prefix of the device using 'serial_no'.\n" " -t Timeout second for wait known usb device appeared\n" " -T Timeout second for wait next known usb device appeared at stage switch\n" " -e set environment variable key=value\n" " -pp usb polling period in milliseconds\n" " -dm disable small memory\n" "uuu -s Enter shell mode. uuu.inputlog record all input commands\n" " you can use \"uuu uuu.inputlog\" next time to run all commands\n\n" "uuu -udev linux: show udev rule to avoid sudo each time \n" "uuu -lsusb List connected know devices\n" "uuu -IgSerNum Set windows registry to ignore USB serial number for known uuu devices\n" "uuu -h show general help\n" "uuu -H show general help and detailed help for commands\n\n"; printf("%s", help); printf("uuu [-d -m -v -bmap -no-bmap] -b[run] "); g_BuildScripts.ShowCmds(); printf(" arg...\n"); printf("\tRun Built-in scripts\n"); g_BuildScripts.ShowAll(); printf("\nuuu -bshow "); g_BuildScripts.ShowCmds(); printf("\n"); printf("\tShow built-in script\n"); printf("\n"); print_autocomplete_help(); if (detail == false) return; size_t start = 0, pos = 0; string str= g_sample_cmd_list; bool bprint = false; while ((pos = str.find('\n',pos)) != str.npos) { string s = str.substr(start, pos - start); if (s.substr(0, 6) == "# ----") bprint = true; if (bprint) { if (s[0] == '#') { printf("%s\n", &(s[1])); } } pos += 1; start = pos; } } void print_version() { printf("uuu (Universal Update Utility) for nxp imx chips -- %s\n\n", uuu_get_version_string()); } int print_cfg(const char *pro, const char * chip, const char * /*compatible*/, uint16_t vid, uint16_t pid, uint16_t bcdmin, uint16_t bcdmax, void * /*p*/) { const char *ext; if (strlen(chip) >= 7) ext = ""; else ext = "\t"; if (bcdmin == 0 && bcdmax == 0xFFFF) printf("\t%s\t %s\t%s 0x%04x\t 0x%04x\n", pro, chip, ext, vid, pid); else printf("\t%s\t %s\t%s 0x%04x\t 0x%04x\t [0x%04x..0x%04x]\n", pro, chip, ext, vid, pid, bcdmin, bcdmax); return 0; } int print_udev_rule(const char * /*pro*/, const char * /*chip*/, const char * /*compatible*/, uint16_t vid, uint16_t pid, uint16_t /*bcdmin*/, uint16_t /*bcdmax*/, void * /*p*/) { printf("SUBSYSTEM==\"usb\", ATTRS{idVendor}==\"%04x\", ATTRS{idProduct}==\"%04x\", TAG+=\"uaccess\"\n", vid, pid); return 0; } int polling_usb(std::atomic& bexit); int g_overall_status; int g_overall_okay; int g_overall_failure; char g_wait[] = "|/-\\"; int g_wait_index; string build_process_bar(size_t width, size_t pos, size_t total) { string str; str.resize(width, ' '); str[0] = '['; str[width - 1] = ']'; if (total == 0) { if (pos == 0) return str; string_ex loc; size_t s = pos / (1024 * 1024); loc.format("%dM", s); str.replace(1, loc.size(), loc); return str; } size_t i; if (pos > total) pos = total; for (i = 1; i < (width-2) * pos / total; i++) { str[i] = '='; } if (i > 1) str[i] = '>'; if (pos == total) str[str.size() - 2] = '='; string_ex per; per.format("%d%%", pos * 100 / total); size_t start = (width - per.size()) / 2; str.replace(start, per.size(), per); str.insert(start, g_vt_yellow); str.insert(start + per.size() + strlen(g_vt_yellow), g_vt_default); return str; } void print_auto_scroll(string str, size_t len, size_t start) { if (str.size() <= len) { str.resize(len, ' '); cout << str; return; } if(str.size()) start = start % str.size(); else start = 0; string s = str.substr(start, len); s.resize(len, ' '); cout << s; } class ShowNotify { public: string m_cmd; string m_dev; size_t m_trans_pos = 0; int m_status = 0; size_t m_cmd_total = 0; size_t m_cmd_index = 0; string m_last_err; int m_done = 0; size_t m_start_pos = 0; size_t m_trans_size = 0; clock_t m_start_time; uint64_t m_cmd_start_time; uint64_t m_cmd_end_time; bool m_IsEmptyLine = false; ShowNotify() : m_start_time{clock()} {} bool update(uuu_notify nt) { if (nt.type == uuu_notify::NOTIFY_DEV_ATTACH) { m_dev = nt.str; m_done = 0; m_status = 0; } if (nt.type == uuu_notify::NOTIFY_CMD_START) { m_start_pos = 0; m_cmd = nt.str; m_cmd_start_time = nt.timestamp; } if (nt.type == uuu_notify::NOTIFY_DECOMPRESS_START) { m_start_pos = 0; m_cmd = nt.str; m_cmd_start_time = nt.timestamp; m_dev = "Prep"; } if (nt.type == uuu_notify::NOTIFY_DOWNLOAD_START) { m_start_pos = 0; m_cmd = nt.str; m_cmd_start_time = nt.timestamp; m_dev = "Prep"; } if (nt.type == uuu_notify::NOTIFY_DOWNLOAD_END) { m_IsEmptyLine = true; } if (nt.type == uuu_notify::NOTIFY_TRANS_SIZE || nt.type == uuu_notify::NOTIFY_DECOMPRESS_SIZE) { m_trans_size = nt.total; return false; } if (nt.type == uuu_notify::NOTIFY_CMD_TOTAL) { m_cmd_total = nt.total; return false; } if (nt.type == uuu_notify::NOTIFY_CMD_INDEX) { m_cmd_index = nt.index; return false; } if (nt.type == uuu_notify::NOTIFY_DONE) { if (m_status) g_overall_failure++; else g_overall_okay++; m_done = 1; } if (nt.type == uuu_notify::NOTIFY_CMD_END) { m_cmd_end_time = nt.timestamp; if(nt.status) { g_overall_status = nt.status; m_last_err = uuu_get_last_err_string(); } m_status |= nt.status; if (m_status) g_overall_failure++; } if (nt.type == uuu_notify::NOTIFY_TRANS_POS || nt.type == uuu_notify::NOTIFY_DECOMPRESS_POS) { if (m_trans_size == 0) { m_trans_pos = nt.index; return true; } if ((nt.index - m_trans_pos) < (m_trans_size / 100) && nt.index != m_trans_size) return false; m_trans_pos = nt.index; } return true; } void print_verbose(uuu_notify*nt) { if (this->m_dev == "Prep" && g_start_usb_transfer) return; if (nt->type == uuu_notify::NOTIFY_DEV_ATTACH) { cout << "New USB Device Attached at " << nt->str << endl; } if (nt->type == uuu_notify::NOTIFY_CMD_START) { cout << m_dev << ">" << "Start Cmd:" << nt->str << endl; } if (nt->type == uuu_notify::NOTIFY_CMD_END) { double diff = m_cmd_end_time - m_cmd_start_time; diff /= 1000; if (nt->status) { cout << m_dev << ">" << g_vt_red <<"Fail " << uuu_get_last_err_string() << "("<< std::setprecision(4) << diff << "s)" << g_vt_default << endl; } else { cout << m_dev << ">" << g_vt_green << "Okay ("<< std::setprecision(4) << diff << "s)" << g_vt_default << endl; } } if (nt->type == uuu_notify::NOTIFY_TRANS_POS || nt->type == uuu_notify::NOTIFY_DECOMPRESS_POS) { if (m_trans_size) cout << g_vt_yellow << "\r" << m_trans_pos * 100 / m_trans_size <<"%" << g_vt_default; else cout << "\r" << m_trans_pos; cout.flush(); } if (nt->type == uuu_notify::NOTIFY_CMD_INFO) cout << nt->str; if (nt->type == uuu_notify::NOTIFY_WAIT_FOR) cout << "\r" << nt->str << " "<< g_wait[((g_wait_index++) & 0x3)]; if (nt->type == uuu_notify::NOTIFY_DECOMPRESS_START) cout << "Decompress file:" << nt->str << endl; if (nt->type == uuu_notify::NOTIFY_DOWNLOAD_START) cout << "Download file:" << nt->str << endl; } void print(int verbose = 0, uuu_notify*nt=NULL) { verbose ? print_verbose(nt) : print_simple(); } string get_print_dev_string() { string str; str = m_dev; str.resize(12, ' '); string_ex s; s.format("%2d/%2d", m_cmd_index+1, m_cmd_total); str += s; return str; } void print_simple() { int width = get_console_width(); int info, bar; info = 18; bar = 40; if (m_IsEmptyLine) { string str(width, ' '); cout << str; return; } if (width <= bar + info + 3) { string_ex str; str += get_print_dev_string(); str += g_wait[(g_wait_index++) & 0x3]; print_oneline(str); return ; } else { string_ex str; str += get_print_dev_string(); str.resize(info, ' '); cout << str; if (m_done || m_status) { string str; str.resize(bar, ' '); str[0] = '['; str[str.size() - 1] = ']'; string err; if (m_status) { err = uuu_get_last_err_string(); err.resize(bar - 2, ' '); str.replace(1, err.size(), err); str.insert(1, g_vt_red); str.insert(1 + strlen(g_vt_red) + err.size(), g_vt_default); } else { str.replace(1, 4, "Done"); str.insert(1, g_vt_green); str.insert(1 + strlen(g_vt_green) + strlen("Done"), g_vt_default); } cout << str; } else { cout << build_process_bar(bar, m_trans_pos, m_trans_size); } cout << " "; print_auto_scroll(m_cmd, width - bar - info-1, m_start_pos); if (clock() - m_start_time > CLOCKS_PER_SEC / 4) { m_start_pos++; m_start_time = clock(); } cout << endl; return; } } }; static map g_map_path_nt; mutex g_callback_mutex; void print_oneline(string str) { size_t w = get_console_width(); if (w <= 3) return; if (str.size() >= w) { str.resize(w - 1); str[str.size() - 1] = '.'; str[str.size() - 2] = '.'; str[str.size() - 3] = '.'; } else { str.resize(w, ' '); } cout << str << endl; } ShowNotify Summary(map *np) { ShowNotify sn; for (auto it = np->begin(); it != np->end(); it++) { if (it->second.m_dev == "Prep") { sn.m_trans_size += it->second.m_trans_size; sn.m_trans_pos += it->second.m_trans_pos; } else { if (it->second.m_trans_pos || it->second.m_cmd_index) g_start_usb_transfer = true; // Hidden HTTP download when USB start transfer } } if(g_start_usb_transfer) sn.m_IsEmptyLine = true; // Hidden HTTP download when USB start transfer sn.m_dev = "Prep"; sn.m_cmd = "Http Download\\Uncompress"; return sn; } int progress(uuu_notify nt, void *p) { map *np = (map*)p; map::iterator it; std::lock_guard lock(g_callback_mutex); if ((*np)[nt.id].update(nt)) { if (!(*np)[nt.id].m_dev.empty()) if ((*np)[nt.id].m_dev != "Prep") g_map_path_nt[(*np)[nt.id].m_dev] = (*np)[nt.id]; if (g_verbose) { if((*np)[nt.id].m_dev == "Prep") Summary(np).print(g_verbose, &nt); else (*np)[nt.id].print(g_verbose, &nt); } else { string_ex str; str.format("\rSuccess %d Failure %d ", g_overall_okay, g_overall_failure); if (g_map_path_nt.empty()) str += "Wait for Known USB Device Appear..."; if (!g_usb_path_filter.empty()) { str += " at path "; for (size_t i = 0; i < g_usb_path_filter.size(); i++) str += g_usb_path_filter[i] + " "; } if (!g_usb_serial_no_filter.empty()) { str += " at serial_no "; for (auto it: g_usb_serial_no_filter) str += it + "*"; } print_oneline(str); print_oneline(""); if ((*np)[nt.id].m_dev == "Prep" && !g_start_usb_transfer) { Summary(np).print(); }else print_oneline(""); for (it = g_map_path_nt.begin(); it != g_map_path_nt.end(); it++) it->second.print(); for (size_t i = 0; i < g_map_path_nt.size() + 3; i++) cout << "\x1B[1F"; } //(*np)[nt.id] = g_map_path_nt[(*np)[nt.id].m_dev]; } if (nt.type == uuu_notify::NOTIFY_THREAD_EXIT) { if(np->find(nt.id) != np->end()) np->erase(nt.id); } return 0; } #ifdef _MSC_VER #define DEFINE_CONSOLEV2_PROPERTIES #include #include #include bool enable_vt_mode() { // Set output mode to handle virtual terminal sequences HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); if (hOut == INVALID_HANDLE_VALUE) { clean_vt_color(); return false; } DWORD dwMode = 0; if (!GetConsoleMode(hOut, &dwMode)) { clean_vt_color(); return false; } dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; if (!SetConsoleMode(hOut, dwMode)) { clean_vt_color(); return false; } return true; } int get_console_width() { CONSOLE_SCREEN_BUFFER_INFO sbInfo; GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &sbInfo); return sbInfo.dwSize.X; } #else #include bool enable_vt_mode() { return true; } int get_console_width() { struct winsize w; ioctl(0, TIOCGWINSZ, &w); return w.ws_col; } #endif void print_usb_filter() { if (!g_usb_path_filter.empty()) { cout << " at path "; for (size_t i = 0; i < g_usb_path_filter.size(); i++) cout << g_usb_path_filter[i] << " "; } } int runshell(int shell) { int uboot_cmd = 0; string prompt = "U>"; if (shell) { cout << "Please input command: " << endl; string cmd; ofstream log("uuu.inputlog", ofstream::binary); log << "uuu_version " << ((uuu_get_version() & 0xFF000000) >> 24) << "." << ((uuu_get_version() & 0xFFF000) >> 12) << "." << ((uuu_get_version() & 0xFFF)) << endl; while (1) { cout << prompt; getline(cin, cmd); if (cmd == "uboot") { uboot_cmd = 1; prompt = "=>"; cout << "Enter into u-boot cmd mode" << endl; cout << "Okay" << endl; } else if (cmd == "exit" && uboot_cmd == 1) { uboot_cmd = 0; prompt = "U>"; cout << "Exit u-boot cmd mode" << endl; cout << "Okay" << endl; }else if (cmd == "help" || cmd == "?") { print_help(); } else if (cmd == "q" || cmd == "quit") { return 0; } else { log << cmd << endl; log.flush(); if (uboot_cmd) cmd = "fb: ucmd " + cmd; int ret = uuu_run_cmd(cmd.c_str(), 0); if (ret) cout << uuu_get_last_err_string() << endl; else cout << "Okay" << endl; } } return 0; } return -1; } void print_udev() { uuu_for_each_cfg(print_udev_rule, NULL); fprintf(stderr, "\n1: put above udev run into /etc/udev/rules.d/70-uuu.rules\n"); fprintf(stderr, "\tsudo sh -c \"uuu -udev >> /etc/udev/rules.d/70-uuu.rules\"\n"); fprintf(stderr, "2: update udev rule\n"); fprintf(stderr, "\tsudo udevadm control --reload\n"); } int print_usb_device(const char *path, const char *chip, const char *pro, uint16_t vid, uint16_t pid, uint16_t bcd, const char *serial_no, void * /*p*/) { printf("\t%s\t %s\t %s\t 0x%04X\t0x%04X\t 0x%04X\t %s\n", path, chip, pro, vid, pid, bcd, serial_no); return 0; } void print_lsusb() { cout << "Connected Known USB Devices\n"; printf("\tPath\t Chip\t Pro\t Vid\t Pid\t BcdVersion\t Serial_no\n"); printf("\t====================================================================\n"); uuu_for_each_devices(print_usb_device, NULL); } #ifdef WIN32 int ignore_serial_number(const char *pro, const char *chip, const char */*comp*/, uint16_t vid, uint16_t pid, uint16_t /*bcdlow*/, uint16_t /*bcdhigh*/, void */*p*/) { printf("\t %s\t %s\t 0x%04X\t0x%04X\n", chip, pro, vid, pid); char sub[128]; snprintf(sub, 128, "IgnoreHWSerNum%04x%04x", vid, pid); const BYTE value = 1; LSTATUS ret = RegSetKeyValueA(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\UsbFlags", sub, REG_BINARY, &value, 1); if(ret == ERROR_SUCCESS) return 0; printf("Set key failure, try run as administrator permission\n"); return -1; } #endif int set_ignore_serial_number() { #ifndef WIN32 printf("Only windows system need set ignore serial number registry"); return -1; #else printf("Set window registry to ignore usb hardware serial number for known uuu device:\n"); return uuu_for_each_cfg(ignore_serial_number, NULL); #endif } int main(int argc, char **argv) { if (auto_complete(argc, argv) == 0) return 0; if (argc >= 2) { string s = argv[1]; if(s == "-udev") { print_udev(); return 0; } if (s == "-bshow") { if (2 == argc || g_BuildScripts.find(argv[2]) == g_BuildScripts.end()) { fprintf(stderr, "Error, must be have script name: "); g_BuildScripts.ShowCmds(stderr); fprintf(stderr,"\n"); return -1; } else { string str = g_BuildScripts[argv[2]].m_text; while (str.size() > 0 && (str[0] == '\n' || str[0] == ' ')) str = str.erase(0,1); printf("%s", str.c_str()); return 0; } } } AutoCursor a; print_version(); if (!enable_vt_mode()) { cout << "Your console don't support VT mode, fail back to verbose mode" << endl; g_verbose = 1; } if (argc == 1) { print_help(); return 0; } int deamon = 0; int shell = 0; string filename; string cmd; int ret; int dryrun = 0; string cmd_script; for (int i = 1; i < argc; i++) { string s = argv[i]; if (!s.empty() && s[0] == '-') { if (s == "-d") { deamon = 1; uuu_set_small_mem(0); } else if (s == "-dm") { uuu_set_small_mem(0); } else if (s == "-s") { shell = 1; g_verbose = 1; } else if (s == "-v") { g_verbose = 1; } else if (s == "-V") { g_verbose = 1; uuu_set_debug_level(2); }else if (s == "-dry") { dryrun = 1; g_verbose = 1; } else if (s == "-h") { print_help(false); return 0; } else if (s == "-H") { print_help(true); return 0; } else if (s == "-m") { i++; uuu_add_usbpath_filter(argv[i]); g_usb_path_filter.push_back(argv[i]); } else if (s == "-ms") { i++; uuu_add_usbserial_no_filter(argv[i]); g_usb_serial_no_filter.push_back(argv[i]); } else if (s == "-t") { i++; uuu_set_wait_timeout(atoll(argv[i])); } else if (s == "-T") { i++; uuu_set_wait_next_timeout(atoll(argv[i])); } else if (s == "-pp") { i++; uuu_set_poll_period(atoll(argv[i])); } else if (s == "-lsusb") { print_lsusb(); return 0; } else if (s == "-IgSerNum") { return set_ignore_serial_number(); } else if (s == "-bmap") { g_bmap_mode = bmap_mode::Force; } else if (s == "-no-bmap") { g_bmap_mode = bmap_mode::Ignore; } else if (s == "-e") { #ifndef WIN32 #define _putenv putenv #endif i++; if (_putenv(argv[i])) { printf("error, failed to set '%s', environment parameter must have the form key=value\n", argv[i]); return -1; } } else if (s == "-b" || s == "-brun") { if (i + 1 == argc) { printf("error, must be have script name: "); g_BuildScripts.ShowCmds(); printf("\n"); return -1; } vector args; for (int j = i + 2; j < argc; j++) { string s = argv[j]; if (s.find(' ') != string::npos) { s.insert(s.begin(), '"'); s.insert(s.end(), '"'); } args.push_back(s); } // if script name is not build-in, try to look for a file if (g_BuildScripts.find(argv[i + 1]) == g_BuildScripts.end()) { const string tmpCmdFileName{argv[i + 1]}; std::ifstream t(tmpCmdFileName); std::string fileContents((std::istreambuf_iterator(t)), std::istreambuf_iterator()); if (fileContents.empty()) { printf("%s is not built-in script or fail load external script file", tmpCmdFileName.c_str()); return -1; } BuiltInScriptRawData tmpCmd{ tmpCmdFileName.c_str(), fileContents.c_str(), "Script loaded from file" }; g_BuildScripts.emplace(tmpCmdFileName, &tmpCmd); cmd_script = g_BuildScripts[tmpCmdFileName].replace_script_args(args); } else { cmd_script = g_BuildScripts[argv[i + 1]].replace_script_args(args); } break; } else { cout << "Unknown option: " << s.c_str(); return -1; } }else if (!s.empty() && s[s.size() - 1] == ':') { for (int j = i; j < argc; j++) { s = argv[j]; if (s.find(' ') != string::npos && s[s.size() - 1] != ':') { s.insert(s.begin(), '"'); s.insert(s.end(), '"'); } cmd.append(s); if(j != (argc -1)) /* Don't add space at last arg */ cmd.append(" "); } break; } else { filename = s; break; } } signal(SIGINT, ctrl_c_handle); uuu_set_askpasswd(ask_passwd); if (deamon && shell) { printf("Error: -d -s Can't apply at the same time\n"); return -1; } if (deamon && dryrun) { printf("Error: -d -dry Can't apply at the same time\n"); return -1; } if (shell && dryrun) { printf("Error: -dry -s Can't apply at the same time\n"); return -1; } if (g_verbose) { printf("%sBuild in config:%s\n", g_vt_boldwhite, g_vt_default); printf("\tPctl\t Chip\t\t Vid\t Pid\t BcdVersion\t Serial_No\n"); printf("\t==================================================\n"); uuu_for_each_cfg(print_cfg, NULL); if (!cmd_script.empty()) printf("\n%sRun built-in script:%s\n %s\n\n", g_vt_boldwhite, g_vt_default, cmd_script.c_str()); if (!shell) cout << "Wait for Known USB Device Appear..."; print_usb_filter(); printf("\n"); } else { cout << "Wait for Known USB Device Appear..."; print_usb_filter(); cout << "\r"; cout << "\x1b[?25l"; cout.flush(); } map nt_session; uuu_register_notify_callback(progress, &nt_session); if (!cmd.empty()) { ret = uuu_run_cmd(cmd.c_str(), dryrun); for (size_t i = 0; i < g_map_path_nt.size()+3; i++) printf("\n"); if(ret) printf("\nError: %s\n", uuu_get_last_err_string()); else printf("Okay\n"); runshell(shell); return ret; } if (!cmd_script.empty()) ret = uuu_run_cmd_script(cmd_script.c_str(), dryrun); else ret = uuu_auto_detect_file(filename.c_str()); if (ret) { ret = runshell(shell); if(ret) cout << g_vt_red << "\nError: " << g_vt_default << uuu_get_last_err_string(); return ret; } if (uuu_wait_uuu_finish(deamon, dryrun)) { cout << g_vt_red << "\nError: " << g_vt_default << uuu_get_last_err_string(); return -1; } runshell(shell); /*Wait for the other thread exit, after send out CMD_DONE*/ std::this_thread::sleep_for(std::chrono::milliseconds(100)); if(!g_verbose) printf("\n\n\n"); return g_overall_status; } mfgtools-uuu_1.5.182/uuu/uuu.lst000066400000000000000000000112341462141313700166030ustar00rootroot00000000000000uuu_version 1.0.0 # # uuu(universal update utility) command list file # First line must contain the minimum required uuu host version # --------------------------------------------------------------------- # Command Format PROTOCOL COMMAND ARG # PROTOCOL # ALL protocol supported common commands # done #last command for whole flow # delay # delay ms # sh\shell #Run shell command, such as wget to file from network # < #use shell command's output as uuu command # this command generally used to burn some sequence number, such as production id and mac address # for example: # FB:< echo ucmd print # # CFG: Config protocol of specific usb device vid/pid # SDPS|SDP|FB\Fastboot|FBK -chip -pid -vid [-bcdversion ] # # SDPS: Stream download after MX8QXPB0 # boot -f [-offset 0x0000] # # SDP: iMX6/iMX7 HID download protocol. # dcd -f # write -f [-addr 0x000000] [-ivt 0] # jump -f [-ivt 0] # boot -f [-nojump] # rdmem -addr -format <8|16|32> # wrmem -addr -format <8|16|32> -value # # FB[-t timeout]:\Fastboot: android fastboot protocol (timeout in ms). # getvar # ucmd # acmd # flash [-raw2sparse [{-no-bmap|-bmap # download -f # crc -f [-format "mmc read $loadaddr"] [-blksz 512] [-each 0x4000000] # [-seek 0] [-skip 0] [-nostop] # each CRC size each loop # seek skip bytes from storage # skip skip bytes from -f # nostop continue check even if found mismatch # write -f [-format "mmc write $loadaddr"] [-blksz 512] [-each 0x4000000] # [-seek 0] [-skip 0] [-nostop] # each write size each loop # seek skip bytes from storage # skip skip bytes from -f # nostop continue write even if error occurs # # # FBK: community kernel with fastboot protocol (NOT compatible with fastboot tools). # ucmd and wait for command finish # acmd don't wait for command finish # sync wait for acmd process to finish # ucp copy file from/to target # T: means target board file # T:- means copy data to target's stdio pipe # copy image T:/root/image ;download image to path /root/image # copy T:/root/image image ;upload /root/image to file image # Example on how to transfer big files: # acmd tar - ; run tar background and get data from stdio # ucp rootfs.tar.gz T:- ; send to target stdio pipe # sync ; wait for tar process to exit # # For example: # SDPS: boot -f # SDP: boot -f # CFG: SDP: -chip imx6ull -pid 0x1234 -vid 0x5678 # # SDP: boot -f u-boot-imx7dsabresd_sd.imx -nojump # SDP: write -f zImage -addr 0x80800000 # SDP: write -f zImage-imx7d-sdb.dtb -addr 0x83000000 # SDP: write -f fsl-image-mfgtool-initramfs-imx_mfgtools.cpio.gz.u-boot -addr 0x83800000 # SDP: jump -f u-boot-dtb.imx -ivt CFG: FB: -vid 0x18D1 -pid 0x0D02 SDP: boot -f u-boot-dtb.imx FB: getvar version FB: ucmd setenv fastboot_buffer 0x80800000 FB: download -f zImage FB: ucmd setenv fastboot_buffer 0x83000000 FB: download -f zImage-imx7d-sdb.dtb FB: ucmd bootz 0x80800000 - 0x83000000 mfgtools-uuu_1.5.182/webusb/000077500000000000000000000000001462141313700157115ustar00rootroot00000000000000mfgtools-uuu_1.5.182/webusb/README.md000066400000000000000000000064371462141313700172020ustar00rootroot00000000000000# Getting Started with Create React App This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). ## Available Scripts In the project directory, you can run: ### `npm start` Runs the app in the development mode.\ Open [http://localhost:3000](http://localhost:3000) to view it in your browser. The page will reload when you make changes.\ You may also see any lint errors in the console. ### `npm test` Launches the test runner in the interactive watch mode.\ See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. ### `npm run build` Builds the app for production to the `build` folder.\ It correctly bundles React in production mode and optimizes the build for the best performance. The build is minified and the filenames include the hashes.\ Your app is ready to be deployed! See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. ### `npm run eject` **Note: this is a one-way operation. Once you `eject`, you can't go back!** If you aren't satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own. You don't have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it. ## Learn More You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). To learn React, check out the [React documentation](https://reactjs.org/). ### Code Splitting This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting) ### Analyzing the Bundle Size This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size) ### Making a Progressive Web App This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app) ### Advanced Configuration This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration) ### Deployment This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment) ### `npm run build` fails to minify This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify) mfgtools-uuu_1.5.182/webusb/package.json000066400000000000000000000016571462141313700202100ustar00rootroot00000000000000{ "name": "client", "version": "0.1.0", "private": true, "dependencies": { "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", "eslint": "^8.48.0", "react": "^18.2.0", "react-dom": "^18.2.0", "react-scripts": "^5.0.1", "web-vitals": "^2.1.4", "@types/w3c-web-serial": "^1.0.3", "web-serial-polyfill": "^1.0.14", "xterm": "^5.2.1", "xterm-addon-fit": "^0.7.0", "xterm-addon-web-links": "^0.8.0" }, "scripts": { "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test", "eject": "react-scripts eject" }, "browserslist": { "production": [ ">0.2%", "not dead", "not op_mini all" ], "development": [ "last 1 chrome version", "last 1 firefox version", "last 1 safari version" ] }, "homepage": "/webuuu/" } mfgtools-uuu_1.5.182/webusb/public/000077500000000000000000000000001462141313700171675ustar00rootroot00000000000000mfgtools-uuu_1.5.182/webusb/public/index.html000066400000000000000000000033131462141313700211640ustar00rootroot00000000000000 React App
mfgtools-uuu_1.5.182/webusb/public/manifest.json000066400000000000000000000003031462141313700216640ustar00rootroot00000000000000{ "short_name": "React App", "name": "Create React App Sample", "icons": [ ], "start_url": ".", "display": "standalone", "theme_color": "#000000", "background_color": "#ffffff" } mfgtools-uuu_1.5.182/webusb/public/robots.txt000066400000000000000000000001031462141313700212320ustar00rootroot00000000000000# https://www.robotstxt.org/robotstxt.html User-agent: * Disallow: mfgtools-uuu_1.5.182/webusb/src/000077500000000000000000000000001462141313700165005ustar00rootroot00000000000000mfgtools-uuu_1.5.182/webusb/src/App.css000066400000000000000000000023541462141313700177360ustar00rootroot00000000000000/* SplitLayout.css */ .split-layout { display: flex; /* Use Flexbox */ justify-content: space-between; /* Space between the columns */ align-items: stretch; /* Stretch columns to match height */ } .left-column, .right-column { flex: 1; /* Equal width for both columns */ padding: 20px; /* Add padding to the columns */ } .u-flex { display: flex; } .u-row { flex-direction: row; padding-bottom: 1rem; } .u-column { flex-direction: column; } .u-row-reverse { flex-direction: row-reverse; } .u-space-between { justify-content: space-between; } .u-center { justify-content: center; } .u-inline-block { display: inline-block; } .link-container{ display: inline-block; width : 8rem; } .popup-loc { position: relative; } .popup-container { background-color: white; position: absolute; display: inline-block; border: thin black solid; border-radius: 4px; padding: 1rem; width: 24rem; } .popup-container li { padding-bottom: 1rem; } .popup-button { width:2rem } .input { display: none; } .custom-file-upload { border: thin black solid; border-radius: 4px; cursor: pointer; } .file-name { display: inline-block; width: 32rem; } mfgtools-uuu_1.5.182/webusb/src/App.js000066400000000000000000000067231462141313700175660ustar00rootroot00000000000000import React, { useState } from 'react'; import Combined from "./components/Combined"; import usePopup from "./logic/usePopup"; import UartTerminal from './terminal'; import 'xterm/css/xterm.css'; import './App.css' const App = () => { const [bootFile, setBootFile] = useState(); const [flashFile, setFlashFile] = useState(); const [term, setTerm] = useState(); const [port, setPort] = useState(); const [{ showPopup, closePopup, show, error }] = usePopup({ bootFile, flashFile }); const pipetoterm = async (port) => { await port.open({ baudRate: 115200 }); const reader = port.readable.getReader(); const readfun = (port, reader) => { reader.read().then(({ value, done }) => { if (!done) { console.log(value); term.write(value); return readfun(port, reader); } else { console.log("End of stream"); } }) }; readfun(port, reader); } return (
Demo for webuuu, Only Support 8QXP/8QM board, NO SPL version
This is early development version. Any issue or idea: report to https://github.com/nxp-imx/mfgtools/issues

Before use this tools, please add below udev rule at linux machine
KERNEL=="hidraw*", ATTRS{'{idVendor}'}=="1fc9", MODE="0666"
SUBSYSTEM=="usb", ATTRS{'{idVendor}'}=="1fc9", ATTRS{'{idProduct}'}=="0152", MODE="0664", TAG+="uaccess"

bootloader: {bootFile ? bootFile.name : ""}
wic image: {flashFile ? flashFile.name : ""}
{error}
{ setTerm(term); term.onData((data) => { console.log(data); const encoder = new TextEncoder(); const writer = window.uartport.writable.getWriter(); writer.write(encoder.encode(data)); writer.releaseLock(); }); }} />
); } export default App; mfgtools-uuu_1.5.182/webusb/src/App.test.js000066400000000000000000000003661462141313700205410ustar00rootroot00000000000000import { render, screen } from '@testing-library/react'; import App from './App'; test('renders learn react link', () => { render(); const linkElement = screen.getByText(/learn react/i); expect(linkElement).toBeInTheDocument(); }); mfgtools-uuu_1.5.182/webusb/src/components/000077500000000000000000000000001462141313700206655ustar00rootroot00000000000000mfgtools-uuu_1.5.182/webusb/src/components/Combined.css000066400000000000000000000005251462141313700231210ustar00rootroot00000000000000.checkbox-container { width: 1rem; } .checkbox { margin:0; padding-right: 1rem; } .boot-image { width:100%; height:auto; border-radius: 50%; } .Popup-list { margin:0; padding-left: 1rem; list-style-position: outside; list-style-type: none; } .image-container { width: 8rem; height: 8rem; }mfgtools-uuu_1.5.182/webusb/src/components/Combined.js000066400000000000000000000055551462141313700227550ustar00rootroot00000000000000import {useEffect, useState} from 'react'; import ProgressBar from './ProgressBar'; import useHIDBoot from '../logic/useHIDBoot'; import useUSBFlash from '../logic/useUSBFlash' import imgSrc from '../images/imx8qxp_mek_bootmode.png' import "./Combined.css" const Combined = ({bootFile, flashFile}) => { // const [imgUrl, setImgUrl] = useState(); const [{ requestHIDDevice, HIDdevice, bootProgress, bootTotal }] = useHIDBoot(bootFile); const [{ requestUSBDevice, USBDevice, flashProgress, flashTotal}] = useUSBFlash(flashFile); // useEffect(() => { // const dothis = async()=>{ // const response = await fetch("mode"); // const blob = await response.blob(); // setImgUrl(URL.createObjectURL(blob)); // } // dothis(); // }, []) return(
  • 1. Switch Boot Mode to "SERIAL"
    {imgSrc? : ""}
  • {bootProgress&&(bootProgress===bootTotal)?

    :""}
    2. {bootProgress? `${bootProgress} bytes out of ${bootTotal} downloaded`: ""}
    {bootProgress&&(bootProgress===bootTotal)?`connected: ${HIDdevice.productName}`: (bootProgress?`Pairing`:"")}
  • {USBDevice?

    :""}
    3.
    {USBDevice? `connected: ${USBDevice.productName}`: ""}
) } export default Combinedmfgtools-uuu_1.5.182/webusb/src/components/ProgressBar.js000066400000000000000000000016701462141313700234600ustar00rootroot00000000000000import {useEffect, useState} from 'react'; const ProgressBar = (props) => { const [soFar, setSoFar] = useState(); const [total, setTotal] = useState(); const Parentdiv = { height: 20, width: '100%', backgroundColor: 'whitesmoke', } const Childdiv = { height: '100%', width: `${total? soFar/total*100: 0}%`, backgroundColor: 'green', textAlign: 'right' } useEffect(()=> { setTotal(props.total); setSoFar(props.soFar); }, [props]) return(
{ soFar&&total? (soFar===total? "Done": {soFar} out of {total} bytes downloaded):"" }
) } export default ProgressBarmfgtools-uuu_1.5.182/webusb/src/helper/000077500000000000000000000000001462141313700177575ustar00rootroot00000000000000mfgtools-uuu_1.5.182/webusb/src/helper/functions.js000066400000000000000000000051751462141313700223350ustar00rootroot00000000000000/* * Copyright 2023 NXP. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * Neither the name of the NXP Semiconductor nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ /* UTILITY */ /* * hex: Hex number to convert * size: Int number of bytes * Returns: an UInt8Array; 2 digits in hex = 1 byte */ function hex_to_ab(hex, sz) { let buffer = new Array(sz).fill(0) for (let i=0; i> 8; } return buffer; } /* * str: String * Returns: a Uint8Array */ function str_to_arr(str) { const encoder = new TextEncoder(); return encoder.encode(str); } /* * ab: ArrayBuffer * Returns a string decoding message in array buffer */ function ab_to_str(ab) { const decoder = new TextDecoder(); return decoder.decode(ab); } /* * obj: Object with key (property) value (hex value) pairs * obj_sz: Object with key (property) value (size of prop, in bytes) pairs * sz: size of complete array buffer, in bytes * Returns Uint8Array with padded values */ function obj_to_arr(obj, obj_sz, sz) { let ab = new Uint8Array(sz); let offset = 0; for (const prop in obj) { let prop_arr = hex_to_ab(obj[prop], obj_sz[prop]); ab.set(prop_arr, offset); offset += obj_sz[prop]; } return ab; } export {hex_to_ab, str_to_arr, ab_to_str, obj_to_arr};mfgtools-uuu_1.5.182/webusb/src/helper/sparse.js000066400000000000000000000103401462141313700216100ustar00rootroot00000000000000/* * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {obj_to_arr} from './functions'; export const SPARSE_HEADER_MAGIC = 0xed26ff3a export const CHUNK_TYPE_RAW = 0xCAC1 export const CHUNK_TYPE_FILL = 0xCAC2 export const CHUNK_TYPE_DONT_CARE = 0xCAC3 export const CHUNK_TYPE_CRC32 = 0xCAC4 export const BLK_SZ = 0x1000; // bytes per block export const CHUNK_SZ = 0x1000; // blocks per full chunk const CHUNK_HEADER_SZ = 12; const SPARSE_HEADER_SZ = 28; export const sparse_header = { // in bytes magic : 4, /* 0xed26ff3a */ major_version : 2, /* (0x1) - reject images with higher major versions */ minor_version : 2, /* (0x0) - allow images with higher minor versions */ file_hdr_sz : 2, /* 28 bytes for first revision of the file format */ chunk_hdr_sz : 2, /* 12 bytes for first revision of the file format */ blk_sz : 4, /* block size in bytes, must be a multiple of 4 (4096) */ total_blks : 4, /* total blocks in the non-sparse output image */ // CHANGE total_chunks : 4, /* total chunks in the sparse input image */ // CHANGE image_checksum : 4, /* CRC32 checksum of the original data, counting "don't care" */ // CHANGE } export const chunk_header = { // in bytes chunk_type : 2, /* 0xCAC1 -> raw; 0xCAC2 -> fill; 0xCAC3 -> don't care */ reserved1 : 2, chunk_sz : 4, /* in blocks in output image */ total_sz : 4, /* in bytes of chunk input file including chunk header and data */ } export const PACKET_SZ = 0x10000; export const DATA_SZ = CHUNK_SZ * BLK_SZ; // in bytes export function build_sparse_header(raw_data_bytelength, i) { let sparse_format = { magic : SPARSE_HEADER_MAGIC, /* 0xed26ff3a */ major_version : 0x1, /* (0x1) - reject images with higher major versions */ minor_version : 0x0, /* (0x0) - allow images with higher minor versions */ file_hdr_sz : 0x1c, /* 28 bytes for first revision of the file format */ chunk_hdr_sz : 0xc, /* 12 bytes for first revision of the file format */ blk_sz : 0x1000, /* block size in bytes, must be a multiple of 4 (4096) */ total_blks : 0x0, /* total blocks in the non-sparse output image */ // CHANGE total_chunks : 0x2, /* total chunks in the sparse input image */ //don't care and raw_data image_checksum : 0x0, /* CRC32 checksum of the original data, counting "don't care" */ } //first chunk is don't care: we don't care about the first 4096*i blocks //second chunk is raw_data: there are 4096 blocks in a 16mb chunk sparse_format.total_blks = CHUNK_SZ * i + raw_data_bytelength/BLK_SZ; return obj_to_arr(sparse_format, sparse_header, SPARSE_HEADER_SZ) } export function build_chunk_header (chunk_type, raw_data_bytelength, i) { let chunk_format = { chunk_type : chunk_type, /* 0xCAC1 -> raw; 0xCAC2 -> fill; 0xCAC3 -> don't care */ reserved1 : 1, chunk_sz : 0, /* in blocks in output image */ total_sz : 0, /* in bytes of chunk input file including chunk header and data */ } if (chunk_type === CHUNK_TYPE_DONT_CARE) { chunk_format.chunk_sz = CHUNK_SZ * i; // don't care chunk_format.total_sz = CHUNK_SZ*BLK_SZ * i + CHUNK_HEADER_SZ; // bytes raw_data + header } else if (chunk_type === CHUNK_TYPE_RAW) { // raw_data chunk_format.chunk_sz = Math.ceil(raw_data_bytelength/BLK_SZ); chunk_format.total_sz = raw_data_bytelength + CHUNK_HEADER_SZ; console.log(chunk_format) } return obj_to_arr(chunk_format, chunk_header, CHUNK_HEADER_SZ); }mfgtools-uuu_1.5.182/webusb/src/images/000077500000000000000000000000001462141313700177455ustar00rootroot00000000000000mfgtools-uuu_1.5.182/webusb/src/images/imx8qxp_mek_bootmode.png000066400000000000000000004407721462141313700246330ustar00rootroot00000000000000JFIFHHXExifMM*i&8Photoshop 3.08BIM8BIM%ُ B~(ICC_PROFILEapplmntrRGB XYZ acspAPPLAPPL-appl8GmOz/ desc0cprt,Pwtpt|rXYZgXYZbXYZrTRC chad,bTRC gTRC mluc enUSDisplay P3mluc enUS4Copyright Apple Inc., 2022XYZ ,XYZ =XYZ J7 XYZ (8 ȹparaff Y [sf32 B&n" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzC C  * ?VXgw0o*䞀 ??/|!em It:;׉[nr#W#CrTuq `U)7c㗃<5/|u/rByg&>pW_OuEo-S]\*wNS|?Eed.$SJk~5dž-v  (gg-syL"-1e<>7|φC\7<m w˿>b&S/^qjIDz9.CKsVݭ<>95q"] Yr2=$bY[|B, قOvUq_${nGAXԃ>5%B#͊>fv۝^4EjwI8dyK-4?e.G!qz~< l#b[>-tbO\+^ 4m$'v០ e64mV7;+W3koojg!!+%8zbIfۻ;LukjG劓SJ/3"2V ~Ҟkjt|[w}_~xObPoKń _?MIU8BO,)k@Imo xȭ}J(?jV^5=mV༎}zWv$ 8ھ?n_?o+[+ GA_JРŸ_ZS{TV['_e4mA!r:?Oߍ7_xCl\LzB ُ5>!OroJesֶQK;0(b?kgeE);4忻Y$;]V 5_7}gw񇉤,T>^/$hk1E8,}X4xC|1uO$Iݷ^_s8:#0dUpr,7s3ҿn<+ q&Xզ X޹o !ѮGASNVyx,;&z|cӼiDKK+ %{c~@>1?~ 0ѮN܀ێ6[!x}tr\XӠ~$~_K-snKa1ОKsG c7?kZbm4e~_o6s;S?]|zn=+ؙrOg)r6[Чп Z]ŋt#g_\hjelc,8O~$/u_?26+3^eC|zKokWI$VI[MBQ#mYn o |(r-`q) zұ!h˭ēX C ha/? / |#ɏM *h mevTJA_]#_6[c-%ː~ڲuc9q.?)6K>qLkDwbWm7~7_^)8n 4\fҴxp r\>|MNbȼmV5ɳ=6s?T^.=p+>_?ٌCYFRUQzcvKnA^?9|#$.@=q_>)YC\y<_)i-ϔQMUǧgq9")oxU՞@d!x&01XE~Vt-~.ۼ㠯Xx|Kg+|Vw@DO,AVUC}b_#~ֺ>SPU!?ϴr!io]{b1}' LR}aj 7mՔb; Z^FU?7~bdӳ?[pԬq:ߊkgÑ^m^*>~߲?dֺ>m ׈euPYQOPx5xu-eUD#V3+ӱ`KWk˙P~coimNKdUnʑs޲HZ20~j'ɿᯍPTfp?uφ)֭$·8=|#/?PIqp̛yW|rtdxYcK3M 36??ĺ'OYHpMhH7j[?m?\ s~ |_EcSc='2\ch)Z~z^:\׻RUƸ];o#i [?.T~_Uogqڿ8Fk}j bM('L G}Ē3[ V3]ܒ;TD+d~Y_l:j_u.u'W-Vx¿cI`XWw=FM|c0'ß'LUm/q]T>Æ5=O[%. _gfAzt=oI/:ͣHV4bqیp)zZG)ɬE#vbsz^ݱԱj4B:ʹφ*'ZMk9VN@b[e5'>4Ң^d>Ѳ7n32Ɵa}0b^+F[p{>W/nU s\v~wҫ!rҐ Y=Y1x4lEi]*:qZ~ѐΡ0Ag [ARo+ojæ]߹i 'Үu܌Hu?f߆vL?B|@ rnO_ꗈb2QaW'Vм_AW|dg<;O&^C0Qaǭ˕k9%s' akbq</j'C?g Aq吲u U _jHAq_ϷÿigCvtN̰ ~lt~Uд=5N =/,ek<{ ZI9MǗЌ|lpc*d0KUGB:VGn|r*倖aʠzpxVIwKU F{;v.k_o«/ 03Uam{H/4+n+e>`ֶg7ſrBۯˬmۓz?~~M^6 7jkC=W]ǶkR^3!k%ږzG~->@m*:]-piĎ'=OU׆`Křr_Nk7ğ muj *K9ϵ~b~ƶ{2V[m濾M/ x656Eo®qpODtG,]>t~8C/\IoM6h|( \)=xSfT<Nk>?') ܌ǥ-.>ZNF:8y^-&|^o|Ǚi ~#^xdM{dUP6ܡpIzq_g᮳3i4U6P222kK +"3P~MW(ZG+^=ZgdiP>{ _~/E"UNTGDxf*4MeFq1To p+!X 9Z%=U~W/;D e0l#x|U('?_}=6zb%1_ӟ/&Cm%ׄgT'?Co#⮁q`E$TzT$O %k8Q<[MQkR9HqԎ~c: 晪ͦH>kf*ៃ/hz+ it^+<־<ն|eӜdכPӇs+߀o~%|L>iO徥2w¿L? 4Kkv'nO_O쁭XhVj6G&y>q__Ǟ/ݚyT"  ކX^J5&g=gM=);)pku/gKH'C0WO k7/m YLD1`˃ _B4}/=蔼0?§ʖǥ`)Nѳ? |7 ҹorH8UW ;gohpia*Nb$ï&}iJCsqy_ՆѤpT 0nGZdd9}')sf &@ms~K|iq_ bM캤j"IQ]eW(N9\f<\d #K i?~CL.C^;⏌ֿmZmk;E@݌=+dxcǗZ 8 ~bp11 F%k٣^/㫫KFlOA_BIE[?%+׉NR/2&>ƿk[,#ڹkEACƕE8l3iN 셷O|0\wMwaj,? Wݿ&NJ.pXǵ( VkC*ewe2=~9?*` ]OƏ7H㫯jf|ctW+mh!Y:d`uϽE]34VsNꙎ<[_M>5$oiͭ^~߃o>>{&%H*w)9c&GYe*)E6L7+Ȓg;Gz5[OC")ua*ʛN0W_ԟI|x'[K}i#qBx݃'1LjвlbH]1VŠ'V&}6}UWO`8y^>TW^kM;Dbƥ=~?, |uf[۹~Dn3Ꮕn]r{S~p8WaJ6c_pQR+&>g6ũ^9[YwMZ?grѾ߻ooԛ@[hg'}=+r};UR;@*6z Z< *I#{ڶ-Nh#\s1Gc6w_!1d}r+n\|$ϟʿ&Fof&o6Ux;\3_L9$SqMqpu<ڇdx;q\ +dQ#68ҽwG_?cj0W#7>PF%.],?JԭgI0v5d~Z?cÖ1o8|-@=~NM=qڟ3z'+֧*:U+ăJԍV.'Ld}Fj #4*VEg8ҳ. -maUAۃ#|}Tg z|oecvFQڿضEE6*mc+qi_,2o'Vh~Զ (ޖQ~U\ⳡQ|jҀplHζ?,3?ſ|%T~$ц *3JgCYJ˔;y_hՇWĿ;O ʎ0՜]SKc? >Z~ ƷzF[y"SGJZVE`#eV9RٴLȫR_I={#2Q E+4uȘ~Kaf]w0w\_Ȓ(R0o{-BI̛EZ-;OYcɌ NMsδ"e8N3iai|Êִ٭wDJ:Jz\>wL|O4Hy>PĻƊ#Ԑ־F~߈]Ss\Sm^e'2q^=yn+_nS¾$׼ +_VFӅcVgU4x7 3|-.ax!ر/ӌW/AsU--^)>Ik2lo!JCcc+UvGV~ܿڮuAc,i?iψJY01z!Fh;Uen;Oʴݟ-[~(Eqz%c5'iߌ-nh"(Fv9QOmϧtsRUv?S< ^mktwQ_o?58RXVL OjR yKcuy݋.Wq#8af_ ץnmQ||յ+QZ,0 +ψOYw{rL1|@-?n܌lBA#rz>ճ n8.fi6MY>!7[k,~e%j^| }@ +ezw,Hӿ<qg ~zD"k,#eSn}qoW޻xf8W' cH(ꗟk+IU^NqC_NDvaI[qx'׃k~Thw->-0@9}ASSyzSg>յφ"̱ӕ*{}?.j\[po'n| 0A' 6 S)j:hڛU?,gg[uU\qO|Q؉u;Dx%Rg|K޲JhP՝;~U3ϛhjtFeL '>O(hI_7 vy=+؉>~|1~4. ;ate9Ojμ4Pc oKx mdRWE'ɐ E}vm7dp7,\HK{n#|GiRa\?9`M3n2n,o-I:x{tS4ߌ Q!ތ: >2ּ?)?nIf,,?W_1/ xHSPy*8_SZn{ zQ_G#_-xZ5.zmh~GQ׀I =qWKM,qC+ N(Oɳ~oN!4C擮*ݦlPdʨ}̆ ;LW[\*"fB{C$#|?mҞZۣW8k?oڏŐ=r:19>QvIkqrcy=+yF܊}K[ֵ oY[YndnCIui8ˇ Ƽ[ԓM[܇+s VOd r[]Y+(&r2׆Y}о uK7:G19_.<|EAg0Z*}~K3fo|{2F– rױk3|Ý53m:w'sǸ_ׯ59.Ò_|@iń>sU8㎕ұPUIs.!̥R^4߿-mX1E~YXK]6L= wud @۠ݯnD3Cgk wV>*eG񝫬BAVh%W?'IHI "I2Pzcj>S>N j;~daj/>VD? Iw~8tp/pXGq7[q{SQԂҿBxp=͟PҜyNҟ}M_ zzV!5 iF"A@'gA޿Aj2ޠhGJɽ5V5ݎ*=[\/V?/m.UiŀSvWjΩ:߰Lp?~B?&-q(8\-F cr,#se-[\6le?J'>[_ZU$mWE!4 Jb[96% /OO#/*ys*:C[U4`+0ӏʅxz^,~WC|?LYv?VT:]T;ұɤn@Y#@=| 8i1\?h>:U?`/s]F;bh_,D%r5:8N|l>+´?h?>a{{W-ǂoME#FCهdstrxi|uoTe, }Wk3˨ՐHv2u_=+{Sf|_x]yn1|Wۥ|zQb墙YT\<+2p/˃>V|W|˨E䪠$ש@!|R.|G2mTGUWM}[V{+O$ g^g\-ʠA_П߇ 1Z[VEʐWz#N[/~ 7-ˇC@~U{;_"fNr[4_qb+*_odǭr,Nͨ_|;܃-mMW6:qҾu̵n0z//'OzpjAdyOlcڡ_%_윅Tj 11^*RKQ}AOKÌ6 X.T`+6(.I[l5 YtX`QNj~{|?mp6i$.Tۊ?' G 1Q* ]um?|Lݔ!^߉75->?qǮ@⿱pPηsh1ğ7씫它jv1t֜WHANwOC/X$2$ǵhF>]OO+ܲfӥZnӧy;:OO.\(IʮnI-\'#RˎR}L 8Jqf 'yDII^BҪwp;$2ZL0q:c+2x&xeNG׎+_/VLcyGaς^?;} F{:p+R>x~!/"$2AWg>!ӾWR\j<1A3? / dWuě{Ǔ>ƹt ":JhzeoxWWCu:ڣ/RNI>NT_yjZQM.PDug1~"%)>VxkMXo^(_u剃qPá~iZ?Gӣ❣]S%xTOPTq]|EH?hwj|CԜZ-"bn>>> GO |.Km qfY_'/w4;$ +wm8|c#\8S:Fm |Zm|E~bv6XG9'nW;Ž29ӏ  0uq8(վ5R}_BޞpћI;b3wo*5_ ik˫k9sC1=scnmPڳdui.RYOfby5/%O&71q37 2WׁƝ/EfF2p|?^nc+%)>Ѽ3m%M)۰A?^LBJ;Jch[5=J;+@>7_J|G5Z1 zWOثg:a[W; ms;=Z3cӡ" ZZ>ft@dQOڿH r'AI`$QAod72Ÿ0'_V]LJ>k0*5cj~1y@g8ڛŻ.tE#_jy=2? .7^6FF:~Ys?e*5?Xm6n3U-Wf~E|a$2--,Oc_+^x+^:H~_ ,i"iyrB;Wx$3k{e [I;ۃYxlMZkR?U:d/gj#s(e1 `//VQ]b//4?6ރ?J#ѧbVJ'?$ŷ3ls qڿy~>|?m. -/O@;noRǹ(|:w ]2(l1X=kQφ_4.-Ju<8ӧi롞/6^Ϫ.O2h;{e-,K_}j?n><=$Fo?hmF{kVGsu{jQMǩIYq{TvBj9&2"1U땒D3Ҩ3rJU\t}5k~5ABះZK{x8lv οP??xdF*ᢺ?Q8u/??mo'm t`Nf_,P1?!A+*iPd *qK79 9)2"dCaͪ(Q=_Xô3kʥ6RַdZ >vE /S|Uk[GN2)ǰo (AߎԓHK+7gc࢟~64O$\zW~"i~unjf ok_OڛIؕ 2q_Է톞_|y~jgy\>,?-HB\{?,/n_bFx!P5ĝ)m*p3Q|v+q4lUG /%g{y$3,iǡW9y6nلSG<`m#-o b3*Dshg:,SC"$vV&!IT_ˏؘz)Jt[ W Ɛ B,5V9eˌU|߁y+i1ۊmDҨgt|a[=ೞ sesXWR;9 _ΜdS<3SF0:NF(qV%k%eS2t q~?T8G9ϯ{oѣQ֋W~eܸaeyRWGYZ8XԆh+m¸1i|7ȚMN+{%Xtv/jyc'#޿<a#X.&vR[htUH?3RsH!xW^ t{+[K 8**jBWѥy[l$| ~nv6C8].xwu뛁wz:HܬNJ~ڿ|'qy SW|NѡuM.@4Q= #sچ>DӪW%? n|J-_;&(NGZ:~6+?k?`V7m`ܸH\}0z ܾH=6o4EX(;N:_s_n[XŶoĶ$ w5g)үK(p8)OT}Q ?\ZOjp 5h1~"xy]%wmGDcr}寉&S B[#ۊUXB5usi{fLS}^ee~:}]3ČVN~QTk7 `w$sF\ھ@7eI*iɵtʭL>"T+?Fs~zܭowEmk^=P G]3g'jF[2~ME{B5t6o- %Ailp[o.UؚSm~hOiw0TF\#s_IѼ9FX{-&u7SvU:f=\18@ /T[ڤ?e]GY#$x#}KOP*p1).m@P7*?J՚dX^ڏZi#ݜy~~חe{F7s[,aWx~ҚMKDˈ|q[Se'nc帺^] (gq*V#a;a+_|PmkO Pbp7H$-X7g =kGaҹGcUoiLWӈZgٺkZskkz~oMg*ԯ#ذ%z/𳕝p6_~׺;}5٥`qٟ$gm GĚ}Nq!YOoP+UoPyܸs95?5<YGeB+qQ<֒2Isϡ;a!ЀH u|վ|F-4jA ?~ "oٶdz m຿|IU"[O*F?CjhW̹VqQ}!2pWSu$˜sޝ$Aq!ҽ8J)r_ О 3vIm̑Eo ۛ%wdcYyzt۰^wwʿwm g hw7z~Y-:̫+JQ+#c 94AďeN Cی i?(KMK~v_ޖ=TmKg,=)^61tN1U$zy9$ɖ*B#!n$JH_½'++ks% dOb/&D~5[Ѵj%U% F1_!][Z]̾`OPHb~?g x^K [[DHh*@kGs>tщF|RtY-dcO߳hW3F( El7{ڢԴfML_|kYI4v=W RW=VeOb8T~H]WAQ]Jkk2Ve2n17-}ihŸ#W]ArnY?*qlt=RM.<®9'i3b)*.QRZPxoZy $@å}*_ F\<`(cO*.n2kHz\GHIZXFg/ՇwwXO"{ ie!J"v^xY.dQ~UnrG֯C쯋7?Z_jG"٠%F}}+]oTԼOzڞr62:V1[&#N?2;#ETwާb*yXD\ky\6r Ao<㊫>ۀ&D"ϕ 0偬מo"oXN;=_HPD(h~->$xʤj?_?V-B8@&Pv>+kQۻiǸ2 ےC }{r2lxY+9Uv+W)V;XҫL7>3ȮEf){T7?]]Ii;)Dnѽ1ǭFAIV]Vmw(bOWО-(|476k~'֠롅Q9E]#瀊BZn}/Q 'zSW 8=JeE ׵j9`BuzŽNFփJ?T~Κ$##ʎݫ[oLo$;@'nu H黐7ȭ vⴗ~JU<kX".nzVWG2??hm*+–=i^Gj>hR[tm+gHߵqxKT]kDx,1t"߱޿F [3D>n?!U=OG zGmݱ^$pqvZM|D's|cs::(ݽ@=&qt Kx.GNW|6Ѡ6@_1\J=wufcMV4`6ue{mBT^JkH m+~-赘["#`7/NT%}m^55fL#6*Rqo#k|֢9 >MZ?;[ԍys5֮_'4?~IךLJ'{1HӊΔu) dznU91I1rAPҫʉv%`s(>5>T^;?{Co 9Ϧq_B+𾥨jMPd|tR2a kHncݔm-_?A6%Yc;dW&yp`m 9>0xD^2$دa=+8ty][M8<u0Km$DŽ7Pb?_$ QҼm}E*2GA?`b-Ӎ9vA?xjFQo'R%xׅ@0?WCx!e18V:|aFyEspZmca SH,&|IL+Z_̷mI 3_ORh?a=!`*G\w.mmc]~r 5N!@_ƧrTzW ?/C;LԭY b=:,]v(=]#s՚Vӧ`QN~^1^G3l9J,υMV;&ȋ6_G|^nuoQѥ\KwU"Ŀݥɳ[T/3_gះ$xn+/m_CۥyOj‡;*67f1ڮҾzE;ַe n=0 g6>-S>Y4xDRMj#^:珥|y1O =`9X*"/Ѿ xz/6L/ ]#k_t !h^Çw]>l+:2"#wzmFwcn}}7@eo.8,38v-5:_e4w^7֗ 3_6>X\IYWqWpEq1a :`o c' K>v`LcV7g{% y%|dV ,x+;2k1Zx#N)\2+~قLO`+kRYe>_Կ$ʖlcWN[4x.Һ,~m.xUH !~!iz:(nFkG6ڗ;ˍL?pࢷg zWnYĖ$*= r]2rjĺNӛha"Cmk~<یq^5 _6fx?Қ]k`.@=+'ste!*[k?l_|l}yfT' "v3%EU~`%"sʞޕWRAnqtRϔrj ڽ#j^ xM.;׶_@QWs9G{Ś>"i݄ u$}08O^IUec8bkmޣ& ÄUݏlzW)iŹ~-ugjѻg!:꿶O_-eH̃+,K|&lc6-N7.]#;Q^YIa "Q>C(+fY^?ʽkYOⱑX am+ƌ>3q_?^cC>ũ.򫕄>1$P*jRz_s~ H? (!XԹ;G=+ķ 71FpU#xk~S~f|Cqo|nybF?*)ׅt9ޏy4~P Ͽ͜~Eh++T.9v-!Ӡeσߵg/.?ЗvyVnl^/?wn|;ᯀ%Ų ̧]|񷈭c0KpePr`OSGH3yJ=~cwaC >UjSPZS+ɽ>fz9'+BR&nnV5E6`VBobz|+[?ٮpF'#Q:^ZjWG\4cZ#~ǿLj4k3|;Jc|4G&:+?ۭ"(ȯɹ`_$/D :R{Qŋ.Iav AԧOǦmvn̤Z>^Yx!>YIv+We~^ ]wV᎜b[344בUDqx s9x-VIݚ)'eqJjL5AFC|W$W%uo; E8mi:T:m|C,mf߱'4/ {[%IHJ޵)휯?ਞf|0Bpr;WA5 ⿨*>G"y5 Z˟ܳ-nqq5³wČJIcpXQҭGˊ}VGڿN{4G~HZ$^#?~s3NqX_Ok-fHF~3"W{?Ug|;u?w2G  rkGJ!ʪ6p{J{\~_Ug9V_W$ұ&ɛyNM=ΣBxfJFW/Ү[j'1@w+ kykE[Wv\ʏ@~|I~4RLWUuQ ,%U@ifX9Oa\W?0p.t' l.@ҼAUe^݇+Y4ǤlC*m?AXXۆ8w`= sڠ22qt1(g-rG>ZyࡐCkUHśq_GZ0# )SpB:-n5MVKp ֧U~>/T.xFO{T 4Ɏڿ6~-I6E @<1l%G _W/Ӑ>% VyKS*ڵf=cd׼'iy[+F21І9cb?}z~u i>Եm,%}GU~H-:`edp_J!4q-k<#=ZFݢXr7)_5ٺQ+57K9Eι;]݀}2Rm r{jMz?va_F͵]+NB v;Woۣ`o[MjG}?բgp;[5NPtU;'zV=ȌLj)>+˩ɻ8y6)?aޝ:zc kk͜`/x|=/;Ȭ7Lár:8Zmg$kz=2?J[o,Jʇo#t%cgyrUf }B=pE4iY™dqT-1 zKq=+O1\OQUqCOtڽ M7<%]*u^(,Ӧ+δf= jM׭rR϶ۚ:sFbW&H Ӯ{}+cGr}GM3xFox:)1H*Gc؊e`$aGFvcǁgf]HNFx5O~zS ɰA'WO*_ ~ϋ5M5o, ޥ{E+#x(8T?_HO$tW)E8'Y9ry|UvÉcNx{j\+2UsH#\ hC¿m./ L~W yzfWwLtw`,chxDȊ-x$,@g~ƺTڏi7)v)?JlMYޒNt<5R5Wmn8NAV)?7Zw'u6b2~|~|1H|iAjYoJ~-[ Yf x5O 35xEg٤*SOS Q^[P{ƛq;];\b|Co[e] Ssuߍz亶g[vDX@z vb[YVc#ҿJN㦙⟈Z+, ā_r)Ϯ1%w~> ? ?jLG -7|luZSO-`zWQ??h)UiqY4-1! +[ռO.ɾI qҪ% QןfH(-ດLx?7^YcP+64ը*'ZӬ<]uk%7o^JES'~ O (:(L| -ٓJW"tR81 {_nK {U=1 $wOWuֿb!#  Ѯs$,7RGN+G>xXx)uRw6'b dg֢)>INZ }kN[˿ڏ7:&ZY%],s]FLxAs<*eGۺteνvJ~6"s6yq~k뎁wp?*E(|T־'ړm `[ӠcL&F]XZn7ew=m pV&/wp2~~S^_ڛ㯁c<7 C1Ӝfv9P? :UjRw?~8|R4r\GGӟzh 1!b:u,9yVi6ʣfjԩQMܳ⠟aOw\U(s@8Y>p/j}4Dǟk_d[oPSb'5|d1gesWnD>]C$aqQ|$g.DG889+?+Mf2 ָg-ZRSEaN+U*!xO?r ܲӵlq0_5I |vOZQ=q[J'6YwRt c=1]k⦵unXOp<#zJy$SڒV:N5d:ukI-K x1T&|':Q :S1e,8k㝠XҶi&§~/݄pʾOª+TU$?4\'Ӡ,}?E )|c9w.B?h^Ǘbok|.Rd>{'??7?SSύ#!o:ȡI_\SZ;'U!,n,2:%Wҿ |'>5~ tNyXj3n?}k16)IFqߊT [i_xJ$Cw L?Xa"'cS8~_|k_zm1@$5Џ+ i5? G߳N'FgQzWS:]?h/|ytΒXb88 ?^ĩF*'~xwOn \`~ &dd8c6q~zqK_}sP] 'Q> xFAҭL{PK9ӷjh<?)iaठx: hLTp1+5 xrGhUG nTH o~_~)]G+ȣa֜(žեCk2Jw wQiod #ᯃmw<(|1qq#xeA -ScPS4 i[-0ǚ?@+A02G\_I+~cڸ,T5s15\{+luǯQ_Ʒx q _'粶,`)gnϟ%|,=1j+xb\7퓧Mb[k3;glW_jsxsK70⿶سq|E<^ 寧|;i5{P[X^2ҰU[kZdևk_/uKRXJRguV* `O )Ǿ+_4|nOCp2?. 횞nv ԜcfC N|n ;,<18ݘkki#vK~HH#"c?ej;GbtC9b R~Kulcn^= ީ#ŖZ]Up!aWq7.jqwAJƺ?ῂv6VP:Qv=,)?/%>#gm,F1J#b5}9<)awgZK+}Afrۤ u234ؖ6~|q8PT3)ɷc: 3Ii)uQR^_֓maA_?e-Z_&/},g?]2q,ർ2~UW6V%gЮ%ݲv?p:⿳gVQ0t)6G5o< Y[GTj?\u$Vב0~?|YAU F2u1\&:?> [|<7RdUߑuOȷ{FypBWE* Dڶ[Q,e<"FA*?XN3ҿ3ki^x+)|*^|] pF6Н7Nϋz3~+xKV^2|q_F7CҾ!IrB{ @ߟxVk;csLA*#xq+/ۍMq0`VF{xz|ˡ.߳O_R,=sQ5woD;pGJChAh{rs\RyIiy9=k63&7cMٰy,{hOs^y~燮"Rx%OuOeg`k4j|[U{%ePHY8Ɲ?κBh:U58sǧe+f%J" 7vO.QXI* vFֿY>7_&MBO(Ɱ> SRQΒ>ے?am.GU*v=*K㤒 B -<]yLM]Vd?֏e_Yh/_Noưgqҽ. IG4,aaӧ5iխ@jXj߂9-TVQO#jyi{$es(0V Fyi88_| +kv=>uSXg{Wn[4^)FaeN? g+qo?!~~ n}Zr2m_n=*Ï;xZ) p:vzi@ԥ"gsuq,okoKC׵|uۏn+gS,kL5n~ZdPKm٪ U̥nQG eUQ 8f]*K?#jq衅bUducjn¿V_ic^{dס{^^Jhg]^ 8ƘEZ_|L% !>R=+)'&?w|7fۦ*1]~_>_ h 2~kvSo%%=Gc|[]i%m#fqGx&Ziy~'fiB!&nlԧ| KPg/*`nkO:\nBm2Oh͊v?=W㮷~nq铟Ɵ1Ϧȁp׵}wBO^B9[?x]rzG0ʆ*Rs>JM piyjΟz#⼹/H@'=k^ ˹3-}gm+wBҨpy~|Jc|7pɂJ.wۆYaGmޥk0n;xgp gF]^;|ĶO=_mCJWR+29~ kp~W]BFveY{]qǻSRv)m|'aE)>ͧk21a-ЕW+oo{ ,Giea%ڠ%3<k#lk_?hi~ξ*bglr c)~-B,6e/<s8x¾?\G^, zْXLO-.Y;mx )}|Mv2KWpgdʠu<_>*-_۵,2س`N@1\?5[e۩xt}ny*`c:W{~EJ`Btlz%cEIj~~>|#ks4IW7QOھoNdҿNكU,IsjwH |/10~t#b1xQOgF/.j şןQQ27\P$BCRpdSî18U ]7#'R\\&n%t|CqpPeJOLk?Iw|uҡؾiU[ڃoJG >~з>#Ĉ!bٔe鎕}sDn3iTۖ]+ѽ2J;{~skHe!xbcl+O&KI)'|Og/_P4- x.Yokkx!Nvf꾌3tVю7-j C?noY|S3'9'c]mݻҮt$EJ۟)y|m$zgx+n>*b" -9U>&??gω].bUQOS_~͖^ 5FH81ᩈ|X sIC|!|z-aw`Fj Uil7oY]zW|{aτ׼ieX?4OUNM.Vᧀt=?Ÿ]:L&f`I9+XV{\xIsEӟ%mo ~W7)J6ɹR>+o9!F$~p\?j\ZsXsKoഏ#aI`R8Yn!g5m:"sSS~`x] @=\:>Zxr]Lm=:}+ZG~~$Ж!L} =0:UZq}kw#@*A K3Z]5׉Ho2rҿ_oU,afm(ד.rr]c{.x0 k$+~#=&; B?<{g6.![߽݃}ka|5>3ʜW+5uOW}f+n|E٨"g`,oʹفqMI??okaoU)~&|F|6s3n|0^gakow 2dxx@VVs\ ֛m MYU~|6v3ᲷT29 v6V=w}:߿U øv 7'A>)xAR"sc}uxRk'gtc 7j&6K&wi[z1W/ӭNHfJ8V~ONjZanf2k.8 Fٱ`Q:b1Vq:"j>(W 0$a֜.A/5 3* 7L&~*k]Yqd=fGR/$gֶÌc#aJy<Jͷr"׼ϱ?Z`2c cwҿےoS+7_ͯ6+ckPo?f^_<3tSVE7,G6.̄|)'/-r= 8,[qVgC瘺ULkinDY+$gE^1mtNT&@ q7g#Ծg\1fqꤶ'8zBebxҥ%DeF8K'?얔cn\NX; mSSU͟caZ=Z }+g67O7R!7sIA$(9ڿ_ t;;T8!%t{E+hd'VOw-Xsڿ:ַ^bɪ1W.Wa_$gC?v?L Iq|f)䯱]x[Ms©"2Ycc@Uv6'$j*CI~\Y>skoOl۞?ϥ~|JIeySOAWR71pgt|[Jڅc#'c75 *MGg6@Hץ~Fo&kME;Ks)notEsʹ>4\C\úK[{Wn|cjZ%湫 QI+ps ?ymicM$a_[_ƀiv ^_n9DizU𒔽d=?~0Ricb8'n]iCDlχ:CQ cTnFq720+ Nj%seZvOjc k=&W.نtqY8>b&֥`/!"¼͌]1\$)HҒmnڹ[Q*=H_$G^:7r4ٲǥ|ؗw>ЯnIBSvz #(+=h~_7]x#nῆWl7ɵI 8"o'\!ҋo3\k*#ZX_W_ٰiY#'oͬMy} :]O.E?.ZCR$ ҾN7e?BB9> qf `:i%QԳ ~z޳>o5whդʼ_^$ׁ>;V̅ w(2Ƭ>?C4Ck׿hxjμ]Č{b.GĝgwLV!ҿJk ~ZͤK0NL5|=\i: +ͣ՛MF>n>'}t'`rcG_[3\_S[4`mۓӥ} {+,]zQ7ϔtnT#`r8+R;1T^7[?P?=6h#?a,+wKDŽ|Si~⼂]E6k&?_4a!eJ1c{ :jwZoI/mc!-^__$׾/%{W̟UOE}4Fi nl*Sv :Դ忳.hwX!;}r+w_ ?yo"?+n\d,c^ugᅗ2$)ǥKw:UJ=C0H-@v)rz zߥ`~?3!mR7y㊯·y.Р/~_&'xr7_"3m}`01SooGVS@mQ.aKSOE ;W[|$_x"6Kv?. >N=g U狹TRq? e UCyGǧzi3'jMQ#+SeDc2"{zqi~՚4(19kYϚ ]}qivBk9*3g W.'>~cF#Tۭpi~VgyTzw犲F7H۵#Z؅J}+FM#SXA|#@|S}""~Uirz c^GwO}QҚaxnup^$volj~2U"F~v"F)J\+9EoȬ,?yr ROjCGL&wf o_W2*iקSz?aY2c'jk$3jϖ\coOOje9iŬk0ed2Fgа5"KF_HYen@V'[Nc 9<՝ě}>CމʘK?o<5isuF6#j^]-s㟊ZG- 67cj`Jg8θm!-5LTiO#B\Ux_N{8P̤tQ+|Ew㇗ kwJ#OB>6\@l%[9GrI#GoFQs1o-=3&Oxn}~<_VFĶѾ&'_Cg+ox~"| O1mv'qxGjtofuo<78>=EtylW{Y_Gs. ?3O\XWmc,(ʨґ8klUC 'j.-F}P*{+o^֡p꫃fGy:qԒ8]<2N헚x[O6Yq>#[i%f7\k?!15-U%G+oR4tx ~mR6Sdڝvv<\m'z'm$`zVU^h>(u%cp>0;5Qnܟ:xlȣi^1{N.JZPO'/K;˂8GJ`+3KW-kq-rŀ)ێsRYfhcpq Xg?K/Ja>:傴eNOZ轑YD[vGNyh\}Wx Þ"Ҋ݇һxDcHa!‚|cRb>l8n7j2VGN)]KS><]Hoc̻   +{fosl E׎%Gv>jx$"bk$qf<k2?>[B']=yhㆬ"Ks_$|>e:K\.䅏@x_}ߕamegdwgxv}OOƚՄZ\h^UndzҦc>DS]-ř#Oi젅;o |2?.#"* cI>`߱ŏx?^x~va_[;sD+FTW?^i`Ϙ;q<_-ռ;j:|!w;fӼIj_xNa׏\`t#aYrR~"j\}x;_SLcqi/.^9A^⼳eV[u>\?#?"|%-fc&}_`ktKoKr"g5xvȒiӃ_g'W񟆭g񫑸W\[}~m:>뵏MO/ v]3P[$RJۊ5୾ m9'= |El4'u9$+Vx:1ɤo0@Pz~u|n~7Rk\?-p{~/q'}F-FqCAU+$;zWm#EC Iqc'}TC$QQ秸d߳OٳEmjRէueH qkfyFA[Y/'U6@1_ؗ{ƚTnnnjqꯑϭ>CEwZ^!ƋwM߻+08 wx3Jo:'-n>c=+ZXhsK>ÃWAzA2  #'wzXׁp78޾Z@@۔Ҿ]4Q Jr8:?߆&Ȗ[$qq1~+?=o}㜏68_|ڷ FR3Q'wT-;S1[‹|F3V?oQ/zW|oxN*KI!) ?*bZɒ4@򯚿i/%R[zc; Gõ{{9K KZ5%uv'_%?/t-߼[`?4CA.t+kg1S\yavr[;c5w?q?]ZұT0 Ͼ+3 t𫬁lϿ"xYf.E}uYil2H@qOz^5H U>cPA geMdw|" 2{2̸Y&񏇿e٩oKl&hJ1W= #>}+H)~׺NOٹ_85+Qm7JRH 'CCGV/b!~p+ѤҿhI(+eT%OHpQ{W#h'`[W>\`r}vS+Nƿ Gb9.i7ۀO@+ܿj=uuϋּ Q|σ(kz3dvay6##w8kg@ojKY?]_ҷ1Oj]){p68+]Ҡ+y>W~5vD|r+YSG5CN~hYkI)gNVg#{  ǽ`*+Q~ڦKuO4)9gF+2aN*~+EQ {㞇'5T]tY- 3c;YelK妮~` ʝݺUDڿU./)3[XuaBm0ǠΙ<= Bvp0KtZ#GZ$qVOo&~_ÚsH5 ?asl4j~̃݌(o~+=+ONAmp2@I;#5s|<#afщG?S~1|Rɒ N-DpX>#n.ӏCAW/Y;W۟^nUOgZmOҾW<+k7{"Ι@ ¾sxr+xQbҲ=̳ KV)M5

Lv0q_QEhTo_u-G@ W'i`{}+]8֧V}YYG?`6nw0;Fku^!ԏh #^Hm/x!Pk$+Xl ,9 |,6>WQx;ZwK(jP`d7ӊu|-i- GMurDn>5~_/-M^mθw +x6iZnÞ% k$1`ҫk ~ZXJ {?-H Tay 9CHr |$ oY[[-d1?߃ Luɸyqҿ]|iK .8!c+4oǤxP N 拱^"Z~i_ \28\#CѼ ZJ X, )g}47-I`ur#1WxM_:ڵs<%WU%=݊!R}<A56lҫǎ%׀b>,6I36׊ ES^Yk=xJ< DHBA_˶tGZӷe,*3WEBT]N9[C%;`lk|lԹY \0?O&P=E K_+#⅗j0'J%p1溸,g.oo<&Q >yxw饹<ѧ-CB<{B3ڙ@WF+gti9Uׁ YՒvUg1?*X+vvdqs`Q1.I`>W'z-ޕߵvlE\dd3ZFVV?Wj,$fe2qq_?5Oq)͡cw?FلA_MyDP1Ӛ{c~X~!f+ M J^G ƾ82=zў_P ]nl5e1G5~!_@m_7ijw0)|{ p@Q^5:ψo.Uϖemt M/QBGd~iV4ڱN CZ-ńꣾҿw^<~lgSwҿ_k}f]^h#!>gž8WZWRA8rǨndwٟ?m|su|\o)nosŸ~S,wq*4H?Juӿt&=!Fp&s|{GƟY5ݽ̮Ų8N+C!SQGMfG@+cs$}}բÒ U)gҨL'i|ğ0į1ݴr+w} n7,3 .~|s+eϒ%~>^olڨcۧaZFQJ9Z7@A\2򯞭dEvcZյ˯kqꎆ?%F9 9xO-![ fee{b?ZW/2CFwbG#p~?0JG3j|@-ʸ?ކX|quWvi@J4]\X ~&4^?!Elԯfk Bg xrg&0/4;6ҿ+.hw!Vz2*Ң8 u-I;4}(Ct9L+S=x5tj WH?_fhmjU IQxCq*lgDcԥM9G;inJj{U~~$aᛅ-na \|'χ־.EY[U7RG o| 5x\icFe'#uGDg|X_N0 {WΗ^"v`#7y5 v4Ywۏʿ 9|a?Y,Jl,ͤpf9`Wm*ڗAK.\tǽb?w|/ge1Ĭ#}1%[> ,Vn3H>/4M:Tx#8ʰZqJߍ2Fqt[]@{'c W ?-,t.sW׌uo~!'OSd{Wǃ4oľ&b0$@9*)V3:5;X㦛5ok/ ثƷl(B [k;V*;c+ZT;r%+9FSS"~џ¿SV>TU gmQUˁ/+UF_&7fSH1x&~lkܚoIy'- }iM9{s*8dq_[mvaA_L: {H&m> ?UItFoy*4{`W\|-RC#zB~|:EoG_*/65asX:K<-_LoNr8wc[[ѵ4RGA5GqCo\bNs_?5'TSUPrpC*hgI-ilPtSA\̌~XV@ h!#EVrLQK!e*P)o yB^k;>_ilDlbGվ8hKh@o`<珗8FG|km!t4R=?~?~gJ 9kWeo~%@w}{W12~z ~>XN kdG<֩h~-3C/QF~ Aǃ!f˦l_[: V5a;(bc]gKğǂ5 Bpi ~;\±ýkgY$~UZC?^fmBҼIoq/bĉxkQAPT]7:pe@)U?Q_.9Em@?8Cl6vgXⷿ6#nQ [tm!TIӡ| ._hN*OxUGäK9 +{q?Vї|u:>5Cpq?˥yUI*=GZC%.5s0XJGz0Nk)!k+֡=6+Y ~d6?Un& Z'|M:ֲ\HIcJ > M(p#ӞI$]بE,ˈ^ל]-ݭk>}8wMGK{;8U6Pk~&D26KhQ!Tmc8~qzzqqV>KjȚ7SSAWAg\:SgګNW(q3qeڻX~Ut?ÿ)t>ѰbT}}MD uU*~+m9j #~ZGi)+; 8OKծ?gWMc2OF;^\L&J X65*+fۆpIxvݍ?<`uO1/oeSmdvde7 s>~%ؘe_yEJa1+_nJ@iH#4%rBM'emtΑzRURȹfaF|*ʿؗ/*@^:SM_ٕq \D`LOv_␅J z{V+~_l4{,O-UcUW?_تo}D%+]K{&WI.:n<-”=r zn_ߋ= >Ub6=V-Gs1*]*P:WW ?.?8_E[n}lޑg|Flk\jpo*N⮡>_1;~.dtOPsj|GyUs9MKJMg퐜 ,*QG͞H֑'It⾐m _i%ȹ,TգN7=:tSv ?Jf +RcXcP=W-K#ʪW+mv2zR4H}+G Gi/=|6[jk#ny>cgjnt[v,u (' g[F W |]~xI[PEv*:zW~_[>j1<ڝpzeyW<|dC[k~gW+;N ítӯ#gnO7kݧٙ_絮B[se~ S,u2}x}TkS]x`h93*ױ&;2JWO5pvӴj0 XNj9ȸA[i$XPv+Gc{E Ͳ3ξݫϡӴE乾e1ՇZCvn;ryyVcr=+86xgΙ{V{keUPt??i}:y)?ޯؤ[413պUR >pa{MT$Wsۉ4@."jt>3Dpm$lf-_Uzrk 荧dT2;#< *mQڤK;9$~zg۬>b*uvk$|6/)՚_A'#Fntk1 }?M 3\_뚌KnWGjv< |9Z{#201ڿ⑤e SmO%<7j~_ilp3ӏ@~eh\sSqoCP$4-Z˜# +*61J7|Y_&4Q+ ?+?<;wn Kc! qۊ Υk h%1h!0A-$r'#>~ f,g@<mJ;PTw>1_W'G]t;gF=+m+=bTK/Z#BuS)gubNS#- xuKЉ=x`q i_ 0G?ě>d|3gSn J@Rb-wƶef- ajz>>>þ ZZ34j9x ;JfWۦoH_l_xSB?4X#|fu6wᯎ&Z a' ;s>[_]c)"PzxOxߌ.-tV#ǥ}qg~,Yy~HRQ𯋟O+/gVYlJR"xs4f9# g?|kX\ʬ B/ڗSo@գvbA¯EҦ#{$z5?K@"y1^+/ k#ax]=?*+D|wdo46%T`} oix\6&\2(,98CiWHWkY;;k 0Tek*_yc킜~Oj|d_'7)_w+"@O=UM{@~3*ѮyB"J2o;Q07#\ AbN/G'Qyƃ2NJ5#נ_?N`Y??W#T}\Ms0W-٭ aS?G%~x":e_09ENq_9ďڧCo4pc82/|1_~%ZS2?w x{24Cm cݥ zVֶeJ/D}omKgbeuyrxehU;UWw9I-" lzM#Ҏomu/ʭ~jy#WgyJvpTv|93yD8d+.?ΟpnfKe?"+ MRv@"ϏUZK5?n.STy0@ˎ{+>o)O7p#7p`,Q:ˡpQ^Fy,=j+1ckek(9,(HR~>PqҞQOpu5ˑ*}1`?i%?u W+9OxZz@iب0]ұnnJOI8Gҧ'Ն_d?ʊԟL >m߱P[r~*Ck { ኰ.?ۮpU%sox '{lV֠zZΎMH 2mXtߑ3c&u&)jrx &coZ61!tvIWۚ/H񟈼}jZ姹I s~G i4[[|"G ׁkEn^k73: k76nmB^< OWfߙPv⤋:ڣe^Hl?;`=E|e+-縆؛|/4iUN:gG~}? 5/^6{u Z݆09<)kajx㻍Fc1{=> Ӟ>Q9TOM^a#̝ב \xPe<-_l+/G֌>#q^q5-SL]sI,[䅦m洒v>IJ>o' J5ۍBe p_H^FT[c!i_>jJf0<GOnXK9o/tc_6%!XcZxei ҼZ|-1ںre,HS^9H#{ebv?OjŻ[V±f#U~:yAqڳ5+s#n힍rlZNӶGj9Q7ǯ^+Y7d)Sw>7+n#C+s1Yx/gU^=w5Z6_|CIb?^x nmbqKA֩L37V=V0yiQ](=#k{kupڗɢJ,ʿj6vv.H =z¼>a ˁVX %e^t?aheL0=1⿉6}_R1z>(|Pcy ʱ=QTbF{X4Cq]=m)inz>dq*^e@UGNjuB5v0__F4g;Td1rNy-#SYXOjg6~vq $}UTvO`eLИ[iąv}7nmjWm\a%zvX60:3|P5 4v Wkn o7 . xQz^[o+xls襱ynއȾq4xtk[!0;T?NFmjgAT7Z[D` ʁVV ~o-Jujg̯co&{Oip G_%!A#JlxΏ$co'5/I #[ ~Y)\9GPר 'ڲٗ`u"ؚg NuwQ:gҰ8{\Tb+8⢊!OF@' ~Q#F8?ʝ$ "&]F3UL2cPKw~ij{;@:ӃZ{Տqg(P } iNIj_W~:dڿn_DW]mqQ_ϗZtI랽;`v~Mi'x"oiTFEh\#oh?-s4S~.x{x?;F,i%g.5+FAqӬ8:WZ~Hyoː>WonKf>?kFZ+Q|ҿ[O;@.fxIG}u62S$͍ID-Wͬf]HNvӛ'L[&?PjK,['¹+OS,m$/ #Jbk]0֯ٯ |[}|4@~9^X|"| y-6LmUq5 -+9y*$}Y*V8-x0_A_? )w:|o( ^#0ѭnArZIpys xZ+V+z+ =],#0[Þ&n:+Gpp+w[~?h _xlf[xx,졛 N$EөJ|_E-sўk(G)~K-Hկd*U=gpk1v? ac<4bgs g7WsOZvԀ[3PV] .>ִb^ #w KU 8 e_]?c~6hV茦T|&;w0a乬EFqqw?fo7zOv |#~ZW ,&[_> Z%j>&UQ|JP$񘲲Nndc_*x*ܱQkI6$2hc*8I9H5A隩,$a+>\$j=γ*؀Q~'ije ?_jM1"OpcȼsץzVj9ac5xwCute s%4œO]*:]cP|WEᮩ6}YTp?r:[__fd3WrV|%i2ݻڲtt+mR̈2BO"c֯pOѭ>vWêBJM oLS 0 H!ƚiXc?銯i4m"1t>#^I2TmUi~t ӂ _ۥM+,o)\tQӽozymc0pץvgv0V&AƛJ'bmvs#¨Gdw,G.+șO@ $C/Ҧ*fy nv$p:~ _.tAģMbOJoxwR͖n?V#K,.@#>v!39'QWL[m5LPe[V <-Ң̼iD9Pyg?jAiF@,$Ac,^h?JluI F`ڄc#[3Դ˴Sum.k˫E$LU]~&q7lJNAϢ"/cYbHf`<)ypNN8.B[y_'Ѓߒ|_ &Xg8$m?o?6?z4e-7= W|<ÊgKHD.[i %ӖS^Y*C8+~,^Ϗu{d }~`T0~ϋ5260$9-A|_ a:L) 'qG?J ʄ;ӥ_d f>p{?Y2jN\|R)d|p軹8O1:!A<(UJGQXbeE{Tu'n+* ] i߸+ x*`lZBvlzՙ+w~ ݴvpeEH_T4}4rZ훱OUK!yLUY.W'fqۊ>V}ع3~Ժw9AG_?ٿUw2GOb&45tqbI4j.8"2t]pO&5)/_X܁2}떻kڮkwX2c+G߾љ$yrݞ_|iRxSF2̓+5i[͊~frWԾ ϟۺŌ1Nif?18sݓ&>$_׵=)>"jQ,c8 򯏿O=W&֊^bÜ|xiyɴ. q<7Bs/$|G̿w+wS#,e%6 C&qߵ›T# @Ҿ>I1=s=Ptj"*rOAX<ɽR`kSFcw讹v?vC'ѢMeohKiƽbO \CtX P8Wx^< .g/$~q]ʗlQoTQOIvr2v?5h }Ņe}&=kpIŨ?ccI⿨OjZ쭧4LVlWW˱V}4d|bSDqӊUc/ݪ-$2)g_NWH_Sb/׏J׍#c5kakxmNbpf̈8 s~ki<|n|Y:f@=rksI|g KMj:]0y' دφ]I{-Ĉ>b0?J:&|M̶~Xzø+M^  ͕ʼV[eIz ?ut/& uˏA_@6kiĬMbî +TьhClcfnqfӷJ+Xcsh;`'aky~ EWo5Dw^/ kV)ҳ}vL!i2xD^v"&N4~%[Z\+9ntAƽ8.<7UKh/V}+.!@nD\,?"~#xk_7@_h,0Ak_ &ykSw ּXpdYV-qw~V;hڿ?/~ͿzD7"GB=}uҿh+KZvQOQW'#i >ݧҵc 1u*I3FHv4״u)"V0F( Oפx⏏hJ'n$- ¹&6ȘB!77C7=~~̷>w:g>7mM"|eŚdEe4g Gߋ"--Ξ~k1lMHJr,]"T>xU ㎕(} I2 vCg[Qİ[wz]InfYO_j`uub.0xc,oIJn%Oa+:qkGohpW^k;m13d,1W\eJǤĚ?|zUmry[!{Tk~\f#wԱ' +PG^_"3ǯW]VѾdVOls_߆ V ?җw+Z[?=?ύ[čb5Tݾ>rgq~,.wO?k/%<;F1ӷ2? +ԗeW'p~ 3Eݏߛko"g~v>*t G 7Tbs_J_ SO qY=ᶇ@׵C<F0? KŞ:ճLO2X@瞠τ~?%;+[H6vMlJ8 ӛ-*Fw:Fx:a_ͼ?5g-S\x'=ӷJ ieR'AsoUU;(6EcjJȭۚG/'(߳‹UzWUO`\s1~Κ$C-P㢿(~ZOj쨽ďѳECef+P'*>R{Vy+KgD[&[5Xb#~ :/m|9]5G3*9<;o]— <+v}X[p'jumjVg2=YAWAV|6eӔ"?eධ;oq_GQxZk2x-}j89S{TZ'+Hu+"Ce??A.Oe nWdRsnǟ~^PB?Xc0$!EHuK0Y}îZlϏoWUh1cW Gtk X|֞I'{>nm2}BU0.@@ݞدό6|%Ӎ/m-^}x_w?࡟ Τw M5_@zq_BCfWndt`Oy+{4qTq_ ;l2¸WށkT?ݛwOWgxꚗM$VQ_(C?n {7_,n'aЊBqԩowu 8֗,hF>qA_ɰQQQ'~#Trk> dԟ¿9ߟz_|ڳXBv ѬDVYʟb2~7j*uكD!TKt Wu$1TQIYWB_ 냹l>R|[Byre U?Z/'E`o~%9ΰ_w1(WW+g?_]o©lr[kF=7pz<|[7&~xlهĀjVl{: S;Io t/2iF5.o:dl5x#_φqc!X"fF϶?~//da= mVkUq*9&t߶}bZI3c\F^>\v7\s+Doƒȍv^mݫμipVosW?)6W@p=kMLcw Jv5RēVA^8+?6>ZZ~W Vm% {}+7zyk dE_6ȡYNqg$Ii^'ZTƒş=x^bMg'!^S<?;|Pgs_+~ZVvoۃ5>}c.nµTȹJN%U$˕돗nj?py_WgC0`xq_<4mT~Fz1GR?U/5$#v]@Nj=TҦIE#.m7YiHi͈`c޿<"fi7`W_ed.mw>vZ {v9{bMݙs'K` N<E}kG|6g%J}z_+sAt_͵ SI*;MuQ8n*ײ!OZ,x´OӏƼu'H+g#ss&"c㤆fg qZ M8@vp}>?Sq:X5!:)!qoUxnY! $.1G읥un_>քn ܿcܻ1Jb~xWJ?^ašs8Z\N#'kTu} uX–f`"RGdH#B$mf/YT@Trb ~tͻ.0trVFSV+^"@<vr&n8ֿXЯϷ~VNJVE ӴxMDO\럦+-<% bMỔ|\|ȥ~Lhfm,@^xJB,攎C:^ƵQxK8l4.=?w1j7TMǵsqI#.=J-6Ǔ'8?JocdO?t_98\DWM%f6:h2+ Ga_W/i6C]4|z?5n{o+>=9\$Hz+w+>]f? [BAtotP~ WUx\ei@;LOJ_ 36៏^+bw60Usyݫ[ G^(Uahn;HZ]*tg M;t>G#Ђvf(zZ~`?fǡ>au~\9?0TF;ҰoU8lϸ T ڗ2W? <')u&$~3_o~ܾêʿFpqץ( 0|(X[F(]KmP9Z^(hizH:&T7ZP*V<[O4?%;O=@+aG>Y.$֘ˈsYV|UirGLKچ2^0H9jPFv_¿_& wG۳_Qn=o3d} ~X3u- \o's3@-8;5Gbk;W{g>%MM'pfY#l}*JQvfTJNƇpt1ăB0N1_l|T;!B[ec=+TH>)W)=Z"'- ۙsMYoLbXq "Օ{f{ $J qRC!z:P_ηW}avC#`/ojaKnfízrG8/~=Vr:#y~`c~wE$Djw52iPV'2JV\8͸޾G׮u]{G6ܦ#=S_gm?02DaN8I}O^4! {˙$q:W>x`u )(ǰ5}pˡ\COᙑw*Ƕ=?ߵ?m2; xgEq<ǟwcՋj9rO_x4|iu "]rUj* ʳ nڳFXMVT؂1_7\se $rO5~ҟG;>Y4~q߁_ \4b`+Gx~l>'X"58cZ?ߵ~~:4S1 + 5vz]xL8-1\v#ϠO }v0aqWWM[^4-Յ{Tm#+b9o07 )W<>]bgbp=+Zm+UZ\MBpe>v#e~ZZU1/Weo|Xf-gOkN.=ÎUM"`ϙ?_<VPMyį$Ɵ t#s d˓-ڤ k@߷W[{N ȵ1*0'==?nvPq_?xkŚ 8,g=+П#xӊ#:jo#4wvlV F^ ֿ-Y4Ӽ$;`whnk_ZefvyBMEh@?it'{ ]jW챑Eg4x MWB-$w7 T37?@+$ AJrh6A+̖H;o+_8~ ZYԮq7L9T#~Z14pGAϭhH$|c%z_ 3WG<S$VD_&JߑX6G5K4cOpk>_ 6D^YO`5]zSP&k#68e?mi7=Wzkn|}k'(#?N!gG稬i0<l'VNj'T9+#cӓڲ/VosDz޿#w}W:Glmkk GO,)l#1;#t?_b,&C}x+{㝄6^2ǂ1؊+eK {]݅vRz~n"n&ӑkjOV ֺn~s \VZ1ͿǴIzO38*8]S-g[$Sʩíme! ks#. f,d!q_C^dSJ*mۜaqD6I#y`e'_5X.g-j%A~%rp-9*STbWTAv@Zbv Cu B*U݀`}/O>+;\\W's7oʽ¿|`y_-לǨif}%tpΗ6oDl碏Oa\g1Wž+?d0c(Zzw3r-݈,ßK&>j|UmyGNkTWI[l;s2թ??luΙ@ِ>sX ӯc¿_'hTG<O/fD*%MٸH0dѵ协,5o)}H 9XEX4pRs~L 2-\﬏XjDh~ff,#+g$sG*R-8u3/\)EѴ8=K[ة~DKrGfu+ZҖ]FﻎEezV:Rili&…0|7uCX$˅'Mk5cW^GjMyqWidM.ܱç[)"0( =s> ٿֿ}i#(xFC;W+rXe:EmWxSoSCX }x$rnneY$B $0泣ͰKcOC0Y۩=+ 7|u> 5Iϕ来3_0qLo+].TjX?d \1pXqj)%qQ[nt W=\(fq_čΠDv?ORڟmJKKi\;  tj!hio/+HѦ]"FkN7LUUqæ9BN@ǚ[? a_ Ys[IKUs2#+M^g SK7Ki3g#~Zw?j7Bos鶹=6H-UJv/د+j&cL001]Kj\^j&?xh{ -5Xj{ZLw" WSwu7Q)sYOg6.wܑ7Q"g MORӒe,? *:RLHj't.8LRGɟymZJzS~% l/$كoT ¾ ??hk/m.pD*H_~ pW䚤يݯ&|quqQ_x^_2K':0pmݏjk,A 9$ s*Mr]<+wwtYK>oPSc_s/l0{N$msG_ɦ LVs26Wbiw5~FPWg=ªhGPau; }G-Ļф`oZP#I)>?)J0 UϦG nMꌢيxp;) WԤpYFS ۋ1&E `UiKH6F"qV"j[ܟx_Swd/̢ebW< Hm`U<=*o53`ڦNL{RJ͢8s'os_Y;~e~&ӛo'm Rw5b dlJ)l*(emghMloIf2{Wc7*?.+{xʹy9Bk#zgfߴV?~!Yq72Ó>kt㾇`zs_n7Jnp@k|_yOf$`,8ۇhrXMn-Er(3ާqk~-j~O`He<߅~~%'O{.A3LW'PڍOMZ=!p] E*9z mǛv[IF.,/81S%)T=> \QSzoR2;O ;NG> WЊ6Sc>.mjŽo Em^KM_Q{WYr@(=e=3&\OHmI C PYwZ2=mAW>-wt>3T#$zLT/N2Qw\~\_oG؄Eq_1̀'ԙq8F*Z!?xgG 6G]V(_m4)YĮ8Rȯϊ /[!0@vLP۞5PCmhai,'同^R}OYfտfGXoq붿??ir#S~M֯[ O<#l 2_ȷ{Y6ǧzkcNU[qe5jN/[[d{ٯ g[/bYƿ_"ŧ]GWX@ǰUٝ7ߊ>5-:lnmI09v_~o~&[[f7R>]a_|~>7|5 .v%UKmHvºgOϤxq { +#`rƯxkW6>|wdl-i_ڠZ m~ml9lғx\lF67+>-gHLK0Bª-L9E0~>լtygHܤz}+͡dTS}ںi~/"޹qdz|X΃qoC-ɴ¢>zqKfNjF1>}JU?%?'–]=DUH|mxӮt9ǒ[ 9@4I`'Jfa}8_EX.l yAȁ(.BN:Q5j@nw~uٿ+n_5f.iKH2ynqk~~Xm`ak>6եN)ٝKմ> B³g|{gu# LH]RH_ˑ}W*լf ìPǸSeZ|AƄB7~Q^V:n[?W|gm<$ëZĿX~uo:G؟W_dr~`w_lSx n|&ɷk*,݇%(@0Σ xJ3'ȺWR:`7d*0ھf{iE7\{W}2=U1?Mqz1X]5/.G^O`~x:R܋?&G>ƯFKlq3[x_M6e0nNH;nՀf 8'*epv?W7ЌyF m ^@q:w?JӿO FZGyXq }*ښ)aVYj~*m s2 W)hܑ?6^,a󁷷L:g5f<1 Jj9?#'M&zGgy>%\mۂW8q @7$qZуW2+ bI|yL[v[FF2W/3un_L|7c#nP?p-q4^{7^+~v/ǝ YW!'S_ۇnOقPFi|JvgwŬ+,6ic*?\uəos+dsU9:0Z{VC-=.ϕc=*Aj[+,c gOOʁnGZבq .9çZ,YV-jqQH?p)GªE%㗕Qm/" t㓊Vҟu?].Ki^TJ-eݐql~g,EmWJ>Yv=UebjV [,\U`2֬@OaXp(پnOf&wm1_ۏlڿ_?vg:MvWtWhIl-{?~K԰PS }[S=XFT9;CW EWt?Qt/Ic\Bs-`OuY3^[°;F3PU FTCۤ+2_J3Po FFpg?k] Z[:4q¿&wg>%5%hc.=(ب)ZF]6_ORX254~=zWnG7ƃ̲Ja]NNzQ>r NJi_O/ëa'{gᖉvѿmEX{<k#ncX+oZ|OiV>#&s)n͓\򚵙0ҋElt·pG8pq)ڍ5y'I5"6Ge{鋱O1XivzEzwoت/ ryF2YGW@?#JxZrO_~)exGN?D,v\qY몍~ۘ687:nҿUvsa­~OKFvgD$[3ψ⽺?)ݳh]76*ۧkAo*p~G_ůΩ?;yXtԑv\2/b[/ kv9PRf# ]O}ΙIP)h@q֮8EެMa$C\*~6kqsl#zqrYc }+H ѩo4*US؞q[D (\W#9~IH*KNد{eI4j㿽g=3 #/ #+;y{0_L/ rKb[:{ ~6]BBGls+eLQW"F8Iޮb2dt㱬<6|.ih"]Naz]fŸ5x[knZYY,λw`qLln=Y77#iE`Қn"A-ֶVBiǗ$OεVAn{(8_3r$(UUim~vq=(3{TU@8ֺoxN^;'e)qEcwo1;x\1- d&KdNA@^}&Nϰ-»Xڹ~^Gդh; #PZw N*ږ&H *:8^kZ-۸۟ _:k!G&2>IcQ4#NѮuQSN5[eW8+lNq)7|BdrNlWˍ+ a}`LzXePڼ[ l7#Np “Zi,2`?L}+$]i)8LcZCmC.~eE9ǧ/''93¶NyXyo*Mc \p}?źLNwoдPI.UCUT}w_$I^Hf3D߳殦KTG`TW]-tpj-HhWы8;OCjaW?Unly[hzxa.C~ ->k#zg~rxw4 EG4|uOYsJ2/$D6N }\2nbNk1i7tLl ? jt#K1;m5Kr.}&^µScTۍ}kr7`Hj;X.v_{_UOOx͢il^|*%fJ?^gY O;3ⴧMI{5k'=Ə7}[-3T+kp7aNIOw"bv:t)5ۅrq>,}o>Fd#´>={_bևޟݷO=1T[EPt_s2Qʿ+fiyĤ Tg۹޶;S~VMYu?xw~" Ē꠮}s^om4>lRk@65εs5YVFJn> ;Y?*"es&r%d:_<xŗ~Ԑʆ@`;ג)ҿ@?vɵyk3sj*w%&5 3tt m1vĻmdA˄VpGr_Z1\1'5Y ^QX <~S=ZE[T?P->=uogp#*= |?53< ~.U08+#dk|MifaPzڿ>` (MgPsѱ؎MXi~$\;jLϖ߳eӆ&DsL+z՟\F"OUwlON[_>pw@SG+|w,V1,d#Ua_JSSnnNȸU'~ !g44խId:bF"t=I*6R>d?ࣟ~$r45^ 2>ꃀ#ukdϻ#< O[A9"#9bByrk͡ fJrk?Q|G'}2-'3W dv? wD,.֣6^1bq soʽ}Nv/+* tn6e4&~s3mQÉk%?^n2[ŀB'|~k:]١Pq/fa3lK#V1J/٪Q9WH?J_)zR[efkAx|'H|ipx_.?ZLLxRF)?Co3By_E! ݈ׯ*:i!M׿jEc֫Gjg?KۃG_bx[Vk4+M~݇g^K?<%GRH"S4Ijq4$x .,/n/4@QednEl~% N_/u/I^5y-̤Hsi4?g6ti>U$:?X87p/9{W)n- m_XS$- Lnj|ƾ]LپVONۏ?qa%eR8s_Ɖ@~sq?t?5r'By=f&Q3W/o_+R m+wM$$6JE/.u/4ɚlgҶtIY1B=G=;Y_h.fҾKҾm sp*\Z2z'pqX3cd[ F7(t+Wq1!Hu8GLWx4ZG PÐǟ­B?9ol\FǦ ǭgY+y`{W+=[IĀ2I=8+ǁ~~ws*yIm X y>?м ! ߵ~KgM4`'*1G:dVc&J9JZjqpt-|+3  |ԞH_Hmn`:|T6rǮl$^#u$}[ӰQ Pܺ8c۾}1tINqoxeC/F 0?.Mݽu#[\gr]C%2ȩ97t~jUH- 4_ZźEK(,2)UdP_Z$Ra \y 6 iX.>9En"xبuN > ֵ(O2!p^ƿ ٞSx#ޘs#oSeM+YjY-@AMZYN 8\˜`v}oWqLo/Eoɬk3DUx涾,]cm>џE gek%@2y8o Q*"(' [4ὅM…˰%ӥtaU1tzW쵧IwC5||B̺"AQh~:ZW VE +bj߳^!:I[;n 'įqXxNE>.Y9b2}+̼kZO-m +5Z]JB'k%{|/$ܹoc*y2[4sQ]"Xwd dҠ-_^h d. k}># QM%yǿ_W ?2+[P%KUUo+ o> a=JQ`VLK !Y~:Z֟ t k7 q. ~H6d?~$⏋g$MA>) x w+9Jf߬VsV@㞠\j~N6>0+ œˊsWM/zGҡw>)k1#2\3棒AUT`1Rlޥ]Wcpu>ÿi\l"`:ۊE.}'~:_ee FwϕG.IR|_xoOy]|g~U=[|Ib\v<9>^ߏߴk$ 0F/ێŸ*njz܈mS/u.֎>1G g'Pga6_4sYHea_?/@GG@M4M:U'j~Z1k>%[Y.3i8}??koЯ.ΏfoI8 TS "STxcfܐ{s_/dٳHjך+<nO5Px "UlK|'> 6u=Cp#oW'a)|NzΥ,KF 0e֥v d0H+ |cwDAy1x?/~cN7QGz/ω:Eյ[y&}EvBjAE~Q޹?\HChӽDJ xW xH@O,OqʪR>G/Y#KnOZٟm{S>|q9ĜtƻXV`x!O=8D@Z$N.jRKqyDA_7Us#c8>{'p?b/3"+t&=X>2[.xgoxW9V!=l}+:|mӧj$nW"N7v[j?BWyQE%J`>P?JచrKps ^W24K0'O²Ve։i:t5l0U8C_Q٢Ear|q@qCL.6r7DA@:B>Rm[q[|jz`uZ/?VwLh$2 c@~>0|DOXtF'2ʎ޾(Voe}yW{~? >/~$Ud4:ѭm #0@Uդ# {dշ4Nd`yIexJ׎?}Q\}n=ٮL*[[}+$YxXѯH$cٮEe<\Pt/mS^k|7|25ҏq⚝#?C}/M=3ʻaf.~O}I^ġ#1 sޒw%9u<^V˧J8ٞjWeeewʠpfti!p1ӌUYT$:/5'Sۏ­Cu %ٗӧgV(RyaCts! ;x#ҁ7s߄Gƿ^ OZ,ܽP{W=;MImw]Y>BLݼhg}ەEЕ ~';+K|g2kZݴ( t^0{tuGlNo%$kƫ5F'K cؠVKtcUn>/$ n_@?ZLdᗈ~x?iU`tff;[M5*x6)=y"R[CQv1zk7J@#:-Pwѹ_]Gfy oSĩ ġcחW޵RA"G݇Jc3,k׹$f8/NcO'{b͖hnչPqk^{qpԅVs?M%5r,G?}/ue Or:nUj3*0z.ww~#iڎ MA0#pM_ˌmU$>_jͫ򊙅Ju2+3*[5.vIU`\4ˌnO irl~}wmGNU:U1L ~#u?+QZ*-M#9?"w-.Xd1j{ʫRX1K)2bYc0bt]sWKgޝ4ԙe+Xb[hMJqGw&B0wFygm#CJ_cz5S8ٯ)ye'Nʿ[7 ]c?E>L#N1Z卬fVrYx JøNG@k$?> Ģ$ֲ5ȭ5A;Jq]파7j,dE2jo ˢXa@q"} FmiL~Nƞ9O41#URe ~q]N>%.[[Y<[[Ec\{Թ&waO;~i.)*8{љn:뽕g`G1_3 :h\m_%F~Ve--xXGҏ[!w'xVRnЫ gx>hd~=ĩӌO|Ҿ!6 |6>߅z. ˎĀҽ cJgb+eӤ/,2=kq|&dOݝcıj}āFtZT5LjSN%/{77AW(KgشFTLtA(ğAu{#88 ~.| Rfg0,kuFUc񦕧{"%j㲉+cm@t+PW'|ZkxOo>8 f˟$7iŚ0حavzʖ"2gMsVxs>K&;զQ(Q a+>c%yBL~UsgO6IjNwRXKFbӴ>aRsv#1WZbgn2eMȰg4;xh_R>6`s2=S[J ڴmsS1aX_aKmCMYO~ *koS@.=+/O/ <9g~%k۷jF V{WMᵯZxGMba "O ~ܟ֓K7.Cl-/4 _c LsHHx!n[uAi6]c$g{Wh[뉀U;?*h|rBaxs,V e9_ʞ 99,+^"Kf,r.lgҿ֞+PXV^ծR2}Uȸݷ ^6ւ6`sӯ.0+yq98{_&'-Džn So`:~_>ּ.ͦ@<,7?¸٬u3˱!v#q ? bߛP0zg_.Qh6LVumG_O{ +~'`VL2^o \݃t~qZ=6x5ZS\Mqk_^ {f[[ckKj_2©XnFH,TR$4N\yw f^MClHzW[^^.x5trTTgW -UςP٣᥷l+(8'iކ&WAEz|3ogƙYm%0 qu&ukm^=bHD#+kWxv x?ߣ+\1@0{W|i7_\xhD2]6YiYv(XXipE#8հDW秶E>EzYA":qTQGP)Oұ:}9>աw"X\OŨ.ʎ;ҡTvg/H~$hr7 Vn mg-x~ jvtU]\H.:uA</ xLa;W5S /M;K1\}:ҪprJ¿:mtТ4>[I),'zt7;Kb}}KxdZڏ ܶdUkh+1 ~#\GòGc#==+SToVR_-ի9V5mk {ZDmcU47r[~Psj/)貶qvjB%;ҿ>xZUxqR*]ϊ~'MqlT 1R앎hRj[J5nA}+^  UFa;dNZڭqm`gSK{(|2#|zj(?vF3W?ڟ,):8i#!3ZcNoWmg7G,/8ֿf5f*FsZN?e] ?E涆goEcIeߊ./y H3rܜ`T;.w>e?E+_X.3B*v8.R_P~ƭ4ų6T,?LGB[U󭬊+]xX];`ڼ]B0>Q_vV_SGO29Oিr:EYSvwko+kn^?K nj.$ʅ1TCaB?[6v%p/ZP:Poc"R-ܶ叹jQvѤP_e?3ғzL+?6iiv=0Xeml584ɜ>a_ P?1U.I)ڙy[߇,&cwn+J/#eSFF  9ښ3dX?gY>vG,ZZ4|bF5m ` Y_|j8lqLWP\gmNc3O~Ϗsp*EeSo%/m7Om/^ e6Uۏ=[ͯYR"Ur짥}{g#CIr>¦c[Z!n(fzSP&A[ORb>2,|CԵs)h~lt?ZnǬXțWo)O^+ò^ Wu)==]E_rFØ-W,G$xI]5e?C&{mSx>zT2բ'Wt13}kLhxv_ C,̸yPx dz~Uc|4Ζ]8ӥ}m71ZFX$ߎzt?p2N,"erx^ wk5̛~5~.ۼdz+xl{6ddwڲz_ZNN=O|1gm]4M`j;kξ ~П>,ix1" ~_b3谍/K废 a@]_7)Ic|z~V{ʟ>ʉ˄ v+xW¿Ij]s8MN0=ĄY \H?7:b!ߞ%bI_JDx?5Y"׉[pkTLd:Z]ҥf^̰潸)$;u#C ws9?c!3<;n &ebcZ[I4" dsҸU&噇C ?|:R6pJRu]=]^FF[i^UFϔ8x?=RO-xPJsQXQ¤t:q&ÚHc?Veօ6K&8 >.m6U~ӛTU[ l@=jyNRJ& <~]u Z;x'`""8\GڤwZ($,)dvO{De1'@D-NQsZQiYpW< nJPQN3_blI.2=90NT(+ ׶ w@\}u;4-u0=W׃I\=@9⻫?j64wn}+~cڝ}!B/=*5ާGm;& Iv$rxS::ODip A+YCszQr*<♕L sHOU%iVʇM"pB gQG.XjŽ%M3J׷y擟ΥH8nd#+4KR ewAv?ȫWyEm'leJL]Z=EܷE'OIm#9SWž {X p}]V B6+bO;C^-o$й<`g謑*(n}+ߡW>*[_[gqҊXOHHr+zUdȘH`Hc^x^5۹ᵒs63ھs$|Dz OPѣepG)o\_H>/tY-1xinIۥxOZ.b5goLj0~]= ⳱ _|-z)G ϶+xz8Nz1KCxgeQ,[A<i5<<+yņ MNx>Rhw[~7žЮCxEr+xz sg5Oc֔nOs6&ڄiC\V~ߣѶ0= ax7U.n1Ծm1yGD˹"\)P4hmǚͳG)>k*sve8MaT&7V#&Y0N:TD'*O1UdqGOi/Ȫr$0+Uϕ8Y;=m\m&$\jCD`bMY8ҨMZk}+KN[]^8YЦP O.dXt)=%Y)~̰=ۗ-eÿڿ/NNǯ[Cm t3ژ~iU cnKEˮ4U^1}LῪEnkdl-zS+#jV>,~*S¾K3Mu*A2U@s2mohٰ0 -'_ZSl qӂy֌W!(Ѕ8i~VO(On}yinM370YgBvvPZǾ ix|W ӧzzLW?P1w+w>E`ܱS K7bogTrNL ncΓM ,h3~<|&Sc~>1 ݓ|%~2gCCqu맑8_iAc$6BDip;@7𦙣~vzPW/SxǺI;Gs1_+6^0 B=kZT TJϏjWp. ~ϊ/|O 6>-8~}23̀HC>U?|+>GZ kshƠo>+k;4G򱙾b{2x5ZMGQWm 'Zy#na"tq+*iaҳ [m7tm hTwmFf裢ު\ Em0"R Q&?O߫,kߊ!s26qP=0#v<aK9 "N;~=~ 1ǫy"XHy ۉOz9HomFnicxjIc#s n< ?ZOb[4_rx?Qsoq}+ƟE ]^s1`}5?D򺘚[ ͬbt>XΛesEHZG 'ڣ zr1^K+ !4 ohb@bG7CӣY `r[+Ě=᭷+Z3PӮuCʁ1VjgN;7[#ͫؗN{Ŷ7[|%Ctm'̖}|ZOv7Ұv='pς>'yr_>zJpgX vp:k85YSvRrG^1Uy#;PCJ;߳Γ Muq\0&Tp1_@AoxGć$W'_cY>В`moNy/'!W=έ%IXu} xf ,#m3p7i/-յ̐7"0S-}NU/| C+a,lC >x[APq'z5kKS*-N!$w|/b ]n`:E6=}*O"oEេhWw7zev~+φt]&5K*QX7A}a`|AinY˱->+&"M(J-D}q Cm8Ws~ܾ7o;L'\Ǒ~j >؍)Gl_R;7S hoXɕ J-|..,~xNM<20Vz"z{QTS'ϱ5_|EՎM=IVO VWÌWvXAУB3F7I?Ҿ!ZJrqt> [ɩ4qCny6'l~]t+k.o-83t'ڿCdkdx-j7ͧ"CLJ 7 Q }::m!;+77:<ɦ*;1SϥUխO~#ontΥ~R l__Hk&y®c*69ҿo.c;eчC_G-5f0۠@Q ]qxz%13>.⭯;6Y8cϷ}7_hV>ҸXZVnAtrR@=-{_?g7[[G*M(71aQzB>\plU4H{cX5cP|{bl uyw9|2R^G.Ǧ} 0ʵ!_>ْ6JQҮӱhw-(sW73]rʼn=+i~\c>+Y^.1:|)C `GcU ڸ=|n9 AmǶ* _/s d1,3@ӱJDyɷ$vJ?O_|oo 0|[Gy7b>ZHR{T*rRG쿃^7Gx"af[-~1P+7`U;1 N*qRI\hzO>xo+S^I#dW?WvkGmX'jgZKX8W+|=Y5͓zq\ßI-3;J+;s)B,Ϡm^Bд2;6@ۥ}5gmt|}{/M_MKo:77#=[ |񆡤^XIp?#|mM'%PIW5-OZM!$O7]ʹLWߵgmA`ʬ s_1u8`Wy kkOJ.y{F b2wz՞CCE4a?5׌ǵv ]7`J a*;1% %Jѻ?~ ~W,|5c%WjH_jR˦Alћg)`F=y__E?'I::ߕ.e b@ WG?n |<՛ú8o3h}㳜;r?Sښ^G?#yn&PGV837M5dheQ#+vh FhYWeq˫x;/2-VN6e§WZg^~UA`?һ+0۔#.Gr;m.{oWU?ҽm((1WZs;ρaXGha2'jWz'$2 4]6<h -~>|>犵?Mkwh~ʒ.[b /ub| (̒8i}=3>k7?R\]~ំ$k^ܝkBʡ|sV7~x| }Tkࣟ`a~{)#RWrn&@G"ߝó¥ .Gc2?-F[*,_'Ǧq[㿷ҿQ ^T C#*Rw>vmncr/+gPm8Jo?zl:o)SkkXݷu 7>oj'= xt ܚvQߵYm+UiYA jT?#Ek#hڹ,Hh<8ڥj>խPOJ3k|W7?JټtEbm 5g!qN<$2B?¿]!E 0~ȯ*+/ ;GY>i h _)9韥Tw=֒okˏR6Pޙ'W9r{ յ/I@'p?,G-ɊE(M>Ŧ%'P ?ӥE"er'ǟI~ y O~Kmxe]o% CENG"HTW~c9!t}]_`W&K-3+f. ^N*,1US ,I\-"ʰy'뚴fΓ D:zPaGx9,x&&mҐEW#+HyiYIݝs[7;7GoQ^wZ֝-)v"Ǜbi(l+IKrVs|_̀w> x6O؉a+:A]&I@!\WVQ+'()-GߒLEN2c66dWxw,!g#5?[QX~M]PXV?E)ޖ)T&9gR`])ÎWJZvEq88ڝKl^Υd/g>28s=X.<fSYb'$z"5Ԡ=G+yb⭉zTs>7[o)S_WZaϠ;8z0՟ragL>=;گ Ԧo ~_[IpǧJ_#nayQ ㏠Od}\8oմ? dpՏju&0oLIn{W˚[]~U#M@7BkUQ;-&:vj/6T*_GqֿU-?'#>->8jV AތG<#^JQ?b 0rz :P{g4`ぎ+_? |m3xGjHqY6#iDy1<:0 nݟ|]`b8lyiYVYG~$ Ҟ@=j 6:qړW);\Wy2$ W=4ӎH!P ;u?mю:u+=: GRQI{W7ǽV~hi^B  p;WcktG{Gx'/VekN93+ pC1E/|O><7M'o3$=Ɠwi-͐ #i}8G܍z.=+?k a,?j+5RcLּa ښr@!X`u_'t:pT:+7oB528%GJN 2[h!b?"ѭ4ߴO~ G @*w8{o|GZN-'A9KfOX|1KUsb*#5^(L >cϸpa EQʛz#]k> t+A'ap/%kT Aewz}Hp=+?[_deYN:p}+_wQԣnmBB#xǥ~ULjg XZ3M!=;/9ɄrT\bO[? }$Ҵs>EЯ_~(*/׊6}SEya+w>2x+ѥ']1+Lczq_M gⴾtzW̲J]j\ v/ YV?_S3Y6mK׶w1ӀWoLf%^rI)PwfV'rrpi "G+g~Ǝkkv ?\W ig[xO%DꟴW $cR:ke?v6|UI8WƎ^>n[n9ab~u_e9=@QZj7^VGA犟Tp숌dW_QOaj0$Q؅#h6SUIq1ϚO=ֿڵi<_1ʬVǤ+H>҇^ 2?/bO> 1U6f5.d%qڡC_\\y`"^Us 6,ϯ4hvC2kv&0ī"Mm.߁xs2t鎕G1/K|dRGPE/ Z? ;kQcV Ҍl{O᫩V??xPv qsFʎi)bU4#rsIV4Hp*R@%{T*:u"y'Aoog")axr[3q=1ƾ]ԵӴ m21s_'&-bA,=Of۽-*п'o; xJCj#[l+ uq8n3[Sѧ.ᐹ8[!nzC`~<11 wFWQk )Ӥ)]??/%.c+q ˸P[B?i[B yܪx߷Tpc=Od_) | sm4N/WGo+E2;W2ZWuU3[54o~ELJnἳB.IjiO&k/~bmsf~h`+ 4?kj&&'؏^'쵦j6DgNa_'kSAI ;qڱլx1AJ-2q%7) )=+9;Z:;Knl&qONih% #\thpO#? =r#;LrlV*J:3O$#쩧\/V<$1͑:{vm׍/x7Dw0!A^kA.7@HTS65gݷ@w|pVrGLi~?^Qhw*08cڿ;?oo,sx᷉4oVȾu8ڿ:ie͊G[gҾi8E]&V77/4\ߴ>*`[*A7%qY ;< +U,_V?ᇀOVm *p8c+izʤYn#$ q&[Wr_^^*ZG2tⳫ^dz*k~~[[&-MBH8OOO+/o 𭟅>#OU{iieee\5Mq+4#i&sj/|qWQq Z4萴|0{zbEls㷥tk5.c9_~ bLQYO'#?} ~mj>5Xk,M~H*.+K2^O{4Lɼ\20WخJEsXoV7?i/s-׺7~?+an6$0G9׏U[M+ gh5eS*6ֳr(l5\a׼tx'a{u^irzkIo1?ϥtq._ߵ3:/ae Ƹb6Ϡ?eo(i5]Jyt ?9FU~1_o~ xrNoJ/*&1{*ӊ\=.y]~ wQ֏koB=WgC?7|,c{_$A+[꯴.5MN 8Qs,VkZiOBt@B/,azU|׀ԧϼny 1ko m>*E!HdW\%y+OnmZ&(*N*0e1#GTuiå[pb9|bHOkf|Ma^k_ Mcօ7(+R_nmhR8^}6JkK7Ccfb&mIYܪ6U0*+V]bLľPc략fMwY>Dyeú(J)㏋ڶ{>gX`~+ ETm|hW ~G&ڶҨ:_YM5gD#;l\]jKo Sc;^ITS''kA>OӍϗmY)].5hÏb?Zx> oY9h|p~Վ3xđdg?²%7qB`= ?`^Mq8]*oF0̣_YW#9_9g!*ҾїcPFRq75M \O FzQv}bϐ|'ai\ˠJG*3m _GgDzz'/ό:Ոn}? }1T%aq{)fb? j#}J "m~q(Н3OOڃ^+m:L JWuExO줤|l(ҿO۲-п6d_?>xmeG|c<[ş XIum#2z}3|%Yab~-8KdPi>ԩy3_hÒOs_`s\ܧ#?w,~n@94+zRRᗩNv'&o5_3zRE]5be^cUt:ms\"1 -9QFHu/XN 3[K' uRxwH?8}}?^?KiQ8w|wLVe |J5ֻ⻻1^oj0ڸCk Gs:txNܪ8+H[_ IurDa(1Z=L?1h>8?m2;n7կϪ|2;_nc1ڽ[?7@0BQqx_Ov+{.2սR7w5s?j?uwmNXhg]JKk5A7O¼<OImyh9;=+̖fIaNOAZ]{lT*^oo)32RʰUI8/on/2Yٹ>|re21 |M:U~mkڔ o azex5zsu?KX_ݱF+~$־E&uLU'vu)_m$PazqҮx_ {3Y]KcSӧTRD4kQwNrqҿ4"_Zi:i DG8f1Q,7TQČcWi9M_G9p15}@8waK'BF3oQWWJG^54ʅ<䯗^ݜ{t澠?t_8ZVO X.3O<6D~6uEiZXjp7=XbPh濴4■|ߥyk#k?h,S$cЀ8/reB: 洡׏́0z͝^,Jy[=v? -2ey}42`oNյ#šǍ-i~œ\*c=G@;i׋m}־m"UC_f_'%$YK0F=6?|4xs иUӵ~~̿Qiž7]=lfU)='0<Ҫݏ D4ɑU'R1!f.S$VG+?߇:rB,H<'NggŔ#=;W=JrGgW?NB#@=ksK^4<%K9Yqڿj|ORƍO9?W?_uxUI0@+ u:?8"gk 'KOYHʲop+Og*x~d8;J?NO7㯃~1Y Y6=J5|MOw U{yUx$UПป֮wr_a~kg)p086]WMsܻ,JG4)[$>`:edoڇKY,>LϹYsLTCs*l1.iNj\Q^WXۀrT.?io͘L]C‘]_\:&vsA~]1{ˉcj|of?gd0}U#?n͛ز*#s7fV agӽUV߉'D5kNMf ZjvS| &?\D>{,831j>.= 5 CYG[Y 0jdin?jikV`vWmkL1w{$}]GTf?'}͠gci/Jdf Fr担Wyq<_vvv9U%fȦ5=`3_LcX'>R?y#c[kr1ǮYGeaUnT?Lz+}Ir| Ƥ#ڏnwQK"nuRqPoD*񹖿)4\ezh23?3a{%ki|*sӊ[+fi;N.xlX^Mۈ[f/O mhteR~KFw&dž5E8W~ >"|= /r_#T^i|G.In.7wVYcez~ѥcL5)U`d=*GO_#4 ֫mk#|*¿-ҳ,q`q׽ 0Ϛu߆|wv>pe}*h=6S?fSc%}m5'%k^C2Cr:`_ߋho2kcwnW\$~'g-^;HC\CFS.oįОQ\J=- ߇~\#AB qTxZէ5-VH%]^9 &Tr8 |g|ijݥj89+a +P>:ί@l[s҃SKrڭðZ^_63q^{C? Nd7"Rp>Wmw#MVfePִPG8Mƽ5?웝H]nGrl[KL4n߅Y^21hD.4*B,3?b-/'mg,GJugQi#O?7W6k_ZTR-[n1xľ0_>4ԧIؓڿ_'ux;P .aMb6z` zokQ=6K;5PGn)T夵=a"~bv7,3Eߠk7p𵮫kG%˽f~ ~?/5QOϕqX5ti|w.|RGռ?VR ?3㯀_G-cNFү/e~+C6Ѥy0).:_sTSK3 {_&;2)B:Ͽ+U ύՒex~:;nyڿ? )4N} pR8+.9㟁"iP?Ý3pE~/-`$yV9דd>UE<ߵ_]&xrA }qh;~F!-V ,k)Cb+sǎOGv?va*(w呂炲8hWj G}++dcW5hd/U-/J5mkRK)W\:q_[m3⛛TbuyCO4i%FNS\xJ{:kk 5E1ǧ .aΏ,ZcץYVDdFz +kXƝIL\O+Ѿ |$heO2czR>.iY^(Gs^k?iυt ʤ `6M< 3O㯏G|--hL)~b0q߽+WV>#`׾~;|GnėP.dezzW#4N[ U0+?2Ў+7LS܇ P:i^ o0k!Egӏ Sr9lhxؿ<)FRG±OZ6QzWƷ7x ^93ދ6ؑ3nBv?*?lc]]N* H[h~"-M-7\\<¤IS֤:,uu{H/xSR柿$OnX3F~ 2 ՟W:]u$r ~hxhUhAm{ vBs0uU> j(ڪ"wڻ?|K6x:Ʃg4\e\ G;/a_ж_ V|]Qy(}q__gO©T2h }8*%$KifG[emՁ #OsiQ8 a.ǭz'+מ/]|lOָ,Ai;O•HZ+J+/NXSÍp3XU(ҹ|MMKZ͹?*xfJոݰ{.Gris@84$z`sVaX=rPJͺq+<_ -s~\[LT~JpI4Fmjrԏ T;NG?JR27#poҘ!G$ʣ0?1gduU=i3ϕUAa]SxS~,\c<휺VyF$#7a6c;A~6]xց“׊tn#4PO00+┒9UN?v4&$@1ҍR[mͺ)ۻ@})PGx,OZUxy95]mt>x47vo{qg 9= Tft`2QMSqOjj \NXӷj!Qmmb? Rz[:%~茶kΣJbu*Od{YnoӢVXb5 3sN^cecjJM++m WDgq2s}~-.olۙ;NъRzI"{y kώ:mR(tT+ [h<]p?|5" Wfx֯?>72+pG_x# Nv\D9 ?HU0f|B~ß>^Y9P;}+jS=2I=ҿx9=vsaHnriRNIX~ܿ eY` q|G0U\(5"en'V~?jGFve`{zb/?5mFyi-$C? +шc_ >16~˨[+&Evk~h3cō9x1+OmsF'\QѭL9U?,㵀bI!Bۨ|4g;F}+Dqi$ pXwbo_Z٦?zn<760h SӮkZ\]O>|/c/8cy7R9>g- S܍\"{~+miڇFF!,'>Xۂ.zWImsj<ʜ,о mK AQcҊjC#m|?|G,MHcҾ~9B ^}ȠY6}+e-/TbF#wܤZ?]?uV9S樓|"=3_ i6Z %qv W>O?fk_Z&xS6%)V=G=9Wo·;Oe!Qʨw%+*Vن*ٯ|mxC[cv'eih$"e}#ɮg崈4AA/CC֐jHQ'%XeXcڽ+7þ /.EUB6ӌ}1\w/Xڧvׂ>?.#RN5VF>͛ ]ΑmkXLe,〧=t~|#?fx*>/05)02l8_ KZ͹氩|}CC=,0Yd>P{_g|L* syQNuT҇r覧ß躕q* ޝ+jt◺@W;?= y۸9;Np}{➑GH؃1}GNzW߰ʹ>/Ԯ9ݾoOx=^|g`Ig8Tch]x4kHӢ#zHp1_wtN7-l)43ĒAW$P?NfG_}_J@tݚ>&ql?j)_j [jڌp,Hz]kz=#`mҿ__NڗW񿇭%VxYqjY4_#>!G Ɣ͵ۜkX |WAA$<zevsR4 czT{ڰ JKeF%jzTYRSIشTjsG]1^ MEU-M61E]PjVQjn1JX;P@6rz ?||;ƥ|~(m / x]V y}OJ3q YTWCQ#Pm>S<\W~>YzT\*? TMe HX䲌WkYߊihi#X <ՙQh d/cFK]6&pe`ƿ.dÚAw:)}k /IO7 pb|j>Xky`AF~5᩟EN* DJ/~"yĪ' GLWg6tZW#%BukJh- -1m"-G'q^uԼ1n4 4W X,aRGQډ8=Y,VkLlg/~ \ӥ8PwnA-Cb:1U6Jh:9,noxf_ $"WfcM7$ՑqN?cIh8?y -BdR^ xwb]Χ' [+iєݠ`HU#[H}s#6zoLrn@3vv- X`ƒXZџs/pq]}{BWU$A\61f4@+~˿/ "]ռwZ"YL;xAS+%Zilm${Wu8Oie\+sWJҼy+Ee/{cۚcn6x3_JUK.<[f RGVcL\2+ѿkƓF¥OnGA_O <\D qBeۻ;=7,D)GU%Q6{0 OC$6Fw1 j2e8z53D@poڿط O*x~$P;yHw(jεNT}CS?x!ݐ;Ӿk[/ צ+W)M¾9a(jGl|ݩx>[$HU01Y)>f/y;WYzqR|oh .|u~5$Pq ҳ~,_?@;62eUY&t~Xh 73 'n1+Yo.Tp=?:&,+D19tґNw"^/k۫UzV83r %~cd"A~`ּ#}>=OV%u KuWdO· pGbqvW#>Sl*:ӎԨTU64~COxXT־,>Ry,8鞸I'81xPNґ+HBӹZ{:+mksz.oJ/TKs Dy>vh< 0+k^[w_$WS,ǧ@k~ OEK+yP1,FrI-#xu8Ù]VH~'㺿! )q?> 5VѴ [ [ƪ =9x [hA᷅.:UҝYI3ba[Hrk!Evٴ_cac|ZH67RxWe/ٲ_v=[K"6 X W/ ot>'KQ,r@V5;q Zα~M("p9bL>}zs[>P~g9qqH$^܄yֿ?onr7ZuyqN\%ѱ%Rcߨ;i(9*H`UO1?q;}s_ 5`.1tOʸ[ֱmijǡ*g9=3> >0< 5~VBh΢QMcCF0$ja1VўA޿B|'|)=O ֝n;o1'v߽:E^x.}Ɋ=:tq58Z1V~_Z[+pˣ\" 򬟋WS^ia*OSJ Q[?[xe{But]~ПKxBTQ.푝GtJJ<}J^_H]5V/wuvf,ĒǦiC!Q#acq+Pr±F)\R\mcDݡc\E W}i<N)6)!RNf t vlV䕷dG eE^j̉iR7҃P[8 Ҭ'ݱҫt84ZVrȤ76y4ưh?ګҶWSq {UHRg}Ң֖:TDyN"\gAP՘.glv LuZ(¦3:SwESBs@`@)= #5'< 0I݊n=GߏAś< vßxM+`W'v~:*x66ym^錚eO/K2ם"I8d **hIIk-݉p=*;NL$8jo s#;8nuE;F6a^Gl/C-V ">Bm7cJ(~xm^̟8 =JZ]ZL]bpK`5&Sh Qþ59Xfe!N?+Ѽ[xM$ȣֿ/ړvFxZD-PvʀV?MWQҊ][018~1c$ϗ(u.^2~$KekOUd_՗?8"[;/%0gn\U>%xJƿťV&Ҁ7}pk T-*@>$hHJy}jop~!1GZ:h? ɮs,FXgdgoZ>!6YMIHό^7_94خܰVM=፩+/7<52}P¿/ٿSgGH>+ ŸdC2:Wo{~[h|v8(ќDžN*]N"g쿲mخH"݌~WL'Ծ7ax\8 nSi7 tRW60TSi?ivO^Z+6*=+S߈,q_GoOb"O>_퇭6THSSHX(>%&h]Gdt+K[X v~4< OKķ/JHz>_}/|; j2orOs0{Whš-}?~mjƣPJGj kX&3M4F\+> -CI2]g_)kh`ʬˀ2z Bq-\ڜ5XX'38(EcǛ (8`Gӎ|]e_ylc׏Z~h9'ڻj>ZXzܶy<_| `{UXcQ#$~w>+zlEJ2y}+smCYַnQ&yPM6~%w?~.|@Q9/n.-#-W9>&>#s; :~d#: _&۷'nDNs" ,laĸŝ܏a qy HR|c=+~HI>Ѧ~"|{WR^NCྲྀ^? Dbr==:W#\aT1g~(~&3 JvV}"cpLO~x>ċKr5diRzp>Q?BvwS/W5ߚwbF WLcυu_C+ ٠[[ym<t+_QM&!R}݇54K⋖D*'ӵX~߲oM~HuK^@XɅ~;*W|Y>ˏ~PqǨq` ;(瑀?^0|S. Ic6¿ڿ>|<#%WVaŹ_ߊ)kZniAh(7jo!۵@q. WtªNԂG/q/g~^%x|*)o|E<[n4I8Xӯ Kdclf5N8cڿ/  GD|d"ۊ~|[{H|(+&H9^xEyƁnej҆mҰ%x3U7$bG8>Aow5Qd9 p Q=+sߋ~>|5PJpZ'ↅ?>ir-݌oXm Zڪpzm {թ+ &=g=y vdGhðc|L&w]IJ5TvSWe)'YwRO;ǽ|mfa۵si:gcV#}sjΉ®Ր`zVC2@]x-cD#GLT[8#AxiHPMap*?:T.Y˓S%鸮|R">H(V|7vd-?5FvUkj5M߽Jv}W] ,j\v$\# yLTmK'}wVK,`2:bY^fA1J%x3I׷yY݀dt Xd0j5R*!/aPpBIo>˜( #*Yv,oP*@W*lr1M3G*qSfC֗iZ"2ZR]JmPO$cgV`uas;v--kdb4<֍{`݈k]ԞRl9 `WOYxjv.Us`vh_ +Қ:Ž1M,¾|f<3_~#T V\>^qU?Ba%J6?}<92|ͧ?_ƭf2 ._1|\h~]hP o'OjNp-k,hA#5wD:Y7P4o4~v[CUNM+L\?a?_R_ B~]|!_Sh">dR8 G#W?d?ض`lӑ_oƻJri:xod3/V үw^f>F:ݫzBɭK !K c=bNrס15])7(V8U}ǥ~^ \x#K QeBH=N=Nox>I}7%^߈6w~55+y3]X3-'9+_J>վ|W fB688՞d9+>FV1P|*ҿ~9aLn/o%jIs*K&{`G FWi=׊A|5~] QmR+B+k࿏;mݶsYJ9 SLcڥnv G$_|..5<=W~=;]-涒P%HTuGC=.BNkcϡBmY#FҵOE{ nJp3_~ GƓ0b >x<+wg i³u  ~(h&ֵ;đvnF凔_.=QkoF&/X7\F]?{6>2WN;?RC[q #[I;:}ly෴;k> ?A:ƻG,4]2Yl;v\ ǵz3d5Mxו#@ұmNҽ9Q{KG 4i5 vl2Tp:~Tw~/ 1Yf_>)E.eEbYgY#.qbOO]x,Inf///=YUMFRM}:߉=;9yr0z|[\%lPxM~CG$C&Tu猾xK{RҮ 1&De' b[ 3-V0q5>0%%`@{'3?+'xwGėLۓkg"jgSK][&FP<+r75k f!+"bGJp*w2z%tFV89xyG>#JĞ4~3L?JWky$ھO i:˫D<01h#{.i_[찎kFn,9˥)T|<={]#e%UWxvUzfcO$?ȞKF )D~^/iRt rה~YCf~|_t|bK|QqBg81ӟjqecF=r"NEqF>88MBj^DW@1#&mrH]ĭ{ư_OeQ.}G|jagyB~|R~/jOeĵHFA$qU>I(ST[_MɺY81<~F|P@yr+񗇾&_i.|w/i%=5_ '\+ ,g;[(|2iPPھdz7F{/xk jG Q2:vz|!,u vzv-\\+" P[F@;O9)M\&]Ic$':[n #Lzֻ[?+;18#Z0I&f%A8y Xʱ?^ _ʀ{%ߒO5?Ogʬ%O,k[<|"W˂ҷ? $.=xUmg"%1<b~2zQo!*R#[Qāא6 _.e6};sSh],~u2?b?jܨ}O]5fVp2$ #{j9uZXLKus⵰PJé[X,:|9:V̿^ULӝcb} Zf/|O]V.X_#'˸"/OJ&۶XqWM-, e6G:r6+,G:}v"B*B9]TD #+ ݴZ N:Wf"f̘Q:qPgW#o_y-Nhe!OCJd,nthEE$h+l*Wf)j+d-åʹ]L-mZy:(gy6Wqbn.viy|}Ijr^z ?OŞ&K2$OC(} s__O xYeյG=Xu?dEh~ȿIO|`o,:i iڭӦAν햯vy(oO_ӷ~;/o#`²eǥ|WA|9o<&# S+5ϸeM3h όk\TG=~'ďk#h/mf 8#El?i{ .S6F8Q_RtEkkrOQ=+}# ұ(b |OuxmVYUv 1,myic+5,T t.;㞕_H/ۛza5>~cK+b&gbzrDn@`;:~ع-s|>^nd%5-otLlQcR4&m4i" QNJ| L*A]>kvRGHTņG*vGC=:?fGExnr|Yv_~w$۟B_+,WƝ7';Ct(`qA/CImlcGB;Vbs)R~6Ix1܁Ed:_3nPTx<;'ޅI.F؎V% ӿ_w|G/ oี+pW~TU=9 n4%d_8ooK 7*j&毲l>? ٳkRMJL2w(,qxW]x|/O 5{˛ZF}UUJGF)%c'7 |=iYڤP*ʲ]kJӇtKK[.Hn> ϟHG; 2G*6|QBcɯcod1 P^@A&L 8{S+ M%-o?$/|y->\2.+/^־ ZAG+.2IA%tXmks?%5K,##WA~x+7p?wnX@;vdc8]kO_kKk6Dx9jGo$I@qg<<n=?쟡x" o}MEpp}_G;Nǎ4=6qqBW[ !?Itupe,3_Uf߅V.5/ʣw1oM)E\pIr6!~? uho5{Y8A/oM>xZUG ;W߷g񾙬R6DUX Ì8;OdįcՙS?SZ{$*QWV?ֿc_Zփ5Sh4sFr}ߧH_6_^H7#NN3=+"qbv|Uֶ{5ͤn1M's!9??s =2hT)-g5~ _xz[ī,XG+uǗvm<z⿤7|*.(c>>)C٣N2I3/&;W ՘*HH?!ԍΟn`"j#nAC㽧_Gg+Ll7)a88OOՏd*Kd`_ *pIhҾ"kZ~"I%U$W7xǥ}]{_|GuhI 9׎R![޵>BRпK[Jb+($v-Eݍk!WH54WR <kidHXۃ1-rѨg[3>ū4Tw} B_UkӭӰX׷=+W\h;όm#8\p@oF)7hc1?jbO2_M}ۅڼ{| CIB^־ac΋/=D| ccW_9ܛsm"#zjRO>jSxsǟ .u9Qe(#UgRW ϵGLJ_|c?.u R R>|UV6^N\9+6e Sg/mfFK6 !Ikw\I d*}Z_hM*KGC|5>#E|e[ k~2>5FA7 U >PhVkt';W/Z[NeʠKEhZs۱P_^G MSFq_8|;Ф`vTc;W`SrGun{fsbRz2@:\['bH F%2u Lzkc3ə 6d5hnqNtkDGݪȶҴ@>QNAӖb\OJfKs(װt#PshD|-(94nBnO,Ã#v F;tm&ylpBjCO=zTugQn>TBR-FpJC뻾k]#imoj$@L(C"aUfn n`R:|_/Zljo{clLRH@_ߖJ+4O#漇HnR<'Uy*Entڗ#8vEe+&rJ ~> i& ֎1} Ms2'i Q$hĠ1#İ韩bjMu\Br#0ǡ%~Z{_\ݱOO^ >Y?-Q5 F.x܎;|.@uTn\7 m !ذn+ώ ~t_*>[aA<.M Zұ)GM~6oLiZAN77o~O|#[K2B8xCKR}~$~DE&>*#,.&?bW\8,a*c,[y펕oiq ɣj[@6N6|8zJjQ(ڱ+\v⾵m??wiy1^WB6]'Ux81\ 0Ƽ5fĪ(&y1[V׳G?*NJ ib35M4f\ў0K_oC~[- #KvVsxzItMvWDjJ?s?n>?-* E)?_~>y<UQ\Jk Mi"u72y_N3T+j> L\>q^ n_ω^&^F=̠w Y5?khD[~v>W0|WU$A0{nUXXv%s{|!,s^_HNj-MgxcOUϺ:{br37ʤun|jI;j\+6+X1ZuU['qr$}_ kiI< W|)x`pPv }Wqo0{,ڬcϕu#y+u ]SV&qi2qA#+ c2ᒼ!%pTf@xSZ22W`ud%}9+@|g@{jݬ+{NW~mN]u=v>3}+wCtV7 1P$/׊tCD6=U;H.B$ũ[?WE<'%UcQv<|{s#k\z=+~o{Q>'|C'ܤ 0XWv=G^+:i/ j ؅%J#vGZΧ5?+ u_+#8S̯ۣ :|9,t9~t;}+_ |\ Ҿ$q$>ʿ3?~g={CJ ?*W vYYJvAt_*e9S.v ֫Sg_?o_asǍQvď+5 N 77٦x)|5>yHM?ho%q;}͐O+~-ī$׵9 CW ަ}0̨gv|/uƟX\c ejm WOcG̬9A=*%+j5dbiVZ-YDU@;k}QR"OYHSXvszbwmibAۑ=:Tw/EM{ UO5M~¸3xI%8N1Ui.Wڢߙ6ļPs]ë.ĉsQ1mHj a#;H#YPmNU<dyHW۵b#)n2Dc(? )1LqǚFtqtP,ۏ,g~ |ZֵY- $m$>ZnX~}jη49ճj@9aV\38ïz= c 㱦y~V^A} P6{:*BK ᜚?t{U$8RxV5VV lc -s~ጲIv,"oE ,PJbլcR(4c)Vww^L'n{]+ᤪQXOIt!b(E5 mx?;w")㹷Ws%{1[Uؿ]OĶs'OL|EK~+Y>|+f!:?T3o~cr@kྃR<ٯbr@cO_]ive0MЎ+l+ZM3<3gk~v{emGh(:J4o1bz-R$ʥ"TOs14v*Z\KC)agWHnUjiM|Jc}+χoф^;vwٸ_Z4>UKEnYZ҈񎞵V5b01]mEN8E-Vnkc 4d䕏~?궳ZxvŗG'5Żyog|T?Ľϯi-#mLW_a'Foƽ2OjPeGo[Y܀G_n:f}km"١˺.Tq_oW6].>oJo/Y~gcb2 /I\0G8ivNF@ +fZPiۈe]+(\D+?YTkFhc+٘srkO'XegXis`xgu@v v]x˒E˫ 8_ܿ?]ڣ MW?S/l#RdBБ+ϧJIb67Ho|K e>_XUm|{_Eseo4D-n`8뎵;5k&'[n`\T.ܞ#H;<|Dm5j:}͖\3ڽ8ֺJn3GI=7<ŢinTC_Gok^.r^ZF:?E|S{k$Y+{KĞu~;Ыc׵9UIX+f4pQT}sN=ʛr3_g}`~^-`᳍r st|~J<\bf k!}JJ˓@$@BVg+<{xǟ 4ω֋*FϏf.>Q]]$Ma+Ŧk?اeV¶44F_6|:>7^ю ̭r;I^0+ jiwZT (-h\ݺm:8O)~9 s#zڒL/RIJNk>0 S5e.x gOe9ee@f5o#o=3c]˓bضvvᔫ>V cWGsЩR\"?h 7xB#azBZg_^\$M0l_{ߎ)}r.W~z{`vVÚ'F*қn|}z|?~ w5ζW:K{%.zkk e7«o(2=[aK*d54=ͫÂf?-|>SJl"vgGOW>$>_#P6$t?|t=x᭘G&+_LzWߵ??|9?z?n%6cl_ /4) @X֒lo"c&Z߆d"$O{~&g,3su }wx @aQq;}/0|+9~c;}OtU}:D TOR]IYXL`"A"GCU7ޕ2H[2%dVgմhD,![F)h IBWⴭg6.;#Ұ=i[1GITuib]@8-#~o%i&Yt#ڿEd#A&68#Ҿh7ڰB0;Ua}v[@u/'T㌲6+B)ngӵ` ? R3GN=z| kO0eAϦ;Wq㕒6W:Gqk$reedyM׈f+PeV9Ҽ\>2I ǩ:kK[fb:S4if]]Y n\ kte,#`\6쌊x49Lg(G,m$z4(&Y Qm&p=+~ úLکF=¾]kq;Mi Q*مֈYk ~^;@-.BЯN:qҿ{1ɨ^#9JY.5Kj2]™d9lW QAo+Wl\Ff2+(˱>8׻l8 %d:Gᾛ>HGUFK18 Ҽ^Yj*Zǎgk]J ~ tB(ES>1k'_ |G/poW~̿7i/Z"Es66ý%Nk}g\im&ԀaoWW4 xKMx[r:ӡgr&eOSiIS}ŒrRLdcھlaC;H(\vN?k? |D?6ѵsU? RQYUs^K愵8+!Z#Sm-#\&~~?ي/U$+>s[GcߧA^``!?TGUΓ>!Ƅ3LOKMݒn1^Q^~u Ԧ Kk0F{W׌m} kA5H+c_B?K.9y~P`n^q:NCjfg{ %8sd#۾8|g?\i¼c6V^TgzPji$ѧ,O"(.9o'./ɧ]̈U:/{I|1n^Fό/A|5?^ԭWwNz?~/x[UKao$Wڋ?{t@0[qB>3^Z~Յ(Os_(|p>9|0Eַf%,?cihHڿQ~|ZuQ|2[H"Khw4VV{>v|Jwo>:QʦpOLb)Е KI#P|q^7L:q 2~UzO:c蚟&ʰuo#ψ %EP8jR|k|"acӥwө͹*S^?}{֠xͻK\_OCarʥp7jد fh ~%٤ V^'O^+}?g?xbl!% ;JL9di4> W χn?xTX2n[*+v_O-}C(|OEpʰj~AheaUUvkyKPP>-|@WƟ׋jw1 pQ_7Sf+B&FC o~k~ Wo][ۺNFF~rM flHg}PkRPmZatꚥ>ޕ. Jv>潣J+/_N+(Mo7&<0;YK3̯:Hgk1Fm<>uRTW1ׅitkr47~\LRvqǕ2LggY2`y|?0.#觅K|AI*1l%#| c_ >%g$zǦk/#mT<+> Nc,3[n@#[YHgWeW ^R\ɝ |CWdv-yxvx&ͭvq_קKEemBͰ6pV,-k0BWOWPp?9A]TQ琺`mz<D>m]]Oʏ+6[Oּmjw~GJ UT Yҫ݈!eu גxk[K *[)ԅ8 4}-Y<ֺ`UY=~^|Ԗq:dddVG35cH8 >Z{YG_s~o4pLcI_ Z[)ieEd+tf|!x\þ{ɾq+ I\(װtq_ҏG ßu i^U Wr<oD7E;UYMU~?[Tunw?|Qt9bIgUWjVE0*;7?W(l!]n8L#q'lGt(`dXeheI>~U0r!m8=f5]KN/֓eL0Gd|(: j8#ֱ>Sٳb6WZzvdM-KFY;{J IexTBM~jkS_ggEw)u$mO+M~gG voCK ۹m6[km[5vɖW@+k 3X?򢈕{_Fىq6qۭu;KG*8l(U" 95aB>A~|gD>e=}@:wO[Ij6rvҬ1+u|,I)lq7>]R^xYW+#wkXacvZF0:Xec,$tgm|BmVWL%*A:2֦:L)ĵLH5V8.e7iA&}Ҿcc_ ǼW>o|dhvÈ[qNkW*Z&ՙx#o_B3}"1wҿwf$߂.c;v$i[\!K J^͞&*Tܔzc?sw&=vi!BFWAmw)>ՌSh7NLg;G>ޕKZ)-TLp5BZ:QLUZ&{qWrG<:QG+\O:Sk~2'do(碨O6#е]7Dԃ,)y j&MXHbo<;{bd_ӥMTi]4R?T|.ZAaW?5Iu ٟ\WzN>FUyq6J_?hpqfoecKGע39%$s_d[Dy0<9a;UGE Ğk;9#s\j5+X|!l°--v;gK71R'i ؆Su=o*q8||?FPeoUXx_Ri4kMI;?#5x5Ye OڄhE8 ~V_6ߏZi"?Od-:?|5׼Mn+Lj >0OAqwuSbB{W'>x@s״~XYVZU.ᶹծO|򝪪}+|9xI‘\Ƿ]?eiF&b-tm'D#k:{os%-}tU5݆8\AҿM?loئOtC~Sģ`1v濝]WQc:3<#;Y~WW|INj m &%dVԑG&>:ɪ=,ik eC+2A'hz a締̏ۻ_9ZBda (K!TrOʯ+Ɵ|B>+io̤0n1:cWTCh^^WWndrǭsOs*]vsieΣ&mZx쾥lp ?W,7(JCg?{-8?z&}>!?tnCp;Bp+u+OپoJe'?6ץ}5Ve!_)~cנॷ36+ziוuG~?V(GNUݮC]HKאFSG|GعA: tr!~Кc0zOէ"5۔1_  <7A?G|;ؗ[:w~Wp t_g[XYiW?.![h}E>|M&w"~hUQG~;W~~ gתO/&َk'y(#W^.m?i}$vs!B+_5{k$-˘}Xnٟ_-E3h?ݯğ&&]bKU^Oֿjw9. Go#!ٕ)&Ghf/vz~l L݋>H6’9+,JkwwD6r|݂W5Y';1?k~^SXHstiQf> t^7(BgA}ؼ/ Wxu{_O`+C kZFr(V?J™cpЦV$ >B>Ъs,>!QX\te1t_;qww_kkۿթzk*r<*Xg5]mX*>H|he➷,'R[_SvEl6#2>,K\$q=QgpJǗ,.0G8YB1.nXʿAbDMgTF<l{ß,mT.1On| |,L4i$^Gێ澂-kEJ²(+#|8껤&ⱲoZh+TW:ԠK!yH.C-=2ȡ%珔ӃRX~VOxĺ-n>:; Ma~)Op,|g#?v_ -1ZP~x¿?ഷWZUyd?I#sR2Ȫgts#d( 㠮A%5@=+4M_PՊ2=#*??#gfc\˸Ҿlڷ> +'Ǩ=ƒ~N>,O/GA,_gziZ5۾-.'A*3ֿ?z?ԧѾh<ݳ__X> >ǦZx>uqxqأ9Ӡ8NcW%A-ՖF" Z (ůjEדL˖<ٻPO HcӠϗn"jΜW*+)Œ9>-.wM@q g)dH#%7e>zWmo ;័ʬj-6_o>!xO/keRhTD;.GZ5~4Dt$e+ӚrA\W 윧C#d[ txDjo5A9Wͥ¿d?ww>4lWV+|}BF.IhםVNf9l*Ummfgtools-uuu_1.5.182/webusb/src/index.css000066400000000000000000000005561462141313700203270ustar00rootroot00000000000000body { margin: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } code { font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace; } mfgtools-uuu_1.5.182/webusb/src/index.js000066400000000000000000000010271462141313700201450ustar00rootroot00000000000000import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css'; import App from './App'; import reportWebVitals from './reportWebVitals'; const root = ReactDOM.createRoot(document.getElementById('root')); root.render( ); // If you want to start measuring performance in your app, pass a function // to log results (for example: reportWebVitals(console.log)) // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals reportWebVitals(); mfgtools-uuu_1.5.182/webusb/src/logic/000077500000000000000000000000001462141313700175755ustar00rootroot00000000000000mfgtools-uuu_1.5.182/webusb/src/logic/useHIDBoot.js000066400000000000000000000076141462141313700221100ustar00rootroot00000000000000/* * Copyright 2023 NXP. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * Neither the name of the NXP Semiconductor nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ import {useEffect, useState} from 'react'; const HIDrequestParams = { filters: [{ vendorId: 8137, productId: 303 }] }; const outputReportId = 0x02; const useHIDBoot = (bootFile) => { const [HIDdevice, setHIDdevice] = useState(); const [bootProgress, setBootProgress] = useState(0); const [bootTotal, setBootTotal] = useState(0); useEffect(()=> { navigator.hid.addEventListener("connect", handleConnectedDevice); navigator.hid.addEventListener("disconnect", handleDisconnectedDevice); }, []) useEffect(() => { const downloadBoot = async() => { if (!HIDdevice) return; await HIDdevice.open(); console.log("Opened device: " + HIDdevice.productName); HIDdevice.addEventListener("inputreport", handleInputReport); doUBoot(); } downloadBoot(); }, [HIDdevice]) const handleConnectedDevice = (e) => { console.log("Device connected: " + e.device.productName); } const handleDisconnectedDevice = (e) => { console.log("Device disconnected: " + e.device.productName); } const handleInputReport = (e) => { console.log(e.device.productName + ": got input report " + e.reportId); console.log(new Uint8Array(e.data.buffer)); } const requestHIDDevice = async() => { const devices = await navigator.hid.requestDevice(HIDrequestParams); if (devices.length === 0) return; setHIDdevice(devices[0]); } const doUBoot = async() => { console.log("trying to boot..."); if (!bootFile) {console.log("choose a file"); return 0;} const imageByteLength = bootFile.size; console.log(bootFile) // 1313792 setBootTotal(imageByteLength); setBootProgress(0); console.log(await bootFile.arrayBuffer()) for (let i=0; 1024*i imageByteLength) len = imageByteLength-1024*i; else len = 1024; const packet = await bootFile.slice(1024*i, 1024*i+len).arrayBuffer(); await HIDdevice.sendReport(outputReportId, packet) setBootProgress((1024*i + len)); console.log(1024*i + len) } } return [{ requestHIDDevice: requestHIDDevice, HIDdevice: HIDdevice, bootProgress, bootTotal, }] } export default useHIDBoot; mfgtools-uuu_1.5.182/webusb/src/logic/usePopup.js000066400000000000000000000040261462141313700217550ustar00rootroot00000000000000/* * Copyright 2023 NXP. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * Neither the name of the NXP Semiconductor nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ import {useState} from 'react'; const usePopup = ({bootFile, flashFile}) => { const [error, setError] = useState(); const [show, setShow] = useState(false); const showPopup = () => { if (flashFile == null || bootFile == null) { setError("Please choose flash files") } else { setError(""); setShow(true); } } const closePopup = () => { setShow(false); } return [{ showPopup, closePopup, show, error, }] } export default usePopupmfgtools-uuu_1.5.182/webusb/src/logic/usePopupContent.js000066400000000000000000000040441462141313700233100ustar00rootroot00000000000000/* * Copyright 2023 NXP. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * Neither the name of the NXP Semiconductor nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ import {useState} from 'react'; const usePopupContent = ({bootFile, flashFile}) => { const [error, setError] = useState(); const [show, setShow] = useState(false); const showPopup = () => { if (flashFile == null || bootFile == null) { setError("Please choose flash files") } else { setError(""); setShow(true); } } const closePopup = () => { setShow(false); } return [{ showPopup, closePopup, show, error, }] } export default usePopupContentmfgtools-uuu_1.5.182/webusb/src/logic/useUSBFlash.js000066400000000000000000000151021462141313700222560ustar00rootroot00000000000000/* * Copyright 2023 NXP. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * Neither the name of the NXP Semiconductor nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ import {useEffect, useState} from 'react'; import {str_to_arr, ab_to_str} from '../helper/functions.js' import {CHUNK_SZ, BLK_SZ, CHUNK_TYPE_RAW, CHUNK_TYPE_DONT_CARE, build_sparse_header, build_chunk_header} from '../helper/sparse.js' const USBrequestParams = { filters: [{ vendorId: 8137, productId: 0x0152 }] }; const useUSBFlash = (flashFile) => { const [USBDevice, setUSBDevice] = useState(); const [flashProgress, setFlashProgress] = useState(); const [flashTotal, setFlashTotal] = useState(); useEffect (()=> { const downloadFlash = async() => { if (!USBDevice) return; try { await USBDevice.open(); console.log(`Opened USB Device: ${USBDevice.productName}`); } catch (err) { console.log(err); } doFlash(); } downloadFlash(); }, [USBDevice]) const requestUSBDevice = async() => { try { const device = await navigator.usb.requestDevice(USBrequestParams); setUSBDevice(device); } catch (err) { console.error(`There is no device. ${err}`); } } async function preBoot () { await USBDevice.claimInterface(0); await send_data(str_to_arr("UCmd:setenv fastboot_dev mmc"), "OKAY"); await send_data(str_to_arr("UCmd:setenv mmcdev ${emmc_dev}"), "OKAY"); await send_data(str_to_arr("UCmd:mmc dev ${emmc_dev}"), "OKAY"); console.log("preboot complete") } const doFlash = async () => { // downloads and splits image into chunks to be processed const PACKET_SZ = 0x10000; const DATA_SZ = CHUNK_SZ * BLK_SZ; // in bytes if (flashFile===null) {return;} await preBoot(); setFlashTotal(flashFile.size); setFlashProgress(0); let offset = 0; let chunk_end = 0; let i = 0; let chunk_len = 0; let packet_len = 0; let reader = new FileReader(); reader.onerror = (evt) => { console.log(evt.target.error); } reader.onload = async (evt) => { let raw_data = evt.target.result; await USBDevice.transferOut(1, raw_data); setFlashProgress(offset); if (offset < chunk_end) { readNextPacket(); } else { // reached end of a chunk // pad with zeros if (packet_len !== PACKET_SZ) { let fill_len = (Math.ceil(packet_len/BLK_SZ)*BLK_SZ - packet_len) let fill = new Uint8Array(fill_len); await USBDevice.transferOut(1, fill); } let result = await USBDevice.transferIn(1, 1048); if ("OKAY" !== await ab_to_str(result.data.buffer)) { throw new Error ("failed to send data:", ab_to_str(result.data.buffer)) } await flash_all(); readNextChunk(); } }; function readNextPacket() { packet_len = Math.min(PACKET_SZ, flashFile.size-offset); let slice = flashFile.slice(offset, offset + packet_len); reader.readAsArrayBuffer(slice); offset += packet_len; } async function readNextChunk() { if (offset !== flashFile.size) { chunk_len = Math.min(DATA_SZ, flashFile.size-offset); chunk_end = Math.min(offset + DATA_SZ, flashFile.size); // rounds chunk len up to nearest block: let write_chunk_len = Math.ceil(chunk_len/BLK_SZ)*BLK_SZ; let hex_len = (write_chunk_len + 52).toString(16); await send_data(str_to_arr(`download:${hex_len}`), `DATA${hex_len}`); await send_headers(write_chunk_len, i); readNextPacket(); i++; } } readNextChunk(); } async function send_headers(raw_data_bytelength, i) { let sparse = build_sparse_header(raw_data_bytelength, i); let dont_care = build_chunk_header(CHUNK_TYPE_DONT_CARE, raw_data_bytelength, i); let raw = build_chunk_header(CHUNK_TYPE_RAW, raw_data_bytelength, i); let headers = new Uint8Array(52); headers.set(sparse, 0); headers.set(dont_care, 28); headers.set(raw, 40); await USBDevice.transferOut(1, headers); } /* * data: string or arraybuffer * success_str: checks response of usb * Throws error if USB input does not match success_str */ async function send_data(data, success_str) { await USBDevice.transferOut(1, data); let result = await USBDevice.transferIn(1, 1048); if (success_str !== ab_to_str(result.data.buffer)) { throw new Error ("failed to send data:", ab_to_str(result.data.buffer)) } } async function flash_all () { await send_data(str_to_arr("flash:all"), "OKAY"); } return [{ requestUSBDevice, USBDevice, flashProgress, flashTotal }] } export default useUSBFlash; mfgtools-uuu_1.5.182/webusb/src/reportWebVitals.js000066400000000000000000000005521462141313700221740ustar00rootroot00000000000000const reportWebVitals = onPerfEntry => { if (onPerfEntry && onPerfEntry instanceof Function) { import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { getCLS(onPerfEntry); getFID(onPerfEntry); getFCP(onPerfEntry); getLCP(onPerfEntry); getTTFB(onPerfEntry); }); } }; export default reportWebVitals; mfgtools-uuu_1.5.182/webusb/src/setupTests.js000066400000000000000000000003611462141313700212210ustar00rootroot00000000000000// jest-dom adds custom jest matchers for asserting on DOM nodes. // allows you to do things like: // expect(element).toHaveTextContent(/react/i) // learn more: https://github.com/testing-library/jest-dom import '@testing-library/jest-dom'; mfgtools-uuu_1.5.182/zlib/000077500000000000000000000000001462141313700153625ustar00rootroot00000000000000mfgtools-uuu_1.5.182/zstd/000077500000000000000000000000001462141313700154065ustar00rootroot00000000000000