Import mfgtools_1.4.77.orig.tar.gz
authorHenry-Nicolas Tourneur <debian@nilux.be>
Mon, 25 Jan 2021 17:38:40 +0000 (17:38 +0000)
committerHenry-Nicolas Tourneur <debian@nilux.be>
Mon, 25 Jan 2021 17:38:40 +0000 (17:38 +0000)
[dgit import orig mfgtools_1.4.77.orig.tar.gz]

76 files changed:
.gitignore [new file with mode: 0644]
.gitmodules [new file with mode: 0644]
.travis.yml [new file with mode: 0644]
CMakeLists.txt [new file with mode: 0644]
Doxyfile.in [new file with mode: 0644]
LICENSE [new file with mode: 0644]
README.md [new file with mode: 0644]
appveyor.yml [new file with mode: 0644]
libuuu/CMakeLists.txt [new file with mode: 0644]
libuuu/backfile.h [new file with mode: 0644]
libuuu/buffer.cpp [new file with mode: 0644]
libuuu/buffer.h [new file with mode: 0644]
libuuu/cmd.cpp [new file with mode: 0644]
libuuu/cmd.h [new file with mode: 0644]
libuuu/config.cpp [new file with mode: 0644]
libuuu/config.h [new file with mode: 0644]
libuuu/error.cpp [new file with mode: 0644]
libuuu/fastboot.cpp [new file with mode: 0644]
libuuu/fastboot.h [new file with mode: 0644]
libuuu/fat.cpp [new file with mode: 0644]
libuuu/fat.h [new file with mode: 0644]
libuuu/ffu_format.h [new file with mode: 0644]
libuuu/gen_ver.sh [new file with mode: 0755]
libuuu/hidreport.cpp [new file with mode: 0644]
libuuu/hidreport.h [new file with mode: 0644]
libuuu/http.cpp [new file with mode: 0644]
libuuu/http.h [new file with mode: 0644]
libuuu/libcomm.h [new file with mode: 0644]
libuuu/liberror.h [new file with mode: 0644]
libuuu/libuuu.h [new file with mode: 0644]
libuuu/notify.cpp [new file with mode: 0644]
libuuu/rominfo.cpp [new file with mode: 0644]
libuuu/rominfo.h [new file with mode: 0644]
libuuu/sdp.cpp [new file with mode: 0644]
libuuu/sdp.h [new file with mode: 0644]
libuuu/sdps.cpp [new file with mode: 0644]
libuuu/sdps.h [new file with mode: 0644]
libuuu/sparse.cpp [new file with mode: 0644]
libuuu/sparse.h [new file with mode: 0644]
libuuu/sparse_format.h [new file with mode: 0644]
libuuu/tar.cpp [new file with mode: 0644]
libuuu/tar.h [new file with mode: 0644]
libuuu/trans.cpp [new file with mode: 0644]
libuuu/trans.h [new file with mode: 0644]
libuuu/usbhotplug.cpp [new file with mode: 0644]
libuuu/version.cpp [new file with mode: 0644]
libuuu/zip.cpp [new file with mode: 0644]
libuuu/zip.h [new file with mode: 0644]
msvc/bzip2.vcxproj [new file with mode: 0644]
msvc/bzip2.vcxproj.filters [new file with mode: 0644]
msvc/createversion.bat [new file with mode: 0644]
msvc/libuuu.filters [new file with mode: 0644]
msvc/libuuu.vcxproj [new file with mode: 0644]
msvc/libuuu.vcxproj.filters [new file with mode: 0644]
msvc/uuu-static-link.sln [new file with mode: 0644]
msvc/uuu-static-link.vcxproj [new file with mode: 0644]
msvc/uuu.sln [new file with mode: 0644]
msvc/uuu.vcxproj [new file with mode: 0644]
msvc/uuu.vcxproj.filters [new file with mode: 0644]
msvc/zlib.vcxproj [new file with mode: 0644]
msvc/zlib.vcxproj.filters [new file with mode: 0644]
uuu/CMakeLists.txt [new file with mode: 0644]
uuu/autocomplete.cpp [new file with mode: 0644]
uuu/buildincmd.cpp [new file with mode: 0644]
uuu/buildincmd.h [new file with mode: 0644]
uuu/emmc_burn_all.lst [new file with mode: 0644]
uuu/emmc_burn_loader.lst [new file with mode: 0644]
uuu/fat_write.lst [new file with mode: 0644]
uuu/gen_txt_include.sh [new file with mode: 0755]
uuu/nand_burn_loader.lst [new file with mode: 0644]
uuu/qspi_burn_loader.lst [new file with mode: 0644]
uuu/sd_burn_all.lst [new file with mode: 0644]
uuu/sd_burn_loader.lst [new file with mode: 0644]
uuu/spl_boot.lst [new file with mode: 0644]
uuu/uuu.cpp [new file with mode: 0644]
uuu/uuu.lst [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..cefd895
--- /dev/null
@@ -0,0 +1,14 @@
+Debug
+Release
+gitversion.h
+*.user
+.vs
+CMakeFiles
+*.cmake
+*.swp
+*.a
+*.so
+uuu/uuu
+Makefile
+CMakeCache.txt
+*.clst
diff --git a/.gitmodules b/.gitmodules
new file mode 100644 (file)
index 0000000..b7eb42d
--- /dev/null
@@ -0,0 +1,9 @@
+[submodule "libusb"]
+       path = libusb
+       url = https://github.com/nxpfrankli/libusb.git
+[submodule "zlib"]
+       path = zlib
+       url = https://github.com/madler/zlib.git
+[submodule "bzip2"]
+       path = bzip2
+       url = git://sourceware.org/git/bzip2.git
diff --git a/.travis.yml b/.travis.yml
new file mode 100644 (file)
index 0000000..9138aff
--- /dev/null
@@ -0,0 +1,41 @@
+language: 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
+            - libzip
+            - openssl
+            - pkg-config
+
+script:
+    - cmake -DOPENSSL_ROOT_DIR=$(brew --prefix)/opt/openssl . && make
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644 (file)
index 0000000..a9317a3
--- /dev/null
@@ -0,0 +1,33 @@
+cmake_minimum_required(VERSION 3.12)
+
+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)
diff --git a/Doxyfile.in b/Doxyfile.in
new file mode 100644 (file)
index 0000000..f925937
--- /dev/null
@@ -0,0 +1,17 @@
+PROJECT_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
diff --git a/LICENSE b/LICENSE
new file mode 100644 (file)
index 0000000..2092934
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright 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.
+
+
diff --git a/README.md b/README.md
new file mode 100644 (file)
index 0000000..1e1096b
--- /dev/null
+++ b/README.md
@@ -0,0 +1,92 @@
+# uuu (Universal Update Utility), mfgtools 3.0
+
+[![Build status](https://ci.appveyor.com/api/projects/status/github/NXPmicro/mfgtools?svg=true)](https://ci.appveyor.com/project/nxpfrankli/mfgtools-kvqcg)
+[![Build Status](https://travis-ci.com/NXPmicro/mfgtools.svg?branch=master)](https://travis-ci.com/NXPmicro/mfgtools)
+
+![GitHub](https://img.shields.io/github/license/NXPmicro/mfgtools.svg)
+
+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 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/  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 attachement 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 u-boot.imx sdcard.bz2\*
+                            decompress sdcard.bz2 file and download the whole image into emmc
+```
+
+# Prebuilt Image and pdf document
+
+The prebuilt image and document are here:
+  - https://github.com/NXPmicro/mfgtools/releases
+  - UUU.pdf is snapshot of [wiki](https://github.com/NXPmicro/mfgtools/wiki)
+
+# How to Build:
+
+## Windows
+- `git clone https://github.com/NXPmicro/mfgtools.git`
+- `cd mfgtools`
+- `git submodule init`
+- `git submodule update`
+- `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/NXPmicro/mfgtools.git`
+- `cd mfgtools`
+- `sudo apt-get install libusb-1.0-0-dev libzip-dev libbz2-dev pkg-config cmake libssl-dev g++`
+- `cmake . && make`
+
+## macOS
+- `git clone https://github.com/NXPmicro/mfgtools.git`
+- `cd mfgtools`
+- `brew install cmake libusb libzip openssl pkg-config`
+- `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.
+
+# 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
diff --git a/appveyor.yml b/appveyor.yml
new file mode 100644 (file)
index 0000000..d0032b3
--- /dev/null
@@ -0,0 +1,120 @@
+version: 1.4.{build}
+image:
+- Visual Studio 2019
+- Visual Studio 2017
+- Ubuntu1604
+
+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: sudo apt-get update
+
+- sh: sudo DEBIAN_FRONTEND=noninteractive apt-get  --yes --force-yes install libusb-1.0-0-dev
+
+- sh: sudo DEBIAN_FRONTEND=noninteractive apt-get --yes --force-yes install libzip-dev
+
+- sh: sudo DEBIAN_FRONTEND=noninteractive apt-get --yes --force-yes install libbz2-dev
+    
+- sh: sudo DEBIAN_FRONTEND=noninteractive apt-get --yes --force-yes install asciidoc
+    
+- sh: sudo DEBIAN_FRONTEND=noninteractive apt-get --yes --force-yes install rename
+
+build_script:
+
+# below powershell actions equals to retarget projects to newest SDK and tool v142 in visual studio 2019
+- ps: If($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2019")  {(gc msvc\uuu.vcxproj) -replace '141', '142' | Out-File -encoding ASCII msvc\uuu.vcxproj}
+- ps: If($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2019")  {(gc msvc\uuu.vcxproj) -replace '10.0.16299.0', '10.0' | Out-File -encoding ASCII msvc\uuu.vcxproj}
+- ps: If($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2019")  {(gc msvc\bzip2.vcxproj) -replace '141', '142' | Out-File -encoding ASCII msvc\bzip2.vcxproj}
+- ps: If($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2019")  {(gc msvc\bzip2.vcxproj) -replace '10.0.16299.0', '10.0' | Out-File -encoding ASCII msvc\bzip2.vcxproj}
+- ps: If($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2019")  {(gc msvc\libuuu.vcxproj) -replace '141', '142' | Out-File -encoding ASCII msvc\libuuu.vcxproj}
+- ps: If($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2019")  {(gc msvc\libuuu.vcxproj) -replace '10.0.16299.0', '10.0' | Out-File -encoding ASCII msvc\libuuu.vcxproj}
+- ps: If($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2019")  {(gc msvc\zlib.vcxproj) -replace '141', '142' | Out-File -encoding ASCII msvc\zlib.vcxproj}
+- ps: If($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2019")  {(gc msvc\zlib.vcxproj) -replace '10.0.16299.0', '10.0' | Out-File -encoding ASCII msvc\zlib.vcxproj}
+- ps: If($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2019")  {(gc libusb\msvc\libusb_dll_2017.vcxproj) -replace '10.0.16299.0', '10.0' | Out-File -encoding ASCII libusb\msvc\libusb_dll_2017.vcxproj}
+- ps: If($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2019")  {(gc libusb\msvc\libusb_dll_2017.vcxproj) -replace '141', '142' | Out-File -encoding ASCII libusb\msvc\libusb_dll_2017.vcxproj}
+- ps: If($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2019")  {(gc msvc\uuu-static-link.vcxproj) -replace '141', '142' | Out-File -encoding ASCII msvc\uuu-static-link.vcxproj}
+- ps: If($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2019")  {(gc msvc\uuu-static-link.vcxproj) -replace '10.0.16299.0', '10.0' | Out-File -encoding ASCII msvc\uuu-static-link.vcxproj}
+- ps: If($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2019")  {(gc libusb\msvc\libusb_static_2017.vcxproj) -replace '10.0.16299.0', '10.0' | Out-File -encoding ASCII libusb\msvc\libusb_static_2017.vcxproj}
+- ps: If($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2019")  {(gc libusb\msvc\libusb_static_2017.vcxproj) -replace '141', '142' | Out-File -encoding ASCII libusb\msvc\libusb_static_2017.vcxproj}
+
+
+- cmd: if "%APPVEYOR_BUILD_WORKER_IMAGE%" == "Visual Studio 2019" (msbuild %APPVEYOR_BUILD_FOLDER%/msvc/uuu.sln /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 /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 /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: cmake -D 'STATIC=1' .
+- sh: make
+
+- sh: git submodule init
+- sh: git submodule update
+- sh: git archive --prefix "uuu-${APPVEYOR_BUILD_VERSION}/" -o "uuu_source-${APPVEYOR_BUILD_VERSION}.tar" HEAD
+- sh: 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"
+- sh: mkdir uuu-${APPVEYOR_BUILD_VERSION}; git describe --tags --long >uuu-${APPVEYOR_BUILD_VERSION}/.tarball-version
+- sh: tar -r uuu-${APPVEYOR_BUILD_VERSION}/.tarball-version -f uuu_source-${APPVEYOR_BUILD_VERSION}.tar
+- sh: gzip uuu_source-${APPVEYOR_BUILD_VERSION}.tar
+- sh: 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)
+
+- sh: git clone https://github.com/NXPmicro/mfgtools.wiki.git
+    
+- sh: cd mfgtools.wiki
+    
+- sh: rename -f 's/\.asciidoc$//' *
+    
+- sh: echo "<revhistory>" > UUU-docinfo.xml
+    
+- sh: git log -n25 --reverse --format="format:<revision><revnumber>%h</revnumber><date>%cd</date><authorinitials>%an</authorinitials><revremark>%s</revremark></revision>" >> UUU-docinfo.xml
+    
+- sh: echo "</revhistory>" >> UUU-docinfo.xml
+    
+- sh: a2x -L -a docinfo UUU
+    
+artifacts:
+- path: uuu.exe
+- path: uuu/uuu
+- 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;  libusb-1.0.dll; uuu/uuu; mfgtools.wiki/UUU.pdf; uuu_source-${APPVEYOR_BUILD_VERSION}.tar.gz; uuu_source-${APPVEYOR_BUILD_VERSION}.zip
+  draft: true
+
+environment:
+  coverity_token:
+    secure: 5VvyV4fYfI6xPsqaeDHvBamkUmmVNjZj0J5pLLQ6NCw=
diff --git a/libuuu/CMakeLists.txt b/libuuu/CMakeLists.txt
new file mode 100644 (file)
index 0000000..1f68418
--- /dev/null
@@ -0,0 +1,65 @@
+cmake_minimum_required(VERSION 3.12)
+
+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(LIBZIP REQUIRED libzip)
+find_package(Threads)
+
+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} ${UUUOPENSLL_INCLUDE_DIR} include)
+
+
+set(CMAKE_CXX_FLAGS_DEBUG "-g -Wall -Wstrict-aliasing -Wextra ${UUUSSL}")
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 ${UUUSSL}")
+
+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
+)
+
+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} )
diff --git a/libuuu/backfile.h b/libuuu/backfile.h
new file mode 100644 (file)
index 0000000..d40e2ca
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * 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 <string>
+
+class Backfile
+{
+public:
+       const std::string& get_filename() const noexcept { return m_filename; }
+
+protected:
+       std::string m_filename;
+};
diff --git a/libuuu/buffer.cpp b/libuuu/buffer.cpp
new file mode 100644 (file)
index 0000000..7fff293
--- /dev/null
@@ -0,0 +1,1570 @@
+/*
+* Copyright 2018-2019 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 <map>
+#include "buffer.h"
+#include <sys/stat.h>
+#include "liberror.h"
+#include <iostream>
+#include <fstream>
+#include "libcomm.h"
+#include "libuuu.h"
+#include "zip.h"
+#include "fat.h"
+#include "tar.h"
+#include <string.h>
+#include "bzlib.h"
+#include "stdio.h"
+#include <limits>
+#include "http.h"
+
+#ifdef _MSC_VER
+#define stat64 _stat64
+#else
+#include "dirent.h"
+#endif
+
+static map<string, shared_ptr<FileBuffer>> g_filebuffer_map;
+static mutex g_mutex_map;
+
+#define MAGIC_PATH '>'
+
+string g_current_dir = ">";
+
+void set_current_dir(const string &dir)
+{
+       g_current_dir = MAGIC_PATH;
+       g_current_dir += dir;
+}
+
+class FSBasic
+{
+public:
+       virtual int get_file_timesample(const string &filename, uint64_t *ptime) = 0;
+       virtual int load(const string &backfile, const string &filename, shared_ptr<FileBuffer> p, bool async) = 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 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)
+               {
+                       set_last_err_string("can't find ext name in path");
+                       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;
+};
+
+static class FSFlat: public FSBasic
+{
+public:
+       FSFlat() { m_ext = ""; }
+       int get_file_timesample(const string &filename, uint64_t *ptime) override
+       {
+               struct stat64 st;
+               if (stat64(filename.c_str() + 1, &st))
+               {
+                       set_last_err_string("stat64 failure");
+                       return -1;
+               }
+
+               *ptime = st.st_mtime;
+
+               return 0;
+       }
+
+       bool exist(const string &backfile, const string &filename) override
+       {
+               struct stat64 st;
+               return stat64(backfile.c_str() + 1, &st) == 0 && ((st.st_mode & S_IFDIR) == 0);
+       }
+
+       int load(const string &backfile, const string &filename, shared_ptr<FileBuffer> p, bool async) override
+       {
+               struct stat64 st;
+               if (stat64(backfile.c_str() + 1, &st))
+               {
+                       set_last_err_string("stat64 failure");
+                       return -1;
+               }
+               p->unmapfile();
+
+               if (p->mapfile(backfile.substr(1), st.st_size))
+                       return -1;
+
+               p->m_avaible_size = st.st_size;
+               
+               atomic_fetch_or(&p->m_dataflags, FILEBUFFER_FLAG_LOADED);
+               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 stat64 st;
+
+               if(stat64(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<FileBuffer> p, bool async) override;
+       virtual bool exist(const string &backfile, const string &filename) override { 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; };
+}g_fshttp;
+
+static class FSHttps : public FSHttp
+{
+public:
+       FSHttps() { m_Prefix = "HTTPS://"; m_Port = 443; }
+}g_fshttps;
+
+int http_load(shared_ptr<HttpStream> http, shared_ptr<FileBuffer> 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(); 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_avaible_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);
+       p->m_request_cv.notify_all();
+
+       ut.type = uuu_notify::NOTIFY_DOWNLOAD_END;
+       ut.str = (char*)filename.c_str();
+       call_notify(ut);
+       return 0;
+}
+
+int FSHttp::load(const string &backfile, const string &filename, shared_ptr<FileBuffer> p, bool async)
+{
+       shared_ptr<HttpStream> http = make_shared<HttpStream>();
+
+       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();
+
+       if (async)
+       {
+               p->m_aync_thread = thread(http_load, http, p, backfile + filename);
+#ifdef WIN32
+               SetThreadPriority(p->m_aync_thread.native_handle(), THREAD_PRIORITY_BELOW_NORMAL);
+#endif
+       }
+       else
+       {
+               if (http_load(http, p, backfile + filename))
+                       return -1;
+
+               p->m_avaible_size = p->m_DataSize;
+               atomic_fetch_or(&p->m_dataflags, FILEBUFFER_FLAG_LOADED);
+               p->m_request_cv.notify_all();
+       }
+
+       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<FileBuffer> p, bool async) 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<FileBuffer> p, bool async) 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<FileBuffer> p, bool async) 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 FSCompressStream : public FSBackFile
+{
+public:
+       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;
+};
+
+static class FSBz2 : public FSCompressStream
+{
+public:
+       FSBz2() { m_ext = ".BZ2"; };
+       int load(const string &backfile, const string &filename, shared_ptr<FileBuffer> p, bool async) override;
+}g_fsbz2;
+
+static class FSGz : public FSCompressStream
+{
+public:
+       FSGz() { m_ext = ".GZ"; };
+       int load(const string &backfile, const string &filename, shared_ptr<FileBuffer> p, bool async) override;
+}g_fsgz;
+
+static class FS_DATA
+{
+public:
+       vector<FSBasic *> 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_fshttps);
+               m_pFs.push_back(&g_fshttp);
+       }
+
+       int get_file_timesample(const string &filename, uint64_t *ptimesame)
+       {
+               if (ptimesame == nullptr)
+               {
+                       set_last_err_string("ptimesame is null\n");
+                       return -1;
+               }
+
+               for (int i = 0; i < m_pFs.size(); i++)
+               {
+                       if (!m_pFs[i]->get_file_timesample(filename, ptimesame))
+                               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 (int 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;
+       }
+       int load(const string &filename, shared_ptr<FileBuffer> p, bool async)
+       {
+               for (int 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, async) == 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<FileBuffer> buff)
+{
+       std::lock_guard<mutex> lock(buff->m_async_mutex);
+
+       Zip zip;
+       if (zip.Open(zipfile))
+               return -1;
+
+       if(zip.get_file_buff(fn, buff))
+               return -1;
+
+       buff->m_avaible_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<FileBuffer> p, bool async)
+{
+       Zip zip;
+
+       if (zip.Open(backfile))
+               return -1;
+
+       if (!zip.check_file_exist(filename))
+               return -1;
+
+       if (async)
+       {
+               p->m_aync_thread = thread(zip_async_load, backfile, filename, p);
+       }
+       else
+       {
+               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<FileBuffer> p, bool async)
+{
+       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_avaible_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<FileBuffer> p, bool async)
+{
+       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 (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;
+}
+
+struct bz2_blk
+{
+       size_t start;
+       size_t size;
+       size_t decompress_offset;
+       size_t decompress_size;
+       size_t actual_size;
+       int     error;
+};
+
+class bz2_blks
+{
+public:
+       vector<bz2_blk> blk;
+       mutex blk_mutex;
+
+       condition_variable cv;
+       mutex con_mutex;
+
+       atomic<size_t> top;
+       atomic<size_t> bottom;
+       bz2_blks() { top = 0; bottom = ULLONG_MAX; }
+};
+
+int bz2_update_available(shared_ptr<FileBuffer> p, bz2_blks * pblk)
+{
+       lock_guard<mutex> lock(pblk->blk_mutex);
+       size_t sz = 0;
+       for (int i = 1; i < pblk->blk.size() - 1; i++)
+       {
+               if (pblk->blk[i].error)
+                       break;
+
+               if (!pblk->blk[i].actual_size)
+                       break;
+
+               sz += pblk->blk[i].actual_size;
+       }
+
+       p->m_avaible_size = sz;
+       p->m_request_cv.notify_all();
+       return 0;
+}
+
+int bz2_decompress(shared_ptr<FileBuffer> pbz, shared_ptr<FileBuffer> p, bz2_blks * pblk)
+{
+       bz2_blk one;
+       size_t cur;
+       vector<uint8_t> buff;
+
+       while (pblk->top + 1 < pblk->bottom)
+       {
+               if (p->IsError())
+                       return -1;
+
+               {
+                       std::unique_lock<std::mutex> lck(pblk->con_mutex);
+                       while (pblk->top + 1 >= pblk->blk.size()) {
+                               pblk->cv.wait(lck);
+                               if (p->IsError())
+                                       return -1;
+                       }
+               }
+
+               {
+                       lock_guard<mutex> lock(pblk->blk_mutex);
+                       if (pblk->top < pblk->blk.size() - 1)
+                       {
+                               cur = pblk->top;
+                               one = pblk->blk[pblk->top];
+                               pblk->top++;
+                       }
+                       else
+                       {
+                               continue;
+                       }
+               }
+
+               unsigned int len = one.decompress_size;
+               buff.resize(len);
+
+               one.error = BZ2_bzBuffToBuffDecompress((char*)buff.data(),
+                       &len,
+                       (char*)pbz->data() + one.start,
+                       one.size,
+                       0,
+                       0);
+               one.actual_size = len;
+
+               {
+                       lock_guard<mutex> lock(pblk->blk_mutex);
+                       (*pblk).blk[cur] = one;
+               }
+
+
+               {
+                       lock_guard<mutex> lock(p->m_data_mutex);
+                       if (p->size() < one.decompress_offset + one.actual_size)
+                               if(p->resize(one.decompress_offset + one.actual_size))
+                                       return -1;
+
+                       memcpy(p->data() + one.decompress_offset, buff.data(), one.actual_size);
+               }
+
+               bz2_update_available(p, pblk);
+
+       }
+
+       return 0;
+}
+
+int bz_async_load(string filename, shared_ptr<FileBuffer> p)
+{
+       shared_ptr<FileBuffer> pbz;
+
+       pbz = get_file_buffer(filename, true);
+       if (pbz == nullptr) {
+               string err;
+               err = "Failure get file buffer: ";
+               err += filename;
+               set_last_err_string(err);
+               return -1;
+       }
+
+       bz2_blks blks;
+       bz2_blk one;
+       memset(&one, 0, sizeof(one));
+       blks.blk.push_back(one);
+       blks.top = 1;
+
+       size_t total = 0;
+
+       uint8_t *p1 = &pbz->at(0);
+
+       int nthread = thread::hardware_concurrency();
+
+       vector<thread> threads;
+
+       if (p->reserve(pbz->size() * 5)) //estimate uncompressed memory size;
+       {
+               set_last_err_string("Out of memory");
+               return -1;
+       }
+
+       for (int i = 0; i < nthread; i++)
+       {
+               threads.push_back(thread(bz2_decompress, pbz, p, &blks));
+#ifdef WIN32
+               if( i!=0 )
+                       SetThreadPriority(threads[i].native_handle(), THREAD_PRIORITY_BELOW_NORMAL);
+#endif
+       }
+
+       size_t requested = 0;
+       for (size_t i = 0; i < pbz->size() - 10; i++)
+       {
+               if(i >= requested)
+               {
+                       requested = i + 0x10000;
+                       if (requested > pbz->size())
+                               requested = pbz->size();
+                       if (pbz->request_data(requested))
+                       {
+                               atomic_fetch_or(&p->m_dataflags, FILEBUFFER_FLAG_ERROR_BIT);
+                               blks.cv.notify_all();
+                               for (int i = 0; i < nthread; i++)
+                               {
+                                       threads[i].join();
+                               }
+                               return -1;
+                       }
+               }
+
+               uint16_t *header = (uint16_t *)p1++;
+               if (*header == 0x5a42) //"BZ"
+               {
+                       uint32_t *magic1 = (uint32_t *)&pbz->at(i+4);
+                       if (*magic1 == 0x26594131) //PI 3.1415926
+                       {
+                               uint16_t *magic2 = (uint16_t *)&pbz->at(i + 8);
+                               if (*magic2 == 0x5953)
+                               {     
+                                       /*which is valude bz2 header*/
+                                       struct bz2_blk one;
+                                       memset(&one, 0, sizeof(one));
+
+                                       one.start = i;
+                                       {
+                                               lock_guard<mutex> lock(blks.blk_mutex);
+
+                                               blks.blk.back().size = i - blks.blk.back().start;
+                                               one.decompress_offset = blks.blk.back().decompress_offset + blks.blk.back().decompress_size;
+                                               one.decompress_size = (pbz->at(i + 3) - '0') * 100 * 1000; /* not l024 for bz2 */
+
+                                               blks.blk.push_back(one);
+                                       }
+                                       total += one.decompress_size;
+
+                                       blks.cv.notify_all();
+                               }
+                       }
+               }
+       }
+
+       if (blks.blk.size() == 1) {
+               set_last_err_string("Can't find validate bz2 magic number");
+               return -1;
+       }
+
+       blks.blk.back().size = pbz->size() - blks.blk.back().start;
+
+       {
+               lock_guard<mutex> lock(p->m_data_mutex);
+               if(p->resize(total))
+                       return -1;
+       }
+
+       atomic_fetch_or(&p->m_dataflags, FILEBUFFER_FLAG_KNOWN_SIZE);
+       p->m_request_cv.notify_all();
+
+       {
+               lock_guard<mutex> lock(blks.blk_mutex);
+               struct bz2_blk one;
+               memset(&one, 0, sizeof(one));
+               blks.blk.push_back(one);
+               blks.bottom = blks.blk.size();
+               blks.cv.notify_all();
+       }
+
+       for (int i = 0; i < nthread; i++)
+       {
+               threads[i].join();
+       }
+
+       for (int i = 1; i < blks.blk.size(); i++)
+       {
+               if (blks.blk[i].error)
+               {
+                       set_last_err_string("decompress err");
+                       return -1;
+               }
+               if ((blks.blk[i].decompress_size != blks.blk[i].actual_size) && (i != blks.blk.size() - 2))  /*two dummy blks (one header and other end)*/
+               {
+                       set_last_err_string("bz2: only support last block less then other block");
+                       return -1;
+               }
+       }
+
+       bz2_update_available(p, &blks);
+
+       if(p->resize(p->m_avaible_size))
+               return -1;
+       atomic_fetch_or(&p->m_dataflags, FILEBUFFER_FLAG_LOADED);
+       p->m_request_cv.notify_all();
+
+       return 0;
+}
+
+bool is_pbzip2_file(string filename)
+{
+       shared_ptr<FileBuffer> file=get_file_buffer(filename, true);
+       uint64_t filesize= file->size();
+       uint64_t readsize= (filesize< (1024*1024) )? filesize:(1024*1024); //read at most 1MB, because maximum block size is 900kb
+
+       file->request_data(readsize);
+
+       int header_num=0;
+       uint8_t* ptr= file->data();
+       for(size_t i =0 ; i < readsize ; 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;
+       else
+               return false;
+}
+
+int decompress_single_thread(string name,shared_ptr<FileBuffer>p)
+{
+       uint8_t* decompressed_file;
+       uint64_t decompressed_size;
+
+       uint8_t* compressed_file;
+       uint64_t compressed_size;
+
+       shared_ptr<FileBuffer> filebuffer=get_file_buffer(name);
+
+       compressed_file=filebuffer->data();
+       compressed_size=filebuffer->size();
+
+       decompressed_file=p->data();
+       decompressed_size=0;
+
+       p->reserve(7*compressed_size);//the usual compressed ratio is about 18%, so 7*18% > 100%
+
+       bz_stream strm;
+       strm.bzalloc  = nullptr;
+       strm.bzfree   = nullptr;
+       strm.opaque   = nullptr;
+
+       int ret;
+       ret = BZ2_bzDecompressInit (&strm,0, 0 );
+       if (ret != BZ_OK)
+               return -1;
+       strm.next_in  = (char*)compressed_file;
+       strm.avail_in = compressed_size;
+
+       uint64_t decompress_amount=5000; //decompress 5000 byte every iteration, choose 5000 only because the pbzip2 also used 5000 in their implementation.
+       while(1)
+       {
+               p->reserve(decompressed_size+1000*decompress_amount);//make sure the space is enough,multiple by 1000 to avoid repeated realloc
+               strm.next_out=(char*)p->data()+decompressed_size;
+               strm.avail_out=decompress_amount;
+
+               ret=BZ2_bzDecompress(&strm);
+               decompressed_size+=decompress_amount;
+
+               if(ret==BZ_STREAM_END)
+               {
+                       decompressed_size-= strm.avail_out;
+                       break;
+               }
+               else if (ret != BZ_OK)//if it is not bz_ok nor bz_stream_end, decompression failed.
+                       return -1;
+
+       }
+       p->resize(decompressed_size);
+       BZ2_bzDecompressEnd(&strm);
+       atomic_fetch_or(&p->m_dataflags, FILEBUFFER_FLAG_LOADED);
+       p->m_request_cv.notify_all();
+       return 0;
+}
+
+
+int FSBz2::load(const string &backfile, const string &filename, shared_ptr<FileBuffer>p, bool async)
+{
+       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<FileBuffer> decompressed_file=get_file_buffer(decompressed_name);
+               Tar tar;
+               tar.Open(decompressed_name);
+               if (tar.get_file_buff(filename, p))
+                       return -1;
+               p->m_avaible_size = p->m_DataSize;
+       }
+       else
+       {
+               if(!check_file_exist(backfile.substr(1)))
+                       return -1;
+               if(is_pbzip2_file(backfile.substr(1))==true)//the bz2 file can be decompressed with multithreading
+                       p->m_aync_thread = thread(bz_async_load, backfile, p);
+               else//the bz2 file can only be decompressed using single thread
+                       p->m_aync_thread = thread(decompress_single_thread, backfile, p);
+
+               if (!async) {
+                       p->m_aync_thread.join();
+                       if (! p->IsLoaded()) {
+                               set_last_err_string("async data load failure\n");
+                               return -1;
+                       }
+               }
+       }
+       return 0;
+}
+
+int FSGz::load(const string &backfile, const string &filename, shared_ptr<FileBuffer>p, bool async)
+{
+       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<FileBuffer> decompressed_file = get_file_buffer(decompressed_name);
+               Tar tar;
+               tar.Open(decompressed_name);
+               if (tar.get_file_buff(filename, p))
+                       return -1;
+               p->m_avaible_size = p->m_DataSize;
+       }
+       else
+       {
+               gzFile fp = gzopen(backfile.c_str() + 1, "r");
+               if (fp == nullptr)
+               {
+                       set_last_err_string("Open file failure");
+                       return -1;
+               }
+
+               shared_ptr<FileBuffer> pb = get_file_buffer(backfile);
+
+               p->reserve(pb->size() * 4); /* guest uncompress size */
+
+               size_t sz = 0x100000;
+               if (sz > pb->size() * 4)
+                       sz = p->size();
+
+               uuu_notify ut;
+               ut.type = uuu_notify::NOTIFY_DECOMPRESS_START;
+               ut.str = (char*)backfile.c_str();
+               call_notify(ut);
+
+               ut.type = uuu_notify::NOTIFY_DECOMPRESS_SIZE;
+               ut.total = pb->size();
+               call_notify(ut);
+
+               size_t cur = 0;
+               while (!gzeof(fp))
+               {
+                       size_t ret = gzread(fp, p->data() + cur, sz);
+                       if (sz < 0)
+                       {
+                               set_last_err_string("decompress error");
+                               return -1;
+                       }
+                       cur += ret;
+                       p->reserve(cur + sz);
+
+                       ut.type = uuu_notify::NOTIFY_DECOMPRESS_POS;
+                       ut.index = gzoffset(fp);
+                       call_notify(ut);
+               }
+
+               p->resize(cur);
+               p->m_avaible_size = cur;
+
+               ut.type = uuu_notify::NOTIFY_DECOMPRESS_POS;
+               ut.index = pb->size();
+               call_notify(ut);
+
+               gzclose(fp);
+               atomic_fetch_or(&p->m_dataflags, FILEBUFFER_FLAG_LOADED);
+               p->m_request_cv.notify_all();
+       }
+       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<FileBuffer> 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<mutex> lock(g_mutex_map);
+               find = (g_filebuffer_map.find(filename) == g_filebuffer_map.end());
+       }
+
+       if (find)
+       {
+               shared_ptr<FileBuffer> p(new FileBuffer);
+
+               if (p->reload(filename, async))
+                       return nullptr;
+
+               {
+                       std::lock_guard<mutex> lock(g_mutex_map);
+                       g_filebuffer_map[filename] = p;
+               }
+               return p;
+       }
+       else
+       {
+               shared_ptr<FileBuffer> p;
+               {
+                       std::lock_guard<mutex> 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<mutex> lock(p->m_async_mutex);
+
+                       if(p->m_aync_thread.joinable())
+                               p->m_aync_thread.join();
+
+                       if(!p->IsLoaded())
+                       {
+                               return nullptr;
+                       }
+               }
+
+               return p;
+       }
+}
+
+FileBuffer::FileBuffer()
+{
+       m_pDatabuffer = nullptr;
+       m_DataSize = 0;
+       m_MemSize = 0;
+       m_dataflags = 0;
+       m_avaible_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;
+}
+
+FileBuffer::~FileBuffer()
+{
+       if(m_aync_thread.joinable())
+               m_aync_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(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<FileBuffer> p, size_t offset, size_t size)
+{
+       m_pDatabuffer = p->data() + offset;
+       m_DataSize = m_MemSize = size;
+       m_allocate_way = ALLOCATION_WAYS::REF;
+       m_ref = p;
+       return 0;
+}
+
+int FileBuffer::reload(string filename, bool async)
+{
+       atomic_init(&this->m_dataflags, 0);
+
+       if (g_fs_data.load(filename, shared_from_this(), async) == 0)
+       {
+               m_timesample = get_file_timesample(filename);
+               return 0;
+       }
+       return -1;
+}
+
+int FileBuffer::request_data(size_t sz)
+{
+       std::unique_lock<std::mutex> lck(m_requext_cv_mutex);
+
+       while(!this->m_dataflags & FILEBUFFER_FLAG_KNOWN_SIZE_BIT)
+               m_request_cv.wait(lck);
+
+       if (IsLoaded())
+       {
+               if (sz > this->size())
+               {
+                       set_last_err_string("exceed data size");
+                       return -1;
+               }
+       }
+
+       
+       while ((sz > m_avaible_size) && !IsLoaded())
+       {
+               if (IsError())
+               {
+                       set_last_err_string("Async request data error");
+                       return -1;
+               }
+               m_request_cv.wait(lck);
+       }
+
+       if (IsLoaded())
+       {
+               if (sz > m_avaible_size)
+               {
+                       set_last_err_string("request offset execeed memory size");
+                       return -1;
+               }
+       }
+
+       return 0;
+}
+
+int FileBuffer::request_data(vector<uint8_t> &data, size_t offset, size_t sz)
+{
+       bool needlock = false;
+
+       if (IsLoaded())
+       {
+               if (offset >= this->size())
+               {
+                       data.clear();
+                       set_last_err_string("request offset execeed memory size");
+                       return -1;
+               }
+       }
+       else
+       {
+               std::unique_lock<std::mutex> lck(m_requext_cv_mutex);
+               while ((offset + sz > m_avaible_size) && !IsLoaded())
+               {
+                       if (IsError())
+                       {
+                               set_last_err_string("Async request data error");
+                               return -1;
+                       }
+                       m_request_cv.wait(lck);
+               }
+
+               if (IsLoaded())
+               {
+                       if (offset > m_avaible_size)
+                       {
+                               data.clear();
+                               set_last_err_string("request offset execeed memory size");
+                               return -1;
+                       }
+               }
+               needlock = true;
+       }
+
+       size_t size = sz;
+       if (offset + size >= m_avaible_size)
+               size = m_avaible_size - offset;
+
+       data.resize(size);
+
+       if (needlock) m_data_mutex.lock();
+
+       memcpy(data.data(), this->data() + offset, size);
+
+       if (needlock) m_data_mutex.unlock();
+
+       return 0;
+}
+
+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)
+{
+       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)
+{
+       return get_file_buffer(filename, true) != nullptr;
+}
+
+#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<mutex> 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);
+}
diff --git a/libuuu/buffer.h b/libuuu/buffer.h
new file mode 100644 (file)
index 0000000..a374374
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+* 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 <atomic>
+#include <cassert>
+#include <condition_variable>
+#include <memory>
+#include <mutex>
+#include <thread>
+#include <vector>
+
+#ifdef _MSC_VER
+#include <Windows.h>
+#else
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+#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_LOADED         (FILEBUFFER_FLAG_LOADED_BIT|FILEBUFFER_FLAG_KNOWN_SIZE_BIT) // LOADED must be knownsize
+#define FILEBUFFER_FLAG_KNOWN_SIZE     FILEBUFFER_FLAG_KNOWN_SIZE_BIT
+
+class FileBuffer: public std::enable_shared_from_this<FileBuffer>
+{
+public:
+       enum class ALLOCATION_WAYS
+       {
+               MALLOC,
+               MMAP,
+               REF,
+               VMALLOC,
+       };
+
+       std::mutex m_data_mutex;
+
+       uint8_t *m_pDatabuffer;
+       size_t m_DataSize;
+       size_t m_MemSize;
+
+       std::shared_ptr<FileBuffer> m_ref;
+
+       int ref_other_buffer(std::shared_ptr<FileBuffer> p, size_t offset, size_t size);
+
+       std::mutex m_async_mutex;
+       
+       std::atomic_int m_dataflags;
+
+       std::thread m_aync_thread;
+
+       std::atomic_size_t m_avaible_size;
+       std::condition_variable m_request_cv;
+       std::mutex m_requext_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
+
+       FileBuffer();
+       FileBuffer(void*p, size_t sz);
+       ~FileBuffer();
+
+       ALLOCATION_WAYS get_m_allocate_way() const noexcept { return m_allocate_way; }
+       int request_data(std::vector<uint8_t> &data, size_t offset, size_t sz);
+       int request_data(size_t total);
+
+       bool IsLoaded() const noexcept
+       {
+               return m_dataflags & FILEBUFFER_FLAG_LOADED_BIT;
+       }
+
+       bool IsKnownSize() const noexcept
+       {
+               return m_dataflags & FILEBUFFER_FLAG_KNOWN_SIZE_BIT;
+       }
+
+       bool IsError() const noexcept
+       {
+               return m_dataflags & FILEBUFFER_FLAG_ERROR_BIT;
+       }
+       uint8_t * data() noexcept
+       {
+               return m_pDatabuffer ;
+       }
+
+       size_t size() const noexcept
+       {
+               return m_DataSize;
+       }
+
+       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(std::string filename, size_t sz);
+
+       int unmapfile();
+       //Read write lock;
+       uint64_t m_timesample;
+       int reload(std::string filename, bool async=false);
+
+private:
+       ALLOCATION_WAYS m_allocate_way = ALLOCATION_WAYS::MALLOC;
+};
+
+std::shared_ptr<FileBuffer> get_file_buffer(std::string filename, bool aysnc=false);
+bool check_file_exist(std::string filename, bool start_async_load=true);
+
+void set_current_dir(const std::string &dir);
diff --git a/libuuu/cmd.cpp b/libuuu/cmd.cpp
new file mode 100644 (file)
index 0000000..06e997a
--- /dev/null
@@ -0,0 +1,1003 @@
+/*
+* 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 <regex>
+#include <iterator>
+#include <memory>
+#include <string.h>
+#include "cmd.h"
+#include "libcomm.h"
+#include "liberror.h"
+#include "libuuu.h"
+#include "config.h"
+#include "trans.h"
+#include "sdps.h"
+#include <atomic>
+#include "buffer.h"
+#include "sdp.h"
+#include "fastboot.h"
+#include <sys/stat.h>
+#include <thread>
+
+#include <stdio.h>  
+#include <stdlib.h>  
+
+static CmdMap g_cmd_map;
+static CmdObjCreateMap g_cmd_create_map;
+static string g_cmd_list_file;
+
+int get_string_in_square_brackets(const std::string &cmd, std::string &context);
+int parser_cmd_list_file(shared_ptr<FileBuffer> pbuff, CmdMap *pCmdMap = nullptr);
+std::string remove_square_brackets(const std::string &cmd);
+
+template <class T>
+void * create_object() { return new T; }
+
+typedef void * (*FN)();
+
+FN g_fn = create_object<int>;
+
+CmdCtx::~CmdCtx()
+{
+}
+
+CmdBase::~CmdBase()
+{
+}
+
+int CmdBase::parser(char *p)
+{
+       if (p != nullptr)
+               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);
+
+       int 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_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 = 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_protocal(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 Protocal:");
+               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 sperate)
+{
+       string str;
+       if (pos == string::npos)
+               return str;
+       if (pos >= cmd.size())
+               return str;
+
+       //trim left space
+       while (cmd[pos] == sperate && pos < cmd.size())
+               pos++;
+
+       bool quate = false;
+       size_t end = string::npos;
+
+       for (size_t s = pos; s < cmd.size(); s++)
+       {
+               if (cmd[s] == '"')
+                       quate = !quate;
+
+               if (!quate && cmd[s] == sperate)
+               {
+                       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<typename T, uint64_t MAX_VAL>
+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<T>(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_suceeded)
+{
+       return str_to_uint<uint16_t, UINT16_MAX>(str, conversion_suceeded);
+}
+
+uint32_t str_to_uint32(const string &str, bool * conversion_suceeded)
+{
+       return str_to_uint<uint32_t, UINT32_MAX>(str, conversion_suceeded);
+}
+
+uint64_t str_to_uint64(const string &str, bool * conversion_suceeded)
+{
+       return str_to_uint<uint64_t, UINT64_MAX>(str, conversion_suceeded);
+}
+
+template <class T> shared_ptr<CmdBase> new_cmd_obj(char *p)
+{
+       return shared_ptr<CmdBase>(new T(p));
+}
+
+CmdObjCreateMap::CmdObjCreateMap()
+{
+       (*this)["CFG:"] = new_cmd_obj<CfgCmd>;
+
+       (*this)["SDPS:BOOT"] = new_cmd_obj<SDPSCmd>;
+
+       (*this)["SDP:DCD"] = new_cmd_obj<SDPDcdCmd>;
+       (*this)["SDP:JUMP"] = new_cmd_obj<SDPJumpCmd>;
+       (*this)["SDP:RDMEM"] = new_cmd_obj<SDPReadMemCmd>;
+       (*this)["SDP:WRMEM"] = new_cmd_obj<SDPWriteMemCmd>;
+       (*this)["SDP:WRITE"] = new_cmd_obj<SDPWriteCmd>;
+       (*this)["SDP:STATUS"] = new_cmd_obj<SDPStatusCmd>;
+       (*this)["SDP:BOOT"] = new_cmd_obj<SDPBootCmd>;
+       (*this)["SDP:BLOG"] = new_cmd_obj<SDPBootlogCmd>;
+
+       (*this)["SDPU:JUMP"] = new_cmd_obj<SDPJumpCmd>;
+       (*this)["SDPU:WRITE"] = new_cmd_obj<SDPWriteCmd>;
+       (*this)["SDPU:BLOG"] = new_cmd_obj<SDPBootlogCmd>;
+
+       (*this)["SDPV:JUMP"] = new_cmd_obj<SDPJumpCmd>;
+       (*this)["SDPV:WRITE"] = new_cmd_obj<SDPWriteCmd>;
+       (*this)["SDPV:BLOG"] = new_cmd_obj<SDPBootlogCmd>;
+
+       (*this)["FB:GETVAR"] = new_cmd_obj<FBGetVar>;
+       (*this)["FASTBOOT:GETVAR"] = new_cmd_obj<FBGetVar>;
+       (*this)["FB:UCMD"] = new_cmd_obj<FBUCmd>;
+       (*this)["FASTBOOT:UCMD"] = new_cmd_obj<FBUCmd>;
+       (*this)["FB:ACMD"] = new_cmd_obj<FBACmd>;
+       (*this)["FASTBOOT:ACMD"] = new_cmd_obj<FBACmd>;
+       (*this)["FB:DOWNLOAD"] = new_cmd_obj<FBDownload>;
+       (*this)["FASTBOOT:DOWNLOAD"] = new_cmd_obj<FBDownload>;
+       (*this)["FB:FLASH"] = new_cmd_obj<FBFlashCmd>;
+       (*this)["FASTBOOT:FLASH"] = new_cmd_obj<FBFlashCmd>;
+       (*this)["FB:ERASE"] = new_cmd_obj<FBEraseCmd>;
+       (*this)["FASTBOOT:ERASE"] = new_cmd_obj<FBEraseCmd>;
+       (*this)["FB:REBOOT"] = new_cmd_obj<FBRebootCmd>;
+       (*this)["FASTBOOT:REBOOT"] = new_cmd_obj<FBRebootCmd>;
+       (*this)["FB:OEM"] = new_cmd_obj<FBOemCmd>;
+       (*this)["FASTBOOT:OEM"] = new_cmd_obj<FBOemCmd>;
+       (*this)["FB:FLASHING"] = new_cmd_obj<FBFlashingCmd>;
+       (*this)["FASTBOOT:FLASHING"] = new_cmd_obj<FBFlashingCmd>;
+       (*this)["FB:SET_ACTIVE"] = new_cmd_obj<FBSetActiveCmd>;
+       (*this)["FASTBOOT:SET_ACTIVE"] = new_cmd_obj<FBSetActiveCmd>;
+       (*this)["FB:CONTINUE"] = new_cmd_obj<FBContinueCmd>;
+       (*this)["FASTBOOT:CONTINUE"] = new_cmd_obj<FBContinueCmd>;
+
+       (*this)["FB:UPDATE-SUPER"] = new_cmd_obj<FBUpdateSuper>;
+       (*this)["FASTBOOT:UPDATE-SUPER"] = new_cmd_obj<FBUpdateSuper>;
+       (*this)["FB:CREATE-LOGICAL-PARTITION"] = new_cmd_obj<FBCreatePartition>;
+       (*this)["FASTBOOT:CREATE-LOGICAL-PARTITION"] = new_cmd_obj<FBCreatePartition>;
+       (*this)["FB:DELETE-LOGICAL-PARTITION"] = new_cmd_obj<FBDelPartition>;
+       (*this)["FASTBOOT:DELETE-LOGICAL-PARTITION"] = new_cmd_obj<FBDelPartition>;
+       (*this)["FB:RESIZE-LOGICAL-PARTITION"] = new_cmd_obj<FBResizePartition>;
+       (*this)["FASTBOOT:RESIZE-LOGICAL-PARTITION"] = new_cmd_obj<FBResizePartition>;
+
+       (*this)["FBK:UCMD"] = new_cmd_obj<FBUCmd>;
+       (*this)["FBK:ACMD"] = new_cmd_obj<FBACmd>;
+       (*this)["FBK:SYNC"] = new_cmd_obj<FBSyncCmd>;
+       (*this)["FBK:UCP"] = new_cmd_obj<FBCopy>;
+
+       (*this)["_ALL:DONE"] = new_cmd_obj<CmdDone>;
+       (*this)["_ALL:DELAY"] = new_cmd_obj<CmdDelay>;
+       (*this)["_ALL:SH"] = new_cmd_obj<CmdShell>;
+       (*this)["_ALL:SHELL"] = new_cmd_obj<CmdShell>;
+       (*this)["_ALL:<"] = new_cmd_obj<CmdShell>;
+       (*this)["_ALL:@"] = new_cmd_obj<CmdEnv>;
+
+}
+
+shared_ptr<CmdBase> 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<CmdBase> 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 Commnd:";
+               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 CmdShell::parser(char * p)
+{
+       if (p)
+               m_cmd = p;
+
+       size_t pos = 0;
+       string s;
+
+       if (parser_protocal(p, pos))
+               return -1;
+
+       m_protocal = 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_protocal;
+                       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_protocal(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<const string&>(cmd).begin();
+       auto cmd_end = static_cast<const string&>(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<bool, string> {
+#ifndef WIN32
+                               auto ptr = getenv(key.c_str());
+                               if (ptr)
+                                       return {true, ptr};
+                               return {false, {}};
+#else
+                               size_t len;
+                               getenv_s(&len, nullptr, 0, key.c_str());
+                               if (!len)
+                                       return {false, {}};
+                               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;
+               }
+       }
+       m_unfold_cmd.append(&*last_pos);
+
+       return 0;
+}
+
+int CmdEnv::run(CmdCtx *p)
+{
+       return run_cmd(p, m_unfold_cmd.c_str(), 0);
+}
+
+int run_cmds(const char *procotal, CmdCtx *p)
+{
+       CmdMap cmdmap, *pCmdMap;
+
+       if (!g_cmd_list_file.empty())
+       {
+               shared_ptr<FileBuffer> pbuff = get_file_buffer(g_cmd_list_file);
+               if (pbuff == nullptr)
+                       return -1;
+               if(parser_cmd_list_file(pbuff, &cmdmap))
+                       return -1;
+               pCmdMap = &cmdmap;
+       }
+       else
+       {
+               pCmdMap = &g_cmd_map;
+       }
+
+       if (pCmdMap->find(procotal) == pCmdMap->end())
+       {
+               return 0;
+       }
+
+       return (*pCmdMap)[procotal]->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<CmdBase> p = create_cmd_obj(s);
+       if (p == nullptr)
+               return -1;
+
+       if (p->parser())
+               return -1;
+
+       if (pCmdMap->find(pro) == pCmdMap->end())
+       {
+               shared_ptr<CmdList> 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<FileBuffer> p(new FileBuffer((void*)buff, strlen(buff)));
+       
+       return parser_cmd_list_file(p);
+}
+
+int parser_cmd_list_file(shared_ptr<FileBuffer> 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<FileBuffer> 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";
+       void *p1 = buffer->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(buffer);
+       }
+
+       //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<int> *) p = 1;
+       if (nt.type == uuu_notify::NOTIFY_CMD_END && nt.status)
+               *(std::atomic<int> *) p = 1;
+
+       return 0;
+}
+int uuu_wait_uuu_finish(int deamon, int dry)
+{
+       std::atomic<int> 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;
+
+       return 0;
+}
+
diff --git a/libuuu/cmd.h b/libuuu/cmd.h
new file mode 100644 (file)
index 0000000..0f8b40f
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+* 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 <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+class ConfigItem;
+
+std::string get_next_param(const std::string &cmd, size_t &pos, char sperate = ' ');
+
+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;
+};
+
+class CmdUsbCtx : public CmdCtx
+{
+public:
+       ~CmdUsbCtx() override;
+       int look_for_match_device(const char * procotol);
+};
+
+struct Param
+{
+       enum class Type
+       {
+               e_uint32,
+               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_protocal(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;
+       uint64_t m_timeout = 2000;
+
+private:
+       std::vector<Param> m_param;
+};
+
+using CreateCmdObj = std::shared_ptr<CmdBase> (*) (char *);
+
+class CmdObjCreateMap:public std::map<std::string, CreateCmdObj>
+{
+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 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_protocal;
+       std::string m_shellcmd;
+};
+
+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<std::shared_ptr<CmdBase>>
+{
+public:
+       int run_all(CmdCtx *p, bool dry_run = false);
+};
+
+class CmdMap : public std::map<std::string, std::shared_ptr<CmdList>>
+{
+public:
+       int run_all(const std::string &protocal, 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 *procotal, CmdCtx *p);
+int run_cmd(CmdCtx *pCtx, const char * cmd, int dry);
diff --git a/libuuu/config.cpp b/libuuu/config.cpp
new file mode 100644 (file)
index 0000000..edc68dd
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+* 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{"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{"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{"FB:", nullptr, nullptr,  0x0525, 0xA4A5});
+       emplace_back(ConfigItem{"FB:", nullptr, nullptr,  0x18D1, 0x0D02});
+       emplace_back(ConfigItem{"FB:", nullptr, nullptr,  BD_VID, 0x0001});
+}
+
+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;
+}
diff --git a/libuuu/config.h b/libuuu/config.h
new file mode 100644 (file)
index 0000000..0ac7b74
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+* 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 <cstdint>
+#include <string>
+#include <vector>
+
+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<ConfigItem>
+{
+public:
+       Config();
+       ConfigItem *find(uint16_t vid, uint16_t pid, uint16_t ver);
+       Config find(const std::string &protocal);
+};
+
+Config * get_config() noexcept;
diff --git a/libuuu/error.cpp b/libuuu/error.cpp
new file mode 100644 (file)
index 0000000..b966040
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+* 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"
+
+using namespace std;
+
+static string g_last_error_str;
+static int g_last_err_id;
+
+static uint32_t g_debug_level;
+
+void uuu_set_debug_level(uint32_t mask)
+{
+       g_debug_level = mask;
+}
+
+int get_libusb_debug_level() noexcept
+{
+       return g_debug_level & 0xFFFF;
+}
+
+const char * uuu_get_last_err_string()
+{
+       return g_last_error_str.c_str();
+}
+
+void set_last_err_string(const string &str)
+{
+       g_last_error_str = str;
+}
+
+int uuu_get_last_err()
+{
+       return g_last_err_id;
+}
+
+void set_last_err_id(int id)
+{
+       g_last_err_id = id;
+}
diff --git a/libuuu/fastboot.cpp b/libuuu/fastboot.cpp
new file mode 100644 (file)
index 0000000..af8311a
--- /dev/null
@@ -0,0 +1,880 @@
+/*
+* 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.
+*
+*/
+
+/*
+ Android fastboot protocol define at
+ https://android.googlesource.com/platform/system/core/+/master/fastboot/
+*/
+#include <string.h>
+#include "fastboot.h"
+#include "libcomm.h"
+#include "cmd.h"
+#include "buffer.h"
+#include "liberror.h"
+#include "libuuu.h"
+#include <iostream>
+#include <fstream>
+#include <sys/stat.h>
+#include "sparse.h"
+#include "ffu_format.h"
+#include "libcomm.h"
+#include "trans.h"
+
+int FastBoot::Transport(string cmd, void *p, size_t size, vector<uint8_t> *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)
+                       {
+                               input->resize(sz);
+                               size_t rz;
+                               if (m_pTrans->read(input->data(), sz, &rz))
+                                       return -1;
+                               input->resize(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 Commnd:";
+               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;
+       return 0;
+}
+
+int FBCmd::parser(char *p)
+{
+       if (p)
+               m_cmd = p;
+
+       size_t pos = 0;
+       string s;
+       
+       if (parser_protocal(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<FileBuffer> buff = get_file_buffer(m_filename);
+       if (buff == nullptr)
+               return -1;
+
+       string_ex cmd;
+       cmd.format("download:%08x", buff->size());
+
+       if (fb.Transport(cmd, buff->data(), buff->size()))
+               return -1;
+
+       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:<file name>");
+               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<FileBuffer> buff = get_file_buffer(m_local_file);
+               if (buff == nullptr)
+               {
+                       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")
+                                       break;
+                               return -1;
+                       }
+
+                       nt.type = uuu_notify::NOTIFY_TRANS_POS;
+                       nt.index = i;
+                       call_notify(nt);
+               }
+
+               nt.type = uuu_notify::NOTIFY_TRANS_POS;
+               nt.index = i;
+               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<uint8_t> 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;
+               m_partition = get_next_param(subcmd, pos);
+       }
+       else 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 (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))
+               return -1;
+
+       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<FileBuffer> pdata, size_t block_size, size_t max)
+{
+       SparseFile sf;
+
+       vector<uint8_t> data;
+
+       if (max > m_sparse_limit)
+                max = m_sparse_limit;
+
+       sf.init_header(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;
+       while (!pdata->request_data(data, i*block_size, block_size))
+       {
+               int ret = sf.push_one_block(data.data());
+               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 (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)
+       {
+               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;
+               }
+
+               shared_ptr<FileBuffer> pdata = get_file_buffer(m_filename, true);
+
+               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, block_size, max);
+       }
+
+       shared_ptr<FileBuffer> pdata = get_file_buffer(m_filename, true);
+       if (pdata == nullptr)
+               return -1;
+
+       pdata->request_data(sizeof(sparse_header));
+       if (SparseFile::is_validate_sparse_file(pdata->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 (pdata->size() <= max)
+       {
+               pdata->request_data(pdata->size());
+
+               if (flash(&fb, pdata->data(), pdata->size()))
+                       return -1;
+       }
+       else
+       {
+               size_t pos = 0;
+               pdata->request_data(sizeof(sparse_header));
+               sparse_header * pfile = (sparse_header *)pdata->data();
+
+               if (!SparseFile::is_validate_sparse_file(pdata->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;
+
+               for(size_t nblk=0; nblk < pfile->total_chunks && pos <= pdata->size(); nblk++)
+               {
+                       pdata->request_data(pos+sizeof(chunk_header_t)+sizeof(sparse_header));
+                       size_t oldpos = pos;
+                       pheader = SparseFile::get_next_chunk(pdata->data(), pos);
+                       pdata->request_data(pos);
+
+                       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;
+                               uuu_notify nt;
+                               nt.type = uuu_notify::NOTIFY_TRANS_POS;
+                               nt.total = startblock;
+                               call_notify(nt);
+                       }
+                       else
+                       {
+                               size_t off = ((uint8_t*)pheader) - pdata->data() + 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(pdata->data() + off, pos - 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 < 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<FileBuffer> p)
+{
+       vector<uint8_t> data;
+       data.resize(sizeof(FFU_SECURITY_HEADER));
+       p->request_data(data, 0, sizeof(FFU_SECURITY_HEADER));
+
+       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<FileBuffer> p, size_t off, size_t blksz, size_t blkindex)
+{
+       SparseFile sf;
+
+       sf.init_header(blksz, 10);
+
+       p->request_data(off + blksz);
+       
+       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() + off))
+               return -1;
+
+       return flash(fb, sf.m_data.data(), sf.m_data.size());
+}
+
+int FBFlashCmd::flash_ffu(FastBoot *fb, shared_ptr<FileBuffer> p)
+{
+       p->request_data(sizeof(FFU_SECURITY_HEADER));
+       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->request_data(off + sizeof(FFU_IMAGE_HEADER));
+       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->request_data(off + sizeof(FFU_STORE_HEADER));
+       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->request_data(off + pIs->dwWriteDescriptorLength);
+
+       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 currrent_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 (currrent_block >= pIs->dwInitialTableIndex && currrent_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", currrent_block, entry->rgDiskLocations[loc].dwBlockIndex, entry->rgDiskLocations[loc].dwDiskAccessMethod);
+                               uint32_t access = 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,
+                                                       p,
+                                                       block_off + (currrent_block + blk) * pIs->dwBlockSizeInBytes,
+                                                       pIs->dwBlockSizeInBytes,
+                                                       blockindex + blk))
+                                               return -1;
+                               }
+                       }
+               }
+
+               nt.type = uuu_notify::NOTIFY_TRANS_POS;
+               nt.total = i;
+               call_notify(nt);
+
+               currrent_block += entry->dwBlockCount;
+       }
+
+       nt.type = uuu_notify::NOTIFY_TRANS_POS;
+       nt.total = i;
+       call_notify(nt);
+
+       return 0;
+}
diff --git a/libuuu/fastboot.h b/libuuu/fastboot.h
new file mode 100644 (file)
index 0000000..8c0dcdc
--- /dev/null
@@ -0,0 +1,253 @@
+/*
+* 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 <cstdint>
+
+class FBFlashCmd;
+class FileBuffer;
+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<uint8_t> *input = nullptr);
+       int Transport(std::string cmd, std::vector<uint8_t> data, std::vector<uint8_t> *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 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<FileBuffer> p, size_t blksz, size_t max);
+       bool isffu(std::shared_ptr<FileBuffer> p);
+       int flash_ffu(FastBoot *fb, std::shared_ptr<FileBuffer> p);
+       int flash_ffu_oneblk(FastBoot *fb, std::shared_ptr<FileBuffer> p, size_t off, size_t blksz, size_t blkindex);
+
+private:
+       std::string m_filename;
+       std::string m_partition;
+       bool m_raw2sparse = false;
+       size_t m_sparse_limit = 0x1000000;
+       uint64_t m_totalsize;
+};
+
+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 FBContinueCmd : public FBCmd
+{
+public:
+       FBContinueCmd(char *p) : FBCmd(p, "continue") {}
+};
diff --git a/libuuu/fat.cpp b/libuuu/fat.cpp
new file mode 100644 (file)
index 0000000..816ccf7
--- /dev/null
@@ -0,0 +1,207 @@
+/*
+* 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 <string.h>
+#include <iostream>
+#include <fstream>
+#include "libcomm.h"
+#include "libuuu.h"
+#include "liberror.h"
+
+#include "fat.h"
+
+int Fat::Open(string filename)
+{
+       m_filename = filename;
+
+       shared_ptr<FileBuffer> 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<FileBuffer> 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<FileBuffer> 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_ptr<FileBuffer>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;
+       }
+
+       shared_ptr<FileBuffer> 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;
+}
diff --git a/libuuu/fat.h b/libuuu/fat.h
new file mode 100644 (file)
index 0000000..3eb3af6
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+* 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 <map>
+
+#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 delele_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<FileBuffer> p, int cluster);
+       int get_file_buff(string filename, shared_ptr<FileBuffer>p);
+       int get_next_cluster(shared_ptr<FileBuffer> p, int cluster);
+       string lfn2string(FatLFN *p);
+       int Open(string filename);
+
+       map<string, FatDirEntry> 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;
+};
diff --git a/libuuu/ffu_format.h b/libuuu/ffu_format.h
new file mode 100644 (file)
index 0000000..523400a
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * 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 <cstdint>
+
+#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
diff --git a/libuuu/gen_ver.sh b/libuuu/gen_ver.sh
new file mode 100755 (executable)
index 0000000..fe9ed8a
--- /dev/null
@@ -0,0 +1,28 @@
+#!/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 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 --tags --long`
+       echo "#define GIT_VERSION \"lib$version\"" > $file_to_write
+fi
diff --git a/libuuu/hidreport.cpp b/libuuu/hidreport.cpp
new file mode 100644 (file)
index 0000000..e9f0d87
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * 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 <cstring>
+
+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<uint8_t> &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<const uint8_t *>(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);
+
+               int ret = m_pdev->write(m_out_buff.data(), report_id == 1? s + m_size_payload: m_size_out + m_size_payload);
+
+               if (ret < 0)
+                       return -1;
+
+               if (off % 0x1F == 0)
+               {
+                       notify(off, uuu_notify::NOTIFY_TRANS_POS);
+               }
+       }
+       notify(off, uuu_notify::NOTIFY_TRANS_POS);
+       return 0;
+}
diff --git a/libuuu/hidreport.h b/libuuu/hidreport.h
new file mode 100644 (file)
index 0000000..495ec17
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+* 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 <vector>
+
+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<uint8_t> &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<uint8_t> &buff, uint8_t report_id)
+       {
+               return write(buff.data(), buff.size(), report_id);
+       }
+
+private:
+       size_t m_notify_total = 0;
+       std::vector<uint8_t> 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;
+};
diff --git a/libuuu/http.cpp b/libuuu/http.cpp
new file mode 100644 (file)
index 0000000..f6dcdf9
--- /dev/null
@@ -0,0 +1,465 @@
+/*
+ * Copyright 2019 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 <ws2tcpip.h>
+#include <windows.h>
+#include <winhttp.h>
+#pragma comment(lib, "Winhttp.lib")
+#else
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#define INVALID_SOCKET -1
+#include <unistd.h>
+#endif
+
+#include "http.h"
+#include "libuuu.h"
+#include "liberror.h"
+#include <string.h>
+#include <locale>
+#include <codecvt>
+
+#ifdef UUUSSL
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+
+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*/
+
+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<codecvt_utf8_utf16<wchar_t>> 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;
+       }
+
+       bResults = WinHttpSendRequest(m_hRequest,
+                       WINHTTP_NO_ADDITIONAL_HEADERS, 0,
+                       WINHTTP_NO_REQUEST_DATA, 0,
+                       0, 0);
+
+       if (!bResults)
+       {
+               set_last_err_string("Fail WinHttpSendRequest");
+               return -1;
+       }
+
+       bResults = WinHttpReceiveResponse(m_hRequest, nullptr);
+
+       if (!bResults)
+       {
+               set_last_err_string("Fail WinHttpReceiveResponse");
+               return -1;
+       }
+
+       DWORD status = 0;
+       DWORD dwSize = sizeof(status);
+       WinHttpQueryHeaders(m_hRequest, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
+               WINHTTP_HEADER_NAME_BY_INDEX, &status,
+               &dwSize, WINHTTP_NO_HEADER_INDEX);
+
+       if (status != HTTP_STATUS_OK)
+       {
+               set_last_err_string("HTTP status is not okay");
+               return -1;
+       }
+       return 0;
+}
+
+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);
+}
+
+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;
+       }
+
+       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 = TLSv1_2_client_method();
+               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
+        }
+
+       if(ishttps)
+               path = "https://" + host + path;
+
+       string request = "GET " + path + " HTTP/1.1\r\n";
+       request += "Host: " + host + "\r\n\r\n";
+
+       ret = SendPacket((char*)request.c_str(), request.size());
+       if (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 termaniate");
+               return -1;
+       }
+
+       m_data_start = i + 4;
+
+       string str;
+       str.resize(i + 2);
+       memcpy((void*)str.c_str(), m_buff.data(), i + 2);
+
+       if (parser_response(str))
+               return -1;
+
+       return 0;
+}
+
+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 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_transfered = 0;
+
+       if (left)
+       {
+               
+               trim_transfered = sz;
+               if (trim_transfered > left)
+                       trim_transfered = left;
+
+               memcpy(buff, m_buff.data() + m_data_start, trim_transfered);
+               m_data_start += trim_transfered;
+       }
+
+       if (trim_transfered < sz)
+       {
+               int ret = 0;
+               sz -= trim_transfered;
+               buff += trim_transfered;
+               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
diff --git a/libuuu/http.h b/libuuu/http.h
new file mode 100644 (file)
index 0000000..66321a7
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * 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 <string>
+#include <vector>
+#include <map>
+
+class HttpStream
+{
+       std::vector<uint8_t> m_buff;
+       int m_socket = -1;
+       std::map<std::string, std::string> 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);
+};
diff --git a/libuuu/libcomm.h b/libuuu/libcomm.h
new file mode 100644 (file)
index 0000000..81191fd
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+* 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 <string>
+#include <stdarg.h>
+#include <locale>
+
+#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_suceeded = nullptr);
+uint32_t str_to_uint32(const string &str, bool * conversion_suceeded = nullptr);
+uint64_t str_to_uint64(const string &str, bool * conversion_suceeded = nullptr);
+
+template <class T>
+inline T round_up(T x, T align)
+{
+       return (x + align - 1) / align * align;
+}
diff --git a/libuuu/liberror.h b/libuuu/liberror.h
new file mode 100644 (file)
index 0000000..0bf6b4b
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+* 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 <string>
+
+void set_last_err_string(const std::string &str);
+void set_last_err_id(int id);
+
diff --git a/libuuu/libuuu.h b/libuuu/libuuu.h
new file mode 100644 (file)
index 0000000..332533e
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+* 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 <stdint.h>
+#include <stddef.h>
+
+#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,
+               NOFITY_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, 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);
+
+/*Set timeout wait for known devices appeared*/
+int uuu_set_wait_timeout(int second);
+/*Set usb device polling period */
+void uuu_set_poll_period(int msecond);
+/*
+ * bit 0:15 for libusb
+ * bit 16:31 for uuu
+ */
+void uuu_set_debug_level(uint32_t mask);
+
+#endif
diff --git a/libuuu/notify.cpp b/libuuu/notify.cpp
new file mode 100644 (file)
index 0000000..4739e4e
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+* 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 <chrono>
+#include <iostream>
+#include <map>
+#include <mutex>
+#include <thread>
+
+using namespace std;
+
+static map<uuu_notify_fun, void*> g_notification_map;
+static mutex g_mutex_notify;
+
+using namespace std::chrono;
+static const time_point<steady_clock> g_now = steady_clock::now();
+
+int uuu_register_notify_callback(uuu_notify_fun f, void *data)
+{
+       std::lock_guard<mutex> 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<mutex> 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<mutex> lock(g_mutex_notify);
+
+       nf.id = std::hash<std::thread::id>{}(std::this_thread::get_id());
+       nf.timestamp = static_cast<uint64_t>(
+               duration_cast<milliseconds>(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;
+               }
+       }
+}
diff --git a/libuuu/rominfo.cpp b/libuuu/rominfo.cpp
new file mode 100644 (file)
index 0000000..ded0b41
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+* 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 <array>
+
+using namespace std;
+
+static constexpr std::array<ROM_INFO, 15> g_RomInfo
+{
+       ROM_INFO{ "MX6Q",        0x00910000, ROM_INFO_HID | ROM_INFO_HID_MX6 },
+       ROM_INFO{ "MX6D",        0x00910000, ROM_INFO_HID | ROM_INFO_HID_MX6 },
+       ROM_INFO{ "MX6SL",       0x00910000, ROM_INFO_HID | ROM_INFO_HID_MX6 },
+       ROM_INFO{ "MX7D",        0x00911000, ROM_INFO_HID | ROM_INFO_HID_MX6 | ROM_INFO_HID_SKIP_DCD },
+       ROM_INFO{ "MX6UL",       0x00910000, ROM_INFO_HID | ROM_INFO_HID_MX6 | ROM_INFO_HID_SKIP_DCD },
+       ROM_INFO{ "MX6ULL",      0x00910000, ROM_INFO_HID | ROM_INFO_HID_MX6 | ROM_INFO_HID_SKIP_DCD },
+       ROM_INFO{ "MX6SLL",      0x00910000, ROM_INFO_HID | ROM_INFO_HID_MX6 | ROM_INFO_HID_SKIP_DCD },
+       ROM_INFO{ "MX8MQ",       0x00910000, ROM_INFO_HID | ROM_INFO_HID_MX6 | ROM_INFO_HID_SKIP_DCD },
+       ROM_INFO{ "MX7ULP",      0x2f018000, ROM_INFO_HID | ROM_INFO_HID_MX6 | ROM_INFO_HID_SKIP_DCD },
+       ROM_INFO{ "MXRT106X",    0x1000,     ROM_INFO_HID | ROM_INFO_HID_MX6 | ROM_INFO_HID_SKIP_DCD },
+       ROM_INFO{ "MX8QXP",      0x0,        ROM_INFO_HID | ROM_INFO_HID_NO_CMD | ROM_INFO_HID_UID_STRING },
+       ROM_INFO{ "MX28",        0x0,        ROM_INFO_HID},
+       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{ "SPL",         0x0,        ROM_INFO_HID | ROM_INFO_HID_MX6 | ROM_INFO_SPL_JUMP | ROM_INFO_HID_SDP_NO_MAX_PER_TRANS},
+       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},
+};
+
+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_V2X = 0x0B;
+
+#pragma pack ()
+
+
+size_t GetContainerActualSize(shared_ptr<FileBuffer> p, size_t offset)
+{
+       auto hdr = reinterpret_cast<struct rom_container *>(p->data() + offset + CONTAINER_HDR_ALIGNMENT);
+       if (hdr->tag != CONTAINER_TAG)
+       {
+               return p->size() - offset;
+       }
+
+       /* Check if include V2X container*/
+       auto image = reinterpret_cast<struct rom_bootimg *>(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<struct rom_container *>(p->data() + offset + cindex * CONTAINER_HDR_ALIGNMENT);
+               if (hdr->tag != CONTAINER_TAG)
+                {
+                       return p->size() - offset;
+               }
+       }
+
+       image = reinterpret_cast<struct rom_bootimg *>(p->data() + offset + cindex * CONTAINER_HDR_ALIGNMENT
+               + sizeof(struct rom_container)
+               + sizeof(struct rom_bootimg) * (hdr->num_images - 1));
+
+       uint32_t sz = image->size + image->offset + cindex * CONTAINER_HDR_ALIGNMENT;
+
+       sz = round_up(sz, static_cast<uint32_t>(CONTAINER_HDR_ALIGNMENT));
+
+       if (sz > (p->size() - offset))
+       {
+               return p->size() - offset;
+       }
+
+       return sz;
+}
+
+bool CheckHeader(uint32_t *p)
+{
+       static constexpr std::array <uint32_t, 2> FlashHeaderMagic
+       {
+               0xc0ffee01,
+               0x42464346
+       };
+
+       for (const auto magic_val : FlashHeaderMagic)
+       {
+               if (*p == magic_val)
+               {
+                       return true;
+               }
+       }
+
+       return false;
+}
+
+size_t GetFlashHeaderSize(shared_ptr<FileBuffer> p, size_t offset)
+{
+       static constexpr std::array<size_t, 4> offsets
+       {
+               0,
+               0x400,
+               0x1fc,
+               0x5fc
+       };
+
+       for (const auto test_offset : offsets) {
+               if (p->size() < (offset + test_offset)) {
+                       return 0;
+               }
+
+               if (CheckHeader(reinterpret_cast<uint32_t*>(p->data() + offset + test_offset))) {
+                       return 0x1000;
+               }
+       }
+
+       return 0;
+}
diff --git a/libuuu/rominfo.h b/libuuu/rominfo.h
new file mode 100644 (file)
index 0000000..2e5e103
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+* 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 <cstdint>
+#include <memory>
+#include <string>
+
+class ConfigItem;
+class FileBuffer;
+
+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;
+
+struct ROM_INFO
+{
+       const char * m_name;
+       uint32_t    free_addr;
+       uint32_t        flags;
+};
+
+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<FileBuffer> p, size_t offset);
+size_t GetFlashHeaderSize(std::shared_ptr<FileBuffer> p, size_t offset = 0);
diff --git a/libuuu/sdp.cpp b/libuuu/sdp.cpp
new file mode 100644 (file)
index 0000000..6be9b94
--- /dev/null
@@ -0,0 +1,681 @@
+/*
+* 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 <string>
+#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 <cstring>
+
+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)); return 0;
+}
+
+IvtHeader *SDPCmdBase::search_ivt_header(shared_ptr<FileBuffer> data, size_t &off, size_t limit)
+{
+       if (limit >= data->size())
+               limit = data->size();
+
+       for (; off < limit; off += 0x100)
+       {
+               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<FileBuffer> buff = get_file_buffer(m_filename);
+
+       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];
+
+       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;
+       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;
+       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);
+}
+
+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);
+       }
+       SDPDcdCmd dcd((char *)str.c_str());
+       if (dcd.parser()) return -1;
+       if (dcd.run(ctx)) return -1;
+
+       str = "SDP: write -f ";
+       str += m_filename;
+       str += " -ivt 0";
+       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";
+       if (m_clear_dcd)
+               str += " -cleardcd";
+
+       SDPJumpCmd jmp((char *)str.c_str());
+       if (!m_nojump)
+       {
+               if (jmp.parser()) return -1;
+               if (jmp.run(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;
+       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;
+
+       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("-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);
+}
+
+int SDPWriteCmd::run(CmdCtx*ctx)
+{
+       size_t size;
+       uint8_t *pbuff;
+       int offset = 0;
+
+       shared_ptr<FileBuffer> fbuff = get_file_buffer(m_filename);
+
+       if (fbuff == nullptr)
+               return -1;
+
+       if (m_Ivt < 0)
+       {
+               pbuff = fbuff->data();
+               size = fbuff->size();
+
+               offset = m_offset;
+
+               if (m_bskipfhdr)
+                       offset += GetFlashHeaderSize(fbuff, offset);
+
+               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)
+                       {
+                               BootData *pDB = (BootData *) &(fbuff->at(off + pIvt->BootData - pIvt->SelfAddr));
+                               offset = off + pDB->ImageSize - (pIvt->SelfAddr - pDB->ImageStartAddr);
+                       }
+                       else
+                       {
+                               offset += GetContainerActualSize(fbuff, offset);
+                       }
+
+                       if (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 += 0x100;
+                       pIvt = search_ivt_header(fbuff, off);
+               }
+               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);
+
+               //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;
+
+               pbuff = (uint8_t*)pIvt;
+       }
+       return run(ctx, pbuff + offset, size, m_download_addr);
+}
+
+int SDPWriteCmd::run(CmdCtx *ctx, void *pbuff, size_t size, uint32_t addr)
+{
+       HIDTrans dev;
+       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 (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;
+       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;
+       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_bool);
+       insert_param_info("-plugin", &m_Ivt, 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;
+       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<FileBuffer> buff = get_file_buffer(m_filename);
+
+       size_t off = 0;
+       IvtHeader *pIVT = search_ivt_header(buff, off);
+
+       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<uint8_t> 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<uint8_t> 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;
+}
diff --git a/libuuu/sdp.h b/libuuu/sdp.h
new file mode 100644 (file)
index 0000000..dc4b026
--- /dev/null
@@ -0,0 +1,216 @@
+/*
+* 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 <climits>
+
+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<FileBuffer> data, size_t &off, size_t limit=ULLONG_MAX);
+
+       std::string m_filename;
+       SDPCmd m_spdcmd;
+
+private:
+       int send_cmd(HIDReport *p);
+
+       std::vector<uint8_t> 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);
+
+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;
+       bool m_bskipfhdr;
+};
+
+class SDPJumpCmd : public SDPCmdBase
+{
+public:
+       SDPJumpCmd(char*p);
+       int run(CmdCtx *p) override;
+
+private:
+       bool m_clear_dcd = false;
+       bool m_Ivt;
+       uint32_t m_jump_addr = 0;
+       bool m_PlugIn;
+};
+
+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 m_clear_dcd = false;
+       uint32_t m_dcd_addr = 0;
+       bool m_nojump = false;
+};
diff --git a/libuuu/sdps.cpp b/libuuu/sdps.cpp
new file mode 100644 (file)
index 0000000..388e3ab
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+* 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 <string>
+#include "sdps.h"
+#include "hidreport.h"
+#include "liberror.h"
+#include "libcomm.h"
+#include "buffer.h"
+#include "sdp.h"
+#include "trans.h"
+
+#include <cstring>
+
+//------------------------------------------------------------------------------
+// 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"
+
+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;
+       if (rom->flags & ROM_INFO_HID_EP1)
+               dev.set_hid_out_ep(1);
+
+       if(dev.open(pro->m_dev))
+               return -1;
+
+       shared_ptr<FileBuffer> p = get_file_buffer(m_filename);
+       if (!p)
+               return -1;
+
+       HIDReport report(&dev);
+       report.set_skip_notify(false);
+
+       size_t offset = m_offset;
+
+       if (m_bskipflashheader)
+               offset += GetFlashHeaderSize(p, offset);
+
+       if (offset >= p->size())
+       {
+               set_last_err_string("Offset bigger than file size");
+               return -1;
+       }
+
+       size_t sz = GetContainerActualSize(p, offset);
+
+       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;
+}
diff --git a/libuuu/sdps.h b/libuuu/sdps.h
new file mode 100644 (file)
index 0000000..9802b73
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+* 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);
+       }
+       int run(CmdCtx *p) override;
+
+private:
+       bool m_bskipflashheader;
+       std::string m_filename;
+       uint32_t m_offset = 0;
+};
diff --git a/libuuu/sparse.cpp b/libuuu/sparse.cpp
new file mode 100644 (file)
index 0000000..263a4be
--- /dev/null
@@ -0,0 +1,224 @@
+/*
+ * 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 <cstddef>
+#include <cstring>
+
+chunk_header_t * SparseFile::get_next_chunk(uint8_t *p, size_t &pos)
+{
+       if (pos == 0)
+       {
+               sparse_header *pheader = (sparse_header*)p;
+               if (pheader->magic != SPARSE_HEADER_MAGIC) {
+                       set_last_err_string("Sparse heade Magic missed");
+                       return nullptr;
+               }
+               pos += pheader->file_hdr_sz;
+       }
+
+       chunk_header_t *pchunk = (chunk_header_t*)(p + pos);
+       pos += pchunk->total_sz;
+       return pchunk;
+}
+
+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)
+{
+       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 = is_same_value(data, pheader->blk_sz) ? CHUNK_TYPE_FILL : CHUNK_TYPE_RAW;
+       int type = 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 = (type == CHUNK_TYPE_FILL) ? sizeof(uint32_t) : pheader->blk_sz;
+               header.total_sz += sizeof(chunk_header_t);
+               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
+                       push(data, sizeof(uint32_t));
+       }
+       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);
+}
diff --git a/libuuu/sparse.h b/libuuu/sparse.h
new file mode 100644 (file)
index 0000000..7d0af05
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+* 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 <cstddef>
+#include <vector>
+
+class SparseFile
+{
+public:
+       std::vector<uint8_t> 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);
+       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;
+};
diff --git a/libuuu/sparse_format.h b/libuuu/sparse_format.h
new file mode 100644 (file)
index 0000000..7347f6d
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * 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 <cstdint>
+
+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 higer 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
diff --git a/libuuu/tar.cpp b/libuuu/tar.cpp
new file mode 100644 (file)
index 0000000..2473cd5
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * 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 <stdint.h>
+#include <map>
+#include <string>
+#include <vector>
+#include "zlib.h"
+#include <memory>
+#include "buffer.h"
+#include "liberror.h"
+#include "libuuu.h"
+#include <stdio.h>
+#include <string.h>
+#include "tar.h"
+#include <fstream>
+#include <iostream>
+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<FileBuffer> 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<FileBuffer> 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<FileBuffer> 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;
+}
+
diff --git a/libuuu/tar.h b/libuuu/tar.h
new file mode 100644 (file)
index 0000000..19ea05a
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * 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 <cstdint>
+#include <map>
+#include <memory>
+#include <string>
+
+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<std::string, Tar_file_Info> 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<FileBuffer> p);
+};
diff --git a/libuuu/trans.cpp b/libuuu/trans.cpp
new file mode 100644 (file)
index 0000000..ed11235
--- /dev/null
@@ -0,0 +1,299 @@
+/*
+* 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 "libuuu.h"
+#include "liberror.h"
+#include "libusb.h"
+
+extern "C"
+{
+#include "libusb.h"
+}
+
+using namespace std;
+
+TransBase::~TransBase()
+{
+}
+
+int TransBase::read(vector<uint8_t> &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;
+       libusb_device_handle * handle = (libusb_device_handle *)m_devhandle;
+       if (libusb_kernel_driver_active(handle, 0))
+       {
+               int ret = libusb_detach_kernel_driver((libusb_device_handle *)m_devhandle, 0);
+               if(ret <0 && ret != LIBUSB_ERROR_NOT_SUPPORTED)
+               {
+                       set_last_err_string("detach kernel driver failure");
+                       return -1;
+               }
+       }
+
+       if (libusb_claim_interface(handle, 0))
+       {
+               set_last_err_string("Failure claim interface");
+               return -1;
+       }
+
+       libusb_config_descriptor *config;
+       if (libusb_get_active_config_descriptor(libusb_get_device(handle), &config))
+       {
+               set_last_err_string("Can't get config descriptor");
+               return -1;
+       }
+
+       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)
+{
+       if (USBTrans::open(p))
+               return -1;
+
+       for (const auto &ep : m_EPs)
+       {
+               if (ep.addr > 0 && ((ep.addr & 0x80) == 0))
+                       m_outEP = ep.addr;
+       }
+
+       return 0;
+}
+
+int HIDTrans::write(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,
+                       1000
+               );
+       }
+       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,
+                       1000
+               );
+       }
+
+       if (ret < 0)
+       {
+               string err;
+               err = "HID(W):";
+               err += libusb_error_name(ret);
+               set_last_err_string(err);
+               return ret;
+       }
+
+       return ret;
+}
+
+int HIDTrans::read(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_read_timeout
+       );
+
+       *rsize = actual;
+
+       if (ret < 0)
+       {
+               string error;
+               string err;
+               err = "HID(R):";
+               err += libusb_error_name(ret);
+               set_last_err_string(err);
+               return ret;
+       }
+
+       return 0;
+}
+
+int BulkTrans::write(void *buff, size_t size)
+{
+       int ret;
+       int actual_lenght;
+       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_lenght,
+                       m_timeout
+               );
+
+               if (ret < 0)
+               {
+                       string error;
+                       string err;
+                       err = "Bulk(W):";
+                       err += libusb_error_name(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_lenght,
+                       2000
+               );
+
+               if (ret < 0)
+               {
+                       string error;
+                       string err;
+                       err = "Bulk(W):";
+                       err += libusb_error_name(ret);
+                       set_last_err_string(err);
+                       return ret;
+               }
+       }
+
+       return ret;
+}
+
+int BulkTrans::open(void *p)
+{
+       if (USBTrans::open(p))
+               return -1;
+
+       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(void *buff, size_t size, size_t *rsize)
+{
+       int ret;
+       int actual_lenght;
+       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_lenght,
+               m_timeout
+       );
+
+       *rsize = actual_lenght;
+
+       if (ret < 0)
+       {
+               string error;
+               string err;
+               err = "Bulk(R):";
+               err += libusb_error_name(ret);
+               set_last_err_string(err);
+               return ret;
+       }
+
+       return ret;
+}
diff --git a/libuuu/trans.h b/libuuu/trans.h
new file mode 100644 (file)
index 0000000..3f137d4
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+* 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 <atomic>
+#include <string>
+#include <vector>
+
+class TransBase
+{
+public:
+       TransBase() = default;
+       TransBase(const TransBase&) = delete;
+       TransBase& operator=(const TransBase&) = delete;
+       virtual ~TransBase();
+
+       virtual int open(void *) { return 0; }
+       virtual int close() { return 0; }
+       virtual int write(void *buff, size_t size) = 0;
+       virtual int read(void *buff, size_t size, size_t *return_size) = 0;
+       int write(std::vector<uint8_t> & buff) { return write(buff.data(), buff.size()); }
+       int read(std::vector<uint8_t> &buff);
+
+protected:
+       void * m_devhandle = nullptr;
+};
+
+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:
+       int open(void *p) override;
+       int close() override;
+
+protected:
+       std::vector<EPInfo> m_EPs;
+};
+class HIDTrans : public USBTrans
+{
+public:
+       HIDTrans(int read_timeout = 1000) : m_read_timeout{read_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; }
+       int write(void *buff, size_t size) override;
+       int read(void *buff, size_t size, size_t *return_size) override;
+
+private:
+       int m_outEP = 0;
+       const int m_read_timeout = 1000;
+       int m_set_report = 9;
+};
+
+class BulkTrans : public USBTrans
+{
+public:
+       BulkTrans(uint64_t timeout = 2000) : m_timeout{timeout} {}
+       ~BulkTrans() override { if (m_devhandle) close();  m_devhandle = nullptr; }
+
+       int open(void *p) override;
+       int write(void *buff, size_t size) override;
+       int read(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;
+       uint64_t m_timeout = 2000;
+};
+
+int polling_usb(std::atomic<int>& bexit);
diff --git a/libuuu/usbhotplug.cpp b/libuuu/usbhotplug.cpp
new file mode 100644 (file)
index 0000000..719aa0e
--- /dev/null
@@ -0,0 +1,432 @@
+/*
+* 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 <thread>
+#include <atomic>
+#include "libusb.h"
+#include "liberror.h"
+#include "config.h"
+#include "cmd.h"
+#include "libcomm.h"
+#include "libuuu.h"
+#include "vector"
+#include <time.h>
+
+static vector<thread> g_running_thread;
+
+static vector<string> g_filter_usbpath;
+
+static int g_wait_usb_timeout = -1;
+static int g_usb_poll_period = 0;
+
+static int g_known_device_appeared;
+
+static int g_libusb_init;
+
+#ifdef _MSC_VER
+#define TRY_SUDO
+#else
+#define TRY_SUDO ",Try sudo uuu"
+#endif
+
+static bool is_match_filter(string path)
+{
+       if (g_filter_usbpath.empty())
+               return true;
+       for (size_t i = 0; i < g_filter_usbpath.size(); i++)
+               if (g_filter_usbpath[i] == path)
+                       return true;
+
+       return false;
+}
+
+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;
+}
+
+static int run_usb_cmds(ConfigItem *item, libusb_device *dev)
+{
+       int ret;
+       uuu_notify nt;
+       nt.type = uuu_notify::NOFITY_DEV_ATTACH;
+
+       string str;
+       str = get_device_path(dev);
+       nt.str = (char*)str.c_str();
+       call_notify(nt);
+
+       CmdUsbCtx ctx;
+       ctx.m_config_item = item;
+
+       /* work around windows open device failure 1/10
+        * sometime HID device detect need some time, refresh list
+        * to make sure HID driver installed.
+        */
+       libusb_device **list = nullptr;
+       libusb_get_device_list(nullptr, &list);
+
+       if (libusb_open(dev, (libusb_device_handle **)&(ctx.m_dev)) < 0)
+       {
+               set_last_err_string("Failure open usb device" TRY_SUDO);
+               nt.type = uuu_notify::NOTIFY_CMD_END;
+               nt.status = -1;
+               call_notify(nt);
+               libusb_free_device_list(list, 1);
+               return -1;
+       }
+
+       ret = run_cmds(item->m_protocol.c_str(), &ctx);
+
+       libusb_free_device_list(list, 1);
+
+       nt.type = uuu_notify::NOTIFY_THREAD_EXIT;
+       call_notify(nt);
+
+       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 descrior");
+               return r;
+       }
+
+       string str;
+       str = get_device_path(dev);
+       if (!is_match_filter(str))
+               return -1;
+
+       ConfigItem *item = get_config()->find(desc.idVendor, desc.idProduct, desc.bcdDevice);
+       int poll = g_usb_poll_period ? g_usb_poll_period : 200;
+       std::this_thread::sleep_for(std::chrono::milliseconds(poll));
+
+       if (item)
+       {
+               g_known_device_appeared = 1;
+               std::thread(run_usb_cmds, item, dev).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);
+       }
+}
+
+int polling_usb(std::atomic<int>& bexit)
+{
+       libusb_device **oldlist = nullptr;
+       libusb_device **newlist = nullptr;
+
+       if (!g_libusb_init)
+       {
+               if (libusb_init(nullptr) < 0)
+               {
+                       set_last_err_string("Call libusb_init failure");
+                       return -1;
+               }
+               g_libusb_init = true;
+               libusb_set_debug(nullptr, get_libusb_debug_level());
+       }
+
+       if (run_cmds("CFG:", nullptr))
+               return -1;
+
+       time_t start = time(0);
+
+       while(!bexit)
+       {
+               ssize_t sz = libusb_get_device_list(nullptr, &newlist);
+               if (sz < 0)
+               {
+                       set_last_err_string("Call libusb_get_device_list failure");
+                       return -1;
+               }
+
+               compare_list(oldlist, newlist);
+
+               if (oldlist)
+                       libusb_free_device_list(oldlist, 1);
+
+               oldlist = newlist;
+
+               int poll = g_usb_poll_period ? g_usb_poll_period : 200;
+               std::this_thread::sleep_for(std::chrono::milliseconds(poll));
+
+               if (g_wait_usb_timeout >= 0 && !g_known_device_appeared)
+               {
+                       if (difftime(time(0), start) >= g_wait_usb_timeout)
+                       {
+                               set_last_err_string("Timeout: Wait for Known USB Device");
+                               return -1;
+                       }
+               }
+       }
+
+       if(newlist)
+               libusb_free_device_list(newlist, 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 (!g_libusb_init)
+       {
+               if (libusb_init(nullptr) < 0)
+               {
+                       set_last_err_string("Call libusb_init failure");
+                       return -1;
+               }
+
+               libusb_set_debug(nullptr, get_libusb_debug_level());
+
+               g_libusb_init = true;
+       }
+
+       if (run_cmds("CFG:", nullptr))
+               return -1;
+
+       time_t start = time(0);
+
+       while (1)
+       {
+               libusb_device **newlist = nullptr;
+               libusb_get_device_list(nullptr, &newlist);
+               size_t i = 0;
+               libusb_device *dev;
+
+               while ((dev = newlist[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 descrior");
+                               return -1;
+                       }
+                       string str = get_device_path(dev);
+
+                       if (!is_match_filter(str))
+                               continue;
+
+                       ConfigItem *item = get_config()->find(desc.idVendor, desc.idProduct, desc.bcdDevice);
+                       if (item && item->m_protocol == str_to_upper(pro))
+                               {
+                                       uuu_notify nt;
+                                       nt.type = uuu_notify::NOFITY_DEV_ATTACH;
+                                       m_config_item = item;
+
+                                       /* work around windows open device failure 1/10
+                                        * sometime HID device detect need some time, refresh list
+                                        * to make sure HID driver installed.
+                                        */
+                                       std::this_thread::sleep_for(std::chrono::milliseconds(200));
+                                       libusb_device **list = nullptr;
+                                       libusb_get_device_list(nullptr, &list);
+
+                                       if (libusb_open(dev, (libusb_device_handle **)&(m_dev)) < 0)
+                                       {
+                                               set_last_err_string("Failure open usb device" TRY_SUDO);
+                                               libusb_free_device_list(list, 1);
+                                               return -1;
+                                       }
+
+                                       libusb_free_device_list(list, 1);
+                                       nt.str = (char*)str.c_str();
+                                       call_notify(nt);
+
+                                       return 0;
+                               }
+               }
+
+               libusb_free_device_list(newlist, 1);
+               std::this_thread::sleep_for(std::chrono::milliseconds(200));
+
+               uuu_notify nt;
+               nt.type = nt.NOTIFY_WAIT_FOR;
+               nt.str = (char*)"Wait for Known USB";
+               call_notify(nt);
+
+               if (g_wait_usb_timeout >= 0)
+               {
+                       if (difftime(time(0), start) >= g_wait_usb_timeout)
+                       {
+                               set_last_err_string("Timeout: Wait for USB Device Appear");
+                               return -1;
+                       }
+               }
+       }
+
+       return -1;
+}
+
+int uuu_add_usbpath_filter(const char *path)
+{
+       g_filter_usbpath.push_back(path);
+       return 0;
+}
+
+int uuu_for_each_devices(uuu_ls_usb_devices fn, void *p)
+{
+       if (!g_libusb_init)
+       {
+               if (libusb_init(nullptr) < 0)
+               {
+                       set_last_err_string("Call libusb_init failure");
+                       return -1;
+               }
+               g_libusb_init = true;
+       }
+       libusb_device **newlist = nullptr;
+       libusb_get_device_list(nullptr, &newlist);
+       size_t i = 0;
+       libusb_device *dev;
+
+       while ((dev = newlist[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 descrior");
+                       return -1;
+               }
+               string str = get_device_path(dev);
+
+               ConfigItem *item = get_config()->find(desc.idVendor, desc.idProduct, desc.bcdDevice);
+               if (item)
+               {
+                       if (fn(str.c_str(), item->m_chip.c_str(), item->m_protocol.c_str(), desc.idVendor, desc.idProduct, desc.bcdDevice, p))
+                       {
+                               set_last_err_string("call back return error");
+                               return -1;
+                       }
+               }
+       }
+
+       libusb_free_device_list(newlist, 1);
+       libusb_exit(nullptr);
+
+       return 0;
+}
+
+int uuu_set_wait_timeout(int second)
+{
+       g_wait_usb_timeout = second;
+       return 0;
+}
+
+void uuu_set_poll_period(int msecond)
+{
+       g_usb_poll_period = msecond;
+}
diff --git a/libuuu/version.cpp b/libuuu/version.cpp
new file mode 100644 (file)
index 0000000..229c5ef
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+* 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 <string>
+
+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<int>(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<int>(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<int>(stoll(temp_num_str, nullptr, 10));
+
+       return (maj << 24) | (min << 12) | build;
+}
diff --git a/libuuu/zip.cpp b/libuuu/zip.cpp
new file mode 100644 (file)
index 0000000..08dc923
--- /dev/null
@@ -0,0 +1,330 @@
+/*
+* 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 <string.h>
+#include <iostream>
+#include <fstream>
+#include "buffer.h"
+#include "libcomm.h"
+#include "libuuu.h"
+#include "liberror.h"
+#include "zip.h"
+
+#define CHUNK 0x10000
+
+int Zip::BuildDirInfo()
+{
+       shared_ptr<FileBuffer> 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_SIGNTURE)
+               {
+                       set_last_err_string("DIR signature missmatched");
+                       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_modidfy_date << 16) + pdir->last_modidfy_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<FileBuffer> 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_ptr<FileBuffer>p)
+{
+       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<FileBuffer> 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("Unsupport 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 */
+               case Z_DATA_ERROR:
+               case Z_MEM_ERROR:
+                       (void)inflateEnd(&m_strm);
+                       return -1;
+               }
+               size_t have = each_out_size - m_strm.avail_out;
+
+               p->m_avaible_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_avaible_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;
+}
diff --git a/libuuu/zip.h b/libuuu/zip.h
new file mode 100644 (file)
index 0000000..37676bc
--- /dev/null
@@ -0,0 +1,192 @@
+/*
+* 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 <cstdint>
+#include <map>
+#include <memory>
+
+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_modidfy_time;
+       uint16_t last_modidfy_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_modidfy_time;
+       uint16_t last_modidfy_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_modidfy_time;
+       uint16_t last_modidfy_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_SIGNTURE 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<FileBuffer> 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;
+       bool m_decompressed;
+
+       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_ptr<FileBuffer>p);
+       int Open(std::string filename);
+
+       std::map<std::string, Zip_file_Info> m_filemap;
+};
+
+
+#pragma pack()
diff --git a/msvc/bzip2.vcxproj b/msvc/bzip2.vcxproj
new file mode 100644 (file)
index 0000000..41c6cb8
--- /dev/null
@@ -0,0 +1,227 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\bzip2\blocksort.c">
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
+    </ClCompile>
+    <ClCompile Include="..\bzip2\bzip2.c">
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
+    </ClCompile>
+    <ClCompile Include="..\bzip2\bzip2recover.c">
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
+    </ClCompile>
+    <ClCompile Include="..\bzip2\bzlib.c">
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
+    </ClCompile>
+    <ClCompile Include="..\bzip2\compress.c">
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
+    </ClCompile>
+    <ClCompile Include="..\bzip2\crctable.c">
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
+    </ClCompile>
+    <ClCompile Include="..\bzip2\decompress.c">
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
+    </ClCompile>
+    <ClCompile Include="..\bzip2\huffman.c">
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
+    </ClCompile>
+    <ClCompile Include="..\bzip2\mk251.c">
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
+    </ClCompile>
+    <ClCompile Include="..\bzip2\randtable.c">
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
+    </ClCompile>
+    <ClCompile Include="..\bzip2\spewG.c">
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
+    </ClCompile>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <VCProjectVersion>15.0</VCProjectVersion>
+    <ProjectGuid>{B54C35CD-5FFE-4FEA-90BA-32894BCFC6BF}</ProjectGuid>
+    <Keyword>Win32Proj</Keyword>
+    <RootNamespace>bzip2</RootNamespace>
+    <WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="Shared">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <LinkIncremental>true</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <LinkIncremental>true</LinkIncremental>
+    <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <LinkIncremental>false</LinkIncremental>
+    <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <LinkIncremental>false</LinkIncremental>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>Use</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <SDLCheck>false</SDLCheck>
+      <PreprocessorDefinitions>_DEBUG;_LIB;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS; _CRT_NONSTDC_NO_DEPRECATE;;_CRT_SECURE_NO_WARNINGS; _CRT_NONSTDC_NO_DEPRECATE;</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+    <Lib>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>Use</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <SDLCheck>false</SDLCheck>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)  _CRT_SECURE_NO_WARNINGS setmode=_setmode;_CRT_SECURE_NO_WARNINGS; _CRT_NONSTDC_NO_DEPRECATE;</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>Use</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>false</SDLCheck>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)  _CRT_SECURE_NO_WARNINGS setmode=_setmode;_CRT_SECURE_NO_WARNINGS; _CRT_NONSTDC_NO_DEPRECATE;</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <PrecompiledHeader>Use</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>false</SDLCheck>
+      <PreprocessorDefinitions>NDEBUG;_LIB;%(PreprocessorDefinitions)  _CRT_SECURE_NO_WARNINGS setmode=_setmode;_CRT_SECURE_NO_WARNINGS; _CRT_NONSTDC_NO_DEPRECATE;</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/msvc/bzip2.vcxproj.filters b/msvc/bzip2.vcxproj.filters
new file mode 100644 (file)
index 0000000..1dc7d08
--- /dev/null
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="Source Files">
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+    <Filter Include="Header Files">
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
+    </Filter>
+    <Filter Include="Resource Files">
+      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\bzip2\blocksort.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\bzip2\bzip2.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\bzip2\bzip2recover.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\bzip2\bzlib.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\bzip2\compress.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\bzip2\crctable.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\bzip2\decompress.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\bzip2\huffman.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\bzip2\mk251.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\bzip2\randtable.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\bzip2\spewG.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/msvc/createversion.bat b/msvc/createversion.bat
new file mode 100644 (file)
index 0000000..0e09573
--- /dev/null
@@ -0,0 +1,16 @@
+@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 uuu_%APPVEYOR_BUILD_VERSION%
+       ) 
+
+       FOR /F "tokens=*" %%a in ('call git describe --tags --long') do (
+               echo #define GIT_VERSION "lib%%a" > %1/gitversion.h
+       )
+)
\ No newline at end of file
diff --git a/msvc/libuuu.filters b/msvc/libuuu.filters
new file mode 100644 (file)
index 0000000..92cb56c
--- /dev/null
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="Source Files">
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+    <Filter Include="Header Files">
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
+    </Filter>
+    <Filter Include="Resource Files">
+      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="stdafx.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="targetver.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="stdafx.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/msvc/libuuu.vcxproj b/msvc/libuuu.vcxproj
new file mode 100644 (file)
index 0000000..6a84e20
--- /dev/null
@@ -0,0 +1,218 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\libuuu\buffer.cpp" />
+    <ClCompile Include="..\libuuu\cmd.cpp" />
+    <ClCompile Include="..\libuuu\config.cpp" />
+    <ClCompile Include="..\libuuu\error.cpp" />
+    <ClCompile Include="..\libuuu\fastboot.cpp" />
+    <ClCompile Include="..\libuuu\fat.cpp" />
+    <ClCompile Include="..\libuuu\hidreport.cpp" />
+    <ClCompile Include="..\libuuu\http.cpp" />
+    <ClCompile Include="..\libuuu\notify.cpp" />
+    <ClCompile Include="..\libuuu\rominfo.cpp" />
+    <ClCompile Include="..\libuuu\sdp.cpp" />
+    <ClCompile Include="..\libuuu\sdps.cpp" />
+    <ClCompile Include="..\libuuu\sparse.cpp" />
+    <ClCompile Include="..\libuuu\tar.cpp" />
+    <ClCompile Include="..\libuuu\trans.cpp" />
+    <ClCompile Include="..\libuuu\usbhotplug.cpp" />
+    <ClCompile Include="..\libuuu\version.cpp" />
+    <ClCompile Include="..\libuuu\zip.cpp" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\libuuu\backfile.h" />
+    <ClInclude Include="..\libuuu\buffer.h" />
+    <ClInclude Include="..\libuuu\cmd.h" />
+    <ClInclude Include="..\libuuu\config.h" />
+    <ClInclude Include="..\libuuu\fastboot.h" />
+    <ClInclude Include="..\libuuu\hidreport.h" />
+    <ClInclude Include="..\libuuu\http.h" />
+    <ClInclude Include="..\libuuu\libcomm.h" />
+    <ClInclude Include="..\libuuu\liberror.h" />
+    <ClInclude Include="..\libuuu\libuuu.h" />
+    <ClInclude Include="..\libuuu\rominfo.h" />
+    <ClInclude Include="..\libuuu\sdps.h" />
+    <ClInclude Include="..\libuuu\sdp.h" />
+    <ClInclude Include="..\libuuu\sparse.h" />
+    <ClInclude Include="..\libuuu\sparse_format.h" />
+    <ClInclude Include="..\libuuu\tar.h" />
+    <ClInclude Include="..\libuuu\trans.h" />
+    <ClInclude Include="..\libuuu\zip.h" />
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <VCProjectVersion>15.0</VCProjectVersion>
+    <ProjectGuid>{048A9BD1-EEF8-4119-9DEF-219D7E177AAC}</ProjectGuid>
+    <Keyword>Win32Proj</Keyword>
+    <RootNamespace>StaticLib1</RootNamespace>
+    <WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="Shared">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <LinkIncremental>true</LinkIncremental>
+    <IntDir>$(Configuration)\$(ProjectName)\</IntDir>
+    <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
+    <IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);..\zlib;..\libsparse\include;..\bzip2</IncludePath>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <LinkIncremental>true</LinkIncremental>
+    <IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);..\zlib;..\libsparse\include;..\bzip2</IncludePath>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <LinkIncremental>false</LinkIncremental>
+    <IntDir>$(Configuration)\$(ProjectName)\</IntDir>
+    <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
+    <IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);..\zlib;..\libsparse\include;..\bzip2</IncludePath>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <LinkIncremental>false</LinkIncremental>
+    <IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);..\zlib;..\libsparse\include;..\bzip2</IncludePath>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+      <AdditionalIncludeDirectories>..\libusb\libusb</AdditionalIncludeDirectories>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+    <PreBuildEvent>
+      <Command>createversion.bat ..\libuuu</Command>
+    </PreBuildEvent>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+      <AdditionalIncludeDirectories>..\libusb\libusb</AdditionalIncludeDirectories>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+    <PreBuildEvent>
+      <Command>createversion.bat ..\libuuu</Command>
+    </PreBuildEvent>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+      <AdditionalIncludeDirectories>..\libusb\libusb</AdditionalIncludeDirectories>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+    <PreBuildEvent>
+      <Command>createversion.bat ..\libuuu</Command>
+    </PreBuildEvent>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+      <AdditionalIncludeDirectories>..\libusb\libusb</AdditionalIncludeDirectories>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+    <PreBuildEvent>
+      <Command>createversion.bat ..\libuuu</Command>
+    </PreBuildEvent>
+  </ItemDefinitionGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/msvc/libuuu.vcxproj.filters b/msvc/libuuu.vcxproj.filters
new file mode 100644 (file)
index 0000000..9970701
--- /dev/null
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="Header Files">
+      <UniqueIdentifier>{56b8d729-e8e8-4b90-be62-ef7a1d4e77c2}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files">
+      <UniqueIdentifier>{9880b066-0013-4325-97c5-de85ce13b31f}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\libuuu\backfile.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\libuuu\liberror.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\libuuu\libuuu.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\libuuu\libcomm.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\libuuu\cmd.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\libuuu\buffer.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\libuuu\config.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\libuuu\sdps.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\libuuu\hidreport.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\libuuu\trans.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\libuuu\sdp.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\libuuu\fastboot.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\libuuu\zip.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\libuuu\sparse.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\libuuu\sparse_format.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\libuuu\rominfo.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\libuuu\tar.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\libuuu\http.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\libuuu\error.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\libuuu\notify.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\libuuu\version.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\libuuu\cmd.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\libuuu\buffer.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\libuuu\config.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\libuuu\sdps.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\libuuu\sparse.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\libuuu\trans.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\libuuu\usbhotplug.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\libuuu\sdp.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\libuuu\fastboot.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\libuuu\zip.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\libuuu\fat.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\libuuu\rominfo.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\libuuu\tar.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\libuuu\hidreport.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\libuuu\http.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/msvc/uuu-static-link.sln b/msvc/uuu-static-link.sln
new file mode 100644 (file)
index 0000000..b014849
--- /dev/null
@@ -0,0 +1,77 @@
+
+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}") = "libusb-1.0 (static)", "..\libusb\msvc\libusb_static_2017.vcxproj", "{349EE8F9-7D25-4909-AAF5-FF3FADE72187}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "uuu-static-link", "uuu-static-link.vcxproj", "{2950F8EE-7895-4431-858A-C21EE105C242}"
+       ProjectSection(ProjectDependencies) = postProject
+               {59666402-A775-49AC-A9BD-19FD528F5FD9} = {59666402-A775-49AC-A9BD-19FD528F5FD9}
+               {B54C35CD-5FFE-4FEA-90BA-32894BCFC6BF} = {B54C35CD-5FFE-4FEA-90BA-32894BCFC6BF}
+               {048A9BD1-EEF8-4119-9DEF-219D7E177AAC} = {048A9BD1-EEF8-4119-9DEF-219D7E177AAC}
+               {349EE8F9-7D25-4909-AAF5-FF3FADE72187} = {349EE8F9-7D25-4909-AAF5-FF3FADE72187}
+       EndProjectSection
+EndProject
+Global
+       GlobalSection(SolutionConfigurationPlatforms) = preSolution
+               Debug|x64 = Debug|x64
+               Debug|x86 = Debug|x86
+               Release|x64 = Release|x64
+               Release|x86 = Release|x86
+       EndGlobalSection
+       GlobalSection(ProjectConfigurationPlatforms) = postSolution
+               {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|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|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|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|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|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
+               {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|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
+               {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|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
+       EndGlobalSection
+       GlobalSection(SolutionProperties) = preSolution
+               HideSolutionNode = FALSE
+       EndGlobalSection
+       GlobalSection(ExtensibilityGlobals) = postSolution
+               SolutionGuid = {93EA02D1-E396-4390-B160-58909BBB9556}
+       EndGlobalSection
+EndGlobal
diff --git a/msvc/uuu-static-link.vcxproj b/msvc/uuu-static-link.vcxproj
new file mode 100644 (file)
index 0000000..142c072
--- /dev/null
@@ -0,0 +1,312 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\uuu\autocomplete.cpp" />
+    <ClCompile Include="..\uuu\buildincmd.cpp" />
+    <ClCompile Include="..\uuu\uuu.cpp" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\uuu\buildincmd.h" />
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <VCProjectVersion>15.0</VCProjectVersion>
+    <ProjectGuid>{2950F8EE-7895-4431-858A-C21EE105C242}</ProjectGuid>
+    <Keyword>Win32Proj</Keyword>
+    <RootNamespace>uuu</RootNamespace>
+    <WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="Shared">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <LinkIncremental>true</LinkIncremental>
+    <IntDir>$(Configuration)\$(ProjectName)\</IntDir>
+    <OutDir>$(Platform)\$(Configuration)</OutDir>
+    <CustomBuildBeforeTargets>Build</CustomBuildBeforeTargets>
+    <TargetName>uuu</TargetName>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <LinkIncremental>true</LinkIncremental>
+    <CustomBuildBeforeTargets>Build</CustomBuildBeforeTargets>
+    <OutDir>$(Platform)\$(Configuration)</OutDir>
+    <TargetName>uuu</TargetName>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <LinkIncremental>false</LinkIncremental>
+    <IntDir>$(Configuration)\$(ProjectName)\</IntDir>
+    <OutDir>$(Platform)\$(Configuration)</OutDir>
+    <CustomBuildBeforeTargets>Build</CustomBuildBeforeTargets>
+    <TargetName>uuu</TargetName>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <LinkIncremental>false</LinkIncremental>
+    <CustomBuildBeforeTargets>Build</CustomBuildBeforeTargets>
+    <OutDir>$(Platform)\$(Configuration)</OutDir>
+    <TargetName>uuu</TargetName>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <AdditionalDependencies>../libusb/$(Platform)/$(Configuration)/lib/libusb-1.0.lib;$(Platform)/$(Configuration)/libuuu.lib;$(Platform)/$(Configuration)/zlib.lib;%(AdditionalDependencies);$(Platform)/$(Configuration)/bzip2.lib</AdditionalDependencies>
+    </Link>
+    <PreBuildEvent>
+      <Command>echo R^"####( &gt; $(SolutionDir)\..\uuu\uuu.clst
+type $(SolutionDir)\..\uuu\uuu.lst &gt;&gt; $(SolutionDir)\..\uuu\uuu.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\uuu.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\emmc_burn_loader.clst
+type $(SolutionDir)\..\uuu\emmc_burn_loader.lst &gt;&gt; $(SolutionDir)\..\uuu\emmc_burn_loader.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\emmc_burn_loader.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\qspi_burn_loader.clst
+type $(SolutionDir)\..\uuu\qspi_burn_loader.lst &gt;&gt; $(SolutionDir)\..\uuu\qspi_burn_loader.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\qspi_burn_loader.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\sd_burn_loader.clst
+type $(SolutionDir)\..\uuu\sd_burn_loader.lst &gt;&gt; $(SolutionDir)\..\uuu\sd_burn_loader.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\sd_burn_loader.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\spl_boot.clst
+type $(SolutionDir)\..\uuu\spl_boot.lst &gt;&gt; $(SolutionDir)\..\uuu\spl_boot.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\spl_boot.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\emmc_burn_all.clst
+type $(SolutionDir)\..\uuu\emmc_burn_all.lst &gt;&gt; $(SolutionDir)\..\uuu\emmc_burn_all.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\emmc_burn_all.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\sd_burn_all.clst
+type $(SolutionDir)\..\uuu\sd_burn_all.lst &gt;&gt; $(SolutionDir)\..\uuu\sd_burn_all.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\sd_burn_all.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\fat_write.clst
+type $(SolutionDir)\..\uuu\fat_write.lst &gt;&gt; $(SolutionDir)\..\uuu\fat_write.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\fat_write.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\nand_burn_loader.clst
+type $(SolutionDir)\..\uuu\nand_burn_loader.lst &gt;&gt; $(SolutionDir)\..\uuu\nand_burn_loader.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\nand_burn_loader.clst
+</Command>
+    </PreBuildEvent>
+    <CustomBuildStep>
+      <TreatOutputAsContent>true</TreatOutputAsContent>
+    </CustomBuildStep>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <AdditionalDependencies>../libusb/$(Platform)/$(Configuration)/lib/libusb-1.0.lib;$(Platform)/$(Configuration)/libuuu.lib;$(Platform)/$(Configuration)/zlib.lib;%(AdditionalDependencies);$(Platform)/$(Configuration)/bzip2.lib</AdditionalDependencies>
+    </Link>
+    <PreBuildEvent>
+      <Command>echo R^"####( &gt; $(SolutionDir)\..\uuu\uuu.clst
+type $(SolutionDir)\..\uuu\uuu.lst &gt;&gt; $(SolutionDir)\..\uuu\uuu.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\uuu.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\emmc_burn_loader.clst
+type $(SolutionDir)\..\uuu\emmc_burn_loader.lst &gt;&gt; $(SolutionDir)\..\uuu\emmc_burn_loader.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\emmc_burn_loader.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\qspi_burn_loader.clst
+type $(SolutionDir)\..\uuu\qspi_burn_loader.lst &gt;&gt; $(SolutionDir)\..\uuu\qspi_burn_loader.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\qspi_burn_loader.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\sd_burn_loader.clst
+type $(SolutionDir)\..\uuu\sd_burn_loader.lst &gt;&gt; $(SolutionDir)\..\uuu\sd_burn_loader.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\sd_burn_loader.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\spl_boot.clst
+type $(SolutionDir)\..\uuu\spl_boot.lst &gt;&gt; $(SolutionDir)\..\uuu\spl_boot.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\spl_boot.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\emmc_burn_all.clst
+type $(SolutionDir)\..\uuu\emmc_burn_all.lst &gt;&gt; $(SolutionDir)\..\uuu\emmc_burn_all.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\emmc_burn_all.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\sd_burn_all.clst
+type $(SolutionDir)\..\uuu\sd_burn_all.lst &gt;&gt; $(SolutionDir)\..\uuu\sd_burn_all.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\sd_burn_all.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\fat_write.clst
+type $(SolutionDir)\..\uuu\fat_write.lst &gt;&gt; $(SolutionDir)\..\uuu\fat_write.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\fat_write.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\nand_burn_loader.clst
+type $(SolutionDir)\..\uuu\nand_burn_loader.lst &gt;&gt; $(SolutionDir)\..\uuu\nand_burn_loader.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\nand_burn_loader.clst
+</Command>
+    </PreBuildEvent>
+    <CustomBuildStep>
+      <TreatOutputAsContent>true</TreatOutputAsContent>
+    </CustomBuildStep>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <AdditionalDependencies>../libusb/$(Platform)/$(Configuration)/lib/libusb-1.0.lib;$(Platform)/$(Configuration)/libuuu.lib;$(Platform)/$(Configuration)/zlib.lib;%(AdditionalDependencies);$(Platform)/$(Configuration)/bzip2.lib</AdditionalDependencies>
+    </Link>
+    <PreBuildEvent>
+      <Command>echo R^"####( &gt; $(SolutionDir)\..\uuu\uuu.clst
+type $(SolutionDir)\..\uuu\uuu.lst &gt;&gt; $(SolutionDir)\..\uuu\uuu.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\uuu.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\emmc_burn_loader.clst
+type $(SolutionDir)\..\uuu\emmc_burn_loader.lst &gt;&gt; $(SolutionDir)\..\uuu\emmc_burn_loader.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\emmc_burn_loader.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\qspi_burn_loader.clst
+type $(SolutionDir)\..\uuu\qspi_burn_loader.lst &gt;&gt; $(SolutionDir)\..\uuu\qspi_burn_loader.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\qspi_burn_loader.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\sd_burn_loader.clst
+type $(SolutionDir)\..\uuu\sd_burn_loader.lst &gt;&gt; $(SolutionDir)\..\uuu\sd_burn_loader.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\sd_burn_loader.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\spl_boot.clst
+type $(SolutionDir)\..\uuu\spl_boot.lst &gt;&gt; $(SolutionDir)\..\uuu\spl_boot.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\spl_boot.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\emmc_burn_all.clst
+type $(SolutionDir)\..\uuu\emmc_burn_all.lst &gt;&gt; $(SolutionDir)\..\uuu\emmc_burn_all.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\emmc_burn_all.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\sd_burn_all.clst
+type $(SolutionDir)\..\uuu\sd_burn_all.lst &gt;&gt; $(SolutionDir)\..\uuu\sd_burn_all.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\sd_burn_all.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\fat_write.clst
+type $(SolutionDir)\..\uuu\fat_write.lst &gt;&gt; $(SolutionDir)\..\uuu\fat_write.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\fat_write.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\nand_burn_loader.clst
+type $(SolutionDir)\..\uuu\nand_burn_loader.lst &gt;&gt; $(SolutionDir)\..\uuu\nand_burn_loader.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\nand_burn_loader.clst
+</Command>
+    </PreBuildEvent>
+    <CustomBuildStep>
+      <TreatOutputAsContent>true</TreatOutputAsContent>
+    </CustomBuildStep>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <AdditionalDependencies>../libusb/$(Platform)/$(Configuration)/lib/libusb-1.0.lib;$(Platform)/$(Configuration)/libuuu.lib;$(Platform)/$(Configuration)/zlib.lib;%(AdditionalDependencies);$(Platform)/$(Configuration)/bzip2.lib</AdditionalDependencies>
+    </Link>
+    <PreBuildEvent>
+      <Command>echo R^"####( &gt; $(SolutionDir)\..\uuu\uuu.clst
+type $(SolutionDir)\..\uuu\uuu.lst &gt;&gt; $(SolutionDir)\..\uuu\uuu.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\uuu.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\emmc_burn_loader.clst
+type $(SolutionDir)\..\uuu\emmc_burn_loader.lst &gt;&gt; $(SolutionDir)\..\uuu\emmc_burn_loader.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\emmc_burn_loader.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\qspi_burn_loader.clst
+type $(SolutionDir)\..\uuu\qspi_burn_loader.lst &gt;&gt; $(SolutionDir)\..\uuu\qspi_burn_loader.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\qspi_burn_loader.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\sd_burn_loader.clst
+type $(SolutionDir)\..\uuu\sd_burn_loader.lst &gt;&gt; $(SolutionDir)\..\uuu\sd_burn_loader.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\sd_burn_loader.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\spl_boot.clst
+type $(SolutionDir)\..\uuu\spl_boot.lst &gt;&gt; $(SolutionDir)\..\uuu\spl_boot.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\spl_boot.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\emmc_burn_all.clst
+type $(SolutionDir)\..\uuu\emmc_burn_all.lst &gt;&gt; $(SolutionDir)\..\uuu\emmc_burn_all.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\emmc_burn_all.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\sd_burn_all.clst
+type $(SolutionDir)\..\uuu\sd_burn_all.lst &gt;&gt; $(SolutionDir)\..\uuu\sd_burn_all.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\sd_burn_all.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\fat_write.clst
+type $(SolutionDir)\..\uuu\fat_write.lst &gt;&gt; $(SolutionDir)\..\uuu\fat_write.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\fat_write.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\nand_burn_loader.clst
+type $(SolutionDir)\..\uuu\nand_burn_loader.lst &gt;&gt; $(SolutionDir)\..\uuu\nand_burn_loader.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\nand_burn_loader.clst
+</Command>
+    </PreBuildEvent>
+    <CustomBuildStep>
+      <TreatOutputAsContent>true</TreatOutputAsContent>
+    </CustomBuildStep>
+  </ItemDefinitionGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/msvc/uuu.sln b/msvc/uuu.sln
new file mode 100644 (file)
index 0000000..544dcdb
--- /dev/null
@@ -0,0 +1,77 @@
+
+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
+               {59666402-A775-49AC-A9BD-19FD528F5FD9} = {59666402-A775-49AC-A9BD-19FD528F5FD9}
+               {B54C35CD-5FFE-4FEA-90BA-32894BCFC6BF} = {B54C35CD-5FFE-4FEA-90BA-32894BCFC6BF}
+               {048A9BD1-EEF8-4119-9DEF-219D7E177AAC} = {048A9BD1-EEF8-4119-9DEF-219D7E177AAC}
+               {349EE8FA-7D25-4909-AAF5-FF3FADE72187} = {349EE8FA-7D25-4909-AAF5-FF3FADE72187}
+       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}") = "libusb-1.0 (dll)", "..\libusb\msvc\libusb_dll_2017.vcxproj", "{349EE8FA-7D25-4909-AAF5-FF3FADE72187}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bzip2", "bzip2.vcxproj", "{B54C35CD-5FFE-4FEA-90BA-32894BCFC6BF}"
+EndProject
+Global
+       GlobalSection(SolutionConfigurationPlatforms) = preSolution
+               Debug|x64 = Debug|x64
+               Debug|x86 = Debug|x86
+               Release|x64 = Release|x64
+               Release|x86 = Release|x86
+       EndGlobalSection
+       GlobalSection(ProjectConfigurationPlatforms) = postSolution
+               {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|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|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|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|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|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
+               {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|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
+               {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|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
+       EndGlobalSection
+       GlobalSection(SolutionProperties) = preSolution
+               HideSolutionNode = FALSE
+       EndGlobalSection
+       GlobalSection(ExtensibilityGlobals) = postSolution
+               SolutionGuid = {93EA02D1-E396-4390-B160-58909BBB9556}
+       EndGlobalSection
+EndGlobal
diff --git a/msvc/uuu.vcxproj b/msvc/uuu.vcxproj
new file mode 100644 (file)
index 0000000..ed0280b
--- /dev/null
@@ -0,0 +1,316 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\uuu\autocomplete.cpp" />
+    <ClCompile Include="..\uuu\buildincmd.cpp" />
+    <ClCompile Include="..\uuu\uuu.cpp" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\uuu\buildincmd.h" />
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <VCProjectVersion>15.0</VCProjectVersion>
+    <ProjectGuid>{2950F8EE-7895-4431-858A-C21EE105C242}</ProjectGuid>
+    <Keyword>Win32Proj</Keyword>
+    <RootNamespace>uuu</RootNamespace>
+    <WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="Shared">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <LinkIncremental>true</LinkIncremental>
+    <IntDir>$(Configuration)\$(ProjectName)\</IntDir>
+    <OutDir>$(Platform)\$(Configuration)</OutDir>
+    <CustomBuildBeforeTargets>Build</CustomBuildBeforeTargets>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <LinkIncremental>true</LinkIncremental>
+    <CustomBuildBeforeTargets>Build</CustomBuildBeforeTargets>
+    <OutDir>$(Platform)\$(Configuration)</OutDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <LinkIncremental>false</LinkIncremental>
+    <IntDir>$(Configuration)\$(ProjectName)\</IntDir>
+    <OutDir>$(Platform)\$(Configuration)</OutDir>
+    <CustomBuildBeforeTargets>Build</CustomBuildBeforeTargets>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <LinkIncremental>false</LinkIncremental>
+    <CustomBuildBeforeTargets>Build</CustomBuildBeforeTargets>
+    <OutDir>$(Platform)\$(Configuration)</OutDir>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <AdditionalDependencies>../libusb/$(Platform)/$(Configuration)/dll/libusb-1.0.lib;$(Platform)/$(Configuration)/libuuu.lib;$(Platform)/$(Configuration)/zlib.lib;%(AdditionalDependencies);$(Platform)/$(Configuration)/bzip2.lib</AdditionalDependencies>
+    </Link>
+    <PreBuildEvent>
+      <Command>echo R^"####( &gt; $(SolutionDir)\..\uuu\uuu.clst
+type $(SolutionDir)\..\uuu\uuu.lst &gt;&gt; $(SolutionDir)\..\uuu\uuu.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\uuu.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\emmc_burn_loader.clst
+type $(SolutionDir)\..\uuu\emmc_burn_loader.lst &gt;&gt; $(SolutionDir)\..\uuu\emmc_burn_loader.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\emmc_burn_loader.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\qspi_burn_loader.clst
+type $(SolutionDir)\..\uuu\qspi_burn_loader.lst &gt;&gt; $(SolutionDir)\..\uuu\qspi_burn_loader.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\qspi_burn_loader.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\sd_burn_loader.clst
+type $(SolutionDir)\..\uuu\sd_burn_loader.lst &gt;&gt; $(SolutionDir)\..\uuu\sd_burn_loader.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\sd_burn_loader.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\spl_boot.clst
+type $(SolutionDir)\..\uuu\spl_boot.lst &gt;&gt; $(SolutionDir)\..\uuu\spl_boot.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\spl_boot.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\emmc_burn_all.clst
+type $(SolutionDir)\..\uuu\emmc_burn_all.lst &gt;&gt; $(SolutionDir)\..\uuu\emmc_burn_all.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\emmc_burn_all.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\sd_burn_all.clst
+type $(SolutionDir)\..\uuu\sd_burn_all.lst &gt;&gt; $(SolutionDir)\..\uuu\sd_burn_all.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\sd_burn_all.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\fat_write.clst
+type $(SolutionDir)\..\uuu\fat_write.lst &gt;&gt; $(SolutionDir)\..\uuu\fat_write.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\fat_write.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\nand_burn_loader.clst
+type $(SolutionDir)\..\uuu\nand_burn_loader.lst &gt;&gt; $(SolutionDir)\..\uuu\nand_burn_loader.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\nand_burn_loader.clst</Command>
+    </PreBuildEvent>
+    <CustomBuildStep>
+      <TreatOutputAsContent>true</TreatOutputAsContent>
+    </CustomBuildStep>
+    <PostBuildEvent>
+      <Command>copy /y "$(SolutionDir)..\libusb\$(Platform)\$(Configuration)\dll\*.dll" $(Platform)\$(Configuration)\</Command>
+    </PostBuildEvent>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <AdditionalDependencies>../libusb/$(Platform)/$(Configuration)/dll/libusb-1.0.lib;$(Platform)/$(Configuration)/libuuu.lib;$(Platform)/$(Configuration)/zlib.lib;%(AdditionalDependencies);$(Platform)/$(Configuration)/bzip2.lib</AdditionalDependencies>
+    </Link>
+    <PreBuildEvent>
+      <Command>echo R^"####( &gt; $(SolutionDir)\..\uuu\uuu.clst
+type $(SolutionDir)\..\uuu\uuu.lst &gt;&gt; $(SolutionDir)\..\uuu\uuu.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\uuu.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\emmc_burn_loader.clst
+type $(SolutionDir)\..\uuu\emmc_burn_loader.lst &gt;&gt; $(SolutionDir)\..\uuu\emmc_burn_loader.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\emmc_burn_loader.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\qspi_burn_loader.clst
+type $(SolutionDir)\..\uuu\qspi_burn_loader.lst &gt;&gt; $(SolutionDir)\..\uuu\qspi_burn_loader.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\qspi_burn_loader.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\sd_burn_loader.clst
+type $(SolutionDir)\..\uuu\sd_burn_loader.lst &gt;&gt; $(SolutionDir)\..\uuu\sd_burn_loader.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\sd_burn_loader.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\spl_boot.clst
+type $(SolutionDir)\..\uuu\spl_boot.lst &gt;&gt; $(SolutionDir)\..\uuu\spl_boot.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\spl_boot.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\emmc_burn_all.clst
+type $(SolutionDir)\..\uuu\emmc_burn_all.lst &gt;&gt; $(SolutionDir)\..\uuu\emmc_burn_all.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\emmc_burn_all.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\sd_burn_all.clst
+type $(SolutionDir)\..\uuu\sd_burn_all.lst &gt;&gt; $(SolutionDir)\..\uuu\sd_burn_all.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\sd_burn_all.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\fat_write.clst
+type $(SolutionDir)\..\uuu\fat_write.lst &gt;&gt; $(SolutionDir)\..\uuu\fat_write.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\fat_write.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\nand_burn_loader.clst
+type $(SolutionDir)\..\uuu\nand_burn_loader.lst &gt;&gt; $(SolutionDir)\..\uuu\nand_burn_loader.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\nand_burn_loader.clst</Command>
+    </PreBuildEvent>
+    <CustomBuildStep>
+      <TreatOutputAsContent>true</TreatOutputAsContent>
+    </CustomBuildStep>
+    <PostBuildEvent>
+      <Command>copy /y "$(SolutionDir)..\libusb\$(Platform)\$(Configuration)\dll\*.dll" $(Platform)\$(Configuration)\</Command>
+    </PostBuildEvent>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <AdditionalDependencies>../libusb/$(Platform)/$(Configuration)/dll/libusb-1.0.lib;$(Platform)/$(Configuration)/libuuu.lib;$(Platform)/$(Configuration)/zlib.lib;%(AdditionalDependencies);$(Platform)/$(Configuration)/bzip2.lib</AdditionalDependencies>
+    </Link>
+    <PreBuildEvent>
+      <Command>echo R^"####( &gt; $(SolutionDir)\..\uuu\uuu.clst
+type $(SolutionDir)\..\uuu\uuu.lst &gt;&gt; $(SolutionDir)\..\uuu\uuu.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\uuu.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\emmc_burn_loader.clst
+type $(SolutionDir)\..\uuu\emmc_burn_loader.lst &gt;&gt; $(SolutionDir)\..\uuu\emmc_burn_loader.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\emmc_burn_loader.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\qspi_burn_loader.clst
+type $(SolutionDir)\..\uuu\qspi_burn_loader.lst &gt;&gt; $(SolutionDir)\..\uuu\qspi_burn_loader.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\qspi_burn_loader.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\sd_burn_loader.clst
+type $(SolutionDir)\..\uuu\sd_burn_loader.lst &gt;&gt; $(SolutionDir)\..\uuu\sd_burn_loader.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\sd_burn_loader.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\spl_boot.clst
+type $(SolutionDir)\..\uuu\spl_boot.lst &gt;&gt; $(SolutionDir)\..\uuu\spl_boot.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\spl_boot.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\emmc_burn_all.clst
+type $(SolutionDir)\..\uuu\emmc_burn_all.lst &gt;&gt; $(SolutionDir)\..\uuu\emmc_burn_all.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\emmc_burn_all.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\sd_burn_all.clst
+type $(SolutionDir)\..\uuu\sd_burn_all.lst &gt;&gt; $(SolutionDir)\..\uuu\sd_burn_all.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\sd_burn_all.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\fat_write.clst
+type $(SolutionDir)\..\uuu\fat_write.lst &gt;&gt; $(SolutionDir)\..\uuu\fat_write.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\fat_write.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\nand_burn_loader.clst
+type $(SolutionDir)\..\uuu\nand_burn_loader.lst &gt;&gt; $(SolutionDir)\..\uuu\nand_burn_loader.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\nand_burn_loader.clst</Command>
+    </PreBuildEvent>
+    <CustomBuildStep>
+      <TreatOutputAsContent>true</TreatOutputAsContent>
+    </CustomBuildStep>
+    <PostBuildEvent>
+      <Command>copy /y "$(SolutionDir)..\libusb\$(Platform)\$(Configuration)\dll\*.dll" $(Platform)\$(Configuration)\</Command>
+    </PostBuildEvent>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <AdditionalDependencies>../libusb/$(Platform)/$(Configuration)/dll/libusb-1.0.lib;$(Platform)/$(Configuration)/libuuu.lib;$(Platform)/$(Configuration)/zlib.lib;%(AdditionalDependencies);$(Platform)/$(Configuration)/bzip2.lib</AdditionalDependencies>
+    </Link>
+    <PreBuildEvent>
+      <Command>echo R^"####( &gt; $(SolutionDir)\..\uuu\uuu.clst
+type $(SolutionDir)\..\uuu\uuu.lst &gt;&gt; $(SolutionDir)\..\uuu\uuu.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\uuu.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\emmc_burn_loader.clst
+type $(SolutionDir)\..\uuu\emmc_burn_loader.lst &gt;&gt; $(SolutionDir)\..\uuu\emmc_burn_loader.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\emmc_burn_loader.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\qspi_burn_loader.clst
+type $(SolutionDir)\..\uuu\qspi_burn_loader.lst &gt;&gt; $(SolutionDir)\..\uuu\qspi_burn_loader.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\qspi_burn_loader.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\sd_burn_loader.clst
+type $(SolutionDir)\..\uuu\sd_burn_loader.lst &gt;&gt; $(SolutionDir)\..\uuu\sd_burn_loader.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\sd_burn_loader.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\spl_boot.clst
+type $(SolutionDir)\..\uuu\spl_boot.lst &gt;&gt; $(SolutionDir)\..\uuu\spl_boot.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\spl_boot.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\emmc_burn_all.clst
+type $(SolutionDir)\..\uuu\emmc_burn_all.lst &gt;&gt; $(SolutionDir)\..\uuu\emmc_burn_all.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\emmc_burn_all.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\sd_burn_all.clst
+type $(SolutionDir)\..\uuu\sd_burn_all.lst &gt;&gt; $(SolutionDir)\..\uuu\sd_burn_all.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\sd_burn_all.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\fat_write.clst
+type $(SolutionDir)\..\uuu\fat_write.lst &gt;&gt; $(SolutionDir)\..\uuu\fat_write.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\fat_write.clst
+echo R^"####( &gt; $(SolutionDir)\..\uuu\nand_burn_loader.clst
+type $(SolutionDir)\..\uuu\nand_burn_loader.lst &gt;&gt; $(SolutionDir)\..\uuu\nand_burn_loader.clst
+echo )####^" &gt;&gt; $(SolutionDir)\..\uuu\nand_burn_loader.clst</Command>
+    </PreBuildEvent>
+    <CustomBuildStep>
+      <TreatOutputAsContent>true</TreatOutputAsContent>
+    </CustomBuildStep>
+    <PostBuildEvent>
+      <Command>copy /y "$(SolutionDir)..\libusb\$(Platform)\$(Configuration)\dll\*.dll" $(Platform)\$(Configuration)\</Command>
+    </PostBuildEvent>
+  </ItemDefinitionGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/msvc/uuu.vcxproj.filters b/msvc/uuu.vcxproj.filters
new file mode 100644 (file)
index 0000000..1aee593
--- /dev/null
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="Source Files">
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+    <Filter Include="Header Files">
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
+    </Filter>
+    <Filter Include="Resource Files">
+      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\uuu\uuu.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\uuu\buildincmd.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\uuu\autocomplete.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\uuu\buildincmd.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/msvc/zlib.vcxproj b/msvc/zlib.vcxproj
new file mode 100644 (file)
index 0000000..0decf32
--- /dev/null
@@ -0,0 +1,193 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <VCProjectVersion>15.0</VCProjectVersion>
+    <ProjectGuid>{59666402-A775-49AC-A9BD-19FD528F5FD9}</ProjectGuid>
+    <Keyword>Win32Proj</Keyword>
+    <RootNamespace>zlib</RootNamespace>
+    <WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="Shared">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <LinkIncremental>true</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <LinkIncremental>true</LinkIncremental>
+    <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <LinkIncremental>false</LinkIncremental>
+    <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <LinkIncremental>false</LinkIncremental>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+      <BufferSecurityCheck>false</BufferSecurityCheck>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+    <Lib>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+      <BufferSecurityCheck>false</BufferSecurityCheck>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+    <Lib>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+      <BufferSecurityCheck>false</BufferSecurityCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+    <Lib>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+      <BufferSecurityCheck>false</BufferSecurityCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+    <Lib>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClInclude Include="stdafx.h" />
+    <ClInclude Include="targetver.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\zlib\adler32.c" />
+    <ClCompile Include="..\zlib\compress.c" />
+    <ClCompile Include="..\zlib\crc32.c" />
+    <ClCompile Include="..\zlib\deflate.c" />
+    <ClCompile Include="..\zlib\gzclose.c" />
+    <ClCompile Include="..\zlib\gzlib.c" />
+    <ClCompile Include="..\zlib\gzread.c" />
+    <ClCompile Include="..\zlib\gzwrite.c" />
+    <ClCompile Include="..\zlib\infback.c" />
+    <ClCompile Include="..\zlib\inffast.c" />
+    <ClCompile Include="..\zlib\inflate.c" />
+    <ClCompile Include="..\zlib\inftrees.c" />
+    <ClCompile Include="..\zlib\trees.c" />
+    <ClCompile Include="..\zlib\uncompr.c" />
+    <ClCompile Include="..\zlib\zutil.c" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/msvc/zlib.vcxproj.filters b/msvc/zlib.vcxproj.filters
new file mode 100644 (file)
index 0000000..fe87903
--- /dev/null
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="Source Files">
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+    <Filter Include="Header Files">
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
+    </Filter>
+    <Filter Include="Resource Files">
+      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="stdafx.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="targetver.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\zlib\adler32.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\zlib\compress.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\zlib\crc32.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\zlib\deflate.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\zlib\gzclose.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\zlib\gzlib.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\zlib\infback.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\zlib\inffast.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\zlib\inflate.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\zlib\inftrees.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\zlib\trees.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\zlib\uncompr.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\zlib\zutil.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\zlib\gzread.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\zlib\gzwrite.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/uuu/CMakeLists.txt b/uuu/CMakeLists.txt
new file mode 100644 (file)
index 0000000..22880f5
--- /dev/null
@@ -0,0 +1,76 @@
+cmake_minimum_required(VERSION 3.12)
+
+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(LIBZIP REQUIRED libzip)
+pkg_check_modules(LIBZ REQUIRED zlib)
+find_package(Threads)
+
+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")
+endif()
+
+set(LSTS
+       uuu.lst
+       emmc_burn_loader.lst
+       emmc_burn_all.lst
+       fat_write.lst
+       qspi_burn_loader.lst
+       sd_burn_loader.lst
+       spl_boot.lst
+       sd_burn_all.lst
+       nand_burn_loader.lst
+)
+
+link_directories(${CMAKE_CURRENT_SOURCE_DIR}/libuuu ${LIBUSB_LIBRARY_DIRS} ${LIBZIP_LIBRARY_DIRS} ${LIBZ_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} ${LIBZIP_LIBRARIES} ${LIBZ_LIBRARIES} dl bz2)
+
+install(TARGETS uuu DESTINATION bin)
+add_compile_definitions(TARGET_PATH="${CMAKE_INSTALL_PREFIX}/bin/uuu")
diff --git a/uuu/autocomplete.cpp b/uuu/autocomplete.cpp
new file mode 100644 (file)
index 0000000..ea4caac
--- /dev/null
@@ -0,0 +1,228 @@
+/*
+* 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 <iostream>
+#include <stdio.h>
+#include <thread>
+#include <atomic>
+#include <iomanip>
+#include <map>
+#include <mutex>
+#include <vector>
+#include <sstream>
+#include <fstream>
+#include <stdarg.h>
+#include <time.h>
+#include <string.h>
+#include <signal.h>
+#include "buildincmd.h"
+
+#include "../libuuu/libuuu.h"
+
+#ifndef _MSC_VER
+#include <unistd.h>
+#include <limits.h>
+#else
+#include <Windows.h>
+#endif
+
+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<string> 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()" <<endl;
+               cout << "  {" << endl;
+               cout << "       COMPREPLY=($(" << TARGET_PATH << " $1 $2 $3))" << endl;
+               cout << "  }" << endl;
+               cout << "  complete -o nospace -F _uuu_autocomplete  uuu" << g_vt_default << endl << endl;
+       }
+#else
+       {
+               printf("Powershell: Enjoy auto [tab] command complete by run below command or put into Documents\\WindowsPowerShell\\Microsoft.PowerShell_profile.ps1\n");
+               
+               HMODULE hModule = GetModuleHandleA(NULL);
+               char path[MAX_PATH];
+               GetModuleFileNameA(hModule, path, MAX_PATH);
+
+               printf("   Register-ArgumentCompleter -CommandName uuu -ScriptBlock {param($commandName,$parameterName,$wordToComplete,$commandAst,$fakeBoundParameter); %s -autocomplete $parameterName }\n\n",
+                       path);
+       }
+#endif
+
+}
diff --git a/uuu/buildincmd.cpp b/uuu/buildincmd.cpp
new file mode 100644 (file)
index 0000000..7d632d2
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+* 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 "buildincmd.h"
+
+BuildCmd g_buildin_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"
+       },
+       {
+               "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"
+       },
+       {
+               NULL,
+               NULL,
+               NULL,
+       }
+};
+
+BuildInScriptVector g_BuildScripts(g_buildin_cmd);
diff --git a/uuu/buildincmd.h b/uuu/buildincmd.h
new file mode 100644 (file)
index 0000000..d01edae
--- /dev/null
@@ -0,0 +1,284 @@
+/*
+* 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 <string>
+#include <vector>
+#include <map>
+#include <locale>
+
+using namespace std;
+
+extern const char * g_vt_yellow ;
+extern const char * g_vt_default ;
+extern const char * g_vt_green ;
+extern const char * g_vt_red  ;
+extern const char * g_vt_kcyn ;
+extern const char * g_vt_boldwhite ;
+
+struct BuildCmd
+{
+       const char *m_cmd;
+       const char *m_buildcmd;
+       const char *m_desc;
+};
+
+class Arg
+{
+public:
+       string m_arg;
+       string m_desc;
+       uint32_t m_flags;
+       string m_options;
+       enum
+       {
+               ARG_MUST = 0x1,
+               ARG_OPTION = 0x2,
+               ARG_OPTION_KEY = 0x4,
+       };
+       Arg() { m_flags = ARG_MUST;     }
+       int parser(string option)
+       {
+               size_t pos;
+               pos = option.find('[');
+               if (pos == string::npos)
+                       return 0;
+               m_options = option.substr(pos + 1, option.find(']') - pos - 1);
+               m_flags = ARG_OPTION | ARG_OPTION_KEY;
+               return 0;
+       }
+};
+
+class BuildInScript
+{
+public:
+       string m_script;
+       string m_desc;
+       string m_cmd;
+       vector<Arg> m_args;
+       bool find_args(string arg)
+       {
+               for (size_t i = 0; i < m_args.size(); i++)
+               {
+                       if (m_args[i].m_arg == arg)
+                               return true;
+               }
+               return false;
+       }
+       BuildInScript() {};
+       BuildInScript(BuildCmd*p)
+       {
+               m_script = p->m_buildcmd;
+               if(p->m_desc)
+                       m_desc = p->m_desc;
+               if(p->m_cmd)
+                       m_cmd = p->m_cmd;
+
+               for (size_t i = 1; i < m_script.size(); i++)
+               {
+                       size_t off;
+                       size_t off_tab;
+                       string param;
+                       if (m_script[i] == '_' 
+                               && (m_script[i - 1] == '@' || m_script[i - 1] == ' '))
+                       {
+                               off = m_script.find(' ', i);
+                               off_tab = m_script.find('\t', i);
+                               size_t ofn = m_script.find('\n', i);
+                               if (off_tab < off)
+                                       off = off_tab;
+                               if (ofn < off)
+                                       off = ofn;
+
+                               if (off == string::npos)
+                                       off = m_script.size() + 1;
+
+                               param = m_script.substr(i, off - i);
+                               if (!find_args(param))
+                               {
+                                       Arg a;
+                                       a.m_arg = param;
+                                       a.m_flags = Arg::ARG_MUST;
+                                       m_args.push_back(a);
+                               }
+                       }
+               }
+
+               for (size_t i = 0; i < m_args.size(); i++)
+               {
+                       size_t pos = 0;
+                       string str;
+                       str += "@";
+                       str += m_args[i].m_arg;
+                       pos = m_script.find(str);
+                       if (pos != string::npos) {
+                               string def;
+                               size_t start_descript;
+                               start_descript = m_script.find('|', pos);
+                               if (start_descript != string::npos)
+                               {
+                                       m_args[i].m_desc = m_script.substr(start_descript + 1,
+                                                                                       m_script.find('\n', start_descript) - start_descript - 1);
+                                       def = m_script.substr(pos, start_descript - pos);
+                                       m_args[i].parser(def);
+                               }
+                       }
+               }
+       }
+
+       void show()
+       {
+               printf("%s\n", m_script.c_str());
+       }
+
+       void show_cmd()
+       {
+               printf("\t%s%s%s\t%s\n", g_vt_boldwhite, m_cmd.c_str(), g_vt_default,  m_desc.c_str());
+               for (size_t i=0; i < m_args.size(); i++)
+               {
+                       string desc;
+                       desc += m_args[i].m_arg;
+                       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%d: %s\n", (int)i, desc.c_str());
+               }
+       }
+
+       inline string str_to_upper(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;
+       }
+
+       string replace_str(string str, string key, string replace)
+       {
+               if (replace.size() > 4)
+               {
+                       if (str_to_upper(replace.substr(replace.size() - 4)) == ".BZ2")
+                       {
+                               replace += "/*";
+                       }
+               }
+
+               for (size_t j = 0; (j = str.find(key, j)) != string::npos;)
+               {
+                       str.replace(j, key.size(), replace);
+                       j += key.size();
+               }
+               return str;
+       }
+
+       string replace_script_args(vector<string> args)
+       {
+               string script = m_script;
+               for (size_t i = 0; i < args.size() && i < m_args.size(); i++)
+               {
+                       script = replace_str(script, m_args[i].m_arg, 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_arg == m_args[i].m_options)
+                                       {
+                                               script = replace_str(script, m_args[i].m_arg, args[j]);
+                                               break;
+                                       }
+                               }
+                       }
+               }
+               return script;
+       }
+};
+
+class BuildInScriptVector : public map<string, BuildInScript>
+{
+public:
+       BuildInScriptVector(BuildCmd*p)
+       {
+               while (p->m_cmd)
+               {
+                       BuildInScript one(p);
+                       (*this)[one.m_cmd] = one;
+                       p++;
+               }
+       }
+
+       void ShowAll()
+       {
+               for (auto iCol = begin(); iCol != end(); ++iCol)
+               {
+                       iCol->second.show_cmd();
+               }
+       }
+
+       void ShowCmds()
+       {
+               printf("<");
+               for (auto iCol = begin(); iCol != end(); ++iCol)
+               {
+                       printf("%s%s%s", g_vt_boldwhite, iCol->first.c_str(), g_vt_default);
+
+                       auto i = iCol;
+                       i++;
+                       if(i != end())
+                               printf("|");
+               }
+               printf(">");
+       }
+
+       void PrintAutoComplete(string match, const char *space=" " )
+       {
+               for (auto iCol = begin(); iCol != end(); ++iCol)
+                {
+                       if(iCol->first.substr(0, match.size()) == match)
+                               printf("%s%s\n", iCol->first.c_str(), space);
+               }
+       }
+
+};
+
+extern BuildInScriptVector g_BuildScripts;
diff --git a/uuu/emmc_burn_all.lst b/uuu/emmc_burn_all.lst
new file mode 100644 (file)
index 0000000..53f4afe
--- /dev/null
@@ -0,0 +1,34 @@
+uuu_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: 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 -raw2sparse all _rootfs.sdcard
+FB: flash 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
diff --git a/uuu/emmc_burn_loader.lst b/uuu/emmc_burn_loader.lst
new file mode 100644 (file)
index 0000000..27128fe
--- /dev/null
@@ -0,0 +1,35 @@
+uuu_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
diff --git a/uuu/fat_write.lst b/uuu/fat_write.lst
new file mode 100644 (file)
index 0000000..994fa09
--- /dev/null
@@ -0,0 +1,11 @@
+uuu_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[-t 20000]: ucmd fatwrite _device _partition ${fastboot_buffer} _filename  ${fastboot_bytes}
+FB: done
diff --git a/uuu/gen_txt_include.sh b/uuu/gen_txt_include.sh
new file mode 100755 (executable)
index 0000000..608954f
--- /dev/null
@@ -0,0 +1,3 @@
+echo "R\"####(" > $2
+cat $1 >> $2
+echo ")####\"" >> $2
diff --git a/uuu/nand_burn_loader.lst b/uuu/nand_burn_loader.lst
new file mode 100644 (file)
index 0000000..49859a3
--- /dev/null
@@ -0,0 +1,34 @@
+uuu_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
+# 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
diff --git a/uuu/qspi_burn_loader.lst b/uuu/qspi_burn_loader.lst
new file mode 100644 (file)
index 0000000..a4cad7f
--- /dev/null
@@ -0,0 +1,41 @@
+uuu_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
+
+# 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
diff --git a/uuu/sd_burn_all.lst b/uuu/sd_burn_all.lst
new file mode 100644 (file)
index 0000000..4870c5d
--- /dev/null
@@ -0,0 +1,31 @@
+uuu_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: 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 -raw2sparse all _rootfs.sdcard
+FB: flash bootloader _flash.bin
+FB: done
diff --git a/uuu/sd_burn_loader.lst b/uuu/sd_burn_loader.lst
new file mode 100644 (file)
index 0000000..4acb0c7
--- /dev/null
@@ -0,0 +1,33 @@
+uuu_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
diff --git a/uuu/spl_boot.lst b/uuu/spl_boot.lst
new file mode 100644 (file)
index 0000000..d005a53
--- /dev/null
@@ -0,0 +1,26 @@
+uuu_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: 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
+# }
\ No newline at end of file
diff --git a/uuu/uuu.cpp b/uuu/uuu.cpp
new file mode 100644 (file)
index 0000000..3cee844
--- /dev/null
@@ -0,0 +1,1078 @@
+/*
+* 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 <iostream>
+#include <stdio.h>
+#include <thread>
+#include <atomic>
+#include <iomanip>
+#include <map>
+#include <mutex>
+#include <vector>
+#include <sstream>
+#include <fstream>
+#include <stdarg.h>
+#include <time.h>
+#include <string.h>
+#include <signal.h>
+#include "buildincmd.h"
+#include <string>
+#include <streambuf>
+
+#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<string> g_usb_path_filter;
+
+int g_verbose = 0;
+static bool g_start_usb_transfer;
+
+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;
+       }
+};
+
+void print_help(bool detail = false)
+{
+       const char help[] =
+               "uuu [-d -m -v -V] <" "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"
+               "    -m          USBPATH Only monitor these paths.\n"
+               "                    -m 1:2 -m 1:3\n\n"
+               "    -t          Timeout second for wait known usb device appeared\n"
+               "    -e          set environment variable key=value\n"
+               "    -pp         usb polling period in milliseconds\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 -h -H       show help, -H means detail helps\n\n";
+       printf("%s", help);
+       printf("uuu [-d -m -v] -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 pid, uint16_t vid, 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, pid, vid);
+       else
+               printf("\t%s\t %s\t%s 0x%04x\t 0x%04x\t [0x%04x..0x%04x]\n", pro, chip, ext, pid, vid, 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<int>& 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::NOFITY_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::NOFITY_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(8, ' ');
+
+               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 = 14;
+               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<string, ShowNotify> 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<uint64_t, ShowNotify> *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<uint64_t, ShowNotify> *np = (map<uint64_t, ShowNotify>*)p;
+       map<string, ShowNotify>::iterator it;
+
+       std::lock_guard<std::mutex> 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] + " ";
+                       }
+
+                       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 <windows.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+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 <sys/ioctl.h>
+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() & 0xFF0000) >> 16)
+                       << "."
+                       << ((uuu_get_version() & 0xFF00) >> 8)
+                       << "."
+                       << ((uuu_get_version() & 0xFF))
+                       << 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, void * /*p*/)
+{
+       printf("\t%s\t %s\t %s\t 0x%04X\t0x%04X\t 0x%04X\n", path, chip, pro, vid, pid, bcd);
+       return 0;
+}
+
+void print_lsusb()
+{
+       cout << "Connected Known USB Devices\n";
+       printf("\tPath\t Chip\t Pro\t Vid\t Pid\t BcdVersion\n");
+       printf("\t==================================================\n");
+
+       uuu_for_each_devices(print_usb_device, NULL);
+}
+
+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;
+               }
+       }
+
+       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;
+                       }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 == "-t")
+                       {
+                               i++;
+                               uuu_set_wait_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 == "-e")
+                       {
+#ifndef WIN32
+       #define _putenv putenv
+#endif
+                               i++;
+                               if (_putenv(argv[i]))
+                               {
+                                       printf("error, failed to set '%s', environment parameter must have the from 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<string> 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()) {
+                                       BuildCmd tmpCmd;
+                                       string tmpCmdFileName = argv[i + 1];
+                                       tmpCmd.m_cmd = tmpCmdFileName.c_str();
+
+                                       std::ifstream t(tmpCmdFileName);
+                                       std::string fileContents((std::istreambuf_iterator<char>(t)),
+                                               std::istreambuf_iterator<char>());
+
+                                       if (fileContents.empty()) {
+                                               printf("%s is not built-in script or fail load external script file", tmpCmdFileName.c_str());
+                                               return -1;
+                                       }
+
+                                       tmpCmd.m_buildcmd = fileContents.c_str();
+
+                                       tmpCmd.m_desc = "Script loaded from file";
+
+                                       BuildInScript tmpBuildInScript(&tmpCmd);
+                                       g_BuildScripts[tmpCmdFileName] = tmpBuildInScript;
+
+                                       cmd_script = g_BuildScripts[tmpCmdFileName].replace_script_args(args);
+                               }
+                               else {
+                                       cmd_script = g_BuildScripts[argv[i + 1]].replace_script_args(args);
+                               }
+                               break;
+                       }
+                       else if (s == "-bshow")
+                       {
+                               if (i + 1 == argc || g_BuildScripts.find(argv[i+1]) == g_BuildScripts.end())
+                               {
+                                       printf("error, must be have script name: ");
+                                       g_BuildScripts.ShowCmds();
+                                       printf("\n");
+                                       return -1;
+                               }
+                               else
+                               {
+                                       printf("%s", g_BuildScripts[argv[i + 1]].m_script.c_str());
+                                       return 0;
+                               }
+                       }
+                       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);
+
+       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\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<uint64_t, ShowNotify> 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)
+       {
+               runshell(shell);
+
+               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;
+}
diff --git a/uuu/uuu.lst b/uuu/uuu.lst
new file mode 100644 (file)
index 0000000..f5ce87a
--- /dev/null
@@ -0,0 +1,70 @@
+uuu_version 1.0.0
+#
+# uuu(universal update utility) command list file
+# Firstly line must be uuu_version show minimize uuu host version number
+# ---------------------------------------------------------------------
+# Command Format PROTOCOL COMMAND ARG
+# PROTOCOL
+#          ALL protocol supported common command
+#                      done        #last command for whole flow
+#                      delay <ms>  # delay ms
+#                      sh\shell <any shell command> #Run shell command, such as wget to file from network
+#                      <        <any shell command> #use shell command's output as uuu command
+#                               this command generally used for burn some sequence number, such production id, mac address
+#                              for example:   
+#                                      FB:< echo ucmd print
+#
+#          CFG:  Config protocol of specific usb device vid/pid
+#                SDPS|SDP|FB\Fastboot|FBK -chip <chip name> -pid <pid> -vid <vid> [-bcdversion <ver>]
+#
+#          SDPS: Stream download after MX8QXPB0
+#                      boot  -f  <filename> [-offset 0x0000]
+#
+#          SDP:  iMX6/iMX7 HID download protocol.
+#                      dcd   -f  <filename>
+#                      write -f  <filename> [-addr 0x000000] [-ivt 0]
+#                      jump  -f  <filename> [-ivt 0]
+#                      boot  -f  <filename> [-nojump]
+#                      rdmem -addr <mem_address> -format <8|16|32>
+#                      wrmem -addr <mem_address> -format <8|16|32> -value <mem_value>
+#
+#          FB[-t timeout]:\Fastboot: android fastboot protocol. unit of timeout is ms
+#                      getvar
+#                      ucmd <any uboot command>
+#                      acmd <any never returned uboot command, like booti, reboot>
+#                      flash [-raw2sparse] <partition> <filename>
+#                      download -f <filename>
+#
+#          FBK: community with kernel with fastboot protocol. DO NOT compatible with fastboot tools.
+#                      ucmd <any kernel command> and wait for command finish
+#                      acmd <any kernel command> don't wait for command finish
+#                      sync                      wait for acmd process finish.
+#                      ucp <soure> <destinate>   copy file from/to target
+#                                                T:<filename> 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 for transfer big file
+#                              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 exit.
+#
+# For example:
+#          SDPS: boot -f <filename>
+#          SDP:  boot -f <filename>
+#          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